Повороты трассировки лучей

В настоящее время я пишу простой трассировщик лучей на 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));

Мой файл rotate.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);
}

Несколько скриншотов.

Файл сцены: поворот на 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

Чем поможет, заранее спасибо!


person Exilia    schedule 02.02.2017    source источник
comment
Ваши матрицы вращения кажутся нетрадиционными. См. здесь   -  person Eugene Sh.    schedule 02.02.2017


Ответы (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. Это ошибочно.

То же самое относится и к другим вашим функциям вращения.

person John Bollinger    schedule 02.02.2017
comment
Я изменил свой код и рассчитал с входными значениями. Я получил такой результат: gyazo.com/ce3e4c35fefa3eb29d9804e4395ca2fb Мне не нравится, что наверху есть тень цилиндр. Любые подсказки? Спасибо. - person Exilia; 02.02.2017
comment
Неважно, мне просто нужно было снова повернуть при вычислении точки пересечения. Мне еще нужно кое-что понять о моей слежке, но вы сделали более чем достаточно. Спасибо еще раз ! - person Exilia; 02.02.2017