# Rotation aller Objekte einer 3D-Szene



## whitebrazilian (11. Mai 2011)

Hallo,

ich habe mir eine Primitive Box erstellt und möchte nun in diese Box weitere Boxen hineinsetzen. Solange ich die kleine Box an dieselbe TransformGroup hänge, welche ich im MouseRotate setze, dreht sich die kleine Box mit. Sobald ich eine weitere TransformGroup für die kleine Box erstelle, funktioniert das natürlich nicht mehr, da ich nicht zwei TransformGroups an das MouseRotate-Objekt übergeben kann.
Ich muss aber mehrere TransformGroups erstellen, weil ich den kleinen Boxen ihre Position im Universum mitgeben möchte. Oder kann ich einem 3D-Objekt unabhängig von der TransformGroup die Position mitgeben? Bisher mache ich das mit der Methode setTranslation(new Vector3f(x,y,z)).

Vielen Dank!

Grüße,
whitebrazilian


----------



## Marco13 (11. Mai 2011)

Die einfachste/üblichste Methode ist, alles, was gedreht werden soll, an eine gemeinsame "Wurzel"-Transform3D zu hängen. Ob das hier angebracht ist, hängt, soweit ich das verstanden habe, von einer entscheidenden Frage ab: Sollen die Positionen der "Inneren" Boxes in _Weltkoordinaten_ angegeben werden, oder immer relativ zur Position der "Überbox"? (Im Zweifelsfall könnte die Überbox vielleicht im Ursprung liegen, aber das müßtest du genauer spezifizieren...)


----------



## whitebrazilian (11. Mai 2011)

Danke erstmal.
Die Überbox liegt in (0,0,-25) um sie besser sehen zu können. Da die inneren Boxen die Beladung eines LKWs darstellen sollen, wäre es sicher besser die Position relativ zur "Überbox" anzugeben, da die Ladung ja immer innerhalb dieser sein sollte.
Ich versuche im Moment, da ich mich erst langsam in Java3D einarbeite, die kleinen Boxen überhaupt einmal zu platzieren. Im besten Fall sollen diese am Ende per Drag and Drop in der großen Box platziert werden.


----------



## Marco13 (11. Mai 2011)

Drag & Drop kann belieibg aufwändig werden. Aber schon zur allgemeinen Frage der Platzierung müßte man genauer wissen, was da am Ende gehen soll. Es soll also "alles" gedreht werden können, und die kleinen Boxen relativ zur großen positioniert sein - aber wo kommt dann eine zweite TransformGroup für die Rotation ins spiel?


----------



## whitebrazilian (11. Mai 2011)

Also mal das eigentliche Problem:

Die Große Box soll die Ladefläche eines LKW darstellen. Diese soll vom Disponenten gedreht werden können um sich einen Überblick zu verschaffen. Dazu müssen sich auch die kleinen Boxen mitdrehen, weil es ja sonst keinen Sinn macht. Ich stelle mir eine Betrachtungsansicht vor, in der der Benutzer den LKW drehen kann und eine Editieransicht, in der er die kleinen Boxen wie folgt platzieren/verschieben kann:

Die kleinen Boxen sollen über Daten aus der Datenbank erstellt werden (dann zunächst irgendwo dargestellt werden: in einem extra Frame oder im selben Frame auf der Seite). Diese sollen dann vom Benutzer in der großen Box platziert werden. Entweder per Drag and Drop oder so, dass dem Benutzer in der Box ein Feld angezeigt wird, in welches nach anklicken die kleine Box gesetzt wird. Die Boxen sollen auch aufeinander gestapelt werden können.

Es soll also in der Betrachtungsansicht alles gedreht werden können und die kleinen Boxen relativ zur großen positioniert sein, richtig. Ob ich dazu eine zweite oder mehrere TransformGroups benötige, weiß ich nicht. In einem Beispielprogramm zur Positionierung von Objekten wurde für jedes Objekt eine extra TransFormGroup angelegt. Deswegen dachte ich, dass dies so üblich wäre.


----------



## Marco13 (11. Mai 2011)

Ja, darauf läuft es raus (auf die Frage, wie man seinen Szenegraph aufbaut). Bisher klingt das noch ziemlich "einfach":

```
Root
    TransformGroup (für Rotation der gesamten Szene)
        LKW-Box
        TransformGroup 0 (für Positionierung der Ladung 0)
        TransformGroup 1 (für Positionierung der Ladung 1)
        TransformGroup 2 (für Positionierung der Ladung 2)
        ...
```

