简体   繁体   English

使用OpenGL和GLUT创建FPS风格的运动系统

[英]Creating an FPS style movement system with OpenGL and GLUT

I'm trying to implement a first person movement system using GLUT and OpenGL. 我正在尝试使用GLUT和OpenGL实现第一人称移动系统。 So far I have the strafing left to right, and forward/backward movement working correctly. 到目前为止,我已经从左到右进行了调整,并且前进/后退动作正常进行。 However, my problem comes with the looking around. 但是,我的问题来自环顾四周。 I want to be able to use the movement of the mouse to look around, like most/all FPS games. 我希望能够像大多数/所有FPS游戏一样使用鼠标的移动来环顾四周。 I'm using gluLookAt for all of my movement/looking around. 我正在使用gluLookAt进行所有移动/环顾四周。 Currently, for the looking around section, I have this (taken from a tutorial) 目前,在“环顾四周”部分中,我有此内容(来自教程)

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

Then for when there is a passive mouse movement, I check for it and do this: 然后,当有被动的鼠标移动时,我检查并执行以下操作:

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

However, this is giving me some really weird, wobbly effect, not particularly close to the one I want. 但是,这给了我一些非常奇怪,颤抖的效果,与我想要的效果并不特别接近。

First off, as far as I know gluLookAt is deprecated, you should consider looking at GLM its a math library that handles pretty much all the mathy stuff for you if you don't want to delve down to that level. 首先,据我所知,不赞成使用gluLookAt,如果您不想深入到该级别,则应考虑查看GLM的数学库,该库可以为您处理几乎所有的数学知识。

Secondly, you could look at using quaternions for your rotation of your camera, they are a lot smoother that just using normal trigonometry for your camera rotation and they also don't suffer from gimbal lock . 其次,您可以考虑使用四元数来旋转相机,它们比使用普通三角法进行相机旋转要平滑得多,并且它们也不会遭受万向节锁定的困扰。 As far as I can remember GLM does have an implementation for quaternions but you can always implement it yourself as well I've done it a long time back and I got it right, so I couldn't have been to hard. 据我所记得,GLM确实有一个四元数的实现,但是您也可以自己实现,我已经很久以前做过了,而且我做对了,所以我不难。 :P :P

If you do want to stick to the trig for now though, here is my old rotate function before I changed to quaternions: 如果您现在确实想继续使用三角函数,则可以在使用四元数之前使用以下旧的rotate函数:

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 is the amount that your mouse has moved from the centre of your screen, and xMid is the middle of your screen. xDelta是鼠标从屏幕中心移开的量,xMid是屏幕中间。 r is the eye of your camera, d is the direction its facing and u is its up vector. r是相机的眼睛,d是其朝向的方向,u是其向上的向量。

If you have any questions just ask me :) 如果您有任何问题,请问我:)

UPDATE: 更新:

Here is the initial article that I used for my implementation of a quaternion based camera . 这是我用于基于四元数的相机的实现的初始文章。

My best advice would just be to try and stay away from euler angles, they lose precision and can cause weird artefacts for movement and rotation. 我最好的建议就是尝试远离欧拉角,因为它们失去了精度,并可能导致移动和旋转的怪异伪像。

The way you are doing it seems right to me except the position part: 我的工作方式对我来说似乎正确,除了职位部分:

position.x = sin(horizontal_angle - 3.14f/2.0f);
position.y = 0.0f;
position.z = cos(horizontal_angle - 3.14f/2.0f);

it should be like that: 应该是这样的:

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() and Key_Pressed depends on the API you use hope it works for you, :). GetKey()和Key_Pressed取决于您使用的API,希望它对您有用:)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM