现在,我的相机正在向前和向后移动。
我的箭头键有一个例程,用于更改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值而不是正确的相机.ex值。所以我的问题是,你如何处理OpenGL中的相机移动?我是否必须跟踪我正在看的“角度”,并做一些触发?
答案 0 :(得分:3)
您应该跟踪相机方向,以便将相机移动到正确的坐标系中,即相机本地(模型空间)。另外,要避免gimbal lock,您应该开始使用四元数。 使用四元数的原因是当你处理欧拉角时,遵循正确的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教程。