2013-02-24 17 views
6

Chcę obrócić mój samochód o 90 stopni w lewo w grze, którą mam.Jak prawidłowo obracać kwaterę GLM?

Kiedy używam tego kodu:

  glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z); 
      glm::quat done(glm::rotate(rot,glm::eulerAngles(rot)+glm::vec3(90.0f,0.0,0.0))); 
      info.Rotation.x = done.x; 
      info.Rotation.y = done.y; 
      info.Rotation.z = done.z; 
      info.Rotation.w = done.w; 

Samochód dostaje dziwny obrót.

Jednak następujące kody nie zmienia rotację samochodów w ogóle (tylko, czego się spodziewałem, tak aby mieć pewność, że GLM jest kompatybilny z czwartorzędowych z gry):

  glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z); 
      glm::quat done(rot); 
      info.Rotation.x = done.x; 
      info.Rotation.y = done.y; 
      info.Rotation.z = done.z; 
      info.Rotation.w = done.w; 

i gdy próbuję to, by sprawdzić, czy rotacja zmienia się z nim:

  glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z); 
      glm::quat done(glm::rotate(rot,vec3(0.0,0.0,0.0))); 
      info.Rotation.x = done.x; 
      info.Rotation.y = done.y; 
      info.Rotation.z = done.z; 
      info.Rotation.w = done.w; 

rotacja samochodów jest po prostu ustawić na 0,0,0,0 obrotów w grze. Spodziewałem obroty pozostają nietknięte z tym kodem, bo oczekiwano poniższy kod, żeby obrócić samochód o 90 stopni w lewo:

  glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z); 
      glm::quat done(glm::rotate(rot,vec3(90.0,0.0,0.0))); 
      info.Rotation.x = done.x; 
      info.Rotation.y = done.y; 
      info.Rotation.z = done.z; 
      info.Rotation.w = done.w; 

ale to nie działa tak, jak chcę. To po prostu Ustawia obrót, a nie dodaje go do "zgnilizny".

Co robię źle?

+1

Spójrz na http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Quaternions.html – user1929959

+0

trued kod z tam, ale tak naprawdę nie obracać mojego samochodu, co jest potrzebne w "kąt" parametru, kąt samochodu, aby pozwolić mu działać poprawnie? Z Angle czy coś? –

+0

@Gizmo: [Spójrz na to pytanie i odpowiedzi.] (Http://stackoverflow.com/q/9715776/734069) –

Odpowiedz

0

Jeśli nie interesuje Cię blokada przegubu Cardana, to powinno zadziałać.

glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z); 
glm::quat rot_euler_angles = glm::gtx::quaternion::eulerAngles(rot); 
rot_euler_angles.x += 90; 

glm::quat done(glm::rotate(rot,rot_euler_angles)); 
info.Rotation.x = done.x; 
info.Rotation.y = done.y; 
info.Rotation.z = done.z; 
info.Rotation.w = done.w; 

myślę, że to również ważny

glm::vec3 rot(90.0*(float)M_PI/180.0, 0, 0); 
info.Rotation = glm::normalize(info.Rotation * glm::quat(rot)); 

Quaternions są fantastyczne, ponieważ mogą one być spotęgowane do bardzo skomplikowanych obrotów.

0

[Choć nie jest GLM The zamawiania z kwaterniony w mnożenie jest jeszcze całkiem jasne, a to zwykle problem]

Użyłem kodu tak, aby uniknąć blokady kardanowego (ponieważ każdy rozwiązanie polegające na wprowadzeniu blokady kardana do kodu, który ma już jony, jest po prostu zbyt ironiczne do rozważenia).

To jest kod C, a QuaternionFromAngles() i QuaternionMultiply() zastępują cel pierwszego parametru. world->axis6_input_rotation to tylko Quaternionf_t. Dane wejściowe pochodzą z 6-osiowego kontrolera, który jest nieco bardziej darmową formą, niż Twój pojazd, chyba że faktycznie podajesz wektory w swoim kodzie.

typedef struct { float w, x, y, z; } Quaternionf_t; 

void GuiMotion6axis(World_t *world, Port_t *port, 
        int x, int y, int z, 
        int xr, int yr, int zr) 
{ 
    // convert spaceball input to World->rotation (a quaternion) 
    // Source http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm 
    const float scale = 0.0004; // should factor in the time delta it covers as well. 
    float xrf = (float)xr * scale; 
    float yrf = (float)yr * scale; 
    float zrf = (float)zr * scale; 

    QuaternionFromAngles(& world->axis6_input_rotation, xrf, yrf, zrf); 
    QuaternionMultiply(& world->rotation, // worldrot = inputrot * worldrot 
         & world->axis6_input_rotation, // a read-only use 
         & world->rotation    // a read-only use 
         ); 

    world->position.x += (float)x * scale; // really should factor in the 
    world->position.y += (float)y * scale; // elasped time. 
    world->position.z += (float)z * scale; 
    return; 
}