ExHenge - create a stone-henge like (vaguely) mysterious temple thing : Object Model « 3D « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Collections Data Structure
8. Database SQL JDBC
9. Design Pattern
10. Development Class
11. Email
12. Event
13. File Input Output
14. Game
15. Hibernate
16. J2EE
17. J2ME
18. JDK 6
19. JSP
20. JSTL
21. Language Basics
22. Network Protocol
23. PDF RTF
24. Regular Expressions
25. Security
26. Servlets
27. Spring
28. Swing Components
29. Swing JFC
30. SWT JFace Eclipse
31. Threads
32. Tiny Application
33. Velocity
34. Web Services SOA
35. XML
Microsoft Office Word 2007 Tutorial
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java » 3D » Object ModelScreenshots 
ExHenge - create a stone-henge like (vaguely) mysterious temple thing


//
//CLASS
//ExHenge - create a stone-henge like (vaguely) mysterious temple thing
//
//DESCRIPTION
//This example illustrates the use of a few of Java 3D's lighting
//types to create atmospheric lighting to make a structure look
//like it is glowing. In particular, we build a central emissive
//dome, unaffected by any lighting. Surrounding that dome are a
//series of arches that are lit by a one or more of a point
//light in the center, directional lights at front-left and
//back-right, and two ambient lights. Each of these lights can be
//turned on and off via menu items.
//
//SEE ALSO
//Arch
//ExAmbientLight
//ExDirectionalLight
//ExPointLight
//
//AUTHOR
//David R. Nadeau / San Diego Supercomputer Center
//
//

import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.CheckboxMenuItem;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.Enumeration;
import java.util.EventListener;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Group;
import javax.media.j3d.ImageComponent;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.IndexedTriangleStripArray;
import javax.media.j3d.Light;
import javax.media.j3d.Link;
import javax.media.j3d.Material;
import javax.media.j3d.PointLight;
import javax.media.j3d.Shape3D;
import javax.media.j3d.SharedGroup;
import javax.media.j3d.Texture;
import javax.media.j3d.TextureAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnAWTEvent;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.media.j3d.WakeupOr;
import javax.vecmath.Color3f;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.PlatformGeometry;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.Viewer;
import com.sun.j3d.utils.universe.ViewingPlatform;

public class ExHenge extends Java3DFrame {
  //--------------------------------------------------------------
  //  SCENE CONTENT
  //--------------------------------------------------------------

  //
  //  Nodes (updated via menu)
  //
  private AmbientLight ambient = null;

  private AmbientLight brightAmbient = null;

  private DirectionalLight redDirectional = null;

  private DirectionalLight yellowDirectional = null;

  private PointLight orangePoint = null;

