KS drehen: Matritzenrechnung? oder Winkelfunktionen?



  • moin.
    Ich möchte gerne ein Programm schreiben, das mir die jeweilige Position (XYZ) ausgibt,
    an der sich ein Punkt nach der Drehung um eine Achse des Koordinatensystems befindet.

    zum mitschreiben:
    ich füttere das Programm mit folgenden Werten:

    posi des Grundkoordinatensystems, hier: X0Y0Z0
    Drehung des Grundkoordinatensystems, hier: X0° Y0° Z0°
    ein zweites KS, deckungsgleich mit KS1
    ein Punkt im Raum, hier: X1 Y0 Z0
    der Punkt bewegt sich immer mit KS2 mit.

    bis jetzt ist noch alles einfach. Wenn ich nun KS2 um die Y-Achse verdrehe,
    ändern sich lediglich X und Z im Bezug auf KS1
    Hier: sagen wir 30°... dann ist der Punkt bei....KS1 X0.866 und Z0.5

    jetzt kommts:
    wenn wir jetzt das KS2 um die X-Achse drehen, ändern sich die Koordinaten des Punktes
    in allen 3 Achsen - weil ja die X-Achse um 30° nach oben geschwenkt ist.
    Wie kann ich das in C berechnen?
    Ich habe es mit Winkelfunktionen probiert, komme aber auf keinen grünen Zweig...

    Danke für Eure Hilfe
    Krishna



  • würde dir sehr empfehlen das Ganze per Matrix zu machen da das "zu Fuss" per Winkelfunktionen eigentlich nur "a pain in the ass" ist. 🙄

    Ich denke, fürn Anfang ists wohl am geschicktesten Vektoren und Matrizen als structs (4 x 1, bzw. 4 x 4 double) zu definieren (soll ja C sein, oder?) und dir ein paar Routinen für Multiplikation von Matrix X Matrix bzw. Matrix X Vector zu stricken. Wenn das mal funktioniert, ist die Implementierung sog. Affiner Transformationen nicht mehr tragisch und einfach über das richtige "Befüllen" der Trafo-Matrix zu erledigen.
    Wenn du an diesem Ansatz interessiert bist, hätt ich noch einiges an Code dazu rumliegen ... allerdings C++, glaub ich.

    grüße



  • hmmmm.
    gerne.
    kannst Du mir erklären, wie ich sie anwende?
    ich habe bisher mit Matritzen noch nichts zu tun gehabt.
    ist das schwierig? 🙂

    Danke für die schnelle Antwort....



  • tja - schwierig ist immer relativ 🙂
    Ist alles in allem ein großes Thema in der Computergraphik und Thema zahlloser Internetseiten, Bücher und Vorlesungen.
    Die Frage ist, willst du nur mal schnell einen speziellen Fall berechnen oder möchtest du den code dann später nochmal erweitern und auch für anderes KS-Trafos verwenden?

    Speziell für eine Rotation um die X-Achse sieht die Matrix wie folgt aus

    |  1       0           0       0  |
    |  0  cos(alpha)  -sin(alpha)  0  |
    |  0  sin(alpha)  cos(alpha)   0  |
    |  0       0           0       1  |
    

    Rotieren tut das Teil dann, indem du nen Vektor oder Punkt damit multiplizierst.
    Als Ergebnis bekommst dann wieder nen Vektor oder Punkt.

    Für C würde sich dann also ne Matrix/Vektor-Struktur anbieten:

    typedef struct {
       double cell[4][4];
    } Matrix;
    
    typedef struct {
       double cell[4];
    } Vector;
    
    typedef Vector Vertex;
    typedef enum { X, Y, Z, W } Coordinate;
    

    Die 4te Komponente wird im Vector eigentlich nicht wirklich benötigt, allerdings Vereinfacht diese das Rechnen für homogene Koordinaten ... (siehe W-Komponente im enum - nicht wichtig im Moment!)

    Zur Multiplikation mit nem Vector:

    Vector multVector( const Matrix *m, const Vector *v ) {
       Vector result;
       result.cell[X] = m->cell[X][X] * v->cell[X] + m->cell[X][Y] * v->cell[Y] + m->cell[X][Z] * v->cell[Z] );
       result.cell[Y] = m->cell[Y][X] * v->cell[X] + m->cell[Y][Y] * v->cell[Y] + m->cell[Y][Z] * v->cell[Z] );
       result.cell[Z] = m->cell[Z][X] * v->cell[X] + m->cell[Z][Y] * v->cell[Y] + m->cell[Z][Z] * v->cell[Z] );
       result.cell[W] = 0.0;
       return result;
    }
    

    Für Punkte (Vertex) ändert sich das Ganze ein bisschen - hier brauchts dann auch (zumindest später dann für Perspektive) die W-Komponente:

    Vertex multVertex( const Matrix *m, const Vertex *v ) {
       Vertex result;
       result.cell[X] = m->cell[X][X] * v->cell[X] + m->cell[X][Y] * v->cell[Y] + m->cell[X][Z] * v->cell[Z] + m->cell[X][W] * v->cell[W] );
       result.cell[Y] = m->cell[Y][X] * v->cell[X] + m->cell[Y][Y] * v->cell[Y] + m->cell[Y][Z] * v->cell[Z] + m->cell[Y][W] * v->cell[W] );
       result.cell[Z] = m->cell[Z][X] * v->cell[X] + m->cell[Z][Y] * v->cell[Y] + m->cell[Z][Z] * v->cell[Z] + m->cell[Z][W] * v->cell[W] );
       result.cell[W] = m->cell[Z][X] * v->cell[X] + m->cell[Z][Y] * v->cell[Y] + m->cell[Z][Z] * v->cell[Z] + m->cell[Z][W] * v->cell[W] );
       return result;
    }
    

    [Hoff, da hat sich jetzt kein Fehler eingeschlichen ...]
    Schaut vielleicht alles schlimmer aus als es ist 😉 - das Nette dran ist halt, dass es für den Allgemeinfall funktioniert und du nur noch deine Matrix füllen musst - je nachdem, was du machen willst: rotieren, verschieben, skallieren, verzerren ... geht dann alles damit.

    Hab auf die Schnelle noch nen Link gefunden, wo du die Matrizen nachgucken kannst - ist von der TUM und fürn Anfang vielleicht etwas viel - aber nur nicht abschrecken lassen 😉
    http://wwwbruegge.in.tum.de/pub//Lehrstuhl/ProgrammierpraktikumSoSe2005/Mathe_Grundlagen_3DCG.pdf

    viel Erfolg damit!



  • die matrizenschreibweise sieht besser aus, aber matrizenrechnung in c komplett selber zu implementieren ist daemlich. da gehts doch "zu fuss" echt einfacher:

    x zeigt nach rechts, y zeigt nach oben, rotation gegen den uhrzeiger

    neuesx = x * cos(a) - y * sin(a)
    neuesy = x * sin(a) + y * cos(a)



  • c.rackwitz schrieb:

    die matrizenschreibweise sieht besser aus, aber matrizenrechnung in c komplett selber zu implementieren ist daemlich. da gehts doch "zu fuss" echt einfacher:

    x zeigt nach rechts, y zeigt nach oben, rotation gegen den uhrzeiger

    neuesx = x * cos(a) - y * sin(a)
    neuesy = x * sin(a) + y * cos(a)

    hast du gut erkannt 😉 - leitet sich ja auch direkt aus der Rotationsmatrix ab ...
    allerdings, um mich zu wiederholen:

    Sepp Brannigan schrieb:

    Die Frage ist, willst du nur mal schnell einen speziellen Fall berechnen oder möchtest du den code dann später nochmal erweitern und auch für anderes KS-Trafos verwenden?


Anmelden zum Antworten