001    /**
002     * NDViewer.java
003     *
004     * This file is part of jndclifford package and it's distributed under the terms of the MIT license.
005     *
006     * The MIT License :
007     * -----------------
008     * Copyright (c) 2002, 2003, 2004, 2005 Pietro Brignola
009     *
010     * Permission is hereby granted, free of charge, to any person obtaining a
011     * copy of this software and associated documentation files (the "Software"),
012     * to deal in the Software without restriction, including without limitation
013     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
014     * and/or sell copies of the Software, and to permit persons to whom the
015     * Software is furnished to do so, subject to the following conditions:
016     * The above copyright notice and this permission notice shall be included in
017     * all copies or substantial portions of the Software.
018     *
019     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
020     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
021     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
022     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
023     * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
024     * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
025     * DEALINGS IN THE SOFTWARE.
026     */
027    
028    package jndclifford;
029    
030    import javax.swing.*;
031    import java.awt.*;
032    import java.awt.event.*;
033    import java.io.*;
034    import javax.swing.event.*;
035    
036    import com.sun.j3d.utils.universe.*;
037    import com.sun.j3d.utils.behaviors.vp.*;
038    
039    import javax.media.j3d.*;
040    import javax.vecmath.*;
041    
042    import java.awt.event.*;
043    import java.util.*;
044    
045    import jclifford.*;
046    
047    /**
048     * <p>NDViewer renders, interactively rotatable, traslatable, and zoomable
049     * geometric scene using Clifford Algebra in 4D Projective space.</p>
050     * @version <p>0.2</p>
051     * @author <p>Realized by <a href="mailto:vassallo@csai.unipa.it">Giorgio Vassallo</a>, <a href="mailto:pietro.brignola@libero.it">Pietro Brignola</a>, May 2003.</p>
052     */
053    public class NDViewer extends JFrame{
054    
055            /**
056             * Creates a MVViewer Object.
057             */
058            public NDViewer()
059            {
060                    //Calling super constructor
061                    super("3D Projective MultiVector Viewer");
062    
063                    //Adding window listener for closing operation
064                    addWindowListener(
065                            new WindowAdapter(){
066                                    public void windowClosing(WindowEvent e){
067                                            //Exit
068                                            System.exit(0);
069                                    }
070                            }
071                    );
072    
073                    //Creating new empty scene graph
074                    draw(new LinkedList());
075            }
076    
077            /**
078             * Creates a user defined scene and attach it to the virtual universe.
079             * Axis are present in the scene and background color is black.
080             * @param drawlist list of the Clifford elements (with relative color) to draw.
081             */
082            public void draw(LinkedList drawlist)
083            {
084                    draw(drawlist, new Color3f(0.0f, 0.0f, 0.0f), true);
085            }
086    
087            /**
088             * Creates a user defined scene and attach it to the virtual universe.
089             * @param drawlist list of the Clifford elements (with relative color) to draw.
090             * @param backgroundcolor the color of the background.
091             * @param axispresence specifies axis presence in the scene.
092             */
093            public void draw(LinkedList drawlist, Color3f backgroundcolor, boolean axispresence)
094            {
095                    //Finds the preferred GraphicsConfiguration object for the system
096                    GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
097    
098                    //Constructs and initializes a new Canvas3D using the preferred GraphicsConfiguration
099                    Canvas3D canvas3D = new Canvas3D(config);
100    
101                    //Adding Canvas3D to the pane
102                    getContentPane().removeAll();
103                    getContentPane().add("Center", canvas3D);
104    
105                    //Creating SimpleUniverse (Convenience Utility class)
106                    //This class sets up a minimal user environment to quickly and easily get a Java 3D program
107                    //up and running.
108                    SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
109    
110                    //Creating the root of the branch graph
111                    BranchGroup scene = createSceneGraph(drawlist, axispresence);
112    
113                    //Creating scene bounds
114                    BoundingSphere bounds = new BoundingSphere(new Point3d(), 1.0e6);
115    
116                    //Creating platform geometry
117                    PlatformGeometry platformGeometry = new PlatformGeometry();
118    
119                    //Adding background
120                    Background background = new Background(backgroundcolor);
121                    background.setApplicationBounds(bounds);
122                    platformGeometry.addChild(background);
123    
124                    //Adding ambient light to platform geometry
125                    Color3f ambientColor = new Color3f(0.4f, 0.4f, 0.4f);
126                    AmbientLight ambientLight = new AmbientLight(ambientColor);
127                    ambientLight.setInfluencingBounds(bounds);
128                    platformGeometry.addChild(ambientLight);
129    
130                    //Adding directional light 1 to platform geometry
131                    Color3f light1Color = new Color3f(0.7f, 0.7f, 0.7f);
132                    Vector3f light1Direction  = new Vector3f(-1.0f, -1.0f, -1.0f);
133                    DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction);
134                    light1.setInfluencingBounds(bounds);
135                    platformGeometry.addChild(light1);
136    
137                    //Adding directional light 2 to platform geometry
138                    Color3f light2Color = new Color3f(0.5f, 0.5f, 0.5f);
139                    Vector3f light2Direction  = new Vector3f( 1.0f, -1.0f, -1.0f);
140                    DirectionalLight light2 = new DirectionalLight(light2Color, light2Direction);
141                    light2.setInfluencingBounds(bounds);
142                    platformGeometry.addChild(light2);
143    
144                    //Adding directional light 3 to platform geometry
145                    Color3f light3Color = new Color3f(0.4f, 0.4f, 0.4f);
146                    Vector3f light3Direction  = new Vector3f( 1.0f,  1.0f, -1.0f);
147                    DirectionalLight light3 = new DirectionalLight(light3Color, light3Direction);
148                    light3.setInfluencingBounds(bounds);
149                    platformGeometry.addChild(light3);
150    
151                    //Adding directional light 4 to platform geometry
152                    Color3f light4Color = new Color3f(0.3f, 0.3f, 0.3f);
153                    Vector3f light4Direction  = new Vector3f(-1.0f,  1.0f, -1.0f);
154                    DirectionalLight light4 = new DirectionalLight(light4Color, light4Direction);
155                    light4.setInfluencingBounds(bounds);
156                    platformGeometry.addChild(light4);
157    
158                    //Seting platform geometry
159                    simpleU.getViewingPlatform().setPlatformGeometry(platformGeometry);
160    
161                    //Behaviour for moving the View around a point of interest when the
162                    //mouse is dragged with a mouse button pressed.
163                    //Includes rotation, zoom, and translation actions.
164                    OrbitBehavior orbit = new OrbitBehavior(canvas3D, OrbitBehavior.REVERSE_ALL 
165                                                                                                                    | OrbitBehavior.STOP_ZOOM );
166                    orbit.setSchedulingBounds(new BoundingSphere(new Point3d(), 1.0e6));
167                    orbit.setProportionalZoom(true);
168                    orbit.setMinRadius(2.0);
169                    //Transform3D T3D = new Transform3D();
170                    //T3D.setTranslation(new Vector3f( 0.0f, 0.0f, 6.0f));
171                    //orbit.setHomeTransform(T3D);
172                    simpleU.getViewingPlatform().setViewPlatformBehavior(orbit);
173    
174                    //This will move the ViewPlatform back a bit so the objects in the scene can be viewed.
175                    simpleU.getViewingPlatform().setNominalViewingTransform();
176    
177                    //Setting the view model's back clip distance (model's front clip distance is 0.1 by default)
178                    //simpleU.getViewer().getView().setFrontClipPolicy(View.VIRTUAL_EYE);
179                    //simpleU.getViewer().getView().setBackClipPolicy(View.VIRTUAL_EYE);
180                    simpleU.getViewer().getView().setBackClipDistance(100.0);
181                    //simpleU.getViewingPlatform().getViewPlatform().setActivationRadius(1.0e6f);
182    
183                    //Used to add Nodes to the geometry side (as opposed to the view side) of the scene graph.
184                    simpleU.addBranchGraph(scene);
185    
186                    //Setting frame title
187                    setTitle("3d Projective MultiVector Viewer - Scene created on " + (new Date()).toString());
188    
189                    //Setting Frame size
190                    setSize(640,640);
191            }
192    
193            /**
194             * Creates the specified defined scene.
195             * @param drawlist list of the Clifford elements (with relative color) to draw.
196             * @param axispresence specifies axis presence in the scene.
197             * @return the branch group of the scene graph
198             */
199            private BranchGroup createSceneGraph(LinkedList drawlist, boolean axispresence)
200            {
201                    //Creating the root of the branch graph
202                    BranchGroup objRoot = new BranchGroup();
203    
204                    // Create a Transformgroup to scale all objects so they appear in the scene.
205                    Transform3D t3d = new Transform3D();
206                    //t3d.setScale(0.7);
207                    TransformGroup objScale = new TransformGroup();
208                    //objScale.setTransform(t3d);
209                    objRoot.addChild(objScale);
210    
211                    //Creating the transform group node and initializing it to the identity.
212                    //Enabling the TRANSFORM_WRITE capability so that behavior code can modify it at runtime.
213                    //Adding it to the root of the subgraph.
214                    TransformGroup objTrans = new TransformGroup();
215                    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
216                    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
217                    objTrans.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
218                    objTrans.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
219                    objTrans.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
220                    objScale.addChild(objTrans);
221    
222                    //Adding axis
223                    if(axispresence)
224                            objTrans.addChild(new Axis());
225    
226                    //Drawing 3D colored representation of all the NDElement in the list
227                    Iterator it = drawlist.iterator();
228                    while(it.hasNext())
229                            addNDElementNode(objTrans, (NDElement) it.next());
230    
231                    //Letting Java 3D perform optimizations on this scene graph and returning it
232                    objRoot.compile();
233                    return objRoot;
234            }
235    
236            /**
237             * Creates 3D representation of the NDElement element and attach it to the group.
238             * @param objTrans the group where all NDElement elements are added.
239             * @param element NDElement element to draw.
240             */
241            private void addNDElementNode(TransformGroup objTrans, NDElement element)
242            {
243                    //Temporary reference variables
244                    float h1, h2, h3, x1, y1, z1, x2, y2, z2, x3, y3, z3;
245                    CliffordBitSet cl1, cl2, cl3;
246                    //Handling different generators number
247                    int size = element.getGeneratorsSize();
248                    switch(size){
249                            case 0:
250                                    //Handling empty generator's list
251                                    return;
252                            case 1:
253                                    //Adding point to the scene
254                                    cl1 = (CliffordBitSet) element.getGenerators().get(0);
255                                    //Handling elements with dimension outside E3
256                                    if(cl1.getMaxDimension() > 3)
257                                            return;
258                                    h1 = (float) (cl1.get("0"));
259                                    x1 = (float) (cl1.get("1") / h1);
260                                    y1 = (float) (cl1.get("2") / h1);
261                                    z1 = (float) (cl1.get("3") / h1);
262                                    objTrans.addChild(new PointShape(new Point3f(x1, y1, z1), element.getColor()));
263                            break;
264                            case 2:
265                                    //Adding segment to the scene
266                                    cl1 = (CliffordBitSet) element.getGenerators().get(0);
267                                    cl2 = (CliffordBitSet) element.getGenerators().get(1);
268                                    //Handling elements with dimension outside E3
269                                    if(cl1.getMaxDimension() > 3 || cl2.getMaxDimension() > 3)
270                                            return;
271                                    h1 = (float) (cl1.get("0"));
272                                    x1 = (float) (cl1.get("1") / h1);
273                                    y1 = (float) (cl1.get("2") / h1);
274                                    z1 = (float) (cl1.get("3") / h1);
275                                    h2 = (float) (cl2.get("0"));
276                                    x2 = (float) (cl2.get("1") / h2);
277                                    y2 = (float) (cl2.get("2") / h2);
278                                    z2 = (float) (cl2.get("3") / h2);
279                                    objTrans.addChild(new SegmentShape(new Point3f(x1, y1, z1),
280                                                                                                            new Point3f(x2, y2, z2),
281                                                                                                            element.getColor()));
282                            break;
283                            case 3:
284                                    //Adding triangle to the scene
285                                    cl1 = (CliffordBitSet) element.getGenerators().get(0);
286                                    cl2 = (CliffordBitSet) element.getGenerators().get(1);
287                                    cl3 = (CliffordBitSet) element.getGenerators().get(2);
288                                    //Handling elements with dimension outside E3
289                                    if(cl1.getMaxDimension() > 3 || cl2.getMaxDimension() > 3 || cl3.getMaxDimension() > 3)
290                                            return;
291                                    h1 = (float) (cl1.get("0"));
292                                    x1 = (float) (cl1.get("1") / h1);
293                                    y1 = (float) (cl1.get("2") / h1);
294                                    z1 = (float) (cl1.get("3") / h1);
295                                    h2 = (float) (cl2.get("0"));
296                                    x2 = (float) (cl2.get("1") / h2);
297                                    y2 = (float) (cl2.get("2") / h2);
298                                    z2 = (float) (cl2.get("3") / h2);
299                                    h3 = (float) (cl3.get("0"));
300                                    x3 = (float) (cl3.get("1") / h3);
301                                    y3 = (float) (cl3.get("2") / h3);
302                                    z3 = (float) (cl3.get("3") / h3);
303                                    objTrans.addChild(new TriangleShape(new Point3f(x1, y1, z1),
304                                                                                                            new Point3f(x2, y2, z2),
305                                                                                                            new Point3f(x3, y3, z3),
306                                                                                                            element.getColor()));
307                            break;
308                            default:
309                                    //Handling higher dimensionality generator's list
310                                    return;
311                    }
312            }
313    }