  //
  //  Build scene
  //
  public Group buildScene() {
    // Turn off the example headlight
    setHeadlightEnable(false);

    // Default to walk navigation
    setNavigationType(Walk);

    //
    // Preload the texture images
    //
    if (debug)
      System.err.println("  textures...");
    Texture groundTex = null;
    Texture spurTex = null;
    Texture domeTex = null;
    TextureLoader texLoader = null;
    ImageComponent image = null;

    texLoader = new TextureLoader("mud01.jpg"this);
    image = texLoader.getImage();
    if (image == null)
      System.err.println("Cannot load mud01.jpg texture");
    else {
      groundTex = texLoader.getTexture();
      groundTex.setBoundaryModeS(Texture.WRAP);
      groundTex.setBoundaryModeT(Texture.WRAP);
      groundTex.setMinFilter(Texture.NICEST);
      groundTex.setMagFilter(Texture.NICEST);
      groundTex.setMipMapMode(Texture.BASE_LEVEL);
      groundTex.setEnable(true);
    }

    texLoader = new TextureLoader("stonebrk2.jpg"this);
    image = texLoader.getImage();
    if (image == null)
      System.err.println("Cannot load stonebrk2.jpg texture");
    else {
      spurTex = texLoader.getTexture();
      spurTex.setBoundaryModeS(Texture.WRAP);
      spurTex.setBoundaryModeT(Texture.WRAP);
      spurTex.setMinFilter(Texture.NICEST);
      spurTex.setMagFilter(Texture.NICEST);
      spurTex.setMipMapMode(Texture.BASE_LEVEL);
      spurTex.setEnable(true);
    }

    texLoader = new TextureLoader("fire.jpg"this);
    image = texLoader.getImage();
    if (image == null)
      System.err.println("Cannot load fire.jpg texture");
    else {
      domeTex = texLoader.getTexture();
      domeTex.setBoundaryModeS(Texture.WRAP);
      domeTex.setBoundaryModeT(Texture.WRAP);
      domeTex.setMinFilter(Texture.NICEST);
      domeTex.setMagFilter(Texture.NICEST);
      domeTex.setMipMapMode(Texture.BASE_LEVEL);
      domeTex.setEnable(true);
    }

    //
    // Build some shapes we'll need
    //
    if (debug)
      System.err.println("  flying buttresses...");

    // Build three types of spurs (flying buttresses)
    Appearance spurApp = new Appearance();

    Material spurMat = new Material();
    spurMat.setAmbientColor(0.6f0.6f0.6f);
    spurMat.setDiffuseColor(1.0f1.0f1.0f);
    spurMat.setSpecularColor(0.0f0.0f0.0f);
    spurApp.setMaterial(spurMat);

    Transform3D tr = new Transform3D();
    tr.setIdentity();
    tr.setScale(new Vector3d(1.04.01.0));

    TextureAttributes spurTexAtt = new TextureAttributes();
    spurTexAtt.setTextureMode(TextureAttributes.MODULATE);
    spurTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
    spurTexAtt.setTextureTransform(tr);
    spurApp.setTextureAttributes(spurTexAtt);

    if (spurTex != null)
      spurApp.setTexture(spurTex);

    Arch spur1 = new Arch(0.0// start Phi
        1.571// end Phi
        9// nPhi
        -0.0982// start Theta
        0.0982// end Theta (11.25 degrees)
        2// nTheta
        2.5// start radius
        1.0// end radius
        0.05// start phi thickness
        0.025// end phi thickness
        spurApp)// appearance

    Arch spur2 = new Arch(0.0// start Phi
        1.571// end Phi
        9// nPhi
        -0.0982// start Theta
        0.0982// end Theta (11.25 degrees)
        2// nTheta
        1.5// start radius
        2.0// end radius
        0.05// start phi thickness
        0.025// end phi thickness
        spurApp)// appearance

    Arch spur3 = new Arch(0.0// start Phi
        1.571// end Phi
        9// nPhi
        -0.0982// start Theta
        0.0982// end Theta (11.25 degrees)
        2// nTheta
        1.5// start radius
        1.0// end radius
        0.05// start phi thickness
        0.025// end phi thickness
        spurApp)// appearance

    Arch spur4 = new Arch(0.0// start Phi
        1.178// end Phi
        9// nPhi
        -0.0982// start Theta
        0.0982// end Theta (11.25 degrees)
        2// nTheta
        4.0// start radius
        4.0// end radius
        0.05// start phi thickness
        0.025// end phi thickness
        spurApp)// appearance

    // Put each spur into a shared group so we can instance
    // the spurs multiple times
    SharedGroup spur1Group = new SharedGroup();
    spur1Group.addChild(spur1);
    spur1Group.compile();

    SharedGroup spur2Group = new SharedGroup();
    spur2Group.addChild(spur2);
    spur2Group.compile();

    SharedGroup spur3Group = new SharedGroup();
    spur3Group.addChild(spur3);
    spur3Group.compile();

    SharedGroup spur4Group = new SharedGroup();
    spur4Group.addChild(spur4);
    spur4Group.compile();

    // Build a central dome
    if (debug)
      System.err.println("  central dome...");

    Appearance domeApp = new Appearance();
    // No material needed - we want the dome to glow,
    // so use a REPLACE mode texture only
    TextureAttributes domeTexAtt = new TextureAttributes();
    domeTexAtt.setTextureMode(TextureAttributes.REPLACE);
    domeTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
    domeApp.setTextureAttributes(domeTexAtt);

    if (domeTex != null)
      domeApp.setTexture(domeTex);

    Arch dome = new Arch(0.0// start Phi
        1.571// end Phi
        5// nPhi
        0.0// start Theta
        2.0 * Math.PI, // end Theta (360 degrees)
        17// nTheta
        1.0// start radius
        1.0// end radius
        0.0// start phi thickness
        0.0// end phi thickness
        domeApp)// appearance

    // Build the ground. Use a trick to get better lighting
    // effects by using an elevation grid. The idea is this:
    // for interactive graphics systems, such as those
    // controlled by Java3D, lighting effects are computed only
    // at triangle vertexes. Imagine a big rectangular ground
    // underneath a PointLight (added below). If the
    // PointLight is above the center of the square, in the real
    // world we'd expect a bright spot below it, fading to
    // darkness at the edges of the square. Not so in
    // interactive graphics. Since lighting is only computed
    // at vertexes, and the square's vertexes are each
    // equidistant from a centered PointLight, all four square
    // coordinates get the same brightness. That brightness
    // is interpolated across the square, giving a *constant*
    // brightness for the entire square! There is no bright
    // spot under the PointLight. So, here's the trick: use
    // more triangles. Pretty simple. Split the ground under
    // the PointLight into a grid of smaller squares. Each
    // smaller square is shaded using light brightness computed
    // at the square's vertexes. Squares directly under the
    // PointLight get brighter lighting at their vertexes, and
    // thus they are bright. This gives the desired bright
    // spot under the PointLight. The more squares we use
    // (a denser grid), the more accurate the bright spot and
    // the smoother the lighting gradation from bright directly
    // under the PointLight, to dark at the distant edges. Of
    // course, with more squares, we also get more polygons to
    // draw and a performance slow-down. So there is a
    // tradeoff between lighting quality and drawing speed.
    // For this example, we'll use a coarse mesh of triangles
    // created using an ElevationGrid shape.
    if (debug)
      System.err.println("  ground...");

    Appearance groundApp = new Appearance();

    Material groundMat = new Material();
    groundMat.setAmbientColor(0.3f0.3f0.3f);
    groundMat.setDiffuseColor(0.7f0.7f0.7f);
    groundMat.setSpecularColor(0.0f0.0f0.0f);
    groundApp.setMaterial(groundMat);

    tr = new Transform3D();
    tr.setScale(new Vector3d(8.08.01.0));

    TextureAttributes groundTexAtt = new TextureAttributes();
    groundTexAtt.setTextureMode(TextureAttributes.MODULATE);
    groundTexAtt.setPerspectiveCorrectionMode(TextureAttributes.NICEST);
    groundTexAtt.setTextureTransform(tr);
    groundApp.setTextureAttributes(groundTexAtt);

    if (groundTex != null)
      groundApp.setTexture(groundTex);

    ElevationGrid ground = new ElevationGrid(11// X dimension
        11// Z dimension
        2.0f// X spacing
        2.0f// Z spacing
        // Automatically use zero heights
        groundApp)// Appearance

    //
    // Build the scene using the shapes above. Place everything
    // withing a TransformGroup.
    //
    // Build the scene root
    TransformGroup scene = new TransformGroup();
    tr = new Transform3D();
    tr.setTranslation(new Vector3f(0.0f, -1.6f0.0f));
    scene.setTransform(tr);

    // Create influencing bounds
    BoundingSphere worldBounds = new BoundingSphere(new Point3d(0.00.0,
        0.0)// Center
        1000.0)// Extent

    // General Ambient light
    ambient = new AmbientLight();
    ambient.setEnable(ambientOnOff);
    ambient.setColor(new Color3f(0.3f0.3f0.3f));
    ambient.setCapability(AmbientLight.ALLOW_STATE_WRITE);
    ambient.setInfluencingBounds(worldBounds);
    scene.addChild(ambient);

    // Bright Ambient light
    brightAmbient = new AmbientLight();
    brightAmbient.setEnable(brightAmbientOnOff);
    brightAmbient.setColor(new Color3f(1.0f1.0f1.0f));
    brightAmbient.setCapability(AmbientLight.ALLOW_STATE_WRITE);
    brightAmbient.setInfluencingBounds(worldBounds);
    scene.addChild(brightAmbient);

    // Red directional light
    redDirectional = new DirectionalLight();
    redDirectional.setEnable(redDirectionalOnOff);
    redDirectional.setColor(new Color3f(1.0f0.0f0.0f));
    redDirectional.setDirection(new Vector3f(1.0f, -0.5f, -0.5f));
    redDirectional.setCapability(AmbientLight.ALLOW_STATE_WRITE);
    redDirectional.setInfluencingBounds(worldBounds);
    scene.addChild(redDirectional);

    // Yellow directional light
    yellowDirectional = new DirectionalLight();
    yellowDirectional.setEnable(yellowDirectionalOnOff);
    yellowDirectional.setColor(new Color3f(1.0f0.8f0.0f));
    yellowDirectional.setDirection(new Vector3f(-1.0f0.5f1.0f));
    yellowDirectional.setCapability(AmbientLight.ALLOW_STATE_WRITE);
    yellowDirectional.setInfluencingBounds(worldBounds);
    scene.addChild(yellowDirectional);

    // Orange point light
    orangePoint = new PointLight();
    orangePoint.setEnable(orangePointOnOff);
    orangePoint.setColor(new Color3f(1.0f0.5f0.0f));
    orangePoint.setPosition(new Point3f(0.0f0.5f0.0f));
    orangePoint.setCapability(AmbientLight.ALLOW_STATE_WRITE);
    orangePoint.setInfluencingBounds(worldBounds);
    scene.addChild(orangePoint);

    // Ground
    scene.addChild(ground);

    // Dome
    scene.addChild(dome);

    // Spur 1's
    Group g = buildRing(spur1Group);
    scene.addChild(g);

    // Spur 2's
    TransformGroup tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(0.3927);
    tg.setTransform(tr);
    g = buildRing(spur2Group);
    tg.addChild(g);
    scene.addChild(tg);

    // Spur 3's
    g = buildRing(spur3Group);
    scene.addChild(g);

    // Spur 4's
    tg = new TransformGroup();
    tg.setTransform(tr);
    g = buildRing(spur4Group);
    tg.addChild(g);
    scene.addChild(tg);

    return scene;
  }

