This Java tip loads a Lightwave3D file and displays it in an applet window.

The application is fairly basic; a more complete version of a Lightwave 3D loader might incorporate features such as settable clip plane distances and animated views (these are both possible with the current Lightwave 3D loader, they just need to be implemented in the application).

 import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.vecmath.Matrix4d;

import com.sun.j3d.loaders.Loader;
import com.sun.j3d.loaders.Scene;
import com.sun.j3d.loaders.lw3d.Lw3dLoader;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * This class loads in a Lightwave3D file and displays it in an applet window.
 * The application is fairly basic; a more complete version of a Lightwave 3D
 * loader might incorporate features such as settable clip plane distances and
 * animated views (these are both possible with the current Lightwave 3D loader,
 * they just need to be implemented in the application).
 */
public class Viewer3D extends Applet {

  private java.net.URL filename;

  private SimpleUniverse u;

  public Viewer3D(java.net.URL url) {
    filename = url;
  }

  public Viewer3D() {
  }

  public void init() {
    if (filename == null) {
      // the path to the file for an applet
      try {
        java.net.URL path = getCodeBase();
        filename = new java.net.URL(path.toString() + "./ballcone.lws");
      } catch (java.net.MalformedURLException ex) {
        System.err.println(ex.getMessage());
        ex.printStackTrace();
        System.exit(1);
      }
    }

    // Construct the Lw3d loader and load the file
    Loader lw3dLoader = new Lw3dLoader(Loader.LOAD_ALL);
    Scene loaderScene = null;
    try {
      loaderScene = lw3dLoader.load(filename);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }

    // Construct the applet canvas
    setLayout(new BorderLayout());
    GraphicsConfiguration config = SimpleUniverse
        .getPreferredConfiguration();

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

    // Create a basic universe setup and the root of our scene
    u = new SimpleUniverse(c);
    BranchGroup sceneRoot = new BranchGroup();

    // Change the back clip distance; the default is small for
    // some lw3d worlds
    View theView = u.getViewer().getView();
    theView.setBackClipDistance(50000f);

    // Now add the scene graph defined in the lw3d file
    if (loaderScene.getSceneGroup() != null) {
      // Instead of using the default view location (which may be
      // completely bogus for the particular file you're loading),
      // let's use the initial view from the file. We can get
      // this by getting the view groups from the scene (there's
      // only one for Lightwave 3D), then using the inverse of the
      // transform on that view as the transform for the entire scene.

      // First, get the view groups (shouldn't be null unless there
      // was something wrong in the load
      TransformGroup viewGroups[] = loaderScene.getViewGroups();

      // Get the Transform3D from the view and invert it
      Transform3D t = new Transform3D();
      viewGroups[0].getTransform(t);
      Matrix4d m = new Matrix4d();
      t.get(m);
      m.invert();
      t.set(m);

      // Now we've got the transform we want. Create an
      // appropriate TransformGroup and parent the scene to it.
      // Then insert the new group into the main BranchGroup.
      TransformGroup sceneTransform = new TransformGroup(t);
      sceneTransform.addChild(loaderScene.getSceneGroup());
      sceneRoot.addChild(sceneTransform);
    }

    // Make the scene graph live by inserting the root into the universe
    u.addBranchGraph(sceneRoot);
  }

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

  /**
   * The main method of the application takes one argument in the args array;
   * the filname that you want to load. Note that the file must be reachable
   * from the directory in which you're running this application.
   */
  public static void main(String args[]) {
    java.net.URL url = null;
    java.net.URL pathUrl = null;
    if (args.length > 0) {
      try {
        if ((args[0].indexOf("file:") == 0)
            || (args[0].indexOf("http") == 0)) {
          url = new java.net.URL(args[0]);
        } else if (args[0].charAt(0) != '/') {
          url = new java.net.URL("file:./" + args[0]);
        } else {
          url = new java.net.URL("file:" + args[0]);
        }
      } catch (java.net.MalformedURLException ex) {
        System.err.println(ex.getMessage());
        ex.printStackTrace();
        System.exit(1);
      }
    } else {
      // the path to the image for an application
      try {
        url = new java.net.URL("file:./ballcone.lws");
      } catch (java.net.MalformedURLException ex) {
        System.err.println(ex.getMessage());
        ex.printStackTrace();
        System.exit(1);
      }
    }
    new MainFrame(new Viewer3D(url), 500, 500);
  }
}