summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/joglutils.jarbin133187 -> 148347 bytes
-rw-r--r--src/net/java/joglutils/msg/actions/Action.java27
-rw-r--r--src/net/java/joglutils/msg/actions/GLRenderAction.java1
-rw-r--r--src/net/java/joglutils/msg/actions/RayPickAction.java211
-rw-r--r--src/net/java/joglutils/msg/impl/RayTriangleIntersection.java146
-rw-r--r--src/net/java/joglutils/msg/math/Line.java6
-rw-r--r--src/net/java/joglutils/msg/math/Mat4f.java10
-rw-r--r--src/net/java/joglutils/msg/misc/Path.java52
-rw-r--r--src/net/java/joglutils/msg/misc/PickedPoint.java72
-rw-r--r--src/net/java/joglutils/msg/misc/PrimitiveVertex.java100
-rw-r--r--src/net/java/joglutils/msg/misc/TriangleCallback.java65
-rw-r--r--src/net/java/joglutils/msg/nodes/Camera.java122
-rw-r--r--src/net/java/joglutils/msg/nodes/Coordinate3.java2
-rw-r--r--src/net/java/joglutils/msg/nodes/Group.java4
-rw-r--r--src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java7
-rw-r--r--src/net/java/joglutils/msg/nodes/Node.java6
-rw-r--r--src/net/java/joglutils/msg/nodes/Shape.java43
-rw-r--r--src/net/java/joglutils/msg/nodes/Texture2.java9
-rw-r--r--src/net/java/joglutils/msg/nodes/TextureCoordinate2.java2
-rw-r--r--src/net/java/joglutils/msg/nodes/Transform.java10
-rw-r--r--src/net/java/joglutils/msg/nodes/TriangleBasedShape.java105
-rw-r--r--src/net/java/joglutils/msg/nodes/TriangleSet.java101
-rw-r--r--src/net/java/joglutils/msg/test/DisplayShelf.java117
23 files changed, 1162 insertions, 56 deletions
diff --git a/build/joglutils.jar b/build/joglutils.jar
index 33d954e..e46dd2a 100644
--- a/build/joglutils.jar
+++ b/build/joglutils.jar
Binary files differ
diff --git a/src/net/java/joglutils/msg/actions/Action.java b/src/net/java/joglutils/msg/actions/Action.java
index 34f14ea..b206cdb 100644
--- a/src/net/java/joglutils/msg/actions/Action.java
+++ b/src/net/java/joglutils/msg/actions/Action.java
@@ -70,6 +70,13 @@ public abstract class Action {
altered by the nodes the action traverses. */
public abstract State getState();
+ /** Returns the path to the node currently being traversed. The
+ caller should make a copy of this path if it is desired to keep
+ it around. */
+ public Path getPath() {
+ return path;
+ }
+
private Object[] argTmp = new Object[2];
/** Invokes the appropriate action method for the given Node. */
protected void apply(ActionTable table, Node node) {
@@ -78,10 +85,28 @@ public abstract class Action {
if (m != null) {
argTmp[0] = this;
argTmp[1] = node;
- m.invoke(null, argTmp);
+ push(node);
+ try {
+ m.invoke(null, argTmp);
+ } finally {
+ pop();
+ }
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
+
+ private Path path = new Path();
+ /** Pushes the given Node onto the internal Path this Action
+ maintains during traversal. */
+ private void push(Node node) {
+ path.add(node);
+ }
+
+ /** Pops the given Node off the internal Path this Action maintains
+ during traversal. */
+ private void pop() {
+ path.remove(path.size() - 1);
+ }
}
diff --git a/src/net/java/joglutils/msg/actions/GLRenderAction.java b/src/net/java/joglutils/msg/actions/GLRenderAction.java
index 7b2fb56..b058e13 100644
--- a/src/net/java/joglutils/msg/actions/GLRenderAction.java
+++ b/src/net/java/joglutils/msg/actions/GLRenderAction.java
@@ -42,7 +42,6 @@ import java.lang.reflect.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
-import net.java.joglutils.msg.elements.*;
import net.java.joglutils.msg.misc.*;
import net.java.joglutils.msg.nodes.*;
diff --git a/src/net/java/joglutils/msg/actions/RayPickAction.java b/src/net/java/joglutils/msg/actions/RayPickAction.java
new file mode 100644
index 0000000..633d7c4
--- /dev/null
+++ b/src/net/java/joglutils/msg/actions/RayPickAction.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.actions;
+
+import java.awt.Component;
+import java.lang.reflect.*;
+import java.util.*;
+
+import net.java.joglutils.msg.math.*;
+import net.java.joglutils.msg.misc.*;
+import net.java.joglutils.msg.nodes.*;
+
+public class RayPickAction extends Action {
+ // Boilerplate
+ private static State defaults = new State();
+ /** Returns the default state all instances of this class are initialized with. */
+ public static State getDefaultState() {
+ return defaults;
+ }
+ private static ActionTable table = new ActionTable(RayPickAction.class);
+
+ /** Adds an action method for the given node type to this action.
+ This should only be called by developers adding new node types
+ and not desiring to use the standard overriding mechanisms. */
+ public static void addActionMethod(Class<? extends Node> nodeType, Method m) {
+ table.addActionMethod(nodeType, m);
+ }
+
+ private State state = new State(defaults);
+ public State getState() {
+ return state;
+ }
+
+ static {
+ // Set up action methods
+ // Note that because this action is built-in, we use virtual
+ // method dispatch to allow overriding of rendering functionality.
+ // We could optionally pull in all of the action methods into this
+ // class. However, factoring the setting of the elements into the
+ // nodes provides for more sharing of common functionality among
+ // actions.
+ try {
+ addActionMethod(Node.class, RayPickAction.class.getMethod("rayPick", RayPickAction.class, Node.class));
+ } catch (Exception e) {
+ throw new RuntimeException("Error initializing action method for RayPickAction class", e);
+ }
+ }
+
+ private int applyDepth = 0;
+ private Vec2f normalizedPoint;
+ private Line ray;
+
+ private Line computedRay;
+
+ static class RayPickedPoint implements Comparable<RayPickedPoint> {
+ float t;
+ PickedPoint point;
+
+ RayPickedPoint(float t, PickedPoint point) {
+ this.t = t;
+ this.point = point;
+ }
+
+ public boolean equals(Object o) {
+ return (o == this);
+ }
+
+ public int compareTo(RayPickedPoint p) {
+ return (int) Math.signum(t - p.t);
+ }
+ }
+
+ // While we're in the process of traversing the scene graph, we
+ // memorize both the paths to intersected geometry as well as the
+ // t parameter indicating the distance to the geometry.
+ private List<RayPickedPoint> tempPickedPoints = new ArrayList<RayPickedPoint>();
+
+ // The list of picked points, sorted by increasing distance from the camera
+ private List<PickedPoint> pickedPoints = new ArrayList<PickedPoint>();
+
+ public void apply(Node node) {
+ int depth = applyDepth++;
+ try {
+ if (depth == 0) {
+ reset();
+ }
+ apply(table, node);
+ } finally {
+ --applyDepth;
+ if (depth == 0) {
+ tabulate();
+ }
+ }
+ }
+
+ /** Sets the point for this RayPickAction based on x and y
+ coordinates relative to the specified AWT Component. */
+ public void setPoint(int x, int y, Component component) {
+ setNormalizedPoint(new Vec2f((float) x / (float) component.getWidth(),
+ 1.0f - ((float) y / (float) component.getHeight())));
+ }
+
+ /** Sets the normalized point for this RayPickAction, where x and y
+ are relative to the lower-left of the viewport and range from
+ [0..1]. */
+ public void setNormalizedPoint(Vec2f normalizedPoint) {
+ this.normalizedPoint = normalizedPoint;
+ ray = null;
+ computedRay = null;
+ }
+
+ /** Sets the ray in world coordinates that this RayPickAction should
+ use for its computation. */
+ public void setRay(Line ray) {
+ this.ray = ray;
+ computedRay = ray;
+ normalizedPoint = null;
+ }
+
+ /** Returns the list of points this action selected during the last
+ traversal, sorted in increasing order of distance from the
+ origin. Typically applications will only need to deal with the
+ first point in the returned list. */
+ public List<PickedPoint> getPickedPoints() {
+ return pickedPoints;
+ }
+
+ /** Returns the computed 3D ray in world coordinates that this
+ RayPickAction is using for its picking. If the action is
+ configured with on-screen coordinates instead of with a 3D ray,
+ then this is automatically updated every time the action
+ traverses a Camera node. May return null if this has not been
+ computed yet. End users should not need to call this method. */
+ public Line getComputedRay() {
+ return computedRay;
+ }
+
+ /** Called during scene graph traversal to update the 3D ray
+ associated with this action if it was configured with on-screen
+ coordinates. End users should not need to call this method. */
+ public void recomputeRay(Camera camera) {
+ if (normalizedPoint != null && ray == null) {
+ if (computedRay == null) {
+ computedRay = new Line();
+ }
+ camera.unproject(normalizedPoint, computedRay);
+ }
+ }
+
+ /** Registers a picked point with the RayPickAction during scene
+ graph traversal. The t argument is the time parameter indicating
+ the distance from the camera. A reference to the PickedPoint is
+ maintained internally so the caller should add a copy if the
+ original is still mutable. End users should not need to call
+ this method. */
+ public void addPickedPoint(PickedPoint p, float t) {
+ tempPickedPoints.add(new RayPickedPoint(t, p));
+ }
+
+ private void reset() {
+ tempPickedPoints.clear();
+ pickedPoints.clear();
+ }
+
+ private void tabulate() {
+ Collections.sort(tempPickedPoints);
+ for (RayPickedPoint p : tempPickedPoints) {
+ pickedPoints.add(p.point);
+ }
+ }
+
+ /** Action method which dispatches to per-node rendering functionality. */
+ public static void rayPick(RayPickAction action, Node node) {
+ node.rayPick(action);
+ }
+}
diff --git a/src/net/java/joglutils/msg/impl/RayTriangleIntersection.java b/src/net/java/joglutils/msg/impl/RayTriangleIntersection.java
new file mode 100644
index 0000000..13d49e9
--- /dev/null
+++ b/src/net/java/joglutils/msg/impl/RayTriangleIntersection.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.impl;
+
+import net.java.joglutils.msg.math.*;
+
+/** Intersection of ray with triangle. Computes parameteric t along
+ with barycentric coordinates (u, v) indicating weight of vert1 and
+ vert2 (weight of vert0 = 1 - u - v) which can be used to
+ interpolate normals and texture coordinates. Two versions, one for
+ two-sided triangle casts and one including backface
+ culling. Algorithm from Moller, Trumbore, "Fast, Minimum Storage
+ Ray / Triangle Intersection", Journal of Graphics Tools, Volume 2,
+ Number 1, 1997, pp. 21-28. */
+
+public class RayTriangleIntersection {
+ private Vec3f edge1 = new Vec3f();
+ private Vec3f edge2 = new Vec3f();
+ private Vec3f tvec = new Vec3f();
+ private Vec3f pvec = new Vec3f();
+ private Vec3f qvec = new Vec3f();
+
+ private static final float EPSILON = 0.000001f;
+
+ public boolean intersectTriangle(Line ray,
+ Vec3f vert0,
+ Vec3f vert1,
+ Vec3f vert2,
+ Vec3f tuv) {
+ // Find vectors for two edges sharing vert0
+ edge1.sub(vert1, vert0);
+ edge2.sub(vert2, vert0);
+
+ // Begin calculating determinant -- also used to calculate U parameter
+ pvec.cross(ray.getDirection(), edge2);
+
+ // If determinant is near zero, ray lies in plane of triangle
+ float det = edge1.dot(pvec);
+
+ if (det > -EPSILON && det < EPSILON)
+ return false;
+
+ float invDet = 1.0f / det;
+
+ // Calculate distance from vert0 to ray origin
+ tvec.sub(ray.getPoint(), vert0);
+
+ // Calculate U parameter and test bounds
+ float u = tvec.dot(pvec) * invDet;
+ if (u < 0.0f || u > 1.0f)
+ return false;
+
+ // Prepare to test V parameter
+ qvec.cross(tvec, edge1);
+
+ // Calculate V parameter and test bounds
+ float v = ray.getDirection().dot(qvec) * invDet;
+ if (v < 0.0f || (u + v) > 1.0f)
+ return false;
+
+ // Calculate t, ray intersects triangle
+ float t = edge2.dot(qvec) * invDet;
+
+ tuv.set(t, u, v);
+ return true;
+ }
+
+ public boolean intersectTriangleBackfaceCulling(Line ray,
+ Vec3f vert0,
+ Vec3f vert1,
+ Vec3f vert2,
+ Vec3f tuv) {
+ // Find vectors for two edges sharing vert0
+ edge1.sub(vert1, vert0);
+ edge2.sub(vert2, vert0);
+
+ // Begin calculating determinant -- also used to calculate U parameter
+ pvec.cross(ray.getDirection(), edge2);
+
+ // If determinant is near zero, ray lies in plane of triangle
+ float det = edge1.dot(pvec);
+
+ if (det < EPSILON)
+ return false;
+
+ // Calculate distance from vert0 to ray origin
+ tvec.sub(ray.getPoint(), vert0);
+
+ // Calculate U parameter and test bounds
+ float u = tvec.dot(pvec);
+ if (u < 0.0f || u > det)
+ return false;
+
+ // Prepare to test V parameter
+ qvec.cross(tvec, edge1);
+
+ // Calculate V parameter and test bounds
+ float v = ray.getDirection().dot(qvec);
+ if (v < 0.0f || (u + v) > det)
+ return false;
+
+ // Calculate t, scale parameters, ray intersects triangle
+ float t = edge2.dot(qvec);
+ float invDet = 1.0f / det;
+ t *= invDet;
+ u *= invDet;
+ v *= invDet;
+ tuv.set(t, u, v);
+ return true;
+ }
+}
diff --git a/src/net/java/joglutils/msg/math/Line.java b/src/net/java/joglutils/msg/math/Line.java
index 2004c08..c599e60 100644
--- a/src/net/java/joglutils/msg/math/Line.java
+++ b/src/net/java/joglutils/msg/math/Line.java
@@ -59,9 +59,9 @@ public class Line {
<b>point</b>. <b>direction</b> does not need to be normalized but must
not be the zero vector. */
public Line(Vec3f direction, Vec3f point) {
- direction = new Vec3f(direction);
- direction.normalize();
- point = new Vec3f(point);
+ this.direction = new Vec3f(direction);
+ this.direction.normalize();
+ this.point = new Vec3f(point);
alongVec = new Vec3f();
recalc();
}
diff --git a/src/net/java/joglutils/msg/math/Mat4f.java b/src/net/java/joglutils/msg/math/Mat4f.java
index b0cc67e..fc4d955 100644
--- a/src/net/java/joglutils/msg/math/Mat4f.java
+++ b/src/net/java/joglutils/msg/math/Mat4f.java
@@ -239,6 +239,16 @@ public class Mat4f {
dest.set(rc, tmp);
}
}
+
+ /** Transforms the given line (origin plus direction) by this
+ matrix. */
+ public Line xformLine(Line line) {
+ Vec3f pt = new Vec3f();
+ Vec3f dir = new Vec3f();
+ xformPt(line.getPoint(), pt);
+ xformDir(line.getDirection(), dir);
+ return new Line(dir, pt);
+ }
/** Copies data in column-major (OpenGL format) order into passed
float array, which must have length 16 or greater. */
diff --git a/src/net/java/joglutils/msg/misc/Path.java b/src/net/java/joglutils/msg/misc/Path.java
new file mode 100644
index 0000000..0743e86
--- /dev/null
+++ b/src/net/java/joglutils/msg/misc/Path.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.misc;
+
+import java.util.*;
+
+import net.java.joglutils.msg.nodes.*;
+
+/** Represents a path through the scene graph. The topmost node is at
+ index 0 and subsequent child nodes are at later indices. */
+
+public class Path extends ArrayList<Node> {
+ /** Returns a copy of this path. */
+ public Path copy() {
+ return (Path) clone();
+ }
+}
diff --git a/src/net/java/joglutils/msg/misc/PickedPoint.java b/src/net/java/joglutils/msg/misc/PickedPoint.java
new file mode 100644
index 0000000..20874b4
--- /dev/null
+++ b/src/net/java/joglutils/msg/misc/PickedPoint.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.misc;
+
+/** Represents a point on a piece of geometry picked for example by a
+ RayPickAction. */
+
+public class PickedPoint extends PrimitiveVertex {
+ private Path path;
+
+ public Object clone() {
+ PickedPoint point = (PickedPoint) super.clone();
+ if (path != null) {
+ point.path = path.copy();
+ }
+ return point;
+ }
+
+ /** Performs a "deep copy" of this PickedPoint so that it shares
+ none of its contents with this one. */
+ public PickedPoint copy() {
+ return (PickedPoint) clone();
+ }
+
+ /** Sets the path to the picked geometry. Note that this simply
+ retains a reference to the given Path, so the Path should be
+ copied if it can later be changed (for example, if it the
+ internal Path in an Action). */
+ public void setPath(Path path) {
+ this.path = path;
+ }
+
+ /** Returns the path to the picked geometry. */
+ public Path getPath() {
+ return path;
+ }
+}
diff --git a/src/net/java/joglutils/msg/misc/PrimitiveVertex.java b/src/net/java/joglutils/msg/misc/PrimitiveVertex.java
new file mode 100644
index 0000000..24b9e46
--- /dev/null
+++ b/src/net/java/joglutils/msg/misc/PrimitiveVertex.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.misc;
+
+import net.java.joglutils.msg.math.*;
+
+/** Represents a vertex on a primitive, including pieces of relevant
+ information such as location, surface normal and texture
+ coordinates. */
+
+public class PrimitiveVertex implements Cloneable {
+ private Vec3f coord;
+ private Vec2f texCoord;
+ private Vec4f color;
+ private Vec3f normal;
+
+ public PrimitiveVertex() {}
+
+ public Object clone() {
+ try {
+ PrimitiveVertex vtx = (PrimitiveVertex) super.clone();
+ if (coord != null) {
+ vtx.setCoord(new Vec3f(coord));
+ }
+ if (texCoord != null) {
+ vtx.setTexCoord(new Vec2f(texCoord));
+ }
+ if (color != null) {
+ vtx.setColor(new Vec4f(color));
+ }
+ if (normal != null) {
+ vtx.setNormal(new Vec3f(normal));
+ }
+ return vtx;
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Performs a "deep copy" of this PrimitiveVertex so that it shares
+ none of its contents with this one. */
+ public PrimitiveVertex copy() {
+ return (PrimitiveVertex) clone();
+ }
+
+ /** Sets the coordinate in this PrimitiveVertex. Refers to the passed vector by reference. */
+ public void setCoord(Vec3f coord) { this.coord = coord; }
+ /** Returns the coordinate in this PrimitiveVertex, or null if it is not known. */
+ public Vec3f getCoord() { return coord; }
+
+ /** Sets the texture coordinate in this PrimitiveVertex. Refers to the passed vector by reference. */
+ public void setTexCoord(Vec2f texCoord) { this.texCoord = texCoord; }
+ /** Returns the texture coordinate in this PrimitiveVertex, or null if it is not known. */
+ public Vec2f getTexCoord() { return texCoord; }
+
+ /** Sets the color in this PrimitiveVertex. Refers to the passed vector by reference. */
+ public void setColor(Vec4f color) { this.color = color; }
+ /** Returns the color in this PrimitiveVertex, or null if it is not known. */
+ public Vec4f getColor() { return color; }
+
+ /** Sets the normal in this PrimitiveVertex. Refers to the passed vector by reference. */
+ public void setNormal(Vec3f normal) { this.normal = normal; }
+ /** Returns the normal in this PrimitiveVertex, or null if it is not known. */
+ public Vec3f getNormal() { return normal; }
+}
diff --git a/src/net/java/joglutils/msg/misc/TriangleCallback.java b/src/net/java/joglutils/msg/misc/TriangleCallback.java
new file mode 100644
index 0000000..61140e2
--- /dev/null
+++ b/src/net/java/joglutils/msg/misc/TriangleCallback.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.misc;
+
+/** Supports iteration over the triangles inside shapes. */
+
+public interface TriangleCallback {
+ /** Called for each triangle generated during enumeration of the
+ triangles in a particular shape. Certain elements of the
+ PrimitiveVertex objects may be null if not set, such as normals
+ or texture coordinates. Note that the PrimitiveVertex objects
+ may be reused between calls, so users should copy them if
+ necessary.
+
+ @param triangleIndex the index within the set of triangles [0..num tris - 1]
+ @param v0 primitive vertex 0
+ @param i0 index of primitive vertex 0 in the current coordinates
+ @param v1 primitive vertex 1
+ @param i1 index of primitive vertex 1 in the current coordinates
+ @param v2 primitive vertex 2
+ @param i2 index of primitive vertex 2 in the current coordinates
+ */
+ public void triangleCB(int triangleIndex,
+ PrimitiveVertex v0,
+ int i0,
+ PrimitiveVertex v1,
+ int i1,
+ PrimitiveVertex v2,
+ int i2);
+}
diff --git a/src/net/java/joglutils/msg/nodes/Camera.java b/src/net/java/joglutils/msg/nodes/Camera.java
index 5d405fe..5333f81 100644
--- a/src/net/java/joglutils/msg/nodes/Camera.java
+++ b/src/net/java/joglutils/msg/nodes/Camera.java
@@ -70,6 +70,10 @@ public abstract class Camera extends Node {
GLModelMatrixElement .enable(GLRenderAction.getDefaultState());
GLProjectionMatrixElement .enable(GLRenderAction.getDefaultState());
GLViewingMatrixElement .enable(GLRenderAction.getDefaultState());
+
+ ModelMatrixElement .enable(RayPickAction.getDefaultState());
+ ProjectionMatrixElement.enable(RayPickAction.getDefaultState());
+ ViewingMatrixElement .enable(RayPickAction.getDefaultState());
}
public Camera() {
@@ -84,38 +88,74 @@ public abstract class Camera extends Node {
}
/** Sets the position of the camera. */
- public void setPosition(Vec3f position) { this.position.set(position); viewDirty = true; }
+ public void setPosition(Vec3f position) {
+ this.position.set(position);
+ viewDirty = true;
+ }
+
/** Returns the position of the camera. */
- public Vec3f getPosition() { return position; }
+ public Vec3f getPosition() {
+ return position;
+ }
/** Sets the orientation of the camera. */
- public void setOrientation(Rotf orientation) { this.orientation.set(orientation); viewDirty = true; }
+ public void setOrientation(Rotf orientation) {
+ this.orientation.set(orientation);
+ viewDirty = true;
+ }
+
/** Returns the orientation of the camera. */
- public Rotf getOrientation() { return orientation; }
+ public Rotf getOrientation() {
+ return orientation;
+ }
/** Sets the aspect ratio of the camera. */
- public void setAspectRatio(float aspectRatio) { this.aspectRatio = aspectRatio; projDirty = true; }
+ public void setAspectRatio(float aspectRatio) {
+ this.aspectRatio = aspectRatio;
+ projDirty = true;
+ }
+
/** Returns the aspect ratio of the camera. */
- public float getAspectRatio() { return aspectRatio; }
+ public float getAspectRatio() {
+ return aspectRatio;
+ }
/** Sets the distance from the eye point to the near clipping plane. */
- public void setNearDistance(float nearDistance) { this.nearDistance = nearDistance; projDirty = true; }
+ public void setNearDistance(float nearDistance) {
+ this.nearDistance = nearDistance;
+ projDirty = true;
+ }
+
/** Returns the distance from the eye point to the near clipping plane. */
- public float getNearDistance() { return nearDistance; }
+ public float getNearDistance() {
+ return nearDistance;
+ }
/** Sets the distance from the eye point to the far clipping plane. */
- public void setFarDistance(float farDistance) { this.farDistance = farDistance; projDirty = true; }
+ public void setFarDistance(float farDistance) {
+ this.farDistance = farDistance;
+ projDirty = true;
+ }
+
/** Returns the distance from the eye point to the far clipping plane. */
- public float getFarDistance() { return farDistance; }
+ public float getFarDistance() {
+ return farDistance;
+ }
/** Sets the distance from the eye point to the focal point of the
scene. This is only used for mouse-based interaction with the
scene and is not factored in to the rendering process. */
- public void setFocalDistance(float focalDistance) { this.focalDistance = focalDistance; projDirty = true; }
+ public void setFocalDistance(float focalDistance) {
+ this.focalDistance = focalDistance;
+ projDirty = true;
+ }
+
/** Returns the distance from the eye point to the focal point of
the scene. This is only used for mouse-based interaction with
the scene and is not factored in to the rendering process. */
- public float getFocalDistance() { return focalDistance; }
+ public float getFocalDistance() {
+ return focalDistance;
+ }
/** Returns the viewing matrix associated with this camera's parameters. */
public Mat4f getViewingMatrix() {
@@ -134,6 +174,59 @@ public abstract class Camera extends Node {
/** Returns the projection matrix associated with this camera's parameters. */
public abstract Mat4f getProjectionMatrix();
+ /** Un-projects the given on-screen point to a line in 3D space
+ which can be used for picking or other operations. The x and y
+ coordinates of the point must be in normalized coordinates,
+ where (0, 0) is the lower-left corner of the viewport and (1, 1)
+ is the upper-right. Allocates new storage for the returned
+ Line. */
+ public Line unproject(Vec2f point) {
+ Line line = new Line();
+ unproject(point, line);
+ return line;
+ }
+
+ /** Un-projects the given on-screen point in to the given line in 3D
+ space (in world coordinates) which can be used for picking or
+ other operations. The x and y coordinates of the point must be
+ in normalized coordinates, where (0, 0) is the lower-left corner
+ of the viewport and (1, 1) is the upper-right. */
+ public void unproject(Vec2f point, Line line) throws SingularMatrixException {
+ // First, we are going to compute the 3D point which corresponds
+ // to the given point on the near plane. Map the screen
+ // coordinates to the (-1, 1) range.
+ Vec4f pt3d = new Vec4f(2 * point.x() - 1,
+ 2 * point.y() - 1,
+ getNearDistance(),
+ 1);
+ // Compute the cumulative view and projection matrices
+ Mat4f mat = new Mat4f();
+ mat.mul(getProjectionMatrix(), getViewingMatrix());
+ // Compute the inverse of this matrix
+ mat.invert();
+ // Multiply
+ Vec4f unproj = new Vec4f();
+ mat.xformVec(pt3d, unproj);
+ if (unproj.z() == 0) {
+ // FIXME: is this the right exception to throw in this case?
+ throw new SingularMatrixException();
+ }
+ float ooZ = 1.0f / unproj.w();
+ Vec3f to = new Vec3f(unproj.x() * ooZ,
+ unproj.y() * ooZ,
+ unproj.z() * ooZ);
+ // FIXME: for orthographic projections, need to do something
+ // different; can't just use the eye point
+ Vec3f from = getPosition();
+ Vec3f dir = to.minus(from);
+
+ // System.err.println("unprojected point: " + from);
+ // System.err.println("unprojected dir : " + dir);
+
+ line.setPoint(from);
+ line.setDirection(dir);
+ }
+
public void doAction(Action action) {
if (ViewingMatrixElement.isEnabled(action.getState())) {
ViewingMatrixElement.set(action.getState(), getViewingMatrix());
@@ -142,4 +235,9 @@ public abstract class Camera extends Node {
ProjectionMatrixElement.set(action.getState(), getProjectionMatrix());
}
}
+
+ public void rayPick(RayPickAction action) {
+ doAction(action);
+ action.recomputeRay(this);
+ }
}
diff --git a/src/net/java/joglutils/msg/nodes/Coordinate3.java b/src/net/java/joglutils/msg/nodes/Coordinate3.java
index e8e2631..7cae14b 100644
--- a/src/net/java/joglutils/msg/nodes/Coordinate3.java
+++ b/src/net/java/joglutils/msg/nodes/Coordinate3.java
@@ -50,6 +50,8 @@ public class Coordinate3 extends Node {
static {
// Enable the elements this node affects for known actions
GLCoordinateElement.enable(GLRenderAction.getDefaultState());
+
+ CoordinateElement .enable(RayPickAction.getDefaultState());
}
/** Sets the coordinate data in this node. */
diff --git a/src/net/java/joglutils/msg/nodes/Group.java b/src/net/java/joglutils/msg/nodes/Group.java
index f9a961b..df3232d 100644
--- a/src/net/java/joglutils/msg/nodes/Group.java
+++ b/src/net/java/joglutils/msg/nodes/Group.java
@@ -52,7 +52,7 @@ public class Group extends Node {
}
/** Adds a child so that it becomes the one with the given index. */
- public void insertChild(Node child, int index) {
+ public void insertChild(int index, Node child) {
children.add(index, child);
}
@@ -103,7 +103,7 @@ public class Group extends Node {
*/
public void replaceChild(int index, Node newChild) throws IndexOutOfBoundsException {
removeChild(index);
- insertChild(newChild, index);
+ insertChild(index, newChild);
}
/** Replaces the old child with the new child. This is a convenience
diff --git a/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java b/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java
index 5e45367..e244f17 100644
--- a/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java
+++ b/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java
@@ -40,6 +40,7 @@ package net.java.joglutils.msg.nodes;
import java.nio.*;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.misc.*;
/** An IndexedTriangleSet assembles the coordinates specified by a
Coordinate3 node, and any auxiliary nodes such as a
@@ -48,7 +49,7 @@ import net.java.joglutils.msg.actions.*;
(FIXME) rendering support for this node is not yet
implemented.) */
-public class IndexedTriangleSet extends Node {
+public class IndexedTriangleSet extends TriangleBasedShape {
private IntBuffer indices;
/** Sets the indices this node uses to group vertices into triangles. */
@@ -64,4 +65,8 @@ public class IndexedTriangleSet extends Node {
public void doAction(Action action) {
throw new RuntimeException("Not yet implemented");
}
+
+ public void generateTriangles(Action action, TriangleCallback cb) {
+ throw new RuntimeException("Not yet implemented");
+ }
}
diff --git a/src/net/java/joglutils/msg/nodes/Node.java b/src/net/java/joglutils/msg/nodes/Node.java
index e9eefc4..f2ab658 100644
--- a/src/net/java/joglutils/msg/nodes/Node.java
+++ b/src/net/java/joglutils/msg/nodes/Node.java
@@ -51,4 +51,10 @@ public class Node {
not required due to the framework supporting action methods, but
for built-in actions it may make it simpler. */
public void render(GLRenderAction action) { doAction(action); }
+
+ /** Support for the built-in RayPickAction. Note that supplying
+ virtual methods in Node subclasses to support various actions is
+ not required due to the framework supporting action methods, but
+ for built-in actions it may make it simpler. */
+ public void rayPick(RayPickAction action) { doAction(action); }
}
diff --git a/src/net/java/joglutils/msg/nodes/Shape.java b/src/net/java/joglutils/msg/nodes/Shape.java
new file mode 100644
index 0000000..9c88e9e
--- /dev/null
+++ b/src/net/java/joglutils/msg/nodes/Shape.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.nodes;
+
+/** The abstract base class for all shapes in the scene graph. */
+
+public abstract class Shape extends Node {
+}
diff --git a/src/net/java/joglutils/msg/nodes/Texture2.java b/src/net/java/joglutils/msg/nodes/Texture2.java
index fd1b82a..29ed969 100644
--- a/src/net/java/joglutils/msg/nodes/Texture2.java
+++ b/src/net/java/joglutils/msg/nodes/Texture2.java
@@ -58,6 +58,8 @@ public class Texture2 extends Node {
static {
// Enable the elements this node affects for known actions
GLTextureElement.enable(GLRenderAction.getDefaultState());
+
+ TextureElement .enable(RayPickAction.getDefaultState());
}
/** Represents the OpenGL MODULATE texture environment mode. */
@@ -144,4 +146,11 @@ public class Texture2 extends Node {
TextureElement.set(action.getState(), getTexture(), getTexEnvMode());
}
}
+
+ public void rayPick(RayPickAction action) {
+ // FIXME: because of the issue of potentially not having an OpenGL
+ // context at the time this is called, the TextureElement should
+ // be updated to hold a reference to this node, and only the
+ // GLTextureElement should poll the texture
+ }
}
diff --git a/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java b/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java
index f7720d2..2782da1 100644
--- a/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java
+++ b/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java
@@ -50,6 +50,8 @@ public class TextureCoordinate2 extends Node {
static {
// Enable the elements this node affects for known actions
GLTextureCoordinateElement.enable(GLRenderAction.getDefaultState());
+
+ TextureCoordinateElement .enable(RayPickAction.getDefaultState());
}
/** Sets the texture coordinate data in this node. */
diff --git a/src/net/java/joglutils/msg/nodes/Transform.java b/src/net/java/joglutils/msg/nodes/Transform.java
index ad5e1bd..044c1b7 100644
--- a/src/net/java/joglutils/msg/nodes/Transform.java
+++ b/src/net/java/joglutils/msg/nodes/Transform.java
@@ -49,9 +49,13 @@ public class Transform extends Node {
static {
// Enable the elements this node affects for known actions
// Note that all of these elements are interdependent
- GLModelMatrixElement .enable(GLRenderAction.getDefaultState());
- GLProjectionMatrixElement .enable(GLRenderAction.getDefaultState());
- GLViewingMatrixElement .enable(GLRenderAction.getDefaultState());
+ GLModelMatrixElement .enable(GLRenderAction.getDefaultState());
+ GLProjectionMatrixElement.enable(GLRenderAction.getDefaultState());
+ GLViewingMatrixElement .enable(GLRenderAction.getDefaultState());
+
+ ModelMatrixElement .enable(RayPickAction.getDefaultState());
+ ProjectionMatrixElement.enable(RayPickAction.getDefaultState());
+ ViewingMatrixElement .enable(RayPickAction.getDefaultState());
}
public Transform() {
diff --git a/src/net/java/joglutils/msg/nodes/TriangleBasedShape.java b/src/net/java/joglutils/msg/nodes/TriangleBasedShape.java
new file mode 100644
index 0000000..c234695
--- /dev/null
+++ b/src/net/java/joglutils/msg/nodes/TriangleBasedShape.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ */
+
+package net.java.joglutils.msg.nodes;
+
+import java.util.*;
+
+import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
+import net.java.joglutils.msg.impl.*;
+import net.java.joglutils.msg.math.*;
+import net.java.joglutils.msg.misc.*;
+
+/** The abstract base class for all shapes in the scene graph which
+ render themselves as a collection of triangles. */
+
+public abstract class TriangleBasedShape extends Shape {
+ /** Based on the state in the given Action, calls the specified
+ triangle callback for each triangle in the shape. Coordinates
+ are specified in the local coordinate system of this shape; the
+ caller must transform them into the world coordinate system if
+ necessary. */
+ public abstract void generateTriangles(Action action,
+ TriangleCallback cb);
+
+ public void rayPick(final RayPickAction action) {
+ // The RayPickAction holds the picking ray in world coordinates.
+ // Transform this ray into local coordinates to do intersection testing
+ // Fetch the current local-to-world matrix
+ Mat4f mat = new Mat4f(ModelMatrixElement.getInstance(action.getState()).getMatrix());
+ // Invert it to get the world-to-local matrix
+ mat.invert();
+ // Transform the RayPickAction's ray by this matrix
+ final Line ray = mat.xformLine(action.getComputedRay());
+
+ // Temporaries
+ final RayTriangleIntersection rti = new RayTriangleIntersection();
+ final Vec3f tuv = new Vec3f();
+
+ // OK, ready to test
+ generateTriangles(action, new TriangleCallback() {
+ public void triangleCB(int triangleIndex,
+ PrimitiveVertex v0,
+ int i0,
+ PrimitiveVertex v1,
+ int i1,
+ PrimitiveVertex v2,
+ int i2) {
+ if (rti.intersectTriangle(ray,
+ v0.getCoord(),
+ v1.getCoord(),
+ v2.getCoord(),
+ tuv)) {
+ // Compute at least the 3D coordinate of the intersection
+ // point for now
+ // FIXME: need to compute other things such as the texture
+ // coordinates
+ PickedPoint p = new PickedPoint();
+ // Compute weights of three vertices
+ float a = 1.0f - tuv.y() - tuv.z();
+ float b = tuv.y();
+ float c = tuv.z();
+ Vec3f loc = v0.getCoord().times(a).plus(v1.getCoord().times(b)).plus(v2.getCoord().times(c));
+ p.setCoord(loc);
+ p.setPath(action.getPath().copy());
+ action.addPickedPoint(p, tuv.x());
+ }
+ }
+ });
+ }
+}
diff --git a/src/net/java/joglutils/msg/nodes/TriangleSet.java b/src/net/java/joglutils/msg/nodes/TriangleSet.java
index 0692738..8f708cb 100644
--- a/src/net/java/joglutils/msg/nodes/TriangleSet.java
+++ b/src/net/java/joglutils/msg/nodes/TriangleSet.java
@@ -37,6 +37,9 @@
package net.java.joglutils.msg.nodes;
+import java.nio.*;
+import java.util.*;
+
import javax.media.opengl.*;
import com.sun.opengl.util.texture.*;
@@ -49,7 +52,7 @@ import net.java.joglutils.msg.misc.*;
node, and any auxiliary nodes such as a TextureCoordinate2 node,
into a set of triangles. */
-public class TriangleSet extends Node {
+public class TriangleSet extends TriangleBasedShape {
private int numTriangles;
/** Sets the number of triangles this TriangleSet references. */
@@ -110,6 +113,102 @@ public class TriangleSet extends Node {
}
}
+ public void generateTriangles(Action action, TriangleCallback cb) {
+ State state = action.getState();
+ FloatBuffer coords = null;
+ FloatBuffer texCoords = null;
+ // FIXME: normals and lighting not supported yet
+ // FloatBuffer normals = null;
+ FloatBuffer colors = null;
+ if (CoordinateElement.isEnabled(state)) {
+ coords = CoordinateElement.get(state);
+ }
+ // No point in continuing if we don't have coordinates
+ if (coords == null)
+ return;
+ if (TextureCoordinateElement.isEnabled(state)) {
+ texCoords = TextureCoordinateElement.get(state);
+ }
+ // if (NormalElement.isEnabled(state)) {
+ // texCoords = NormalElement.get(state);
+ // }
+ if (ColorElement.isEnabled(state)) {
+ colors = ColorElement.get(state);
+ }
+ PrimitiveVertex v0 = new PrimitiveVertex();
+ PrimitiveVertex v1 = new PrimitiveVertex();
+ PrimitiveVertex v2 = new PrimitiveVertex();
+ v0.setCoord(new Vec3f());
+ v1.setCoord(new Vec3f());
+ v2.setCoord(new Vec3f());
+ if (texCoords != null) {
+ v0.setTexCoord(new Vec2f());
+ v1.setTexCoord(new Vec2f());
+ v2.setTexCoord(new Vec2f());
+ }
+ if (colors != null) {
+ v0.setColor(new Vec4f());
+ v1.setColor(new Vec4f());
+ v2.setColor(new Vec4f());
+ }
+
+ int coordIdx = 0;
+ for (int i = 0; i < numTriangles; i++) {
+ // Vertex 0
+ v0.getCoord().set(coords.get(3 * coordIdx + 0),
+ coords.get(3 * coordIdx + 1),
+ coords.get(3 * coordIdx + 2));
+ if (texCoords != null) {
+ v0.getTexCoord().set(texCoords.get(2 * coordIdx + 0),
+ texCoords.get(2 * coordIdx + 1));
+ }
+ if (colors != null) {
+ v0.getColor().set(colors.get(4 * coordIdx + 0),
+ colors.get(4 * coordIdx + 1),
+ colors.get(4 * coordIdx + 2),
+ colors.get(4 * coordIdx + 3));
+ }
+
+ // Vertex 1
+ v1.getCoord().set(coords.get(3 * (coordIdx + 1) + 0),
+ coords.get(3 * (coordIdx + 1) + 1),
+ coords.get(3 * (coordIdx + 1) + 2));
+ if (texCoords != null) {
+ v1.getTexCoord().set(texCoords.get(2 * (coordIdx + 1) + 0),
+ texCoords.get(2 * (coordIdx + 1) + 1));
+ }
+ if (colors != null) {
+ v1.getColor().set(colors.get(4 * (coordIdx + 1) + 0),
+ colors.get(4 * (coordIdx + 1) + 1),
+ colors.get(4 * (coordIdx + 1) + 2),
+ colors.get(4 * (coordIdx + 1) + 3));
+ }
+
+ // Vertex 2
+ v2.getCoord().set(coords.get(3 * (coordIdx + 2) + 0),
+ coords.get(3 * (coordIdx + 2) + 1),
+ coords.get(3 * (coordIdx + 2) + 2));
+ if (texCoords != null) {
+ v2.getTexCoord().set(texCoords.get(2 * (coordIdx + 2) + 0),
+ texCoords.get(2 * (coordIdx + 2) + 1));
+ }
+ if (colors != null) {
+ v2.getColor().set(colors.get(4 * (coordIdx + 2) + 0),
+ colors.get(4 * (coordIdx + 2) + 1),
+ colors.get(4 * (coordIdx + 2) + 2),
+ colors.get(4 * (coordIdx + 2) + 3));
+ }
+
+ // Call callback
+ cb.triangleCB(i,
+ v0, 3 * i + 0,
+ v1, 3 * i + 1,
+ v2, 3 * i + 2);
+
+ coordIdx += 3;
+ }
+ }
+
// Helper routine for setting up a texture matrix to allow texture
// coords in the scene graph to always be specified from (0..1)
private Mat4f textureMatrix = new Mat4f();
diff --git a/src/net/java/joglutils/msg/test/DisplayShelf.java b/src/net/java/joglutils/msg/test/DisplayShelf.java
index 73a63de..c6ae2b7 100644
--- a/src/net/java/joglutils/msg/test/DisplayShelf.java
+++ b/src/net/java/joglutils/msg/test/DisplayShelf.java
@@ -73,6 +73,7 @@ public class DisplayShelf extends Container {
static class TitleGraph {
String url;
+ Separator sep = new Separator();
Transform xform = new Transform();
Texture2 texture = new Texture2();
Coordinate3 coords = new Coordinate3();
@@ -83,9 +84,11 @@ public class DisplayShelf extends Container {
}
private Group root;
+ private Separator imageRoot;
private String[] images;
private List<TitleGraph> titles = new ArrayList<TitleGraph>();
private int targetIndex;
+ private JSlider slider;
// This encodes both the current position and the animation alpha
private float currentIndex;
// If the difference between the current index and target index is >
@@ -130,7 +133,7 @@ public class DisplayShelf extends Container {
final List<TitleGraph> queuedGraphs = new ArrayList<TitleGraph>();
queuedGraphs.addAll(titles);
- new Thread(new Runnable() {
+ Thread loaderThread = new Thread(new Runnable() {
public void run() {
while (queuedGraphs.size() > 0) {
TitleGraph graph = queuedGraphs.remove(0);
@@ -152,7 +155,10 @@ public class DisplayShelf extends Container {
}
}
}
- }).start();
+ });
+ // Avoid having the loader thread preempt the rendering thread
+ loaderThread.setPriority(Thread.MIN_PRIORITY + 1);
+ loaderThread.start();
}
private void setTargetIndex(int index) {
@@ -219,8 +225,9 @@ public class DisplayShelf extends Container {
camera.setFarDistance(20.0f);
canvas = new GLCanvas();
canvas.addGLEventListener(new Listener());
+ canvas.addMouseListener(new MListener());
add(canvas, BorderLayout.CENTER);
- final JSlider slider = new JSlider(0, images.length - 1, 0);
+ slider = new JSlider(0, images.length - 1, 0);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
setTargetIndex(slider.getValue());
@@ -239,7 +246,7 @@ public class DisplayShelf extends Container {
root.removeAllChildren();
// The images
- Separator imageRoot = new Separator();
+ imageRoot = new Separator();
// The mirrored images, under the floor
Separator mirrorRoot = new Separator();
@@ -274,7 +281,7 @@ public class DisplayShelf extends Container {
titles.add(graph);
computeCoords(graph.coords, DEFAULT_ASPECT_RATIO);
graph.xform.getTransform().setTranslation(new Vec3f(i, 0, 0));
- Separator sep = new Separator();
+ Separator sep = graph.sep;
sep.addChild(graph.xform);
sep.addChild(graph.coords);
sep.addChild(graph.texture);
@@ -375,6 +382,27 @@ public class DisplayShelf extends Container {
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
}
+ class MListener extends MouseAdapter {
+ RayPickAction ra = new RayPickAction();
+
+ public void mousePressed(MouseEvent e) {
+ ra.setPoint(e.getX(), e.getY(), e.getComponent());
+ // Apply to the scene root
+ ra.apply(root);
+ List<PickedPoint> pickedPoints = ra.getPickedPoints();
+ Path p = null;
+ if (!pickedPoints.isEmpty())
+ p = pickedPoints.get(0).getPath();
+ if (p != null && p.size() > 1) {
+ int idx = imageRoot.findChild(p.get(p.size() - 2));
+ if (idx >= 0) {
+ // Need to keep the slider and this mechanism in sync
+ slider.setValue(idx);
+ }
+ }
+ }
+ }
+
public static void main(String[] args) {
Frame f = new Frame("Display Shelf test");
f.setLayout(new BorderLayout());
@@ -390,33 +418,58 @@ public class DisplayShelf extends Container {
// The images to configure the shelf with
String[] images = {
- "http://a1.phobos.apple.com/r10/Music/05/7d/c3/dj.umbuvrfe.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/cb/9a/b3/mzi.krksguze.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/94/8d/83/dj.jionwnuf.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/26/43/02/dj.dgnjindw.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/69/2a/63/mzi.wpfmtfzp.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/17/e1/88/dj.gcajwhco.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/21/f6/32/dj.glzycglj.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/d1/6b/3b/mzi.pajmxsmk.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/f6/a7/b2/dj.lamcsbwx.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/84/a5/4f/dj.nqvsikaq.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/7d/c3/23/dj.elyzoipc.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/80/a5/8c/dj.oidpsvzg.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/d1/b2/cf/dj.moyzjiht.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/49/a3/59/mzi.ssjpuxwt.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/9b/8f/7c/dj.qizpbris.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/b1/4f/c8/dj.uadqyjbr.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/d4/31/df/mzi.pqzeferc.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/4b/88/a7/dj.jhotijvb.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/a8/a9/36/dj.asztraij.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/d6/6b/c4/mzi.dricykdh.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Features/d4/81/a3/dj.tpysowpf.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/4f/2c/a6/dj.cawuddxy.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/d8/9c/8a/mzi.vmajyyha.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/00/5c/31/mzi.tuyoxwib.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/da/c8/e2/mzi.sanzeosx.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/43/cc/0e/dj.zfqfgoas.200x200-75.jpg",
- "http://a1.phobos.apple.com/r10/Music/73/70/13/mzi.uswlslxx.200x200-75.jpg"
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.jsepedzf.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.wvbmknhn.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.oorrjicu.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.woofnkar.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.tapbaxpy.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.awlngumx.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.bpuzrjch.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.nqarjlzt.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.hgadlawz.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.sdfnrwzj.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.vtbicehh.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.lhgtckcs.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.tbwyqyqm.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.eimndamh.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.nxvdfcwt.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.njoydoqk.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.ikfbfqzh.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.niqwioqm.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.tqqldmqe.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.ynokefwv.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.jodjmgxs.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.yhdaeino.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.xmgrrxef.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.pahnmknr.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.sbkwhrik.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.hwbcjnfx.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.umbuvrfe.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.krksguze.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.jionwnuf.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.dgnjindw.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.wpfmtfzp.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.gcajwhco.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.glzycglj.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.pajmxsmk.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.lamcsbwx.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.nqvsikaq.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.elyzoipc.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.oidpsvzg.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.moyzjiht.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.qizpbris.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.uadqyjbr.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.pqzeferc.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.jhotijvb.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.asztraij.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.dricykdh.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.tpysowpf.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.cawuddxy.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.vmajyyha.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.tuyoxwib.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.sanzeosx.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/dj.zfqfgoas.200x200-75.jpg",
+ "http://download.java.net/media/jogl/builds/ds_tmp/mzi.uswlslxx.200x200-75.jpg"
};
Separator root = new Separator();