Main Menu

Request: Objekte drehen

Started by firstdeathmaker, October 12, 2011, 10:34:25 AM

Previous topic - Next topic

firstdeathmaker

Hallo,

ich habe eine Frage bezüglich des Drehens von Objekten (AE):

Mit myObject3d.translate() und den rotate Befehlen kann man zwar Objekte drehen, aber immer nur relativ zur ihrer eigenen Position.

Damit ich es absolut auf eine bestimmte Drehposition setzen kann, habe ich versucht mit

setOrientation(SimpleVector dir, SimpleVector up)

zu arbeiten. Nur leider wird das Objekt seltsam verdreht: Ich lasse den dir-Vektor in eine x-y Richtung zeigen, und übergebe als "up" einen Einheitsvektor in z-Richtung.

Das Objekt zeigt zwar in die richtige Richtung, allerdings zeigt es mit der Seite nach oben. Wenn das Objekt gerade neu geladen wurde, dann ist normalerweise die Oberseite oben (Z-Richtung = Oben bei mir). Wenn ich den Up-Vektor allerdings ändere (damit die richtige Seite nach oben zeigt), dann wir das Objekt teilweise zu einer ganz platten Ebene zusammen gepresst.


Um das ganze mal in einen Kontext zu setzen: Ich möchte eine Top-Down Ansicht erhalten und meine Raumschiffe nur auf der X-Y Ebene bewegen. Daher möchte ich meine Objekte nur um die Z-Achse rotieren lassen. Allerdings würde ich gerne die Ausrichtung der Objekte absolut und nicht relativ setzen können.

EgonOlsen

Scheint mir so, als ob nicht im richtigen Koordinatensytem denkst (wenn z bei dir oben ist...): http://www.jpct.net/wiki/index.php/Coordinate_system

firstdeathmaker

Ich dachte das wäre alles relativ? Wenn ich meine Kamera auf 0,0,20 setze, mein Objekt bei 0,0,0 lade und dann die Kamera mit lookAt auf die Objektposition ausrichte, dann müsste meine Kamera von oben auf das Objekt drauf schauen, oder? Ich hab das Objekt in Wings3D modelliert und dort am Koordinatensystem ausgerichtet.

Aber ich glaub ich beginne zu ahnen das ich hier irgendwo einen Denkfehler gemacht habe, ich weis nur noch nicht genau wo... naja, ich werd heute Abend noch mal was ausprobieren, mit dem wiki-koordinatensystem.

EgonOlsen

Nein, das Koordinatensystem des Worldspaces ist fix. Alle anderen sind natürlich relativ zum Worldspace. Aber wenn du von (0,0,20) auf (0,0,0) schaust, dann guckts zu quasi von hinten auf das Objekt, nicht von oben.

firstdeathmaker

So, hab mich jetzt noch mal hingesetzt und es mit den Infos ausprobiert. Irgendwie bekomme ich das Objekt immer noch nicht sauber positioniert:

Schritt 1: Ich modelliere das Schiff in Wings3D und richte es an der X-Achse aus. Die positive Y-Achse ist oben. (siehe angehängtes .wings file)


Schritt 2: Ich lade das Schiff und positioniere die Kamera:
Quotecam = world.getCamera();
         cam.setPosition(0,-50,0);
         cam.lookAt(ship.getTransformedCenter());

Schritt 3: Ich frage die Touch-Events ab und setze die Orientierung des Raumschiffes:
(direction ist auch ein SingleVector)

QuoteSimpleVector up = new SimpleVector(0,-1f,0);   
         direction.x = (event.getX()-(w/2));
         direction.z = -(event.getY()-(h/2));
         
         ship.setOrientation(direction, up);

Ergebnis: Das Schiff zeigt auf dem Bildschirm nach unten und ist um 90 Grad nach rechts gedreht. Man sieht also nur die Seite des Schiffes, nicht die Oberseite.



Also drehe ich das Schiff in Wings um 90° um die X-Achse nach links. Nur jetzt fällt beim Antippen des Bildschirms auf: Das Schiff wird, wenn man z.B. an den unteren Bildschirmrand tippt (direction.x = 0, direction.z = -227) nicht genau nach unten ausgerichtet, sondern leicht schräg:

(die genauen Werte von direction bei diesem Screenshot sind: X: -0.27304077 Z: -255.82458)



Wieso ist das so?

Fighter.wings
BattleshipAdmiral.rar

EgonOlsen

Du mischt da Screenspace-Koordinaten vom Touchevent direkt mit den Worldspace-Koordinaten deiner 3D-Szene. Das kann nicht klappen (dafür klappt es erstaunlich gut...). Du musst die Touchkoordinaten erst in 3D-Koordinaten auf der Ebene des Raumschiffs umwandeln.
Die bekommst du so (ich gehe jetzt davon aus, dass das Schiff in der XZ-Ebene liegt und du von oben drauf schaust...):


