SlideShare una empresa de Scribd logo
1 de 27
The Joy of Java 3D
by Greg Hopkins
Copyright © 2001-2007

Introduction
Java 3D is an addition to Java for displaying three-dimensional graphics. Programs written in Java 3D can
be run on several different types of computer and over the internet.
The Java 3D class library provides a simpler interface than most other graphics libraries, but has enough
capabilities to produce good games and animation. Java 3D builds on existing technology such as DirectX
and OpenGL so the programs do not run as slowly as you might expect. Also, Java 3D can incorporate
objects created by 3D modeling packages like TrueSpace and VRML models.
This tutorial is an introduction to Java 3D. Examples lead you through the basic methods for producing 3D
images and animation. You do not need to have any knowledge of 3D graphics or Java 3D to learn from
this tutorial, but it will help if you have a basic understanding of the Java programming language.
Programming in three dimensions can seem complicated because of the amount of jargon and the
mathematics involved, this tutorial will keep things as simple as possible.
Please help to improve this tutorial for future readers by reporting any mistakes you find or suggesting
improvements to editor@java3d.org.

Installing and Running Java 3D
The software you need to use Java 3D is available free from Sun Microsystems at http://java.sun.com/.
Sun often releases new versions so it is better to look at their site than rely on this document to find what
you need. You will have to register as a member of "Java Developer Connection" to download some of the
files.
At time of writing, the newest version of Java (6.3) is at http://java.sun.com/javase/downloads/index.jsp.
The current version of the Java 3D extension (1.5.1) is at https://java3d.dev.java.net/#Downloads Netscape
and Internet Explorer both require you to download plug-ins if you want to use up-to-date versions of Java
and Java3D in applets, the plug-in can be found at http://java.sun.com/products/plugin/.
Once you have installed Java and Java 3D you can compile programs using the command:
javac FileName.java
And run them using:
java FileName
The FileName should always be the same as the name of the public class defined in that file. In some
versions of Java 3D you may get a message about a null graphics configuration, but you can just ignore
this.

1
Getting Started – Your First Program
The following program shows you the basic steps needed to display 3D objects.
1.
2.
3.
4.
5.

Create a virtual universe to contain your scene.
Create a data structure to contain a group of objects.
Add an object to the group
Position the viewer so that they are looking at the object
Add the group of objects to the universe

Look at the Hello3d() constructor and you will see the five lines that perform each of these steps. The
program displays a glowing cube, the viewer is looking directly at the red face of the cube, so what you
actually see is a red square on a black background
import
import
import
import

com.sun.j3d.utils.universe.SimpleUniverse;
com.sun.j3d.utils.geometry.ColorCube;
com.sun.j3d.utils.geometry.Sphere;
javax.media.j3d.BranchGroup;

public class Hello3d {
public Hello3d()
{
SimpleUniverse universe = new SimpleUniverse();
BranchGroup group = new BranchGroup();
group.addChild(new ColorCube(0.3));
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(group);
}
public static void main( String[] args ) {
new Hello3d();
}
} // end of class Hello3d
The import statements at the beginning of this program use various parts of Java 3D, so compiling and
running this program is a good test that you have installed Java 3D correctly.

2
Lighting up the World
OK, the first example was a good start, but was it 3D? If you don’t think a square
qualifies as three-dimensional, you are going to need to add some lights to your
universe. The way the light falls on an object provides us with the shading that
helps us see shapes in three dimensions
The next example illustrates how to display a ball lit by a red light:

import
import
import
import

com.sun.j3d.utils.geometry.*;
com.sun.j3d.utils.universe.*;
javax.media.j3d.*;
javax.vecmath.*;

public class Ball {
public Ball() {
// Create the universe
SimpleUniverse universe = new SimpleUniverse();
// Create a structure to contain objects
BranchGroup group = new BranchGroup();
// Create a ball and add it to the group of objects
Sphere sphere = new Sphere(0.5f);
group.addChild(sphere);
// Create a red light that shines for 100m from the origin
Color3f light1Color = new Color3f(1.8f, 0.1f, 0.1f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
// look towards the ball
universe.getViewingPlatform().setNominalViewingTransform();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
public static void main(String[] args) { new Ball(); }
}
The sphere we created is white (the default), it appears red because of the colored light. Since it is a
DirectionalLight, we also have to specify how far the light shines and in what direction. In the example, the
light shines for 100 meters from the origin and the direction is to the right, down and into the screen (this is
defined by the vector: 4.0 right, -7.0 down, and -12.0 into the screen).
You can also create an AmbientLight which will produce a directionless light, or a SpotLight if you want to
focus on a particular part of your scene. A combination of a strong directional light and a weaker ambient
light gives a natural-looking appearance to your scene. Java 3D lights do not produce shadows.

3
Positioning the Objects
So far, the examples have created objects in the same place, the center
of the universe. In Java 3D, locations are described by using x, y, z
coordinates. Increasing coordinates go along the x-axis to the right,
along the y-axis upwards, and along the z-axis out of the screen. In the
picture, x, y and z are represented by spheres, cones and cylinders.
This is called a “right-handed” coordinate system because the thumb
and first two fingers of your right hand can be used to represent the
three directions. All the distances are measured in meters.
To place your objects in the scene, you start at point (0,0,0), and then move the objects wherever you want.
Moving the objects is called a “transformation”, so the classes you use are: TransformGroup and
Transform3D. You add both the object and the Transform3D to a TransformGroup before adding the
TransformGroup to the rest of your scene.

Step
1. Create a transform, a transform group and an object
2.
3.
4.
5.

Specify a location for the object
Set the transform to move (translate) the object to
that location
Add the transform to the transform group
Add the object to the transform group

Example
Transform transform= new Transform3D();
TransformGroup tg = new TransformGroup();
Cone cone = new Cone(0.5f, 0.5f);
Vector3f vector = new Vector3f(-.2f,.1f , -.4f);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(cone);

This may seem complicated, but the transform groups enable you to collect objects together and move them
as one unit. For example, a table could be made up of cylinders for legs and a box for the top. If you add all
the parts of the table to a single transform group, you can move the whole table with one translation.
The Transform3D class can do much more than specifying the co-ordinates of the object. The functions
include setScale to change the size of an object and rotX, rotY and rotZ for rotating an object around each
axis (counter clockwise).
This example displays the different objects on each axis.
import
import
import
import

com.sun.j3d.utils.geometry.*;
com.sun.j3d.utils.universe.*;
javax.media.j3d.*;
javax.vecmath.*;

public class Position {
public Position() {
SimpleUniverse universe = new SimpleUniverse();
BranchGroup group = new BranchGroup();
// X axis made of spheres
for (float x = -1.0f; x <= 1.0f; x = x + 0.1f)
{
Sphere sphere = new Sphere(0.05f);
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();

4
Vector3f vector = new Vector3f( x, .0f, .0f);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(sphere);
group.addChild(tg);
}
// Y axis made of cones
for (float y = -1.0f; y <= 1.0f; y = y + 0.1f)
{
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
Cone cone = new Cone(0.05f, 0.1f);
Vector3f vector = new Vector3f(.0f, y, .0f);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(cone);
group.addChild(tg);
}
// Z axis made of cylinders
for (float z = -1.0f; z <= 1.0f; z = z+ 0.1f)
{
TransformGroup tg = new TransformGroup();
Transform3D transform = new Transform3D();
Cylinder cylinder = new Cylinder(0.05f, 0.1f);
Vector3f vector = new Vector3f(.0f, .0f, z);
transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(cylinder);
group.addChild(tg);
}
Color3f light1Color = new Color3f(.1f, 1.4f, .1f); // green light
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
universe.getViewingPlatform().setNominalViewingTransform();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
public static void main(String[] args) {
new Position();
}
}

5
Appearance Is Everything
There are many ways to change the way that objects in your scene look.
You can change their color, how much light they reflect. You can paint
them with two-dimensional images, or add rough textures to their
surfaces. The Appearance class contains the functions for making these
changes. This section shows you how to use these functions.
The simplest way of setting the appearance is by specifying only the
color and the shading method. This works for setting an object to being
a simple color, but to make an object look realistic, you need to specify
how an object appears under lights. You do this by creating a Material.

Step
1. Create an object
2. Create an appearance
3. Create a color
4. Create the coloring attributes
5.
6.

Add the attributes to the appearance
Set the appearance for the object

Example
Sphere sphere = new Sphere();
Appearance ap = new Appearance();
Color3f col = new Color3f(0.0f, 0.0f, 1.0f);
ColoringAttributes ca = new ColoringAttributes
(col, ColoringAttributes.NICEST);
ap.setColoringAttributes(ca);
sphere.setAppearance(ap);

Materials
Materials have five properties that enable you to specify how the object appears. There are four colors:
Ambient, Emissive, Diffuse, and Specular. The fifth property is shininess, that you specify with a number.
Each color specifies what light is given off in a certain situation.
•
•
•
•

Ambient color reflects light that been scattered so much by the environment that the direction is
impossible to determine. This is created by an AmbientLight in Java 3D.
Emissive color is given off even in darkness. You could use this for a neon sign or a glow-in-the-dark
object
Diffuse color reflects light that comes from one direction, so it's brighter if it comes squarely down on
a surface that if it barely glances off the surface. This is used with a DirectionalLight.
Specular light comes from a particular direction, and it tends to bounce off the surface in a preferred
direction. Shiny metal or plastic have a high specular component. The amount of specular light that
reaches the viewer depends on the location of the viewer and the angle of the light bouncing off the
object.

Changing the shininess factor affects not just how shiny the object is, but whether it shines with a small
glint in one area, or a larger area with less of a gleaming look.
For most objects you can use one color for both Ambient and Diffuse components, and black for Emissive
(most things don’t glow in the dark). If it’s a shiny object, you would use a lighter color for Specular
reflections. For example, the material for a red billiard ball might be:
// billiard ball
//

ambient emissive diffuse specular shininess

// Material mat = new Material(red,

black,

red,

white,

70f);

6
For a rubber ball, you could use a black or red specular light instead of white which would make the ball
appear less shiny. Reducing the shininess factor from 70 to 0 would not work the way you might expect, it
would spread the white reflection across the whole object instead of it being concentrated in one spot.

Texture
Materials make change the appearance of a whole shape, but sometimes even the shiniest objects can seem
dull. By adding texture you can produce more interesting effects like marbling or wrapping a twodimensional image around your object.
The TextureLoader class enables you to load an image to use as a texture. The dimensions of your image
must be powers of two, for example 128 pixels by 256. When you load the texture you can also specify
how you want to use the image. For example, RGB to use the color of the image or LUMINANCE to see
the image in black and white.
After the texture is loaded, you can change the TextureAttributes to say whether you want the image to
replace the object underneath or modulate the underlying color. You can also apply it as a decal or blend
the image with the color of your choice.
If you are using a simple object like a sphere then you will also have to enable texturing by setting the
“primitive flags”. These can be set to Primitive.GENERATE_NORMALS +
Primitive.GENERATE_TEXTURE_COORDS when you create the object.
In case this is starting to sound a bit complicated, here is an example. You can experiment with the texture
settings in this example and compare the results. You can download the picture I used from
http://www.java3d.org/Arizona.jpg or you can substitute a picture of your own.
import
import
import
import
import
import

com.sun.j3d.utils.geometry.*;
com.sun.j3d.utils.universe.*;
com.sun.j3d.utils.image.*;
javax.media.j3d.*;
javax.vecmath.*;
java.awt.Container;

public class PictureBall {
public PictureBall() {
// Create the universe
SimpleUniverse universe = new SimpleUniverse();
// Create a structure to contain objects
BranchGroup group = new BranchGroup();
// Set up colors
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
Color3f red = new Color3f(0.7f, .15f, .15f);
// Set up the texture map
TextureLoader loader = new TextureLoader("K:3dArizona.jpg",
"LUMINANCE", new Container());
Texture texture = loader.getTexture();
texture.setBoundaryModeS(Texture.WRAP);
texture.setBoundaryModeT(Texture.WRAP);

7
texture.setBoundaryColor( new Color4f( 0.0f, 1.0f, 0.0f, 0.0f ) );
// Set up the texture attributes
//could be REPLACE, BLEND or DECAL instead of MODULATE
TextureAttributes texAttr = new TextureAttributes();
texAttr.setTextureMode(TextureAttributes.MODULATE);
Appearance ap = new Appearance();
ap.setTexture(texture);
ap.setTextureAttributes(texAttr);
//set up the material
ap.setMaterial(new Material(red, black, red, black, 1.0f));
// Create a ball to demonstrate textures
int primflags = Primitive.GENERATE_NORMALS +
Primitive.GENERATE_TEXTURE_COORDS;
Sphere sphere = new Sphere(0.5f, primflags, ap);
group.addChild(sphere);
// Create lights
Color3f light1Color = new Color3f(1f, 1f, 1f);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
AmbientLight ambientLight =
new AmbientLight(new Color3f(.5f,.5f,.5f));
ambientLight.setInfluencingBounds(bounds);
group.addChild(ambientLight);
// look towards the ball
universe.getViewingPlatform().setNominalViewingTransform();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
public static void main(String[] args) {
new PictureBall();
}
}
You can also set up three-dimensional textures, using shapes instead of a flat image. Unfortunately, these
do not currently work very well across different platforms.

Special Effects
Look at the AppearanceTest example that comes with Java 3D for more effects you can use. For example
you can display objects as wire-frames, display only the corners of an object and so on. You can even make
objects transparent, with the following settings:
TransparencyAttributes t_attr =
new TransparencyAttributes(TransparencyAttributes.BLENDED,0.5f,
TransparencyAttributes.BLEND_SRC_ALPHA,
TransparencyAttributes.BLEND_ONE);

8
ap.setTransparencyAttributes( t_attr );

Java 3D and the User Interface
Most real-life applications use a mixture of three dimensional and two-dimensional elements. This section
describes how to combine your Java 3D with the rest of your program.

Canvas3D
Each area where three-dimensional graphics can be painted is called a Canvas3D. This is a rectangle that
contains a view of the objects in your universe. You place the canvas inside a frame, then you create a
universe to be displayed in the canvas.
The following example shows how to create a canvas in a frame with labels at the top and bottom. The
program can be run as either an applet or an application.
import
import
import
import
import
import
import
import
import
public

com.sun.j3d.utils.universe.SimpleUniverse;
com.sun.j3d.utils.geometry.ColorCube;
javax.media.j3d.BranchGroup;
javax.media.j3d.Canvas3D;
java.awt.GraphicsConfiguration;
java.awt.BorderLayout;
java.awt.Label;
java.applet.Applet;
com.sun.j3d.utils.applet.MainFrame;
class CanvasDemo extends Applet {

public CanvasDemo()

{

setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(config);
add("North",new Label("This is the top"));
add("Center", canvas);
add("South",new Label("This is the bottom"));
BranchGroup contents = new BranchGroup();
contents.addChild(new ColorCube(0.3));
SimpleUniverse universe = new SimpleUniverse(canvas);
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(contents);
}
public static void main( String[] args ) {
CanvasDemo demo = new CanvasDemo();
new MainFrame(demo,400,400);
}
}

Java 3D and Swing
The Canvas3D takes advantage of your computer’s graphics card to increase performance. Unfortunately,
this means that it does not mix very well with Sun’s swing user interface components. These components
are called “lightweight” Lightweight components can be hidden by a Canvas3D even if they are supposed
to be at the front.

9
There are several solutions to this problem:
•

You can mix lightweight and heavyweight components on the same screen if you keep them in
separate containers.

•

If you use Popup menus, a static function on JPopupMenu fixes the problem:
setDefaultLightWeightPopupEnabled(false);

•

You can use the older AWT components instead of swing.

10
Animation and Interaction – a Bouncing Ball
To create animation you need to move the objects between each frame of animation. You can use a timer
and move the 3D objects by a small amount each time. Also, you can modify the objects in other ways, the
next example scales the ball so that it looks squashed at the bottom of each bounce.
For interaction with the user, you can process keystrokes or clicks on buttons or other components.
One thing to notice is that you have to tell Java3D you are going to move something by setting a capability.
Otherwise, you will not be able to move anything once it has been drawn.
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
The following example combines these techniques. You start it by clicking on the button, then the ball
bounces up and down, and you can press a or s to move the ball left or right.
import
import
import
import
import
import
import
import
import
import

java.applet.Applet;
java.awt.*;
java.awt.event.*;
java.awt.event.WindowAdapter;
com.sun.j3d.utils.applet.MainFrame;
com.sun.j3d.utils.universe.*;
javax.media.j3d.*;
javax.vecmath.*;
com.sun.j3d.utils.geometry.Sphere;
javax.swing.Timer;

public class BouncingBall extends Applet implements ActionListener,
KeyListener {
private Button go = new Button("Go");
private TransformGroup objTrans;
private Transform3D trans = new Transform3D();
private float height=0.0f;
private float sign = 1.0f; // going up or down
private Timer timer;
private float xloc=0.0f;
public BranchGroup createSceneGraph() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objRoot.addChild(objTrans);
// Create a simple shape leaf node, add it to the scene graph.
Sphere sphere = new Sphere(0.25f);
objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
Transform3D pos1 = new Transform3D();
pos1.setTranslation(new Vector3f(0.0f,0.0f,0.0f));
objTrans.setTransform(pos1);
objTrans.addChild(sphere);
objRoot.addChild(objTrans);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

11
Color3f light1Color = new Color3f(1.0f, 0.0f, 0.2f);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
// Set up the ambient light
Color3f ambientColor = new Color3f(1.0f, 1.0f, 1.0f);
AmbientLight ambientLightNode = new AmbientLight(ambientColor);
ambientLightNode.setInfluencingBounds(bounds);
objRoot.addChild(ambientLightNode);
return objRoot;
}
public BouncingBall() {
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
add("Center", c);
c.addKeyListener(this);
timer = new Timer(100,this);
//timer.start();
Panel p =new Panel();
p.add(go);
add("North",p);
go.addActionListener(this);
go.addKeyListener(this);
// Create a simple scene and attach it to the virtual universe
BranchGroup scene = createSceneGraph();
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
}
public void keyPressed(KeyEvent e) {
//Invoked when a key has been pressed.
if (e.getKeyChar()=='s') {xloc = xloc + .1f;}
if (e.getKeyChar()=='a') {xloc = xloc - .1f;}
}
public void keyReleased(KeyEvent e){
// Invoked when a key has been released.
}
public void keyTyped(KeyEvent e){
//Invoked when a key has been typed.
}
public void actionPerformed(ActionEvent e ) {
// start timer when button is pressed
if (e.getSource()==go){
if (!timer.isRunning()) {
timer.start();
}
}

12
else {
height += .1 * sign;
if (Math.abs(height *2) >= 1 ) sign = -1.0f * sign;
if (height<-0.4f) {
trans.setScale(new Vector3d(1.0, .8, 1.0));
}
else {
trans.setScale(new Vector3d(1.0, 1.0, 1.0));
}
trans.setTranslation(new Vector3f(xloc,height,0.0f));
objTrans.setTransform(trans);
}
}
public static void main(String[] args) {
System.out.println("Program Started");
BouncingBall bb = new BouncingBall();
bb.addKeyListener(bb);
MainFrame mf = new MainFrame(bb, 256, 256);
}
}

13
Natural Selection
Once you have created a 3D scene you may want to interact with the objects
within it. A first step is to select an object with the mouse. The Java 3D
picking classes help you to do this, you can use them in the following way:

1.

Create a PickCanvas from the Canvas 3D and the BranchGroup you want to pick from.
PickCanvas pickCanvas = new PickCanvas(canvas, group);

2.

Set the pickCanvas to use the bounds of the object for picking.
pickCanvas.setMode(PickCanvas.BOUNDS);

3.

Handle the mouse event by extending MouseAdapter and listening for mouse events on the
Canvas3D using canvas.addMouseListener(this).

4.

Define the mouseClicked function so that the PickCanvas calls the PickClosest
function to return the PickResult.

5.

Call getNode on PickResult to find out more about the object that has been picked.

Here is a complete example that displays two objects (a cube and a sphere). When you click the mouse it
prints out the class name of the selected object.
import com.sun.j3d.utils.picking.*;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.event.*;
import java.awt.*;
public class Pick extends MouseAdapter {
private PickCanvas pickCanvas;
public Pick()
{
Frame frame = new Frame("Box and Sphere");
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(config);
canvas.setSize(400, 400);
SimpleUniverse universe = new SimpleUniverse(canvas);
BranchGroup group = new BranchGroup();
// create a color cube
Vector3f vector = new Vector3f(-0.3f, 0.0f, 0.0f);
Transform3D transform = new Transform3D();
transform.setTranslation(vector);
TransformGroup transformGroup = new TransformGroup(transform);
ColorCube cube = new ColorCube(0.3);
transformGroup.addChild(cube);
group.addChild(transformGroup);
//create a sphere
Vector3f vector2 = new Vector3f(+0.3f, 0.0f, 0.0f);
Transform3D transform2 = new Transform3D();

14
transform2.setTranslation(vector2);
TransformGroup transformGroup2 = new TransformGroup(transform2);
Appearance appearance = new Appearance();
appearance.setPolygonAttributes(
new PolygonAttributes(PolygonAttributes.POLYGON_LINE,
PolygonAttributes.CULL_BACK,0.0f));
Sphere sphere = new Sphere(0.3f,appearance);
transformGroup2.addChild(sphere);
group.addChild(transformGroup2);
universe.getViewingPlatform().setNominalViewingTransform();
universe.addBranchGraph(group);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent winEvent) {
System.exit(0);
}
});
frame.add(canvas);
pickCanvas = new PickCanvas(canvas, group);
pickCanvas.setMode(PickCanvas.BOUNDS);
canvas.addMouseListener(this);
frame.pack();
frame.show();
}
public static void main( String[] args ) {
new Pick();
}
public void mouseClicked(MouseEvent e)
{
pickCanvas.setShapeLocation(e);
PickResult result = pickCanvas.pickClosest();
if (result == null) {
System.out.println("Nothing picked");
} else {
Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE);
Shape3D s = (Shape3D)result.getNode(PickResult.SHAPE3D);
if (p != null) {
System.out.println(p.getClass().getName());
} else if (s != null) {
System.out.println(s.getClass().getName());
} else{
System.out.println("null");
}
}
}
} // end of class Pick

