|
/*
* %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.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
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 java.util.Enumeration;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Hashtable;
import java.util.Vector;
import javax.media.j3d.Alpha;
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.ColoringAttributes;
import javax.media.j3d.ImageComponent;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.LineArray;
import javax.media.j3d.LineAttributes;
import javax.media.j3d.LineStripArray;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Screen3D;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TriangleFanArray;
import javax.media.j3d.View;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4d;
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.geometry.Sphere;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class ViewProj extends Applet implements Java3DExplorerConstants {
PolygonAttributes solidPa;
PolygonAttributes wirePa;
JSlider dynamicOffsetSlider;
JSlider staticOffsetSlider;
JLabel dynamicSliderValueLabel;
JLabel staticSliderValueLabel;
float dynamicOffset = 1.0f;
float staticOffset = 1.0f;
float frontClipDist = 1.413f;
float backClipDist = 3.309f;
float backClipRatio = backClipDist / frontClipDist;
View view;
ViewingPlatform viewingPlatform;
float innerScale = 0.94f;
TransformGroup innerTG;
Transform3D scale;
Transform3D projTrans = new Transform3D();
int numClipGridPts;
int maxClipGridPts = 180;
Point3f[] clipGridPtsVW = new Point3f[maxClipGridPts];
Point3f[] clipGridPtsProj = new Point3f[maxClipGridPts];
int numCirclePts = 36;
Point3f[] circlePtsVW = new Point3f[numCirclePts];
Point3f[] circlePtsProj = new Point3f[numCirclePts];
Point3f eyePtVW = new Point3f();
float fov;
float sphereRadius = 0.85f;
BranchGroup urScene;
BranchGroup lrScene;
SimpleUniverse urUniverse;
SimpleUniverse lrUniverse;
boolean isApplication;
Canvas3D canvas;
Canvas3D urCanvas;
Canvas3D lrCanvas;
OffScreenCanvas3D offScreenCanvas;
OffScreenCanvas3D urOffScreenCanvas;
OffScreenCanvas3D lrOffScreenCanvas;
String snapImageString = "Snap Main";
String urSnapImageString = "Snap UR";
String lrSnapImageString = "Snap LR";
String outFileBase = "vproj";
int outFileSeq = 0;
float offScreenScale = 1.0f;
String urOutFileBase = "vprojur";
int urOutFileSeq = 0;
float urOffScreenScale = 1.0f;
String lrOutFileBase = "vprojlr";
int lrOutFileSeq = 0;
float lrOffScreenScale = 1.0f;
NumberFormat nf;
Vector4d projPt = new Vector4d();
public BranchGroup createSceneGraph() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
// Create the transform group node and initialize it to the
// identity. Enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at runtime. Add it to the
// root of the subgraph.
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objRoot.addChild(objTrans);
// Create a Sphere. We will display this as both wireframe and
// solid to make a hidden line display
// wireframe
Appearance wireApp = new Appearance();
ColoringAttributes ca = new ColoringAttributes(black,
ColoringAttributes.SHADE_FLAT);
wireApp.setColoringAttributes(ca);
wirePa = new PolygonAttributes(PolygonAttributes.POLYGON_LINE,
PolygonAttributes.CULL_BACK, 0.0f);
wireApp.setPolygonAttributes(wirePa);
Sphere outWireSphere = new Sphere(sphereRadius, 0, 10, wireApp);
objTrans.addChild(outWireSphere);
// solid
ColoringAttributes outCa = new ColoringAttributes(red,
ColoringAttributes.SHADE_FLAT);
Appearance outSolid = new Appearance();
outSolid.setColoringAttributes(outCa);
solidPa = new PolygonAttributes(PolygonAttributes.POLYGON_FILL,
PolygonAttributes.CULL_BACK, 0.0f);
solidPa.setPolygonOffsetFactor(dynamicOffset);
solidPa.setPolygonOffset(staticOffset);
solidPa.setCapability(PolygonAttributes.ALLOW_OFFSET_WRITE);
outSolid.setPolygonAttributes(solidPa);
Sphere outSolidSphere = new Sphere(sphereRadius, 0, 10, outSolid);
objTrans.addChild(outSolidSphere);
innerTG = new TransformGroup();
innerTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
scale = new Transform3D();
updateInnerScale();
objTrans.addChild(innerTG);
// Create a smaller sphere to go inside. This sphere has a different
// tesselation and color
Sphere inWireSphere = new Sphere(sphereRadius, 0, 15, wireApp);
innerTG.addChild(inWireSphere);
// inside solid
ColoringAttributes inCa = new ColoringAttributes(blue,
ColoringAttributes.SHADE_FLAT);
Appearance inSolid = new Appearance();
inSolid.setColoringAttributes(inCa);
inSolid.setPolygonAttributes(solidPa);
Sphere inSolidSphere = new Sphere(sphereRadius, 0, 15, inSolid);
innerTG.addChild(inSolidSphere);
// Create a new Behavior object that will perform the desired
// operation on the specified transform object and add it into
// the scene graph.
AxisAngle4f axisAngle = new AxisAngle4f(0.0f, 0.0f, 1.0f,
-(float) Math.PI / 2.0f);
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,
80000, 0, 0, 0, 0, 0);
RotationInterpolator rotator = new RotationInterpolator(rotationAlpha,
objTrans, yAxis, 0.0f, (float) Math.PI * 2.0f);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
100.0);
rotator.setSchedulingBounds(bounds);
//objTrans.addChild(rotator);
Background bgWhite = new Background(white);
bgWhite.setApplicationBounds(bounds);
objTrans.addChild(bgWhite);
// Have Java 3D perform optimizations on this scene graph.
objRoot.compile();
return objRoot;
}
void updateInnerScale() {
scale.set(innerScale);
innerTG.setTransform(scale);
}
public BranchGroup createVWorldViewSG() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
objRoot.setCapability(BranchGroup.ALLOW_DETACH);
// setup a transform group to hold the scaled scene
TransformGroup objTrans = new TransformGroup();
objRoot.addChild(objTrans);
// get the eye point, field of view and clip distances
float fov = (float) view.getFieldOfView();
// figure out the angle factors to find points along the edges
// of the FOV
// X = fovSpreadX * (Y - eyeVW.y) + eyeVW.x;
float fovSpreadX = (float) Math.tan(fov / 2);
// Z = fovSpreadZ * (X - eyeVW.x) + eyeVW.z;
float fovSpreadZ = 1.0f / fovSpreadX;
//System.out.println("fovSpreadX = " + fovSpreadX);
//System.out.println("fovSpreadZ = " + fovSpreadZ);
Transform3D vpTransform = new Transform3D();
viewingPlatform.getViewPlatformTransform().getTransform(vpTransform);
Vector3f vpTranslation = new Vector3f();
vpTransform.get(vpTranslation);
eyePtVW.set(vpTranslation);
eyePtVW.negate();
// get the eye point in our 2D coord system.
Point3f eyePt = new Point3f(0.0f, eyePtVW.z, 0.1f);
float frontClipDist = (float) view.getFrontClipDistance();
float backClipDist = (float) view.getBackClipDistance();
// set up the clip plane lines
Point3f[] cpPoints = new Point3f[5];
cpPoints[0] = new Point3f(frontClipDist * fovSpreadX, eyePtVW.z
+ frontClipDist, 0.1f);
cpPoints[1] = new Point3f(cpPoints[0]);
cpPoints[1].x *= -1;
Point3f backLeft = new Point3f(-backClipDist * fovSpreadX, eyePtVW.z
+ backClipDist, 0.1f);
cpPoints[2] = backLeft;
Point3f backRight = new Point3f(backLeft);
backRight.x *= -1;
cpPoints[3] = backRight;
cpPoints[4] = cpPoints[0];
//for (int i = 0; i < 4; i++) {
// System.out.println("cpPoints[" + i + "] = " + cpPoints[i]);
//}
int[] cpLength = new int[1];
cpLength[0] = 5;
LineStripArray cpLines = new LineStripArray(5, LineArray.COORDINATES,
cpLength);
cpLines.setCoordinates(0, cpPoints);
Appearance cpApp = new Appearance();
ColoringAttributes cpCa = new ColoringAttributes(blue,
ColoringAttributes.SHADE_FLAT);
cpApp.setColoringAttributes(cpCa);
Shape3D cpShape = new Shape3D(cpLines, cpApp);
objTrans.addChild(cpShape);
// get the limits of the space
float minY = eyePt.y;
float maxY = backLeft.y;
float minX = backLeft.x;
float maxX = backRight.x;
// figure out the X and Y extents and offsets
float deltaX = maxX - minX;
float deltaY = maxY - minY;
float offsetX = -(maxX + minX) / 2.0f;
float offsetY = -(maxY + minY) / 2.0f;
float gridSize = Math.max(deltaX, deltaY);
// scale the grid slightly to give a border around the edge
gridSize *= 1.1f;
//System.out.println("offsetX = " + offsetX);
//System.out.println("offsetY = " + offsetY);
// Scale the view to fit -1 to 1
Transform3D trans = new Transform3D();
trans.set(new Vector3f(offsetX, offsetY, 0.0f), 2.0f / gridSize);
objTrans.setTransform(trans);
// figure out a grid step that is a multiple of 10 which keeps the
// number of steps less than 30.
float gridStep = 1.0f;
while ((gridSize / gridStep) > 30.0) {
gridStep *= 10;
}
int gridNumSteps = (int) Math.ceil(gridSize / gridStep) + 1;
// allocate the grid points array, four points for each step (x and y)
// with a couple extra points for the extra grid points added
// below
int gridNumPoints = 4 * (gridNumSteps + 4);
Point3f[] gridPts = new Point3f[gridNumPoints];
for (int i = 0; i < gridNumPoints; i++) {
gridPts[i] = new Point3f();
}
// find the grid limits. Add a step on each side to make sure
// the grid is larger than the view
float gridMinY = gridStepFloor(minY, gridStep) - gridStep;
float gridMaxY = gridStepCeil(maxY, gridStep) + gridStep;
float gridMinX = gridStepFloor(minX, gridStep) - gridStep;
float gridMaxX = gridStepCeil(maxX, gridStep) + gridStep;
//System.out.println("gridMinY = " + gridMinY);
//System.out.println("gridMaxY = " + gridMaxY);
//System.out.println("gridMinX = " + gridMinX);
//System.out.println("gridMaxX = " + gridMaxX);
// set up the background grid
Appearance bgApp = new Appearance();
ColoringAttributes bgCa = new ColoringAttributes();
bgCa.setColor(grey);
LineAttributes bgLa = new LineAttributes();
bgApp.setColoringAttributes(bgCa);
// clear out the clip grid point list
numClipGridPts = 0;
// set up the vertical lines
int numPts = 0;
for (float x = gridMinX; x <= gridMaxX; x += gridStep) {
gridPts[numPts].x = x;
gridPts[numPts].y = gridMinY;
gridPts[numPts].z = -0.2f;
gridPts[numPts + 1].x = x;
gridPts[numPts + 1].y = gridMaxY;
gridPts[numPts + 1].z = -0.2f;
numPts += 2;
// try to add a line to the clipped grid
// find the intersection of the clipped line with the FOV sides
// this is a distance relative to the eye
float clipZ = fovSpreadZ * Math.abs(x - eyePtVW.x);
if (clipZ < frontClipDist) { // clip to front clip plane
clipZ = frontClipDist;
}
if (clipZ < backClipDist) { // clip to back clip plane
// line is not clipped
clipGridPtsVW[numClipGridPts].x = x;
clipGridPtsVW[numClipGridPts].y = clipZ + eyePtVW.z;
clipGridPtsVW[numClipGridPts].z = -0.1f;
clipGridPtsVW[numClipGridPts + 1].x = x;
clipGridPtsVW[numClipGridPts + 1].y = backClipDist + eyePtVW.z;
clipGridPtsVW[numClipGridPts + 1].z = -0.1f;
numClipGridPts += 2;
}
}
LineArray vertLa = new LineArray(numPts, LineArray.COORDINATES);
vertLa.setCoordinates(0, gridPts, 0, numPts);
Shape3D vertShape = new Shape3D(vertLa, bgApp);
objTrans.addChild(vertShape);
// set up the horizontal lines
numPts = 0;
for (float y = gridMinY; y <= gridMaxY; y += gridStep) {
gridPts[numPts].x = gridMinX;
gridPts[numPts].y = y;
gridPts[numPts++].z = -0.2f;
gridPts[numPts].x = gridMaxX;
gridPts[numPts].y = y;
gridPts[numPts++].z = -0.2f;
// try to add a line to the clipped grid
// find the intersection of the clipped line with the FOV sides
// this is a distance relative to the eye
float clipDist = (y - eyePtVW.z);
if ((clipDist > frontClipDist) && (clipDist < backClipDist)) {
float clipX = fovSpreadX * clipDist;
clipGridPtsVW[numClipGridPts].x = -clipX;
clipGridPtsVW[numClipGridPts].y = y;
clipGridPtsVW[numClipGridPts].z = -0.1f;
clipGridPtsVW[numClipGridPts + 1].x = clipX;
clipGridPtsVW[numClipGridPts + 1].y = y;
clipGridPtsVW[numClipGridPts + 1].z = -0.1f;
numClipGridPts += 2;
}
}
LineArray horizLa = new LineArray(numPts, LineArray.COORDINATES);
horizLa.setCoordinates(0, gridPts, 0, numPts);
Shape3D horizShape = new Shape3D(horizLa, bgApp);
objTrans.addChild(horizShape);
// draw the clipped grid.
if (numClipGridPts > 0) {
LineArray clipLa = new LineArray(numClipGridPts,
LineArray.COORDINATES);
clipLa.setCoordinates(0, clipGridPtsVW, 0, numClipGridPts);
Appearance clipGridApp = new Appearance();
ColoringAttributes clipCa = new ColoringAttributes(black,
ColoringAttributes.SHADE_FLAT);
clipGridApp.setColoringAttributes(clipCa);
LineAttributes clipGridLa = new LineAttributes();
Shape3D clipShape = new Shape3D(clipLa, clipGridApp);
objTrans.addChild(clipShape);
}
// set up the coordinate system
Appearance coordSysApp = new Appearance();
LineAttributes coordSysLa = new LineAttributes();
coordSysLa.setLineWidth(3.0f);
coordSysApp.setLineAttributes(coordSysLa);
ColoringAttributes coordSysCa = new ColoringAttributes(grey,
ColoringAttributes.SHADE_FLAT);
coordSysApp.setColoringAttributes(coordSysCa);
Point3f[] coordSysPts = new Point3f[4];
coordSysPts[0] = new Point3f(gridMinX, 0, -0.5f);
coordSysPts[1] = new Point3f(gridMaxX, 0, -0.5f);
coordSysPts[2] = new Point3f(0, gridMinY, -0.5f);
coordSysPts[3] = new Point3f(0, gridMaxY, -0.5f);
LineArray coordSysLines = new LineArray(4, LineArray.COORDINATES);
coordSysLines.setCoordinates(0, coordSysPts);
Shape3D coordSysShape = new Shape3D(coordSysLines, coordSysApp);
objTrans.addChild(coordSysShape);
// set up the circle
Appearance circleApp = new Appearance();
ColoringAttributes circleCa = new ColoringAttributes();
circleCa.setColor(red);
circleApp.setColoringAttributes(circleCa);
PolygonAttributes pa = new PolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
circleApp.setPolygonAttributes(pa);
int step = 360 / (numCirclePts - 1);
for (int deg = 0; deg < 360; deg += step) {
double angle = Math.toRadians(deg);
circlePtsVW[deg / 10].x = sphereRadius * (float) Math.sin(angle);
circlePtsVW[deg / 10].y = sphereRadius * (float) Math.cos(angle);
circlePtsVW[deg / 10].z = -0.3f;
}
circlePtsVW[numCirclePts - 1].set(circlePtsVW[0]);
int[] lineStripLength = new int[1];
lineStripLength[0] = numCirclePts;
//LineStripArray circleLineStrip = new LineStripArray(numCirclePts,
// LineArray.COORDINATES, lineStripLength);
TriangleFanArray circleLineStrip = new TriangleFanArray(numCirclePts,
LineArray.COORDINATES, lineStripLength);
circleLineStrip.setCoordinates(0, circlePtsVW);
Shape3D circleShape = new Shape3D(circleLineStrip, circleApp);
objTrans.addChild(circleShape);
return objRoot;
}
// return the closest multiple of step less than value
float gridStepFloor(float value, float step) {
return (float) (step * (Math.floor(value / step)));
}
// return the closest multiple of step greater than value
float gridStepCeil(float value, float step) {
return (float) (step * (Math.ceil(value / step)));
}
public BranchGroup createProjViewSG() {
// Create the root of the branch graph
BranchGroup objRoot = new BranchGroup();
objRoot.setCapability(BranchGroup.ALLOW_DETACH);
// setup a transform group to hold the scaled scene
TransformGroup objTrans = new TransformGroup();
Transform3D scale = new Transform3D();
scale.set(0.9);
objTrans.setTransform(scale);
objRoot.addChild(objTrans);
// create the clip limits line
Point3f[] cpPoints = new Point3f[5];
cpPoints[0] = new Point3f(-1, -1, 0.1f);
cpPoints[1] = new Point3f(1, -1, 0.1f);
cpPoints[2] = new Point3f(1, 1, 0.1f);
cpPoints[3] = new Point3f(-1, 1, 0.1f);
cpPoints[4] = cpPoints[0];
int[] cpLength = new int[1];
cpLength[0] = 5;
LineStripArray cpLines = new LineStripArray(5, LineArray.COORDINATES,
cpLength);
cpLines.setCoordinates(0, cpPoints);
Appearance cpApp = new Appearance();
ColoringAttributes cpCa = new ColoringAttributes(blue,
ColoringAttributes.SHADE_FLAT);
cpApp.setColoringAttributes(cpCa);
LineAttributes cpLa = new LineAttributes();
Shape3D cpShape = new Shape3D(cpLines, cpApp);
objTrans.addChild(cpShape);
// transform and render the clip grid points
updateProjTrans();
if (numClipGridPts > 0) {
// transform the clipGridPts
for (int i = 0; i < numClipGridPts; i++) {
projectPoint(clipGridPtsVW[i], clipGridPtsProj[i]);
}
LineArray clipLn = new LineArray(numClipGridPts,
&nbs
|