使用OpenGL和GLUT创建FPS样式移动系统

时间:2014-10-01 03:41:31

标签: c++ opengl mouse glut frame-rate

我正在尝试使用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);

然而,这给了我一些非常奇怪,颤抖的效果,并不是特别接近我想要的那个。

2 个答案:

答案 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 希望它适合你,:)。