Search code examples
cgraphics3draytracingrotational-matrices

Raytracing Rotations


I'm currently coding a simple raytracer in C. Everything is working fine, except for the rotations. I'm trying to rotate my objects (cylinders in that matter). The cylinders rotates, but the shading are completely off, and the object only rotates between 0° and 90°, and goes back to normal at 360° (which is obvious). I'd appreciate if anyone could give me a hint on what I'm doing wrong. Here's some sample code.

Function that find intersections for cylinders :

    double      mininter;
    double      inter;
    t_vect      *normal;
    t_color     *c;
    t_cyl       *cyl;

    cyl = e->scene.cyls;
    mininter = -1;
    while (cyl != NULL && limiter-- != 0)
    {
        ray = rotate_eye(ray, cyl->rotate, -1);
        inter = cylinder_inter(cyl, ray);
        if (inter > ACCURACY && (inter < mininter || mininter == -1))
        {
            mininter = inter;
            p = vect_add(ray->og, vect_mult(ray->dir, inter));
            ray = rotate_eye(ray, cyl->rotate, 1);
            normal = cylinder_normal(cyl->og, p);
            c = cyl->color;
        }
        cyl = cyl->next;
    }
    return (new_inter(normal, mininter, c, p));

My rotation.c file :

    static t_vect   *x(t_vect *v, double rot, int stage)
{
    rot = DEG_TO_RAD(rot * stage);
    v->y = v->y * cos(rot) + v->z * -sin(rot);
    v->z = v->y * sin(rot) + v->z * cos(rot);
    return (v);
}

static t_vect   *y(t_vect *v, double rot, int stage)
{
    rot = DEG_TO_RAD(rot * stage);
    v->x = v->x * cos(rot) + v->z * sin(rot);
    v->z = v->x * -sin(rot) + v->z * cos(rot);
    return (v);
}

static t_vect   *z(t_vect *v, double rot, int stage)
{
    rot = DEG_TO_RAD(rot * stage);
    v->x = v->x * cos(rot) + v->y * -sin(rot);
    v->y = v->x * sin(rot) + v->y * cos(rot);
    return (v);
}

t_ray           *rotate_eye(t_ray *ray, t_vect *rot, int stage)
{
    ray->og = x(ray->og, rot->z, stage);
    ray->og = y(ray->og, rot->y, stage);
    ray->og = z(ray->og, rot->x, stage);
    ray->dir = x(ray->dir, rot->z, stage);
    ray->dir = y(ray->dir, rot->y, stage);
    ray->dir = z(ray->dir, rot->x, stage);
    return (ray);
}

The shadow/color file :

static double   shadows(t_env *e, t_inter *inter)
{
    t_ray       *iray;
    t_vect      *v;
    t_vect      *l;

    l = e->scene.spot->pos;
    v = new_vector(l->x - inter->point->x, l->y - inter->point->y,
        l->z - inter->point->z);
    iray = new_ray(inter->point, l);
    return (calc_inter(e, iray)->dist);
}

t_color         *find_color_at(t_env *e, t_ray *ray)
{
    t_color     *result;
    t_inter     *mininter;
    t_vect      *dist_l;
    double      shade;

    mininter = calc_inter(e, ray);
    if (mininter->dist > ACCURACY)
    {
        dist_l = normalize(vect_add(e->scene.spot->pos, negative(ray->og)));
        shade = dot_product(dist_l, mininter->normal);
        if (shadows(e, mininter) > ACCURACY)
            result = color_scalar(AMBIENTLIGHT * shadows(e, mininter),
                mininter->color);
        else
            result = shade < 0 ? color_scalar(AMBIENTLIGHT + DIFFUSELIGHT *
                0, mininter->color) : color_scalar(AMBIENTLIGHT +
                DIFFUSELIGHT * shade, mininter->color);
    }
    else
        result = new_color(0, 0, 0);
    return (result);
}

Some screeshots.

Scene file : 0° rotation

camera:
pos:
0, 0, 100
dir:
0, 0, 0
----
spheres:
new:
pos:
20, 0, 20
radius:
30
color:
42, 255, 255
----
----
cylinders:
new:
pos:
-20, 0, -30
radius:
20
color:
255, 42, 23
rotate:
0, 0, 0
----
----
spot:
pos:
50, 0, 150
----
END

https://gyazo.com/6ab10dbfba27a889ac6397c30aa4adda

Scene file : 42° rotation

camera:
pos:
0, 0, 100
dir:
0, 0, 0
----
spheres:
new:
pos:
20, 0, 20
radius:
30
color:
42, 255, 255
----
----
cylinders:
new:
pos:
-20, 0, -30
radius:
20
color:
255, 42, 23
rotate:
42, 0, 0
----
----
spot:
pos:
50, 0, 150
----
END

https://gyazo.com/f244f6c7e2d2a81b6001fc175c16c289

Scene file : 91° rotation

camera:
pos:
0, 0, 100
dir:
0, 0, 0
----
spheres:
new:
pos:
20, 0, 20
radius:
30
color:
42, 255, 255
----
----
cylinders:
new:
pos:
-20, 0, -30
radius:
20
color:
255, 42, 23
rotate:
91, 0, 0
----
----
spot:
pos:
50, 0, 150
----
END

https: //gyazo.com/86cda440cfca079d07e04d1ef19b8a21

Anything will help, thanks in advance !


Solution

  • Consider your rotation around the x axis:

        static t_vect   *x(t_vect *v, double rot, int stage)
    {
        rot = DEG_TO_RAD(rot * stage);
        v->y = v->y * cos(rot) + v->z * -sin(rot);
        v->z = v->y * sin(rot) + v->z * cos(rot);
        return (v);
    }
    

    Notice that the y coordinate of the input vector contributes to both the y and z coordinates of the result vector. Now notice that what you actually use in the computation of the resulting z coordinate is not the input y, but rather the computed result y. This is erroneous.

    Similar applies to your other rotation functions.