  //
  //  Build a ring of shapes, each shape contained in a given
  //  shared group
  //
  public Group buildRing(SharedGroup sg) {
    Group g = new Group();

    g.addChild(new Link(sg))// 0 degrees

    TransformGroup tg = new TransformGroup();
    Transform3D tr = new Transform3D();
    tr.rotY(0.785)// 45 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(-0.785)// -45 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(1.571)// 90 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(-1.571)// -90 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(2.356)// 135 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(-2.356)// -135 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    tg = new TransformGroup();
    tr = new Transform3D();
    tr.rotY(Math.PI)// 180 degrees
    tg.setTransform(tr);
    tg.addChild(new Link(sg));
    g.addChild(tg);

    return g;
  }

  //--------------------------------------------------------------
  //  USER INTERFACE
  //--------------------------------------------------------------

  //
  //  Main
  //
  public static void main(String[] args) {
    ExHenge ex = new ExHenge();
    ex.initialize(args);
    ex.buildUniverse();
    ex.showFrame();
  }

  //  On/off choices
  private boolean ambientOnOff = true;

  private boolean brightAmbientOnOff = false;

  private boolean redDirectionalOnOff = false;

  private boolean yellowDirectionalOnOff = false;

  private boolean orangePointOnOff = true;

  private CheckboxMenuItem ambientOnOffMenu;

