Für ein Spiel möchte ich ein spherisches Objekt erstellen, ähnlich zu einem Conway/Goldberg Polyhedron. Dazu habe ich 5 und 6 eckige Kacheln erstellt und versuche diese jetzt zu platzieren. Die Sphere soll einen Radius von 25 Meter haben.
Dazu habe ich die Kacheln mit einem Offset von 25 Meter auf der X Achse zum Koordinatenursprung versehen (die Kacheln liegen also auf der Außenseite einer Kugel mit Radius=25m). Also so, als wenn man einen Stift an eine Schnur bindet, und das andere Ende der Schnur festnagelt. Mein Gedanke dabei war, das ich dann ja "nur" die Winkel x/y/z einstellen brauche, und dann ist die Kachel schon am richtigen Ort.
Da ich keine Lust habe x solcher Kacheln von Hand zu platzieren, habe ich versucht mir die Objekte automatisiert zu erstellen.
Der Editor speichert das Objekt in folgendem Format:
x/y/z sind die Skalierungs und Rotationsvektoren (M=R.S)
w1,w2,w3 sind die x/y/z Entfernung in Meter zum Koordinatenursprung (in diesem Falle 0, wegen dem Offset auf dem Objekt selbst).
Jetzt kommt das "Problem":
Im Editor der Engine kann ich ein Objekt um jede Achse einzeln drehen, ohne das die anderen Achsen beeinflusst werden. Um bei dem Beispiel mit dem Stift an der Schnur zu bleiben: Stift um X Grad nach rechts ziehen, und Y Grad nach oben.
Das scheint aber keine Rotation im mathematischen Sinne zu sein.
Als Beispiel habe ich mal die Kachel im Editor um x=17° y=29° und z=35° "rotiert". Wenn ich das Objekt speicher, dann ergeben sich folgende Werte:
Wenn ich aber versuche das zu berechnen, also eine Matrix [[1,0,0] [0,1,0] [0,0,1]] nehme, und nacheinander an den Achsen um die jeweiligen Winkel rotiere, dann erhalte ich aus meinem Programm diese Werte:
Wenn ich das dann im Editor öffne, zeigt der Editor diese Winkel für das Objekt an:
x: -31,1°
y: -12,2°
z: -42,9°
Ehrlich gesagt bin ich nicht so fit in Mathe, dass ich da jetzt erkennen könnte, was ich genau machen muss, um die richtigen Werte zu erhalten.
Ich bin für jede Hilfe dankbar und freue mich, wenn ihr mir hier etwas helfen könntet.
Man muss bedenken, dass Matrix-Multiplikationen nicht kommutativ sind. Das heißt, die Reihenfolge ist wichtig. Wenn du z.B. erst um x, dann um y drehst, kann das Ergebnis anders sein, als wenn du erst um y und dann um x drehst. Vielleicht passiert hier so etwas.
Man muss bedenken, dass Matrix-Multiplikationen nicht kommutativ sind.
Das heißt, die Reihenfolge ist wichtig.
Richtig, das habe ich auch schon rausgefunden. Das ist aber nicht, was ich möchte. Im Editor ist die Reihenfolge anscheinend nicht wichtig, bzw. scheint dort etwas anderes zu passieren.
Vllt ist es eher transformation/translation statt rotation, oder es fehlt noch ein korrektur schritt?
Die in der zweiten Transformation enthaltene Rotationsmatrix (die ersten
9 Elemente) ist die Transponierte der Rotationsmatrix der ersten
Transformation. Da hast du bei deiner Berechnung wohl irgendetwas
durcheinandergeschmissen.
Edit:
Da bei Rotationsmatrizen die Transponierte gleich der Inversen ist, hast
du evtl. statt der Rotation von der Start- zur Zielorientierung
versehentlich die rückwärts gerichtete Rotation, also von der Ziel- zur
Startorientierung berechnet.
die Kacheln liegen also auf der Außenseite einer Kugel mit Radius=25m
Das Goldberg-Polyhedron ist ziemlich tricky. Ich hatte mit denen das Problem, dass meine Kacheln nicht planar wurden. Mir hat dann ein hawaiianischer Mathematiker geholfen. Das Resultat findest du unter https://github.com/eddyverl/FreeCad-Pyramids-and-Polyhedrons.
m *= x_rotation;
m *= y_rotation;
m *= z_rotation;
Die Multiplikation ist falsch herum. Du willst nicht m mit x_rotation multiplizieren, sondern x_rotation mit m. Wie schon anfangs gesagt: Matrix-Multiplikation ist nicht kommutativ.
Die Rotationsmatrix wird also zeilenweise abgelegt, gefolgt vom
Translationsvektor. Du bist irrtümlicherweise davon ausgegangen, dass
die Matrix spaltenweise abgelegt wird, so dass die drei Elemente der
Basisvektoren jeweils direkt hintereinander in der Argumentliste
auftauchen.
Nein, das stimmt so. Godot bezieht die Winkel auf intrinsische
Rotationen (mitdrehendes Koordinatensystem), während Kaj in seinem
Rust-Programm mit extrinsischen Rotationen (feststehendes
Koordinatensystem) rechnet. Diesen Unterschied hat Kaj (bewusst oder
unbewusst) dadurch kompensiert, dass er die Reihenfolge der drei
Einzelrotationen umgedreht hat.
Als Beispiel habe ich mal die Kachel im Editor um x=17° y=29° und z=35°
"rotiert". Wenn ich das Objekt speicher, dann ergeben sich folgende
Werte:
transform = Transform3D(0.716447, -0.501661, 0.48481, 0.664624,
0.702058, -0.255714, -0.212082, 0.505422, 0.836403, 0, 0, 0)
Selbst wenn man die Werte geeignet anordnet, stimmen nur zwei davon mit
denen der obigen Matrix überein. Drei weitere haben das falsche
Vorzeichen, und die restlichen vier sind völlig verschieden.
Die mit deinem modifizierten Rust-Programm berechneten Werte erhältst du
auch in Godot, wenn du dort die "Rotation Order" von "XYZ" in "ZYX"
änderst.