Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Quaternionen in Euler-Winkel...


Martok - So 27.04.08 20:00
Titel: Quaternionen in Euler-Winkel...
(Bin mir nicht ganz sicher, ob das nicht eher in Sonstiges gehört...)

Hallo,

Ich hab grade ein ziemliches Problem, aber immerhin hab ich glaub ich schon mehr erreicht als viele andere, die es versucht haben.
Es geht um das Spiel GTA San Andreas. Das kennt 2 Arten von Objekten: statische(Map) und dynamische(Scripts). Hierbei werden 2 Arten benutzt, die Rotationen abzulegen: Die Map-Dateien arbeiten mit Quaternionen, die Scripts mit 3 Eulerschen Winkeln.
Mein Programm soll aus der Map den Code für dynamische Objekte generieren. Das Problem ist folgendes: GTA ist verbuggt:
Zitat:
...the functions GTA uses to rotate the objects are incorrect. IIRC z rotation is done around the world's z axis, x and y rotation are done around the object's x and y axies respecitvely.


Das heißt, das ich mit den korrekt berechneten Eulerwinkeln etwas machen muss, damit die falsch rechnende Routine entsprechend angepasste Werte bekommt. Die Frage ist, was...

Ich hab hier schon eine Bastellösung, die funktioniert aber bei genau 4 Objekten nicht... und das ist eindeutig zu viel, meine bisherige Logik ist also definitiv falsch.

Code würde ich gerne liefern, das Problem ist nur, dass der, den ich habe ja korrekt ist. Ich will ja wissen, welche Fehler ich machen muss, damit es geht :roll:

Naja, vielleicht hat ja wer ne Idee. Ich würde ja in einem GTA-Forum fragen, aber da gibts quasi keine Mathematiker ;)

mfg
Martok

EDIT: Ich hab ne Idee.

Ein paar Beispiele
1:
2:
3:
4:
5:
  {971, 1089.2000, 1243.7000, 17.7000, -180.00, 86.40, 270.00, 500.0},   // subwaygate
  {971, 1060.8000, 1243.7000, 19.2000, -179.99, 87.40, 269.99, 500.0},   // subwaygate
  {971, 1075.0000, 1243.7000, 18.4000, -179.99, 87.60, 269.99, 500.0},   // subwaygate
  {971, 1082.1000, 1243.7000, 18.1000, -179.99, 87.40, 269.99, 500.0},   // subwaygate
  {976, 1040.9000, 1324.2000, 7.4844, -120.40, 90.00, 0.00, 500.0},   // phils_compnd_gate

Die Einträge 5,6 und 7 sind die Rotationen. So in der Form funktionieren sie aus oben genanntem Grund nicht.
Meine Idee ist jetzt, äquivalente Drehungen zu finden, bei denen die x-Achse nicht benutzt wird, z.B.

Quelltext
1:
{-179.99, 87.40, 269.99}  ->  {0.00, ??, ??}                    

Das müsste ja theoretisch möglich sein. Hat jemand ne Idee, wie es gehen könnte?

Kleines Problem bleibt: der letzte funktioniert, ich nehme an weil rz nicht verwendet wird, oder aber weil ry genau 90° ist. Auf jeden Fall hat das irgendwas damit zu tun... ich weiß bloß nicht was.


Martok - Di 29.04.08 22:39

Keiner ne Idee? Ich hab zwar schon einiges versucht, aber so wirklich macht das alles keinen Sinn. Am einfachsten wird wohl wirklich die Idee aus dem Edit oben. Nur dass ich außer nem verschärften Drehwurm noch keine Idee hab...


Edit: so, ich hab mal von Hand im Ingame-Map-Editor versucht die Sache hinzudrehen, und dabei wieder was festgestellt:


Quelltext
1:
2:
3:
4:
falsch:  -179.9961,  70.0000, -90.0036
richtig:     110.0,      0.0,     90.0

richtig: -120.3999, 90.0000, 0.0000 (muss so bleiben, der stimmt!)


das irritiert mich doch. Einer falsch, der andere goldrichtig. Irgend ne Idee, woran das liegen kann?


Martok - Mi 14.05.08 23:29

Ich glaube ich hatte grade ne Erleuchtung :idea: :shock: :idea:

Und zwar scheint der Unterschied darin zu bestehen, dass er statischen Objekten eine Matrix direkt aus der Quaternion konstruiert. Dynamische Objekte werden aber einzeln gedreht, erst X, dann Y, dann Z. Hier ist also der Unterschied. (Die Translation kommt bei beiden anschließend.)

Ich suche also die X,Y,Z-Rotation, die das gleiche Ergebnis wie die Quaternions-matrix liefert. Hier müsste ich die Rotationen einzeln 'rückgängig' machen, oder? Also erst aus X,Y die Z rausrechnen, und dann aus X die verbleibenden Y.
Übrig bleiben müsste dann das was ich suche.
Oder?


Martok - Do 15.05.08 13:24

So, nachdem ich mal wieder einen Thread lang mit mir selbst geredet habe (wie bisher bei fast allen fiesen Fragen... :roll:), hatte ich grade noch eine Erleuchtung.

Mein Ansatz von gestern war schon ganz richtig. Die 2. Erleuchtung kam in Form eines Tafelwerks. Irgendwie konnte ich mich dran erinnern, dass da mal was stand. Und siehe da:


Delphi-Quelltext
1:
2:
3:
4:
 //koordinatensytem rotieren um phi=z1
  x:= x1 * cos(z1) - y1 * sin(z1);
  y:= x1 * sin(z1) + y1 * cos(z1);
  z:= z1;


Das wars.

Eigentlich ganz einfach...


uall@ogc - Do 15.05.08 15:31

Also gehts nun? Übrigens ist das kein Fehler soindern ein Feature. Es macht durchaus Sinn dies so zu lösen wie GTA es macht. :)


Martok - Do 15.05.08 15:56

user profile iconuall@ogc hat folgendes geschrieben:
Also gehts nun?

Sieht so aus. Wenigstens eine Map hab ich schon fehlerfrei konvertiert, weitere Tests folgen später, jetzt kommt erstmal der Rest zu dem Tool.

user profile iconuall@ogc hat folgendes geschrieben:
Übrigens ist das kein Fehler soindern ein Feature. Es macht durchaus Sinn dies so zu lösen wie GTA es macht. :)

Mag sein, ist aber wenig sinnbringend, es überall anders zu machen. GTA3/VC hatten es z.B. auch in der Map so wie dynamische Objekte. Übrigens hat das nachträgliche rotieren bereits bestehender Objekte noch eine andere Auffassung von Rotationswinkeln...


BenBE - Do 15.05.08 17:16

@uall: Welche denn?


uall@ogc - Fr 16.05.08 08:30

So wie ich es verstanden habe, könnte es sein, dass die Welt um den mittelpunk Rotiert wird (DIe Rotation als Neigung) und um die Person Rotiert wird (Rotation als umhersehen in der 3. Perskeptive). Hab GTA nie gespielt aber könnte mit u.U. vorstellen dass dies die Idee war. Oder so ähnlich.


Martok - Mo 26.05.08 19:05

Ich bins nochmal... Frage wieder auf, es geht nicht.

Sondern nur, wenn entweder y oder z gleich 0 sind, dann scheint sich der Fehler nicht bemerkbar zu machen. Ist nur leider nicht immer so... :roll:

Nochmal die Formeln:

Delphi-Quelltext
1:
2:
3:
  x:= x1 * cos(z1) - y1 * sin(z1);
  y:= x1 * sin(z1) + y1 * cos(z1);
  z:= z1;


Und die Ergebnisse:

Delphi-Quelltext
1:
2:
3:
/// 89.9999, -51,9998, 89,9999 Eingabe x1,y1,z1
/// 51.9999,  89.9998, 89.9999 falsch!
/// 180    ,  89.9999,217.0000    richtig (manuell ausprobiert)


Vermutlich wird erst um x, dann um global-y und dann um lokal-z gedreht. Sicher bin ich mir aber nicht...


Martok - So 15.06.08 03:03

Mathematisch ist dem nicht beizukommen :shock:
Zumindest seh ich keine Logik. Ich hab jetzt folgendes gemacht (nicht vor Schreck umfallen^^): ich behandle jeden Fall der nicht gepasst hat (alles Vielfache von 90°...) einzeln.

Delphi-Quelltext
1:
2:
SameValue(A,B,Epsilon:double): return abs(A-B) < Epsilon;
X2,Y2,Z2: v[0,1,2] vor Veränderung


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
  if SameValue(v[0],pi/2,0.0001and SameValue(v[2],pi/2,0.0001then begin
    v[0]:= pi;
    v[1]:= pi/2;
    v[2]:= Y2+3*pi/2;
  end else
  if SameValue(v[0],-pi/2,0.0001and SameValue(v[1],-pi/2,0.0001then begin
    v[0]:= pi/2;
    v[1]:= -pi/2;
    v[2]:= 0;
  end else
  if SameValue(v[0],-pi/2,0.0001and SameValue(v[2],-pi/2,0.0001then begin
    v[0]:= -pi;
    v[1]:= pi/2;
    v[2]:= pi/2 - Y2;
  end else
  if SameValue(v[1],-pi/2,0.0001and SameValue(v[2],0,0.0001then begin
    v[0]:= -X2;
    v[1]:= -pi/2;
    v[2]:= 0;
  end else
  if SameValue(v[1],0,0.0001and SameValue(v[2],pi/2,0.0001then begin
    v[0]:= 0;
    v[1]:= -X2;
    v[2]:= pi/2;
  end else begin
    m:= IdentityHmgMatrix;
    m:= MatrixMultiply(m, CreateRotationMatrixZ(sin(Z2),cos(Z2)));
    v:= VectorTransform(v,m);
  end;

Interessant ist, dass ich die Matrix-Rotation dann nicht mehr ausführen muss... Irgendwas hebt sich da auf, ich weiß bloß nicht was. Ich hab mich damit jetzt über 2 Monate beschäftigt, vielleicht bin ich auch nur betriebsblind...

Es fehlt also irgend eine Rotation... da Z öfter mal 0 wird oder glatt um 90° gedreht wird hatte ich ja einige Vermutungen, aber die waren alle falsch. Also nichts offensichtliches, vermute ich.

Wer hier die fehlende Rotation findet, kriegt... hm. Ich kann eigentlich immer noch nichts anbieten, außer einem extra großen Hinweis in der About-Box... Eventuell auch was anderes, da findet sich dann schon was ;)