More Accurate Picking
The previous example shows the most basic form of picking, based on the bounds of the object. If you try
the example and click near the sphere you can see that it isn't very accurate. If you imagine a box around
the sphere and click anywhere within that box, the program will report that you have picked the sphere.
This is because the box and the sphere both have the same bounds.

If you need to be more accurate you need to use geometry picking. Change the line:

pickCanvas.setMode(PickCanvas.BOUNDS);
15
to
pickCanvas.setMode(PickCanvas.GEOMETRY);
Unfortunately, this is not the whole story. For geometry picking to work you need to set
various capabilities on the objects in your scene. These capabilities are set to off by
default so that applications that do not use advanced picking are not slowed down
unnecessarily. To turn them on, use:
node.setCapability(Node.ENABLE_PICK_REPORTING);
PickTool.setCapabilities(node, PickTool.INTERSECT_FULL);
If you set the capabilities on all the objects you have added to the scene, you may find
that detailed picking still does not work. This is because objects may be made up of other
objects. For example instead of setting them once for a cube, you may need to set the
capabilities six times, once for each face. The easiest way to make sure that all parts of
each object are pickable is to call the following function on BranchGroup of your scene:
public void enablePicking(Node node) {
node.setPickable(true);
node.setCapability(Node.ENABLE_PICK_REPORTING);
try {
Group group = (Group) node;
for (Enumeration e = group.getAllChildren();
e.hasMoreElements();) {
enablePicking((Node)e.nextElement());
}
}
catch(ClassCastException e) {
// if not a group node, there are no children so ignore
exception
}
try {
Shape3D shape = (Shape3D) node;
PickTool.setCapabilities(node, PickTool.INTERSECT_FULL);
for (Enumeration e = shape.getAllGeometries();
e.hasMoreElements();) {
Geometry g = (Geometry)e.nextElement();
g.setCapability(g.ALLOW_INTERSECT);
}
}
catch(ClassCastException e) {
// not a Shape3D node ignore exception
}
}
After all the capabilities are set you can use System.out.println on your pick result to find the full
range of information available. You can also use PickAllSorted instead of PickClosest to pick
more than one object at the same time.

Pick Shapes
So far the examples have picked objects using the default shape: an imaginary ray going from the viewer's
eye position through the mouse pointer into infinity. Instead of a thin ray you can change the shape used for
picking. For example, you might use a cylinder instead of a narrow ray to make picking points easier. A
cone shaped area is an easy way to pick anything that a viewer can see.

16
The setShape function on PickCanvas (and PickTool) can set the shape to a Cone, Cylinder, Point
or Ray. Each of these shapes can either go on forever (a ray) or stop after a fixed distance (a segment), you
can also pick based on a Bounds object.
As well as setting the shape you can set the tolerance for the picking operation. This is the distance (in
pixels) that your PickShape can miss the target object by and still select the object.

Advanced Picking
Picking can be used for more than just mouse selection. The pick shapes can be located anywhere and can
be moved around within your scene. They can be used for collision detection or avoidance. For example,
you could use a pick shape in front of a person to detect potential obstacles and stop them from bumping
into things. If you were writing a pool game you could use a PickRaySegment to represent the pool cue and
you could pick with BoundingSphere to detecting collisions between the balls.

17
Of Mice and Men
To be able to work with objects in Java 3D, it
helps if you understand where the viewer and the
mouse pointer are in the scene.
For example we can create a cube that you can
draw on; the mouse pointer represents the end of a
pencil. To draw on the cube, we need to know
where the mouse pointer touches a face of the
cube.
When the mouse is dragged, the mouse event in
the mouseDragged callback gives us the x and
y co-ordinates of the mouse pointer. The following
code gets the location of the mouse in the image
plate and then transforms it into the location in the
virtual world.

