Matrix rotation wie mit OpenGL's "glRotatef", funktioniert bloß nicht ganz



  • Hallo,

    ich habe eine eigene Matrix Klasse geschrieben damit ich nicht dauernd "glGetFloat" und "glLoadMatrixf" verwenden muss.

    Ich habe dafür auch drei extra Funktionen: "matrixRotateX", "matrixRotateY" und "matrixRotateZ"
    Aber um eine Rotation durchführen zu können wie mit "glRotatef(Angle, 1.0f, 1.0f, 1.0)" funktioniert bei miener Funktion "matrixRotate" nicht richtig.

    Das OpenGL Manual beschreibt das so:

    glRotate produces a rotation of angle	degrees	around the
    	  vector (x,y,z).  The current matrix (see glMatrixMode) is
    	  multiplied by	a rotation matrix with the product replacing
    	  the current matrix, as if glMultMatrix were called with the
    	  following matrix as its argument:
    
    		  ( xx(1-c)+c   xy(1-c)-zs  xz(1-c)+ys   0  )
    		  |                                         |
    		  | yx(1-c)+zs  yy(1-c)+c   yz(1-c)-xs   0  |
    		  | xz(1-c)-ys  yz(1-c)+xs  zz(1-c)+c    0  |
    		  |                                         |
    		  (     0            0          0        1  )
    	  Where	c = cos(angle),	s = sine(angle), and ||( x,y,z )|| = 1
    	  (if not, the GL will normalize this vector).
    

    Und meine Funktion arbeitet so:

    typedef f64 double;
    #define SIN(x) sin(x*M_PI/180)
    #define COS(x) cos(x*M_PI/180)
    
            /*
            ( xx(1-c)+c   xy(1-c)-zs  xz(1-c)+ys  0 )
            | yx(1-c)+zs  yy(1-c)+c   yz(1-c)-xs  0 |
            | xz(1-c)-ys  yz(1-c)+xs  zz(1-c)+c   0 |
            (     0           0           0       1 )
            */
            inline matrix4<Type>& matrixRotate(Type Angle, bool isAxisX, bool isAxisY, bool isAxisZ)
            {
                matrix4<Type> tM;
                // Parameters normalization
                f64 x = static_cast<f64>(isAxisX);
                f64 y = static_cast<f64>(isAxisY);
                f64 z = static_cast<f64>(isAxisZ);
                f64 c = COS(Angle);
                f64 s = SIN(Angle);
                f64 cc = 1.0-c;
    
                // Rotation
                tM[0*4+0] = x*x*cc+c;   tM[1*4+0] = x*y*cc-z*s; tM[2*4+0] = x*z*cc+y*s; tM[3*4+0] = 0;
                tM[0*4+1] = y*x*cc+z*s; tM[1*4+1] = y*y*cc+c;   tM[2*4+1] = y*z*cc-x*s; tM[3*4+1] = 0;
                tM[0*4+2] = x*z*cc-y*s; tM[1*4+2] = y*z*cc+x*s; tM[2*4+2] = z*z*cc+c;   tM[3*4+2] = 0;
                tM[0*4+3] = 0;          tM[1*4+3] = 0;          tM[2*4+3] = 0;          tM[3*4+3] = 1;
    
                return *this *= tM;
            }
    

    Was also stimmt an meiner Funktion (oder vielleicht an der Beschreibung) nicht?



  • (x,y,z) ist ein normierter Vektor - steht auch da: ||( x,y,z )|| = 1.
    Warum willst Du eine Rotationsachse als 3 bool uebergeben?



  • glRotate produces a rotation of angle degrees around the
    vector (x,y,z).

    wie gibts du der Funktion den Vektor? bool x, y, z - macht wenig Sinn.

    BTW:
    Hier wird gezeigt wie man die Rotationsmatrixen um X, Y und Z Achse herleiten kann:
    http://loop.servehttp.com/~vertexwahn/oldwiki/public_html_an_turing/MatrizenfuerDummies.pdf

    Google liefert Ergebnisse zum Stichwort: "rotation around an arbitrary axis"

    auf der seite http://mathlib.zfx.info/html_de/ findest du die ZFX-Math Library, die zeigt wie man solche funktionen implementieren kann



  • Naja ich dachte warum soll ich die X, Y, Z Werte als 'float' übergeben wenn die doch sowieso nur 0.0f oder 1.0f sein sollen?!



  • LukasBanana schrieb:

    Naja ich dachte warum soll ich die X, Y, Z Werte als 'float' übergeben wenn die doch sowieso nur 0.0f oder 1.0f sein sollen?!

    warum sollte man hier nicht einen beliebengen Vektor angeben können?



  • Naja jedenfalls sind nicht die boolean Werte am Fehler schuld.

    Wenn ich nur um eine Achse drehe sieht das ganz normal aus, aber wenn ich um alle oder nur um zwei Achsen drehen will werden die Objekte beim Drehen komisch verzehrt.



  • LukasBanana schrieb:

    ...werden die Objekte beim Drehen komisch verzehrt.

    Na dann Mahlzeit.



  • (x,y,z) ist ein normierter Vektor - steht auch da: ||( x,y,z )|| = 1.

    Ist mehr als eins Deiner Bools gesetzt gilt das nicht.



  • hellihjb schrieb:

    Ist mehr als eins Deiner Bools gesetzt gilt das nicht.

    Moment mal, soll das heißen dass nur ein einziger Wert 1, und die beiden anderen 0 sein müssen? 😮


  • Mod

    LukasBanana schrieb:

    hellihjb schrieb:

    Ist mehr als eins Deiner Bools gesetzt gilt das nicht.

    Moment mal, soll das heißen dass nur ein einziger Wert 1, und die beiden anderen 0 sein müssen? 😮

    bei deiner seltsamen implementierung scheinbar schon 🙄



  • soll das heißen dass nur ein einziger Wert 1, und die beiden anderen 0 sein müssen?

    Wie gesagt... Du musst den Vektor normieren.
    Da Du das entweder nicht willst oder nicht verstehst was das bedeutet, funktioniert die Funktion eben nur dann wenn das zufaellig der Fall ist.
    Dank der Bool-Darstellung klappt's immerhin in 37,5% 😉



  • Achso :p *KAPPIER*

    ich weiß schon was normieren ist.

    die Länge des vectors muss 1 sein.
    Achso okay danke 🙂


Anmelden zum Antworten