Beispielprogramm Universe


... [ Seminar XML und JAVA ] ... [ Thema Java 3D API ] ... [ Group Node Objects ] ...

Übersicht: Beispielprogramm Universe


Universe als Fallstudie

Das Beispielprogramm Universe simuliert die Bewegung der Erde und des Mondes um die Sonne. Diese Simulation ist deshalb so gut geeignet, da hier das reale Universum, in dem sich Erde und Mond bewegen, stellvertretend für das virtuelle Universum in Java 3D steht. Außerdem spielen sich im realen Universum reichlich Vorgänge ab, die man durch Java 3D simulieren kann. So kann man gut die Verwendung von Interpolatoren, Transformationen, Geometrien, Lichtwirkungen, usw. demonstrieren, da wir gerade diesen Phänomenen in der physikalischen Realität begegnen. Dieses Dokument basiert auf dem Beispielprogramm und viele Codeauszüge sind darin enthalten, um das Themengebiet zu verdeutlichen. Man kann das Beispielprogramm als Fallstudie betrachten. Alle Klassen der Java 3D API werden nicht behandelt, die Fallstudie enthält aber einige wichtige Beispiele. Die Komplexität der API wäre zu groß, um zu jeder Klasse ein Beispiel anzuführen. Daher dient die Fallstudie in erster Linie der Bewältigung der Komplexität. Trotzdem existiert zu jedem Objekt des Szenengraphen ein Beispiel, sodass die wichtigsten Gebiete des Stoffes abgedeckt werden. Beispiele finden sich zu den Themengebieten: Leaf Node Objects, Group Node Objects und NodeComponent Objects. Alle Kapitel zusammen erklären den Aufbau eines einfachen Szenengraphen, die Fallstudie bietet daher einen idealen Einstieg in die 3D-Programmierung mit Java. Der Inhalt des Dokuments basiert in erster Linie auf dem Java-Tutorial der Firma Sun Microsystems. Im Literaturverzeichnis gibt es Hyperlinks zu entsprechenden Webseiten. Wie beim Java-Tutorial liegt auch hier der Schwerpunkt auf der Gestaltung des Inhalts (Content). Interessierte Leser können sich an dieser Stelle den Quelltext des Beispielprogrammes downloaden.


Szenengraph

Nachfolgend ist der Szenengraph des Beispielprogramms dargestellt. Da aus Platzgründen nicht alle Objekte in einer Abbildung enthalten sein können, teilt sich der Szenengraph in zwei Abbildungen:

Abb.1: Universe Group Node und Leaf Node Objects


Abb.2: Universe NodeComponent Objects


Quelltext

