|
Arbeiten mit Java3D
- An kleinen Beispielen soll Schritt für Schritt die Benutzung von Java3D beschrieben werden.
- Da die Programme schnell umfangreich werden, wird zuvor erarbeitetes immer wieder in Hilfsmethoden zusammengefaßt werden.
- Es wird von darauf abgezielt, die Darstellung innerhalb eines Applets einzufügen, dies gelingt zur Zeit aber noch nicht (gelang aber bereits im Beispiel 2dlinienapplet, s. .zip-File).
- Dies setzt voraus, dass beim Client-Rechner Java3D installiert ist, da hardwarenahe Library-Teile nicht über das Internet übertragen werden.
- Die Elemente der darzustellenden Szene werden in einen Szenen-Graph eingehangen (Baumstruktur).
|
java3dbeispiele.zip - nachfolgende und weitere Beispiele.
Der Klassenpfad
- Beim Kompilieren unter KNOPPIX muß der Klassenpfad für die Java3D-Bibliotheken mit angegeben werden.
- Komilieren und Starten eines Programms sieht deshalb folgendermaßen aus (Beispiel):
|
cd Verzeichnis/in/dem/Beispiel3D.java liegt
javac -classpath /usr/share/java/vecmath.jar:/usr/share/java/j3dcore.jar:/usr/share/java/j3dcore-1.5.2+dfsg.jar:/usr/share/java/java3ds-fileloader-1.2.jar:/usr/share/java/j3dutils.jar:/usr/share/java/j3dutils-1.5.2+dfsg.jar:. -Xlint:deprecation Beispiel3D.java
java -classpath /usr/share/java/vecmath.jar:/usr/share/java/j3dcore.jar:/usr/share/java/j3dcore-1.5.2+dfsg.jar:/usr/share/java/java3ds-fileloader-1.2.jar:/usr/share/java/j3dutils.jar:/usr/share/java/j3dutils-1.5.2+dfsg.jar:. Beispiel3D
Code 0-1: Kompilieren und Starten eines Programms.
- Es ist ab Java6 auch möglich eine Wildcard (*) zu verwenden, um alle Archive in einem Verzeichnis dem Classpath hinzuzufügen:
|
cd Verzeichnis/in/dem/Beispiel3D.java liegt
javac -classpath /usr/share/java/*:. -Xlint:deprecation Beispiel3D.java
java -classpath /usr/share/java/*:. -Xlint:deprecation Beispiel3D
Code 0-2: Kompilieren und Starten eines Programms mit Wildcard.
- Legt man die jar-Pakete von Java3d in das Applet-Verzeichnis funktioniert auch:
|
cd Verzeichnis/in/dem/Beispiel3D.java liegt
javac -classpath ./*:. -Xlint:deprecation Beispiel3D.java
java -classpath ./*:. -Xlint:deprecation Beispiel3D
Code 0-3: Kompilieren und Starten eines Programms mit lokalen .jar-Files.
- Die .jar-Dateien für Java3D liegen bei Knoppix nach der Installation des Debian-Paketes unter:
- /KNOPPIX-DATA/usr/share/java
- Es sind:
- j3dcore-1.5.2+dfsg.jar
- j3dutils-1.5.2+dfsg.jar
- java3ds-fileloader-1.2.jar
- vecmath-1.5.2.jar
|
- Der Classpath kann auch vorher festgelegt werden mit:
|
export CLASSPATH=:/usr/share/java/vecmath.jar:/usr/share/java/j3dcore.jar:/usr/share/java/j3dcore-1.5.2+dfsg.jar:/usr/share/java/java3ds-fileloader-1.2.jar:/usr/share/java/j3dutils.jar:/usr/share/java/j3dutils-1.5.2+dfsg.jar:.
Code 0-4: Setzen des Classpath.
"Einfaches" Beispiel
- Um überhaupt etwas auf den Bildschirm zu zaubern, ist bei Java3D ziemlich viel Quellcode zu schreiben.
- In dem folgenden Beispiel soll eine rote Kugel in einer vertikalen Bewegung animiert werden.
- Dieses Beispiel ist zwar nicht ganz einfach, enthält aber alles, was zur Erstellung von 3D-Animationen notwendig ist.
|
- Um Szenen performanter animieren zu können, können unveränderlche Äste mit compile() kompiliert werden.
- Dies wird hier nicht genutzt.
|
- Die einzelnen Elemente der 3D-Animation werden hier durch statische Methoden in einer selbst geschriebenen Hilfsklasse erzeugt.
- holeKugel(..) beispielsweise liefert ein geometrisches Kugel-Objekt des gewünschten Radius und der gewünschten Farbe zurück.
- Die Methode erzeugt aber zugleich auch einen Transformationsknoten, an den die Kugel gehangen wird.
- Zurückgegeben wird der Transformationsknoten, in dem die Kugel dann liegt.
- Dies erlaubt es, Größe, Position und Drehung der Kugel später in der Animation zu transformiern.
|
- Für die Verschiebung und Drehung geometrischer Komponenten existiert die Methode holeTransformation(..) in J3D.
- Diese Methode liefert ein Transformationsobjekt, in dem die Information über die Art der Transformation enthalten ist.
- Insbesondere können Verschiebung, Drehung und auch Skalierung darin über eine 4x4-Matrix beschrieben werden.
- Die obere linke 3x3 Untermatrix darin entspricht der Rotation.
- In dem Beispiel hier wurden vorher von Hand drei Drehmatrizen (um die x-, y- und z-Achse) miteinander multipliziert und das Ergebnis hier hinein gelegt.
- Dass alle Drehungen möglich sind ist günstig, um alle Wege bei der Animation offen zu lassen, aber führt natürlich zu Einbußen in der Performance.
|
- Kameraposition, Beleuchtung usw. werden hier in elementarer Weise festgelegt und nicht weiter behandelt.
- Unter Verwendung der Hilfsklasse J3D kann das Testbeispiel recht einfach gestaltet werden:
|
import com.sun.j3d.utils.universe.SimpleUniverse;
import java.applet.Applet;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.TransformGroup;
import com.sun.j3d.utils.applet.MainFrame;
import vis3d.J3D;
import java.awt.Frame;
import java.awt.BorderLayout;
public class Java3D1 extends Applet implements Runnable
{
double phi = 0.0;
public SimpleUniverse universum;
public BranchGroup welt; //Wurzel der Baumstruktur, in der die Szene zusammengestellt wird.
public TransformGroup kugel;
public Java3D1()
{
setLayout(new BorderLayout());
this.universum = J3D.holeUniversum();
welt = J3D.holeWelt();
kugel = J3D.holeKugel(0.1,255,0,0);
welt.addChild(kugel);
kugel.setTransform(J3D.holeTransformation(0.0,0.5,0.0,0.0,0.0,0.0));
universum.addBranchGraph(welt);
add(this.universum.getCanvas()); //Zeichenfläche auf Applet setzen.
}
public void start()
{
Thread thread = new Thread(this);
thread.start();
}
public void run()
{
while(true)
{
try
{
Thread.sleep(40);
}
catch(Exception e)
{
}
kugel.setTransform(J3D.holeTransformation(0.0,-0.1+0.3*(1.0+Math.sin(phi)),0.0,0.0,0.0,0.0));
phi+=0.02;
}
}
public static void main(String[] args)
{
Java3D1 applet = new Java3D1();
applet.init();
applet.start();
MainFrame mainframe = new MainFrame(applet,600,600);
mainframe.dispose();
mainframe.setUndecorated(true);
mainframe.setVisible(true);
mainframe.setExtendedState(Frame.MAXIMIZED_BOTH);
mainframe.setAlwaysOnTop(true);
}
}
Code 0-5: Klasse Java3D1.java: Vertikale Animation einer roten Kugel.
- Es folgt die Klasse J3D mit den Hilfsmethoden:
|
package vis3d;
import com.sun.j3d.utils.universe.SimpleUniverse;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import java.awt.GraphicsConfiguration;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.SpotLight;
import javax.media.j3d.PointLight;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.media.j3d.TransformGroup;
import com.sun.j3d.utils.geometry.Sphere;
import javax.media.j3d.Material;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.Appearance;
import javax.vecmath.Matrix4d;
import javax.media.j3d.Transform3D;
/**
Klasse mit statischen Methoden, mit denen sich die Benutzung von Java3D
übersichtlicher gestalten lassen soll.
*/
public class J3D
{
/**Liefert die Welt, in der ein Szenenbaum eingefügt werden kann
*/
public static SimpleUniverse holeUniversum()
{
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
SimpleUniverse universum = new SimpleUniverse(c);
universum.getViewingPlatform().setNominalViewingTransform();
return universum;
}
public static BranchGroup holeWelt()
{
BranchGroup welt = new BranchGroup();
//Umgebungslicht
AmbientLight licht = new AmbientLight(new Color3f(0.3f,0.3f,0.3f));
licht.setInfluencingBounds(
new BoundingSphere(
new Point3d(0.0,0.0,0.0), 100.0
)
);
//spot( farbe, Quellpos, Richtung)
PointLight spot = new PointLight(
new Color3f(1.0f,1.0f,1.0f),
new Point3f(-3.0f,10.0f,3.0f),
new Point3f(0.3f,-1.0f,-0.3f)
);
spot.setInfluencingBounds(
new BoundingSphere(
new Point3d(0.0,0.0,0.0), 100.0
)
);
welt.addChild(licht);
welt.addChild(spot);
return welt;
}
/**
Es wird ein Transformationsknoten zurückgeliefert, an dem die Kugel hängt.
*/
public static TransformGroup holeKugel(double radius, int rot, int gruen, int blau)
{
//Material(Color3f ambientColor, Color3f emissiveColor, Color3f diffuseColor, float shininess)
float r = (float)rot/256.0f;
float g = (float)gruen/256.0f;
float b = (float)blau/256.0f;
Color3f farbe_a = new Color3f(r,g,b);
Color3f farbe_e = new Color3f(0.0f,0.0f,0.0f);
Color3f farbe_d = new Color3f(r*0.5f,g*0.5f,b*0.5f);
Color3f farbe_x = new Color3f(1.0f,1.0f,1.0f);
Appearance erscheinung = new Appearance();
Material mat = new Material(farbe_a,farbe_e,farbe_d,farbe_x,100.0f);
mat.setLightingEnable(true);
erscheinung.setMaterial(mat);
erscheinung.setColoringAttributes(
new ColoringAttributes(farbe_d,ColoringAttributes.SHADE_GOURAUD)
);
Sphere kugel = new Sphere( (float)radius,Sphere.GENERATE_NORMALS, 80, erscheinung );
TransformGroup tg = new TransformGroup();
tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
tg.addChild(kugel);
return tg;
}
public static Transform3D holeTransformation(double x, double y, double z,
double a, double b, double c)
{
return
new Transform3D
(
new Matrix4d //zeilenweise
(
Math.cos(b)*Math.cos(c),
-Math.cos(a)*Math.sin(c) + Math.sin(a)*Math.sin(b)*Math.cos(c),
Math.sin(a)*Math.sin(c) + Math.cos(a)*Math.sin(b)*Math.cos(c),
x,
Math.cos(b)*Math.sin(c),
Math.cos(a)*Math.cos(c) + Math.sin(a)*Math.sin(b)*Math.sin(c),
-Math.sin(a)*Math.cos(c) + Math.cos(a)*Math.sin(b)*Math.sin(c),
y,
-Math.sin(b),
Math.sin(a)*Math.sin(b),
Math.cos(a)*Math.cos(b),
z,
0.0,
0.0,
0.0,
1.0
)
);
}
}
Code 0-6: Klasse J3D.java - Hilfsmethoden zur Erleichteurng der Verwendung von Java3D.
- Neben diesem, sind in obigem .zip-File noch weitere Beispiele zum Testen enthalten.
|
|