  private CheckboxMenuItem brightAmbientOnOffMenu;

  private CheckboxMenuItem redDirectionalOnOffMenu;

  private CheckboxMenuItem yellowDirectionalOnOffMenu;

  private CheckboxMenuItem orangePointOnOffMenu;

  //
  //  Initialize the GUI (application and applet)
  //
  public void initialize(String[] args) {
    // Initialize the window, menubar, etc.
    super.initialize(args);
    exampleFrame.setTitle("Java 3D ExHenge Example");

    //
    //  Add a menubar menu to change parameters
    //    Dim ambient light
    //    Bright ambient light
    //    Red directional light
    //    Yellow directional light
    //    Orange point light
    //

    Menu m = new Menu("Lights");

    ambientOnOffMenu = new CheckboxMenuItem("Dim ambient light",
        ambientOnOff);
    ambientOnOffMenu.addItemListener(this);
    m.add(ambientOnOffMenu);

    brightAmbientOnOffMenu = new CheckboxMenuItem("Bright ambient light",
        brightAmbientOnOff);
    brightAmbientOnOffMenu.addItemListener(this);
    m.add(brightAmbientOnOffMenu);

    redDirectionalOnOffMenu = new CheckboxMenuItem("Red directional light",
        redDirectionalOnOff);
    redDirectionalOnOffMenu.addItemListener(this);
    m.add(redDirectionalOnOffMenu);

    yellowDirectionalOnOffMenu = new CheckboxMenuItem(
        "Yellow directional light", yellowDirectionalOnOff);
    yellowDirectionalOnOffMenu.addItemListener(this);
    m.add(yellowDirectionalOnOffMenu);

    orangePointOnOffMenu = new CheckboxMenuItem("Orange point light",
        orangePointOnOff);
    orangePointOnOffMenu.addItemListener(this);
    m.add(orangePointOnOffMenu);

    exampleMenuBar.add(m);
  }