SimpleVector clickPos=reproject2D3D(cam, buffer,eventX, eventY, shipPlaneZ);
clickPos.matMul(cam.getBack().invert3x3());

firstdeathmaker

Kann es sein, dass es den Befehl "reproject2D3D" in AE nicht gibt?

EgonOlsen

Äh, doch. Da fehlte ein Interact2D. davor...Sorry.

firstdeathmaker

okay... werd ich heute Abend mal wieder ausprobieren. Heute morgen hat er den Befehl, obwohl ich über "import" Interact2D eingebunden hatte nicht gefunden.

Aber nur so zum Verständnis, wieso funktioniert mein vorheriger Ansatz nicht? Mit

Quotedirection.x = (event.getX()-(w/2));
         direction.z = -(event.getY()-(h/2));

wobei h und w die Bildschirmhöhe und Breite in Pixeln ist, bekomme ich doch einen Vektor der vom Ursprung in die jeweilige Richtung zeigt. Wenn ich dann im World-Context ein Objekt an der Stelle 0/0 positioniere und dann in die Richtung des jeweiligen Vektors zeigen lasse, dann müsste das doch genau gehen? Ich befinde mich ja mit meiner Kamera nicht irgendwo, sondern genau über dem Objekt und bewege mich mit meinen Koordinaten nur auf einer festen Ebene.

EgonOlsen

Ich bin nicht sicher...vielleicht würde es für diesen speziellen Fall sogar klappen. Aber allgemeingültig ist nicht. Du kannst ja mal die Ergebnisse der beiden Ansätze vergleichen.

firstdeathmaker

So, nach langem hin und her hab ich es jetzt hinbekommen. Allerdings leider nicht mit den Befehlen die du vorgeschlagen hast, die haben leider nicht so funktioniert wie ich es wollte.

Der Fehler mit dem schrägen Offset wurde wohl dadurch erzeugt, dass die Kamera nicht auf den Mittelpunkt des Koordinatensystems, sondern auf:

cam.lookAt(ship.getTransformedCenter());

gerichtet war.

Jetzt habe ich das ganze so gelöst:

Bei der initialisierung setze ich die Kamera folgendermaßen:
Quotecam.setPosition(0,50,0);
         cam.setOrientation(new SimpleVector(0,-1f,0), new SimpleVector(0,0,1f));

Sie zeigt also in negative Y-Richtung auf die x, z Ebene, wobei positives z oben ist.

Bei einem Touch-Event richte ich das Schiff folgendermassen aus:

QuoteSimpleVector up = new SimpleVector(0,-1f,0);
         direction.x = (event.getY()-(h/2));
         direction.z = -(event.getX()-(w/2));
         ship.setOrientation(direction,new SimpleVector(0,1f,0));
Also auf der x-z Ebene was die Richtung angeht, und die Oberseite des Modells zur Kamera hin gerichtet.

Socke

Ich hänge mich mal an den Thread.  ;D

Wie komme ich an die aktuelle Drehung eines Objekts?

Ich kann ja mit translate eine Position bestimmen und hab dann auch ein getTranslate. Mit rotateY kann ich ein Objekt drehen aber die beiden Methoden getRotationMatrix() und getRotationPivot()  scheinen den Wert nicht zu haben den ich eine Zeile zuvor gesetzt habe.

Ich spiele gerade mit der PC Version rum. Wo ist der Trick?  :P

EgonOlsen

Es gibt keinen Trick. Mit einer Rotation um eine der Achsen veränderst du die Rotationmatrix, in der quasi die Historie der bisherigen Rotationen gespeichert ist. Mit den Winkeln direkt weiterzuarbeiten, macht keinen Sinn, weil man damit in alle möglichen lustigen Problem laufen würde (z.B. http://de.wikipedia.org/wiki/Gimbal_Lock). Aus der Matrix lassen sich aber durchaus wieder Winkel ableiten. Z.B. so: http://www.jpct.net/forum2/index.php/topic,576.0.html
Das Problem dabei ist, dass dabei aber nur ein Winkel für x,y,z rauskommt, der, wenn man alle Winkel zusammen betrachtet, die aktuelle Rotation darstellt. Das heißt aber nicht, dass das auch automatisch der Winkel ist, den du übergeben hast. Für einfache Fälle mag das noch stimmen, aber bei komplexeren Rotationen nicht mehr. Oder anders gesagt: Es gibt unendlich viele Kombinationen, wie ein Objekt in einem Rotationszustand landen kann. Die Winkel aus der Matrix sind nur eine davon.
Wenn der absolute Wert wirklich wichtig ist (z.B. bei einer Kamerasteuerung wie in einem Shooter), bietet es sich an, ihn selber im eigenen Code zu verfolgen.