Quaternion + Drehung um gekippte verschobene Achse zu Target?
-
Ich glaub du denkst viel zu kompliziert. Am einfachsten geht man das mit einer Hierarchie von Transformationen an. Du hast eine Transformation die dein Turret relativ zum Schiff platziert. Und dann hast du die Transformation die dein Schiff relativ zur Welt platziert. Die absolute Transformation vom Turret ergibt sich dann indem du die Turret- und Schiffstransformation konkatenierst. Dein Turret richtest du relativ zum Schiff aus. Damit du das kannst brauchst du eben die Koordinaten deines Ziels im Koordinatensystem des Schiffes. Die bekommst du einfach indem du eben das Ziel in Weltkoordinaten mit der inversen Schiffstransformation transformierst. Damit hast du die Ausrichtung des Schiffes relativ zur Welt automatisch berücksichtigt. Jetzt musst du nur noch die Turrets relativ zum Schiff auf diesen transformierten Punkt ausrichten und bekommst damit deine Turret Transformation. Und über die Hierarchie (Welt <- Schiff <- Turret) bekommst du schlussendlich die Transformation die dein Turret in Weltkoordinaten übersetzt.
-
dot schrieb:
...Die absolute Transformation vom Turret ergibt sich dann indem du die Turret- und Schiffstransformation konkatenierst.Dein Turret richtest du relativ zum Schiff aus. Damit du das kannst brauchst du eben die Koordinaten deines Ziels im Koordinatensystem des Schiffes. Die bekommst du einfach indem du eben das Ziel in Weltkoordinaten mit der inversen Schiffstransformation transformierst. Damit hast du die Ausrichtung des Schiffes relativ zur Welt automatisch berücksichtigt.
siehe zweiter Beitrag von mir
WeakPeak schrieb:
...Das Zentrum des Raumschiffes des Spielers, ist im Koordinatensystem auf 0.0f, 0.0f, 0.0f gelegt...also nur eine Rotation um die Y-Achse stattfindet macht das absolut nichts aus, die Winkel werden korrekt berchnet und auch die Eigenrotation des Raumschiffes, welche in die Formeln mit einfliesst , wird korrekt berechnet...
dot schrieb:
Jetzt musst du nur noch die Turrets relativ zum Schiff auf diesen transformierten Punkt ausrichten und bekommst damit deine Turret Transformation. Und über die Hierarchie (Welt <- Schiff <- Turret) bekommst du schlussendlich die Transformation die dein Turret in Weltkoordinaten übersetzt.
einfach:
f32 turmrotationY = getFixedAngle(thisY - 90 - rotationsDifferenz.Y); //getFixedAngle() = Funktion um Rotationswerte auf Werte Zwischen 0° und 359,999...° zu Runden (mittels fmodf) //thisY = Y-Drehung des Schiffes um die Koordinate 0.0,0.0,0.0 //-90 = Die Waffen sind damit Sie in, wenn sie nicht schiessen in Flugrichtung zeigen um 90° gedreht, diese pre-definierte Rotation der Waffen wird hier "Neutralisiert" //RotationsDifferenz = ein Vector3D<f32> welcher die zuvor errechneten "Horizonthalwinkel" (einen Normalisierten Vektor in Richtung des Zielpunktes welcher aus der (Zielskoordinate - Absoluter Position der Waffen) errechnet wird, das .Y wählt dann hier nur die Y-Rotation aus. auch diese Rechnung habe ich mittels atan funktion der math.h nachgerechnet und ja ich habe das PI/180 zur umrechnung zwischen RAD und DEG nicht vergessen.
etwas Komplizierter:
core::vector3df thisVector = emptyY->getAbsolutePosition();//!das wäre der spatiale up vector(ein normalisierter Vektor in die Richtung der Achse um die die Waffe gedreht wird) thisVectorsROTX = thisVector.getSphericalCoordinateAngles().X; thisVectorsROTZ = thisVector.getSphericalCoordinateAngles().Z;//!hier stimmt noch etwas ganz und gar nicht core::vector3df toTargetROT = toTarget; toTargetROT.rotateXYBy(thisVectorsROTX , core::vector3df (weaponAbsPos.X, weaponAbsPos.Y + 0.75f , weaponAbsPos.Z)); toTargetROT.rotateYZBy(thisVectorsROTZ , core::vector3df (weaponAbsPos.X, weaponAbsPos.Y + 0.75f , weaponAbsPos.Z)); core::vector3df rotationsDifferenzFINAL = toTargetROT.getHorizontalAngle();
hierdurch wird der Waffe->Ziel Vektor um die Waffe als Ursprung gedreht, ohne diese Anpassung sieht man ab ca. 20° Kippwinkel(Rotation um die X-Achse bei gleichzeitigem ca 90° Winkel zwischen Schiff und Ziel) mit blossem Auge das die Rotation des Turmes nicht stimmt da die Horizonthalen Winkel für den Nicht gekippten Vektor bzw. die Welt-Achsen berechnet wurden.
für die eingebauten Funktionen bitte ich die definitionen :
[url][/url]
http://irrlicht.sourceforge.net/docu/classirr_1_1core_1_1vector3d.htmlhier zu entnehmen damit ich nicht nicht jede einzelne Funktion erklären muss.
rotatationDifferenzFINAL, also mit gekipptem Vector wird dann im obern Code anstelle von rotationsDifferenz (ohne vectorrotation um den Waffenpunkt als Center) eingetragen, diese Anpassung habe ich kürzlich erst hinzugefügt aber sie ist nicht ganz korrekt da sich bei der Berechnung von thisVectorsROTX/Z ein Fehler eingeschlichen hat, es werden lokale Winkel des Objectes welche sich mit eines Y-Rotation gegenüber den Globalen ändern benutzt, dies wird noch korrigiert.Von einfach bis Kompliziert habe ich alles durch was in irgendeiner Formelsammlung hierzu steht
-
Ich würde dir generell erstmal empfehlen dich von diesem Denken in Eulerwinkeln zu lösen, Winkel sind meiner Erfahrung nach wenn dann überhaupt nur sehr bedingt hilfreich, vor allem in 3D. Für mich hab ich jedenfalls festgestellt dass man sobald irgendwelche Winkel ins Spiel kommen meistens am komplett falschen Weg gelandet ist da man damit, wenn überhaupt, meistens zu einer unnötig komplexen und suboptimalen Lösung kommt. Ich sprach absichtlich von Transformationen und nicht von Rotationen. Angenommen du arbeitest mit Matritzen und Zeilenvektoren (wegen der Multiplikationsreihenfolge) so würde ich ganz naiv erstmal folgendes versuchen:
- Zielposition (TargetPosition) ins lokale Koordinatensystem deines Schiffes Transformieren (ShipTransform ist die Worldmatrix deines Schiffes): RelativeTargetPosition = TargetPosition * ShipTransform^(-1)
- Turret im Schiffskoordinatensystem auf RelativeTargetPosition ausrichten (hier kann man evtl. mit Winkeln rummachen) -> TurretTransform
- Fertig, TurretTransform * ShipTransform ist die finale WorldMatrix für dein Turret
Wenn du z.B. nur eine Matrix berechnen willst die ein Objekt irgendwie ausrichtet brauchst du nix mit Winkeln anfangen. Wenn du beispielsweise eine Achse kennst (z.B. die lokale z-Achse) und einen zweiten Vektor der in einer Ebene mit dieser Achse liegt (z.B. Up Vektor) kannst du über zwei Kreuzprodukte einfach die beiden anderen Achsen ausrechnen. Jetzt nur noch die drei Achsenvektoren in die Zeilen einer Matrix packen und fertig. Unkompliziert und ganz ohne irgendwelche obskuren Winkelberechnungen
Wenn deine Turrets noch relativ zum Schiff irgendwie "schräg" platziert sind kannst du auch einfach den kompletten Weg gehen (TurretLocal ist die Transformation von Turret nach Schiff, definiert also wie auf dem Schiff dein Turret platziert ist):
- Zielposition relativ zum Turret berechnen: RelativeTargetPosition = TargetPosition * ShipTransform^(-1) * TurretLocal^(-1)
- Turret lokal auf RelativeTargetPosition ausrichten -> TurretTransform
- Fertig, TurretTransform * TurretLocal * ShipTransform ist die finale WorldMatrix für dein Turret
Wie dir auffällt rechne ich da oben ausschließlich direkt mit Matritzen, irgendwelche Winkel kommen nirgendwo vor. Ein Turret dient nicht umsonst oft als das Paradebeispiel für eine Transformationshierarchie schlechthin
-
Ok ich baue jetzt erst nochmal alles auf Matrixtransformationen um dann melde ich mich wieder, Danke schonmal.
-
Dumme Frage:
Über den Aufbau hatten wir ja bereits gesprochen.
Die Waffen sind ja an diversen Stellen des Schiffes plaziert, manche haben durch die die Predifinierte Drehung / Rotation / Transformation einen Winkelrichtung CCW also entgegengesetzt zu der des Schiffes...Schiff 10° im Uhrzeigersinn = Waffe -10° im Uhrzeigersinn
was bei allen Waffen "Abschussrohren" zum Beispiel zutrifft.Ich habs umgebaut sieht gerade so aus:
//--- rotate node relative to its current rotation -used in turn,pitch,roll --- void shipObject::rotate(irr::scene::ISceneNode *node, irr::core::vector3df rot) { irr::core::matrix4 m; m.setRotationDegrees(node->getRotation()); irr::core::matrix4 n; n.setRotationDegrees(rot); m *= n; node->setRotation( m.getRotationDegrees() ); node->updateAbsolutePosition(); } //--- turn ship or any node left or right --- void shipObject::turn(irr::scene::ISceneNode *node, irr::f32 rot) { rotate(node, irr::core::vector3df(0.0f, rot, 0.0f) ); } //--- pitch ship or any node up or down --- void shipObject::pitch(irr::scene::ISceneNode *node, irr::f32 rot) { rotate(node, irr::core::vector3df(rot, 0.0f, 0.0f) ); } //--- roll ship or any node left or right --- void shipObject::roll(irr::scene::ISceneNode *node, irr::f32 rot) { rotate(node, irr::core::vector3df(0.0f, 0.0f, rot) ); } //!! Zielen //--- aim the target --- void shipObject::aim(irr::scene::ISceneNode *nodeTarget, irr::scene::ISceneNode *nodeTurret, irr::scene::ISceneNode *nodeWeapon) { // --- get absolute and relative transformation matices for all nodes --- irr::core::matrix4 sh = this->getAbsoluteTransformation (); irr::core::matrix4 tu = nodeTurret->getRelativeTransformation (); irr::core::matrix4 we = nodeWeapon->getRelativeTransformation (); irr::core::matrix4 ta = nodeTarget->getAbsoluteTransformation (); //-- get inverse matrices -- irr::core::matrix4 sh_i; sh.getInverse(sh_i); irr::core::matrix4 tu_i; sh.getInverse(tu_i); irr::core::matrix4 we_i; sh.getInverse(we_i); //-- get relative turret + weapon to target matrices -- irr::core::matrix4 relativeTargetMatrixTur = ta * sh_i * tu_i; irr::core::matrix4 relativeTargetMatrixWea = relativeTargetMatrixTur * we_i; irr::core::vector3df relRotTurTar = relativeTargetMatrixTur.getRotationDegrees(); irr::core::vector3df relRotWeaTar = relativeTargetMatrixWea.getRotationDegrees(); turn(nodeTurret, relRotTurTar.Y); pitch(nodeWeapon, relRotWeaTar.X); } //--- reset weapon position --- void shipObject::resetWeaponPosition(irr::scene::ISceneNode *nodeWeapon) { irr::core::matrix4 w; w.setRotationDegrees(irr::core::vector3df(0.0f, 0.0f, 0.0f)); nodeWeapon->setRotation( w.getRotationDegrees() ); nodeWeapon->updateAbsolutePosition(); } //--- reset weapon position --- void shipObject::resetTurretPosition(irr::scene::ISceneNode *nodeTurret, irr::core::vector3df rot) { irr::core::matrix4 t; t.setRotationDegrees(rot); nodeTurret->setRotation( t.getRotationDegrees() ); nodeTurret->updateAbsolutePosition(); }
aber leider flippen die Waffen in die Ausgangslage zurück während des Schiessens
die Waffen die oben auf dem Schiff montiert sind Beispielsweise, hier der code für die Ausrichtung dieser
turretRotationsList.push_back( core::vector3df(0,90,180) );
leicht zu sehen Z Drehung = 180° stehen also upside down.
Der code zum schiessen (in einfacher form, normalerweise wird hier via timer noch laserstrahldicke, visibilty etc, eingestellt:aim( fireTarget, (*turretsIT), (*turretWeaponListIT));
und zum reseten der Drehungen in die Ausgangslage:
resetTurretPosition((*turretsIT), (*turretRotationsIT)); resetWeaponPosition((*turretWeaponListIT));
Fällt die da was auf warum die Turrets welche upside down sein sollten während des schiessen zurück flippen in 0,0,0 Rotation?
-
Also im moment habe ich je nach Drehung des Schiffes und Target Position alles zwischen sich wild drehenden Waffen und Turrets die upside-down hin und her flippen.
Ich hab da nochmal weiter rumgetestet und habe ja noch ältere, stimmende werte im Kopf.
bei diese Zeile erhalte ich schon komische Werte:
irr::core::matrix4 relativeTargetMatrixTur = ta * sh_i * tu_i;
von 0, 90, 0
es sollten aber sein irgendwas, 105.irgendwas, 0.
hmm
-
Also aktuell sieht mein Code so aus (unkomplett und fehlerhaft) aber ich muss nun erstmal etwas Schlafen.
void shipObject::aim(irr::scene::ISceneNode *nodeTarget, irr::scene::ISceneNode *nodeTurret, irr::scene::ISceneNode *nodeWeapon) { //! std::cout << "\n rotationZ 2 > " << nodeTurret->getRotation().Z; // --- get absolute and relative transformation matices for all nodes --- irr::core::matrix4 sh = this->getAbsoluteTransformation (); irr::core::matrix4 tu = nodeTurret->getAbsoluteTransformation (); irr::core::matrix4 we = nodeWeapon->getAbsoluteTransformation (); irr::core::matrix4 ta = nodeTarget->getAbsoluteTransformation (); //-- get inverse matrices -- irr::core::matrix4 sh_i; sh.getInverse(sh_i); irr::core::matrix4 tu_i; tu.getInverse(tu_i); irr::core::matrix4 we_i; we.getInverse(we_i); //-- get relative turret + weapon to target matrices -- irr::core::matrix4 relativeTargetMatrixTur = ta * tu_i; irr::core::matrix4 relativeTargetMatrixWea = ta * we_i; //-- get the Translations -- irr::core::vector3df relTranslation = relativeTargetMatrixWea.getTranslation(); irr::core::vector3df relTransAngle = relTranslation.getHorizontalAngle(); irr::core::matrix4 tu_to_ta; tu_to_ta.setRotationDegrees(relTransAngle); tu_to_ta *= tu_i; irr::core::vector3df finTuRot = tu_to_ta.getRotationDegrees(); turn(nodeTurret, finTuRot.Y); //!!!pitch(nodeWeapon, relRotWeaTar.X); }
Komischerweise erhalte ich übrigens bei sowas:
irr::core::vector3df rot = nodeTurret->getAbsoluteTransformation ().getRotationDegrees(); std::cout << "\n rot > " << rot.X << " - "<< rot.Y << " - "<< rot.Z; irr::core::vector3df rot2 = nodeTurret->getRotation(); std::cout << "\n rot2 > " << rot2.X << " - "<< rot2.Y << " - "<< rot2.Z;
folgendes Vrgebniss
rot > 0 - 270 - 360
rot2 > 0 - 90 - 180naja Morgen / Heute ist auch noch ein tag
-
Achja das wilde umherzappelnten Turrets hatte übrigens was damit zu tun das die Idee mit dem mit-einberechnen der aktuellen Rotation zwar ganz nett ist aber in einer onRender Funktion dazu führt das die Waffen umherkreiseln / springen
zumindest in verbindung mit einer relativen Veränderung zur aktuellen Rotation.
Ausserdem kommen bei Inversen Matrizen alles mögliche raus nur nichts sinnvolles.
Warum kann ich Matritzen niche einfach regulär lassen und einfach subtrahieren, warum invertieren und multiplizieren?
-
Ich versteh nicht was du da jetzt immer noch dauernd mit diesen ganzen Rotationswinkeln willst.
WeakPeak schrieb:
Warum kann ich Matritzen niche einfach regulär lassen und einfach subtrahieren, warum invertieren und multiplizieren?
Weil Matrixtransformationen nunmal so funktionieren!? Du kannst Matritzen auch Addieren und Subtrahieren, nur wird dir das was dabei rauskommt nicht weiterhelfen. Bei normalen Zahlen fragst du ja doch auch nicht warum du a * b rechnest und nicht a + b, oder?
-
dot schrieb:
Ich versteh nicht was du da jetzt immer noch dauernd mit diesen ganzen Rotationswinkeln willst.
WeakPeak schrieb:
Warum kann ich Matritzen niche einfach regulär lassen und einfach subtrahieren, warum invertieren und multiplizieren?
Weil Matrixtransformationen nunmal so funktionieren!? Du kannst Matritzen auch Addieren und Subtrahieren, nur wird dir das was dabei rauskommt nicht weiterhelfen. Bei normalen Zahlen fragst du ja doch auch nicht warum du a * b rechnest und nicht a + b, oder?
Das was bei der Multiplikation rauskommt bringt mich aber auch nicht weiter da Turret und Waffe aus 2 verschiedenen Objekten(Mesh´s) bestehen welche jeweils nur auf einer Achse gedreht werden dürfen.
Turret = Y-Achse
Waffe = X-Achse
.. und dies um eine gekippte Achse welche durch die Drehung des parent vorgegeben ist, ich habe zwar hierhttp://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm
eine entsprechende Matrix gefunden mit der ich mich mal neher beschäftigen muss aber mit bisherugen versuchen kam ich nicht auf brauchbare Werte, zudem sind Matrizen auch etwas Rechenintensiver, ich werde mit den Darstellungen aus dem Link oben später mal weiter rum versuchen und auch noch quaternions austesten.
Aktuelles Problem bei meinen aktuellen Matrix versuchen war halt dass
- bei einbeziehung der aktuellen Rotationen sich drehende Turrets rauskamen, aktuell läuft das Projekt auf ca. 35FPS also ca. 30ms pro render-durchgeang in der Zeit werden 8 Turrets sowie 8 Waffen gedreht und ggf. 16 andere aufgrund von Collisionen oder der vorhandensein von bereits maximal zulässigen 8 Waffen 16 andere Turrets/Waffen in die Ursprungsrotation gefahren. Ich weiss nicht ob ich etwas falsch berechnet hatte, die Ursprungsrotation noch nicht wieder hergestellt war oder was sonst passiert ist, jedenfalls kann ich nur Absolute Drehungen berechnen lassen welche das mit einfliessen der aktuellen Rotation nicht mit einbezieht.
- ich mit Matritzen noch nicht wirklich sicher rechnen kann und so auch sicherlich Fehler auftreten.
- es bisher so aussieht das ich alle 3 Drehungen aus eine Matritzen Mutliplikaton übernehmen muss um verwertbare ergebnisse zu erzielen, allerdings habe ich bisher auch nur standard Matritzen verwendet, evtl würde mir die Matritze aus dem Link oben etwas einringen.
Danke für die Geduld.
-
Die Irrlicht Engine arbeitet, soweit ich das sehe, sowieso schon auf Basis eines Szenegraphen. D.h. eigentlich sollte da Kaum noch die Notwendigkeit bestehen selbst Hand an Matritzen zu legen. Dein Turret ist einfach ein Child von deinem Ship. Und deine Weapon wiederum ein Child von deinem Turret. D.h. alles was du noch machen musst ist die Absolute von deinem Turret Node zu nehmen und deine Zielposition mit der Inversen davon zu transformieren. Damit kannst du das Turret dann um die lokale Y Achse ausrichten (von mir aus über den Drehwinkel). Und dann kannst du das gleiche nochmal mit der Weapon machen für deren X Rotation. Ich kenn mich jetzt mit Irrlich nicht aus, evtl. kann man das ganze irgendwie noch besser machen, aber das wär mal mein naiver Ansatz...