Point3d mousePos = new Point3d();
canvas.getPixelLocationInImagePlate(event.getX(), event.getY(),
mousePos);
Transform3D transform = new Transform3D();
canvas.getImagePlateToVworld(transform);
transform.transform(mousePos);
The eye position (actually the position of the top of the viewers nose – the center eye) can be transformed
into virtual world co-ordinates in the same way.
Point3d eyePos = new Point3d();
canvas.getCenterEyeInImagePlate(eyePos);
transform.transform(eyePos);
Now that we know the points where the eye and the mouse pointer are, we want to find where on the cube
to draw. Let’s assume we want to draw on the front face of the cube. We can find where a line through
these two points intersects with the face of the cube. For the front face of a unit cube at the origin, the
corners are at: (.5, -.5, .5), (.5, .5, .5), (-.5, .5, .5), (-.5, -.5, .5).
We only need three of them to define a plane and then a bit of vector mathematics to give us the point
where a line from the eye to the mouse pointer hits the cube.
Point3d
Point3d
Point3d
Point3d

p1 = new Point3d(.5, -.5, .5);
p2 = new Point3d(.5, .5, .5);
p3 = new Point3d(-.5, .5, .5);
intersection = getIntersection(eyePos, mousePos, p1, p2, p3);

18
/**
* Returns the point where a line crosses a plane
*/
Point3d getIntersection(Point3d line1, Point3d line2,
Point3d plane1, Point3d plane2, Point3d plane3) {
Vector3d p1 = new Vector3d(plane1);
Vector3d p2 = new Vector3d(plane2);
Vector3d p3 = new Vector3d(plane3);
Vector3d p2minusp1 = new Vector3d(p2);
p2minusp1.sub(p1);
Vector3d p3minusp1 = new Vector3d(p3);
p3minusp1.sub(p1);
Vector3d normal = new Vector3d();
normal.cross(p2minusp1, p3minusp1);
// The plane can be defined by p1, n + d = 0
double d = -p1.dot(normal);
Vector3d i1 = new Vector3d(line1);
Vector3d direction = new Vector3d(line1);
direction.sub(line2);
double dot = direction.dot(normal);
if (dot == 0) return null;
double t = (-d - i1.dot(normal)) / (dot);
Vector3d intersection = new Vector3d(line1);
Vector3d scaledDirection = new Vector3d(direction);
scaledDirection.scale(t);
intersection.add(scaledDirection);
Point3d intersectionPoint = new Point3d(intersection);
return intersectionPoint;
}
Now we know where the intersection point is, it is easy to draw on an image that we can use as a texture on
the cube. Remember that the y coordinate for the mouse gets higher as you move the mouse pointer down
the screen. This has to be reversed to get to the y coordinate you are used to seeing on a graph.
public void mouseDragged(MouseEvent event) {
Point3d intersectionPoint = getPosition(event);
if (Math.abs(intersectionPoint.x) < 0.5 &&
Math.abs(intersectionPoint.y) < 0.5) {
double x = (0.5 + intersectionPoint.x) * imageWidth;
double y = (0.5 - intersectionPoint.y) * imageHeight;
Graphics2D g = (Graphics2D) frontImage.getGraphics();
g.setColor( Color.BLACK);
g.setStroke(new BasicStroke(3));
int iX = (int)(x + .5);
int iY = (int)(y + .5);
if (lastX < 0) {
lastX = iX;
lastY = iY;
}
g.drawLine(lastX, lastY, iX, iY);
lastX = iX;
lastY = iY;
changeTexture(texture, frontImage, frontShape);
}

19
Of course, the method I’ve explained so far assumes that the cube always stays in the same place. In a real
application you are likely to have objects in different places and different orientations. Fortunately, it is
easy to allow for this by transforming the points of the plane from the local to virtual world coordinates and
then transforming the intersection point back to local coordinates at the end.
Transform3D currentTransform = new Transform3D();
box.getLocalToVworld(currentTransform);
currentTransform.transform(p1);
currentTransform.transform(p2);
currentTransform.transform(p3);
Point3d intersection = getIntersection(eyePos, mousePos, p1, p2, p3);
currentTransform.invert();
currentTransform.transform(intersection);
Here’s an example that puts all these techniques together. It shows a cube with different colored faces. You
can rotate the cube with the left mouse button, and draw on the front (blue) face with the right mouse
button.
import
import
import
import
import
import
import
import
import
import
import
import
import

java.applet.Applet;
java.awt.*;
java.awt.event.*;
java.awt.image.BufferedImage;
javax.media.j3d.*;
javax.vecmath.*;
com.sun.j3d.utils.applet.MainFrame;
com.sun.j3d.utils.behaviors.mouse.MouseRotate;
com.sun.j3d.utils.geometry.*;
com.sun.j3d.utils.image.TextureLoader;
com.sun.j3d.utils.pickfast.PickCanvas;
com.sun.j3d.utils.universe.SimpleUniverse;
com.sun.j3d.utils.universe.ViewingPlatform;

public class DrawingExample extends Applet implements MouseListener,
MouseMotionListener {
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private

static final long serialVersionUID = 1L;
MainFrame frame;
Box box;
int imageHeight = 256;
int imageWidth = 256;
Canvas3D canvas;
SimpleUniverse universe;
BranchGroup group = new BranchGroup();
PickCanvas pickCanvas;
BufferedImage frontImage;
Shape3D frontShape;
Texture texture;
Appearance appearance;
TextureLoader loader;
int lastX=-1;
int lastY=-1;
int mouseButton = 0;
TransformGroup boxTransformGroup;

20
public static void main(String[] args) {
DrawingExample object = new DrawingExample();
object.frame = new MainFrame(object, args,
object.imageWidth, object.imageHeight);
object.startSheet();
object.validate();
}
public Point3d getPosition(MouseEvent event) {
Point3d eyePos = new Point3d();
Point3d mousePos = new Point3d();
canvas.getCenterEyeInImagePlate(eyePos);
canvas.getPixelLocationInImagePlate(event.getX(),
event.getY(), mousePos);
Transform3D transform = new Transform3D();
canvas.getImagePlateToVworld(transform);
transform.transform(eyePos);
transform.transform(mousePos);
Vector3d direction = new Vector3d(eyePos);
direction.sub(mousePos);
// three points on the plane
Point3d p1 = new Point3d(.5, -.5, .5);
Point3d p2 = new Point3d(.5, .5, .5);
Point3d p3 = new Point3d(-.5, .5, .5);
Transform3D currentTransform = new Transform3D();
box.getLocalToVworld(currentTransform);
currentTransform.transform(p1);
currentTransform.transform(p2);
currentTransform.transform(p3);
Point3d intersection = getIntersection(eyePos, mousePos,
p1, p2, p3);
currentTransform.invert();
currentTransform.transform(intersection);
return intersection;
}
/**
* Returns the point where a line crosses a plane
*/
Point3d getIntersection(Point3d line1, Point3d line2,
Point3d plane1, Point3d plane2, Point3d plane3) {
Vector3d p1 = new Vector3d(plane1);
Vector3d p2 = new Vector3d(plane2);
Vector3d p3 = new Vector3d(plane3);
Vector3d p2minusp1 = new Vector3d(p2);
p2minusp1.sub(p1);
Vector3d p3minusp1 = new Vector3d(p3);
p3minusp1.sub(p1);
Vector3d normal = new Vector3d();
normal.cross(p2minusp1, p3minusp1);
// The plane can be defined by p1, n + d = 0
double d = -p1.dot(normal);
Vector3d i1 = new Vector3d(line1);
Vector3d direction = new Vector3d(line1);
direction.sub(line2);
double dot = direction.dot(normal);

21
if (dot == 0) return null;
double t = (-d - i1.dot(normal)) / (dot);
Vector3d intersection = new Vector3d(line1);
Vector3d scaledDirection = new Vector3d(direction);
scaledDirection.scale(t);
intersection.add(scaledDirection);
Point3d intersectionPoint = new Point3d(intersection);
return intersectionPoint;
}
private void startSheet() {
setLayout(new BorderLayout());
GraphicsConfiguration config = SimpleUniverse
.getPreferredConfiguration();
canvas = new Canvas3D(config);
universe = new SimpleUniverse(canvas);
add("Center", canvas);
positionViewer();
getScene();
universe.addBranchGraph(group);
pickCanvas = new PickCanvas(canvas, group);
pickCanvas.setMode(PickInfo.PICK_BOUNDS);
canvas.addMouseMotionListener(this);
frame.addMouseMotionListener(this);
canvas.addMouseListener(this);
frame.addMouseListener(this);
}
public void getScene() {
addLights(group);
Appearance ap = getAppearance(new Color3f(Color.blue));
ap.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
ap.setCapability(Appearance.ALLOW_TEXGEN_WRITE);
box = new Box(.5f, .5f, .5f,
Primitive.GENERATE_TEXTURE_COORDS,
getAppearance(new Color3f(Color.green)));
box.setCapability(Box.ENABLE_APPEARANCE_MODIFY);
box.setCapability(Box.GEOMETRY_NOT_SHARED);
frontShape = box.getShape(Box.FRONT);
frontShape.setAppearance(ap);

box.getShape(Box.TOP).setAppearance(getAppearance(Color.magenta));
box.getShape(Box.BOTTOM).setAppearance(
getAppearance(Color.orange)); ;
box.getShape(Box.RIGHT).setAppearance(
getAppearance(Color.red));
box.getShape(Box.LEFT).setAppearance(
getAppearance(Color.green));
box.getShape(Box.BACK).setAppearance(
getAppearance(Color.yellow));
frontImage = new BufferedImage(imageWidth, imageHeight,
BufferedImage.TYPE_INT_RGB);

22
Graphics2D g = (Graphics2D)frontImage.getGraphics();
g.setColor(new Color(70,70,140));
g.fillRect(0, 0, imageWidth, imageHeight);
addTexture(frontImage, frontShape);
MouseRotate behavior = new MouseRotate();
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
boxTransformGroup = new TransformGroup();
boxTransformGroup
.setCapability(TransformGroup.ALLOW_TRANSFORM_R

EAD);

boxTransformGroup
.setCapability(TransformGroup.ALLOW_TRANSFORM_W
RITE);

behavior.setTransformGroup(boxTransformGroup);
boxTransformGroup.addChild(behavior);
behavior.setSchedulingBounds(bounds);
boxTransformGroup.addChild(box);
group.addChild(boxTransformGroup);
}
public void addTexture(BufferedImage image, Shape3D shape) {
frontShape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
appearance = shape.getAppearance();

appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
appearance.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
changeTexture( texture, image, shape);
Color3f col = new Color3f(0.0f, 0.0f, 1.0f);
ColoringAttributes ca = new ColoringAttributes(col,
ColoringAttributes.NICEST);
appearance.setColoringAttributes(ca);
}
public void changeTexture(Texture texture, BufferedImage image,
Shape3D shape) {
loader = new TextureLoader(image, "RGB",
TextureLoader.ALLOW_NON_POWER_OF_TWO);
texture = loader.getTexture();
texture.setBoundaryModeS(Texture.CLAMP_TO_BOUNDARY);
texture.setBoundaryModeT(Texture.CLAMP_TO_BOUNDARY);
texture.setBoundaryColor(new Color4f(0.0f, 1.0f, 0.5f, 0f));
// Set up the texture attributes
// could be REPLACE, BLEND or DECAL instead of MODULATE

1.0f));

// front = getAppearance(new Color3f(Color.YELLOW));
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
Color3f red = new Color3f(0.7f, .15f, .15f);
appearance.setMaterial(new Material(red, black, red, white,

23
TextureAttributes texAttr = new TextureAttributes();
texAttr.setTextureMode(TextureAttributes.REPLACE);
appearance.setTextureAttributes(texAttr);
appearance.setTexture(texture);
shape.setAppearance(appearance);
}
BufferedImage getStartingImage(int i, int width, int height) {
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D)image.getGraphics();
g.setColor(new Color(70,70,140));
g.fillRect(0, 0, width, height);
return image;
}
public void positionViewer() {
ViewingPlatform vp = universe.getViewingPlatform();
TransformGroup tg1 = vp.getViewPlatformTransform();
Transform3D t3d = new Transform3D();
tg1.getTransform(t3d);
vp.setNominalViewingTransform();
}
public static void addLights(BranchGroup group) {
Color3f light1Color = new Color3f(0.7f, 0.8f, 0.8f);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,
0.0, 0.0),
100.0);
Vector3f light1Direction = new Vector3f(4.0f, -7.0f,
-12.0f);
DirectionalLight light1 = new DirectionalLight(light1Color,
light1Direction);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
AmbientLight light2 = new AmbientLight(new Color3f(0.3f,
0.3f, 0.3f));
light2.setInfluencingBounds(bounds);
group.addChild(light2);
}
public static Appearance getAppearance(Color color) {
return getAppearance(new Color3f(color));
}
public static Appearance getAppearance(Color3f color) {
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
Appearance ap = new Appearance();
Texture texture = new Texture2D();
TextureAttributes texAttr = new TextureAttributes();
texAttr.setTextureMode(TextureAttributes.MODULATE);
texture.setBoundaryModeS(Texture.WRAP);
texture.setBoundaryModeT(Texture.WRAP);

24
0.0f));
70f);