Wie gesagt: Die Interaktion (Interaktives verschieben und Drag & Drop) kann dann nochmal ziemlich aufwändig werden. Eigentlich stellt sich die Frage danach erst später, aber man sollte jetzt schon im Hinterkopf behalten, dass die "TransformGroup 0 bis N" ja ggf. noch änderbar sein müssen, und man wissen muss, welche Ladung mit dieser TG transformiert wird. 

Vermutlich wäre es gut, wenn man da (GROB im Sinne von MVC...) auch trennen würde zwischen der Ladung an sich und der LadungsDarstellung (eben die Box mit ihrer Position). Eventuell (!!!) könnte man auch die Box und die TransformGroup sinnvoll zu einer Klasse zusammenfassen, im Sinne von

```
class LadungsDarstellung
{
    private Box box;
    private TransformGroup transformGroup;
...
    public void setPosition(Tuple3f pos) { transformGroup.setTranslation(...); }

    Node getNode() { return transformGroup; }
...
}
```
und die könnte dann (quasi über einen Listener) mit der Ladung verbunden sein, aber das sind alles Sachen, die du entscheiden mußt...


----------



## whitebrazilian (11. Mai 2011)

Danke für deine Antwort. Ich habe jetzt einfach nur mal versucht alle Transform3D-Objekte an ein Wurzel Transform3D-Objekt zu hängen. Wie gesagt ich bin in Java3D noch Anfänger.


```
BranchGroup rootBranchGroup = new BranchGroup();
TransformGroup BoxTG = new TransformGroup();
Transform3D rootTransform = new Transform3D();
...
BoxTG.addChild(new Box(2.44f,2.35f,7.7f,Sphere.GENERATE_NORMALS,BoxAppearance));
...
for (int i = 0; i<=3; i++){

TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
	      
Appearance appearance = new Appearance();
appearance.setMaterial(newMaterial(newColor3f(1f,0f,0f),newColor3f(1f,0f,0f),newColor3f(1f,0f,0f),newColor3f(0.8f,0.8f,0.8f),1f));
appearance.setPolygonAttributes(newPolygonAttributes(PolygonAttributes.POLYGON_FILL,PolygonAttributes.CULL_NONE,0));
				    	
Box box = new Box(1.2f, 1f, 0.8f,Sphere.GENERATE_NORMALS,appearance);
Vector3f vector = new Vector3f(i, i, -25+i);
transform.setTranslation(vector);
					      
rootTransform.add(transform);
					    
tg.setTransform(transform);
tg.addChild(box);
BoxTG.addChild(tg);
					
}
		

BoxTG.setTransform(rootTransform);
...
MouseRotate mouseRotate = new MouseRotate();
mouseRotate.setTransformGroup(BoxTG);
...
rootBranchGroup.addChild(BoxTG);
...
```

Ich bekomme diese Fehlermeldung:

Exception in thread "Thread-3" javax.media.j3d.BadTransformException: TransformGroup: non-affine transform
	at javax.media.j3d.TransformGroup.setTransform(TransformGroup.java:118)
	at BoxExample.createSceneGraph(BoxExample.java:133)
	at BoxExample.init(BoxExample.java:183)
	at com.sun.j3d.utils.applet.MainFrame.run(MainFrame.java:267)
	at java.lang.Thread.run(Unknown Source)


----------



## Marco13 (11. Mai 2011)

Hm. Was soll denn mit 
rootTransform.add(transform);
genau erreicht werden? (Ich nehme an, die Zeile 133 ist die
BoxTG.setTransform(rootTransform);
oder?)

Transform3Ds addieren macht nur selten Sinn. Meistens multipliziert man die eher, wenn man eine "Hintereinanderausführung" erreichen will (und man nicht beide Getrennt verändern muss - z.B. macht es oft Sinn, zwei Transforms oder TransformGroups zu speichern, getrennt für Drehung und Verschiebung oder so...)


----------



## whitebrazilian (11. Mai 2011)

Also das Rotieren aller Boxen zusammen funktioniert genauso wie du sagtest, indem ich einfach die neu erstellten Boxen an die root TransformGroup hänge. Das mit dem add war ein Denkfehler von mir.
Ich kann jetz zumindest "zu Fuß" schon mal Boxen in die große Box packen. Ich habe in einem ausführlichen Tutorial irgendetwas mit Collision Prevention gelesen, ich denke das brauche ich auf jeden Fall, wenn ich das Drag and Drop realisieren möchte.

Vielen Dank auf jeden Fall!


----------

