2017-07-04 4 views
0

J'ai une fonction qui fait tourner la caméra autour du joueur par des angles de lacet et de tangage.La précision du flotteur OpenGL rend la différence inattendue

void Camera::updateVectors() { 
    GLfloat radius = glm::length(center - position); 
    position.x = cos(glm::radians(this->yaw)) * cos(glm::radians(this->pitch)); 
    position.y = sin(glm::radians(this->pitch)); 
    position.z = sin(glm::radians(this->yaw)) * cos(glm::radians(this->pitch)); 
    position *= radius; 
    this->front = glm::normalize(center - position); 
    this->right = glm::normalize(glm::cross(this->front, this->worldUp)); 
    this->up = glm::normalize(glm::cross(this->right, this->front)); 
    lookAt = glm::lookAt(this->position, this->position + this->front, this->up); 
} 

quand je déplace le joueur la caméra doit se déplace avec elle en ajoutant un vecteur de translation à la fois le centre et la position de la caméra:

void Camera::Transform(glm::vec3& t) { 
    this->position += t; 
    this->center += t; 
} 

avant de déplacer le lecteur fonctionne le rotation de la caméra fine et le mouvement du joueur fonctionne aussi bien mais une fois que j'essaye de faire tourner la caméra après que le joueur l'ait déplacé, je commence à changer de position de manière inattendue.

enter image description here

après avoir fait un certain débogage j'ai remarqué que le rayon qui est calculé à la première ligne qui est la distance entre le centre et la position de la caméra comme 49,888889 ou 50,000079 et en raison des valeurs initialisées devrait être 50,0, cette très petite différence rend le résultat inattendu. alors comment pourrais-je traiter cette précision float ou y at-il un bug dans mon code ou mes calculs.

Edit: la position du joueur dépend de son lacet et de tangage et mettre à jour le centre de la caméra

GLfloat velocity = this->movementSpeed * deltaTime; 
if (direction == FORWARD) { 
    glm::vec3 t = glm::vec3(sin(glm::radians(yaw)), sin(glm::radians(pitch)), cos(glm::radians(yaw))) * velocity; 
    matrix = glm::translate(matrix, t); 
    for (GLuint i = 0; i < this->m_Entries.size(); i++) { 
     this->m_Entries[i].setModelMatrix(matrix); 
    } 
    glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]); 
    f *= velocity; 
    scene->getDefCamera()->Transform(f); 
} 
if (direction == BACKWARD) { 
    glm::vec3 t = glm::vec3(sin(glm::radians(yaw)), 0.0, cos(glm::radians(yaw))) * velocity; 
    matrix = glm::translate(matrix, -t); 
    for (GLuint i = 0; i < this->m_Entries.size(); i++) { 
     this->m_Entries[i].setModelMatrix(matrix); 
    } 
    glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]); 
    f *= velocity; 
    f = -f; 
    scene->getDefCamera()->Transform(f); 
} 
+0

LookAt = GLM :: LookAt (this-> Position, this- > position + this-> avant, this-> haut); this-> front est un vecteur normalisé. vous ajoutez une petite quantité à votre position de caméra je pense. glm :: lookat deuxième argument devrait être la position mondiale de l'objet, pas sûr ... –

+0

mettre le centre au lieu de position + avant, il pourrait aider, ne sais pas –

+0

le deuxième vecteur dans les paramètres de la fonction lookAt est la direction de la vue et le centre et la position + avant dans la direction du vecteur de sauvegarde de sorte que le résultat est le même – Mohamed

Répondre

0

la solution est simplement fait des transformations sur la vue de la caméra matricielle à la place de ce qui en fait par lookAt fonction premier initialiser l'appareil photo

void Camera::initCamera(glm::vec3& pos, glm::vec3& center, GLfloat yaw, GLfloat pitch) { 
    view = glm::translate(view, center-pos); 
    view = glm::rotate(view, glm::radians(yaw), glm::vec3(0.0, 1.0, 0.0)); 
    view = glm::rotate(view, glm::radians(pitch), glm::vec3(1.0, 0.0, 0.0)); 
    view = glm::translate(view, pos-center); 
} 

alors la fonction de rotation:

void Camera::Rotate(GLfloat xoffset, GLfloat yoffset, glm::vec3& c) { 
    xoffset *= this->mouseSensitivity; 
    yoffset *= this->mouseSensitivity; 
    view = glm::translate(view, c);//c is the player position 
    view = glm::rotate(view, glm::radians(xoffset), glm::vec3(0.0, 1.0, 0.0)); 
    view = glm::rotate(view, glm::radians(yoffset), glm::vec3(1.0, 0.0, 0.0)); 
    view = glm::translate(view, - c); 
} 

et le mouvement de la caméra fonction:

void Camera::Translate(glm::vec3& t) { 
    view = glm::translate(view, -t); 
} 

et dans la classe de joueur lorsque le joueur déplace pousser la caméra de se déplacer dans sa direction par ce code

void Mesh::Move(Move_Directions direction, GLfloat deltaTime) { 
GLfloat velocity = 50.0f * this->movementSpeed * deltaTime; 
if (direction == FORWARD) { 
    glm::vec3 t = glm::vec3(sin(glm::radians(yaw)), sin(glm::radians(pitch)), cos(glm::radians(yaw))) * velocity; 
    matrix = glm::translate(matrix, t); 
    for (GLuint i = 0; i < this->m_Entries.size(); i++) { 
     this->m_Entries[i].setModelMatrix(matrix); 
    } 
    glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]); 
    f *= velocity; 
    scene->getDefCamera()->Translate(f); 
} 
if (direction == BACKWARD) { 
    glm::vec3 t = glm::vec3(sin(glm::radians(yaw)), 0.0, cos(glm::radians(yaw))) * velocity; 
    matrix = glm::translate(matrix, -t); 
    for (GLuint i = 0; i < this->m_Entries.size(); i++) { 
     this->m_Entries[i].setModelMatrix(matrix); 
    } 
    glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]); 
    f *= velocity; 
    f = -f; 
    scene->getDefCamera()->Translate(f); 
} 
if (direction == RIGHT) { 
    matrix = glm::rotate(matrix, (GLfloat) -M_PI * deltaTime, glm::vec3(0.0, 1.0, 0.0)); 
    for (GLuint i = 0; i < this->m_Entries.size(); i++) { 
     this->m_Entries[i].setModelMatrix(matrix); 
    } 
} 
if (direction == LEFT) { 
    matrix = glm::rotate(matrix, (GLfloat) M_PI * deltaTime, glm::vec3(0.0, 1.0, 0.0)); 
    for (GLuint i = 0; i < this->m_Entries.size(); i++) { 
     this->m_Entries[i].setModelMatrix(matrix); 
    } 
} 
} 

merci pour tout le monde a aidé

3

Le principal problème ici est que vous êtes en rotation basé sur une position qui est en mouvement. Mais les rotations sont basées sur l'origine du système de coordonnées. Ainsi, lorsque vous déplacez la position, la rotation est toujours en cours par rapport à l'origine.

Au lieu d'avoir Transform compenser le position, il devrait seulement compenser le center. En effet, stocker position n'a aucun sens; calcule la position de la caméra en fonction de son point central actuel, du rayon et des angles de rotation. Le rayon est une propriété qui devrait être stockée, non calculée.

+0

Cela a beaucoup aidé grâce – Mohamed