Java3D Lights (Pyramid.java is same as Example2)

File: java3d/Lights/Main.java

import java.awt.*;
import javax.swing.*;

import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.keyboard.*;
import com.sun.j3d.utils.behaviors.vp.*;
import com.sun.j3d.utils.geometry.*;

/**
 * Example using lighting
 * R. Jacob  11/3/2006
 */
public class Main extends JFrame {
    public static void main (String[] args) {
	new Main();
    }

    public Main() {
	/*
	 * Here, we really need our own canvas, and our own JFrame,
	 * so we can put some Swing widgets around the edge
	 */
	setSize (500, 500);
	setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

	/*
	 * Set up SimpleUniverse, with our own Canvas3D
	 */
	Canvas3D canvas3D = new Canvas3D (SimpleUniverse.getPreferredConfiguration());
	SimpleUniverse universe = new SimpleUniverse (canvas3D);
	Scene scene = new Scene ();
	Lights lights = new Lights (scene);
	addKbdNavig (universe, scene);

	/*
	 * Install our scene graph
	 */
	scene.compile();
	universe.addBranchGraph (scene);

	/*
	 * Make a GUI layout in our JFrame,
	 * with the 3D canvas in the center
	 */
	Container content = getContentPane();
	content.setLayout (new BorderLayout());
	content.add (canvas3D, BorderLayout.CENTER);

	/*
	 * Our buttons, each is connected to one of the lights we
	 * created in Scene
	 */
	JPanel panel = new JPanel ();
	content.add (panel, BorderLayout.SOUTH);
	panel.add (new LightButton (lights.getMainLight(), "Main light"));
	panel.add (new LightButton (lights.getFillLight(), "Fill light"));
	panel.add (new LightButton (lights.getAmbientLight(), "Ambient light"));

	setVisible (true);
    }

    /*
     * Set up for keyboard navigation, as usual.
     */
    private void addKbdNavig (SimpleUniverse universe, BranchGroup scene) {
	KeyNavigatorBehavior kbdBehavior = new KeyNavigatorBehavior (
		universe.getViewingPlatform().getViewPlatformTransform());
	kbdBehavior.setSchedulingBounds (new BoundingSphere (new Point3d(), Float.MAX_VALUE));
	scene.addChild (kbdBehavior);
    }
}

File: java3d/Lights/Scene.java

import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.geometry.*;

import java.awt.Font;

/**
 * Create scene graph here.
 */
public class Scene extends BranchGroup {
    public Scene () {
	// Move to where we want the first object
	Transform3D translate = new Transform3D ();
	translate.setTranslation (new Vector3d (0.7, 0, -3.));

	TransformGroup objTranslate = new TransformGroup(translate);
	this.addChild(objTranslate);

	// Then we rotate it in X and Y
	Transform3D rotate = new Transform3D();
	rotate.rotX (Math.toRadians (45.));

	Transform3D tempRotate = new Transform3D();
	tempRotate.rotY (Math.toRadians (30.));

	rotate.mul(tempRotate);
	TransformGroup objRotate = new TransformGroup(rotate);
	objTranslate.addChild(objRotate);

	// Set up its appearance properties, for yellow
	Material mat = new Material ();
	mat.setDiffuseColor (1.f, 1.f, 0);
	mat.setAmbientColor (0.2f, 0.2f, 0);
	Appearance appearance = new Appearance();
	appearance.setMaterial (mat);

	// Add the Box
	// We request GENERATE_NORMALS so this object can be lit
	objRotate.addChild(new Box (0.1f, 0.3f, 0.1f, Box.GENERATE_NORMALS, appearance));

	// A red sphere, in a new location
	Transform3D translate2 = new Transform3D();	
	translate2.setTranslation (new Vector3d (-0.8, 0, -4.));
	TransformGroup objTranslate2 = new TransformGroup(translate2);	
	this.addChild (objTranslate2);

	// Set Appearance for red
	Material mat2 = new Material ();
	mat2.setDiffuseColor (1.f, 0, 0);
	mat2.setAmbientColor (0.3f, 0, 0);
	Appearance appearance2 = new Appearance();
	appearance2.setMaterial (mat2);

	// Add the sphere
	objTranslate2.addChild (new Sphere (0.3f, Sphere.GENERATE_NORMALS, appearance2));

	// A pyramid, in a third location
	Transform3D translate3 = new Transform3D();	
	translate3.setTranslation (new Vector3d (0, 0, -5.));
	TransformGroup objTranslate3 = new TransformGroup(translate3);	
	this.addChild (objTranslate3);

	// and rotated in Y
	Transform3D rotate3 = new Transform3D();
	rotate3.rotY (Math.toRadians (45.));
	TransformGroup objRotate3 = new TransformGroup (rotate3);	
	objTranslate3.addChild (objRotate3);

	// Set Appearance for green
	Material mat3 = new Material ();
	mat3.setDiffuseColor (0, 1.f, 0);
	mat3.setAmbientColor (0, 0.3f, 0);
	Appearance appearance3 = new Appearance();
	appearance3.setMaterial (mat3);

	// Add the pyramid, this time make it a separate class
	objRotate3.addChild (new Pyramid (appearance3));

	// A text label
	Transform3D translate4 = new Transform3D();	
	translate4.setTranslation (new Vector3d (0, 0.5, -3.));
	TransformGroup objTranslate4 = new TransformGroup(translate4);	
	this.addChild (objTranslate4);
	
	// Add the Text2D object
	Text2D label = new Text2D ("I am 2D text",
		new Color3f (1.f, 1.f, 1.f),
		"Helvetica", 24, Font.PLAIN);
	objTranslate4.addChild (label);
    }
}

