2009-07-24 11 views
2

Ich versuche, ein Kamera-Modell in Delphi/OpenGL nach der Beschreibung in OpenGL SuperBible zu implementieren. Die Kamera hat eine Position, einen Vorwärtsvektor und einen Aufwärtsvektor. Das Übersetzen der Kamera scheint OK zu sein, aber wenn ich versuche, die Kamera entsprechend dem Vorwärtsvektor zu drehen, verliere ich mein Objekt.OpenGL: Hilfe bei der Kamera-Umwandlung

function TCamera.GetCameraOrientation: TMatrix4f; 
var 
    x, z: T3DVector; 
begin 
    z := T3DVector.Create(-FForward.X, -FForward.y, -FForward.z); 
    x := T3DVector.Cross(z, FUp); 

    result[0, 0] := x.X; 
    result[1, 0] := x.Y; 
    result[2, 0] := x.Z; 
    result[3, 0] := 0; 

    result[0, 1] := FUp.X; 
    result[1, 1] := FUp.Y; 
    result[2, 1] := FUp.Z; 
    result[3, 1] := 0; 

    result[0, 2] := z.x; 
    result[1, 2] := z.y; 
    result[2, 2] := z.z; 
    result[3, 2] := 0; 

    result[0, 3] := 0; 
    result[1, 3] := 0; 
    result[2, 3] := 0; 
    result[3, 3] := 1; 
end; 

procedure TCamera.ApplyTransformation; 
var 
    cameraOrient: TMatrix4f; 
    a, b, c: TMatrix4f; 
begin 
    cameraOrient := getcameraOrientation; 
    glMultMatrixf(@cameraOrient); 
    glTranslatef(-FPosition.x, -FPosition.y, -FPosition.z); 
end; 

die Position Given (0, 0, -15) Vorwärts-Vektor (0 0 1) und bis-Vektor (0 1 0), I erwartet, dass eine Identitätsmatrix von dem getCameraOrientation-Verfahren zu erhalten, aber stattdessen bekomme ich

(1, 0, 0, 0) 
(0, 1, 0, 0) 
(0, 0, -1, 0) 
(0, 0, 0, 1) 

Wenn ich den Vorwärtsvektor (0 0 -1) ändern erhalte ich die folgende Matrix:

(-1, 0, 0, 0) 
(0, 1, 0, 0) 
(0, 0, 1, 0) 
(0, 0, 0, 1) 

nach dem Aufruf von glMultMatrix() und glTranslate(), glGet () gibt mir folgende GL_MODELVIEW_MATRIX:

(1, 0, 0, 0) 
(0, 1, 0, 0) 
(0, 0, -1, 0) 
(0, 0, 15, 1) 

ich hätte die 15 erwartet in Spalte 4 zu sein, Zeile 3, nicht Spalte 3, Zeile 4

Kann jemand sehen, wo ich diese falsch gemacht?

EDIT: Der ursprüngliche Code von OpenGL SuperBible:

inline void GetCameraOrientation(M3DMatrix44f m) 
     { 
     M3DVector3f x, z; 

     // Make rotation matrix 
     // Z vector is reversed 
     z[0] = -vForward[0]; 
     z[1] = -vForward[1]; 
     z[2] = -vForward[2]; 

     // X vector = Y cross Z 
     m3dCrossProduct(x, vUp, z); 

     // Matrix has no translation information and is 
     // transposed.... (rows instead of columns) 
     #define M(row,col) m[col*4+row] 
      M(0, 0) = x[0]; 
      M(0, 1) = x[1]; 
      M(0, 2) = x[2]; 
      M(0, 3) = 0.0; 
      M(1, 0) = vUp[0]; 
      M(1, 1) = vUp[1]; 
      M(1, 2) = vUp[2]; 
      M(1, 3) = 0.0; 
      M(2, 0) = z[0]; 
      M(2, 1) = z[1]; 
      M(2, 2) = z[2]; 
      M(2, 3) = 0.0; 
      M(3, 0) = 0.0; 
      M(3, 1) = 0.0; 
      M(3, 2) = 0.0; 
      M(3, 3) = 1.0; 
     #undef M 
     } 

    inline void ApplyCameraTransform(bool bRotOnly = false)  
     { 
     M3DMatrix44f m; 

     GetCameraOrientation(m); 

     // Camera Transform 
     glMultMatrixf(m); 

     // If Rotation only, then do not do the translation 
     if(!bRotOnly) 
      glTranslatef(-vOrigin[0], -vOrigin[1], -vOrigin[2]); 
     } 

