我无法理解此问题背后的数学原理,我正在尝试创建一个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
);
};
答案 0 :(得分:2)
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
是相机在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);