this is a last ditch attempt to get my project up and running. the deadline
is next week. i include full code below. my problems are: 1) after i've
calculated the point of intersection of the incident ray and the shape and
the direction of the refracted ray, how do i calculate the transform3d so
the next beam of light (a shape3d) is placed correctly (mine isn't) 2) how
do i determine if a point is in a shape or not, 3) how do i check if i've
specified normals to my shapes correctly
basically, if anyone can play ith this program (the main's in glassUniverse)
and make it look better, i'd be most grateful:
/////////////////////////////////////////////////////////////////////
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import com.sun.j3d.utils.applet.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.image.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.behaviors.keyboard.*;
import javax.swing.*;
public class glassUniverse extends Applet implements ActionListener
{
// so all the rays of light start off in the same direction
// these 2 points serve as a guide
final Point3d origin=new Point3d(0.0f,0.0f,0.0f);
final Vector3d rayInitialDirection=new Vector3d(2.0f,0.0f,0.0f);
// so you don't render the scene twice
boolean firstime=true;
// button to trigger the refraction event
Button doneButton;
// the scale of the objects
private final double scale=1;
// a heavyweight Canvas3D so that we can render our 3D graphics
private Canvas3D this3Dcanvas;
// Globally used colors
private Color3f red=new Color3f(0.9f,0.0f,0.0f);
private Color3f indigo=new Color3f(0.9f,0.0f,0.9f);
private Color3f black=new Color3f(0.0f,0.0f,0.0f);
private Color3f white=new Color3f(1.0f,1.0f,1.0f);
private Color3f lightgrey=new Color3f(0.7f,0.7f,0.7f);
private Color3f darkgrey=new Color3f(0.2f,0.2f,0.2f);
private Color3f blue=new Color3f(0.0
f,0.0f,0.7f);
private Color3f green=new Color3f(0.0f,1.0f,0.0f);
private Color3f pink=new Color3f(1.0f,0.7f,0.7f);
private Color3f lightblue=new Color3f(0.7f,0.7f,1.0f);
private Color3f yellow=new Color3f(0.8f,0.8f,0.0f);
private Color3f orange=new Color3f(0.9f,0.2f,0.0f);
private Color3f violet=new Color3f(0.8f,0.44f,0.8f);
private Color3f[]
rainbowColours={red,orange,yellow,green,blue,indigo,violet};
// relative indices of refraction going from air to glass
private static double[] refractiveIndex={1.7,1.6,1.5,1.4,1.3,1.2,1.1};
// globally used shapes
myShape[]shapes={
new Tetrahedron()
//,new Octahedron()
//,new convergingLens()
,new Cube()
// ,new divergingLens()
};
// the glass shapes' transform groups and transforms
TransformGroup[] individualObjTransformGrp=new
TransformGroup[shapes.length];
// the light rays' group and transform
TransformGroup lightTransformGrp;
private Transform3D lightTransform;
TransformGroup objTransGroup=new TransformGroup();
public glassUniverse()
// set size to maximum
Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
this.setLocation(0,0);
this.setSize(screenSize.width,screenSize.height);
// add instructions
int controlPanelHeight=150;
Panel controlPanel=new Panel();
controlPanel.setSize(screenSize.width,controlPanelHeight);
Label mouseinstructions=new Label("PUT A GLASS OBJECT IN FRONT OF THE RAY
OF LIGHT AND PRESS THE BUTTON.");
Label keyinstructions=new Label("DRAG the THREE MOUSE BUTTONS (ALT-DRAG
works for the 3rd mouse button on a PC) to move the objects.");
Label lightinstructions=new Label("Use CONTROL, ALT and SHIFT with the
ARROW KEYS to navigate.");
controlPanel.add(mouseinstructions);
controlPanel.add(keyinstructions);
controlPanel.add(lightinstructions);
doneButton=new Button("Refract light");
doneButton.addActionListener(this);
controlPanel.add(doneButton);
// create the glassUniverse Canvas
this3Dcanvas=new Canvas3D(null);
this3Dcanvas.setSize(screenSize.width,screenSize.height-controlPanelHeight);
// Layout panels
setLayout(new FlowLayout());
controlPanel.setLayout(new GridLayout(4,1));
add(controlPanel);
add(this3Dcanvas);
// Now that we have our Canvas3D, we are ready to build our scene
graph
VirtualUniverse thisUniverse = new VirtualUniverse();
Locale thisLocale = new Locale(thisUniverse);
// create content branch
BranchGroup scene=createSceneGraph(this3Dcanvas);
// Make the universe live by adding the objects to the locale
thisLocale.addBranchGraph(scene);
}
public BranchGroup createSceneGraph(Canvas3D canvas)
{
// Create the root of the branch graph
BranchGroup rootBranch=new BranchGroup();
// attach the scene graph's ViewPlatform to a Canvas3D for rendering
View thisView = new View();
thisView.addCanvas3D(this3Dcanvas);
// use the default PhysicalBody and PhysicalEnvironment
PhysicalBody thisBod = new PhysicalBody();
thisBod.setLeftEyePosition(new Point3d(-.006,0.0,0.0));// default
is(-0.033, 0.0, 0.0)
thisBod.setRightEyePosition(new Point3d(+.006,0.0,0.0));
thisView.setPhysicalBody(thisBod);
thisView.setPhysicalEnvironment(new PhysicalEnvironment());
thisView.setMonoscopicViewPolicy(View.LEFT_EYE_VIEW);
// construct a View and connect it to our view branch's ViewPlatform
// insert the platform into the transform group,
// and the transform group into the branch group
BranchGroup viewBranch=new BranchGroup();
TransformGroup viewTransformGrp=new TransformGroup();
Transform3D viewTransform=new Transform3D();
Vector3d moveBack=new Vector3d(5,0,20);
viewTransform.set(moveBack);
viewTransformGrp.setTransform(viewTransform);
ViewPlatform thisViewPlatform=new ViewPlatform();
viewTransformGrp.addChild(thisViewPlatform);
viewBranch.addChild(viewTransformGrp);
rootBranch.addChild(viewBranch);
// attach view to the view platform
thisView.attachViewPlatform(thisViewPlatform);
// add the transform group node for the glass objects
rootBranch.addChild(objTransGroup);
// Create a bounds for the background and behaviours
BoundingSphere bounds=new BoundingSphere(new Point3d
(0.0,0.0,0.0), // centre
1000.0); // extent
// Set up the patterned background from an image file
/*
TextureLoader bgTexture=new TextureLoader("Clouds.gif",this);
Background bg=new Background(bgTexture.getImage());
bg.setApplicationBounds(bounds);
rootBranch.addChild(bg);
*/
// Set up the plain white background
Background thisBackground=new Background(white);
thisBackground.setApplicationBounds(bounds);
rootBranch.addChild(thisBackground);
// Set up the global lights
Vector3f lightDirection3DVector=new Vector3f(-1.0f,-1.0f,-1.0f);
AmbientLight thisAmbientLight=new AmbientLight(darkgrey);
thisAmbientLight.setInfluencingBounds(bounds);
DirectionalLight thisDirectionalLight=
new DirectionalLight(lightgrey,lightDirection3DVector);
thisDirectionalLight.setInfluencingBounds(bounds);
rootBranch.addChild(thisAmbientLight);
rootBranch.addChild(thisDirectionalLight);
// Set up colouring attributes
// A ColoringAttributes node component controls shading model (flat or
Gouraud)
// ColoringAttributes theseColouringAttributes=new
ColoringAttributes();
// theseColouringAttributes.setColor(pink);
Appearance thisAppearance=new Appearance();
// thisAppearance.setColoringAttributes(theseColouringAttributes);
// Set up the transparency amount (0.0=opaque, 1.0=invisible)
TransparencyAttributes ta=new TransparencyAttributes();
ta.setTransparencyMode(ta.FASTEST);
ta.setTransparency(0.6f);
thisAppearance.setTransparencyAttributes(ta);
// Set up the lit solid texture map from an image file
/*TextureLoader tex=new TextureLoader("Silver.gif",this);
thisAppearance.setTexture(tex.getTexture());
TextureAttributes theseTextureAttributes=new TextureAttributes();
theseTextureAttributes.setTextureMode(TextureAttributes.MODULATE);
thisAppearance.setTextureAttributes(theseTextureAttributes);*/
// A Material node component controls:
// Ambient, emissive, diffuse, and specular color, shininess factor
Material thisMaterial=new Material();
thisMaterial.setAmbientColor(lightgrey);
thisMaterial.setDiffuseColor(lightblue);
thisMaterial.setEmissiveColor(darkgrey);
thisMaterial.setSpecularColor(white);
thisMaterial.setShininess(70.0f);
thisAppearance.setMaterial(thisMaterial);
// Enable the TRANSFORM_READ/WRITE capabilities so that the behaviour
// code can modify it at runtime
objTransGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objTransGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
objTransGroup.setCapability(Group.ALLOW_CHILDREN_EXTEND);
// create the key behaviour so you can navigate
KeyBehavior keyNavigationBehaviour=new KeyBehavior(objTransGroup);
keyNavigationBehaviour.setSchedulingBounds(new BoundingSphere(new
Point3d(),1000.0));
objTransGroup.addChild(keyNavigationBehaviour);
// create the mouse pick behaviour so you can drag and drop objects
PickRotateBehavior pickRotateBehaviour=new
PickRotateBehavior(rootBranch,canvas,bounds,PickObject.USE_BOUNDS);
objTransGroup.addChild(pickRotateBehaviour);
PickZoomBehavior pickZoomBehaviour=new
PickZoomBehavior(rootBranch,canvas,bounds,PickObject.USE_BOUNDS);
objTransGroup.addChild(pickZoomBehaviour);
PickTranslateBehavior pickTranslateBehaviour=new
PickTranslateBehavior(rootBranch,canvas,bounds,PickObject.USE_BOUNDS);
objTransGroup.addChild(pickTranslateBehaviour);
// add the glass object nodes
for(int j=0;j<shapes.length;j++)
{
// an arbitrary equation that separates the objects nicely
double xpos=(double)(j+1)*scale*4;
objTransGroup.addChild(createObject(thisAppearance,xpos,0.0,j));
}
// add the light rays' transform group and transform
lightTransformGrp=new TransformGroup();
// set the light ray to the left of the glass objects a bit
Vector3d thisVector3d=new Vector3d(-0.5,0.0,0.0);
Transform3D translateLightTransform=new Transform3D();
translateLightTransform.set(thisVector3d);
// rotate the light ray so it's pointing at the glass objects
Transform3D rotateLightTransform=new Transform3D();
rotateLightTransform.rotZ(-Math.PI/2);
// multiply these two transforms together
lightTransform=new Transform3D();
lightTransform.mul(translateLightTransform,rotateLightTransform);
// set the scale
lightTransform.setScale(scale);
// set the group's transform
lightTransformGrp.setTransform(lightTransform);
// Enable the capabilities so that our behaviour code can modify it at
runtime
lightTransformGrp.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
lightTransformGrp.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
// add the arrow of light
// set up arrow lengths
float arrowDiameter=0.2f;
double arrowLength=rayInitialDirection.length();
float arrowHeadLength=5.0f*arrowDiameter;
float arrowHeadDiameter=2.0f*arrowDiameter;
float cylinderLength=(float)arrowLength-arrowHeadLength;
// Set up arrow appearance
Appearance arrowAppearance=new Appearance();
ColoringAttributes arrowColouringAttributes;
arrowColouringAttributes=new ColoringAttributes();
arrowColouringAttributes.setColor(yellow);
arrowAppearance.setColoringAttributes(arrowColouringAttributes);
TransparencyAttributes arrowTransparency=new TransparencyAttributes();
arrowTransparency.setTransparencyMode(arrowTransparency.FASTEST);
arrowTransparency.setTransparency(0.6f);
arrowAppearance.setTransparencyAttributes(arrowTransparency);
Material arrowMaterial=new Material();
arrowMaterial.setAmbientColor(pink);
arrowMaterial.setDiffuseColor(orange);
arrowMaterial.setEmissiveColor(yellow);
arrowMaterial.setSpecularColor(white);
arrowMaterial.setShininess(0.0f);
arrowAppearance.setMaterial(arrowMaterial);
// the parts of the arrow
Node arrowCylinder=new
Cylinder(arrowDiameter,cylinderLength,arrowAppearance);
Node ArrowHeadCone=new
Cone(arrowHeadDiameter,arrowHeadLength,1,arrowAppearance);
// put these 2 pieces together
Transform3D arrowHeadTransform=new Transform3D();
arrowHeadTransform.set(new
Vector3f(0.0f,cylinderLength/2.0f+0.5f*arrowHeadLength,0.0f));
TransformGroup arrowHeadTransformGroup=new
TransformGroup(arrowHeadTransform);
arrowHeadTransformGroup.addChild(ArrowHeadCone);
lightTransformGrp.addChild(arrowHeadTransformGroup);
lightTransformGrp.addChild(arrowCylinder);
// add the arrow/light group to the picture
objTransGroup.addChild(lightTransformGrp);
// Let Java 3D perform optimisations on this scene graph.
rootBranch.compile();
return rootBranch;
}
private Group createObject(Appearance thisAppearance,double xpos,double
ypos,int index)
{
// Create a transform
Transform3D objectTransform=new Transform3D();
objectTransform.set(scale,new Vector3d(xpos,ypos,0.0));
// attach the transform to the group
individualObjTransformGrp[index]=new
TransformGroup(objectTransform);
// Enable the capabilities so that our behaviour code can modify it at
runtime
individualObjTransformGrp[index].setCapability(TransformGroup.ALLOW_TRANSFOR
M_WRITE);
individualObjTransformGrp[index].setCapability(TransformGroup.ALLOW_TRANSFOR
M_READ);
individualObjTransformGrp[index].setCapability(TransformGroup.ENABLE_PICK_RE
PORTING);
// Create a shapes leaf node and set the appearance
shapes[index].setAppearance(thisAppearance);
individualObjTransformGrp[index].addChild(shapes[index]);
return individualObjTransformGrp[index];
}
public void actionPerformed(ActionEvent evt)
{
if(firstime)
{
firstime=false;
/*
* To add a shapes to a live scene, create a BranchGroup, add a
* transform group, add your shapes and then add this BranchGroup
* to the live BranchGroup
* (root BranchGroup)
*
* rootBranchGroup (live)
* |
* addBranchGroup (not live until added)
* |
* TransformGroup
* |
* shapes
*/
// the branch group that is added when the button is pressed to
show refraction
BranchGroup refractionBranch=new BranchGroup();
// number of rays I'll show; you can change this number
int noOfRays=3;
// comment this line back in if you want to see all the colours
// for(int
colourIndex=0;colourIndex<rainbowColours.length;colourIndex++)
int colourIndex=0;
{
// add refracted beam's transform
TransformGroup refractionTransformGrp[]=new
TransformGroup[noOfRays];
Transform3D[] refractionTransform=new Transform3D[noOfRays];
for(int i=0;i<noOfRays;i++)
{
refractionTransformGrp[i]=new TransformGroup();
refractionTransform[i]=new Transform3D();
// Enable the capabilities so that our behaviour code can
modify it at runtime
refractionTransformGrp[i].setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE
);
refractionTransformGrp[i].setCapability(TransformGroup.ALLOW_TRANSFORM_READ)
;
}
// initial start point and direction of light ray
Point3d start=new Point3d(origin);
Vector3d dir=new Vector3d(rayInitialDirection);
// the transforms on the shapes
Transform3D[] ShapeTransforms=new Transform3D[noOfRays];
for(int
i=0;i<shapes.length;i++)ShapeTransforms[i]=getShapeTransform(i);
// the light beams
lightBeam[] thisLightBeam=new lightBeam[noOfRays];
// to hold the data about the refraction
double[] refractionVariables=new double[10];
// to hold the refractive index
double refractIndex=refractiveIndex[colourIndex];
// the rotation and translation transforms for the beams
Transform3D translateTransform=new Transform3D();
Transform3D rotateXTransform=new Transform3D();
Transform3D rotateYTransform=new Transform3D();
Transform3D rotateZTransform=new Transform3D();
for(int i=0;i<noOfRays;i++)
{
calculateRefraction(start,dir,shapes,ShapeTransforms,refractiveIndex[colourI
ndex],refractionVariables);
// the rotation and translation transforms for the next
beam
refractionTransform[i].mul(rotateXTransform);
refractionTransform[i].mul(rotateYTransform);
refractionTransform[i].mul(rotateZTransform);
refractionTransform[i].mul(translateTransform);
// add beam of light
thisLightBeam[i]=new
lightBeam(rainbowColours[colourIndex]
,refractionVariables[0]);
refractionTransformGrp[i].setTransform(refractionTransform[i]);
refractionTransformGrp[i].addChild(thisLightBeam[i]);
refractionBranch.addChild(refractionTransformGrp[i]);
// the point of intersection
Point3d intersectionPoint=new Point3d
(refractionVariables[3],refractionVariables[4],refractionVariables[5]);
// the new start and direction of light ray
start.set(intersectionPoint);
// the direction of the refracted ray
Vector3d refractedDirection=new Vector3d
(refractionVariables[6],refractionVariables[7],refractionVariables[8]);
refractedDirection.scale(refractionVariables[0]);
dir.set(refractedDirection);
translateTransform.set(new
Vector3d(refractionVariables[3]
,refractionVariables[4],refractionVariables[5]));
rotateXTransform.rotX(refractionVariables[6]);
rotateYTransform.rotY(refractionVariables[7]);
rotateZTransform.rotZ(refractionVariables[8]);
}
}
objTransGroup.addChild(refractionBranch); // now live
}
}
public static void main(String[] args)
// allows glassWorld to be run as an application
{
new MainFrame(new glassUniverse(),1014,700);
}
// returns true if this ray intersects with the shape
// has a problem (i.e. returns false) if the ray hits an edge
// should build in a ray intersect line method
// parameters: the light ray start and finish and the shape index
private boolean doesRayIntersectShape
(Vector3d rayStart,Vector3d rayFinish,myShape[] shapes,int shapeIndex)
// set up the ray
rayFinish.sub(rayStart);
PickRay ray=new PickRay(new Point3d(rayStart),new
Vector3d(rayFinish));
// get the real vertex coordinates of the shape
myShape thisShape=shapes[shapeIndex];
Point3f[] faceCoords=new Point3f[thisShape.getNumberTriangles()*3];
Point3d[]faceCoordinates=new Point3d[faceCoords.length];
for(int i=0;i<thisShape.getNumberTriangles()*3;i++)
{
faceCoords[i]=new Point3f(thisShape.getTriangleCoordinates(i));
}
for(int i=0;i<faceCoords.length;i++)
{
getShapeTransform(shapeIndex).transform(faceCoords[i]);
faceCoordinates[i]=new Point3d(faceCoords[i]);
}
// see if the ray intersects any of the faces
Intersect thisIntersect=new Intersect();
boolean toReturn=false;
double[]dist=new double[3];
for(int i=0;i<faceCoordinates.length;i+=3)
{
if(thisIntersect.rayAndTriangle(ray,faceCoordinates,i,dist))toReturn=true;
}
return toReturn;
}
// parameters: the light ray start and finish, the shapes and their
transforms,
// the light's relative refractive index
// the refractionVariables array should be allocated by the user.
// make sure the shapes are closed and the refractionVariables array has
a length of 9
// refractionVariables will contain:
// at index 0, the distance from ray start to the first intersection
// at index 1, air to glass=0, glass to air=1
// at index 2, a flag telling you whether it's refraction(0) or
reflection(1)
// at indices 3,4,5 the components representing the point of
intersection
// at indices 6,7,8 the normalised components of the direction of the
reflected/refracted ray
public static void calculateRefraction
(Point3d rayStart,Vector3d direction,myShape[] shapes,Transform3D[]
ShapeTransforms,
double refractiveIndex,double[] refractionVariables)
{
boolean totalInternalReflection;
Vector3d dirOfRefractedRay=new Vector3d(); // direction of
refracted/reflected ray
Intersect thisIntersect=new Intersect();
// set up the ray
PickRay ray=new PickRay(rayStart,direction);
int count=0;
// to hold all the distances from ray start to intersection
double[] intersectDist=new double[shapes.length*2];
// to hold all the angles of incidence
boolean[] isAirToGlass=new boolean[shapes.length*2];
// to hold the refracted directions
Vector3d[] refractedDirections=new Vector3d[shapes.length*2];
// to hold all the normals
Vector3d[] normals=new Vector3d[shapes.length*2];
// to hold all the totalInternalReflections
boolean[] totalInternalReflections=new boolean[shapes.length*2];
for(int i=0;i<shapes.length*2;i++)
{
isAirToGlass[i]=true;
refractedDirections[i]=new Vector3d();
normals[i]=new Vector3d();
}
for(int shapeIndex=0;shapeIndex<shapes.length;shapeIndex++)
{
// get the real vertex coordinates of the shape after they've
been placed
// in space with the shape transform
myShape thisShape=shapes[shapeIndex];
Point3f[] faceCoords=new
Point3f[thisShape.getNumberTriangles()*3];
Point3d[]faceCoordinates=new Point3d[faceCoords.length];
for(int i=0;i<thisShape.getNumberTriangles()*3;i++)
{
faceCoords[i]=new
Point3f(thisShape.getTriangleCoordinates(i));
}
for(int i=0;i<faceCoords.length;i++)
{
ShapeTransforms[shapeIndex].transform(faceCoords[i]);
faceCoordinates[i]=new Point3d(faceCoords[i]);
}
// the distance to intersection
double[]dist=new double[3];
double[] distance=new double[2];
// the direction of refraction
Vector3d[] refractedDir={new Vector3d(),new Vector3d()};
Vector3d[] norm={new Vector3d(),new Vector3d()};
boolean[] reflect={false,false};
int countFacesIntersected=0;
// to calculate the shape face normals
Vector3d AB=new Vector3d();
Vector3d AC=new Vector3d();
Vector3d normal=new Vector3d();
// the cosine of the angle of incidence
double cosine;
// air to glass or glass to air
boolean[] airOrGlass=new boolean[2];
double actualRefractiveIndex;
// for each shape face
for(int i=0;i<faceCoordinates.length;i+=3)
{
if(thisIntersect.rayAndTriangle(ray,faceCoordinates,i,dist))
{
// the distance to intersection
distance[countFacesIntersected]=dist[0];
AB.sub(faceCoordinates[i+1],faceCoordinates[i]);
AC.sub(faceCoordinates[i+2],faceCoordinates[i]);
normal.cross(AB,AC);
normal.normalize(); // the normal
norm[countFacesIntersected]=normal;
// check if light is going from air to glass or glass to
air
// check if rayStart point is on positive side of this
plane
boolean airGlassOrder=true;
airOrGlass[countFacesIntersected]=airGlassOrder;
if(airGlassOrder)actualRefractiveIndex=refractiveIndex;
else actualRefractiveIndex=1/refractiveIndex;
Vector3d incidentDirection=new Vector3d(direction);
incidentDirection.normalize(); // the vector of ray
incidence
// method taken from:
//
http://www.research.microsoft.com/~hollasch/cgindex/render/refraction.txt
Vector3d temp=new Vector3d();
double c1=incidentDirection.dot(normal);
double
c2=1-actualRefractiveIndex*actualRefractiveIndex*(1-c1*c1);
if (c2<0) totalInternalReflection=true;
else totalInternalReflection=false;
reflect[countFacesIntersected]=totalInternalReflection;
if(!totalInternalReflection)
{
incidentDirection.scale(actualRefractiveIndex);
dirOfRefractedRay.set(incidentDirection);
temp.set(normal);
temp.scale(actualRefractiveIndex*c1-Math.sqrt(c2));
dirOfRefractedRay.add(temp);
}
else
{
temp.set(incidentDirection);
double t=-2*temp.dot(normal);
temp.set(normal);
temp.scale(t);
temp.add(incidentDirection);
dirOfRefractedRay.set(temp);
}
dirOfRefractedRay.normalize();
refractedDir[countFacesIntersected]=dirOfRefractedRay;
//
JOptionPane.showMessageDialog(null,"refractedDir["+countFacesIntersected+"]:
"+refractedDir[countFacesIntersected].x+","+refractedDir[countFacesIntersect
ed].y+","+refractedDir[countFacesIntersected].z);
countFacesIntersected++;
}
}
// copy the data for the 2 points of intersection with this
shape
intersectDist[count]=distance[0];
refractedDirections[count]=refractedDir[0];
JOptionPane.showMessageDialog(null,"distance"+intersectDist[count]);
JOptionPane.showMessageDialog(null,"refractedDirections["+count+"]:"+refract
edDirections[count].x+","+refractedDirections[count].y+","+refractedDirectio
ns[count].z);
normals[count]=norm[0];
totalInternalReflections[count]=reflect[0];
isAirToGlass[count++]=airOrGlass[0];
intersectDist[count]=distance[1];
refractedDirections[count]=refractedDir[1];
JOptionPane.showMessageDialog(null,"distance"+intersectDist[count]);
JOptionPane.showMessageDialog(null,"refractedDirections["+count+"]:"+refract
edDirections[count].x+","+refractedDirections[count].y+","+refractedDirectio
ns[count].z);
normals[count]=norm[1];
totalInternalReflections[count]=reflect[1];
isAirToGlass[count++]=airOrGlass[1];
}// end of for each shape
// get the index of the shortest distance, i.e. to the first
intersection
double shortestDistance=1000000000;
int indexOfShortest=-1;
for(int i=0;i<shapes.length*2;i++)
{
if(intersectDist[i]==0)intersectDist[i]=1000000000;
if(intersectDist[i]<=shortestDistance)
{
shortestDistance=intersectDist[i];
indexOfShortest=i;
}
}
// from air to glass or glass to air
boolean airToGlass=isAirToGlass[indexOfShortest];
if(airToGlass)refractionVariables[1]=0;
else refractionVariables[1]=1;
// distance to intersection
refractionVariables[0]=shortestDistance;
// normal to intersected face
Vector3d normalToIntersectedFace=normals[indexOfShortest];
// reflection or refraction
boolean didItReflect=totalInternalReflections[indexOfShortest];
if (didItReflect) refractionVariables[2]=1;
else refractionVariables[2]=0;
// calculate the point of intersection
direction.normalize();
// incident direction now going up to intersection
direction.scale(refractionVariables[0]);
Point3d intersection=new Point3d();
intersection.set(rayStart);
intersection.add(direction);
refractionVariables[3]=intersection.x;
refractionVariables[4]=intersection.y;
refractionVariables[5]=intersection.z;
// get the direction of the refracted ray
refractionVariables[6]=refractedDirections[indexOfShortest].x;
refractionVariables[7]=refractedDirections[indexOfShortest].y;
refractionVariables[8]=refractedDirections[indexOfShortest].z;
// check
// JOptionPane.showMessageDialog(null,"distance:"+shortestDistance);
normalToIntersectedFace.normalize();
//
JOptionPane.showMessageDialog(null,"normal:"+normalToIntersectedFace.x+","+n
ormalToIntersectedFace.y+","+normalToIntersectedFace.z);
//
JOptionPane.showMessageDialog(null,"directionOfRefractedRay:"+refractedDirec
tions[indexOfShortest].x+","+refractedDirections[indexOfShortest].y+","+refr
actedDirections[indexOfShortest].z);
//
JOptionPane.showMessageDialog(null,"intersection:"+intersection.x+","+inters
ection.y+","+intersection.z);
//
JOptionPane.showMessageDialog(null,"totalInternalReflection:"+didItReflect);
// JOptionPane.showMessageDialog(null,"airToGlass:"+airToGlass);
}
// returns the transform of the shapes
// parameter: the index of the shape in the shapes array
Transform3D getShapeTransform(int shapeIndex)
{
Transform3D shapeTransform=new Transform3D();
individualObjTransformGrp[shapeIndex].getTransform(shapeTransform);
return shapeTransform;
}
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
import javax.swing.*;
public class Cube extends myShape
{
private int noFaces=6;
private int noVertices=8;
QuadArray cube=new
QuadArray(24,QuadArray.COORDINATES|QuadArray.NORMALS|QuadArray.COLOR_3);
private Point3f vertex0=new Point3f(1.0f,-1.0f,1.0f);
private Point3f vertex1=new Point3f(1.0f,1.0f,1.0f);
private Point3f vertex2=new Point3f(-1.0f,1.0f,1.0f);
private Point3f vertex3=new Point3f(-1.0f,-1.0f,1.0f);
private Point3f vertex4=new Point3f(-1.0f,-1.0f,-1.0f);
private Point3f vertex5=new Point3f(-1.0f,1.0f,-1.0f);
private Point3f vertex6=new Point3f(1.0f,1.0f,-1.0f);
private Point3f vertex7=new Point3f(1.0f,-1.0f,-1.0f);
private Point3f[] triangleVertices=
{
// front face
vertex0, vertex1, vertex2,
vertex0, vertex2, vertex3,
// back face
vertex4, vertex5, vertex6,
vertex4, vertex6, vertex7,
// right face
vertex7, vertex6, vertex1,
vertex7, vertex1, vertex0,
// left face
vertex3, vertex2, vertex5,
vertex3, vertex5, vertex4,
// top face
vertex1, vertex6, vertex5,
vertex1, vertex5, vertex2,
// bottom face
vertex3, vertex4, vertex7,
vertex3, vertex7, vertex0
};
private Point3f[]verts=
{
// front face
vertex0,
vertex1,
vertex2,
vertex3,
// back face
vertex4,
vertex5,
vertex6,
vertex7,
// right face
vertex7,
vertex6,
vertex1,
vertex0,
// left face
vertex3,
vertex2,
vertex5,
vertex4,
// top face
vertex1,
vertex6,
vertex5,
vertex2,
// bottom face
vertex3,
vertex4,
vertex7,
vertex0,
};
// set the normals
private Vector3f[]normals=
{
new Vector3f(0.0f,0.0f,1.0f), // front face
new Vector3f(0.0f,0.0f,-1.0f), // back face
new Vector3f(1.0f,0.0f,0.0f), // right face
new Vector3f(-1.0f,0.0f,0.0f), // left face
new Vector3f(0.0f,1.0f,0.0f), // top face
new Vector3f(0.0f,-1.0f,0.0f), // bottom face
};
public Cube()
{
super();
int i;
cube.setCoordinates(0,verts);
// set the normal
for(i=0;i<24;i++)
{
cube.setNormal(i,normals[i/4]);
}
// set the colours
Color3f colour[]=new Color3f[6];
colour[0]=new Color3f(1.0f, 0.0f, 0.0f);
colour[1]=new Color3f(0.0f, 1.0f, 0.0f);
colour[2]=new Color3f(0.0f, 0.0f, 1.0f);
colour[3]=new Color3f(1.0f, 1.0f, 0.0f);
colour[4]=new Color3f(0.0f, 1.0f, 1.0f);
colour[5]=new Color3f(1.0f, 0.0f, 1.0f);
for(i=0;i<24;i++)
{
cube.setColor(i,colour[i%6]);
}
setGeometry(cube);
setAppearance(new Appearance());
}
public Point3f getTriangleCoordinates(int i)
{
return triangleVertices[i];
}
public String getName()
{
return "cube";
}
public int getNumberTriangles()
{
return 12;
}
}
/////////////////////////////////////////////////////////////////////
import java.awt.AWTEvent;
import java.awt.event.*;
import java.util.Enumeration;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
/**
* KeyBehavior is a generic behavior class to take key presses and move a
* TransformGroup through a Java3D scene. The actions resulting from the
key strokes
* are modified by using the Ctrl, Alt and Shift keys.
*
* (version 1.0) reconstructed class to make more generic.
*
* MODIFIED:
* @version 1.0, 25 September 1998 aajc
* @author Andrew AJ Cain, Swinburne University, Australia
* <[EMAIL PROTECTED]>
*
* edited from code by:
* Gary S. Moss <[EMAIL PROTECTED]>
* U. S. Army Research Laboratory
*
* CLASS NAME:
* KeyBehavior
*
* PUBLIC FEATURES:
* // Data
*
* // Constructors
*
* // Methods:
*
* COLLABORATORS:
*
*/
public class KeyBehavior extends Behavior
{
protected static final double FAST_SPEED = 2.0;
protected static final double NORMAL_SPEED = 1.0;
protected static final double SLOW_SPEED = 0.5;
private TransformGroup transformGroup;
private Transform3D transform3D;
private WakeupCondition keyCriterion;
private final static double TWO_PI = (2.0 * Math.PI);
private double rotateXAmount = Math.PI / 16.0;
private double rotateYAmount = Math.PI / 16.0;
private double rotateZAmount = Math.PI / 16.0;
private double moveRate = 0.3;
private double speed = NORMAL_SPEED;
private int forwardKey = KeyEvent.VK_UP;
private int backKey = KeyEvent.VK_DOWN;
private int leftKey = KeyEvent.VK_LEFT;
private int rightKey = KeyEvent.VK_RIGHT;
public KeyBehavior( TransformGroup tg )
{
transformGroup = tg;
transform3D = new Transform3D();
}
public void initialize()
{
WakeupCriterion[] keyEvents = new WakeupCriterion[2];
keyEvents[0] = new WakeupOnAWTEvent( KeyEvent.KEY_PRESSED );
keyEvents[1] = new WakeupOnAWTEvent( KeyEvent.KEY_RELEASED );
keyCriterion = new WakeupOr( keyEvents );
wakeupOn( keyCriterion );
}
public void processStimulus( Enumeration criteria )
{
WakeupCriterion wakeup;
AWTEvent[] event;
while( criteria.hasMoreElements() )
{
wakeup = (WakeupCriterion) criteria.nextElement();
if( !(wakeup instanceof WakeupOnAWTEvent) )
continue;
event = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
for( int i = 0; i < event.length; i++ )
{
if( event[i].getID() == KeyEvent.KEY_PRESSED )
{
processKeyEvent((KeyEvent)event[i]);
}
}
}
wakeupOn( keyCriterion );
}
protected void processKeyEvent(KeyEvent event)
{
int keycode = event.getKeyCode();
if(event.isShiftDown()) speed = FAST_SPEED;
else speed = NORMAL_SPEED;
if( event.isAltDown() )
altMove(keycode);
else if( event.isControlDown())
controlMove(keycode);
else
standardMove(keycode);
}
file://moves forward backward or rotates left right
private void standardMove(int keycode)
{
if(keycode == forwardKey)
moveForward();
else if(keycode == backKey)
moveBackward();
else if(keycode == leftKey)
rotLeft();
else if(keycode == rightKey)
rotRight();
}
file://moves left right, rotate up down
protected void altMove(int keycode)
{
if(keycode == forwardKey)
rotUp();
else if(keycode == backKey)
rotDown();
else if(keycode == leftKey)
moveLeft();
else if(keycode == rightKey)
moveRight();
}
file://move up down, rot left right
protected void controlMove(int keycode)
{
if(keycode == forwardKey)
moveUp();
else if(keycode == backKey)
moveDown();
else if(keycode == leftKey)
rollLeft();
else if(keycode == rightKey)
rollRight();
}
private void moveForward()
{
doMove(new Vector3d(0.0,0.0, -getMovementRate()));
}
private void moveBackward()
{
doMove(new Vector3d(0.0,0.0, getMovementRate()));
}
private void moveLeft()
{
doMove(new Vector3d( -getMovementRate() ,0.0,0.0));
}
private void moveRight()
{
doMove(new Vector3d(getMovementRate(),0.0,0.0));
}
private void moveUp()
{
doMove(new Vector3d(0.0, getMovementRate() ,0.0));
}
private void moveDown()
{
doMove(new Vector3d(0.0, -getMovementRate() ,0.0));
}
protected void rotRight()
{
doRotateY(getRotateRightAmount());
}
protected void rotUp()
{
doRotateX(getRotateUpAmount());
}
protected void rotLeft()
{
doRotateY(getRotateLeftAmount());
}
protected void rotDown()
{
doRotateX(getRotateDownAmount());
}
protected void rollLeft()
{
doRotateZ(getRollLeftAmount());
}
protected void rollRight()
{
doRotateZ(getRollRightAmount());
}
protected void doRotateY(double radians)
{
transformGroup.getTransform(transform3D);
Transform3D toMove = new Transform3D();
toMove.rotY(radians);
transform3D.mul(toMove);
transformGroup.setTransform(transform3D);
}
protected void doRotateX(double radians)
{
transformGroup.getTransform(transform3D);
Transform3D toMove = new Transform3D();
toMove.rotX(radians);
transform3D.mul(toMove);
transformGroup.setTransform(transform3D);
}
protected void doRotateZ(double radians)
{
transformGroup.getTransform(transform3D);
Transform3D toMove = new Transform3D();
toMove.rotZ(radians);
transform3D.mul(toMove);
transformGroup.setTransform(transform3D);
}
protected void doMove(Vector3d theMove)
{
transformGroup.getTransform(transform3D);
Transform3D toMove = new Transform3D();
toMove.setTranslation(theMove);
transform3D.mul(toMove);
transformGroup.setTransform(transform3D);
}
protected double getMovementRate()
{
return moveRate * speed;
}
protected double getRollLeftAmount()
{
return rotateZAmount * speed;
}
protected double getRollRightAmount()
{
return -rotateZAmount * speed;
}
protected double getRotateUpAmount()
{
return rotateYAmount * speed;
}
protected double getRotateDownAmount()
{
return -rotateYAmount * speed;
}
protected double getRotateLeftAmount()
{
return rotateYAmount * speed;
}
protected double getRotateRightAmount()
{
return -rotateYAmount * speed;
}
public void setRotateXAmount(double radians)
{
rotateXAmount = radians;
}
public void setRotateYAmount(double radians)
{
rotateYAmount = radians;
}
public void setRotateZAmount(double radians)
{
rotateZAmount = radians;
}
public void setMovementRate(double meters)
{
moveRate = meters; // Travel rate in meters/frame
}
public void setForwardKey(int key)
{
forwardKey = key;
}
public void setBackKey(int key)
{
backKey = key;
}
public void setLeftKey(int key)
{
leftKey = key;
}
public void setRightKey(int key)
{
rightKey = key;
}
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.picking.*;
public class Octahedron extends myShape
{
private Point3f vertex0=new Point3f(0.0f,0.0f,-1.5f);
private Point3f vertex1=new Point3f(0.0f,0.0f,1.5f);
private Point3f vertex2=new Point3f(0.0f,-1.0f,0.0f);
private Point3f vertex3=new Point3f(0.0f,1.0f,0.0f);
private Point3f vertex4=new Point3f(1.0f,0.0f,0.0f);
private Point3f vertex5=new Point3f(-1.0f,0.0f,0.0f);
private int noFaces=8;
private int noVertices=24;
private Point3f[] vertices=
{
vertex4, vertex2, vertex0, // front 4 faces
vertex4, vertex0, vertex3,
vertex4, vertex3, vertex1,
vertex4, vertex1, vertex2,
vertex5, vertex1, vertex3, // back 4 faces
vertex5, vertex3, vertex0,
vertex5, vertex0, vertex2,
vertex5, vertex2, vertex1,
};
private Point2f texCoord[] =
{
new Point2f(0.0f, 0.0f),
new Point2f(1.0f, 0.0f),
new Point2f(0.5f,((float)Math.sqrt(3.0))/2.0f),
};
public Octahedron()
{
int i;
TriangleArray tetra=new TriangleArray(noVertices,TriangleArray.COORDINATES|
TriangleArray.NORMALS|TriangleArray.TEXTURE_COORDINATE_2|TriangleArray.COLOR_3);
// set the vertex points
tetra.setCoordinates(0,vertices);
// set the texture coordintaes
for (i = 0;i<noVertices;i++)
{
tetra.setTextureCoordinate(i,texCoord[i%3]);
}
// set the colours
Color3f colour[]=new Color3f[6];
colour[0]=new Color3f(1.0f, 0.0f, 0.0f);
colour[1]=new Color3f(0.0f, 1.0f, 0.0f);
colour[2]=new Color3f(0.0f, 0.0f, 1.0f);
colour[3]=new Color3f(1.0f, 1.0f, 0.0f);
colour[4]=new Color3f(0.0f, 1.0f, 1.0f);
colour[5]=new Color3f(1.0f, 0.0f, 1.0f);
for(i=0;i<noVertices;i++)
{
tetra.setColor(i,colour[i%6]);
}
// set the normals
int face;
Vector3f normal=new Vector3f();
Vector3f vector1=new Vector3f();
Vector3f vector2=new Vector3f();
Point3f [] points=new Point3f[3];
for(i=0;i<3;i++)points[i]=new Point3f();
for(face=0;face<noVertices/3;face++)
{
tetra.getCoordinates(face*3,points);
vector1.sub(points[1],points[0]);
vector2.sub(points[2],points[0]);
normal.cross(vector1,vector2);
normal.normalize();
for (i=0;i<3;i++)
{
tetra.setNormal((face*3+i),normal);
}
}
// create the shape
Appearance thisAppearance=new Appearance();
this.setGeometry(tetra);
this.setAppearance(thisAppearance);
}
public Point3f getTriangleCoordinates(int i)
{
return vertices[i];
}
public String getName()
{
return "octahedron";
}
public int getNumberTriangles()
{
return vertices.length/3;
}
}
/////////////////////////////////////////////////////////////////////
/*
* @(#)PickMouseBehavior.java 1.1 99/04/13 15:39:24
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to
use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies
of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* 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.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or
in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* Base class that allows users to adding picking and mouse manipulation to
* his scene graph (see PickDragBehavior for an example of how to extend
* this base class). This class is useful for interactive apps.
*/
public abstract class PickMouseBehavior extends Behavior {
/**
* Portion of the scene graph to operate picking on.
*/
protected PickObject pickScene;
protected WakeupCriterion[] conditions;
protected WakeupOr wakeupCondition;
protected boolean buttonPress = false;
protected TransformGroup currGrp;
protected static final boolean debug = false;
protected MouseEvent mevent;
/**
* Creates a PickMouseBehavior given current canvas, root of the tree to
* operate on, and the bounds.
*/
public PickMouseBehavior(Canvas3D canvas, BranchGroup root, Bounds
bounds){
super();
currGrp = new TransformGroup();
currGrp.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
currGrp.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
root.addChild(currGrp);
pickScene = new PickObject(canvas, root);
}
public void initialize() {
conditions = new WakeupCriterion[2];
conditions[0] = new WakeupOnAWTEvent(Event.MOUSE_MOVE);
conditions[1] = new WakeupOnAWTEvent(Event.MOUSE_DOWN);
wakeupCondition = new WakeupOr(conditions);
wakeupOn(wakeupCondition);
}
private void processMouseEvent(MouseEvent evt) {
buttonPress = false;
if (evt.getID()==MouseEvent.MOUSE_PRESSED |
evt.getID()==MouseEvent.MOUSE_CLICKED) {
buttonPress = true;
return;
}
else if (evt.getID() == MouseEvent.MOUSE_MOVED) {
// Process mouse move event
}
}
public void processStimulus (Enumeration criteria) {
WakeupCriterion wakeup;
AWTEvent[] evt = null;
int xpos = 0, ypos = 0;
while(criteria.hasMoreElements()) {
wakeup = (WakeupCriterion)criteria.nextElement();
if (wakeup instanceof WakeupOnAWTEvent)
evt = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
}
if (evt[0] instanceof MouseEvent){
mevent = (MouseEvent) evt[0];
if (debug)
System.out.println("got mouse event");
processMouseEvent((MouseEvent)evt[0]);
xpos = mevent.getPoint().x;
ypos = mevent.getPoint().y;
}
if (debug)
System.out.println("mouse position " + xpos + " " + ypos);
if (buttonPress){
updateScene(xpos, ypos);
}
wakeupOn (wakeupCondition);
}
/**
* Sets the pickMode for this behavior
* @param mode The pick mode, either USE_GEOMETRY or USE_BOUNDS
*/
public void setPickMode(int pickMode) {
pickScene.setPickMode(pickMode);
}
/**
* Returns the pickMode for this behavior
*/
public int getPickMode() {
return pickScene.getPickMode();
}
/**
* Sets the pick geometry shape type for this behavior
* @param type The pick shape type, either SHAPE_RAY, SHAPE_APERTURE or
* SHAPE_RAY_APERTURE. The default is SHAPE_RAY.
*/
public void setPickShapeMode(int type) {
pickScene.setPickShapeMode(type);
}
/**
* Returns the pick geometry shape type
*/
public int getPickShapeMode() {
return pickScene.getPickShapeMode();
}
/**
* Sets the pick aperture for SHAPE_APERTURE mode for this behavior
* @param Point[] aperturePts The pick aperture, which should be a convex,
* counter-clockwise loop of Points around 0,0
*/
public void setPickAperture(Point[] aperturePts) {
pickScene.setPickAperture(aperturePts);
}
/**
* Returns the pick aperture for SHAPE_APERTURE mode for this behavior
*/
public Point[] getPickAperture() {
return pickScene.getPickAperture();
}
/** Subclasses shall implement this update function
*/
public abstract void updateScene(int xpos, int ypos);
}
/////////////////////////////////////////////////////////////////////
/*
* @(#)PickZoomBehavior.java 1.1 99/04/13 15:39:26
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.*/
import com.sun.j3d.utils.behaviors.mouse.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* A mouse behavior that allows user to pick and zoom scene graph objects.
* Common usage: 1. Create your scene graph. 2. Create this behavior with
* the root and canvas.
*/
public class PickZoomBehavior extends PickMouseBehavior implements
com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback {
MouseZoom zoom;
private PickingCallback callback = null;
private TransformGroup currentTG;
/**
* Creates a pick/zoom behavior that waits for user mouse events for
* the scene graph. This constructor initializes the pickMode to
* BOUNDS picking.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
**/
public PickZoomBehavior(BranchGroup root, Canvas3D canvas, Bounds bounds){
super(canvas, root, bounds);
zoom = new MouseZoom(MouseBehavior.MANUAL_WAKEUP);
zoom.setTransformGroup(currGrp);
currGrp.addChild(zoom);
zoom.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
}
/**
* Creates a pick/zoom behavior that waits for user mouse events for
* the scene graph. This constructor sets the pick mode.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
* @param pickMode specifies PickObject.USE_BOUNDS or
PickObject.USE_GEOMETRY.
* Note: If pickMode is set to PickObject.USE_GEOMETRY, all the geometry
* objects in the scene graph that allow picking must have the
* ALLOW_INTERSECT bit set.
*/
public PickZoomBehavior(BranchGroup root, Canvas3D canvas, Bounds bounds,
int pickMode){
super(canvas, root, bounds);
zoom = new MouseZoom(MouseBehavior.MANUAL_WAKEUP);
zoom.setTransformGroup(currGrp);
currGrp.addChild(zoom);
zoom.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
pickScene.setPickMode(pickMode);
}
/**
* Update the scene to manipulate any nodes. This is not meant to be
* called by users. Behavior automatically calls this. You can call
* this only if you know what you are doing.
*
* @param xpos Current mouse X pos.
* @param ypos Current mouse Y pos.
**/
public void updateScene(int xpos, int ypos){
TransformGroup tg = null;
if (mevent.isAltDown() && !mevent.isMetaDown()){
tg =(TransformGroup)pickScene.pickNode(pickScene.pickClosest(xpos,
ypos),
PickObject.TRANSFORM_GROUP);
// Check for valid selection
if ((tg != null) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_READ)) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_WRITE))){
zoom.setTransformGroup(tg);
zoom.wakeup();
currentTG = tg;
} else if (callback!=null)
callback.transformChanged( PickingCallback.NO_PICK, null );
}
}
/**
* Callback method from MouseZoom
* This is used when the Picking callback is enabled
*/
public void transformChanged( int type, Transform3D transform ) {
callback.transformChanged( PickingCallback.ZOOM, currentTG );
}
/**
* Register the class @param callback to be called each
* time the picked object moves
*/
public void setupCallback( PickingCallback callback ) {
this.callback = callback;
if (callback==null)
zoom.setupCallback( null );
else
zoom.setupCallback( this );
}
}
/////////////////////////////////////////////////////////////////////
/*
* @(#)PickRotateBehavior.java 1.1 99/04/13 15:39:25
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to
use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies
of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* 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.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or
in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import com.sun.j3d.utils.behaviors.mouse.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* A mouse behavior that allows user to pick and drag scene graph objects.
* Common usage:
* <p>
* 1. Create your scene graph.
* <p>
* 2. Create this behavior with root and canvas.
* <p>
* <blockquote><pre>
* PickRotateBehavior behavior = new PickRotateBehavior(canvas, root,
bounds);
* root.addChild(behavior);
* </pre></blockquote>
* <p>
* The above behavior will monitor for any picking events on
* the scene graph (below root node) and handle mouse drags on pick hits.
* Note the root node can also be a subgraph node of the scene graph (rather
* than the topmost).
*/
public class PickRotateBehavior extends PickMouseBehavior implements
com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback {
MouseRotate drag;
private PickingCallback callback=null;
private TransformGroup currentTG;
/**
* Creates a pick/rotate behavior that waits for user mouse events for
* the scene graph. This constructor initializes pickMode to BOUNDS
picking.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
**/
public PickRotateBehavior(BranchGroup root, Canvas3D canvas, Bounds
bounds){
super(canvas, root, bounds);
drag = new MouseRotate(MouseRotate.MANUAL_WAKEUP);
drag.setTransformGroup(currGrp);
currGrp.addChild(drag);
drag.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
}
/**
* Creates a pick/rotate behavior that waits for user mouse events for
* the scene graph. This constructor specifies the pickMode.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
* @param pickMode specifies PickObject.USE_BOUNDS or
PickObject.USE_GEOMETRY.
* Note: If pickMode is set to PickObject.USE_GEOMETRY, all the geometry
* objects in the scene graph that allow picking must have the
* ALLOW_INTERSECT bit set.
*/
public PickRotateBehavior(BranchGroup root, Canvas3D canvas, Bounds
bounds,
int pickMode) {
super(canvas, root, bounds);
drag = new MouseRotate(MouseRotate.MANUAL_WAKEUP);
drag.setTransformGroup(currGrp);
currGrp.addChild(drag);
drag.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
pickScene.setPickMode(pickMode);
}
/**
* Update the scene to manipulate any nodes. This is not meant to be
* called by users. Behavior automatically calls this. You can call
* this only if you know what you are doing.
*
* @param xpos Current mouse X pos.
* @param ypos Current mouse Y pos.
**/
public void updateScene(int xpos, int ypos){
TransformGroup tg = null;
if (!mevent.isMetaDown() && !mevent.isAltDown()){
tg =(TransformGroup)pickScene.pickNode(pickScene.pickClosest(xpos,
ypos),
PickObject.TRANSFORM_GROUP);
// Make sure the selection exists and is movable.
if ((tg != null) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_READ)) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_WRITE))){
drag.setTransformGroup(tg);
drag.wakeup();
currentTG = tg;
} else if (callback!=null)
callback.transformChanged( PickingCallback.NO_PICK, null );
}
}
/**
* Callback method from MouseRotate
* This is used when the Picking callback is enabled
*/
public void transformChanged( int type, Transform3D transform ) {
callback.transformChanged( PickingCallback.ROTATE, currentTG );
}
/**
* Register the class @param callback to be called each
* time the picked object moves
*/
public void setupCallback( PickingCallback callback ) {
this.callback = callback;
if (callback==null)
drag.setupCallback( null );
else
drag.setupCallback( this );
}
}
/////////////////////////////////////////////////////////////////////
/*
* @(#)PickTranslateBehavior.java 1.1 99/04/13 15:39:25
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to
use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies
of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* 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.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or
in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import com.sun.j3d.utils.behaviors.mouse.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* A mouse behavior that allows user to pick and translate scene graph
objects.
* Common usage: 1. Create your scene graph. 2. Create this behavior with
* the root and canvas. See PickRotateBehavior for more details.
*/
public class PickTranslateBehavior extends PickMouseBehavior implements
com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback {
MouseTranslate translate;
private PickingCallback callback = null;
private TransformGroup currentTG;
/**
* Creates a pick/translate behavior that waits for user mouse events for
* the scene graph. This constructor initializes the pickMode BOUNDS
picking.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
**/
public PickTranslateBehavior(BranchGroup root, Canvas3D canvas, Bounds
bounds){
super(canvas, root, bounds);
translate = new MouseTranslate(MouseBehavior.MANUAL_WAKEUP);
translate.setTransformGroup(currGrp);
currGrp.addChild(translate);
translate.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
}
/**
* Creates a pick/translate behavior that waits for user mouse events for
* the scene graph. This method specifies the pick mode.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
* @param pickMode specifies PickObject.USE_BOUNDS or
PickObject.USE_GEOMETRY.
* Note: If pickMode is set to PickObject.USE_GEOMETRY, all the geometry
* objects in the scene graph that allow picking must have the
* ALLOW_INTERSECT bit set.
*/
public PickTranslateBehavior(BranchGroup root, Canvas3D canvas, Bounds
bounds,
int pickMode){
super(canvas, root, bounds);
translate = new MouseTranslate(MouseBehavior.MANUAL_WAKEUP);
translate.setTransformGroup(currGrp);
currGrp.addChild(translate);
translate.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
pickScene.setPickMode(pickMode);
}
/**
* Update the scene to manipulate any nodes. This is not meant to be
* called by users. Behavior automatically calls this. You can call
* this only if you know what you are doing.
*
* @param xpos Current mouse X pos.
* @param ypos Current mouse Y pos.
**/
public void updateScene(int xpos, int ypos){
TransformGroup tg = null;
if (!mevent.isAltDown() && mevent.isMetaDown()){
tg =(TransformGroup)pickScene.pickNode(pickScene.pickClosest(xpos,
ypos),
PickObject.TRANSFORM_GROUP);
file://Check for valid selection.
if ((tg != null) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_READ)) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_WRITE))){
translate.setTransformGroup(tg);
translate.wakeup();
currentTG = tg;
} else if (callback!=null)
callback.transformChanged( PickingCallback.NO_PICK, null );
}
}
/**
* Callback method from MouseTranslate
* This is used when the Picking callback is enabled
*/
public void transformChanged( int type, Transform3D transform ) {
callback.transformChanged( PickingCallback.TRANSLATE, currentTG );
}
/**
* Register the class @param callback to be called each
* time the picked object moves
*/
public void setupCallback( PickingCallback callback ) {
this.callback = callback;
if (callback==null)
translate.setupCallback( null );
else
translate.setupCallback( this );
}
}
/////////////////////////////////////////////////////////////////////
/*
* @(#)PickZoomBehavior.java 1.1 99/04/13 15:39:26
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.*/
import com.sun.j3d.utils.behaviors.mouse.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
/**
* A mouse behavior that allows user to pick and zoom scene graph objects.
* Common usage: 1. Create your scene graph. 2. Create this behavior with
* the root and canvas.
*/
public class PickZoomBehavior extends PickMouseBehavior implements
com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback {
MouseZoom zoom;
private PickingCallback callback = null;
private TransformGroup currentTG;
/**
* Creates a pick/zoom behavior that waits for user mouse events for
* the scene graph. This constructor initializes the pickMode to
* BOUNDS picking.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
**/
public PickZoomBehavior(BranchGroup root, Canvas3D canvas, Bounds bounds){
super(canvas, root, bounds);
zoom = new MouseZoom(MouseBehavior.MANUAL_WAKEUP);
zoom.setTransformGroup(currGrp);
currGrp.addChild(zoom);
zoom.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
}
/**
* Creates a pick/zoom behavior that waits for user mouse events for
* the scene graph. This constructor sets the pick mode.
* @param root Root of your scene graph.
* @param canvas Java 3D drawing canvas.
* @param bounds Bounds of your scene.
* @param pickMode specifies PickObject.USE_BOUNDS or
PickObject.USE_GEOMETRY.
* Note: If pickMode is set to PickObject.USE_GEOMETRY, all the geometry
* objects in the scene graph that allow picking must have the
* ALLOW_INTERSECT bit set.
*/
public PickZoomBehavior(BranchGroup root, Canvas3D canvas, Bounds bounds,
int pickMode){
super(canvas, root, bounds);
zoom = new MouseZoom(MouseBehavior.MANUAL_WAKEUP);
zoom.setTransformGroup(currGrp);
currGrp.addChild(zoom);
zoom.setSchedulingBounds(bounds);
this.setSchedulingBounds(bounds);
pickScene.setPickMode(pickMode);
}
/**
* Update the scene to manipulate any nodes. This is not meant to be
* called by users. Behavior automatically calls this. You can call
* this only if you know what you are doing.
*
* @param xpos Current mouse X pos.
* @param ypos Current mouse Y pos.
**/
public void updateScene(int xpos, int ypos){
TransformGroup tg = null;
if (mevent.isAltDown() && !mevent.isMetaDown()){
tg =(TransformGroup)pickScene.pickNode(pickScene.pickClosest(xpos,
ypos),
PickObject.TRANSFORM_GROUP);
// Check for valid selection
if ((tg != null) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_READ)) &&
(tg.getCapability(TransformGroup.ALLOW_TRANSFORM_WRITE))){
zoom.setTransformGroup(tg);
zoom.wakeup();
currentTG = tg;
} else if (callback!=null)
callback.transformChanged( PickingCallback.NO_PICK, null );
}
}
/**
* Callback method from MouseZoom
* This is used when the Picking callback is enabled
*/
public void transformChanged( int type, Transform3D transform ) {
callback.transformChanged( PickingCallback.ZOOM, currentTG );
}
/**
* Register the class @param callback to be called each
* time the picked object moves
*/
public void setupCallback( PickingCallback callback ) {
this.callback = callback;
if (callback==null)
zoom.setupCallback( null );
else
zoom.setupCallback( this );
}
}
/////////////////////////////////////////////////////////////////////
/*
* @(#)PickingCallback.java 1.1 99/04/13 15:39:26
*
* Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to
use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies
of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* 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.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or
in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
/**
* @Author Paul Byrne
*/
import javax.media.j3d.TransformGroup;
public interface PickingCallback {
public final static int ROTATE=0;
public final static int TRANSLATE=1;
public final static int ZOOM=2;
/**
* The user made a selection but nothing was
* actually picked
*/
public final static int NO_PICK=3;
/**
* Called by the Pick Behavior with which this callback
* is registered each time the Picked object is moved
*/
public void transformChanged( int type, TransformGroup tg );
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.picking.*;
public class Tetrahedron extends myShape
{
private Point3f vertex1=new Point3f(1.0f,1.0f,1.0f);
private Point3f vertex2=new Point3f(1.0f,-1.0f,-1.0f);
private Point3f vertex3=new Point3f(-1.0f,-1.0f,1.0f);
private Point3f vertex4=new Point3f(-1.0f,1.0f,-1.0f);
private Point3f[] vertices=
{
vertex1, vertex2, vertex4, // front face
vertex1, vertex4, vertex3, // left, back face
vertex2, vertex3, vertex4, // right, back face
vertex1, vertex3, vertex2, // bottom face
};
private Point2f texCoord[] =
{
new Point2f(0.0f, 0.0f),
new Point2f(1.0f, 0.0f),
new Point2f(0.5f,((float)Math.sqrt(3.0))/2.0f),
};
public Tetrahedron()
{
int i;
TriangleArray tetra=new TriangleArray(12,TriangleArray.COORDINATES|
TriangleArray.NORMALS|TriangleArray.TEXTURE_COORDINATE_2|TriangleArray.COLOR_3);
// set the vertex points
tetra.setCoordinates(0,vertices);
for (i = 0; i < 12; i++)
{
tetra.setTextureCoordinate(i,texCoord[i%3]);
}
// set the colours
tetra.setColor(0,new Color3f(1.0f,0.0f,0.0f));
tetra.setColor(1,new Color3f(0.0f,1.0f,0.0f));
tetra.setColor(2,new Color3f(0.0f,0.0f,1.0f));
tetra.setColor(3,new Color3f(1.0f,1.0f,0.0f));
tetra.setColor(4,new Color3f(0.0f,1.0f,1.0f));
tetra.setColor(5,new Color3f(1.0f,0.0f,1.0f));
tetra.setColor(6,new Color3f(1
.0f,0.0f,0.0f));
tetra.setColor(7,new Color3f(0.0f,1.0f,0.0f));
tetra.setColor(8,new Color3f(0.0f,0.0f,1.0f));
tetra.setColor(9,new Color3f(1.0f,1.0f,0.0f));
tetra.setColor(10,new Color3f(0.0f,1.0f,1.0f));
tetra.setColor(11,new Color3f(1.0f,0.0f,1.0f));
// set the normals
int face;
Vector3f normal=new Vector3f();
Vector3f vector1=new Vector3f();
Vector3f vector2=new Vector3f();
Point3f [] points=new Point3f[3];
for(i=0;i<3;i++)points[i]=new Point3f();
for(face=0;face<4;face++)
{
tetra.getCoordinates(face*3,points);
vector1.sub(points[1],points[0]);
vector2.sub(points[2],points[0]);
normal.cross(vector1,vector2);
normal.normalize();
for (i=0;i<3;i++)
{
tetra.setNormal((face*3+i),normal);
}
}
// create the shape
Appearance thisAppearance=new Appearance();
this.setGeometry(tetra);
this.setAppearance(thisAppearance);
}
public Point3f getTriangleCoordinates(int i)
{
return vertices[i];
}
public String getName()
{
return "tetrahedron";
}
public int getNumberTriangles()
{
return vertices.length/3;
}
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.picking.*;
public class convergingLens extends myShape
{
private float radius=1.0f;
private float halfOuterLength=0.4f;
private float oneOverSquRoot2=0.707107f;
// 8 vertices going anticlockwise round the perimeter
private Point3f vertex0=new Point3f(radius,0.0f,0.0f);
private Point3f vertex1=new
Point3f(radius*oneOverSquRoot2,radius*oneOverSquRoot2,0.0f);
private Point3f vertex2=new Point3f(0.0f,radius,0.0f);
private Point3f vertex3=new Point3f(-radius*oneOverSquRoot2,radius*oneOver
SquRoot2,0.0f);
private Point3f vertex4=new Point3f(-radius,0.0f,0.0f);
private Point3f vertex5=new
Point3f(-radius*oneOverSquRoot2,-radius*oneOverSquRoot2,0.0f);
private Point3f vertex6=new Point3f(0.0f,-radius,0.0f);
private Point3f vertex7=new
Point3f(radius*oneOverSquRoot2,-radius*oneOverSquRoot2,0.0f);
// vertex in front
private Point3f vertex8=new Point3f(0.0f,0.0f,halfOuterLength);
// vertex behind
private Point3f vertex9=new Point3f(0.0f,0.0f,-halfOuterLength);
private Point3f[] vertices=
{
// front face going anticlockwise
vertex8, vertex0, vertex1,
vertex8, vertex1, vertex2,
vertex8, vertex2, vertex3,
vertex8, vertex3, vertex4,
vertex8, vertex4, vertex5,
vertex8, vertex5, vertex6,
vertex8, vertex6, vertex7,
vertex8, vertex7, vertex0,
// back face
vertex9, vertex4, vertex3,
vertex9, vertex3, vertex2,
vertex9, vertex2, vertex1,
vertex9, vertex1, vertex0,
vertex9, vertex0, vertex7,
vertex9, vertex7, vertex6,
vertex9, vertex6, vertex5,
vertex9, vertex5, vertex4
};
private Point2f texCoord[]=
{
new Point2f(0.0f, 0.0f),
new Point2f(1.0f, 0.0f),
new Point2f(0.5f,((float)Math.sqrt(3.0))/2.0f)
};
private Color3f colour[]=
{
new Color3f(1.0f, 0.0f, 0.0f),
new Color3f(0.0f, 1.0f, 0.0f),
new Color3f(0.0f, 0.0f, 1.0f),
new Color3f(1.0f, 1.0f, 0.0f),
new Color3f(0.0f, 1.0f, 1.0f),
new Color3f(1.0f, 0.0f, 1.0f)
};
public convergingLens()
{
int i;
TriangleArray tetra=new
TriangleArray(vertices.length,TriangleArray.COORDINATES|
TriangleArray.NORMALS|TriangleArray.TEXTURE_COORDINATE_2|TriangleArray.COLOR
_3);
// set the vertex points
tetra.setCoordinates(0,vertices);
for(i=0;i<vertices.length;i++)
{
tetra.setTextureCoordinate(i,texCoord[i%3]);
}
// set the colours
for(i=0;i<vertices.length;i++)
{
tetra.setColor(i,colour[i%6]);
}
// set the normals
int face;
Vector3f normal=new Vector3f();
Vector3f vector1=new Vector3f();
Vector3f vector2=new Vector3f();
Point3f [] points=new Point3f[3];
for(i=0;i<3;i++)points[i]=new Point3f();
for(face=0;face<vertices.length/3;face++)
{
tetra.getCoordinates(face*3,points);
vector1.sub(points[1],points[0]);
vector2.sub(points[2],points[0]);
normal.cross(vector1,vector2);
normal.normalize();
for (i=0;i<3;i++)
{
tetra.setNormal((face*3+i),normal);
}
}
// create the shape
Appearance thisAppearance=new Appearance();
this.setGeometry(tetra);
this.setAppearance(thisAppearance);
}
public String getName()
{
return "converging lens";
}
public Point3f getTriangleCoordinates(int i)
{
return vertices[i];
}
public int getNumberTriangles()
{
return vertices.length/3;
}
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.picking.*;
public class divergingLens extends myShape
{
private float oneOverSquRoot2=0.707107f;
private float radius=1.0f;
private float halflength=0.3f;
private float halfInnerLength=0.1f;
// 8 vertices going anticlockwise round the perimeter at the front
private Point3f vertex0=new Point3f(radius,0.0f,halflength);
private Point3f vertex1=new
Point3f(radius*oneOverSquRoot2,radius*oneOverSquRoot2,halflength);
private Point3f vertex2=new Point3f(0.0f,radius,halflength);
private Point3f vertex3=new
Point3f(-radius*oneOverSquRoot2,radius*oneOverSquRoot2,halflength)
;
private Point3f vertex4=new Point3f(-radius,0.0f,halflength);
private Point3f vertex5=new
Point3f(-radius*oneOverSquRoot2,-radius*oneOverSquRoot2,halflength);
private Point3f vertex6=new Point3f(0.0f,-radius,halflength);
private Point3f vertex7=new
Point3f(radius*oneOverSquRoot2,-radius*oneOverSquRoot2,halflength);
// 8 vertices going anticlockwise round the perimeter at the back
private Point3f vertex0b=new Point3f(radius,0.0f,-halflength);
private Point3f vertex1b=new
Point3f(radius*oneOverSquRoot2,radius*oneOverSquRoot2,-halflength);
private Point3f vertex2b=new Point3f(0.0f,radius,-halflength);
private Point3f vertex3b=new
Point3f(-radius*oneOverSquRoot2,radius*oneOverSquRoot2,-halflength);
private Point3f vertex4b=new Point3f(-radius,0.0f,-halflength);
private Point3f vertex5b=new
Point3f(-radius*oneOverSquRoot2,-radius*oneOverSquRoot2,-halflength);
private Point3f vertex6b=new Point3f(0.0f,-radius,-halflength);
private Point3f vertex7b=new
Point3f(radius*oneOverSquRoot2,-radius*oneOverSquRoot2,-halflength);
// vertex in front
private Point3f vertex8=new Point3f(0.0f,0.0f,halfInnerLength);
// vertex behind
private Point3f vertex9=new Point3f(0.0f,0.0f,-halfInnerLength);
private Point3f[] vertices=
{
// front face going anticlockwise
vertex8, vertex0, vertex1,
vertex8, vertex1, vertex2,
vertex8, vertex2, vertex3,
vertex8, vertex3, vertex4,
vertex8, vertex4, vertex5,
vertex8, vertex5, vertex6,
vertex8, vertex6, vertex7,
vertex8, vertex7, vertex0,
// back face
vertex9, vertex4b, vertex3b,
vertex9, vertex3b, vertex2b,
vertex9, vertex2b, vertex1b,
vertex9, vertex1b, vertex0b,
vertex9, vertex0b, vertex7b,
vertex9, vertex7b, vertex6b,
vertex9, vertex6b, vertex5b,
vertex9, vertex5b, vertex4b,
// sides
vertex0, vertex0b, vertex1b,
vertex0, vertex1b, vertex1,
vertex1, vertex1b, vertex2b,
vertex1, vertex2b, vertex2,
vertex2, vertex2b, vertex3b,
vertex2, vertex3b, vertex3,
vertex3, vertex3b, vertex4b,
vertex3, vertex4b, vertex4,
vertex4, vertex4b, vertex5b,
vertex4, vertex5b, vertex5,
vertex5, vertex5b, vertex6b,
vertex5, vertex6b, vertex6,
vertex6, vertex6b, vertex7b,
vertex6, vertex7b, vertex7,
vertex7, vertex7b, vertex0b,
vertex7, vertex0b, vertex0
};
private Point2f texCoord[] =
{
new Point2f(0.0f, 0.0f),
new Point2f(1.0f, 0.0f),
new Point2f(0.5f,((float)Math.sqrt(3.0))/2.0f)
};
private Color3f colour[]=
{
new Color3f(1.0f, 0.0f, 0.0f),
new Color3f(0.0f, 1.0f, 0.0f),
new Color3f(0.0f, 0.0f, 1.0f),
new Color3f(1.0f, 1.0f, 0.0f),
new Color3f(0.0f, 1.0f, 1.0f),
new Color3f(1.0f, 0.0f, 1.0f)
};
public divergingLens()
{
int i;
TriangleArray tetra=new
TriangleArray(vertices.length,TriangleArray.COORDINATES|
TriangleArray.NORMALS|TriangleArray.TEXTURE_COORDINATE_2|TriangleArray.COLOR
_3);
// set the vertex points
tetra.setCoordinates(0,vertices);
for(i=0;i<vertices.length;i++)
{
tetra.setTextureCoordinate(i,texCoord[i%3]);
}
// set the colours
for(i=0;i<vertices.length;i++)
{
tetra.setColor(i,colour[i%6]);
}
// set the normals
int face;
Vector3f normal=new Vector3f();
Vector3f vector1=new Vector3f();
Vector3f vector2=new Vector3f();
Point3f [] points=new Point3f[3];
for(i=0;i<3;i++)points[i]=new Point3f();
for(face=0;face<vertices.length/3;face++)
{
tetra.getCoordinates(face*3,points);
vector1.sub(points[1],points[0]);
vector2.sub(points[2],points[0]);
normal.cross(vector1,vector2);
normal.normalize();
for (i=0;i<3;i++)
{
tetra.setNormal((face*3+i),normal);
}
}
// create the shape
Appearance thisAppearance=new Appearance();
this.setGeometry(tetra);
this.setAppearance(thisAppearance);
}
public String getName()
{
return"diverging lens";
}
public Point3f getTriangleCoordinates(int i)
{
return vertices[i];
}
public int getNumberTriangles()
{
return vertices.length/3;
}
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
public class lightBeam extends Shape3D
{
ColoringAttributes theseColouringAttributes;
Appearance thisAppearance=new Appearance();
Point3f[] vertices;
TriangleStripArray beam;
// yellow beam, extends along x axis with a length of 5 and a radius of 0.2
public lightBeam()
{
this(new Color3f(0.8f,0.8f,0.0f),0.2,5);
}
// Constructs a beam along x axis with a length of 5 and a radius of 0.2
// with the specified colour
public lightBeam(Color3f colour)
{
this(colour,0.2,5);
}
// Constructs a yellow beam along x axis with the specified length and a radius of 0.2
public lightBeam(double thisLength)
{
this(new Color3f(0.8f,0.8f,0.0f),0.2,thisLength);
}
// Constructs a yellow beam along x axis with the specified length and a radius of 0.2
public lightBeam(Color3f colour,double thisLength)
{
this(colour,0.2,thisLength);
}
// Constructs a lightBeam with the specified colour and geometry
// parameters: colour, radius, length
public lightBeam(Color3f colour,double radius,double length)
{
// set up the geometry array
int segmentCount=12; // number of segments in the beam
int beamVertexCount=(segmentCount+1)*2+2; // number of vertices in total
int beamStripCount[]=new int[1]; // number of
vertices per triangle strip
beamStripCount[0]=beamVertexCount;
beam=new TriangleStripArray(beamVertexCount,
GeometryArray.COORDINATES|GeometryArray.NORMALS,beamStripCount);
// The angle subtended by a single segment
double segmentAngle=2*Math.PI/segmentCount;
double thisAngle=0;
// the coordinates of a point on the perimeter
float yCoord,zCoord;
// The direction of a normal ray from the beam's centre
float normalY,normalZ;
for(int count=0;count<beamVertexCount-3;count++)
// not very good. I've got a seam on my cylinder; overlapping
triangles!
// I should probably use quadrilaterals
{
yCoord=(float)(radius*Math.cos(thisAngle));
zCoord=(float)(radius*Math.sin(thisAngle));
normalY=(float)Math.sin(thisAngle);
normalZ=(float)Math.cos(thisAngle);
beam.setCoordinate(count,new float[]{(float)length,yCoord,zCoord});
beam.setNormal(count,new float[]{(float)length,normalY,normalZ});
count++;
beam.setCoordinate(count,new float[]{0f,yCoord,zCoord});
beam.setNormal(count,new float[]{0f,normalY,normalZ});
thisAngle+=segmentAngle;
}
setGeometry(beam);
// Set up ray appearance and colouring capability
theseColouringAttributes=new ColoringAttributes();
Color3f yellow=new Color3f(0.8f,0.8f,0.0f);
theseColouringAttributes.setColor(yellow);
thisAppearance.setColoringAttributes(theseColouringAttributes);
TransparencyAttributes rayTransparency=new TransparencyAttributes();
rayTransparency.setTransparencyMode(rayTransparency.FASTEST);
rayTransparency.setTransparency(0.7f);
thisAppearance.setTransparencyAttributes(rayTransparency);
Material rayMaterial=new Material();
Color3f pink=new Color3f(1.0f,0.7f,0.7f);
rayMaterial.setAmbientColor(pink);
rayMaterial.setDiffuseColor(yellow);
rayMaterial.setEmissiveColor(colour);
Color3f white=new Color3f(1.0f,1.0f,1.0f);
rayMaterial.setSpecularColor(white);
rayMaterial.setShininess(0.0f);
thisAppearance.setMaterial(rayMaterial);
setAppearance(thisAppearance);
setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
thisAppearance.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
theseColouringAttributes.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE)
;
setColour(colour);
}
// Sets the colour of the line
public void setColour(Color3f colour)
{
theseColouringAttributes.setColor(colour);
thisAppearance.setColoringAttributes(theseColouringAttributes);
setAppearance(thisAppearance);
}
}
/////////////////////////////////////////////////////////////////////
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.picking.*;
public abstract class myShape extends Shape3D
{
// Sole constructor
public myShape(){}
// name
abstract public String getName();
// the point in the triangle array
abstract public Point3f getTriangleCoordinates(int index);
abstract public int getNumberTriangles();
}
/////////////////////////////////////////////////////////////////////
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA3D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".