2014-10-01 83 views
0

我想用GLUT和OpenGL實現第一人稱運動系統。到目前爲止,我已經從左到右掃視,前進/後退運動正常工作。但是,我的問題伴隨着四處張望。我希望能夠像大多數/所有FPS遊戲一樣使用鼠標的移動環視四周。我正在使用gluLookAt來處理我所有的動作/環顧四周。目前,周邊部分看,我有這樣的(從教程中獲得)用OpenGL和GLUT創建一個FPS風格的運動系統

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

首先,據我所知,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是它的朝向,u是它的向上向量。

如果您有任何問題,只是問我:)

UPDATE:

下面是我用我的實施quaternion based camera的初始物品。

我最好的建議就是試着遠離歐拉角度,它們會失去精確度,並可能導致運動和旋轉的怪異人爲因素。

+0

感謝您的回覆,我想我會和四元組一起去,似乎是一個更好的選擇! – Finn 2014-10-02 01:40:48

+0

萬向節鎖是我們頭部旋轉方式的結果,也就是說,當你直視或直下時,你有一個奇點。你的'基於四元數的解決方案'可以避免萬向節鎖,而不是通過四元數的優勢,但是通過將節距夾緊在兩極之外,所以你不能直視或直下。您也可以夾住Eular角度,從而避免出現問題。如果你不夾緊,那麼四元數不會爲你節省,因爲當'視圖 - 位置'平行於'上'時,它們的交叉積將降到零,並且你得到可怕的萬向節鎖。 – ybungalobill 2016-01-02 22:47:28

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