# setRotation



## benoetigeHilfe (16. Jun 2010)

Hallo miteinander, 

1. Problem: 
ich möchte gerne ein Objekt mit 
	
	
	
	





```
setRotation(new AxisAngle4f( 1f , 0f , 0f , (float)Math.toRadians(40)));
```
 den Winkel ändern.
Das klappt soweit auch , aber ich möchte z.B wie oben auf der X-Achse den Winkel um 40° ändern und zusätzlich auf der Y-Achse den Winkel um 20° ändern.

Mit 
	
	
	
	





```
setRotation(new AxisAngle4f( 1f , 1f , 0f , (float)Math.toRadians(40)));
```
 ändern ich beide ABER beide um 40° .
Wie kann man das lösen?

2. Problem: 

Gibt es eine Methode um herauszufinden wie das Objekt ausgerichtet ist.
Für die Position des Objekt gibt es ja die möglichkeit es so zu machen: 

```
Transform3D variable3D = new Transform3D();
Vector3f vectorVariable = new Vector3f();

variable3D.get(vectorVariable);
vectorVariable.getX();
vectorVariable.getZ(); ....
```

Aber sowas wie 

```
vectorVariable.getRotationX();
```

oder so??

Mfg


----------



## benoetigeHilfe (16. Jun 2010)

Edit:
Problem 1 gelöst mit der Methode 
	
	
	
	





```
mul(Transform3D variableDreiD);
```


----------



## Marco13 (16. Jun 2010)

EDIT: Ach, es geht ja um einen vector - der hat sowieso nur 3 floats, und nichts, was mit einer Rotation zu tun hat - oder meintest du den Winkel zu den jeweiligen Achsen? Die kann man natürlich mit 
angleX = vector.angle(new Vector3f(1,0,0)); // Winkel zur X-Achse
ausrechnen...



Zu Frage 2: Nicht direkt. Bedenke, dass eine Transformation "irgendwas" beschreiben kann. Man kann da u.U. nur mit sehr viel mathematischem Gefrickel erahnen, was der Rotationsanteil sein könnte. Es gibt zwar diese Möglichkeit (transform3D.get(quat4f)) aber es wäre besser, sich den Zustand seines Objektes so zu speichern, dass man das nicht machen muss - also in deinem Fall die Rotationen z.B. als
private float rotationX = 20;
private float rotationY = 40;
oder in einem
private Vector3f rotation = new Vector3f(20,40,0);
oder so zu speichern...


----------



## benoetigeHilfe (16. Jun 2010)

Hallo Marco,

ja das mit Speichern habe ich nämlich vor.
Also einmal kann ich per Hand (Eingabe) die ausrichtung ändern was ich dann mit der Methode mul() anstelle und dann alle 3 Werte abspeicher.

Pseudocode: 

```
int rotX = 40;
int rotY = 30;
int rotZ = 12;

if( rotX != 0 )
{
    transform3d.setRotation(new AxisAngle4f( 1f , 0f , 0f , (float)Math.toRadians( rotX )));
    transform3dTmp.mul(transform3d);
}

if( rotY != 0 )
{
    transform3d.setRotation(new AxisAngle4f( 0f , 1f , 0f , (float)Math.toRadians( rotY )));
    transform3dTmp.mul(transform3d);
}

if( rotZ != 0 )
{
    transform3d.setRotation(new AxisAngle4f( 1f , 0f , 1f , (float)Math.toRadians( rotZ )));
    transform3dTmp.mul(transform3d);
}

transformgroup.setTransform(transform3dTmp);
```
Jetzt kann man aber mit der PickRotateBehavior  auch die ausrichtung ändern was auch gewollt ist, und natürlich will ich auch nur 3 Werte haben.	
Dafür muss Matrix3d verwenden werden und dann an hand der Matrix und berechnen mit asin() und Co. alle drei Werte zu erhalten, genau?
Siehe: 

```
Matrix3d matrix = new Matrix3d();
transform3d.get(matrix);

// und dann an Hand der matrix die Berechnung?
```

Oder gibt es ne Saubere bzw leichtere Art dies zu lösen ?

Mfg


----------



## Marco13 (16. Jun 2010)

Hm, aus einer PickRotateBehavior kriegt man nur die gesamte Transform, und aus der Transform (bzw. Matrix) kreigt man die Rotation nur mit dem oben erwähnten "gebastel". Zumindest kann man sicher sein, dass dort IMMER NUR eine Rotation drinsteckt, dann düfte das gar nicht sooo problematisch sein...


----------



## benoetigeHilfe (17. Jun 2010)

Ich muss zugeben das ich in meiner bisherigen kurzen Laufbahn nicht wirklich damit zu tun hatte und meine Probleme damit habe 

Ich benutze Matrix3d da ich nur den rotationswinkel habe möchte.

