Проблемы с вращением камеры OpenGL - PullRequest
1 голос
/ 21 октября 2019

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

Я пытаюсь повернутьи расположите мою точку взгляда со 180 степенями свободы. Я понимаю, что более простое решение - это сделать мир, чтобы он соответствовал моей точке зрения, но я не хочу такой подход. Я довольно незнаком с тригонометрией, которая здесь используется, и не могу понять, как решить эту проблему так, как я хочу ...

Вот моя попытка сделать это до сих пор ...

код, чтобы получить координаты мыши относительно центра окна, затем обработать его в объекте моей камеры

#define DEG2RAD(a) (a * (M_PI / 180.0f))//convert to radians
static void glutPassiveMotionHandler(int x, int y) {
    glf centerX = WinWidth / 2; glf centerY = WinHeight / 2;//get windows origin point
    f speed = 0.2f;
    f oldX = mouseX;  f oldY = mouseY;

    mouseX = DEG2RAD(-((x - centerX)));//get distance from 0 and convert to radians
    mouseY = DEG2RAD(-((y - centerY)));//get distance from 0 and convert to radians

    f diffX = mouseX - oldX; f diffY = mouseY - oldY;//get difference from last frame to this frame

    if (mouseX != 0 || mouseY != 0) {
        mainCamera->Rotate(diffX, diffY);
    }

Код для поворота камеры

void Camera::Rotate(f angleX, f angleY) {
    Camera::refrence = Vector3D::NormalizeVector(Camera::refrence * cos(angleX)) + (Camera::upVector * sin(angleY));//rot up
    Camera::refrence = Vector3D::NormalizeVector((Camera::refrence * cos(angleY)) - (Camera::rightVector * sin(angleX)));//rot side to side
};

Камера:: refrence - наша точка обзора, обработка точки поиска обрабатывается следующим образом

void Camera::LookAt(void) {
    gluLookAt(
        Camera::position.x, Camera::position.y, Camera::position.z,
        Camera::refrence.x, Camera::refrence.y, Camera::refrence.z,
        Camera::upVector.x, Camera::upVector.y, Camera::upVector.z
    );
};

Ответы [ 2 ]

2 голосов
/ 21 октября 2019

Камера определяется точкой положения (position), целевой точкой (refrence) и вектором повышения upVector. Если вы хотите изменить ориентацию камеры, то вам нужно повернуть вектор направления от положения (position) к цели (refrence), а не к целевой точке на Матрица вращения .

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

Напишите функцию, которая устанавливает матрицу вращения 3x3 вокруг произвольной оси:

void RotateMat(float m[], float angle_radians, float x, float y, float z)
{
    float c = cos(angle_radians);
    float s = sin(angle_radians);

    m[0] = x*x*(1.0f-c)+c;   m[1] = x*y*(1.0f-c)-z*s; m[2] = x*z*(1.0f-c)+y*s;
    m[3] = y*x*(1.0f-c)+z*s; m[4] = y*y*(1.0f-c)+c;   m[5] = y*z*(1.0f-c)-x*s;
    m[6] = z*x*(1.0f-c)-y*s; m[7] = z*y*(1.0f-c)+x*s; m[8] = z*z*(1.0f-c)+c };
}

Напишите функцию, которая вращает трехмерный вектор по матрице:

Vector3D Rotate(float m[], const Vector3D &v)
{
  Vector3D rv;
  rv.x = m[0] * v.x + m[3] * v.y + m[6] * v.z;
  rv.y = m[1] * v.x + m[4] * v.y + m[7] * v.z;
  rv.z = m[2] * v.x + m[5] * v.y + m[8] * v.z;
  return rv;
}

Вычислите вектор от позиции до цели:

Vector3D los = Vector3D(refrence.x - position.x, refrence.y - position.y, refrence.z - position.z);

Поверните все векторы вокруг оси z на angleX:

float rotX[9];
RotateMat(rotX, angleX, Vector3D(0, 0, 1));

los = Rotate(rotX, los);
upVector = Rotate(rotX, upVector);

Поверните все векторы вокругтекущая ось y вида на angleY:

float rotY[9];
RotateMat(rotY, angleY, Vector3D(los.x, los.y, 0.0));

los = Rotate(rotY, los);
upVector = Rotate(rotY, upVector);

Рассчитать новую целевую точку:

refrence = Vector3D(position.x + los.x, position.y + los.y, position.z + los.z);
2 голосов
/ 21 октября 2019

U_Cam_X_angle - вращение вправо влево. U_Cam_Y_angle - вращение вверх-вниз.

view_radius - расстояние просмотра (увеличение) до U_look_point_x, U_look_point_y и U_look_point_z. Это ВСЕГДА отрицательное число! Это потому, что вы всегда смотрите в положительном направлении. Глубже на экране больше позитива. Это все в радианах.

Последние три .. eyeX, eyeY и eyeZ - это место, где камера находится в трехмерном пространстве.

Этот код находится на VB.net,Найдите онлайн конвертер для VB в C ++ или сделайте это вручную.

Public Sub set_eyes()

    Dim sin_x, sin_y, cos_x, cos_y As Single
    sin_x = Sin(U_Cam_X_angle + angle_offset)
    cos_x = Cos(U_Cam_X_angle + angle_offset)
    cos_y = Cos(U_Cam_Y_angle)
    sin_y = Sin(U_Cam_Y_angle)
    cam_y = Sin(U_Cam_Y_angle) * view_radius
    cam_x = (sin_x - (1 - cos_y) * sin_x) * view_radius
    cam_z = (cos_x - (1 - cos_y) * cos_x) * view_radius

    Glu.gluLookAt(cam_x + U_look_point_x, cam_y + U_look_point_y, cam_z + U_look_point_z, _
                        U_look_point_x, U_look_point_y, U_look_point_z, 0.0F, 1.0F, 0.0F)

    eyeX = cam_x + U_look_point_x
    eyeY = cam_y + U_look_point_y
    eyeZ = cam_z + U_look_point_z

End Sub
...