texture.setBoundaryColor(new Color4f(0.0f, 1.0f, 0.0f,
Material mat = new Material(color, black, color, white,
ap.setTextureAttributes(texAttr);
ap.setMaterial(mat);
ap.setTexture(texture);
ColoringAttributes ca = new ColoringAttributes(color,
ColoringAttributes.NICEST);
ap.setColoringAttributes(ca);
return ap;

}
@Override
public void mouseClicked(MouseEvent arg0) {
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}

@Override
public void mousePressed(MouseEvent event) {
lastX=-1;
lastY=-1;
mouseButton = event.getButton();
}
@Override
public void mouseReleased(MouseEvent arg0) {
}
@Override
public void mouseDragged(MouseEvent event) {
if (mouseButton==MouseEvent.BUTTON1) return;
Point3d intersectionPoint = getPosition(event);
if (Math.abs(intersectionPoint.x) < 0.5 &&
Math.abs(intersectionPoint.y) < 0.5) {
double x = (0.5 + intersectionPoint.x) * imageWidth;
double y = (0.5 - intersectionPoint.y) * imageHeight;
Graphics2D g = (Graphics2D) frontImage.getGraphics();
g.setColor( Color.BLACK);
g.setStroke(new BasicStroke(3));
int iX = (int)(x + .5);
int iY = (int)(y + .5);
if (lastX < 0) {
lastX = iX;
lastY = iY;
}
g.drawLine(lastX, lastY, iX, iY);
lastX = iX;
lastY = iY;
changeTexture(texture, frontImage, frontShape);

25
}

}

@Override
public void mouseMoved(MouseEvent arg0) {
}
}

26
Further Information
I hope this tutorial has got you interested in programming with Java 3D. You should now know enough to
program simple scenes, or games like the Pyramid game at http://www.fungames.org.
There are several sources of information to help you learn more.

Online Information
•

Java 3D comes with several useful examples, these are described at:
http://www.java.sun.com/products/javamedia/3D/forDevelopers/J3D_1_2_API/j3dguide/AppendixExamples.html

•

Sun’s tutorial is at:
http://java.sun.com/products/java-media/3D/collateral/

•

The API documentation is at:
http://java.sun.com/products/java-media/3D/forDevelopers/j3dapi/index.html

•

My site is at:
http://www.java3d.org

Books
There the following books on Java 3D::
•

Java 3D API Jump-Start, by Aaron E. Walsh and Doug Gehringer

•

Killer Game Programming in Java

•

3D User Interfaces with Java 3D, by John Barrilleaux

•

Java 3D Programming, by Daniel Selman

•

The Java 3D API Specification (With CD-ROM), by Henry Sowizral, Kevin Rushforth, Michael
Deering

27

Más contenido relacionado

La actualidad más candente

Opensource gis development - part 3
Opensource gis development - part 3Opensource gis development - part 3
Opensource gis development - part 3Andrea Antonello
 
The Ring programming language version 1.5.3 book - Part 48 of 184
The Ring programming language version 1.5.3 book - Part 48 of 184The Ring programming language version 1.5.3 book - Part 48 of 184
The Ring programming language version 1.5.3 book - Part 48 of 184Mahmoud Samir Fayed
 
Lec 7 28_aug [compatibility mode]
Lec 7 28_aug [compatibility mode]Lec 7 28_aug [compatibility mode]
Lec 7 28_aug [compatibility mode]Palak Sanghani
 
The Ring programming language version 1.3 book - Part 38 of 88
The Ring programming language version 1.3 book - Part 38 of 88The Ring programming language version 1.3 book - Part 38 of 88
The Ring programming language version 1.3 book - Part 38 of 88Mahmoud Samir Fayed
 
Python object oriented programming (lab2) (2)
Python object oriented programming (lab2) (2)Python object oriented programming (lab2) (2)
Python object oriented programming (lab2) (2)iloveallahsomuch
 
Type script by Howard
Type script by HowardType script by Howard
Type script by HowardLearningTech
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Codestasimus
 
Dotnet unit 4
Dotnet unit 4Dotnet unit 4
Dotnet unit 4007laksh
 
TypeScript by Howard
TypeScript by HowardTypeScript by Howard
TypeScript by HowardLearningTech
 
Unit3 jwfiles
Unit3 jwfilesUnit3 jwfiles
Unit3 jwfilesmrecedu
 
03 Geographic scripting in uDig - halfway between user and developer
03 Geographic scripting in uDig - halfway between user and developer03 Geographic scripting in uDig - halfway between user and developer
03 Geographic scripting in uDig - halfway between user and developerAndrea Antonello
 

La actualidad más candente (14)

Opensource gis development - part 3
Opensource gis development - part 3Opensource gis development - part 3
Opensource gis development - part 3
 
The Ring programming language version 1.5.3 book - Part 48 of 184
The Ring programming language version 1.5.3 book - Part 48 of 184The Ring programming language version 1.5.3 book - Part 48 of 184
The Ring programming language version 1.5.3 book - Part 48 of 184
 
Lec 7 28_aug [compatibility mode]
Lec 7 28_aug [compatibility mode]Lec 7 28_aug [compatibility mode]
Lec 7 28_aug [compatibility mode]
 
The Ring programming language version 1.3 book - Part 38 of 88
The Ring programming language version 1.3 book - Part 38 of 88The Ring programming language version 1.3 book - Part 38 of 88
The Ring programming language version 1.3 book - Part 38 of 88
 
Python object oriented programming (lab2) (2)
Python object oriented programming (lab2) (2)Python object oriented programming (lab2) (2)
Python object oriented programming (lab2) (2)
 
Type script by Howard
Type script by HowardType script by Howard
Type script by Howard
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
Dotnet unit 4
Dotnet unit 4Dotnet unit 4
Dotnet unit 4
 
TypeScript by Howard
TypeScript by HowardTypeScript by Howard
TypeScript by Howard
 
Unit3 jwfiles
Unit3 jwfilesUnit3 jwfiles
Unit3 jwfiles
 
C Language Unit-3
C Language Unit-3C Language Unit-3
C Language Unit-3
 
03 Geographic scripting in uDig - halfway between user and developer
03 Geographic scripting in uDig - halfway between user and developer03 Geographic scripting in uDig - halfway between user and developer
03 Geographic scripting in uDig - halfway between user and developer
 
Python programming : Abstract classes interfaces
Python programming : Abstract classes interfacesPython programming : Abstract classes interfaces
Python programming : Abstract classes interfaces
 
Polymorphism
PolymorphismPolymorphism
Polymorphism
 

Destacado

Headrush Convo Quiz Mains
Headrush Convo Quiz MainsHeadrush Convo Quiz Mains
Headrush Convo Quiz MainsDhruv Bhatnagar
 
Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...
Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...
Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...Al Baha University
 
الكتاب المقدس العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...
الكتاب المقدس   العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...الكتاب المقدس   العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...
الكتاب المقدس العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...Ibrahimia Church Ftriends
 
Qu'est-ce que l'innovation?
Qu'est-ce que l'innovation?Qu'est-ce que l'innovation?
Qu'est-ce que l'innovation?Islem Yezza
 
John Palmer – Become Great at SubPrime – It’s over 40% of the Market!
John Palmer – Become Great at SubPrime – It’s over 40% of the Market!John Palmer – Become Great at SubPrime – It’s over 40% of the Market!
John Palmer – Become Great at SubPrime – It’s over 40% of the Market!Sean Bradley
 
Inv pres q32014_final
Inv pres q32014_finalInv pres q32014_final
Inv pres q32014_finalCNOServices
 
The Indian Backpacker Re-Launches as a Budget Travel guide to India
The Indian Backpacker Re-Launches as a Budget Travel guide to IndiaThe Indian Backpacker Re-Launches as a Budget Travel guide to India
The Indian Backpacker Re-Launches as a Budget Travel guide to IndiaAkshay Chhugani
 
Principy srozumitelného a použitelného designu
Principy srozumitelného a použitelného designuPrincipy srozumitelného a použitelného designu
Principy srozumitelného a použitelného designuMichaela Fischerová
 
الكنيسة والعبادة دستور الكنيسه الانجيليه بمصر
الكنيسة والعبادة    دستور الكنيسه الانجيليه بمصرالكنيسة والعبادة    دستور الكنيسه الانجيليه بمصر
الكنيسة والعبادة دستور الكنيسه الانجيليه بمصرIbrahimia Church Ftriends
 
لا يوجد الا اله واحد ثلاثه اقانيم
لا يوجد الا اله واحد    ثلاثه اقانيملا يوجد الا اله واحد    ثلاثه اقانيم
لا يوجد الا اله واحد ثلاثه اقانيمIbrahimia Church Ftriends
 
Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...
Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...
Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...Al Baha University
 
Salvament mari del_follet
Salvament mari del_folletSalvament mari del_follet
Salvament mari del_folletlauret64
 
реферат оксэм
реферат оксэмреферат оксэм
реферат оксэмAsya Levi
 

Destacado (20)

Goal4d
Goal4dGoal4d
Goal4d
 
Java cheat sheet
Java cheat sheetJava cheat sheet
Java cheat sheet
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat Sheet
 
Critical
CriticalCritical
Critical
 
Headrush Convo Quiz Mains
Headrush Convo Quiz MainsHeadrush Convo Quiz Mains
Headrush Convo Quiz Mains
 
Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...
Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...
Spectroscopy letters volume 26 issue 3 1993 [doi 10.1080 00387019308011552] s...
 
الكتاب المقدس العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...
الكتاب المقدس   العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...الكتاب المقدس   العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...
الكتاب المقدس العهد الجديد -رِسَالَةُ بُولُسَ الرَّسُولِ الأُولَى إِلَى أَه...
 
Qu'est-ce que l'innovation?
Qu'est-ce que l'innovation?Qu'est-ce que l'innovation?
Qu'est-ce que l'innovation?
 
Trajan
TrajanTrajan
Trajan
 
John Palmer – Become Great at SubPrime – It’s over 40% of the Market!
John Palmer – Become Great at SubPrime – It’s over 40% of the Market!John Palmer – Become Great at SubPrime – It’s over 40% of the Market!
John Palmer – Become Great at SubPrime – It’s over 40% of the Market!
 
Inv pres q32014_final
Inv pres q32014_finalInv pres q32014_final
Inv pres q32014_final
 
The Indian Backpacker Re-Launches as a Budget Travel guide to India
The Indian Backpacker Re-Launches as a Budget Travel guide to IndiaThe Indian Backpacker Re-Launches as a Budget Travel guide to India
The Indian Backpacker Re-Launches as a Budget Travel guide to India
 
Principy srozumitelného a použitelného designu
Principy srozumitelného a použitelného designuPrincipy srozumitelného a použitelného designu
Principy srozumitelného a použitelného designu
 
всё начинается с любви»
всё начинается с любви»всё начинается с любви»
всё начинается с любви»
 
الكنيسة والعبادة دستور الكنيسه الانجيليه بمصر
الكنيسة والعبادة    دستور الكنيسه الانجيليه بمصرالكنيسة والعبادة    دستور الكنيسه الانجيليه بمصر
الكنيسة والعبادة دستور الكنيسه الانجيليه بمصر
 
لا يوجد الا اله واحد ثلاثه اقانيم
لا يوجد الا اله واحد    ثلاثه اقانيملا يوجد الا اله واحد    ثلاثه اقانيم
لا يوجد الا اله واحد ثلاثه اقانيم
 
Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...
Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...
Spectroscopy Letters Volume 26 issue 3 1993 [doi 10.1080_00387019308011552] S...
 
Salvament mari del_follet
Salvament mari del_folletSalvament mari del_follet
Salvament mari del_follet
 
реферат оксэм
реферат оксэмреферат оксэм
реферат оксэм
 
Education
EducationEducation
Education
 

Similar a Learn Java 3D

Java3 d 1
Java3 d 1Java3 d 1
Java3 d 1Por Non
 
Embed the nasa world wind java sdk in eclipse
Embed the nasa world wind java sdk in eclipseEmbed the nasa world wind java sdk in eclipse
Embed the nasa world wind java sdk in eclipseMohammad Fajar
 
CS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingCS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingMark Kilgard
 
Copy of repast javagettingstarted
Copy of repast javagettingstartedCopy of repast javagettingstarted
Copy of repast javagettingstartedNimish Verma
 
CS 354 Object Viewing and Representation
CS 354 Object Viewing and RepresentationCS 354 Object Viewing and Representation
CS 354 Object Viewing and RepresentationMark Kilgard
 
CSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docx
CSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docxCSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docx
CSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docxfaithxdunce63732
 
Java design patterns
Java design patternsJava design patterns
Java design patternsShawn Brito
 
Structural pattern 3
Structural pattern 3Structural pattern 3
Structural pattern 3Naga Muruga
 
Creating Custom Charts With Ruby Vector Graphics
Creating Custom Charts With Ruby Vector GraphicsCreating Custom Charts With Ruby Vector Graphics
Creating Custom Charts With Ruby Vector GraphicsDavid Keener
 
Java Graphics
Java GraphicsJava Graphics
Java GraphicsShraddha
 
Advanced Game Development with the Mobile 3D Graphics API
Advanced Game Development with the Mobile 3D Graphics APIAdvanced Game Development with the Mobile 3D Graphics API
Advanced Game Development with the Mobile 3D Graphics APITomi Aarnio
 
Graphics, Threads and HTTPConnections in MIDLets
Graphics, Threads and HTTPConnections in MIDLetsGraphics, Threads and HTTPConnections in MIDLets
Graphics, Threads and HTTPConnections in MIDLetsJussi Pohjolainen
 
Gdc09 Minigames
Gdc09 MinigamesGdc09 Minigames
Gdc09 MinigamesSusan Gold
 
openFrameworks 007 - 3D
openFrameworks 007 - 3DopenFrameworks 007 - 3D
openFrameworks 007 - 3Droxlu
 
World wind java sdk in progess
World wind java sdk in progessWorld wind java sdk in progess
World wind java sdk in progessRaffaele de Amicis
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Korhan Bircan
 
Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5Takao Wada
 

Similar a Learn Java 3D (20)

Java3 d 1
Java3 d 1Java3 d 1
Java3 d 1
 
Games 3 dl4-example
Games 3 dl4-exampleGames 3 dl4-example
Games 3 dl4-example
 
Embed the nasa world wind java sdk in eclipse
Embed the nasa world wind java sdk in eclipseEmbed the nasa world wind java sdk in eclipse
Embed the nasa world wind java sdk in eclipse
 
CS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingCS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and Culling
 
Copy of repast javagettingstarted
Copy of repast javagettingstartedCopy of repast javagettingstarted
Copy of repast javagettingstarted
 
CS 354 Object Viewing and Representation
CS 354 Object Viewing and RepresentationCS 354 Object Viewing and Representation
CS 354 Object Viewing and Representation
 
CSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docx
CSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docxCSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docx
CSC139 Chapter 10 Lab Assignment (2)PolymorphismObjectivesIn.docx
 
Java design patterns
Java design patternsJava design patterns
Java design patterns
 
Structural pattern 3
Structural pattern 3Structural pattern 3
Structural pattern 3
 
Creating Custom Charts With Ruby Vector Graphics
Creating Custom Charts With Ruby Vector GraphicsCreating Custom Charts With Ruby Vector Graphics
Creating Custom Charts With Ruby Vector Graphics
 
Java Graphics
Java GraphicsJava Graphics
Java Graphics
 
Advanced Game Development with the Mobile 3D Graphics API
Advanced Game Development with the Mobile 3D Graphics APIAdvanced Game Development with the Mobile 3D Graphics API
Advanced Game Development with the Mobile 3D Graphics API
 
Graphics, Threads and HTTPConnections in MIDLets
Graphics, Threads and HTTPConnections in MIDLetsGraphics, Threads and HTTPConnections in MIDLets
Graphics, Threads and HTTPConnections in MIDLets
 
Gdc09 Minigames
Gdc09 MinigamesGdc09 Minigames
Gdc09 Minigames
 
openFrameworks 007 - 3D
openFrameworks 007 - 3DopenFrameworks 007 - 3D
openFrameworks 007 - 3D
 
World wind java sdk in progess
World wind java sdk in progessWorld wind java sdk in progess
World wind java sdk in progess
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)
 
Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5
 