Antwort

2

Da der Code von getcameraOrientation die resultierende Matrix ist ganz offensichtlich: forward = (0, 0, 1) ergibt z = (0, 0, - 1), was der 3. Zeile der Matrix entspricht. Das Kreuzprodukt von z = (0, 0, -1) und FUp = (0, 1, 0) ergibt x = (1, 0, 0), was der ersten Zeile der Matrix entspricht. Die zweite Zeile ist nur eine Kopie von FUp und die vierte Zeile ist nur behoben.

Ich verstehe eigentlich nicht, was Sie erreichen wollen, aber wenn Sie die Kamera drehen, verlieren Sie deutlich Ihr Objekt. In der realen Welt, wenn Sie einen Punkt betrachten und Ihren Kopf drehen - es ist das gleiche. Haben Sie versucht, die Reihenfolge von Übersetzung und Rotation umzukehren?

+0

Er sollte in der Lage sein, sich um den Vorwärtsvektor zu drehen, ohne sein Objekt aus den Augen zu verlieren. – Nosredna

+0

Ich rotiere nicht um den Vorwärtsvektor, ich rotiere entsprechend dem Vorwärtsvektor. In meinem Fall, wo oben ist gerade auf der y-Achse, wird dies die gleiche sein wie eine Drehung um die y-Achse. Da vorwärts gerade entlang der z-Achse verläuft, sollte es überhaupt keine Drehung geben. Aber da ist, so verliere ich die Spur meines Objekts .... – Vegar

+2

Nun die Matrix in Ihrem ersten Fall kehrt die Z-Achse zurück. Wenn Sie auf die positive Z-Achse "schauen", wird das Zurückkehren nur "zurückschauen". Warum wird z aus dem negativen Vorwärtsvektor berechnet, anstatt nur eine Kopie zu sein? –

1

Einheitsmatrix

Ich bin mir nicht sicher, warum die SuperBible mit schlägt vor (-FForward.X, -FForward.y, -FForward.z) Ihre Z-Vektor zu erstellen. Wenn Sie die Minuszeichen herausnehmen, erhalten Sie die Identitätsmatrix, die Sie erwarten, wenn Ihr Vorwärtsvektor (0, 0, 1) ist.

Wenn Sie die Minuszeichen beibehalten möchten und einen Vorwärtsvektor von (0, 0, -1) möchten, um eine Identitätsmatrix zu erstellen, müssen Sie das Kreuzprodukt von Cross (z, FUp) zu ändern Cross (FUp, z), weil OpenGL ein rechtshändiges Koordinatensystem verwendet. Siehe Cross product.

15 an der falschen Stelle

Ich stimme Ihnen zu, dass ich eine Übersetzungsmatrix wie folgt aussehen erwarten:

(1, 0, 0, x) 
(0, 1, 0, y) 
(0, 0, 1, z) 
(0, 0, 0, 1) 

Beachten Sie aber, dass OpenGL seine Matrix in Spalte speichert bestellen nicht Zeile bestellen, also wenn Sie die Modelview Matrix glGet wird es in dieser Reihenfolge kommen:

(m[0], m[4], m[8], m[12]) 
(m[1], m[5], m[9], m[13]) 
(m[2], m[6], m[10], m[14]) 
(m[3], m[7], m[11], m[15]) 

Wenn Sie dachten, dass es in der Reihenreihenfolge war, dann kann das sein, was die Verwirrung verursacht.

Verwandte Themen