/*
* %Z%%M% %I% %E% %U%
*
* ************************************************************** "Copyright (c)
* 2001 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed,licensed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility."
*
* ***************************************************************************
*/
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.text.NumberFormat;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.ImageComponent;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.Material;
import javax.media.j3d.Screen3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class Human1 extends Applet implements ChangeListener, ActionListener {
SimpleUniverse u;
boolean isApplication;
Canvas3D canvas;
OffScreenCanvas3D offScreenCanvas;
View view;
// These names correspond to the H-Anim names
TransformGroup Human_body;
TransformGroup Human_r_shoulder;
TransformGroup Human_r_elbow;
TransformGroup Human_l_shoulder;
TransformGroup Human_l_elbow;
TransformGroup Human_skullbase;
// these set up the transformations
int rShoulderRot = 0;
AxisAngle4f rShoulderAA = new AxisAngle4f(0.0f, 0.0f, -1.0f, 0.0f);
JSlider rShoulderSlider;
JLabel rShoulderSliderLabel;
int rElbowRot = 0;
AxisAngle4f rElbowAA = new AxisAngle4f(0.0f, 0.0f, -1.0f, 0.0f);
JSlider rElbowSlider;
JLabel rElbowSliderLabel;
int lShoulderRot = 0;
AxisAngle4f lShoulderAA = new AxisAngle4f(0.0f, 0.0f, 1.0f, 0.0f);
JSlider lShoulderSlider;
JLabel lShoulderSliderLabel;
int lElbowRot = 0;
AxisAngle4f lElbowAA = new AxisAngle4f(0.0f, 0.0f, 1.0f, 0.0f);
JSlider lElbowSlider;
JLabel lElbowSliderLabel;
String snapImageString = "Snap Image";
String outFileBase = "human";
int outFileSeq = 0;
float offScreenScale = 1.5f;
// GUI elements
JTabbedPane tabbedPane;
// Temporaries that are reused
Transform3D tmpTrans = new Transform3D();
Vector3f tmpVector = new Vector3f();
AxisAngle4f tmpAxisAngle = new AxisAngle4f();
// These will be created, attached the scene graph and then the variable
// will be reused to initialize other sections of the scene graph.
Cylinder tmpCyl;
Sphere tmpSphere;
TransformGroup tmpTG;
// colors for use in the cones
Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
// geometric constant
Point3f origin = new Point3f();
Vector3f yAxis = new Vector3f(0.0f, 1.0f, 0.0f);
// NumberFormat to print out floats with only two digits
NumberFormat nf;
// Returns the TransformGroup we will be editing to change the tranform
// on the cone
void createHuman() {
Human_body = new TransformGroup();
// center the body
tmpVector.set(0.0f, -1.5f, 0.0f);
tmpTrans.set(tmpVector);
Human_body.setTransform(tmpTrans);
// Set up an appearance to make the body with red ambient,
// black emmissive, red diffuse and white specular coloring
Material material = new Material(red, black, red, white, 64);
Appearance appearance = new Appearance();
appearance.setMaterial(material);
// offset and place the cylinder for the body
tmpTG = new TransformGroup();
// offset the shape
tmpVector.set(0.0f, 1.5f, 0.0f);
tmpTrans.set(tmpVector);
tmpTG.setTransform(tmpTrans);
tmpCyl = new Cylinder(0.75f, 3.0f, appearance);
tmpTG.addChild(tmpCyl);
// add the shape to the body
Human_body.addChild(tmpTG);
// create the r_shoulder TransformGroup
Human_r_shoulder = new TransformGroup();
Human_r_shoulder.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
Human_r_shoulder.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
// translate from the waist
tmpVector.set(-0.95f, 2.9f, -0.2f);
tmpTrans.set(tmpVector);
Human_r_shoulder.setTransform(tmpTrans);
// place the sphere for the r_shoulder
tmpSphere = new Sphere(0.22f, appearance);
Human_r_shoulder.addChild(tmpSphere);
// offset and place the cylinder for the r_shoulder
tmpTG = new TransformGroup();
// offset the shape
tmpVector.set(0.0f, -0.5f, 0.0f);
tmpTrans.set(tmpVector);
tmpTG.setTransform(tmpTrans);
tmpCyl = new Cylinder(0.2f, 1.0f, appearance);
tmpTG.addChild(tmpCyl);
// add the shape to the r_shoulder
Human_r_shoulder.addChild(tmpTG);
// add the shoulder to the body group
Human_body.addChild(Human_r_shoulder);
// create the r_elbow TransformGroup
Human_r_elbow = new TransformGroup();
Human_r_elbow.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
Human_r_elbow.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
tmpVector.set(0.0f, -1.054f, 0.0f);
tmpTrans.set(tmpVector);
Human_r_elbow.setTransform(tmpTrans);
// place the sphere for the r_elbow
tmpSphere = new Sphere(0.22f, appearance);
Human_r_elbow.addChild(tmpSphere);
// offset and place the cylinder for the r_shoulder
tmpTG = new TransformGroup();
// offset the shape
tmpVector.set(0.0f, -0.5f, 0.0f);
tmpTrans.set(tmpVector);
tmpTG.setTransform(tmpTrans);
tmpCyl = new Cylinder(0.2f, 1.0f, appearance);
tmpTG.addChild(tmpCyl);
// add the shape to the r_shoulder
Human_r_elbow.addChild(tmpTG);
// add the elbow to the shoulder group
Human_r_shoulder.addChild(Human_r_elbow);
// create the l_shoulder TransformGroup
Human_l_shoulder = new TransformGroup();
Human_l_shoulder.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
Human_l_shoulder.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
tmpVector.set(0.95f, 2.9f, -0.2f);
tmpTrans.set(tmpVector);
Human_l_shoulder.setTransform(tmpTrans);
// place the sphere for the l_shoulder
tmpSphere = new Sphere(0.22f, appearance);
Human_l_shoulder.addChild(tmpSphere);
// offset and place the cylinder for the l_shoulder
tmpTG = new TransformGroup();
// offset the shape
tmpVector.set(0.0f, -0.5f, 0.0f);
tmpTrans.set(tmpVector);
tmpTG.setTransform(tmpTrans);
tmpCyl = new Cylinder(0.2f, 1.0f, appearance);
tmpTG.addChild(tmpCyl);
// add the shape to the l_shoulder
Human_l_shoulder.addChild(tmpTG);
// add the shoulder to the body group
Human_body.addChild(Human_l_shoulder);
// create the r_elbow TransformGroup
Human_l_elbow = new TransformGroup();
Human_l_elbow.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
Human_l_elbow.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
tmpVector.set(0.0f, -1.054f, 0.0f);
tmpTrans.set(tmpVector);
Human_l_elbow.setTransform(tmpTrans);
// place the sphere for the l_elbow
tmpSphere = new Sphere(0.22f, appearance);
Human_l_elbow.addChild(tmpSphere);
// offset and place the cylinder for the l_elbow
tmpTG = new TransformGroup();
// offset the shape
tmpVector.set(0.0f, -0.5f, 0.0f);
tmpTrans.set(tmpVector);
tmpTG.setTransform(tmpTrans);
tmpCyl = new Cylinder(0.2f, 1.0f, appearance);
tmpTG.addChild(tmpCyl);
// add the shape to the l_elbow
Human_l_elbow.addChild(tmpTG);
// add the shoulder to the body group
Human_l_shoulder.addChild(Human_l_elbow);
// create the skullbase TransformGroup
Human_skullbase = new TransformGroup();
tmpVector.set(0.0f, 3.632f, 0.0f);
tmpTrans.set(tmpVector);
Human_skullbase.setTransform(tmpTrans);
// offset and place the sphere for the skull
tmpSphere = new Sphere(0.5f, appearance);
// add the shape to the l_shoulder
Human_skullbase.addChild(tmpSphere);
// add the shoulder to the body group
Human_body.addChild(Human_skullbase);
}
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
Object source = e.getSource();
if (action == snapImageString) {
Point loc = canvas.getLocationOnScreen();
offScreenCanvas.setOffScreenLocation(loc);
Dimension dim = canvas.getSize();
dim.width *= offScreenScale;
dim.height *= offScreenScale;
nf.setMinimumIntegerDigits(3);
offScreenCanvas.snapImageFile(
outFileBase + nf.format(outFileSeq++), dim.width,
dim.height);
nf.setMinimumIntegerDigits(0);
}
}
public void setRShoulderRot(int rotation) {
rShoulderRot = rotation;
rShoulderAA.angle = (float) Math.toRadians(rShoulderRot);
Human_r_shoulder.getTransform(tmpTrans);
tmpTrans.setRotation(rShoulderAA);
Human_r_shoulder.setTransform(tmpTrans);
}
public void setRElbowRot(int rotation) {
float angle = (float) Math.toRadians(rotation);
rElbowRot = rotation;
rElbowAA.angle = (float) Math.toRadians(rElbowRot);
Human_r_elbow.getTransform(tmpTrans);
tmpTrans.setRotation(rElbowAA);
Human_r_elbow.setTransform(tmpTrans);
}
public void setLShoulderRot(int rotation) {
lShoulderRot = rotation;
lShoulderAA.angle = (float) Math.toRadians(lShoulderRot);
Human_l_shoulder.getTransform(tmpTrans);
tmpTrans.setRotation(lShoulderAA);
Human_l_shoulder.setTransform(tmpTrans);
}
public void setLElbowRot(int rotation) {
float angle = (float) Math.toRadians(rotation);
lElbowRot = rotation;
lElbowAA.angle = (float) Math.toRadians(lElbowRot);
Human_l_elbow.getTransform(tmpTrans);
tmpTrans.setRotation(lElbowAA);
Human_l_elbow.setTransform(tmpTrans);
}
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
int value = source.getValue();
if (source == rShoulderSlider) {
setRShoulderRot(value);
rShoulderSliderLabel.setText(Integer.toString(value));
} else if (source == rElbowSlider) {
setRElbowRot(value);
rElbowSliderLabel.setText(Integer.toString(value));
} else if (source == lShoulderSlider) {
setLShoulderRot(value);
lShoulderSliderLabel.setText(Integer.toString(value));
} else if (source == lElbowSlider) {
setLElbowRot(value);
lElbowSliderLabel.setText(Integer.toString(value));
}
}
BranchGroup createSceneGraph() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
// Create a TransformGroup to scale the scene down by 3.5x
// TODO: move view platform instead of scene using orbit behavior
TransformGroup objScale = new TransformGroup();
Transform3D scaleTrans = new Transform3D();
scaleTrans.set(1 / 3.5f); // scale down by 3.5x
objScale.setTransform(scaleTrans);
objRoot.addChild(objScale);
// Create a TransformGroup and initialize it to the
// identity. Enable the TRANSFORM_WRITE capability so that
// the mouse behaviors code can modify it at runtime. Add it to the
// root of the subgraph.
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
objScale.addChild(objTrans);
// Add the primitives to the scene
createHuman(); // the human
objTrans.addChild(Human_body);
BoundingSphere bounds = new BoundingSphere(new Point3d(), 100.0);
Background bg = new Background(new Color3f(1.0f, 1.0f, 1.0f));
bg.setApplicationBounds(bounds);
objTrans.addChild(bg);
// set up the mouse rotation behavior
MouseRotate mr = new MouseRotate();
mr.setTransformGroup(objTrans);
mr.setSchedulingBounds(bounds);
mr.setFactor(0.007);
objTrans.addChild(mr);
// Set up the ambient light
Color3f ambientColor = new Color3f(0.1f, 0.1f, 0.1f);
AmbientLight ambientLightNode = new AmbientLight(ambientColor);
ambientLightNode.setInfluencingBounds(bounds);
objRoot.addChild(ambientLightNode);
// Set up the directional lights
Color3f light1Color = new Color3f(1.0f, 1.0f, 1.0f);
Vector3f light1Direction = new Vector3f(0.0f, -0.2f, -1.0f);
DirectionalLight light1 = new DirectionalLight(light1Color,
light1Direction);
light1.setInfluencingBounds(bounds);
objRoot.addChild(light1);
return objRoot;
}
public Human1() {
this(false, 1.0f);
}
public Human1(boolean isApplication, float initOffScreenScale) {
this.isApplication = isApplication;
this.offScreenScale = initOffScreenScale;
}
public void init() {
// set up a NumFormat object to print out float with only 3 fraction
// digits
nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(3);
setLayout(new BorderLayout());
GraphicsConfiguration config = SimpleUniverse
.getPreferredConfiguration();
canvas = new Canvas3D(config);
add("Center", canvas);
u = new SimpleUniverse(canvas);
if (isApplication) {
offScreenCanvas = new OffScreenCanvas3D(config, true);
// set the size of the off-screen canvas based on a scale
// of the on-screen size
Screen3D sOn = canvas.getScreen3D();
Screen3D sOff = offScreenCanvas.getScreen3D();
Dimension dim = sOn.getSize();
dim.width *= offScreenScale;
dim.height *= offScreenScale;
sOff.setSize(dim);
sOff.setPhysicalScreenWidth(sOn.getPhysicalScreenWidth()
* offScreenScale);
sOff.setPhysicalScreenHeight(sOn.getPhysicalScreenHeight()
* offScreenScale);
// attach the offscreen canvas to the view
u.getViewer().getView().addCanvas3D(offScreenCanvas);
}
// Create a simple scene and attach it to the virtual universe
BranchGroup scene = createSceneGraph();
// This will move the ViewPlatform back a bit so the
// objects in the scene can be viewed.
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);
view = u.getViewer().getView();
add("East", guiPanel());
}
// create a panel with a tabbed pane holding each of the edit panels
JPanel guiPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1));
// Human_r_shoulder rotation
panel.add(new JLabel("Right Shoulder rotation"));
rShoulderSlider = new JSlider(JSlider.HORIZONTAL, 0, 180, rShoulderRot);
rShoulderSlider.addChangeListener(this);
rShoulderSliderLabel = new JLabel(Integer.toString(rShoulderRot));
panel.add(rShoulderSlider);
panel.add(rShoulderSliderLabel);
// Human_r_elbow rotation
panel.add(new JLabel("Right Elbow rotation"));
rElbowSlider = new JSlider(JSlider.HORIZONTAL, 0, 180, rElbowRot);
rElbowSlider.addChangeListener(this);
rElbowSliderLabel = new JLabel(Integer.toString(rElbowRot));
panel.add(rElbowSlider);
panel.add(rElbowSliderLabel);
// Human_l_shoulder rotation
panel.add(new JLabel("Left Shoulder rotation"));
lShoulderSlider = new JSlider(JSlider.HORIZONTAL, 0, 180, lShoulderRot);
lShoulderSlider.addChangeListener(this);
lShoulderSliderLabel = new JLabel(Integer.toString(lShoulderRot));
panel.add(lShoulderSlider);
panel.add(lShoulderSliderLabel);
// Human_l_elbow rotation
panel.add(new JLabel("Left Elbow rotation"));
lElbowSlider = new JSlider(JSlider.HORIZONTAL, 0, 180, lElbowRot);
lElbowSlider.addChangeListener(this);
lElbowSliderLabel = new JLabel(Integer.toString(lElbowRot));
panel.add(lElbowSlider);
panel.add(rElbowSliderLabel);
if (isApplication) {
JButton snapButton = new JButton(snapImageString);
snapButton.setActionCommand(snapImageString);
snapButton.addActionListener(this);
panel.add(snapButton);
}
return panel;
}
public void destroy() {
u.removeAllLocales();
}
// The following allows Human to be run as an application
// as well as an applet
//
public static void main(String[] args) {
float initOffScreenScale = 2.5f;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-s")) {
if (args.length >= (i + 1)) {
initOffScreenScale = Float.parseFloat(args[i + 1]);
i++;
}
}
}
new MainFrame(new Human1(true, initOffScreenScale), 950, 600);
}
}
class OffScreenCanvas3D extends Canvas3D {
OffScreenCanvas3D(GraphicsConfiguration graphicsConfiguration,
boolean offScreen) {
super(graphicsConfiguration, offScreen);
}
private BufferedImage doRender(int width, int height) {
BufferedImage bImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
ImageComponent2D buffer = new ImageComponent2D(
ImageComponent.FORMAT_RGB, bImage);
//buffer.setYUp(true);
setOffScreenBuffer(buffer);
renderOffScreenBuffer();
waitForOffScreenRendering();
bImage = getOffScreenBuffer().getImage();
return bImage;
}
void snapImageFile(String filename, int width, int height) {
BufferedImage bImage = doRender(width, height);
/*
* JAI: RenderedImage fImage = JAI.create("format", bImage,
* DataBuffer.TYPE_BYTE); JAI.create("filestore", fImage, filename +
* ".tif", "tiff", null);
*/
/* No JAI: */
try {
FileOutputStream fos = new FileOutputStream(filename + ".jpg");
BufferedOutputStream bos = new BufferedOutputStream(fos);
JPEGImageEncoder jie = JPEGCodec.createJPEGEncoder(bos);
JPEGEncodeParam param = jie.getDefaultJPEGEncodeParam(bImage);
param.setQuality(1.0f, true);
jie.setJPEGEncodeParam(param);
jie.encode(bImage);
bos.flush();
fos.close();
} catch (Exception e) {
System.out.println(e);
}
}
} |