光线跟踪旋转

时间:2017-02-02 14:41:33

标签: c graphics 3d raytracing rotational-matrices

我正在用C编写一个简单的光线跟踪器。除旋转外,一切正常。我正在尝试旋转我的物体(在那个问题上是圆柱体)。圆柱体旋转,但阴影完全关闭,物体仅在0°和90°之间旋转,并在360°恢复正常(这是显而易见的)。如果有人能给我一些关于我做错的提示,我会很感激。这是一些示例代码。

查找圆柱的交点的函数:

    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));

我的rotation.c文件:

    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);
}

阴影/颜色文件:

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);
}

一些screeshots。

场景文件:0°旋转

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

场景文件:42°旋转

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

场景文件:旋转91°

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

任何事都会有所帮助,提前谢谢!

1 个答案:

答案 0 :(得分:1)

考虑围绕 x 轴的旋转:

    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);
}

请注意,输入向量的 y 坐标对结果向量的 y z 坐标都有贡献。现在请注意,在计算生成的 z 坐标时实际使用的不是输入 y ,而是计算结果 y 。这是错误的。

类似适用于您的其他旋转功能。