4759826-Java-Thread
4759826-Java-Thread4759826-Java-Thread
4759826-Java-Thread
 

Más de Jay Thakkar

Memory error-talk
Memory error-talkMemory error-talk
Memory error-talkJay Thakkar
 
Exploring-javafx-3d
Exploring-javafx-3dExploring-javafx-3d
Exploring-javafx-3dJay Thakkar
 
O pening Files w ith LOCI Bio - Formats
O pening Files w ith LOCI Bio - FormatsO pening Files w ith LOCI Bio - Formats
O pening Files w ith LOCI Bio - FormatsJay Thakkar
 
Talk 8-Kevin-Imagej2
Talk 8-Kevin-Imagej2 Talk 8-Kevin-Imagej2
Talk 8-Kevin-Imagej2 Jay Thakkar
 
Basic image processing
Basic image processingBasic image processing
Basic image processingJay Thakkar
 
Architectural Design
Architectural DesignArchitectural Design
Architectural DesignJay Thakkar
 
Dicom standard-of-china 2011-03
Dicom standard-of-china 2011-03Dicom standard-of-china 2011-03
Dicom standard-of-china 2011-03Jay Thakkar
 

Más de Jay Thakkar (8)

Memory error-talk
Memory error-talkMemory error-talk
Memory error-talk
 
Mongo db m101j
Mongo db m101jMongo db m101j
Mongo db m101j
 
Exploring-javafx-3d
Exploring-javafx-3dExploring-javafx-3d
Exploring-javafx-3d
 
O pening Files w ith LOCI Bio - Formats
O pening Files w ith LOCI Bio - FormatsO pening Files w ith LOCI Bio - Formats
O pening Files w ith LOCI Bio - Formats
 
Talk 8-Kevin-Imagej2
Talk 8-Kevin-Imagej2 Talk 8-Kevin-Imagej2
Talk 8-Kevin-Imagej2
 
Basic image processing
Basic image processingBasic image processing
Basic image processing
 
Architectural Design
Architectural DesignArchitectural Design
Architectural Design
 
Dicom standard-of-china 2011-03
Dicom standard-of-china 2011-03Dicom standard-of-china 2011-03
Dicom standard-of-china 2011-03
 

Último

Single or Multiple melodic lines structure
Single or Multiple melodic lines structureSingle or Multiple melodic lines structure
Single or Multiple melodic lines structuredhanjurrannsibayan2
 
Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)Jisc
 
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Pooja Bhuva
 
Micro-Scholarship, What it is, How can it help me.pdf
Micro-Scholarship, What it is, How can it help me.pdfMicro-Scholarship, What it is, How can it help me.pdf
Micro-Scholarship, What it is, How can it help me.pdfPoh-Sun Goh
 
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptxHMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptxmarlenawright1
 
The basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptxThe basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptxheathfieldcps1
 
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfUnit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfDr Vijay Vishwakarma
 
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...Amil baba
 
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...ZurliaSoop
 
On National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan FellowsOn National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan FellowsMebane Rash
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxRamakrishna Reddy Bijjam
 
Google Gemini An AI Revolution in Education.pptx
Google Gemini An AI Revolution in Education.pptxGoogle Gemini An AI Revolution in Education.pptx
Google Gemini An AI Revolution in Education.pptxDr. Sarita Anand
 
Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxJisc
 
Plant propagation: Sexual and Asexual propapagation.pptx
Plant propagation: Sexual and Asexual propapagation.pptxPlant propagation: Sexual and Asexual propapagation.pptx
Plant propagation: Sexual and Asexual propapagation.pptxUmeshTimilsina1
 
Application orientated numerical on hev.ppt
Application orientated numerical on hev.pptApplication orientated numerical on hev.ppt
Application orientated numerical on hev.pptRamjanShidvankar
 
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptxMaritesTamaniVerdade
 
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdfUGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdfNirmal Dwivedi
 
This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.christianmathematics
 
Food safety_Challenges food safety laboratories_.pdf
Food safety_Challenges food safety laboratories_.pdfFood safety_Challenges food safety laboratories_.pdf
Food safety_Challenges food safety laboratories_.pdfSherif Taha
 

Último (20)

Single or Multiple melodic lines structure
Single or Multiple melodic lines structureSingle or Multiple melodic lines structure
Single or Multiple melodic lines structure
 
Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)Jamworks pilot and AI at Jisc (20/03/2024)
Jamworks pilot and AI at Jisc (20/03/2024)
 
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
Sensory_Experience_and_Emotional_Resonance_in_Gabriel_Okaras_The_Piano_and_Th...
 
Micro-Scholarship, What it is, How can it help me.pdf
Micro-Scholarship, What it is, How can it help me.pdfMicro-Scholarship, What it is, How can it help me.pdf
Micro-Scholarship, What it is, How can it help me.pdf
 
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptxHMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
HMCS Vancouver Pre-Deployment Brief - May 2024 (Web Version).pptx
 
The basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptxThe basics of sentences session 3pptx.pptx
The basics of sentences session 3pptx.pptx
 
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdfUnit 3 Emotional Intelligence and Spiritual Intelligence.pdf
Unit 3 Emotional Intelligence and Spiritual Intelligence.pdf
 
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
NO1 Top Black Magic Specialist In Lahore Black magic In Pakistan Kala Ilam Ex...
 
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Hongkong ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
 
On National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan FellowsOn National Teacher Day, meet the 2024-25 Kenan Fellows
On National Teacher Day, meet the 2024-25 Kenan Fellows
 
Python Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docxPython Notes for mca i year students osmania university.docx
Python Notes for mca i year students osmania university.docx
 
Google Gemini An AI Revolution in Education.pptx
Google Gemini An AI Revolution in Education.pptxGoogle Gemini An AI Revolution in Education.pptx
Google Gemini An AI Revolution in Education.pptx
 
Towards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptxTowards a code of practice for AI in AT.pptx
Towards a code of practice for AI in AT.pptx
 
Plant propagation: Sexual and Asexual propapagation.pptx
Plant propagation: Sexual and Asexual propapagation.pptxPlant propagation: Sexual and Asexual propapagation.pptx
Plant propagation: Sexual and Asexual propapagation.pptx
 
Application orientated numerical on hev.ppt
Application orientated numerical on hev.pptApplication orientated numerical on hev.ppt
Application orientated numerical on hev.ppt
 
Mehran University Newsletter Vol-X, Issue-I, 2024
Mehran University Newsletter Vol-X, Issue-I, 2024Mehran University Newsletter Vol-X, Issue-I, 2024
Mehran University Newsletter Vol-X, Issue-I, 2024
 
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
2024-NATIONAL-LEARNING-CAMP-AND-OTHER.pptx
 
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdfUGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
UGC NET Paper 1 Mathematical Reasoning & Aptitude.pdf
 
This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.This PowerPoint helps students to consider the concept of infinity.
This PowerPoint helps students to consider the concept of infinity.
 
Food safety_Challenges food safety laboratories_.pdf
Food safety_Challenges food safety laboratories_.pdfFood safety_Challenges food safety laboratories_.pdf
Food safety_Challenges food safety laboratories_.pdf
 