  //
  //  Handle checkboxes
  //
  public void itemStateChanged(ItemEvent event) {
    Object src = event.getSource();
    if (src == ambientOnOffMenu) {
      ambientOnOff = ambientOnOffMenu.getState();
      ambient.setEnable(ambientOnOff);
      return;
    }
    if (src == brightAmbientOnOffMenu) {
      brightAmbientOnOff = brightAmbientOnOffMenu.getState();
      brightAmbient.setEnable(brightAmbientOnOff);
      return;
    }
    if (src == redDirectionalOnOffMenu) {
      redDirectionalOnOff = redDirectionalOnOffMenu.getState();
      redDirectional.setEnable(redDirectionalOnOff);
      return;
    }
    if (src == yellowDirectionalOnOffMenu) {
      yellowDirectionalOnOff = yellowDirectionalOnOffMenu.getState();
      yellowDirectional.setEnable(yellowDirectionalOnOff);
      return;
    }
    if (src == orangePointOnOffMenu) {
      orangePointOnOff = orangePointOnOffMenu.getState();
      orangePoint.setEnable(orangePointOnOff);
      return;
    }

    // Handle all other checkboxes
    super.itemStateChanged(event);
  }
}

//
//CLASS
//ElevationGrid - a 3D terrain grid built from a list of heights
//
//DESCRIPTION
//This class creates a 3D terrain on a grid whose X and Z dimensions,
//and row/column spacing are parameters, along with a list of heights
//(elevations), one per grid row/column pair.
//

class ElevationGrid extends Primitive {
  // Parameters
  protected int xDimension = 0, zDimension = 0;

  protected double xSpacing = 0.0, zSpacing = 0.0;

  protected double[] heights = null;

  // 3D nodes
  private Appearance mainAppearance = null;

  private Shape3D shape = null;

  private IndexedTriangleStripArray tristrip = null;

  //
  //  Construct an elevation grid
  //
  public ElevationGrid() {
    xDimension = 2;
    zDimension = 2;
    xSpacing = 1.0;
    zSpacing = 1.0;
    mainAppearance = null;
    zeroHeights();
    rebuild();
  }

  public ElevationGrid(int xDim, int