2017-06-08 2 views
-1

J'essaie d'implémenter un système de mouvement de caméra dans le programme sur lequel je travaille actuellement. Je n'arrive pas à comprendre comment déplacer la caméra dans des unités non discrètes, donc quand je bouge la caméra, elle "saute" à la position suivante. comment puis-je déplacer la caméra en douceur sans sauts.SDL OpenGL mouvement de caméra lisse

CameraControlls Fonction:

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

Structure de l'appareil photo:

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; 
}; 
+0

Vous ne savez pas ce que vous demandez. Vous produisez N images par seconde, donc si le mouvement entre les images n et n + 1 est trop large - il semblerait que 'saut'. Vous avez besoin d'une fréquence d'images plus élevée (souvent limitée par les capacités d'affichage), d'un mouvement plus lent ou d'une sorte de flou de mouvement. Cependant, il est très peu probable que cela devienne un problème si votre caméra n'est pas censée se déplacer à très grande vitesse (par exemple, une course à grande vitesse). – keltar

Répondre

1

Je suppose que l'événement clé de sdl ne se déclenche pas chaque image afin que vous ne devez pas modifier la position de la caméra directement à partir de là parce que la caméra ne mettra pas à jour chaque image.

je créerais une MOVE_FORWARD variable booléenne qui représentera si la clé vers l'avant est poussé ou non

  • En cas clé vous mettez à jour la variable MOVE_FORWARD.

    while (SDL_PollEvent(&e)) 
    { 
    .......... 
        case SDL_KEYDOWN: 
         switch (e.key.keysym.sym) 
         { 
         case SDLK_w: 
          MOVE_FORWARD=true; 
          break; 
    
  • Dans chaque image que vous mettez à jour position de la caméra

    if (MOVE_FORWARD){pos+=0.3} 
    

De cette façon, la caméra actualise sa position chaque image et non seulement lorsque l'événement se déclenche clés


Vous pouvez également éviter de créer des variables d'état clés en utilisant SDL_GetKeyboardState(NULL) au lieu de SDL_PollEvent(&e):

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

Vous devez toujours vider la file d'attente des événements (interrogation ou pompage) ou SDL_GetKeyboardState ne recevrait pas les valeurs mises à jour. – keltar