Learn Java 3D

  • 1. The Joy of Java 3D by Greg Hopkins Copyright © 2001-2007 Introduction Java 3D is an addition to Java for displaying three-dimensional graphics. Programs written in Java 3D can be run on several different types of computer and over the internet. The Java 3D class library provides a simpler interface than most other graphics libraries, but has enough capabilities to produce good games and animation. Java 3D builds on existing technology such as DirectX and OpenGL so the programs do not run as slowly as you might expect. Also, Java 3D can incorporate objects created by 3D modeling packages like TrueSpace and VRML models. This tutorial is an introduction to Java 3D. Examples lead you through the basic methods for producing 3D images and animation. You do not need to have any knowledge of 3D graphics or Java 3D to learn from this tutorial, but it will help if you have a basic understanding of the Java programming language. Programming in three dimensions can seem complicated because of the amount of jargon and the mathematics involved, this tutorial will keep things as simple as possible. Please help to improve this tutorial for future readers by reporting any mistakes you find or suggesting improvements to editor@java3d.org. Installing and Running Java 3D The software you need to use Java 3D is available free from Sun Microsystems at http://java.sun.com/. Sun often releases new versions so it is better to look at their site than rely on this document to find what you need. You will have to register as a member of "Java Developer Connection" to download some of the files. At time of writing, the newest version of Java (6.3) is at http://java.sun.com/javase/downloads/index.jsp. The current version of the Java 3D extension (1.5.1) is at https://java3d.dev.java.net/#Downloads Netscape and Internet Explorer both require you to download plug-ins if you want to use up-to-date versions of Java and Java3D in applets, the plug-in can be found at http://java.sun.com/products/plugin/. Once you have installed Java and Java 3D you can compile programs using the command: javac FileName.java And run them using: java FileName The FileName should always be the same as the name of the public class defined in that file. In some versions of Java 3D you may get a message about a null graphics configuration, but you can just ignore this. 1
  • 2. Getting Started – Your First Program The following program shows you the basic steps needed to display 3D objects. 1. 2. 3. 4. 5. Create a virtual universe to contain your scene. Create a data structure to contain a group of objects. Add an object to the group Position the viewer so that they are looking at the object Add the group of objects to the universe Look at the Hello3d() constructor and you will see the five lines that perform each of these steps. The program displays a glowing cube, the viewer is looking directly at the red face of the cube, so what you actually see is a red square on a black background import import import import com.sun.j3d.utils.universe.SimpleUniverse; com.sun.j3d.utils.geometry.ColorCube; com.sun.j3d.utils.geometry.Sphere; javax.media.j3d.BranchGroup; public class Hello3d { public Hello3d() { SimpleUniverse universe = new SimpleUniverse(); BranchGroup group = new BranchGroup(); group.addChild(new ColorCube(0.3)); universe.getViewingPlatform().setNominalViewingTransform(); universe.addBranchGraph(group); } public static void main( String[] args ) { new Hello3d(); } } // end of class Hello3d The import statements at the beginning of this program use various parts of Java 3D, so compiling and running this program is a good test that you have installed Java 3D correctly. 2
  • 3. Lighting up the World OK, the first example was a good start, but was it 3D? If you don’t think a square qualifies as three-dimensional, you are going to need to add some lights to your universe. The way the light falls on an object provides us with the shading that helps us see shapes in three dimensions The next example illustrates how to display a ball lit by a red light: import import import import com.sun.j3d.utils.geometry.*; com.sun.j3d.utils.universe.*; javax.media.j3d.*; javax.vecmath.*; public class Ball { public Ball() { // Create the universe SimpleUniverse universe = new SimpleUniverse(); // Create a structure to contain objects BranchGroup group = new BranchGroup(); // Create a ball and add it to the group of objects Sphere sphere = new Sphere(0.5f); group.addChild(sphere); // Create a red light that shines for 100m from the origin Color3f light1Color = new Color3f(1.8f, 0.1f, 0.1f); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f); DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); light1.setInfluencingBounds(bounds); group.addChild(light1); // look towards the ball universe.getViewingPlatform().setNominalViewingTransform(); // add the group of objects to the Universe universe.addBranchGraph(group); } public static void main(String[] args) { new Ball(); } } The sphere we created is white (the default), it appears red because of the colored light. Since it is a DirectionalLight, we also have to specify how far the light shines and in what direction. In the example, the light shines for 100 meters from the origin and the direction is to the right, down and into the screen (this is defined by the vector: 4.0 right, -7.0 down, and -12.0 into the screen). You can also create an AmbientLight which will produce a directionless light, or a SpotLight if you want to focus on a particular part of your scene. A combination of a strong directional light and a weaker ambient light gives a natural-looking appearance to your scene. Java 3D lights do not produce shadows. 3
  • 4. Positioning the Objects So far, the examples have created objects in the same place, the center of the universe. In Java 3D, locations are described by using x, y, z coordinates. Increasing coordinates go along the x-axis to the right, along the y-axis upwards, and along the z-axis out of the screen. In the picture, x, y and z are represented by spheres, cones and cylinders. This is called a “right-handed” coordinate system because the thumb and first two fingers of your right hand can be used to represent the three directions. All the distances are measured in meters. To place your objects in the scene, you start at point (0,0,0), and then move the objects wherever you want. Moving the objects is called a “transformation”, so the classes you use are: TransformGroup and Transform3D. You add both the object and the Transform3D to a TransformGroup before adding the TransformGroup to the rest of your scene. Step 1. Create a transform, a transform group and an object 2. 3. 4. 5. Specify a location for the object Set the transform to move (translate) the object to that location Add the transform to the transform group Add the object to the transform group Example Transform transform= new Transform3D(); TransformGroup tg = new TransformGroup(); Cone cone = new Cone(0.5f, 0.5f); Vector3f vector = new Vector3f(-.2f,.1f , -.4f); transform.setTranslation(vector); tg.setTransform(transform); tg.addChild(cone); This may seem complicated, but the transform groups enable you to collect objects together and move them as one unit. For example, a table could be made up of cylinders for legs and a box for the top. If you add all the parts of the table to a single transform group, you can move the whole table with one translation. The Transform3D class can do much more than specifying the co-ordinates of the object. The functions include setScale to change the size of an object and rotX, rotY and rotZ for rotating an object around each axis (counter clockwise). This example displays the different objects on each axis. import import import import com.sun.j3d.utils.geometry.*; com.sun.j3d.utils.universe.*; javax.media.j3d.*; javax.vecmath.*; public class Position { public Position() { SimpleUniverse universe = new SimpleUniverse(); BranchGroup group = new BranchGroup(); // X axis made of spheres for (float x = -1.0f; x <= 1.0f; x = x + 0.1f) { Sphere sphere = new Sphere(0.05f); TransformGroup tg = new TransformGroup(); Transform3D transform = new Transform3D(); 4
  • 5. Vector3f vector = new Vector3f( x, .0f, .0f); transform.setTranslation(vector); tg.setTransform(transform); tg.addChild(sphere); group.addChild(tg); } // Y axis made of cones for (float y = -1.0f; y <= 1.0f; y = y + 0.1f) { TransformGroup tg = new TransformGroup(); Transform3D transform = new Transform3D(); Cone cone = new Cone(0.05f, 0.1f); Vector3f vector = new Vector3f(.0f, y, .0f); transform.setTranslation(vector); tg.setTransform(transform); tg.addChild(cone); group.addChild(tg); } // Z axis made of cylinders for (float z = -1.0f; z <= 1.0f; z = z+ 0.1f) { TransformGroup tg = new TransformGroup(); Transform3D transform = new Transform3D(); Cylinder cylinder = new Cylinder(0.05f, 0.1f); Vector3f vector = new Vector3f(.0f, .0f, z); transform.setTranslation(vector); tg.setTransform(transform); tg.addChild(cylinder); group.addChild(tg); } Color3f light1Color = new Color3f(.1f, 1.4f, .1f); // green light BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f); DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); light1.setInfluencingBounds(bounds); group.addChild(light1); universe.getViewingPlatform().setNominalViewingTransform(); // add the group of objects to the Universe universe.addBranchGraph(group); } public static void main(String[] args) { new Position(); } } 5
  • 6. Appearance Is Everything There are many ways to change the way that objects in your scene look. You can change their color, how much light they reflect. You can paint them with two-dimensional images, or add rough textures to their surfaces. The Appearance class contains the functions for making these changes. This section shows you how to use these functions. The simplest way of setting the appearance is by specifying only the color and the shading method. This works for setting an object to being a simple color, but to make an object look realistic, you need to specify how an object appears under lights. You do this by creating a Material. Step 1. Create an object 2. Create an appearance 3. Create a color 4. Create the coloring attributes 5. 6. Add the attributes to the appearance Set the appearance for the object Example Sphere sphere = new Sphere(); Appearance ap = new Appearance(); Color3f col = new Color3f(0.0f, 0.0f, 1.0f); ColoringAttributes ca = new ColoringAttributes (col, ColoringAttributes.NICEST); ap.setColoringAttributes(ca); sphere.setAppearance(ap); Materials Materials have five properties that enable you to specify how the object appears. There are four colors: Ambient, Emissive, Diffuse, and Specular. The fifth property is shininess, that you specify with a number. Each color specifies what light is given off in a certain situation. • • • • Ambient color reflects light that been scattered so much by the environment that the direction is impossible to determine. This is created by an AmbientLight in Java 3D. Emissive color is given off even in darkness. You could use this for a neon sign or a glow-in-the-dark object Diffuse color reflects light that comes from one direction, so it's brighter if it comes squarely down on a surface that if it barely glances off the surface. This is used with a DirectionalLight. Specular light comes from a particular direction, and it tends to bounce off the surface in a preferred direction. Shiny metal or plastic have a high specular component. The amount of specular light that reaches the viewer depends on the location of the viewer and the angle of the light bouncing off the object. Changing the shininess factor affects not just how shiny the object is, but whether it shines with a small glint in one area, or a larger area with less of a gleaming look. For most objects you can use one color for both Ambient and Diffuse components, and black for Emissive (most things don’t glow in the dark). If it’s a shiny object, you would use a lighter color for Specular reflections. For example, the material for a red billiard ball might be: // billiard ball // ambient emissive diffuse specular shininess // Material mat = new Material(red, black, red, white, 70f); 6
  • 7. For a rubber ball, you could use a black or red specular light instead of white which would make the ball appear less shiny. Reducing the shininess factor from 70 to 0 would not work the way you might expect, it would spread the white reflection across the whole object instead of it being concentrated in one spot. Texture Materials make change the appearance of a whole shape, but sometimes even the shiniest objects can seem dull. By adding texture you can produce more interesting effects like marbling or wrapping a twodimensional image around your object. The TextureLoader class enables you to load an image to use as a texture. The dimensions of your image must be powers of two, for example 128 pixels by 256. When you load the texture you can also specify how you want to use the image. For example, RGB to use the color of the image or LUMINANCE to see the image in black and white. After the texture is loaded, you can change the TextureAttributes to say whether you want the image to replace the object underneath or modulate the underlying color. You can also apply it as a decal or blend the image with the color of your choice. If you are using a simple object like a sphere then you will also have to enable texturing by setting the “primitive flags”. These can be set to Primitive.GENERATE_NORMALS + Primitive.GENERATE_TEXTURE_COORDS when you create the object. In case this is starting to sound a bit complicated, here is an example. You can experiment with the texture settings in this example and compare the results. You can download the picture I used from http://www.java3d.org/Arizona.jpg or you can substitute a picture of your own. import import import import import import com.sun.j3d.utils.geometry.*; com.sun.j3d.utils.universe.*; com.sun.j3d.utils.image.*; javax.media.j3d.*; javax.vecmath.*; java.awt.Container; public class PictureBall { public PictureBall() { // Create the universe SimpleUniverse universe = new SimpleUniverse(); // Create a structure to contain objects BranchGroup group = new BranchGroup(); // Set up colors Color3f black = new Color3f(0.0f, 0.0f, 0.0f); Color3f white = new Color3f(1.0f, 1.0f, 1.0f); Color3f red = new Color3f(0.7f, .15f, .15f); // Set up the texture map TextureLoader loader = new TextureLoader("K:3dArizona.jpg", "LUMINANCE", new Container()); Texture texture = loader.getTexture(); texture.setBoundaryModeS(Texture.WRAP); texture.setBoundaryModeT(Texture.WRAP); 7
  • 8. texture.setBoundaryColor( new Color4f( 0.0f, 1.0f, 0.0f, 0.0f ) ); // Set up the texture attributes //could be REPLACE, BLEND or DECAL instead of MODULATE TextureAttributes texAttr = new TextureAttributes(); texAttr.setTextureMode(TextureAttributes.MODULATE); Appearance ap = new Appearance(); ap.setTexture(texture); ap.setTextureAttributes(texAttr); //set up the material ap.setMaterial(new Material(red, black, red, black, 1.0f)); // Create a ball to demonstrate textures int primflags = Primitive.GENERATE_NORMALS + Primitive.GENERATE_TEXTURE_COORDS; Sphere sphere = new Sphere(0.5f, primflags, ap); group.addChild(sphere); // Create lights Color3f light1Color = new Color3f(1f, 1f, 1f); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f); DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); light1.setInfluencingBounds(bounds); group.addChild(light1); AmbientLight ambientLight = new AmbientLight(new Color3f(.5f,.5f,.5f)); ambientLight.setInfluencingBounds(bounds); group.addChild(ambientLight); // look towards the ball universe.getViewingPlatform().setNominalViewingTransform(); // add the group of objects to the Universe universe.addBranchGraph(group); } public static void main(String[] args) { new PictureBall(); } } You can also set up three-dimensional textures, using shapes instead of a flat image. Unfortunately, these do not currently work very well across different platforms. Special Effects Look at the AppearanceTest example that comes with Java 3D for more effects you can use. For example you can display objects as wire-frames, display only the corners of an object and so on. You can even make objects transparent, with the following settings: TransparencyAttributes t_attr = new TransparencyAttributes(TransparencyAttributes.BLENDED,0.5f, TransparencyAttributes.BLEND_SRC_ALPHA, TransparencyAttributes.BLEND_ONE); 8
  • 9. ap.setTransparencyAttributes( t_attr ); Java 3D and the User Interface Most real-life applications use a mixture of three dimensional and two-dimensional elements. This section describes how to combine your Java 3D with the rest of your program. Canvas3D Each area where three-dimensional graphics can be painted is called a Canvas3D. This is a rectangle that contains a view of the objects in your universe. You place the canvas inside a frame, then you create a universe to be displayed in the canvas. The following example shows how to create a canvas in a frame with labels at the top and bottom. The program can be run as either an applet or an application. import import import import import import import import import public com.sun.j3d.utils.universe.SimpleUniverse; com.sun.j3d.utils.geometry.ColorCube; javax.media.j3d.BranchGroup; javax.media.j3d.Canvas3D; java.awt.GraphicsConfiguration; java.awt.BorderLayout; java.awt.Label; java.applet.Applet; com.sun.j3d.utils.applet.MainFrame; class CanvasDemo extends Applet { public CanvasDemo() { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); Canvas3D canvas = new Canvas3D(config); add("North",new Label("This is the top")); add("Center", canvas); add("South",new Label("This is the bottom")); BranchGroup contents = new BranchGroup(); contents.addChild(new ColorCube(0.3)); SimpleUniverse universe = new SimpleUniverse(canvas); universe.getViewingPlatform().setNominalViewingTransform(); universe.addBranchGraph(contents); } public static void main( String[] args ) { CanvasDemo demo = new CanvasDemo(); new MainFrame(demo,400,400); } } Java 3D and Swing The Canvas3D takes advantage of your computer’s graphics card to increase performance. Unfortunately, this means that it does not mix very well with Sun’s swing user interface components. These components are called “lightweight” Lightweight components can be hidden by a Canvas3D even if they are supposed to be at the front. 9
  • 10. There are several solutions to this problem: • You can mix lightweight and heavyweight components on the same screen if you keep them in separate containers. • If you use Popup menus, a static function on JPopupMenu fixes the problem: setDefaultLightWeightPopupEnabled(false); • You can use the older AWT components instead of swing. 10
  • 11. Animation and Interaction – a Bouncing Ball To create animation you need to move the objects between each frame of animation. You can use a timer and move the 3D objects by a small amount each time. Also, you can modify the objects in other ways, the next example scales the ball so that it looks squashed at the bottom of each bounce. For interaction with the user, you can process keystrokes or clicks on buttons or other components. One thing to notice is that you have to tell Java3D you are going to move something by setting a capability. Otherwise, you will not be able to move anything once it has been drawn. TransformGroup objTrans = new TransformGroup(); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); The following example combines these techniques. You start it by clicking on the button, then the ball bounces up and down, and you can press a or s to move the ball left or right. import import import import import import import import import import java.applet.Applet; java.awt.*; java.awt.event.*; java.awt.event.WindowAdapter; com.sun.j3d.utils.applet.MainFrame; com.sun.j3d.utils.universe.*; javax.media.j3d.*; javax.vecmath.*; com.sun.j3d.utils.geometry.Sphere; javax.swing.Timer; public class BouncingBall extends Applet implements ActionListener, KeyListener { private Button go = new Button("Go"); private TransformGroup objTrans; private Transform3D trans = new Transform3D(); private float height=0.0f; private float sign = 1.0f; // going up or down private Timer timer; private float xloc=0.0f; public BranchGroup createSceneGraph() { // Create the root of the branch graph BranchGroup objRoot = new BranchGroup(); objTrans = new TransformGroup(); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objRoot.addChild(objTrans); // Create a simple shape leaf node, add it to the scene graph. Sphere sphere = new Sphere(0.25f); objTrans = new TransformGroup(); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); Transform3D pos1 = new Transform3D(); pos1.setTranslation(new Vector3f(0.0f,0.0f,0.0f)); objTrans.setTransform(pos1); objTrans.addChild(sphere); objRoot.addChild(objTrans); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); 11
  • 12. Color3f light1Color = new Color3f(1.0f, 0.0f, 0.2f); Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f); DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); light1.setInfluencingBounds(bounds); objRoot.addChild(light1); // Set up the ambient light Color3f ambientColor = new Color3f(1.0f, 1.0f, 1.0f); AmbientLight ambientLightNode = new AmbientLight(ambientColor); ambientLightNode.setInfluencingBounds(bounds); objRoot.addChild(ambientLightNode); return objRoot; } public BouncingBall() { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); Canvas3D c = new Canvas3D(config); add("Center", c); c.addKeyListener(this); timer = new Timer(100,this); //timer.start(); Panel p =new Panel(); p.add(go); add("North",p); go.addActionListener(this); go.addKeyListener(this); // Create a simple scene and attach it to the virtual universe BranchGroup scene = createSceneGraph(); SimpleUniverse u = new SimpleUniverse(c); u.getViewingPlatform().setNominalViewingTransform(); u.addBranchGraph(scene); } public void keyPressed(KeyEvent e) { //Invoked when a key has been pressed. if (e.getKeyChar()=='s') {xloc = xloc + .1f;} if (e.getKeyChar()=='a') {xloc = xloc - .1f;} } public void keyReleased(KeyEvent e){ // Invoked when a key has been released. } public void keyTyped(KeyEvent e){ //Invoked when a key has been typed. } public void actionPerformed(ActionEvent e ) { // start timer when button is pressed if (e.getSource()==go){ if (!timer.isRunning()) { timer.start(); } } 12
  • 13. else { height += .1 * sign; if (Math.abs(height *2) >= 1 ) sign = -1.0f * sign; if (height<-0.4f) { trans.setScale(new Vector3d(1.0, .8, 1.0)); } else { trans.setScale(new Vector3d(1.0, 1.0, 1.0)); } trans.setTranslation(new Vector3f(xloc,height,0.0f)); objTrans.setTransform(trans); } } public static void main(String[] args) { System.out.println("Program Started"); BouncingBall bb = new BouncingBall(); bb.addKeyListener(bb); MainFrame mf = new MainFrame(bb, 256, 256); } } 13
  • 14. Natural Selection Once you have created a 3D scene you may want to interact with the objects within it. A first step is to select an object with the mouse. The Java 3D picking classes help you to do this, you can use them in the following way: 1. Create a PickCanvas from the Canvas 3D and the BranchGroup you want to pick from. PickCanvas pickCanvas = new PickCanvas(canvas, group); 2. Set the pickCanvas to use the bounds of the object for picking. pickCanvas.setMode(PickCanvas.BOUNDS); 3. Handle the mouse event by extending MouseAdapter and listening for mouse events on the Canvas3D using canvas.addMouseListener(this). 4. Define the mouseClicked function so that the PickCanvas calls the PickClosest function to return the PickResult. 5. Call getNode on PickResult to find out more about the object that has been picked. Here is a complete example that displays two objects (a cube and a sphere). When you click the mouse it prints out the class name of the selected object. import com.sun.j3d.utils.picking.*; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.geometry.*; import javax.media.j3d.*; import javax.vecmath.*; import java.awt.event.*; import java.awt.*; public class Pick extends MouseAdapter { private PickCanvas pickCanvas; public Pick() { Frame frame = new Frame("Box and Sphere"); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); Canvas3D canvas = new Canvas3D(config); canvas.setSize(400, 400); SimpleUniverse universe = new SimpleUniverse(canvas); BranchGroup group = new BranchGroup(); // create a color cube Vector3f vector = new Vector3f(-0.3f, 0.0f, 0.0f); Transform3D transform = new Transform3D(); transform.setTranslation(vector); TransformGroup transformGroup = new TransformGroup(transform); ColorCube cube = new ColorCube(0.3); transformGroup.addChild(cube); group.addChild(transformGroup); //create a sphere Vector3f vector2 = new Vector3f(+0.3f, 0.0f, 0.0f); Transform3D transform2 = new Transform3D(); 14
  • 15. transform2.setTranslation(vector2); TransformGroup transformGroup2 = new TransformGroup(transform2); Appearance appearance = new Appearance(); appearance.setPolygonAttributes( new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_BACK,0.0f)); Sphere sphere = new Sphere(0.3f,appearance); transformGroup2.addChild(sphere); group.addChild(transformGroup2); universe.getViewingPlatform().setNominalViewingTransform(); universe.addBranchGraph(group); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent winEvent) { System.exit(0); } }); frame.add(canvas); pickCanvas = new PickCanvas(canvas, group); pickCanvas.setMode(PickCanvas.BOUNDS); canvas.addMouseListener(this); frame.pack(); frame.show(); } public static void main( String[] args ) { new Pick(); } public void mouseClicked(MouseEvent e) { pickCanvas.setShapeLocation(e); PickResult result = pickCanvas.pickClosest(); if (result == null) { System.out.println("Nothing picked"); } else { Primitive p = (Primitive)result.getNode(PickResult.PRIMITIVE); Shape3D s = (Shape3D)result.getNode(PickResult.SHAPE3D); if (p != null) { System.out.println(p.getClass().getName()); } else if (s != null) { System.out.println(s.getClass().getName()); } else{ System.out.println("null"); } } } } // end of class Pick More Accurate Picking The previous example shows the most basic form of picking, based on the bounds of the object. If you try the example and click near the sphere you can see that it isn't very accurate. If you imagine a box around the sphere and click anywhere within that box, the program will report that you have picked the sphere. This is because the box and the sphere both have the same bounds. If you need to be more accurate you need to use geometry picking. Change the line: pickCanvas.setMode(PickCanvas.BOUNDS); 15
  • 16. to pickCanvas.setMode(PickCanvas.GEOMETRY); Unfortunately, this is not the whole story. For geometry picking to work you need to set various capabilities on the objects in your scene. These capabilities are set to off by default so that applications that do not use advanced picking are not slowed down unnecessarily. To turn them on, use: node.setCapability(Node.ENABLE_PICK_REPORTING); PickTool.setCapabilities(node, PickTool.INTERSECT_FULL); If you set the capabilities on all the objects you have added to the scene, you may find that detailed picking still does not work. This is because objects may be made up of other objects. For example instead of setting them once for a cube, you may need to set the capabilities six times, once for each face. The easiest way to make sure that all parts of each object are pickable is to call the following function on BranchGroup of your scene: public void enablePicking(Node node) { node.setPickable(true); node.setCapability(Node.ENABLE_PICK_REPORTING); try { Group group = (Group) node; for (Enumeration e = group.getAllChildren(); e.hasMoreElements();) { enablePicking((Node)e.nextElement()); } } catch(ClassCastException e) { // if not a group node, there are no children so ignore exception } try { Shape3D shape = (Shape3D) node; PickTool.setCapabilities(node, PickTool.INTERSECT_FULL); for (Enumeration e = shape.getAllGeometries(); e.hasMoreElements();) { Geometry g = (Geometry)e.nextElement(); g.setCapability(g.ALLOW_INTERSECT); } } catch(ClassCastException e) { // not a Shape3D node ignore exception } } After all the capabilities are set you can use System.out.println on your pick result to find the full range of information available. You can also use PickAllSorted instead of PickClosest to pick more than one object at the same time. Pick Shapes So far the examples have picked objects using the default shape: an imaginary ray going from the viewer's eye position through the mouse pointer into infinity. Instead of a thin ray you can change the shape used for picking. For example, you might use a cylinder instead of a narrow ray to make picking points easier. A cone shaped area is an easy way to pick anything that a viewer can see. 16
  • 17. The setShape function on PickCanvas (and PickTool) can set the shape to a Cone, Cylinder, Point or Ray. Each of these shapes can either go on forever (a ray) or stop after a fixed distance (a segment), you can also pick based on a Bounds object. As well as setting the shape you can set the tolerance for the picking operation. This is the distance (in pixels) that your PickShape can miss the target object by and still select the object. Advanced Picking Picking can be used for more than just mouse selection. The pick shapes can be located anywhere and can be moved around within your scene. They can be used for collision detection or avoidance. For example, you could use a pick shape in front of a person to detect potential obstacles and stop them from bumping into things. If you were writing a pool game you could use a PickRaySegment to represent the pool cue and you could pick with BoundingSphere to detecting collisions between the balls. 17
  • 18. Of Mice and Men To be able to work with objects in Java 3D, it helps if you understand where the viewer and the mouse pointer are in the scene. For example we can create a cube that you can draw on; the mouse pointer represents the end of a pencil. To draw on the cube, we need to know where the mouse pointer touches a face of the cube. When the mouse is dragged, the mouse event in the mouseDragged callback gives us the x and y co-ordinates of the mouse pointer. The following code gets the location of the mouse in the image plate and then transforms it into the location in the virtual world. Point3d mousePos = new Point3d(); canvas.getPixelLocationInImagePlate(event.getX(), event.getY(), mousePos); Transform3D transform = new Transform3D(); canvas.getImagePlateToVworld(transform); transform.transform(mousePos); The eye position (actually the position of the top of the viewers nose – the center eye) can be transformed into virtual world co-ordinates in the same way. Point3d eyePos = new Point3d(); canvas.getCenterEyeInImagePlate(eyePos); transform.transform(eyePos); Now that we know the points where the eye and the mouse pointer are, we want to find where on the cube to draw. Let’s assume we want to draw on the front face of the cube. We can find where a line through these two points intersects with the face of the cube. For the front face of a unit cube at the origin, the corners are at: (.5, -.5, .5), (.5, .5, .5), (-.5, .5, .5), (-.5, -.5, .5). We only need three of them to define a plane and then a bit of vector mathematics to give us the point where a line from the eye to the mouse pointer hits the cube. Point3d Point3d Point3d Point3d p1 = new Point3d(.5, -.5, .5); p2 = new Point3d(.5, .5, .5); p3 = new Point3d(-.5, .5, .5); intersection = getIntersection(eyePos, mousePos, p1, p2, p3); 18
  • 19. /** * Returns the point where a line crosses a plane */ Point3d getIntersection(Point3d line1, Point3d line2, Point3d plane1, Point3d plane2, Point3d plane3) { Vector3d p1 = new Vector3d(plane1); Vector3d p2 = new Vector3d(plane2); Vector3d p3 = new Vector3d(plane3); Vector3d p2minusp1 = new Vector3d(p2); p2minusp1.sub(p1); Vector3d p3minusp1 = new Vector3d(p3); p3minusp1.sub(p1); Vector3d normal = new Vector3d(); normal.cross(p2minusp1, p3minusp1); // The plane can be defined by p1, n + d = 0 double d = -p1.dot(normal); Vector3d i1 = new Vector3d(line1); Vector3d direction = new Vector3d(line1); direction.sub(line2); double dot = direction.dot(normal); if (dot == 0) return null; double t = (-d - i1.dot(normal)) / (dot); Vector3d intersection = new Vector3d(line1); Vector3d scaledDirection = new Vector3d(direction); scaledDirection.scale(t); intersection.add(scaledDirection); Point3d intersectionPoint = new Point3d(intersection); return intersectionPoint; } Now we know where the intersection point is, it is easy to draw on an image that we can use as a texture on the cube. Remember that the y coordinate for the mouse gets higher as you move the mouse pointer down the screen. This has to be reversed to get to the y coordinate you are used to seeing on a graph. public void mouseDragged(MouseEvent event) { Point3d intersectionPoint = getPosition(event); if (Math.abs(intersectionPoint.x) < 0.5 && Math.abs(intersectionPoint.y) < 0.5) { double x = (0.5 + intersectionPoint.x) * imageWidth; double y = (0.5 - intersectionPoint.y) * imageHeight; Graphics2D g = (Graphics2D) frontImage.getGraphics(); g.setColor( Color.BLACK); g.setStroke(new BasicStroke(3)); int iX = (int)(x + .5); int iY = (int)(y + .5); if (lastX < 0) { lastX = iX; lastY = iY; } g.drawLine(lastX, lastY, iX, iY); lastX = iX; lastY = iY; changeTexture(texture, frontImage, frontShape); } 19
  • 20. Of course, the method I’ve explained so far assumes that the cube always stays in the same place. In a real application you are likely to have objects in different places and different orientations. Fortunately, it is easy to allow for this by transforming the points of the plane from the local to virtual world coordinates and then transforming the intersection point back to local coordinates at the end. Transform3D currentTransform = new Transform3D(); box.getLocalToVworld(currentTransform); currentTransform.transform(p1); currentTransform.transform(p2); currentTransform.transform(p3); Point3d intersection = getIntersection(eyePos, mousePos, p1, p2, p3); currentTransform.invert(); currentTransform.transform(intersection); Here’s an example that puts all these techniques together. It shows a cube with different colored faces. You can rotate the cube with the left mouse button, and draw on the front (blue) face with the right mouse button. import import import import import import import import import import import import import java.applet.Applet; java.awt.*; java.awt.event.*; java.awt.image.BufferedImage; javax.media.j3d.*; javax.vecmath.*; com.sun.j3d.utils.applet.MainFrame; com.sun.j3d.utils.behaviors.mouse.MouseRotate; com.sun.j3d.utils.geometry.*; com.sun.j3d.utils.image.TextureLoader; com.sun.j3d.utils.pickfast.PickCanvas; com.sun.j3d.utils.universe.SimpleUniverse; com.sun.j3d.utils.universe.ViewingPlatform; public class DrawingExample extends Applet implements MouseListener, MouseMotionListener { private private private private private private private private private private private private private private private private private private static final long serialVersionUID = 1L; MainFrame frame; Box box; int imageHeight = 256; int imageWidth = 256; Canvas3D canvas; SimpleUniverse universe; BranchGroup group = new BranchGroup(); PickCanvas pickCanvas; BufferedImage frontImage; Shape3D frontShape; Texture texture; Appearance appearance; TextureLoader loader; int lastX=-1; int lastY=-1; int mouseButton = 0; TransformGroup boxTransformGroup; 20
  • 21. public static void main(String[] args) { DrawingExample object = new DrawingExample(); object.frame = new MainFrame(object, args, object.imageWidth, object.imageHeight); object.startSheet(); object.validate(); } public Point3d getPosition(MouseEvent event) { Point3d eyePos = new Point3d(); Point3d mousePos = new Point3d(); canvas.getCenterEyeInImagePlate(eyePos); canvas.getPixelLocationInImagePlate(event.getX(), event.getY(), mousePos); Transform3D transform = new Transform3D(); canvas.getImagePlateToVworld(transform); transform.transform(eyePos); transform.transform(mousePos); Vector3d direction = new Vector3d(eyePos); direction.sub(mousePos); // three points on the plane Point3d p1 = new Point3d(.5, -.5, .5); Point3d p2 = new Point3d(.5, .5, .5); Point3d p3 = new Point3d(-.5, .5, .5); Transform3D currentTransform = new Transform3D(); box.getLocalToVworld(currentTransform); currentTransform.transform(p1); currentTransform.transform(p2); currentTransform.transform(p3); Point3d intersection = getIntersection(eyePos, mousePos, p1, p2, p3); currentTransform.invert(); currentTransform.transform(intersection); return intersection; } /** * Returns the point where a line crosses a plane */ Point3d getIntersection(Point3d line1, Point3d line2, Point3d plane1, Point3d plane2, Point3d plane3) { Vector3d p1 = new Vector3d(plane1); Vector3d p2 = new Vector3d(plane2); Vector3d p3 = new Vector3d(plane3); Vector3d p2minusp1 = new Vector3d(p2); p2minusp1.sub(p1); Vector3d p3minusp1 = new Vector3d(p3); p3minusp1.sub(p1); Vector3d normal = new Vector3d(); normal.cross(p2minusp1, p3minusp1); // The plane can be defined by p1, n + d = 0 double d = -p1.dot(normal); Vector3d i1 = new Vector3d(line1); Vector3d direction = new Vector3d(line1); direction.sub(line2); double dot = direction.dot(normal); 21
  • 22. if (dot == 0) return null; double t = (-d - i1.dot(normal)) / (dot); Vector3d intersection = new Vector3d(line1); Vector3d scaledDirection = new Vector3d(direction); scaledDirection.scale(t); intersection.add(scaledDirection); Point3d intersectionPoint = new Point3d(intersection); return intersectionPoint; } private void startSheet() { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse .getPreferredConfiguration(); canvas = new Canvas3D(config); universe = new SimpleUniverse(canvas); add("Center", canvas); positionViewer(); getScene(); universe.addBranchGraph(group); pickCanvas = new PickCanvas(canvas, group); pickCanvas.setMode(PickInfo.PICK_BOUNDS); canvas.addMouseMotionListener(this); frame.addMouseMotionListener(this); canvas.addMouseListener(this); frame.addMouseListener(this); } public void getScene() { addLights(group); Appearance ap = getAppearance(new Color3f(Color.blue)); ap.setCapability(Appearance.ALLOW_TEXTURE_WRITE); ap.setCapability(Appearance.ALLOW_TEXGEN_WRITE); box = new Box(.5f, .5f, .5f, Primitive.GENERATE_TEXTURE_COORDS, getAppearance(new Color3f(Color.green))); box.setCapability(Box.ENABLE_APPEARANCE_MODIFY); box.setCapability(Box.GEOMETRY_NOT_SHARED); frontShape = box.getShape(Box.FRONT); frontShape.setAppearance(ap); box.getShape(Box.TOP).setAppearance(getAppearance(Color.magenta)); box.getShape(Box.BOTTOM).setAppearance( getAppearance(Color.orange)); ; box.getShape(Box.RIGHT).setAppearance( getAppearance(Color.red)); box.getShape(Box.LEFT).setAppearance( getAppearance(Color.green)); box.getShape(Box.BACK).setAppearance( getAppearance(Color.yellow)); frontImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); 22
  • 23. Graphics2D g = (Graphics2D)frontImage.getGraphics(); g.setColor(new Color(70,70,140)); g.fillRect(0, 0, imageWidth, imageHeight); addTexture(frontImage, frontShape); MouseRotate behavior = new MouseRotate(); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0); boxTransformGroup = new TransformGroup(); boxTransformGroup .setCapability(TransformGroup.ALLOW_TRANSFORM_R EAD); boxTransformGroup .setCapability(TransformGroup.ALLOW_TRANSFORM_W RITE); behavior.setTransformGroup(boxTransformGroup); boxTransformGroup.addChild(behavior); behavior.setSchedulingBounds(bounds); boxTransformGroup.addChild(box); group.addChild(boxTransformGroup); } public void addTexture(BufferedImage image, Shape3D shape) { frontShape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE); appearance = shape.getAppearance(); appearance.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE); appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE); appearance.setCapability(Appearance.ALLOW_MATERIAL_WRITE); changeTexture( texture, image, shape); Color3f col = new Color3f(0.0f, 0.0f, 1.0f); ColoringAttributes ca = new ColoringAttributes(col, ColoringAttributes.NICEST); appearance.setColoringAttributes(ca); } public void changeTexture(Texture texture, BufferedImage image, Shape3D shape) { loader = new TextureLoader(image, "RGB", TextureLoader.ALLOW_NON_POWER_OF_TWO); texture = loader.getTexture(); texture.setBoundaryModeS(Texture.CLAMP_TO_BOUNDARY); texture.setBoundaryModeT(Texture.CLAMP_TO_BOUNDARY); texture.setBoundaryColor(new Color4f(0.0f, 1.0f, 0.5f, 0f)); // Set up the texture attributes // could be REPLACE, BLEND or DECAL instead of MODULATE 1.0f)); // front = getAppearance(new Color3f(Color.YELLOW)); Color3f black = new Color3f(0.0f, 0.0f, 0.0f); Color3f white = new Color3f(1.0f, 1.0f, 1.0f); Color3f red = new Color3f(0.7f, .15f, .15f); appearance.setMaterial(new Material(red, black, red, white, 23
  • 24. TextureAttributes texAttr = new TextureAttributes(); texAttr.setTextureMode(TextureAttributes.REPLACE); appearance.setTextureAttributes(texAttr); appearance.setTexture(texture); shape.setAppearance(appearance); } BufferedImage getStartingImage(int i, int width, int height) { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D)image.getGraphics(); g.setColor(new Color(70,70,140)); g.fillRect(0, 0, width, height); return image; } public void positionViewer() { ViewingPlatform vp = universe.getViewingPlatform(); TransformGroup tg1 = vp.getViewPlatformTransform(); Transform3D t3d = new Transform3D(); tg1.getTransform(t3d); vp.setNominalViewingTransform(); } public static void addLights(BranchGroup group) { Color3f light1Color = new Color3f(0.7f, 0.8f, 0.8f); BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); Vector3f light1Direction = new Vector3f(4.0f, -7.0f, -12.0f); DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction); light1.setInfluencingBounds(bounds); group.addChild(light1); AmbientLight light2 = new AmbientLight(new Color3f(0.3f, 0.3f, 0.3f)); light2.setInfluencingBounds(bounds); group.addChild(light2); } public static Appearance getAppearance(Color color) { return getAppearance(new Color3f(color)); } public static Appearance getAppearance(Color3f color) { Color3f black = new Color3f(0.0f, 0.0f, 0.0f); Color3f white = new Color3f(1.0f, 1.0f, 1.0f); Appearance ap = new Appearance(); Texture texture = new Texture2D(); TextureAttributes texAttr = new TextureAttributes(); texAttr.setTextureMode(TextureAttributes.MODULATE); texture.setBoundaryModeS(Texture.WRAP); texture.setBoundaryModeT(Texture.WRAP); 24
  • 25. 0.0f)); 70f); texture.setBoundaryColor(new Color4f(0.0f, 1.0f, 0.0f, Material mat = new Material(color, black, color, white, ap.setTextureAttributes(texAttr); ap.setMaterial(mat); ap.setTexture(texture); ColoringAttributes ca = new ColoringAttributes(color, ColoringAttributes.NICEST); ap.setColoringAttributes(ca); return ap; } @Override public void mouseClicked(MouseEvent arg0) { } @Override public void mouseEntered(MouseEvent arg0) { } @Override public void mouseExited(MouseEvent arg0) { } @Override public void mousePressed(MouseEvent event) { lastX=-1; lastY=-1; mouseButton = event.getButton(); } @Override public void mouseReleased(MouseEvent arg0) { } @Override public void mouseDragged(MouseEvent event) { if (mouseButton==MouseEvent.BUTTON1) return; Point3d intersectionPoint = getPosition(event); if (Math.abs(intersectionPoint.x) < 0.5 && Math.abs(intersectionPoint.y) < 0.5) { double x = (0.5 + intersectionPoint.x) * imageWidth; double y = (0.5 - intersectionPoint.y) * imageHeight; Graphics2D g = (Graphics2D) frontImage.getGraphics(); g.setColor( Color.BLACK); g.setStroke(new BasicStroke(3)); int iX = (int)(x + .5); int iY = (int)(y + .5); if (lastX < 0) { lastX = iX; lastY = iY; } g.drawLine(lastX, lastY, iX, iY); lastX = iX; lastY = iY; changeTexture(texture, frontImage, frontShape); 25
  • 27. Further Information I hope this tutorial has got you interested in programming with Java 3D. You should now know enough to program simple scenes, or games like the Pyramid game at http://www.fungames.org. There are several sources of information to help you learn more. Online Information • Java 3D comes with several useful examples, these are described at: http://www.java.sun.com/products/javamedia/3D/forDevelopers/J3D_1_2_API/j3dguide/AppendixExamples.html • Sun’s tutorial is at: http://java.sun.com/products/java-media/3D/collateral/ • The API documentation is at: http://java.sun.com/products/java-media/3D/forDevelopers/j3dapi/index.html • My site is at: http://www.java3d.org Books There the following books on Java 3D:: • Java 3D API Jump-Start, by Aaron E. Walsh and Doug Gehringer • Killer Game Programming in Java • 3D User Interfaces with Java 3D, by John Barrilleaux • Java 3D Programming, by Daniel Selman • The Java 3D API Specification (With CD-ROM), by Henry Sowizral, Kevin Rushforth, Michael Deering 27