z.B 

```
transform3d.setRotation ( new AxisAngle4d ( 0f , 1f ,0f , (float)Math.toRadians(10)));
// X und Z = 0

Matrix3d matrix = new Matrix3d();
transfrom3d.get(matrix);

/**
* Werte:
*
*  0.9848077538938695    | 0.0       | 0.17364817266677934
*  0.0                    | 0.999... | 0.0
* -0.17364817266677934  | 0.0       | 0.984807753893869
*
*/

double wert1 = Math.asin(matrix.getElement ( 0, 2 ));
System.out.println( wert1 );
// Ergbebnis: 0.17453292012214658

double yRotation = Math.toDegress( wert1 );
System.out.println( yRotation );
// Ergebnis : 9.999...  

// Ergbnis 9.999... stimmt mit dem Wert 10 , auch wenn bissl ungenau aber kann man ja runden ;)
```

Das wars auch mit dem können für diese Berechnung.
Geb ich also zusätzlich 
	
	
	
	





```
transform3d.setRotation ( new AxisAngle4d ( 1f , 0f ,0f , (float)Math.toRadians(10)));
```
 für X
Wie bekomme ich jetzt den zweiten Wert ? also X ?

Werte wenn X und Y Rotation auf 10°



```
/**
* Werte Matrix:
*
*  0.9848077538938695    | 0.0              | 0.17364817266677934
*  0.030153687870511616 | 0.9848077538938694  | -0.17101006689174583
* -0.17101006689174583  | 0.17364817266677934 | 0.9698463121294884
*
*/

// Mein Versuch:

double wert2 =matrix.getElement( 1 , 0 )/wert1;
System.out.println(wert2);
//Ergebnis : 0.17276791019945467

double xRotation = Math.toDegrees(Math.asin(wert2));
System.out.println( xRotation );
// Ergebnis: 9.948790367101656
```

Das Ergebnis würde ja mit der 10 Stimmen aber gebe ich den dritten wert also Z-Rotation ein , stimmt es nicht mehr ?!?!?

Was mach ich falsch ? 

Mfg


----------



## Marco13 (17. Jun 2010)

Wo-ho  Ja, mit "mathematischem Gefrickel" meinte ich, dass das eben nicht so einfach ist  Insbesondere wird es schwierig (vielleicht sogar unmöglich? Da müßte man mal Andrey oder Fancy fragen, oder warten, bis mein Kaffee wirkt), das ganze wieder in Euler-Winkel umzurechnen - also in die getrennten Rotationen um X, Y und Z. Und man kann nicht erwarten, dass wenn man da irgendwas hinkriegt, man aus der Matrix dann genau die Werte wieder rausbekommt, die man reingesteckt hat. Man kriegt bestenfalls "irgendeine" Rotation, die "zufällig" dieselbe Matrix ergibt, aber vielleicht auf einem anderen Weg. Ein ganz suggestives Beispiel: Wenn man mehrere Rotationen um X, Y und Z ausführt, jeweils um genau +/- 90°, dann kommen dort häufig gleiche Matrizen raus, obwohl unterschiedliche Rotationsreihenfolgen verwendet werden.

Du könntest in Erwägung ziehen, die PickRotateBehavior selbst nachzubauen, je nachdem wie das genaue Verhalten sein soll kann das aber auch aufwändig werden (und da drin werden mit Sicherheit keine Eulerwinkel verwendet  ).

Vielleicht solltest du genauer beschrieben, was du vorhast. Ursprünglich hast du gesagt, dass du "die Aurichtung des Objektes bestimmen" willst. Willst du vielleicht doch nur die Winkel der Hauptachsen des gedrehten Objektes zu den ursprünglichen Achsen wissen?


----------



## benoetigeHilfe (17. Jun 2010)

Hmmm ...
Also ich habe vor 3 Werte in eine datei zu speichern. Die 3 ( X , Y und Z) Werte sind die Werte wie das Objekt um seine eigene Achsen gedreht wurde.
Also eine Box ist z.B default :

```
1.0 , 0.0 , 0.0
0.0 , 1.0 , 0.0
0.0 , 0.0 , 1.0
```

Also so schaut man auf die Vorderseite der Box ( angenommen view ist auf default ) .
Jetzt bewege ich das Objekt mit der Maus um die eigene X-Achse, sagen wir mal um 45° , Y-Achse um 45° und Z-Achse um 20°.

So sieht es nach und nach aus: 







Leider habe ich, wenn ich mit der Maus das Objekt bewege, nicht um wieviel Grad ich die Box bewegt habe sondern nur die Matrix.

```
0.66...  , -0.24... , 0.70...
0.71...  ,  0.49...  , -0.49...
-0.22...,  0.83...  , 0.49...
```

