Проблема с переворотом камеры

Я программирую игру на С#, используя движок XNA3.1. Однако у меня есть небольшая проблема с моей камерой, в основном моя камера имеет тенденцию «переворачиваться», когда она поворачивается более чем на 180 градусов по крену (когда камера достигает 180 градусов, она, кажется, переворачивается обратно на 0 градусов). Код для получения матрицы представления выглядит следующим образом:

Globals.g_GameProcessingInfo.camera.viewMat = Matrix.CreateLookAt(Globals.g_GameProcessingInfo.camera.target.pos, Globals.g_GameProcessingInfo.camera.LookAt, up);                //Calculate the view matrix

Переменная Globals.g_GameProcessingInfo.camera.LookAt представляет собой позицию на 1 единицу непосредственно перед камерой относительно вращения камеры, а переменная «вверх» получается с помощью следующей функции:

static Vector3 GetUp()      //Get the up Vector of the camera
{
    Vector3 up = Vector3.Zero;
    Quaternion quat = Quaternion.Identity;
    Quaternion.CreateFromYawPitchRoll(Globals.g_GameProcessingInfo.camera.target.rot.Y, Globals.g_GameProcessingInfo.camera.target.rot.X, Globals.g_GameProcessingInfo.camera.target.rot.Z, out quat);

    up.X = 2 * quat.X * quat.Y - 2 * quat.W * quat.Z;       //Set the up x-value based on the orientation of the camera
    up.Y = 1 - 2 * quat.X * quat.Z - 2 * quat.Z * quat.Z;   //Set the up y-value based on the orientation of the camera
    up.Z = 2 * quat.Z * quat.Y + 2 * quat.W * quat.X;       //Set the up z-value based on the orientation of the camera
    return up;      //Return the up Vector3
}

person Ice Phoenix    schedule 13.01.2010    source источник
comment
Просто для обновления я реализовал функцию преобразования вектора вверх на основе вращения камеры с помощью Vector.Transform(). Затем я подумал, что проблема может быть вызвана тем, что вектор вверх равен вектору взгляда, и поэтому он перевернулся (как это было проблемой в предыдущих играх). После перекодирования функции для обновления взгляда на положение камера по-прежнему имеет тенденцию переворачиваться в той же области, и ничего драматического не происходит с вращением или взглядом на переменные камеры.   -  person Ice Phoenix    schedule 14.01.2010
comment
Попробуйте отредактировать вопрос, а не добавлять комментарий к своему вопросу при добавлении дополнительной информации. Комментарии — это способ обсудить или прокомментировать чужие ответы или чужие комментарии.   -  person Manish    schedule 15.01.2010


Ответы (5)


У меня такие же проблемы в OpenGL с gluLookAt. Я исправил эту проблему с помощью своего собственного класса камеры:

void Camera::ComputeVectors()
{
    Matrix4x4 rotX, rotZ;
    Quaternion q_x, q_y, q_z;
    Quaternion q_yx, q_yz;
    q_x.FromAngleAxis(radians.x, startAxisX);
    q_y.FromAngleAxis(radians.y, startAxisY);
    q_z.FromAngleAxis(radians.z, startAxisZ);
    q_yx = q_y * q_x;
    q_yx.ToMatrix(rotZ);
    q_yz = q_y * q_z;
    q_yz.ToMatrix(rotX);
    axisX = startAxisX;
    axisZ = startAxisZ; 
    axisX.Transform(rotX);
    axisZ.Transform(rotZ);
    axisY = axisX.Cross(axisZ);

    position = startPosition;
    position -= center;
    position.Transform(q_yx);
    position += center;
}

Возможно, это слишком сложно, но работает. axisY — ваш восходящий вектор. Полный список кодов находится по адресу: http://github.com/filipkunc/opengl-editor-cocoa/blob/master/PureCpp/MathCore/Camera.cpp

Надеюсь, поможет.

person Filip Kunc    schedule 18.01.2010
comment
эй, чувак, огромное спасибо за это, это определенно помогло, и проблема теперь решена, не знаю, что могло пойти не так, но эта функция решила проблему: D. - person Ice Phoenix; 19.01.2010

Это, вероятно, медленнее, но единственный способ, который я знаю, - это матрица вращения для 3D. Ссылка на Википедию

alt text

Где

alt text

и U = (Камера.положение - Камера.взгляд).норма

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

person Buttink    schedule 15.01.2010
comment
хм, выглядит интересно, я посмотрю на это, но я почти уверен, что правильно понимаю направление вверх. Спасибо за информацию - person Ice Phoenix; 15.01.2010

Мех надеялся увидеть где-нибудь там загар.

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

как вы настраиваете поворот камеры? ты уверен, что там ничего не происходит?

person John Nicholas    schedule 13.01.2010
comment
Я получил уравнение из некоторых старых слайдов лекций, которые я просматривал, когда получал степень по программированию. Это чисто математический способ вычисления восходящего вектора на основе вращения кватерниона. Я устанавливаю вращение камеры в различных областях игры с помощью Vector3 (тангаж, рыскание, крен), и я не вижу ничего смешного. - person Ice Phoenix; 13.01.2010

Я немного не уверен в математике вашего метода GetUp. Не могли бы вы подробнее рассказать о математике, стоящей за этим?

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

Некоторый полукод, чтобы уточнить, возможно:

var up = Vector3.Up;
var target = <some point in space>;
var rotation = <current rotation quaternion>;

var forward = target - position;
forward = Vector3.Transform(forward, rotation);

var updatedPosition = target - forward;
var updatedUp = Vector3.Transform(up, rotation);

var view = Matrix.CreateLookAt(updatedPosition, target, updatedUp);
person Peter Lillevold    schedule 13.01.2010
comment
Код в методе GetUp представляет собой фрагмент кода камеры, который я обычно использую, который я изначально получил со слайдов своей лекции, полученной на моем курсе программирования. Прошло некоторое время с тех пор, как я проанализировал фактическую математику, стоящую за этим, но нам в основном сказали, что это даст вам направление вверх на основе ориентации (и это работало в предыдущих проектах, над которыми я работал). Я вижу, как вы это объясняете, и я попытаюсь попробовать, так как это менее сложно и исключает любую математическую ошибку. - person Ice Phoenix; 13.01.2010
comment
Я согласен, Up.z чувствует, что ему нужно где-то. - person Jason Hernandez; 15.01.2010

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

Я обнаружил, что это на самом деле довольно просто. Просто сделайте это:

Matrix ypr = Matrix.CreateFromYawPitchRoll(yaw, pitch, roll);
Vector3 up = Vector3.Transform(Vector3.Up, ypr);

«вверх» — это нужное вам направление.

person Jin    schedule 07.12.2011