it's ok, no response required. i'm well on my way to solving this.
Shamim Khaliq [EMAIL PROTECTED] <http://www.shamimkhaliq.co.uk/>
----- Original Message -----
From: Shamim Khaliq <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, April 19, 2001 11:03 AM
Subject: modelling the refraction of light
> 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()
> file://,new Octahedron()
> file://,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".