2013-11-02 54 views
1

現在,我的相機正在向前和向後移動。使用箭頭鍵的OpenGL相機控制

我有一個用於改變gluLookAt調用中使用的相機變量值的箭頭鍵的例程。

gluLookAt(camera.ex,camera.ey, camera.ez, 
    camera.cx,camera.cy,camera.cz, 
    camera.x,camera.y,camera.z); 


// Callback routine for non-ASCII key entry. 
void specialKeyInput(int key, int x, int y) 
{ 

if (key == GLUT_KEY_UP) camera.ez -= 0.1; 
if (key == GLUT_KEY_DOWN) camera.ez += 0.1; 
if (key == GLUT_KEY_LEFT) camera.cx -= 0.1; 
if (key == GLUT_KEY_RIGHT) camera.cx += 0.1; 

glutPostRedisplay(); 
} 

我通過這樣做面臨的問題是,即使我面對的(說向左),我按向上鍵,我「米抵消我camera.ez值,而不是正確的camera.ex值。所以我的問題是,你如何處理在OpenGL中的相機運動?我必須跟蹤我正在看的「角度」,並做一些trig?

+0

你試圖做[這樣的事情](http://gamedev.stackexchange.com/a/31042)? – genpfault

+0

@genpfault是的,我相信是的。儘管我並不完全確定如何遵循這一點...... –

回答

3

你應該跟蹤攝像機的方向,將攝像機移動到正確的座標系中,即攝像機的本地(模型空間)。另外,爲避免gimbal lock,您應該開始使用四元數 使用四元數的原因是當您處理歐拉角遵循cor是很重要的rect rotation order否則你不會得到你想要的。

下面是使用GLM庫基於四元數,第一人稱視角類的簡單的例子:

class Camera 
{ 
public: 
    void move(glm::vec3 directions, glm::vec2 rotations, float frametime); 
    // ... constructors etc. 
private: 
    glm::mat4 view_; 
    glm::vec3 camera_pos_; 
    glm::quat camera_orientation_; 
    const float camera_speed_; 
} 

// move directions - (forward/backward/0, left/right/0, up/down/0). each direction could be 1, -1 or 0 
// rotations - (horizontal_amount, vertical_amount) 
void Camera::move(glm::vec3 directions, glm::vec2 rotations, float frametime) 
{ 
    auto pitch = glm::quat(glm::vec3(-rotations.y, 0, 0.f)); 
    auto yaw = glm::quat(glm::vec3(0, -rotations.x, 0.f)); 

    camera_orientation_ = glm::normalize(yaw * camera_orientation_ * pitch); 

    auto camera_roll_direction = camera_orientation_ * glm::vec3(0, 0, -1); 
    auto camera_pitch_direction = camera_orientation_ * glm::vec3(-1, 0, 0); 

    // forward/backward move - all axes could be affected 
    camera_pos_ += directions[0] * camera_roll_direction * frametime * camera_speed_; 
    // left and right strafe - only xz could be affected  
    camera_pos_ += directions[1] * camera_pitch_direction * frametime * camera_speed_; 
    // up and down flying - only y-axis could be affected 
    camera_pos_.y += directions[2] * frametime * camera_speed_; 

    view_ = glm::lookAt(camera_pos_, camera_pos_ + camera_roll_direction, 
         glm::cross(camera_roll_direction, camera_pitch_direction)); 
} 

而且使用這樣的:

main_loop() 
{ 
    //... 
    glm::vec2 rotation; 
    glm::vec3 directions; 
    rotation.x = get_mouse_move_x_offset(); 
    rotation.y = get_mouse_move_y_offset(); 

    if(is_key_pressed(KEY_D)) directions.y = -1; 
    if(is_key_pressed(KEY_A)) directions.y = 1; 
    if(is_key_pressed(KEY_W)) directions.x = 1; 
    if(is_key_pressed(KEY_S)) directions.x = -1; 
    if(is_key_pressed(KEY_E)) directions.z = 1; 
    if(is_key_pressed(KEY_Q)) directions.z = -1; 

    cam.move(directions, rotation, frametime); 
} 

yaw * camera_orientation_ * pitch乘法的順序很重要,因爲我們需要將偏航變換應用於模型空間中的世界空間和俯仰變換。

有關四元數和旋轉的更多信息,請參閱this教程。

+0

是否有可能不使用任何外部庫並儘可能保持「純」?我知道這聽起來像一個愚蠢的要求。 –

+0

@ Stupid.Fat.Cat你可以自己實現相對容易的四元數和矩陣類,但只要你沒有試圖達到最好的性能,我就沒有看到這麼做。另外GLM是一個只有頭文件的跨平臺庫,所以你不需要任何庫文件,只需#include所需的頭文件 – yuyoyuppe

+0

@Stupid.Fat.Cat另外你需要實現向量和向量操作。 glm :: lookat只是返回矩陣,你需要傳遞給頂點着色器(如果你使用的是opengl 3+)。如果您使用的是opengl 2.0,您可以使用glMatrixMode和glLoadMatrix函數來設置您的模型視圖矩陣。如果你不熟悉矩陣變換,我強烈建議你學習[他們](http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/)。 – yuyoyuppe