Der folgende Quelltext ist lediglich inline-dokumentiert. Auf eine ausführliche Dokumentation wird verzichtet, da diese durch die Behandlung der Themengebiete: Group Node Objects, Leaf Node Objects und NodeComponent Objects erfolgt. Der Quelltext wird dort auszugsweise im Kontext des dazugehörigen Themas erläutert. Interessierte Leser können sich an dieser Stelle den Quelltext des Beispielprogrammes downloaden.
  1. // Klasse Universe
  2. //
  3. // (c)2000 Stefan Theess, FH Wedel
  4. import javax.media.j3d.*;
  5. import javax.vecmath.*;
  6. import com.sun.j3d.utils.geometry.*;
  7. import com.sun.j3d.utils.universe.*;
  8. import com.sun.j3d.utils.image.TextureLoader;
  9. import com.sun.j3d.utils.behaviors.mouse.*;
  10. import com.sun.j3d.utils.applet.MainFrame;
  11. import java.applet.Applet;
  12. import java.awt.*;
  13. // Universe simuliert die Bewegung der Erde und des Mondes um die Sonne
  14. public class Universe extends Applet {
  15. private static final Color3f BLACK = new Color3f(0f, 0f, 0f);
  16. private static final Color3f WHITE = new Color3f(1f, 1f, 1f);
  17. private static final String TEXTURE_FNAME = "earth.jpg";
  18. private static final float EARTHRADIUS = 0.1f;
  19. private static final float SUNRADIUS = 0.05f;
  20. private static final float MOONRADIUS = 0.033f;
  21. private static final float MOONORBIT = 0.3f; /* Radius Mondumlaufb */
  22. private static final float EARTHORBIT = 0.7f; /* Radius Erdumlaufb */
  23. private static final float ECLIPTIC = -0.4f; /* Ekliptikwinkel */
  24. private static final float EARTHAXIS = 0.25f; /* Laenge Erdachse */
  25. private static final long MONTH = 3000; /* Zeit Mond um Erde */
  26. private static final long DAY = 100; /* Zeit Erde um sich selbst */
  27. private static final long YEAR = 36500; /* Zeit Erde um Sonne */
  28. private static final int CIRCLECOORDS = 32; /* Anzahl Kreiskoordn */
  29. public Universe() {
  30. setLayout(new BorderLayout());
  31. GraphicsConfiguration config =
  32. SimpleUniverse.getPreferredConfiguration();
  33. Canvas3D canvas3D = new Canvas3D(config);
  34. add("Center", canvas3D);
  35. // SimpleUniverse vereinfacht das Erstellen des Universums
  36. SimpleUniverse simpleUni = new SimpleUniverse(canvas3D);
  37. BranchGroup sceneGraph = createSceneGraph();
  38. // ViewPlatform wird so eingestellt,
  39. // dass man die Objekte betrachten kann
  40. simpleUni.getViewingPlatform().setNominalViewingTransform();
  41. simpleUni.addBranchGraph(sceneGraph);
  42. } // Ende Konstruktor Universe
  43. // liefert die Koordinaten eines Kreises mit dem Radius r und N Paaren
  44. private Point3f[] createCircleCoords(float r, int N) {
  45. Point3f[] coords = new Point3f[N];
  46. int n;
  47. double a;
  48. float x, z;
  49. for (a = 0, n = 0; n < N; a = 2.0 * Math.PI / (N-1) * ++n) {
  50. x = (float) (r * Math.sin(a));
  51. z = (float) (r * Math.cos(a));
  52. coords[n] = new Point3f(x, 0f, z);
  53. }
  54. return coords;
  55. } // Ende Methode createCircleCoords
  56. // erzeugt die Geometrie eines Kreises mit Radius r und N Punkten
  57. private Geometry createCircleGeometry(float r, int N) {
  58. int[] stripCounts = {N};
  59. LineStripArray lsa =
  60. new LineStripArray(N, LineStripArray.COORDINATES, stripCounts);
  61. lsa.setCoordinates(0, createCircleCoords(r, N));
  62. return lsa;
  63. } // Ende Methode createCircleGeometry
  64. // erzeugt die Geometrie einer Linie der Laenge l
  65. private Geometry createLineGeometry(float l) {
  66. LineArray la = new LineArray(2, LineArray.COORDINATES);
  67. la.setCoordinate(0, new Point3f(0f, -l/2f, 0f));
  68. la.setCoordinate(1, new Point3f(0f, l/2f, 0f));
  69. return la;
  70. } // Ende Methode createLineGeometry
  71. // erzeugt den Content-Branch des Szenengraphen
  72. public BranchGroup createSceneGraph() {
  73. BranchGroup objRoot = new BranchGroup();
  74. BoundingSphere bounds = new BoundingSphere();
  75. // erzeugt die Erde
  76. Appearance earthAppear = new Appearance();
  77. earthAppear.setTexture(
  78. new TextureLoader(TEXTURE_FNAME, this).getTexture());
  79. Sphere earth = new Sphere(EARTHRADIUS,
  80. Primitive.GENERATE_TEXTURE_COORDS,
  81. earthAppear);
  82. // erzeugt die Sonne
  83. Appearance sunAppear = new Appearance();
  84. sunAppear.setMaterial(new Material(BLACK, WHITE, WHITE, WHITE, 1f));
  85. Sphere sun = new Sphere(SUNRADIUS, sunAppear);
  86. // erzeugt den Mond
  87. Appearance moonAppear = new Appearance();
  88. moonAppear.setMaterial(new Material(BLACK, BLACK, WHITE, WHITE, 1f));
  89. Sphere moon = new Sphere(MOONRADIUS, moonAppear);
  90. // erzeugt die Umlaufbahnen und die Erdachse
  91. Shape3D earthOrbit =
  92. new Shape3D(createCircleGeometry(EARTHORBIT, CIRCLECOORDS));
  93. Shape3D moonOrbit =
  94. new Shape3D(createCircleGeometry(MOONORBIT, CIRCLECOORDS));
  95. Shape3D earthAxis =
  96. new Shape3D(createLineGeometry(EARTHAXIS));
  97. // erzeugt das Sonnenlicht
  98. PointLight sunlight = new PointLight();
  99. sunlight.setInfluencingBounds(bounds);
  100. // versetzt den Mond auf seine Umlaufbahn
  101. Transform3D moonTranslate = new Transform3D();
  102. moonTranslate.set(new Vector3f(0f, 0f, MOONORBIT));
  103. TransformGroup objMoonTranslate = new TransformGroup(moonTranslate);
  104. // simuliert einen Monat (Bewegung Mond um Erde)
  105. TransformGroup objMonth = new TransformGroup();
  106. objMonth.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  107. RotationInterpolator rotIntMonth =
  108. new RotationInterpolator(new Alpha(-1, MONTH), objMonth);
  109. rotIntMonth.setSchedulingBounds(bounds);
  110. // simuliert einen Tag (Bewegung der Erde um sich selbst)
  111. TransformGroup objDay = new TransformGroup();
  112. objDay.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  113. RotationInterpolator rotIntDay =
  114. new RotationInterpolator(new Alpha(-1, DAY), objDay);
  115. rotIntDay.setSchedulingBounds(bounds);
  116. // simuliert die Ekliptik (Neigung der Erdachse)
  117. Transform3D ecliptic = new Transform3D();
  118. ecliptic.rotZ(ECLIPTIC);
  119. TransformGroup objEcliptic = new TransformGroup(ecliptic);
  120. float[] knots = new float[CIRCLECOORDS];
  121. for (int n = 0; n < CIRCLECOORDS; ++n) {
  122. knots[n] = (float)n * (1 / (float)(CIRCLECOORDS-1));
  123. }
  124. // simuliert ein Jahr (Bewegung der Erde um die Sonne)
  125. TransformGroup objYear = new TransformGroup();
  126. objYear.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  127. PositionPathInterpolator rotIntYear =
  128. new PositionPathInterpolator(
  129. new Alpha(-1, YEAR),
  130. objYear,
  131. new Transform3D(),
  132. knots,
  133. createCircleCoords(EARTHORBIT, CIRCLECOORDS)
  134. );
  135. rotIntYear.setSchedulingBounds(bounds);
  136. // Mouse Rotation Behavior zum Rotieren des Universums mit der Maus
  137. TransformGroup objRotate = new TransformGroup();
  138. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  139. objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  140. MouseRotate mouseRotate = new MouseRotate();
  141. mouseRotate.setTransformGroup(objRotate);
  142. mouseRotate.setSchedulingBounds(bounds);
  143. // setzt den Szenengraphen zusammen
  144. objRoot.addChild(objRotate);
  145. objRotate.addChild(mouseRotate);
  146. objRotate.addChild(sun);
  147. objRotate.addChild(sunlight);
  148. objRotate.addChild(objYear);
  149. objRotate.addChild(earthOrbit);
  150. objYear.addChild(rotIntYear);
  151. objYear.addChild(objEcliptic);
  152. objYear.addChild(objMonth);
  153. objEcliptic.addChild(objDay);
  154. objDay.addChild(rotIntDay);
  155. objDay.addChild(earth);
  156. objDay.addChild(earthAxis);
  157. objMonth.addChild(rotIntMonth);
  158. objMonth.addChild(objMoonTranslate);
  159. objMonth.addChild(moonOrbit);
  160. objMoonTranslate.addChild(moon);
  161. // nimmt Optimierungen am Ast des Szenengraphen vor
  162. objRoot.compile();
  163. return objRoot;
  164. } // Ende Methode createSceneGraph
  165. // um Programm sowohl als Applet wie auch als Applikation
  166. // laufen zu lassen
  167. public static void main(String[] args) {
  168. // erzeugt Applikationsfenster der Groesse 800x600
  169. new MainFrame(new Universe(), 800, 600);
  170. } // Ende Methode main
  171. } // Ende Klasse Universe


... [ Seminar XML und JAVA ] ... [ Thema Java 3D API ] ... [ Beispielprogramm Universe ] ... [ Group Node Objects ] ...