2013-02-24 7 views
6

Ich will mein Auto im Spiel, das ich habe, um 90 Grad nach links drehen.Wie man eine GLM-Quaternion korrekt rotiert?

Wenn ich diesen Code verwenden:

  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; 

Das Auto bekommt eine seltsame Rotation.

jedoch die folgenden Codes nicht die Autos Rotation überhaupt ändern (genau das, was ich erwartet habe, nur um sicher zu sein, dass GLM mit dem Quats aus dem Spiel kompatibel ist):

  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; 

und wenn ich versuche, dies zu überprüfen, ob die Rotation mit ihr verändert wird:

  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; 

die Autos Drehung wird auf die 0,0,0,0 Rotationen im Spiel gerade eingestellt hat. Ich erwartete die Drehungen mit diesem Code unberührt zu bleiben, weil ich den folgenden Code erwartet, dass das Auto um 90 Grad nach links zu drehen:

  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; 

aber das funktioniert nicht so, wie ich will. Es stellt nur die Rotation ein, fügt sie nicht zu 'rot' hinzu.

Was mache ich falsch?

+1

Werfen Sie einen Blick auf http://www.arcsynthesis.org/gltut/Positioning/Tut08%20Quaternions.html – user1929959

+0

den Code von dort abgerichtet, aber mein Auto nicht wirklich drehen, was muss ich in der "Winkel" Parameter, der Winkel des Autos, damit es richtig funktioniert? Z Winkel oder etwas? –

+0

@Gizmo: [Sehen Sie sich diese Frage und Antworten an.] (Http://stackoverflow.com/q/9715776/734069) –

Antwort

0

Wenn Sie sich nicht um Gimbal Lock kümmern, dann sollte dies funktionieren.

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; 

Ich denke, das

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

Quaternionen sind fantastisch, weil sie zusammengesetzt werden können, sehr komplexe Drehungen zu machen.

0

[Dies ist zwar nicht GLM ist, die von Quaternionen in den mehrfachen Bestellung ist immer noch ziemlich klar, und das ist in der Regel das Problem]

ich Code wie folgt verwendet habe Gimbal Lock zu vermeiden (da jeden Lösung, die ein Gimbal-Lock in einen Code einführt, der bereits Quaternionen aufweist, ist einfach zu ironisch, um dies zu berücksichtigen).

Dies ist C-Code, und die QuaternionFromAngles() und QuaternionMultiply() überschreiben das Ziel des ersten Parameters. world->axis6_input_rotation ist nur ein Quaternionf_t. Die Eingabe erfolgt von einem 6-Achsen-Controller, der etwas freier ist als Ihr Fahrzeugsimulator, es sei denn, Sie übergeben Vektoren in Ihrem Code.

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