我正在尝试使用GLUT和OpenGL实现第一人称移动系统。到目前为止,我有从左到右的扫描,前进/后退运动正常。但是,我的问题来自环顾四周。我希望能够像大多数/所有FPS游戏一样使用鼠标移动来环顾四周。我正在使用gluLookAt进行所有运动/环顾四周。目前,对于环顾四周的部分,我有这个(取自教程)
gluLookAt(position.x, position.y, position.z,
position.x + direction.x, position.y + direction.y, position.z + direction.z,
up_vector.x, up_vector.y, up_vector.z);
然后,当有一个被动的鼠标移动时,我检查它并执行此操作:
horizontal_angle += 0.005* float(x - origin_x);
vertical_angle += 0.005* float(y - origin_y);
direction_vector.x = cos(vertical_angle) * sin(horizontal_angle);
direction_vector.y = sin(vertical_angle);
direction_vector.z = cos(vertical_angle) * cos(horizontal_angle);
position.x = sin(horizontal_angle - 3.14f/2.0f);
position.y = 0.0f;
position.z = cos(horizontal_angle - 3.14f/2.0f);
up_vector = crossProduct(right_vector, direction_vector);
然而,这给了我一些非常奇怪,颤抖的效果,并不是特别接近我想要的那个。
答案 0 :(得分:2)
首先,据我所知gluLookAt已被弃用,您应该考虑将GLM视为一个数学库,如果您不想深入研究该级别,它可以为您处理几乎所有的东西。
其次,您可以使用quaternions来旋转相机,它们更加平滑,只需使用普通的三角法进行相机旋转,它们也不会受到gimbal lock的影响。据我所知,GLM确实有一个四元数的实现,但你可以自己实现它,我已经做了很长一段时间,我做对了,所以我不能去努力。 :P
如果你现在想要坚持使用trig,那么在我改为四元数之前,这是我的旧旋转功能:
void Camera::rotateCamera(int xDelta, int yDelta, int xMid, int yMid)
{
const GLfloat X_SCALED = (GLfloat)xDelta / (GLfloat)xMid;
const GLfloat Y_SCALED = (GLfloat)yDelta / (GLfloat)yMid;
const GLfloat ANGLE_DELTA = 2 * 360.0f / 360.0f * 3.14f;
const GLfloat LEFT_RIGHT_ROT = X_SCALED * ANGLE_DELTA;
const GLfloat UP_DOWN_ROT = Y_SCALED * ANGLE_DELTA;
direction = d - r;
vec3 right = cross(direction, u);
vec4 temp(direction.x, direction.y, direction.z, 0.0f);
mat4 identity;
identity = rotate(identity, UP_DOWN_ROT, right);
identity = rotate(identity, LEFT_RIGHT_ROT, u) ;
temp = identity * temp;
d = r;
d[0] += temp[0];
d[1] += temp[1];
d[2] += temp[2];
view = lookAt(r,d,u);
}
xDelta是鼠标从屏幕中心移动的数量,xMid是屏幕的中间位置。 r是你的相机的眼睛,d是它面向的方向,你是它的向上矢量。
如果您有任何问题,请问我:)
<强>更新强>
以下是我用于实施quaternion based camera的初始文章。
我最好的建议就是尽量远离欧拉角,它们会失去精确度,并且会导致移动和旋转的怪异伪影。
答案 1 :(得分:2)
除了位置部分之外,你的方式对我来说似乎是正确的:
position.x = sin(horizontal_angle - 3.14f/2.0f);
position.y = 0.0f;
position.z = cos(horizontal_angle - 3.14f/2.0f);
它应该是这样的:
vector right_vector = crossProduct(direction_vector, vector(0, 1, 0)); // maybe crossProduct(vector(0, 1, 0), direction_vector)
float speed = 3; // you decide the value.
if ( GetKey(Key_Forward) == Key_Pressed ) {
position.x += (direction_vector.x * speed);
position.y += (direction_vector.y * speed);
position.z += (direction_vector.z * speed);
} else if ( GetKey(Key_Back) == Key_Pressed ) {
position.x -= (direction_vector.x * speed);
position.y -= (direction_vector.y * speed);
position.z -= (direction_vector.z * speed);
}
if ( GetKey(Key_Right) == Key_Pressed ) {
position.x += (right_vector.x * speed);
position.y += (right_vector.y * speed);
position.z += (right_vector.z * speed);
} else if ( GetKey(Key_Back) == Key_Pressed ) {
position.x -= (right_vector.x * speed);
position.y -= (right_vector.y * speed);
position.z -= (right_vector.z * speed);
}
GetKey()和Key_Pressed取决于您使用的API 希望它适合你,:)。