# Starthilfe Teil 1: SimpleUniverse



## hoon (3. Nov 2003)

Hi Volks,

wer sich ein wenig mit Java3D beschäftigt hat, dem ist bestimmt das folgende Bildchen bekannt:







Der Einstieg in Java3D ist zu Beginn etwas mühselig. Um es dem Neuling etwas zu erleichtern, haben die Java3D-Entwickler einige Hilfsklassen zur Verfügung gestellt. Das oben dargestellte Bild zeigt einen eleganten Weg den sonst etwas aufwendig zu programmierenden Sichtzweig einfach abzukürzen. Dafür wird die Hilfsklasse *SimpleUniverse* angeboten. Ein Großteil des im Bild gestrichelten Bereiches wird hier mit sinnvollen Voreinstellungen in einer Klasse beschrieben. Um das so minimalistisch erzeugte Universum zu füllen, ist nun der Inhaltszweig (linker Bereich, ausserhalb des gestrichelten Bereiches) mit geometrischen Körpern zu bestücken. Ein geometrischer Körper ist jedoch erst sichtbar, wenn man ihn mit gewissen Aussehenseigenschaften gekoppelt hat. Um auch hier die Sache etwas abzukürzen, finden wir eine weitere Hilfsklasse in Form einer *ColorCube*. Diese ColorCube beinhaltet also Geometrie und Aussehen in einem Objekt. Mit dieser Kenntnis sind wir nun in der Lage ein einfaches Java3D-Programm zu erstellen. Das folgende Programm nutzt die oben erwähnten Hilfsklassen zuzüglich eines einfachen Maus-Verhaltens.


```
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import javax.media.j3d.*;

public class MySimpleUniverse extends Applet
{
	// Inhaltszweig
	public BranchGroup erzeugeInhalt()
	{
		// Erzeugen einer (Wurzel)Gruppe die den geamten Inhalt des Universum aufnehmen soll
		BranchGroup inhalt = new BranchGroup();
		
		// Erzeugen eines geometrischen Objektes inklusive voreingestellten Aussehens
		ColorCube farbigerWuerfel = new ColorCube(0.4);

		// Erzeugen einer Transformgruppe mit Zugriffsrechten fuer Maussteuerung
		TransformGroup tg = new TransformGroup();
		tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		
		// Gebe dem verwaisten Wuerfel drehfreudige Eltern
		tg.addChild(farbigerWuerfel);
		
		// Erzeuge ein Mausdrehobjekt in einem geplanten Bereich mit Ziel-Transformgruppe
		MouseRotate rotor = new MouseRotate();
		rotor.setSchedulingBounds(new BoundingSphere());
		rotor.setTransformGroup(tg);
		
		// Einhaengen der Transformgruppe und des Mausverhaltens in die Wurzelgruppe
		inhalt.addChild(tg);
		inhalt.addChild(rotor);

		// Optimiert den gesamten Inhaltszweig - nicht unbedingt erforderlich
		inhalt.compile();

		return inhalt; // Los, gibs mir!
	}
	
	// Sichtzweig
	public SimpleUniverse erzeugeSicht()
	{
		// Erzeugen eines minimalen virtuellen Universums mit Hilfe der SimpleUniverse-Klasse
		SimpleUniverse minimalesUniversum = null;

		// Besorgen der besten Konfiguration hinsichtlich der
		// Anzeigeumgebung (Farbtiefe, Tranzparenzwerte der Pixel, ...)
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

		// Erzeugen des aeusserst schweren Anzeigeflaeche-Objektes
		Canvas3D canvas3d = new Canvas3D(config);

		// Hinzufügen der Anzeigeflaeche zum Clientbereich des Fensters
		add(canvas3d);

		// Uebergabe des Canvas3D-Objekts als Anzeigeflaeche
		minimalesUniversum = new SimpleUniverse(canvas3d);

		// setNominalViewingTransform() stellt den Betrachter 2,41m auf die positive
		// z-Achse mit Sichtrichtung nach unten in negative z-Achse
		minimalesUniversum.getViewingPlatform().setNominalViewingTransform();

		return minimalesUniversum; // Her mit dem Mist!
	}

	// Diese Methode wird vom Browser beim Laden des Applets aufgerufen.
	public void init()
	{
		// Erzeuge neues Layout für Container
		setLayout(new BorderLayout());

		// Sei Gott und erzeuge ein minimales Universum mit Sicht auf den Inhalt
		SimpleUniverse su = erzeugeSicht();

		// Sei Gott und erzeuge den Inhalt des Universums mit Maussteuerung
		BranchGroup suInhalt = erzeugeInhalt();

		// Es werde Licht! - verbindet Universum inklusive Sicht mit Inhalt
		su.addBranchGraph(suInhalt);
	}

	// Startpunkt fuer die Laufzeitumgebung
	public static void main(String[] args)
	{
		new MainFrame(new MySimpleUniverse(), 800, 600);
	}
}
```