Und anhand dieser Matrix möchte ich gerne für X , Y und Z Rotation die Winkel haben um dann die 3 Werte in einer Datei abspeichern zu können.
Da ich , wenn ich per Eingabe die ausrichtung ändern natürlich auch die aktuelle ausrichtung schon habe.

Hoffe ich konnte mein Problem jetzt gut schildern  

Mfg

P.S danke für deine bisherige Hilfe


----------



## Guest2 (17. Jun 2010)

Moin,

imho (für eine voll qualifizierte Antwort würde ich auch erst länger drüber nachdenken wollen ) würde ich vermuten, dass unter der Annahme:

1.	Die Matrix enthält nur die Rotationskomponenten (sonnst polar decomposition)

2.	Die Matrix ist so aufgebaut wie das sonst so "üblich" ist, also z.B. wie in OpenGL glRotate

Durch wildes Ein- und Gleichsetzen, man wieder zurück auf den Rotationswinkel und den Rotationsvektor kommen müsste. Und das müsste sich dann imho auch als Kombination von Rotationen um Euler Winkel darstellen lassen.

Die Ursprungsfolge von Rotationen läst sich so aber nicht mehr wiederherstellen (die Rotationsmatrix ist ja keine Datenbank ), aber das Ergebnis sollte übereinstimmen.

Gruß,
Fancy


----------



## Marco13 (17. Jun 2010)

Ja, in deinem Beispiel wurde das Endergebnis eben erreicht durch
X: 45° 
Y: 45°
Z: 20°
Das sieht man der Matrix aber nicht mehr an. Das gleiche Ergebnis könnte (nur zur verdeutlichung) auch durch
Y: 15°
X: 65° 
Z: 3700°
(oder so) erreicht werden. Man wird also vielleicht "irgendwelche" Eulerwinkel ausrechnen können, aber nicht notwendigerweise die, die als Eingabe gedient haben. Man kann das auch theoretisch fundierter sagen: 3 Zahlen reichen nicht um eine beliebige Rotation im 3D-Raum zu beschreiben, weil es keinen Homöomorphismus vom R^3 auf den SO(3) gibt. (Klingt toll  )

Wenn es nur um's Eindeutlige Abspeichern geht, braucht man IMMER 4 Zahlen - da würde sich ein Quaternion anbieten...

EDIT: Ach, da war er ja schon 

EDIT2: _"...Durch wildes Ein- und Gleichsetzen, man wieder zurück auf den Rotationswinkel und den Rotationsvektor kommen müsste."_ Ja, kommt man, und das ist gar nicht so wild, weil die Matrix4f dafür netterweise schon eine Methode anbietet  Aber das hat dann eben nichts mit Eulerwinkeln zu tun, sondern eher mit dem oben angesprochenen Quaternion (das ja so gesehen äquivalent zu einem AxisAngle ist)


----------



## benoetigeHilfe (17. Jun 2010)

Wenn ich es richtig verstanden habe könnte nach der Eulerrechnung andere Ergebnisse herauskommen ABER die Box würde "optisch" so ausgerichtet sein wie ich es ausgerichtet hatte?
P.S die bisherigen Erfolge mit der Eulerrechnung waren nicht besonders dolle .

Das Quaternion werde ich mir morgen dann mal zusätzlich anschauen.
Habe mir das eben nur kurz angeschaut und ich denke das könnte mich ein Stück weiterbringen.
Genaure Informationen werden sicherlich morgen hier im Forum stehen. 

P.S
Die Reihenfolge wie das Objekt ausgerichtet worden ist , ist gänzlich Egal.
Hätte ich wohl noch hinzufügen sollen bei meiner Erklärung


----------



## Marco13 (17. Jun 2010)

Ja, eine schnelle Websuche nach sowas wie "compute euler angles from rotation matrix" liefert z.B. http://www.gregslabaugh.name/publications/euler.pdf , aber sicher noch mehr...


----------



## Guest2 (17. Jun 2010)

Marco13 hat gesagt.:


> EDIT2: _"...Durch wildes Ein- und Gleichsetzen, man wieder zurück auf den Rotationswinkel und den Rotationsvektor kommen müsste."_ Ja, kommt man, und das ist gar nicht so wild, weil die Matrix4f dafür netterweise schon eine Methode anbietet



Und ich hätte mich erstmal hingesetzt und hätte Gleichungen aufgestellt. 




benoetigeHilfe hat gesagt.:


> Wenn ich es richtig verstanden habe könnte nach der Eulerrechnung andere Ergebnisse herauskommen ABER die Box würde "optisch" so ausgerichtet sein wie ich es ausgerichtet hatte?



Ja, wobei sich die Frage stellt, warum Du nicht einfach die 3x3 Matrix (oder die 4x4) Matrix speicherst. Dann könntest Du die Ausrichtung nicht nur im Winkel speichern, sondern wenn Du willst auch noch die Translation und die Skalierung. Und einfacher wäre es auch.

