# Java3D - Zylinder genau wie Vektor ausrichten



## Peter_Pils2 (28. Okt 2009)

Guten Tag,

ich habe einige Körper in meiner Szene und möchte die Geschwindigkeitsvektoren als Zylinder oder Linien anzeigen lassen.

Beispiel Geschwindigkeitsvektor: (1.5, 2.7, 0), ein fallender Körper der sich außerdem in X-Richtung bewegt.

Mein bisheriger Lösungsversuch (besser noch viele gescheiterte Lösungsversuche) haben nicht zum Ziel geführt. Mein aktueller Stand ist folgender:


```
// Geschwindigkeitsvektor
Vector3d v = new Vector3d(1.5, 2.7, 0);

TransformGroup vectors = body.getVectorGroup();
		    
// Soll den Bewegungsvektor darstellen
Cylinder cylinder1 = new Cylinder();
			
vectors.addChild(cylinder1);
```

Dieser Teil wird jedes Frame ausgeführt:


```
// -- Bewegungsvektor-Transform3D
Transform3D vecTrans = new Transform3D();
		
// Entsprechend des Geschwindigkeitsvektors drehen
setRotation(vecTrans, body.v);
		
// Auf die Position des Körpers verschieben
setTranslation(vecTrans, body.getTransform3D());
		
// Auf eine passende Größe skalieren
setScale(vecTrans, new Vector3d(0.02, body.v.length() / 20, 0.02));
		
// Vom Körper "heraus" schieben
translateOriented(vecTrans, new Vector3d(0, 2.4, 0));
		
// vecTrans übernehmen
body.getVectorGroup().setTransform(vecTrans);
```

Das Verschieben und Skalieren funktioniert alles tadellos, nur der Punkt setRotation erfüllt seine Aufgabe nicht...

setRotation sieht wie folgt aus:


```
// origTransform = vecTrans
// origTuple = body.v

Vector3d copyVector = new Vector3d(origTuple);
		
// RotationsVektor anhand der Winkelunterschiede bestimmen
Vector3d rotationVector = new Vector3d(
	copyVector.angle(new Vector3d(1, 0, 0)),
	copyVector.angle(new Vector3d(0, 1, 0)),
	copyVector.angle(new Vector3d(0, 0, 1))
);

origTransform.setEuler(targetVector);
```

Der Zylinder dreht sich zwar um den Körper herum, das allerdings sehr chaotisch und alles andere als logisch...

Erkennt jemand einen Denkfehler? Bin nämlich bereits echt am Verzweifeln...


Schonmal vielen vielen Dank,

Peter Pils


----------



## Marco13 (30. Okt 2009)

Hm... setEuler ist da glaub' ich nicht das richtige... Als Text:
Man hat die Richtung des ursprünglichen Zylinders (ist glaub' ich entlang der y-Achse, also (0,1,0) - muss man nachsehen)
Man hat die Richtung in die er zeigen soll
Man kann den Winkel zwischen beiden ausrechnen
Wenn der Winkel nicht 0 ist, kann man das cross product zwischen beiden Ausrechnen

Die Rotation, die den Zylinder entlang der gewünschten Richtung ausrichtet ist dann: Die Rotation um die Achse, die durch das Kreuzprodukt gegeben ist (um den Winkel, den die beiden Richtungen zueinander hatten)


----------



## agentone (14. Jun 2010)

Junge!!!!!
Ich....

Ich finde keine Worte. Ich sitz den ganzen Tag über einem ganz ähnlichen Problem. (Anzeigen eines Moleküls. Bindung zwischen 2 Atomen mithilfe eines Zylinders darstellen und dafür so drehen, dass er die Atome verbindet.)

Und dann find ich deine Lösung.

Und es hat PERFEKT funktioniert!


```
Transform3D translate=new Transform3D();
			
Vector3f start=new Vector3f(0,length,0);
Vector3f target=new Vector3f(dx,dy,dz);
			
Vector3f cross=new Vector3f();
cross.cross(start,target);
float angle=start.angle(target);
			
translate.setRotation(new AxisAngle4f(cross,angle));
```

DANKE!!!

5 Sterne für den Meister-Mathematiker und -Informatiker.


----------



## Marco13 (14. Jun 2010)

Schön wenn sich die Antwort nachträglich doch noch als nützlich rausgestellt hat  Einen Winkel <epsilon sollte man ggf. noch abfangen, da kommt beim CrossProduct nämlich Mist raus...


----------



## agentone (15. Jun 2010)

> <epsilon sollte man ggf. noch abfangen, da kommt beim CrossProduct nämlich Mist raus...



Vorallem, wenn Start- und Ziel-Vektor parallel sind...

(Für "epsilon" meinst du dieses Epsilon: Epsilon ? Wikipedia, oder ? "In der Mathematik dient ε zur Bezeichnung einer beliebig kleinen Zahl größer als Null." "In der Geometrie verwendet man ε oftmals für einen kleinen Winkel.")


----------



## Marco13 (15. Jun 2010)

Ja, eben genau den Fall dass der Winkel zwischen start- und zielvektor "fast 0" ist. Z.B. sowas wie

```
float angle = ...
if (angle < 1e5)
{
    System.out.println("Mach' nix, die sind schon (fast) richtig ausgerichtet");
}
else
{
    ... die Berechnung wie vorher
}
```


----------