*Wie kann ich die Sache laufen lassen?*

- Ueberpruefe, ob Du das Java3D-SDK und die Java3D-JRE korrekt installiert hast.
- Schreibe den Code in eine Datei mit dem Namen "MySimpleUniverse.java".
- Gehe in die Eingabeaufforderung und compiliere den Code mit "javac MySimpleUniverse.java".
- Fuehre den Bytecode aus mit "java MySimpleUniverse".

*Das Ergebnis sollte aehnlich diesem Bild aussehen:*






*Versuche jetzt mit der linken Maustaste den Wuerfel zu drehen!*

So, ich hoffe die Neugier etwas geschürt zu haben und freue mich über mehr Diskussionen im Java3D-Bereich.   

hoon


PS: Nächster Beitrag: VirtualUniverse  :roll:


----------



## bygones (3. Nov 2003)

Cool - vielen DAnk - auch für den Beitrag über die Installation von Java3d unter Windows !!

Werde mir das dann mal in Ruhe anschauen....


----------



## Kerberus (24. Dez 2003)

Ist es nicht so, dass im SimpleUnivers die Canvas3D nicht inbebriffen ist? Die muss man ja selbst erzeugen und dem SimpleUniverse übergeben, so weit ich weiss.


----------



## hoon (24. Dez 2003)

Ja, Du hast schon recht. Das obige Bild ist so nicht korrekt. Jedoch wird die vereinfachende SimpleUniverse-Klasse selbst  im Sun-Tutorial so abgebildet. Ich fand es bisher auch etwas verwirrend. Leider kann ich hier Bilder nicht direkt ablegen, sonst könnte man mal eine korrigierte Grafik einfügen.

Frohe Weihnacht! 

Gruss hoon

PS: Ich wollte eigentlich noch mehr Starthilfe-Progrämmchen anbieten, jedoch war ich in letzter Zeit etwas verhindert.


----------



## Draco (7. Jan 2004)

Hallo,

ich muß mich im Rahmen einer Projektarbeit mit Java 3D beschäftigen und, da ich blutiger Java-Anfänger bin stehe ich voll auf dem Schlauch.

Ich muß in einer Umgebung mehr oder weniger komplizierte Objekte darstellen. Diese wollte ich nach Möglichkeit auf ihre Grundkörper zurückführen, um der Vektorgrafik aus dem Weg zu gehen. der 2. Grund ist, diese Objekte müssen durch Ereignisse Teilanimiert werden.

*Nun zu meinen Problemen:*

Wie kann ich Objekte wie Cube, Box, ... *frei* in dem Universum platzieren????

Wie kann ich einem Objekt eine Bewegung (horizontale rechts-links-Bewegung) aufzwingen????

Wie kann ich einen Button einfügen, wenn ich gleichzeitig die Funktion Box im Applet verwende???
Die Klassen der Beiden Objekte "beisen" sich....

Wie kann ich diese Bewegung durch einen Mouseclick auf einen Button starten????


