SDL OpenGL 流畅的相机移动

SDL OpenGL smooth camera movement

我正在尝试将相机运动系统实现到我目前正在处理的程序中。我不知道如何以非离散单位移动相机,所以当我将相机移动到下一个位置时 "jumps"。怎样才能平稳移动相机而不跳动呢

CameraControlls 函数:

void CameraControlls()
{  

while (SDL_PollEvent(&e))
{
    if (e.type == SDL_QUIT)
    {
        exit(0);
    }

    switch (e.type)
    {
    case SDL_KEYDOWN:
        switch (e.key.keysym.sym)
        {
        case SDLK_w:
            cam.MoveForward(0.3f);
            break;
        case SDLK_s:
            cam.MoveBackward(0.3f);
            break;
        case SDLK_d:
            cam.MoveRight(0.2f);
            break;
        case SDLK_a:
            cam.MoveLeft(0.2f);
            break;
        case SDLK_ESCAPE:
            exit(0);
            break;
        case SDLK_RIGHT:
            cam.Yaw(-0.01f);
            break;
        case SDLK_LEFT:
            cam.Yaw(0.01f);
            break;
        case SDLK_DOWN:
            cam.Pitch(0.01f);
            break;
        case SDLK_UP:
            cam.Pitch(-0.01f);
            break;
        }
      }
   }
}

相机结构:

struct Camera
 {
 public:
Camera(glm::vec3& pos, float fov, float aspect, float zNear, float zFar)
{
    this->pos = pos;
    this->forward = glm::vec3(0.0f, 0.0f, 1.0f);
    this->up = glm::vec3(0.0f, 1.0f, 0.0f);
    this->projection = glm::perspective(fov, aspect, zNear, zFar);
}
inline glm::mat4 GetViewProjection() const
{
    return projection * glm::lookAt(pos, pos + forward, up);
}
void MoveBackward(float amt)
{
    pos -= forward*amt;
}
void MoveForward(float amt)
{
    pos += forward * amt;
}
void MoveRight(float amt)
{
    pos -= glm::cross(up, forward) * amt;
}
void MoveLeft(float amt)
{
    pos += glm::cross(up, forward) * amt;
}
void Pitch(float angle)
{
    glm::vec3 right = glm::normalize(glm::cross(up, forward));
    forward = glm::vec3(glm::normalize(glm::rotate(angle, right) * glm::vec4(forward, 0.0)));
    up = glm::normalize(glm::cross(forward, right));
}
void Yaw(float angle)
{
    static const glm::vec3 UP(0.0f, 1.0f, 0.0f);
    glm::mat4 rotation = glm::rotate(angle, UP);
    forward = glm::vec3(glm::normalize(rotation * glm::vec4(forward, 0.0)));
    up = glm::vec3(glm::normalize(rotation * glm::vec4(up, 0.0)));
}
   private:
glm::mat4 projection;
glm::vec3 pos;
glm::vec3 forward;
glm::vec3 up;
};

我想 sdl 的关键事件并不是每帧都触发,所以你不应该直接从那里改变相机位置,因为相机不会更新每一帧。

我会创建一个布尔变量 MOVE_FORWARD 来表示是否按下前进键

  • 在按键事件中更新 MOVE_FORWARD 变量。

    while (SDL_PollEvent(&e))
    {
    ..........
        case SDL_KEYDOWN:
            switch (e.key.keysym.sym)
            {
            case SDLK_w:
                MOVE_FORWARD=true;
                break;
    
  • 在每一帧中你更新相机的位置

    if (MOVE_FORWARD){pos+=0.3}
    

这样相机每帧都会更新它的位置,而不仅仅是在关键事件触发时


您还可以避免使用 SDL_GetKeyboardState(NULL) 而不是 SDL_PollEvent(&e) 创建关键状态变量:

Uint8* keystate = SDL_GetKeyState(NULL);    
if(keystate[SDL_SCANCODE_W])
{
  pos+=0.3;
}