Java tutorial
/* Author Claude G. Schwab * Copyright (c) 2005 University of applied sciences * Biel School of Engineering and Architecture, Switzerland. * http://www.hta-bi.bfh.ch * All Rights Reserved. * Compiled with SDK 1.4.1 and Java3D API Version 1.3 * * This Demo class is a demonstration software (code) * for my introduction to Java3D. */ import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.Toolkit; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.text.NumberFormat; import java.util.Enumeration; import javax.media.j3d.Alpha; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.Background; import javax.media.j3d.Behavior; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.ColoringAttributes; import javax.media.j3d.DirectionalLight; import javax.media.j3d.GeometryArray; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Group; import javax.media.j3d.LineArray; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.PointLight; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.QuadArray; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Switch; import javax.media.j3d.Texture; import javax.media.j3d.TextureAttributes; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.TransparencyAttributes; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.media.j3d.WakeupOnAWTEvent; import javax.media.j3d.WakeupOnElapsedFrames; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.vecmath.AxisAngle4f; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.TexCoord2f; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.behaviors.picking.PickRotateBehavior; import com.sun.j3d.utils.behaviors.picking.PickTranslateBehavior; import com.sun.j3d.utils.behaviors.picking.PickZoomBehavior; import com.sun.j3d.utils.geometry.GeometryInfo; import com.sun.j3d.utils.geometry.NormalGenerator; import com.sun.j3d.utils.geometry.Sphere; import com.sun.j3d.utils.geometry.Stripifier; import com.sun.j3d.utils.image.TextureLoader; /** * This class is the main class of the program Demo. It creates a Virtual * Universe and a Locale and attaches to the Locale: a right-handed 3D * coordinate system, a color cube, a tetrahedron, the earth and the ViewBranch. * It also overrides the addBranchGraph methode. */ public class Demo3D extends JFrame implements Runnable { static int screenwidth; static int screenheight; static Thread fpsThread; long sleepDuration = 200; // in msec int decimalForAllFps = 1; JLabel jLabel; // Create a virtual universe. VirtualUniverse universe = new VirtualUniverse(); // A single hi-res. Locale node is created and attached to the // virtual universe. Locale locale = new Locale(universe); Canvas3D canvas3D; ViewBranch viewBr; /** * Constructor that allows to specify the desired initial instances. */ public Demo3D() { // Set the best GraphicsConfiguration GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D(); GraphicsConfiguration graphConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() .getBestConfiguration(template); canvas3D = new Canvas3D(graphConf); // The used Canvas3D // Construction of the main frame. setTitle("Demo"); JPanel jMainPanel = new JPanel(true); jMainPanel.setLayout(new BorderLayout(0, 5)); // hor_gap and ver_gap JPanel jFpsPanel = new JPanel(true); jFpsPanel.setBackground(Color.white); jLabel = new JLabel(""); jLabel.setText("Wait for informations"); jFpsPanel.add(jLabel); jMainPanel.add(canvas3D, BorderLayout.CENTER); /* * // For the stereo-mode with an "Head Monted Display" (HMD). JPanel * jScene_Stereo_Panel = new JPanel(true); * jScene_Stereo_Panel.setLayout(new GridLayout(1, 2, 0, 0)); // rows, * col, hor_gap and ver_gap jScene_Stereo_Panel.add(canvas3D); * jScene_Stereo_Panel.add(canvas3D); * jMainPanel.add(jScene_Stereo_Panel, BorderLayout.CENTER); */ jMainPanel.add(jFpsPanel, BorderLayout.SOUTH); setContentPane(jMainPanel); // The ViewBranch class creates the instances of ViewPlatform, View, // etc. viewBr = new ViewBranch(canvas3D); fpsThread = new Thread(this); myScene(); } /** * Assembling of all components of the scene. */ public void myScene() { // Necessary to use NewTextureLoader in other classes. NewTextureLoader.setImageObserver(this); // AWT Component // Attach the subgraphs SceneBuilder1, SceneBuilder2, SceneBuilder3 // and the ViewBranch to the Locale node. addBranchGraph(new SceneBuilder1().mySubGraph1()); addBranchGraph(new SceneBuilder2().mySubGraph2()); addBranchGraph(new SceneBuilder3(canvas3D).mySubGraph3()); addBranchGraph(viewBr.myViewBranch()); } /** * Allows to attach all subgraphs of the scene and the ViewBranch to the * Locale node. * * @param javax.media.j3d.BranchGroup * brGr - the root of the subgraph */ public void addBranchGraph(BranchGroup brGr) { locale.addBranchGraph(brGr); } ///////////////////////////// Framemeter ///////////////////////////// /** * This start method allows to start the thread of the framemeter. */ public void start() { SwingUtilities.invokeLater(fpsThread); } /** * This run method allows to launch the computation of all frames per second * for the framemeter. */ public void run() { long lastFrameTime; double fps; double min = Double.MAX_VALUE; double max = Double.MIN_VALUE; long count = 0; double sum = 0; double mean = 0; while (true) { lastFrameTime = viewBr.view.getLastFrameDuration(); if (lastFrameTime > 0) { fps = 1000 / (double) lastFrameTime; count += 1; sum += fps; mean = sum / count; // To format all fps-informations. NumberFormat numbForm; numbForm = NumberFormat.getInstance(); numbForm.setMaximumFractionDigits(decimalForAllFps); if (min > fps && fps != 0 && count > 4) min = fps; if (max < fps) max = fps; jLabel.setText("Frames/sec = " + numbForm.format(fps) + " ; minFrames/sec = " + numbForm.format(min) + " ; maxFrames/sec = " + numbForm.format(max) + " ; meanFrames/sec = " + numbForm.format(mean)); // System.out.println("Frames per second = " + fps); } try { Thread.sleep(sleepDuration); } catch (InterruptedException e) { } } } ///////////////////////// End of the framemeter ///////////////////////// /** * Main of the Demo program. Take the graphic environment of the * workstation. */ public static void main(String args[]) { JFrame jFrameDemo = new Demo3D(); // To be sure to stop the application when the frame is closed. WindowListener winListener = new WindowAdapter() { public void windowClosing(WindowEvent event) { System.exit(0); } }; jFrameDemo.addWindowListener(winListener); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); screenwidth = (int) screenSize.getWidth(); screenheight = (int) screenSize.getHeight(); jFrameDemo.setSize(screenwidth, screenheight); // Turn on the visibility of the frame. jFrameDemo.setVisible(true); fpsThread.start(); } } /* * Author Claude G. Schwab Copyright (c) 2002 University of applied sciences * Biel School of Engineering and Architecture, Switzerland. * http://www.hta-bi.bfh.ch All Rights Reserved. Compiled with SDK 1.4.1 and * Java3D API Version 1.3 * * This ViewBranch class is a demonstration software (code) for my introduction * to Java3D. */ /** * This class creates all necessary objects on the "View Branch" side of the * scene graph. */ class ViewBranch { public BranchGroup vbBrGr; private Canvas3D canvas3D; private PhysicalBody body; private PhysicalEnvironment environment; public static View view; // static for the Framemeter private ViewPlatform viewPlat; private TransformGroup vpTrGrStart, vpTrGrKeys_Transl_Turn, vpTrGrKeys_Rot_Up_Down; private Transform3D trStart; private BoundingSphere cameraBounds; private Camera_Transl_Turn camera_Transl_Turn; private Camera_Rot_Up_Down camera_Rot_Up_Down; private Aimer aimer; /** * Constructor that allows to specify the desired Canvas3D. * * @param javax.media.j3d.Canvas3D * canv - the Canvas3D being used */ public ViewBranch(Canvas3D canv) // The instance canv of Canvas3D class is { // created in the constructor of the Demo class. canvas3D = canv; } /** * Create the ViewBranch * * @return javax.media.j3d.BranchGroup vbBrGr - the root of the ViewBranch */ public BranchGroup myViewBranch() { // Create the minimal PhysicalBody and PhysicalEnvironnement // instances with default parameters. body = new PhysicalBody(); environment = new PhysicalEnvironment(); // Create a View instance and attach the Canvas3D, the PhysicalBody // and the PhysicalEnvironment to it. view = new View(); view.setFrontClipDistance(0.02); // Default value is 0.1 m view.setBackClipDistance(40.0); // Default value is 10 m // Rem.: BackClipDistance / FrontClipDistance = 2000 > 1000 but < 3000 view.addCanvas3D(canvas3D); view.setPhysicalBody(body); view.setPhysicalEnvironment(environment); /* * // Choices of the projection type. They are 2 possibilities, namely: // * PERSPECTIVE_PROJECTION and PARALLEL_PROJECTION. // Note: the default * value is PERSPECTIVE_PROJECTION * view.setProjectionPolicy(View.PARALLEL_PROJECTION); */ // Create a ViewPlatform instance and bind it with the View instance. viewPlat = new ViewPlatform(); viewPlat.setActivationRadius(40.0f); // Default value is 62 m view.attachViewPlatform(viewPlat); // Create the action volume for the camera's navigation. cameraBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // Create the two necessary TransformGroups for the ViewPlatform's // motion (6 translations and 4 rotations). vpTrGrKeys_Rot_Up_Down = new TransformGroup(); vpTrGrKeys_Transl_Turn = new TransformGroup(); // With the ALLOW_TRANSFORM_READ and ALLOW_TRANSFORM_WRITE // capabilities, we allow the modification of the TransformGroup's // code by the Behavior's code at run time. vpTrGrKeys_Transl_Turn.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); vpTrGrKeys_Transl_Turn.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); vpTrGrKeys_Rot_Up_Down.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); vpTrGrKeys_Rot_Up_Down.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // Attach the ViewPlatform to the vpTrGrKeys_Rot_Up_Down node. vpTrGrKeys_Rot_Up_Down.addChild(viewPlat); // Create and attach an aimer to the TransformGroup node // vpTrGrKeys_Rot_Up_Down. aimer = new Aimer(1.5f); vpTrGrKeys_Rot_Up_Down.addChild(aimer.myAimer()); // View-platform's motion ==> camera's navigation: 6 translations and 4 // rotations. // Create and attach the camera's rotation on the vpTrGrKeys_Rot_Up_Down // node. camera_Rot_Up_Down = new Camera_Rot_Up_Down(vpTrGrKeys_Rot_Up_Down); camera_Rot_Up_Down.setSchedulingBounds(cameraBounds); vpTrGrKeys_Rot_Up_Down.addChild(camera_Rot_Up_Down); // Create and attach the camera's translation and rotation instances // on the vpTrGrKeys_Transl_Turn node. camera_Transl_Turn = new Camera_Transl_Turn(vpTrGrKeys_Transl_Turn); camera_Transl_Turn.setSchedulingBounds(cameraBounds); vpTrGrKeys_Transl_Turn.addChild(camera_Transl_Turn); // Attach the vpTrGrKeys_Rot_Up_Down node to the vpTrGrKeys_Transl_Turn // node. vpTrGrKeys_Transl_Turn.addChild(vpTrGrKeys_Rot_Up_Down); // Give the starting position of the ViewPlatform. trStart = new Transform3D(); // Identity matrix trStart.set(new Vector3f(0.0f, 0.0f, 10.0f)); // Translation of the // camera (0,0,10) // Create the TransformGroup node for the ViewPlatform's // starting position. vpTrGrStart = new TransformGroup(trStart); // Attach the vpTrGrKeys_Transl_Turn node to the TransformGroup // node vpTrGrStart. vpTrGrStart.addChild(vpTrGrKeys_Transl_Turn); // Add the TransformGroup node vpTrGrStart to the view // BranchGroup node vbBrGr. vbBrGr = new BranchGroup(); vbBrGr.addChild(vpTrGrStart); // Compile the ViewBranch to optimize the performances. vbBrGr.compile(); // Return the final version of the view branch BranchGroup node vbBrGr. return vbBrGr; } } /** * This class serves to put a locale right-handed 3D coordinate system as * reference system into the scene. It also creates a background, the * illumination of the scene and the borders of the virtual universe. */ class SceneBuilder1 { public BranchGroup brGr1; private CoordSyst coordSyst; private BoundingSphere boundsBackGr, boundsGen; private Background backGr; private NewTextureLoader newTextureLoader; private AmbientLight ambientLight; private PointLight pointLight; private DirectionalLight directionalLight; private BordersIn bordersIn; private BordersOut bordersOut; private static final float dimUniverse = 5.0f; // dimensions of the virtual // universe are: // dimUniverse x dimUniverse x dimUniverse /** * Create the subgraph #1 * * @return javax.media.j3d.BranchGroup brGr1 - the root of the subgraph #1 */ public BranchGroup mySubGraph1() { // Create the BranchGroup brGr1 of the subgraph #1. brGr1 = new BranchGroup(); // Create and attach the coordinate system to the brGr1. coordSyst = new CoordSyst(1.0f, 1.0f, 0.0f, // Color of the x-axis 0.0f, 0.0f, 1.0f, // Color of the y-axis 1.0f, 0.0f, 0.0f, // Color of the z-axis 0.75f); // Lenght of the 3 axes brGr1.addChild(coordSyst); // Background setting for the scene. newTextureLoader = new NewTextureLoader("Images/Ciel_Out.jpg"); newTextureLoader.setImageObserver(newTextureLoader.getImageObserver()); backGr = new Background(newTextureLoader.getImage()); backGr.setImageScaleMode(Background.SCALE_FIT_ALL); boundsBackGr = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0); backGr.setApplicationBounds(boundsBackGr); brGr1.addChild(backGr); // A BoundingSphere instance as general bounding region. boundsGen = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // Lighting of the scene. // Create and attach an ambient light. ambientLight = new AmbientLight(true, new Color3f(0.2f, 0.2f, 0.2f)); ambientLight.setInfluencingBounds(boundsGen); brGr1.addChild(ambientLight); // Create and attach a point light. pointLight = new PointLight(true, new Color3f(1.0f, 1.0f, 0.3f), new Point3f(-100.0f, 0.0f, 100.0f), new Point3f(0.0f, 0.05f, 0.1f)); pointLight.setInfluencingBounds(boundsGen); brGr1.addChild(pointLight); // Create and attach a directional light. directionalLight = new DirectionalLight(true, new Color3f(0.8f, 1.0f, 1.0f), new Vector3f(-0.5f, -0.5f, -0.5f)); directionalLight.setInfluencingBounds(boundsGen); brGr1.addChild(directionalLight); // Create the borders of the virtual universe for the inside view of the // scene. bordersIn = new BordersIn(dimUniverse); brGr1.addChild(bordersIn.myInternalUniverse()); // Create the borders of the virtual universe for the outside view of // the scene. bordersOut = new BordersOut(dimUniverse); brGr1.addChild(bordersOut.myExternalUniverse()); // Compile the subgraph to optimize the performances. brGr1.compile(); // Return the final version of the BranchGroup node brGr1 return brGr1; } } /** * This class serves to put a colored cube into the scene graph. It also * produces a "static rotation" and a "dynamic rotation" of the colored cube. */ class SceneBuilder2 { public BranchGroup brGr2; private BoundingSphere boundsGen; private TransformGroup trGr2_1, trGr2_2; private CoordSyst coordSyst; private ColorCube colorCube; private Transform3D trans1, rot1; private Alpha rotationAlpha; private AxisAngle4f axe_rot; private RotationInterpolator rotator; /** * Create the subgraph #2 * * @return javax.media.j3d.BranchGroup brGr2 - the root of the subgraph #2 */ public BranchGroup mySubGraph2() { // Create the BranchGroup node brGr2 of the second subgraph. brGr2 = new BranchGroup(); // A BoundingSphere instance as general bounding region. boundsGen = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // Create a Transform3D instance rot1 to perform the necessary // "static rotation" for the desired cube's position. rot1 = new Transform3D(); // Rotation of Pi/2 - arctan(1/sqrt(2)) = 0.955 rad about the // (1,0,-1)-axis passing through the origin. axe_rot = new AxisAngle4f(1.0f, 0.0f, -1.0f, 0.955f); rot1.setRotation(axe_rot); // Create the first TransformGroup node trGr2_1 and attach the // "static rotation" rot1 instance to it. trGr2_1 = new TransformGroup(rot1); // Create and attach a coordinate system to the TransformGroup node // trGr2_1 of the subgraph #2, that is to the cube. coordSyst = new CoordSyst(1.0f, 1.0f, 0.0f, // Color of the x-axis 0.0f, 0.0f, 1.0f, // Color of the y-axis 1.0f, 0.0f, 0.0f, // Color of the z-axis 0.4f); // Lenght of the 3 axes trGr2_1.addChild(coordSyst); // Create the ColorCube (Shape3D) and attach it to the // TransformGroup node trGr2_1 of the subgraph #2. colorCube = new ColorCube(0.5f); trGr2_1.addChild(colorCube); // Create the second TransformGroup node trGr2_2. trGr2_2 = new TransformGroup(); // With the ALLOW_TRANSFORM_WRITE capability, we allow the // modification of the TransformGroup's code by the behavior's // code at run time. trGr2_2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // Attach the first node trGr2_1 to the second node trGr2_2. trGr2_2.addChild(trGr2_1); // Prepare the RotationInterpolator (Behavior) for the // cube's rotation about the y-axis. trans1 = new Transform3D(); // Create the alpha(t) function. rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 10000, 0, 0, 0, 0, 0); // Create the cube's rotation about the y-axis. rotator = new RotationInterpolator(rotationAlpha, trGr2_2, trans1, 0.0f, (float) Math.PI * 2.0f); rotator.setSchedulingBounds(boundsGen); trGr2_2.addChild(rotator); brGr2.addChild(trGr2_2); // Compile the subgraph to optimize the performances. brGr2.compile(); // Return the final version of the BranchGroup node brGr2 return brGr2; } } /** * This class serves to attache both the BranchGraph31 and BranchGraph32 to the * Locale and to pick the tetrahedron. */ /* * Note: It is not always necessary to use "detach" and "add" to add/remove a * subgraph from a scene graph. In many cases the using of the setEnable() * method, to turn a subgraph on and off, is adequate. */ class SceneBuilder3 { public BranchGroup brGr3; private AddDetachEarthBehavior addDetachEarthBehavior; private BoundingSphere boundsGen, pickBounds; private Canvas3D canvas3D; // needed 3 times for the Picking of the // tetrahedron private PickRotateBehavior pickRotBehavior; private PickZoomBehavior pickZoomBehavior; private PickTranslateBehavior pickTransBehavior; private SceneBuilder31 sceneBuilder31; private SceneBuilder32 sceneBuilder32; private Tetrahedron tetrahedron; /** * Constructor that allows to specify the desired Canvas3D. * * @param javax.media.j3d.Canvas3D * canv - the active Canvas3D */ public SceneBuilder3(Canvas3D canv) { canvas3D = canv; } /** * Create the subgraph #3 * * @return javax.media.j3d.BranchGroup brGr3 - the root of the subgraph #3 */ public BranchGroup mySubGraph3() { // Create the BranchGroup node brGr3, in other words the root of // the subgraph31 and subgraph32. brGr3 = new BranchGroup(); // To allow the detach/add process of the subgraph 32 from the // BranchGroup node brGr3. brGr3.setCapability(Group.ALLOW_CHILDREN_READ); brGr3.setCapability(Group.ALLOW_CHILDREN_WRITE); brGr3.setCapability(Group.ALLOW_CHILDREN_EXTEND); // A BoundingSphere instance as picking bound region. pickBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 5.0); // A BoundingSphere instance as general bounding region. boundsGen = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // Create and attach the subgraph31 with the tetrahedron // to the BranchGroup node brGr3. tetrahedron = new Tetrahedron(1.0f); sceneBuilder31 = new SceneBuilder31(tetrahedron.myTetrahedron()); brGr3.addChild(sceneBuilder31.mySubGraph31()); // Picking of the tetrahedron // Note:It's the instruction: // trGr31.setCapability(TransformGroup.ENABLE_PICK_REPORTING) // in the class SceneBuilder31 that determines if the // tetrahedron is pickable or not. // Pick and translate the tetrahedron parallel to the z-axis if the // mouse pointer is over it. pickZoomBehavior = new PickZoomBehavior(brGr3, canvas3D, pickBounds); // pickZoomBehavior.setEnable(ctrlDown); brGr3.addChild(pickZoomBehavior); // Pick and translate the tetrahedron in the (x-y)-plane if the // mouse pointer is over it. pickTransBehavior = new PickTranslateBehavior(brGr3, canvas3D, pickBounds); // pickTransBehavior.setEnable(ctrlDown); brGr3.addChild(pickTransBehavior); // Pick and rotate the tetrahedron if the mouse pointer is over it. pickRotBehavior = new PickRotateBehavior(brGr3, canvas3D, pickBounds); // pickRotBehavior.setEnable(ctrlDown); brGr3.addChild(pickRotBehavior); // Create the subgraph32 ===> the earth in double rotation. sceneBuilder32 = new SceneBuilder32(); brGr3.addChild(sceneBuilder32.mySubGraph32()); // Create an instance of the AddDetachEarthBehavior class to // allow the detach/add process of the subgraph32. addDetachEarthBehavior = new AddDetachEarthBehavior(this, sceneBuilder32); addDetachEarthBehavior.setSchedulingBounds(boundsGen); brGr3.addChild(addDetachEarthBehavior); // Compile the subgraph to optimize the performances. brGr3.compile(); // Return the final version of the BranchGroup node brGr3 return brGr3; } /** * This method is called up in the DetachEathBehavior class to add a new * representation of the earth. */ public void addEarth() { brGr3.addChild(sceneBuilder32.mySubGraph32()); } } /** * This class serves to put the objet (a tetrahedron) into the scene. It also * produces a "static translation" of the tetrahedron and allows its picking. */ class SceneBuilder31 { public TransformGroup trGr31; private Shape3D myObject; private Transform3D transl; private Vector3d vectransl; // translation /** * Constructor that allows to specify the desired object. * * @param javax.media.j3d.Shape3D * objet - the Shape3D instance which will be attached to the * subgraph #31 */ public SceneBuilder31(Shape3D object) { myObject = object; } /** * Create the subgraph #31 and prepare the TransformGroup node trGr31 for * the tetrahedron's picking. * * @return javax.media.j3d.TransformGroup trGr31_2 - the root of the * subgraph #31 */ public TransformGroup mySubGraph31() { // Create a Transform3D node to execute the desired "static translation" // of the tetrahedron ===> start position. transl = new Transform3D(); vectransl = new Vector3d(0.0, -2.0, 0.0); // translation transl.set(vectransl); // Create the TransformGroup node trGr31, attach into it the "static // translation" instance and prepare it for the picking. trGr31 = new TransformGroup(transl); trGr31.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); trGr31.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); trGr31.setCapability(TransformGroup.ENABLE_PICK_REPORTING); // Attach myObject (Shape3D leaf) to the TransformGroup node trGr31. trGr31.addChild(myObject); // Return the final version of the TransformGroup node trGr31. return trGr31; } } /** * This class serves to put the rendering of five different earth's * representations (each with a right-handed 3D coordinate system) into the * scene graph. It also produces a "static translation" and a double "dynamic * rotation" of each earth's representations and allows to detach and then add * again this subgraph32 from to the entire scene graph. */ /* * Note: It is not always necessary to use "detach" and "add" to detach/add a * subgraph from a scene graph. In many cases the using of the setEnable() * method, to turn a subgraph on and off, is adequate. */ class SceneBuilder32 { public BranchGroup brGr32; private TransformGroup trGr32_1, trGr32_2, trGr32_3; private int thisEarth; private BoundingSphere boundsGen; private CoordSyst coordSyst; private SwitchBehavior switchBehavior; private Switch switchEarths; // the Switch for the 5 different earth's // representations private Transform3D transl; private Vector3d vectTransl; // translation private Alpha rotationAlpha_1, rotationAlpha_2; private RotationInterpolator rotator_1, rotator_2; // The five different earth's representations private Earth earth_Points, earth_Lines, earth_Polygons, earth_Gouraud, earth_Texture; /** * Create the subgraph #32 * * @return javax.media.j3d.TransformGroup trGr32_3 - the root of the * subgraph #32 */ public BranchGroup mySubGraph32() { // A BoundingSphere instance as general bounding region. boundsGen = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // Create the first TransformGroup node trGr32_1 to: // 1) attach the Switch node with the five different earth's // representations to the subgraph32 // 2) attach a coordinate system to each earth's representation // 3) rotate each earth about its own y-axis. trGr32_1 = new TransformGroup(); // With the ALLOW_TRANSFORM_WRITE capability, we allow the // modification of the TransformGroup's code by the behavior's // code at run time. trGr32_1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // SwitchBehavior is the class which controls the fonctioning of // the switchEarths node. switchBehavior = new SwitchBehavior(this); switchBehavior.setSchedulingBounds(boundsGen); trGr32_1.addChild(switchBehavior); // The Switch which allows the rendering of the five different // earth's representations. switchEarths = new Switch(); // With the ALLOW_TRANSFORM_WRITE, ALLOW_SWITCH_WRITE and // ALLOW_CHILDREN_READ // capabilities we allow to get or set new capabilities. switchEarths.setCapability(Switch.ALLOW_SWITCH_READ); switchEarths.setCapability(Switch.ALLOW_SWITCH_WRITE); switchEarths.setCapability(Switch.ALLOW_CHILDREN_READ); // Attach the different earth's representations to the Switch node. // Increasing earth_Points = new Earth("points", 0.4f); switchEarths.addChild(earth_Points.myEarth()); // # 0 earth_Lines = new Earth("lines", 0.4f); switchEarths.addChild(earth_Lines.myEarth()); // # 1 earth_Polygons = new Earth("polygons", 0.4f); switchEarths.addChild(earth_Polygons.myEarth()); // # 2 earth_Gouraud = new Earth("gouraud", 0.4f); switchEarths.addChild(earth_Gouraud.myEarth()); // # 3 earth_Texture = new Earth("texture", 0.4f); switchEarths.addChild(earth_Texture.myEarth()); // # 4 // Decreasing switchEarths.addChild(earth_Texture.myEarth()); // # 4 switchEarths.addChild(earth_Gouraud.myEarth()); // # 3 switchEarths.addChild(earth_Polygons.myEarth()); // # 2 switchEarths.addChild(earth_Lines.myEarth()); // # 1 switchEarths.addChild(earth_Points.myEarth()); // # 0 // Attach the Switch node with the five different earth's // representations to the TransformGroup node trGr32_1. trGr32_1.addChild(switchEarths); // Create and attach a coordinate system to the TransformGroup node // trGr32_1, that is to each earth's representation. coordSyst = new CoordSyst(1.0f, 1.0f, 0.0f, // Color of the x-axis 0.0f, 0.0f, 1.0f, // Color of the y-axis 1.0f, 0.0f, 0.0f, // Color of the z-axis 0.6f); // Lenght of the 3 axes trGr32_1.addChild(coordSyst); // Create the alpha(t) function for the earth's rotation about // its own y-axis. rotationAlpha_1 = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 10000, 0, 0, 0, 0, 0); // Create the earth's rotation about its own y-axis. rotator_1 = new RotationInterpolator(rotationAlpha_1, trGr32_1, new Transform3D(), 0.0f, (float) Math.PI * 2.0f); rotator_1.setSchedulingBounds(boundsGen); trGr32_1.addChild(rotator_1); // Create a Transform3D instance to execute the desired "static // translation" of the earth, that is the rotation radius around // the sun. transl = new Transform3D(); vectTransl = new Vector3d(2.5, 0.0, 0.0); transl.set(vectTransl); // Create the second TransformGroup node trGr32_2 and attach the // "static translation" transl to it. trGr32_2 = new TransformGroup(transl); // Attach the trGr32_1 node to the trGr32_2 node. trGr32_2.addChild(trGr32_1); // Create the third TransformGroup node trGr32_3 for the earth's // rotation around the sun. trGr32_3 = new TransformGroup(); // With the ALLOW_TRANSFORM_WRITE capability, we allow the // modification of the TransformGroup's code by the behavior's // code at run time. trGr32_3.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // Attach the trGr32_2 node to the trGr32_3 node. trGr32_3.addChild(trGr32_2); // Create the alpha(t) function for the earth's rotation around the sun. rotationAlpha_2 = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 20000, 0, 0, 0, 0, 0); // To restart correctly the rotation of the earth around the // sun after a detach/add process of the subgraph32 from the // BranchGroup node brGr3. rotationAlpha_2.setStartTime(System.currentTimeMillis()); // Create the earth's rotation around the sun. rotator_2 = new RotationInterpolator(rotationAlpha_2, trGr32_3, new Transform3D(), 0.0f, (float) Math.PI * 2.0f); rotator_2.setSchedulingBounds(boundsGen); trGr32_3.addChild(rotator_2); // To allow the detaching of this subgraph32 from the // BranchGroup node brGr3. brGr32 = new BranchGroup(); brGr32.setCapability(BranchGroup.ALLOW_DETACH); brGr32.addChild(trGr32_3); // Return the final version of the BranchGroup node brGr32. return brGr32; } /** * This method is called up in the SwitchBehavior class and gets the new * earth's representation which has to be drawn. * * @param thisEarth - * the new earth's representation to draw. */ public void setNewEarth(int thisEarth) { switchEarths.setWhichChild(thisEarth); } // This method is called up in the DetachEathBehavior class to // detach the momentary representation of the earth. public void detachEarth() { brGr32.detach(); } } /* * @(#)NewTextureLoades.java 1.0 99/10/21 * * Copyright (c) 1996-1999 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. */ /** * A texture loading utility that doesn't require an image observer for * constructing objects. This class extends the TextureLoader class of the * com.sun.j3d.utils.image package. * */ class NewTextureLoader extends TextureLoader { static java.awt.Component observer; /** * Specify an object to server as the image observer. Use this method once * before constructing any texture loaders. * * @param imageObserver * the object to be used in subsequent NewTextureLoader * constuctions */ public static void setImageObserver(java.awt.Component imageObserver) { observer = imageObserver; } /** * Retreve the object used as the image observer for NewTextureLoader * objects. Use this method when the image observer is needed. * * @return the object used in as the image observer in subsequent * NewTextureLoader constuctions */ public static java.awt.Component getImageObserver() { return observer; } // constructors without an image observer argument /** * Constructs a NewTextureLoader object loading the specified iamge in * default (RGBA) format. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param image * the image object to load */ public NewTextureLoader(java.awt.Image image) { super(image, observer); } /** * Constructs a NewTextureLoader object loading the specified image and * option flags in the default (RGBA) format. The an image observer must be * set using the setImageObserver() method before using this constructor. * * @param image * the image object to load * @param flags * the flags to use in construction (e.g. generate mipmap) */ public NewTextureLoader(java.awt.Image image, int flags) { super(image, flags, observer); } /** * Constructs a NewTextureLoader object loading the specified file using the * specified format. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param image * the image object to load * @param format * specificaiton of which channels to use (e.g. RGB) */ public NewTextureLoader(java.awt.Image image, java.lang.String format) { super(image, format, observer); } /** * Constructs a NewTextureLoader object loading the specified file with * specified format and flags. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param image * the image object to load * @param format * specificaiton of which channels to use (e.g. RGB) * @param flags * the flags to use in construction (e.g. generate mipmap) */ public NewTextureLoader(java.awt.Image image, java.lang.String format, int flags) { super(image, format, flags, observer); } /** * Constructs a NewTextureLoader object loading the specified file using the * default format (RGBA). The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param fname * the name of the file to load */ public NewTextureLoader(java.lang.String fname) { super(fname, observer); } /** * Constructs a NewTextureLoader object loading the specified file with the * specified flags. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param fname * the name of the file to load * @param flags * the flags to use in construction (e.g. generate mipmap) */ public NewTextureLoader(java.lang.String fname, int flags) { super(fname, flags, observer); } /** * Constructs a NewTextureLoader object loading the specified file using the * specified format. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param fname * the name of the file to load * @param format * specificaiton of which channels to use (e.g. RGB) */ public NewTextureLoader(java.lang.String fname, java.lang.String format) { super(fname, format, observer); } /** * Constructs a NewTextureLoader object loading the specified file using the * specified format and flags. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param fname * the name of the file to load * @param format * specificaiton of which channels to use (e.g. RGB) * @param flags * the flags to use in construction (e.g. generate mipmap) */ public NewTextureLoader(java.lang.String fname, java.lang.String format, int flags) { super(fname, format, flags, observer); } /** * Constructs a NewTextureLoader object loading the specified URL using the * default format. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param url * specifies the URL of the image to load */ public NewTextureLoader(java.net.URL url) { super(url, observer); } /** * Constructs a NewTextureLoader object loading the specified URL using the * specified flags. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param url * specifies the URL of the image to load * @param flags * the flags to use in construction (e.g. generate mipmap) */ public NewTextureLoader(java.net.URL url, int flags) { super(url, flags, observer); } /** * Constructs a NewTextureLoader object loading the specified URL using the * specified format. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param url * specifies the URL of the image to load * @param format * specificaiton of which channels to use (e.g. RGB) */ public NewTextureLoader(java.net.URL url, java.lang.String format) { super(url, format, observer); } /** * Constructs a NewTextureLoader object loading the specified URL using the * specified format and flags. The an image observer must be set using the * setImageObserver() method before using this constructor. * * @param url * specifies the URL of the image to load * @param format * specificaiton of which channels to use (e.g. RGB) * @param flags * the flags to use in construction (e.g. generate mipmap) */ public NewTextureLoader(java.net.URL url, java.lang.String format, int flags) { super(url, format, flags, observer); } } // end of TexturedPlane class /** * This class is a keyboard behavior to control the partly rotation (rotate up * and rotate down) of the camera. */ class Camera_Rot_Up_Down extends Behavior { // The TransformGroup node to modify by the keyboard interaction. private TransformGroup target_trGr; // Wake up event when a key is pressed. private WakeupOnAWTEvent wakeUp = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED); // The key event private KeyEvent keyEvent; // The angle to turn when the Home key or End key is pressed. private float angle = (float) Math.PI / 36; private Transform3D myKeyNavTransf3D = new Transform3D(); private Transform3D rotation = new Transform3D(); /** * Constructor that allows to specify the desired target transform group. * * @param javax.media.j3d.TransformGroup * target - the target transform group */ public Camera_Rot_Up_Down(TransformGroup target) { target_trGr = target; } /** * Override Behavior's initialize method to setup wakeup criteria. */ public void initialize() { wakeupOn(wakeUp); } /** * Override Behavior's stimulus method to handle the event. This method is * called when a key on the keyboard has been pressed and operates on the * specified transform group to move the camera. * * @param Enumeration * criteria - all pressed keys in a list. This will be passed by * the system. */ public void processStimulus(Enumeration criteria) { WakeupOnAWTEvent eventToWakeUp; AWTEvent[] events; if (criteria.hasMoreElements()) { // Decode the wakeup criteria eventToWakeUp = (WakeupOnAWTEvent) criteria.nextElement(); events = eventToWakeUp.getAWTEvent(); keyEvent = (KeyEvent) events[0]; int keyCode = keyEvent.getKeyCode(); // Perform our processing // Get the initial transformation from target and put it // into myKeyNavTransf3D target_trGr.getTransform(myKeyNavTransf3D); // Not any of the 2 rotations don't act simultaneously. switch (keyCode) { case KeyEvent.VK_HOME: // Home - rotate up rotation.rotX(angle); break; case KeyEvent.VK_END: // End - rotate down rotation.rotX(-angle); break; default: rotation.rotX(0.0f); } myKeyNavTransf3D.mul(rotation); // Return the final transformation myKeyNavTransf3D to target target_trGr.setTransform(myKeyNavTransf3D); } // Set wakeup criteria for next time. wakeupOn(wakeUp); } } /** * This class creates an aimer in the ViewBranch. */ class Aimer extends Shape3D { private float scale_XYZ; private LineArray aimer; private float scaledExtremites[]; /** * Constructor that allows to specify the desired initial aimer's * dimensions. * * @param type * float s_XYZ - the scale factor to adjust the aimer's * dimensions */ public Aimer(float s_XYZ) { scale_XYZ = s_XYZ; } /** * Construct an aimer. * * @return javax.media.j3d.Shape3D myAimer - the constructed aimer. */ public Shape3D myAimer() { // Construction of the aimer (LineArray). aimer = new LineArray(20, LineArray.COORDINATES | LineArray.COLOR_3); // Scalling of the vertices of the aimer using scale_XYZ. scaledExtremites = new float[extremites.length]; for (int i = 0; i < extremites.length; i++) scaledExtremites[i] = extremites[i] * scale_XYZ; aimer.setCoordinates(0, scaledExtremites); aimer.setColors(0, color); this.setGeometry(aimer); return this; } // Aimer's geometry private static final float extremites[] = { // top-front 0.075f, 0.05f, -1.0f, -0.075f, 0.05f, -1.0f, // left-front -0.075f, 0.05f, -1.0f, -0.075f, -0.05f, -1.0f, // bottom-front -0.075f, -0.05f, -1.0f, 0.075f, -0.05f, -1.0f, // right-front 0.075f, -0.05f, -1.0f, 0.075f, 0.05f, -1.0f, // top-back 0.04f, 0.025f, -1.0f, -0.04f, 0.025f, -1.0f, // left-back -0.04f, 0.025f, -1.0f, -0.04f, -0.025f, -1.0f, // bottom-back -0.04f, -0.025f, -1.0f, 0.04f, -0.025f, -1.0f, // right-back 0.04f, -0.025f, -1.0f, 0.04f, 0.025f, -1.0f, // cross -0.04f, 0.025f, -1.0f, 0.04f, -0.025f, -1.0f, -0.04f, -0.025f, -1.0f, 0.04f, 0.025f, -1.0f }; // Colors of the aimer (each vertex in aimer is red). float color[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // front-frame 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // back-frame 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // cross 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }; } /** * This class creates a simple cube with a given texture to simulate the inside * of the virtual universe. */ class BordersIn extends Shape3D { private QuadArray cube; private float scale_XYZ; private NewTextureLoader newTextureLoader; private Texture texture; private TextureAttributes textAttr; /** * Constructor that allows to specify the desired scale factor of the * virtual universe. * * @param type * float s_XYZ - the scale factor to adjust the borders of the * virtual universe */ public BordersIn(float s_XYZ) { scale_XYZ = s_XYZ; } /** * Construction of the desired borders of the virtual universe (cube). * * @return javax.media.j3d.Shape3D myUniverse - the constructed borders of * the virtual universe */ public Shape3D myInternalUniverse() { cube = new QuadArray(cubeFaces.length, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2); ////////////////////// Geometric part /////////////////////////// // Scaling of the faces. for (int i = 0; i < cubeFaces.length; i++) cubeFaces[i].scale(scale_XYZ); cube.setCoordinates(0, cubeFaces); for (int i = 0; i < cubeFaces.length; i++) { // With i mod 4 ==> 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 for // the 4 vertices of the 6 faces, thus each vertex has // a point in the texture space. In this case, each cube's // face has the same texture coordinates. cube.setTextureCoordinate(0, i, textCoord[i % 4]); } // The geometry is passed to the instance this of the cube. this.setGeometry(cube); ////////////////////// Appearance part /////////////////////////// Appearance appearance = new Appearance(); // This code block is only necessary to insure, in all cases, the // correct // rendering of the 6 faces of the cube (bug in Java3D version 1.2.0 !). // Set up the polygon's rendering-mode PolygonAttributes polygonAttributes = new PolygonAttributes(); polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_FILL); appearance.setPolygonAttributes(polygonAttributes); // Loading the texture for the 6 cube's faces. newTextureLoader = new NewTextureLoader("Images/Galaxies.gif"); newTextureLoader.setImageObserver(newTextureLoader.getImageObserver()); texture = newTextureLoader.getTexture(); appearance.setTexture(texture); // Application modes of the texture textAttr = new TextureAttributes(); textAttr.setTextureMode(TextureAttributes.MODULATE); // there still are: // BLEND, COMBINE, // DECAL, and REPLACE appearance.setTextureAttributes(textAttr); // The appearance is passed to the instance this of the cube. this.setAppearance(appearance); return this; } // The 8 vertices p1, p2, ..., p8 of the cube. private static final Point3f p1 = new Point3f(1.0f, 1.0f, 1.0f); private static final Point3f p2 = new Point3f(1.0f, -1.0f, 1.0f); private static final Point3f p3 = new Point3f(-1.0f, -1.0f, 1.0f); private static final Point3f p4 = new Point3f(-1.0f, 1.0f, 1.0f); private static final Point3f p5 = new Point3f(-1.0f, 1.0f, -1.0f); private static final Point3f p6 = new Point3f(-1.0f, -1.0f, -1.0f); private static final Point3f p7 = new Point3f(1.0f, -1.0f, -1.0f); private static final Point3f p8 = new Point3f(1.0f, 1.0f, -1.0f); // The 6 faces of the cube. private static final Point3f cubeFaces[] = { // internal front face p5, p6, p7, p8, // internal right face p1, p8, p7, p2, // internal back face p1, p2, p3, p4, // internal left face p4, p3, p6, p5, // internal top face p1, p4, p5, p8, // internal bottom face p3, p2, p7, p6 }; // Coordinates in the texture space. Each cube's face has the // same texture coordinates. private TexCoord2f textCoord[] = { new TexCoord2f(0.0f, 0.0f), new TexCoord2f(0.0f, 1.0f), new TexCoord2f(1.0f, 1.0f), new TexCoord2f(1.0f, 0.0f) }; } /** * This class creates a simple cube with a given texture to simulate the outside * of the virtual universe. */ class BordersOut extends Shape3D { private QuadArray cube; private float scale_XYZ; private NewTextureLoader newTextureLoader; private Texture texture; private TextureAttributes textAttr; /** * Constructor that allows to specify the desired scale factor of the * virtual universe. * * @param type * float s_XYZ - the scale factor to adjust the borders of the * virtual universe */ public BordersOut(float s_XYZ) { scale_XYZ = s_XYZ; } /** * Construction of the desired borders of the virtual universe (cube). * * @return javax.media.j3d.Shape3D myUniverse - the constructed borders of * the virtual universe */ public Shape3D myExternalUniverse() { cube = new QuadArray(cubeFaces.length, QuadArray.COORDINATES | QuadArray.TEXTURE_COORDINATE_2); ////////////////////// Geometric part /////////////////////////// // Scaling of the faces. for (int i = 0; i < cubeFaces.length; i++) cubeFaces[i].scale(scale_XYZ); cube.setCoordinates(0, cubeFaces); for (int i = 0; i < cubeFaces.length; i++) { // With i mod 4 ==> 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 for // the 4 vertices of the 6 faces, thus each vertex has // a point in the texture space. In this case, each cube's // face has the same texture coordinates. cube.setTextureCoordinate(0, i, textCoord[i % 4]); } // The geometry is passed to the instance this of the cube. this.setGeometry(cube); ////////////////////// Appearance part /////////////////////////// Appearance appearance = new Appearance(); // This code block is only necessary to insure, in all cases, the // correct // rendering of the 6 faces of the cube (bug in Java3D version 1.2.0 !). // Set up the polygon's rendering-mode PolygonAttributes polygonAttributes = new PolygonAttributes(); polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_FILL); appearance.setPolygonAttributes(polygonAttributes); // Loading the texture for the 6 cube's faces. newTextureLoader = new NewTextureLoader("Images/Ciel_Outside.jpg"); newTextureLoader.setImageObserver(newTextureLoader.getImageObserver()); texture = newTextureLoader.getTexture(); appearance.setTexture(texture); // Application modes of the texture textAttr = new TextureAttributes(); textAttr.setTextureMode(TextureAttributes.MODULATE); // there still are: // BLEND, COMBINE, // DECAL, and REPLACE appearance.setTextureAttributes(textAttr); // The appearance is passed to the instance this of the cube. this.setAppearance(appearance); return this; } // The 8 vertices p1, p2, ..., p8 of the cube. private static final Point3f p1 = new Point3f(1.0f, 1.0f, 1.0f); private static final Point3f p2 = new Point3f(1.0f, -1.0f, 1.0f); private static final Point3f p3 = new Point3f(-1.0f, -1.0f, 1.0f); private static final Point3f p4 = new Point3f(-1.0f, 1.0f, 1.0f); private static final Point3f p5 = new Point3f(-1.0f, 1.0f, -1.0f); private static final Point3f p6 = new Point3f(-1.0f, -1.0f, -1.0f); private static final Point3f p7 = new Point3f(1.0f, -1.0f, -1.0f); private static final Point3f p8 = new Point3f(1.0f, 1.0f, -1.0f); // The 6 faces of the cube. private static final Point3f cubeFaces[] = { // external front face p5, p8, p7, p6, // external right face p8, p1, p2, p7, // external back face p1, p4, p3, p2, // external left face p4, p5, p6, p3, // external top face p8, p5, p4, p1, // external bottom face p2, p3, p6, p7 }; // Coordinates in the texture space. Each cube's face has the // same texture coordinates. private TexCoord2f textCoord[] = { new TexCoord2f(1.0f, 1.0f), new TexCoord2f(0.0f, 1.0f), new TexCoord2f(0.0f, 0.0f), new TexCoord2f(1.0f, 0.0f) }; } /** * This class is a switch behavior to control the rendering of the five * different earth's representations. */ class SwitchBehavior extends Behavior { // The Alpha class which gives the alpha values to command the Switch node. private Alpha switchAlpha; private float switchAlphaValue; // The class which contains the Switch node for the rendering of // the 5 different earth's representations. private SceneBuilder32 sceneBuilder32 = null; // The earth which will be rendered. private int thisEarth = 0; // Wakeup event after each frame. private WakeupOnElapsedFrames wakeUp = new WakeupOnElapsedFrames(0); /** * Constructor that allows to specify the reference of the SceneBuilder32's * instance. * * @param sceneBuilder32 - * the SceneBuilder32 instance */ public SwitchBehavior(SceneBuilder32 sceneBuilder32) { super(); // Create the alpha(t) function to automaticaly switch between the // five different earth's representations. switchAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE | Alpha.DECREASING_ENABLE, 0, 0, 10000, 0, 0, 10000, 0, 0); // Get the SceneBuilder32 reference this.sceneBuilder32 = sceneBuilder32; } /** * Override Behavior's initialize method to setup wakeup criteria. */ public void initialize() { wakeupOn(wakeUp); } /** * Override Behavior's stimulus method to handle the event. This method is * called up when the define number of frames is draw. * * @param criteria - * the wake-up criteria */ public void processStimulus(Enumeration criteria) { switchAlphaValue = switchAlpha.value(); if (switchAlphaValue <= 0.15f) thisEarth = 0; else if (0.15f < switchAlphaValue && switchAlphaValue <= 0.4f) thisEarth = 1; else if (0.4f < switchAlphaValue && switchAlphaValue <= 0.6f) thisEarth = 2; else if (0.6f < switchAlphaValue && switchAlphaValue <= 0.8f) thisEarth = 3; else if (0.8f < switchAlphaValue) thisEarth = 4; sceneBuilder32.setNewEarth(thisEarth); // Set wakeup criteria for next time. wakeupOn(wakeUp); } } /** * This class creates a simple colored cube. */ class ColorCube extends Shape3D { private QuadArray cube; // The constant colors of each cube's face private static final Color3f red = new Color3f(1.0f, 0.0f, 0.0f); private static final Color3f green = new Color3f(0.0f, 1.0f, 0.0f); private static final Color3f blue = new Color3f(0.0f, 0.0f, 1.0f); private static final Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f); private static final Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f); private static final Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f); /** * Constructor that allows to specify the desired scale factor for the * colored cube. * * @param type * float s_XYZ - the scale factor to adjust the edges's length of * the colored cube */ public ColorCube(float scale_XYZ) { // 24 cube = new QuadArray(cubeFaces.length, QuadArray.COORDINATES | QuadArray.COLOR_3); // Scaling of vertices for (int i = 0; i < cubeFaces.length; i++) cubeFaces[i].scale(scale_XYZ); cube.setCoordinates(0, cubeFaces); cube.setColors(0, colorsFaces); this.setGeometry(cube); } // The 8 vertices p1, ..., p8 of the cube. private static final Point3f p1 = new Point3f(1.0f, 1.0f, 1.0f); private static final Point3f p2 = new Point3f(-1.0f, 1.0f, 1.0f); private static final Point3f p3 = new Point3f(-1.0f, -1.0f, 1.0f); private static final Point3f p4 = new Point3f(1.0f, -1.0f, 1.0f); private static final Point3f p5 = new Point3f(1.0f, -1.0f, -1.0f); private static final Point3f p6 = new Point3f(1.0f, 1.0f, -1.0f); private static final Point3f p7 = new Point3f(-1.0f, 1.0f, -1.0f); private static final Point3f p8 = new Point3f(-1.0f, -1.0f, -1.0f); // The 6 faces of the cube. private static final Point3f cubeFaces[] = { // front face p1, p2, p3, p4, // right face p1, p4, p5, p6, // back face p8, p7, p6, p5, // left face p2, p7, p8, p3, // top face p1, p6, p7, p2, // bottom face p5, p4, p3, p8 }; // The constant colors for the 6 faces. private static final Color3f[] colorsFaces = { // front face red, red, red, red, // back face green, green, green, green, // right face blue, blue, blue, blue, // left face yellow, yellow, yellow, yellow, // top face magenta, magenta, magenta, magenta, // bottom face cyan, cyan, cyan, cyan }; } /** * This class is used to detach then add again the subgraph 32 from the scene * graph. */ /* * Note: It is not always necessary to use "detach" and "add" to add/remove a * subgraph from a scene graph. In many cases the using of the setEnable() * method, to turn a subgraph on and off, is adequate. */ class AddDetachEarthBehavior extends Behavior { // The classe which contains the addEarth method. private SceneBuilder3 sceneBuilder3; // The classe which contains the detachEarth method. private SceneBuilder32 sceneBuilder32; // To control the detach / add sequence. private boolean validation = false; // Wake up event when a key is pressed. private WakeupOnAWTEvent wakeUp = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED); // The key event private KeyEvent keyEvent; /** * Constructor that allows to specify the references of the SceneBuilder3's * and SceneBuilder32's instances. * * @param sceneBuilder3 - * the SceneBuilder3 instance * @param sceneBuilder32 - * the SceneBuilder32 instance */ public AddDetachEarthBehavior(SceneBuilder3 sceneBuilder3, SceneBuilder32 sceneBuilder32) { super(); // Get the SceneBuilder3's and SceneBuilder32's references this.sceneBuilder3 = sceneBuilder3; this.sceneBuilder32 = sceneBuilder32; } /** * Override Behavior's initialize method to setup wakeup criteria. */ public void initialize() { wakeupOn(wakeUp); } /** * Override Behavior's stimulus method to handle the event. This method is * called when a key on the keyboard has been pressed and operates on the * specified transform group to move the camera. * * @param Enumeration * criteria - all pressed keys in a list. This will be passed by * the system. */ public void processStimulus(Enumeration criteria) { WakeupOnAWTEvent eventToWakeUp; AWTEvent[] events; if (criteria.hasMoreElements()) { // Decode the wakeup criteria eventToWakeUp = (WakeupOnAWTEvent) criteria.nextElement(); events = eventToWakeUp.getAWTEvent(); keyEvent = (KeyEvent) events[0]; int keyCode = keyEvent.getKeyCode(); // Perform our processing switch (keyCode) { case KeyEvent.VK_A: if (validation) { sceneBuilder3.addEarth(); System.out.println("===> Add Earth"); validation = false; } break; case KeyEvent.VK_D: if (!validation) { sceneBuilder32.detachEarth(); System.out.println("===> Detach Earth"); validation = true; } break; default: } } // Set wakeup criteria for next time. wakeupOn(wakeUp); } } /** * This class is a keyboard behavior to control the translation and the partly * rotation (turn left and turn right) of the camera. * * After a translation or rotation performed by using this class, the * observation direction of the virtual camera will always stay parallel to the * coordinate system's (x-y)-plane of the parent node. * * In the case of this Demo application, it will be the coordinate system * associated with the Locale node. */ class Camera_Transl_Turn extends Behavior { // The TransformGroup node to modify by the keyboard interaction. private TransformGroup target_trGr; // Wake up event when a key is pressed. private WakeupOnAWTEvent wakeUp = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED); // The key event private KeyEvent keyEvent; // The angle to turn when a Direction Key and the Shift key are pressed. private float angle = (float) Math.PI / 36; // The step size to move when a Direction Key or the PageDown or // PageUp key is pressed. private float step = 1f; private Transform3D myKeyNavTransf3D = new Transform3D(); private Vector3f translation = new Vector3f(); private Vector3f dtrans = new Vector3f(); private Vector3f dtrans0 = new Vector3f(); private Transform3D trans_rot = new Transform3D(); /** * Constructor that allows to specify the desired target transform group. * * @param javax.media.j3d.TransformGroup * target - the target transform group */ public Camera_Transl_Turn(TransformGroup target) { target_trGr = target; } /** * Override Behavior's initialize method to setup wakeup criteria. */ public void initialize() { wakeupOn(wakeUp); } /** * Override Behavior's stimulus method to handle the event. This method is * called when a key on the keyboard has been pressed and operates on the * specified transform group to move the camera. * * @param Enumeration * criteria - all pressed keys in a list. This will be passed by * the system. */ public void processStimulus(Enumeration criteria) { WakeupOnAWTEvent eventToWakeUp; AWTEvent[] events; if (criteria.hasMoreElements()) { // Decode the wakeup criteria eventToWakeUp = (WakeupOnAWTEvent) criteria.nextElement(); events = eventToWakeUp.getAWTEvent(); keyEvent = (KeyEvent) events[0]; int keyCode = keyEvent.getKeyCode(); // Perform our processing // Get the initial transformation from target and put it into // myKeyNavTransf3D target_trGr.getTransform(myKeyNavTransf3D); // Set the translational components of myKeyNavTransf3D in // translation myKeyNavTransf3D.get(translation); // Not any of the 8 motions (6 translations and 2 rotations) // don't act simultaneously. switch (keyCode) { case KeyEvent.VK_UP: // Up Arrow - to move forward trans_rot.set(new Vector3f(0.0f, 0.0f, -step)); break; case KeyEvent.VK_DOWN: // Down Arrow - to move backwards trans_rot.set(new Vector3f(0.0f, 0.0f, step)); break; case KeyEvent.VK_LEFT: // Left Arrow -to turn left or move left if (keyEvent.isShiftDown()) trans_rot.set(new Vector3f(-step, 0.0f, 0.0f)); else trans_rot.rotY(angle); break; case KeyEvent.VK_RIGHT: // Right Arrow - to turn right or move right if (keyEvent.isShiftDown()) trans_rot.set(new Vector3f(step, 0.0f, 0.0f)); else trans_rot.rotY(-angle); break; case KeyEvent.VK_PAGE_DOWN: // Page Down - to move down trans_rot.set(new Vector3f(0.0f, -step, 0.0f)); break; case KeyEvent.VK_PAGE_UP: // Page Up - to move up trans_rot.set(new Vector3f(0.0f, step, 0.0f)); break; default: trans_rot.set(new Vector3f(0.0f, 0.0f, 0.0f)); } myKeyNavTransf3D.mul(trans_rot); // Return the final transformation myKeyNavTransf3D to target target_trGr.setTransform(myKeyNavTransf3D); } // Set wakeup criteria for next time. wakeupOn(wakeUp); } } /** * This class creates the Earth by using the Sphere class and a given texture * (Earth.jpg). */ class Earth { public Sphere earth; private String renderingType; private float scale_XYZ; private Color3f diffAmb, reflDiff, reflSpec, emittedLight; private float c; // shininess; private Appearance appearance; private Material material; private ColoringAttributes coloringAttributes; private PolygonAttributes polygonAttributes; private NewTextureLoader newTextureLoader; private Texture texture; private TextureAttributes textAttr; /** * Constructor that allows to specify the desired rendering's mode and the * desired scale factor. * * @param java.lang.String * nom - the desired type of earth's rendering, * @param type * float s_XYZ - the scale factor to adjust the earth's radius */ public Earth(String name, float s_XYZ) { renderingType = name; scale_XYZ = s_XYZ; } /** * This methode serves to construct the earth. * * @return com.sun.j3d.utils.geometry.Sphere earth - the constructed earth */ public Sphere myEarth() { // Optical properties of the earth. // Ambient-diffuse-reflection coefficient diffAmb = new Color3f(1.0f, 1.0f, 1.0f); // Diffuse-reflection coefficient reflDiff = new Color3f(1.0f, 1.0f, 1.0f); // Specular-reflection coefficient (reflectance function) reflSpec = new Color3f(0.0f, 0.0f, 0.1f); // c = shininess: cos^c in the specular reflection c = 1; // Emitted light emittedLight = new Color3f(0.0f, 0.0f, 0.0f); appearance = new Appearance(); // Create the material and set up the optical properties. material = new Material(diffAmb, emittedLight, reflDiff, reflSpec, c); appearance.setMaterial(material); // Set up the polygon's rendering-mode (with the polygonAttributes) and // the shading-mode (with the coloringAttributes). polygonAttributes = new PolygonAttributes(); coloringAttributes = new ColoringAttributes(); // Points if (renderingType.compareTo("points") == 0) { polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_POINT); } /* Lines*/ else if (renderingType.compareTo("lines") == 0) { polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_LINE); } /* Polygons */ else if (renderingType.compareTo("polygons") == 0) { /* is the default value*/ polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_FILL); coloringAttributes.setShadeModel(ColoringAttributes.SHADE_FLAT); } /* Gouraud */ else if (renderingType.compareTo("gouraud") == 0) { polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_FILL); /* is the default value*/ coloringAttributes.setShadeModel(ColoringAttributes.SHADE_GOURAUD); /* is the default value*/ } else if (renderingType.compareTo("texture") == 0) { polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_FILL); /* is the default value*/ coloringAttributes.setShadeModel(ColoringAttributes.SHADE_GOURAUD); /* is the default value*/ /* Loading of the texture*/ newTextureLoader = new NewTextureLoader("Images/Earth.jpg"); newTextureLoader.setImageObserver(newTextureLoader.getImageObserver()); texture = newTextureLoader.getTexture(); appearance.setTexture(texture); /* Application mode of the texture */ textAttr = new TextureAttributes(); textAttr.setTextureMode(TextureAttributes.REPLACE); /* there still are: BLEND, COMBINE, DECAL, and MODULATE*/ appearance.setTextureAttributes(textAttr); } appearance.setPolygonAttributes(polygonAttributes); appearance.setColoringAttributes(coloringAttributes); /* Construction of the earth with all its features.*/ earth = new Sphere(scale_XYZ, Sphere.GENERATE_NORMALS | Sphere.GENERATE_TEXTURE_COORDS, 10, appearance); return earth; } } /** * This class creates a tetrahedron with a given texture (Claude.jpg). */ class Tetrahedron extends Shape3D { private float scale_XYZ; private Point3f vertices[]; private int lengthVertices = 4, lengthTetraFaceIndices = 12; // 4 faces x 3 // vertices private int tetraFaceIndices[], textCoordIndices[]; private GeometryInfo tetra_GeometryInfo; private NormalGenerator normalGenerator; private Stripifier stripifier; private GeometryArray tetra_GeometryArray; private TexCoord2f textCoord2f[]; // for triangles private boolean crAngle; private Appearance appearance; private Color3f diffAmb, reflDiff, reflSpec, emittedLight; private Material material; private TransparencyAttributes trAttr; private NewTextureLoader newTextureLoader; private Texture texture; private TextureAttributes textAttr; /** * Constructor that allows to specify the desired scale factor. * * @param type * float s_XYZ - the scale factor to adjust the edges's length of * the tetrahedron */ public Tetrahedron(float s_XYZ) { scale_XYZ = s_XYZ; } /** * Construction of the desired tetrahedron. * * @return javax.media.j3d.Shape3D myTetrahedron - the constructed * tetrahedron */ public Shape3D myTetrahedron() { ////////////////////// Geometric part /////////////////////////// // The 4 vertices p0, p1, p2 and p3 of the tetrahedron. vertices = new Point3f[lengthVertices]; // 4 vertices[0] = new Point3f(0.0f, 0.0f, 0.0f); vertices[1] = new Point3f(1.0f, 0.0f, 0.0f); vertices[2] = new Point3f(0.0f, 1.0f, 0.0f); vertices[3] = new Point3f(0.0f, 0.0f, 1.0f); // Scaling of vertices for (int i = 0; i < lengthVertices; i++) // lengthVertices = 4 vertices[i].scale(scale_XYZ); // Set the face's indices for the tetrahedron (referenced to the array // of vertices // by setCoordinates(vertices) and // setCoordinateIndices(tetraFaceIndices)). tetraFaceIndices = new int[lengthTetraFaceIndices]; // 12 // From the camera in the view coordinate system // bottom tetraFaceIndices[0] = 0; tetraFaceIndices[1] = 1; tetraFaceIndices[2] = 3; // back-left face tetraFaceIndices[3] = 0; tetraFaceIndices[4] = 3; tetraFaceIndices[5] = 2; // back face tetraFaceIndices[6] = 0; tetraFaceIndices[7] = 2; tetraFaceIndices[8] = 1; // front face tetraFaceIndices[9] = 1; tetraFaceIndices[10] = 2; tetraFaceIndices[11] = 3; // Create the GeometryInfo instance and set the vertices tetra_GeometryInfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY); tetra_GeometryInfo.setCoordinates(vertices); tetra_GeometryInfo.setCoordinateIndices(tetraFaceIndices); // triangulator = new Triangulator(); // only for polygons: // POLYGON_ARRAY // triangulator.triangulate(tetra_GeometryInfo); // and with: int // stripCounts[] // gi.setStripCounts(...) // int contourCounts[] // Set the parameters (1 texture with dimension 2) for the texture's // coordinates tetra_GeometryInfo.setTextureCoordinateParams(1, 2); // case #1: each face of the tetrahedron has the same texture portion. // The coordinates of the 3 points in the 2D texture space. textCoord2f = new TexCoord2f[3]; textCoord2f[0] = new TexCoord2f(0.0f, 0.2f); textCoord2f[1] = new TexCoord2f(0.5f, 1.0f); textCoord2f[2] = new TexCoord2f(1.0f, 0.5f); // Set the texture coordinate's indices (referenced to the array of 2D // points // in the texture space by setTextureCoordinates(0, textCoord2f) and // setTextureCoordinateIndices(0, textCoordIndices)). textCoordIndices = new int[lengthTetraFaceIndices]; // 12 // From the camera in the view coordinate system (inverse of // tetraFaceIndices !!!) // front face textCoordIndices[0] = 0; textCoordIndices[1] = 1; textCoordIndices[2] = 2; // back face textCoordIndices[3] = 0; textCoordIndices[4] = 1; textCoordIndices[5] = 2; // back-left face textCoordIndices[6] = 2; textCoordIndices[7] = 0; textCoordIndices[8] = 1; // bottom textCoordIndices[9] = 0; textCoordIndices[10] = 1; textCoordIndices[11] = 2; /* * // case #2: each face of the tetrahedron has a different part of the * texture. * // The coordinates of the 4 points in the 2D texture space. * textCoord2f = new TexCoord2f[4]; textCoord2f[0] = new * TexCoord2f(0.0f, 0.5f); textCoord2f[1] = new TexCoord2f(1.0f, 0.5f); * textCoord2f[2] = new TexCoord2f(0.6f, 0.7f); textCoord2f[3] = new * TexCoord2f(0.6f, 0.3f); * * // Set the texture coordinate's indices (referenced to the array of * 2D points // in the texture space by setTextureCoordinates(0, * textCoord2f) and // setTextureCoordinateIndices(0, * textCoordIndices)). textCoordIndices = new * int[lengthTetraFaceIndices]; // 12 * // From the camera in the view coordinate system (inverse of * tetraFaceIndices !!!) // front face textCoordIndices[0] = 3; * textCoordIndices[1] = 2; textCoordIndices[2] = 0; // back face * textCoordIndices[3] = 1; textCoordIndices[4] = 2; textCoordIndices[5] = * 3; // back-left face textCoordIndices[6] = 1; textCoordIndices[7] = * 0; textCoordIndices[8] = 2; // bottom textCoordIndices[9] = 1; * textCoordIndices[10]= 3; textCoordIndices[11]= 0; */ // just one set tetra_GeometryInfo.setTextureCoordinates(0, textCoord2f); // just one set tetra_GeometryInfo.setTextureCoordinateIndices(0, textCoordIndices); normalGenerator = new NormalGenerator(); normalGenerator.generateNormals(tetra_GeometryInfo); if (crAngle) normalGenerator.setCreaseAngle(0.0f); // with 0 radian ===> creased stripifier = new Stripifier(); stripifier.stripify(tetra_GeometryInfo); tetra_GeometryArray = tetra_GeometryInfo.getGeometryArray(); // The geonometry is passed to the instance this of the tetrahedron. this.setGeometry(tetra_GeometryArray); ////////////////////// Appearance part /////////////////////////// appearance = new Appearance(); // Optical properties of the tetrahedron. // Ambient-diffuse-reflection coefficient diffAmb = new Color3f(1.0f, 0.5f, 1.0f); // Diffuse-reflection coefficient reflDiff = new Color3f(1.0f, 0.5f, 1.0f); // Specular-reflection coefficient (reflectance function) reflSpec = new Color3f(1.0f, 0.5f, 1.0f); // c = shininess: cos^c in the specular reflection float c = 15; // Emitted light emittedLight = new Color3f(0.0f, 0.0f, 0.0f); material = new Material(diffAmb, emittedLight, reflDiff, reflSpec, c); appearance.setMaterial(material); // This instance acts only on the tetrahedron and not on its texture. trAttr = new TransparencyAttributes(TransparencyAttributes.NICEST, 0.0f); // 0.0 = fully opaque // 1.0 = fully transparent appearance.setTransparencyAttributes(trAttr); // Loading the texture newTextureLoader = new NewTextureLoader("Images/Claude.jpg"); newTextureLoader.setImageObserver(newTextureLoader.getImageObserver()); texture = newTextureLoader.getTexture(); appearance.setTexture(texture); // Application mode of the texture textAttr = new TextureAttributes(); textAttr.setTextureMode(TextureAttributes.MODULATE); // there still are: // BLEND, COMBINE, // DECAL, and REPLACE appearance.setTextureAttributes(textAttr); // The appearance is passed to the instance this of the tetrahedron. this.setAppearance(appearance); return this; } } /** * This class creates a right-handed 3D coordinate system. */ class CoordSyst extends Shape3D { private float rX, gX, bX, rY, gY, bY, rZ, gZ, bZ, scale_XYZ; private LineArray axes; private float scaledExtremites[]; /** * Constructor that allows to specify the desired initial colors and the * length of the axes. * * @param type * float rougeX, vertX, bleuX, rougeY, vertY, bleuY, rougeZ, * vertZ, bleuZ - the colors of the axes * @param type * float s_XYZ - the scale factor to adjust the axes's length */ public CoordSyst(float rougeX, float vertX, float bleuX, float rougeY, float vertY, float bleuY, float rougeZ, float vertZ, float bleuZ, float s_XYZ) { rX = rougeX; rY = rougeY; rZ = rougeZ; gX = vertX; gY = vertY; gZ = vertZ; bX = bleuX; bY = bleuY; bZ = bleuZ; scale_XYZ = s_XYZ; // Colors of the three axes. float color[] = { rX, gX, bX, rX, gX, bX, // the x axis rY, gY, bY, rY, gY, bY, // the y axis rZ, gZ, bZ, rZ, gZ, bZ }; // the z axis // Construction of the axes (LineArray). axes = new LineArray(6, LineArray.COORDINATES | LineArray.COLOR_3); // Scalling of the vertices of the 3 axes using scale_XYZ. scaledExtremites = new float[extremites.length]; for (int i = 0; i < extremites.length; i++) scaledExtremites[i] = extremites[i] * scale_XYZ; axes.setCoordinates(0, scaledExtremites); axes.setColors(0, color); this.setGeometry(axes); } // Definition of the geometry of the three axes. private static final float extremites[] = { // x-axis 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // y-axis 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, // z-axis 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; }