Dalton has posted 1 posts at DZone. View Full User Profile

3D Model Interaction with Java 3D

01.26.2008
| 48538 views |
  • submit to reddit

This tutorial is based on a Computer Graphics assignment for which I was given the task of creating an application in which some articulated animal would walk using a hierarchical model. I had 4 days to complete this assignment, so I had to learn Java 3D quickly, but I ended up having to read fragmented documentation, mostly focused on theory I already knew, with practical examples that were either too simple or too complex.


The objective of this tutorial is to provide a guide for writing a basic Java 3D application with a 3D model loaded from disk; it's less generic than the official Java3D application tutorial and less focused on theory than other tutorials, but more straightforward for the experienced Java developer who already knows basic CG theory and just wants to know what goes where very quickly - going deeper in the APIs is up to you.

Requirements


  • JDK version 1.5 or above (the examples use Java 5 features)
  • Java 3D version 1.4 or above installed
  • Experience with JFC
  • Basic computer graphics knowledge (3D transforms, Illumination types)
  • A 3D model visualizer, like PoseRay
  • A 3D model converter like 3dWin will be useful if you find some interesting 3D model in a format not supported by any Java 3D loader

Models

You can download free 3D models on websites like TurboSquid or The 3D Archive. Free models may not have the quality you are looking for, so if you are on a serious/commercial project, you should probably consider purchasing a quality model. If you really want to model your objects you can try Blender.

Visualizing the model

I will use a cockroach I downloaded from The 3D Archive. You can choose another model if you will as long you know what you're doing. I will use PoseRay to visualize the model. PoseRay cannot open every 3D format, so if the format of your model is not supported by PoseRay, you will have to use some other program like 3dWin to convert it to a format PoseRay accepts. PoseRay is actually intended to work with Moray and Povray, but it works very well for the purpose of viewing 3D models.