Andererseits kann so ein bissel zusätzliches Mathe knobeln natürlich auch nicht schaden. 

Gruß,
Fancy


----------



## benoetigeHilfe (18. Jun 2010)

Ja das mit der Matrix3d abspeichern habe ich als letzte lösung angesehen aber ich möchte das Objekt mit der Maus bewegen können und per Eingabe .
Und bei der Eingabefelder sollte die aktuelle ausrichtung stehen , eben die drei zahlen  

Mfg


----------



## benoetigeHilfe (18. Jun 2010)

Meine bisherien bemühung mit Euler:


```
double beta = 0.0;
double gamma = 0.0;
double alpha = 0.0;

Matrix3d max = new Matrix3d();
transform3d.get(max);

if( max.getM00() == 0 && max.getM10() == 0 )
{
     beta = Math.PI/2;
     alpha = 0.0;
     gamma = Math.atan2(max.getM01() , max.getM11() );

}
else
{
    beta = Math.atan2( max.getM20() , Math.pow( max.getM00() , max.getM10()) );
    alpha = Math.atan2( max.getM10() , max.getM00() );
    gamma = Math.atan2( max.getM21() , max.getM22() );

}

System.out.printl( " Y-Rotation: "+Math.toDegrees( beta ) + " | X-Rotation: "+ Math.toDegrees( alpha ) +" | Z-Rotation: "+ Math.toDegrees( gamma ) );

/** Eingabe war: 
*
* XRotation: 20°
* YRotation: 45°
* ZRotation: 30°
*/

// System.out.println( Y-Rotation: -29.43.... | X-Rotation: 43.40... | Z-Rotation:  47.97... )
```

An Hand dessen hier : Hier

Naja , das Ergebnis ist eher nüchtern, mit den Ergebnis bekomme ich das Objekt nicht zur gewollten ausrichtung ?!? Sprich : Eingabeausrichtung.
Also mach ich was falsch bei der Rechnung ?!?


----------



## Marco13 (18. Jun 2010)

Wurzel, Vorzeichen... ein KSKB hilft bei sowas...

```
import javax.vecmath.*;

public class EulerTest
{
    public static void main(String args[])
    {
        Vector3d angleRad = new Vector3d(
            Math.toRadians(20),
            Math.toRadians(45),
            Math.toRadians(30));

        Matrix3d max = create(angleRad);

        System.out.println("Input:");
        printDeg(angleRad);
        
        System.out.println("Computed:");
        Vector3d computed = computeAngles(max);
        printDeg(computed);
        
        System.out.println("Input matrix:");
        System.out.println(max);
        
        Matrix3d comp = create(computed);
        System.out.println("Computed matrix");
        System.out.println(comp);
    }
    
    private static Matrix3d create(Vector3d v)
    {
        Matrix3d max = new Matrix3d();
        max.setIdentity();
        
        Matrix3d rot = new Matrix3d();
        rot.setIdentity();
        rot.rotZ(v.x);
        max.mul(rot);
        rot.rotY(v.y);
        max.mul(rot);
        rot.rotX(v.z);
        max.mul(rot);
        
        return max;
    }
    
    
    private static void printDeg(Vector3d rad)
    {
        System.out.println(Math.toDegrees(rad.x));
        System.out.println(Math.toDegrees(rad.y));
        System.out.println(Math.toDegrees(rad.z));
    }
    
    private static Vector3d computeAngles(Matrix3d max)
    {
        double beta = 0.0;
        double gamma = 0.0;
        double alpha = 0.0;
        if( max.m00 == 0 && max.m10 == 0 )
        {
             beta = Math.PI/2;
             alpha = 0.0;
             gamma = Math.atan2(max.m01 , max.m11 );
         
        }
        else
        {
            beta = Math.atan2( -max.m20 , Math.sqrt( max.m00*max.m00+max.m10*max.m10) );
            alpha = Math.atan2( max.m10 , max.m00 );
            gamma = Math.atan2( max.m21 , max.m22 );
         
        }
        return new Vector3d(alpha, beta, gamma);
    }
    
    
}
```


----------



## benoetigeHilfe (18. Jun 2010)

Hallo Marco, 

wenn java3d bei dir vorhanden bekommste ein KSKB.

Mfg


----------



## Marco13 (18. Jun 2010)

Das KSKB (ohne Java3D!) hatte ich ja jetzt gepostet, eigentlich sollte die Frage damit beantwortet sein...


----------



## benoetigeHilfe (18. Jun 2010)

Ooops ...
Das ist mir jetzt peinlich .
Habe garnicht darauf geachtet das du ein KSKB gepostet hast .
Eindeutig zu wenig Kaffee bis jetzt , danke


----------

