Вращение камеры-обскуры в 3D

Я пытаюсь повернуть камеру-обскуру в трехмерном пространстве. Ранее я провел трассировку комнаты. В качестве хорошей практики я сначала сделал математику и попытался запрограммировать математику на С++.

// Camera position
vec3 cameraPos(0, 0, -19);


// Rotate camera
float& yaw;
vec3 c1(cos(yaw), 0, sin(yaw));
vec3 c2(0, 1, 0);
vec3 c3(-sin(yaw), 0, cos(yaw));
glm::mat3 R(c1, c2, c3);

Что я сделал, чтобы повернуть камеру, так это:

if (keystate[SDLK_LEFT])
{
    //cameraPos.x -= translation;
    if (yaw > 0)
    {   
        yaw = 0.01;
    }
    cout << yaw << endl;
    cameraPos = R * cameraPos;
    cout << "LEFT" << endl;
}
if (keystate[SDLK_RIGHT])
{
    //cameraPos.x += translation;
    if (yaw > 0)
    {
        yaw = -0.01;
    }
    cout << yaw << endl;
    cameraPos = R * cameraPos;
    cout << "RIGHT" << endl;
}

Я умножил матрицу вращения R на вектор положения камеры. Теперь происходит то, что комната движется только влево, независимо от того, какую клавишу я нажимаю.

В учебнике, за которым я следую, говорится:

Если камера вращается с помощью матрицы R, то векторы, представляющие направления вправо (ось x), вниз (ось y) и вперед (ось z), будут получены как:

vec3 right(R[0][0],R[0][1],R[0][2]);
vec3 down(R[1][0],R[1][1],R[2][2]);
vec3 right(R[2][0],R[2][1],R[2][2]);

Чтобы смоделировать вращающуюся камеру, вам нужно использовать эти направления как при перемещении камеры, так и при отбрасывании лучей.

Я не понимаю, как я должен использовать приведенную выше информацию.

Любая помощь или ссылки приветствуются.


person Lebowski    schedule 13.04.2016    source источник


Ответы (1)


Похоже, вы не обновляете свою матрицу R после изменения yaw. Это означает, что каждый раз, когда вы делаете camerapos = R * camerapos, вы вращаете вектор camerapos в одном направлении.

Более правильным способом сделать это было бы разделить камеры, каждый раз строить R и использовать другой вектор для результата положения камеры.

Что-то вроде этого:

// Camera position
vec3 cameraPos(0, 0, -19);
vec3 trueCameraPos;
float yaw;

if (keystate[SDLK_LEFT])
{
    //cameraPos.x -= translation;
    if (yaw > 0)
    {   
        yaw = 0.01;
    }
    cout << yaw << endl;
    cout << "LEFT" << endl;
}
if (keystate[SDLK_RIGHT])
{
    //cameraPos.x += translation;
    if (yaw > 0)
    {
        yaw = -0.01;
    }
    cout << yaw << endl;
    cout << "RIGHT" << endl;
}

// Rotate camera
vec3 c1(cos(yaw), 0, sin(yaw));
vec3 c2(0, 1, 0);
vec3 c3(-sin(yaw), 0, cos(yaw));
glm::mat3 R(c1, c2, c3);

trueCameraPos = R * cameraPos;

Что касается определений камеры, то камере нужны три вектора, чтобы определить ее ориентацию. Если вы поворачиваете камеру, ориентация также меняется, иначе вы просто переместите камеру, и она всегда будет смотреть в одном направлении.

Определение, выделенное желтым, неверно, так как должно быть три перпендикулярных вектора, обычно вверх, вправо и вперед. Теперь есть два правых вектора (один из которых вниз, прямо противоположен вектору вверх), поэтому последний должен быть вектором вперед.

Эти векторы определяют направления, используемые в трассировщике лучей. Вперед идут лучи, вверх и вправо определяют направления смещения в плоскости изображения для каждого пикселя изображения. Скорее всего, вы уже используете их в своем коде трассировки.

person Sami Kuhmonen    schedule 13.04.2016
comment
Спасибо за Ваш ответ. Что касается выделенного желтым цветом раздела, вы понимаете, что это значит? - person Lebowski; 13.04.2016
comment
Это говорит о том, что каждая строка матрицы вращения соответствует вектору направления (относительно того, что представляет базовый кадр). Таким образом, строка 1 в R является вектором правильного направления и т. д. Сравните с x-шляпой, y-шляпой и z-шляпой в контексте общей физики. Я считаю, что второе право является опечаткой и должно было сказать вперед. - person user2475059; 13.04.2016
comment
Да я тоже так считаю. Спасибо :) - person Lebowski; 13.04.2016
comment
@Lebowski Добавил информацию и о них, пользователь 2475059 прав насчет второго правого вперед. - person Sami Kuhmonen; 13.04.2016
comment
@SamiKuhmonen Я нигде в своем коде не реализовал право, вниз, вперед. Модификации, которые вы сделали, работают, и у меня есть ротация. Я просто не уверен, вращение это или перевод, так как я беспокоюсь, что нужно использовать право, вниз, вперед, чтобы получить правильную перспективу. Я немного запутался. - person Lebowski; 13.04.2016
comment
@Lebowski У вас есть какие-то векторы в коде, когда вы зацикливаете каждый пиксель результирующего изображения и прослеживаете луч через них. Этими векторами должны быть эти три. У вас могут быть только константы, если камера всегда указывала в одном направлении. Вы можете легко проверить это, поскольку, если вы продолжаете вращать камеру, вы либо в конечном итоге смотрите на сцену с противоположной стороны при достижении 180 градусов, либо вы постоянно смотрите в одном и том же направлении, а камера просто вращается вокруг исходной точки. - person Sami Kuhmonen; 13.04.2016
comment
@Lebowski Возможно, вы захотите прочитать о матрицах вращения. Я лично обнаружил, что изучение вращений является одной из наиболее полезных вещей, которые я делал в инженерии (аэро), поскольку они, кажется, часто используются в самых разных контекстах. - person user2475059; 13.04.2016
comment
@ user2475059 Я просмотрел страницу в Википедии. Что еще можете порекомендовать. Я хотел бы быть хорошим в этом деле. - person Lebowski; 13.04.2016
comment
@Lebowski Это будет зависеть от вашего уровня знаний. Курс линейной алгебры не помешал бы, если бы у вас его не было. Мне не повезло найти вводные страницы, которые я бы порекомендовал; все они, кажется, либо не говорят того, что имеет значение, либо уходят далеко вглубь математики. Это одна из лучших хардкорных математических статей, которые я быстро нашел. Честно говоря, во многом (для меня) это удобно с линейной алгеброй, которая пронизывает математику вращения; как только вы получите контекст, сами матрицы станут довольно простыми. - person user2475059; 13.04.2016