1. Load the model 2. Check the model (shot #1)
3. Check the model (shot #2) 4. Check how this model is branched

These are the pieces that form the complete model. You will have to analyze how your model is branched to see if you can animate or interact with it as you plan. Every component of the model has a name - let it be the parts of your main subject or just other components from the scene. You can get these names on your program, but it's easier to check which part is which here. You can use the update function if the names aren't descriptive enough. You will need to know the name of every part if you plan to texturize or animate them independently.

In the end, all that matters is that you save your file in a format that Java loaders will recognize. Preferably, save it in the Wavefront .obj or Lightwave .lwo format because Java 3D comes with loaders for these file formats by default. Other loaders are available, but you will have to download them separately. Other Java3D loaders

Loading the model

Wavefront .obj format

            import java.io.FileReader;
import java.io.IOException;
import com.sun.j3d.loaders.Scene; // Contains the object loaded from disk.
import com.sun.j3d.loaders.objectfile.ObjectFile; // Loader of .obj models

public static Scene loadScene(String location) throws IOException {
ObjectFile loader = new ObjectFile(ObjectFile.RESIZE);
return loader.load(new FileReader(location));
}

Lightwave .lwo format

            import com.sun.j3d.loaders.lw3d.Lw3dLoader; // Loader of .lwo models

public static Scene loadScene(String location) throws IOException {
Lw3dLoader loader = new Lw3dLoader();
return loader.load(new FileReader(location));
}

Recommended reading: ObjectFile javadoc, Lw3dLoader javadoc.

Basic setup

Now that you know how to load the model let's see how it will look on your program before proceeding to further manipulation. The most important class of this example is the SimpleUniverse, which saves you from having to configure the view of your scene. A directional light is added to allow you to view your object (no light and you will see a plain black). You can view the source in html or download it .

Spooky

 

Roach as seen on the example program

Recommended reading: SimpleUniverse javadoc

Getting the scene components

We need to obtain a reference to every body part we need to manipulate (or just scene component, if you are not using a model of an animal). If you want to create a variable for every component and assign a meaningful name to each one, you will have to know what name maps to what component. The following piece of code demonstrates how to list the name of every named object from the scene:

            import javax.media.j3d.Shape3D;

void listSceneNamedObjects(Scene scene) {
Map<String, Shape3D> nameMap = scene.getNamedObjects();

for (String name : nameMap.keySet()) {
System.out.printf("Name: %s\n", name);
}
}

Have in mind that every Shape3D is already part of the BranchGroup of the scene you have loaded. If you want to create another graph with your custom hierarchy, you will have to get a reference to one specific Shape3D and then remove it from the BranchGroup:

            import javax.media.j3d.BranchGroup;

/* Obtains a reference to a specific component in the scene */
Shape3D eyes = nameMap.get("eyes");

/* The graph that still contains a reference to "eyes" */
BranchGroup root = scene.getSceneGroup();

/* Removes "eyes" from this graph */
root.removeChild(eyes);

/* Now you are free to use "eyes" in your custom graph */

Always remember you cannot add a component to more than one graph. If one component is already part of a graph and you try to add it to another, you will get a MultipleParentException. If you need the same component in more than one graph, you can clone them.

Transformations

Basic transformation steps:

  1. Add the parts you want to transform to a TransformGroup;
  2. Apply the TransformGroup.ALLOW_TRANSFORM_WRITE capability to the group if it wasn't set;
  3. Create or use some previously created instance of Transform3D;
  4. Configure this instance of Transform3D as / if necessary;
  5. Apply this Transform3D instance on the TransformGroup instance.

That implies you will have to keep references to instances of these classes in order to transform specific nodes of your graph.

The following piece of code demonstrates translation, rotation on multiple axis and non uniform scaling. It uses code created on previous sections.

            import javax.vecmath.Vector3f;
import javax.vecmath.Vector3d;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.Transform3D;


Map<String, Shape3D> nameMap = scene.getNamedObjects();

/* Get the node you want to transform */
Shape3D wing = nameMap.get("wing");

/* Add it to a TransformGroup */
TransformGroup transformGroup = new TransformGroup();
transformGroup.addChild(wing);

/* Necessary to allow this group to be transformed */
transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

/* Accumulates all transforms */
Transform3D transforms = new Transform3D();

/* Creates rotation transforms for x, y and z axis */
Transform3D rotX = new Transform3D();
Transform3D rotY = new Transform3D();
Transform3D rotZ = new Transform3D();

rotX.rotX(15D); // +15 degrees on the X axis
rotY.rotY(30D); // +30 degrees on the Y axis
rotZ.rotZ(-20D); // -20 degrees on the Z axis

/* Combines all rotation transforms */
transforms.mul(rotX, rotY);
transforms.mul(transforms, rotZ);

/* Translation: translates 2 on X, 3 on Y and -10 on Z */
Vector3f translationVector = new Vector3f(2F, 3F, -10F);
transforms.setTranslation(translationVector);

/* Non uniform scaling: scales 3x on X, 1x on Y and 2x on Z */
Vector3d scale = new Vector3d(3D, 1D, 2D);
transforms.setScale(scale);

/* Apply all transformations */
transformGroup.setTransform(transforms);

Recommended reading: Transform3D javadoc, TransformGroup javadoc

References
Published at DZone with permission of its author, Dalton Filho. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Rick Ross replied on Sat, 2008/01/26 - 2:39pm

Wow, Dalton! I am truly impressed, and you are a rock star! This is super neat, so thank you for being part of the DZone/Javalobby community!

Rick

Steven Devijver replied on Sat, 2008/01/26 - 2:44pm

I can't stop thinking "Groovy Builder" ... :-)

Andres Almiray replied on Sat, 2008/01/26 - 3:15pm in response to: Steven Devijver

hehe me too =) I hope some takes on the the task of creating one.

Bob Spuckwood replied on Sun, 2008/01/27 - 12:37pm

Uh, so where, exactly is the viewable demo?

Rick Ross replied on Sun, 2008/01/27 - 5:07pm in response to: Bob Spuckwood

[quote=jonjonz]Uh, so where, exactly is the viewable demo?[/quote]

The rhetorical value of starting with "Uh" is lost on me. Be kind to this man, please. If you'd like to see a demo, then I imagine he'd be happy to oblige if you just ask nicely. Your comment seemed to carry more an overtone of criticism than of request. Dalton worked hard and put much effort into this article, so let's give him some acknowledgement.

"This looks interesting, Dalton. Would it be possible to provide a link to a viewable demo? Thanks."

Cheers,
Rick

Dalton Filho replied on Mon, 2008/01/28 - 11:31am

jonjonz,

I have now included a binary download that includes the 3D model. Note that you must have Java3D installed for it to work. Check https://java3d.dev.java.net/binary-builds.html

 

Dalton

Trent Creekmore replied on Thu, 2009/04/02 - 7:16pm

So where is the example code?

Trent Creekmore replied on Tue, 2009/04/07 - 6:51pm

s

deepak singh replied on Wed, 2009/06/03 - 2:03am


I was  testing 3D Model Interaction with Java 3D throught this example .
 During testing following error is coming


Exception in thread "main" java.lang.UnsatisfiedLinkError: no j3dcore-ogl in java.library.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1709)
        at java.lang.Runtime.loadLibrary0(Runtime.java:823)
        at java.lang.System.loadLibrary(System.java:1030)
        at javax.media.j3d.MasterControl$6.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.media.j3d.MasterControl.loadLibraries(Unknown Source)
        at javax.media.j3d.VirtualUniverse.<clinit>(Unknown Source)
        at javax.media.j3d.Canvas3D.<clinit>(Unknown Source)

        at com.daltonfilho.tutorials.java3d.SceneControl.initCanvas(SceneControl.java:68)
        at com.daltonfilho.tutorials.java3d.SceneControl.<init>(SceneControl.java:54)
        at com.daltonfilho.tutorials.java3d.Program.main(Program.java:31)



can you  help me i am using netbean +j2re1.4.1+jdk1.6.0_10+Java3D.1.4

I will very thank full for you help

deepak

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.