File: java3d/Lights/Lights.java

import javax.media.j3d.*;
import javax.vecmath.*;

import com.sun.j3d.utils.geometry.*;

/**
 * An object to hold our lights, plugs them into given scene,
 * also sets up ivars mainLight, fillLight, and ambientLight
 *
 * Uses typical setup, like portrait or TV studio:
 * 	Main (key) light, directional, from 45 deg. user's right, above
 * 	Fill light, directional, from 45deg. user's left, dimmer
 */
public class Lights {
    // So main can get them to send to buttons
    private DirectionalLight mainLight;
    private DirectionalLight fillLight;
    private AmbientLight ambientLight;

    public Lights (Scene scene) {
	// Main light
	mainLight = new DirectionalLight (
		new Color3f (1.f, 1.f, 1.f),
		new Vector3f (-1.f, -0.5f, -1.f));
	mainLight.setInfluencingBounds (new BoundingSphere (new Point3d(), Float.MAX_VALUE));
	mainLight.setCapability(Light.ALLOW_STATE_WRITE);
        scene.addChild(mainLight);

	// Fill light
	fillLight = new DirectionalLight (
		new Color3f (.5f, .5f, .5f),
		new Vector3f (1.f, 0, -1.f));
	fillLight.setInfluencingBounds (new BoundingSphere (new Point3d(), Float.MAX_VALUE));
	fillLight.setCapability(Light.ALLOW_STATE_WRITE);
        scene.addChild(fillLight);

	// Ambient
	ambientLight = new AmbientLight ();
	ambientLight.setInfluencingBounds (new BoundingSphere (new Point3d(), Float.MAX_VALUE));
	ambientLight.setCapability(Light.ALLOW_STATE_WRITE);
	scene.addChild(ambientLight);
    }

    public Light getMainLight () {
	return mainLight;
    }

    public Light getFillLight () {
	return fillLight;
    }

    public Light getAmbientLight () {
	return ambientLight;
    }
}

File: java3d/Lights/LightButton.java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import javax.media.j3d.*;

public class LightButton extends JCheckBox implements ItemListener {
    private Light light;

    public LightButton (Light light, String label) {
	this.light = light;
	setText (label);
	setSelected (true);
	addItemListener (this);
    }

    /**
     * Note no need for repaint()
     * canvas updates from scene graph automatically
     * whenever scene graph data change
     */
    public void itemStateChanged (ItemEvent e) {
	light.setEnable (e.getStateChange()==ItemEvent.SELECTED);
    }
}