Ich bin mir im Klaren darüber, daß dies wirklich viele Fragen sind. Vielleicht könnte ich sie nach langem, langem rätzeln auch selbst lösen, doch ich habe einfach nicht mehr die Nerven dazu... :-(


Anbei schreibe ich mal meinen Quelltext. Vielleicht sind dort ja noch Fehler enthalten, die weitere Probleme nach sich ziehen....

Ich danke euch schon mal recht herzlich im Voraus.

Draco




```
package festo.distribution;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowAdapter;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.behaviors.mouse.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class magazin extends Applet {
    
    float angle = 0.0f;
    Transform3D trans = new Transform3D();
    
   private SimpleUniverse u = null;
    
    //Inhaltszweig
    public BranchGroup createSceneGraph() {
        // Kreieren der root des branch graph (Teilbaumgraph)
        BranchGroup objRoot = new BranchGroup();
        
        BoundingSphere bounds =
	    new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        
        // Kreieren einer Transformgroup, um alle Objekte
        // in ihrer Größe der Scene anzupassen
        TransformGroup objScale = new TransformGroup();
        Transform3D t3d = new Transform3D();
        t3d.setScale(0.2);
        objScale.setTransform(t3d);
        objRoot.addChild(objScale);
        
        // Diese TranformGroup wird vom Mousmanipulator benutzt
        TransformGroup objTrans = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);    //Falls gesetzt, dann ist das Verändern der Subknoten erlaubt (Schreibzugriff).
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);     //Falls gesetzt, dann ist das Auslesen der Subknoten erlaubt (Lesezugriff).
        objTrans.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);    //Falls gesetzt, dann ist das Hinzufügen von neuen Subknoten zu diesem Group-Objekt erlaubt.
        objScale.addChild(objTrans);

        // Diese TransformGroup dient zur Animation der Box
        TransformGroup objAni = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);    //Falls gesetzt, dann ist das Verändern der Subknoten erlaubt (Schreibzugriff).
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);     //Falls gesetzt, dann ist das Auslesen der Subknoten erlaubt (Lesezugriff).
        objTrans.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);    //Falls gesetzt, dann ist das Hinzufügen von neuen Subknoten zu diesem Group-Objekt erlaubt.
        objTrans.addChild(objAni);
        
        // Kreieren des Zylinder
        PolygonAttributes attr = new PolygonAttributes();
        attr.setCullFace(PolygonAttributes.CULL_NONE);
        Appearance ap = new Appearance();
        Material mat = new Material();
        mat.setLightingEnable(true);
        ap.setMaterial(mat);
        ap.setPolygonAttributes(attr);
        
        // Anlegen der Objekte
        Cylinder CylinderObj = new Cylinder(1.0f, 3.0f, ap);
        Box BoxObj = new Box(1,1,3,ap);
        ColorCube ColorCube = new ColorCube();
        
        // Einfügen der Objekte in Graph
        objTrans.addChild(CylinderObj);
        objAni.addChild(BoxObj);
        
        // Mouse-Rotationsverhalten kreieren                .....  Wird durch das Gedrückthalten der linken Maustaste aktiviert
        MouseRotate behavior = new MouseRotate(objTrans);
        objTrans.addChild(behavior);
        behavior.setSchedulingBounds(bounds);
    
        // Mouse-Zoomverhalten kreieren                     .....  Wird durch das Gedrückthalten der mittleren Maustaste aktiviert
        MouseZoom behavior2 = new MouseZoom(objTrans);
        objTrans.addChild(behavior2);
        behavior2.setSchedulingBounds(bounds);
        
        // Mouse-Translationsverhalten kreieren             .....  Wird durch das Gedrückthalten der rechten Maustaste aktiviert
        MouseTranslate behavior3 = new MouseTranslate(objTrans);
        objTrans.addChild(behavior3);
        behavior3.setSchedulingBounds(bounds);
      
        // Lichteffekte der Scene (2 unterschiedliche Lichtfarben)
        Color3f lColor1 = new Color3f(0.5f, 0.0f, 0.5f);
        Color3f lColor2 = new Color3f(0.7f, 0.7f, 0.0f);
        Vector3f lDir1  = new Vector3f(-1.0f, -1.0f, 1.0f);
        Vector3f lDir2  = new Vector3f(0.0f, 0.0f, -1.0f);
        DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
        DirectionalLight lgt2 = new DirectionalLight(lColor2, lDir2);
        lgt1.setInfluencingBounds(bounds);
        lgt2.setInfluencingBounds(bounds);
        objScale.addChild(lgt1);
        objScale.addChild(lgt2);
        
        // Hintergrund mit Farbe definieren
        Color3f bgColor = new Color3f(0.05f, 0.05f, 0.5f);      //blau
        Background bgNode = new Background(bgColor);
        bgNode.setApplicationBounds(bounds);
        objRoot.addChild(bgNode);
        
        // Optimiert den gesamten Inhaltszweig 
        objRoot.compile();

	return objRoot;
    
    }
    
    public magazin() {

    }

    public void init() {
	setLayout(new BorderLayout());
        GraphicsConfiguration config =
           SimpleUniverse.getPreferredConfiguration();

	Canvas3D c = new Canvas3D(config);
	add("Center", c);

        //JPanel p = new JPanel();
	//p.add(rotateB);
	//add("North", p);
        
        // Kreieren einer einfachen Scene und Anbindung
        // an das virtuelle Universum
	BranchGroup scene = createSceneGraph();
	u = new SimpleUniverse(c);

        // Dies setzt die ViewPlatform ein Stück zurück,
        // um alle Objekte der Scene betrachten zu können
        u.getViewingPlatform().setNominalViewingTransform();

	u.addBranchGraph(scene);
    }

    public void destroy() {
	u.cleanup();
    }

    // Das Folgende erlaub das Prog als eine Applikation
    // bzw. ein Applet laufen zu lassen
    public static void main(String[] args) {
        //Framegröße        
	new MainFrame(new magazin(), 256, 256);
    }

}
```


----------



## Illuvatar (20. Mai 2004)

Wenn das hier nicht mehr weitergeht, schreib ich mal ein Tutorial.
Hier ist schonmal der Anfang.


----------



## Gast (21. Okt 2005)

Wenn ich das Beispiel von hoon ausprobiere, erscheint nur ein leerer Frame und in der Konsole kommt die Fehlermeldung "wglCreateContext Failed: Das Pixelformat ist ungültig."

Was mache ich da falsch?


----------



## Guest (8. Nov 2006)

hoon hat gesagt.:
			
		

> Hi Volks,
> 
> wer sich ein wenig mit Java3D beschäftigt hat, dem ist bestimmt das folgende Bildchen bekannt:
> 
> ...


----------

