旋转OpenGL相机的问题

时间:2019-10-21 13:55:32

标签: opengl trigonometry glut vector-graphics

我无法理解此问题背后的数学原理,我正在尝试创建一个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
};

Camera :: 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 个答案:

答案 0 :(得分:2)

U_Cam_X_angle向左旋转。U_Cam_Y_angle向上旋转。

view_radius是到U_look_point_xU_look_point_yU_look_point_z的观看距离(缩放)。 这总是一个负数!这是因为您一直在朝着积极的方向看。屏幕越深越积极。 这都是弧度的。

最后三个.. eyeXeyeYeyeZ是相机在3D空间中的位置。

此代码在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

答案 1 :(得分:2)

摄像机由位置点(position),目标点(refrence)和上矢量upVector定义。如果要更改相机的方向,则必须将方向矢量从位置(position)旋转到目标(refrence),而不是目标点旋转{{3 }}。

请注意,由于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 };
}

编写一个通过矩阵旋转3维矢量的函数:

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

通过angleX绕着世界的z轴旋转所有矢量:

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

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

通过angleY围绕视图的当前y轴旋转所有矢量:

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