summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/net/java/joglutils/msg/actions/Action.java58
-rw-r--r--src/net/java/joglutils/msg/actions/GLRenderAction.java153
-rw-r--r--src/net/java/joglutils/msg/elements/BlendElement.java5
-rw-r--r--src/net/java/joglutils/msg/elements/ColorElement.java5
-rw-r--r--src/net/java/joglutils/msg/elements/CoordinateElement.java8
-rw-r--r--src/net/java/joglutils/msg/elements/ModelMatrixElement.java8
-rw-r--r--src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java8
-rw-r--r--src/net/java/joglutils/msg/elements/TextureCoordinateElement.java8
-rw-r--r--src/net/java/joglutils/msg/elements/TextureElement.java8
-rw-r--r--src/net/java/joglutils/msg/elements/ViewingMatrixElement.java8
-rw-r--r--src/net/java/joglutils/msg/misc/State.java8
-rw-r--r--src/net/java/joglutils/msg/nodes/Blend.java15
-rw-r--r--src/net/java/joglutils/msg/nodes/Camera.java19
-rw-r--r--src/net/java/joglutils/msg/nodes/Color4.java10
-rw-r--r--src/net/java/joglutils/msg/nodes/Coordinate3.java10
-rw-r--r--src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java2
-rw-r--r--src/net/java/joglutils/msg/nodes/Node.java14
-rw-r--r--src/net/java/joglutils/msg/nodes/PerspectiveCamera.java8
-rw-r--r--src/net/java/joglutils/msg/nodes/Separator.java11
-rw-r--r--src/net/java/joglutils/msg/nodes/Texture2.java10
-rw-r--r--src/net/java/joglutils/msg/nodes/TextureCoordinate2.java10
-rw-r--r--src/net/java/joglutils/msg/nodes/Transform.java13
-rw-r--r--src/net/java/joglutils/msg/nodes/TriangleSet.java70
23 files changed, 305 insertions, 164 deletions
diff --git a/src/net/java/joglutils/msg/actions/Action.java b/src/net/java/joglutils/msg/actions/Action.java
index 21ca2bc..34f14ea 100644
--- a/src/net/java/joglutils/msg/actions/Action.java
+++ b/src/net/java/joglutils/msg/actions/Action.java
@@ -37,47 +37,51 @@
package net.java.joglutils.msg.actions;
+import java.lang.reflect.*;
+
import net.java.joglutils.msg.misc.*;
import net.java.joglutils.msg.nodes.*;
/** The base class of all actions, which are applied to nodes in the
scene graph to implement operations such as rendering. <P>
- Subclasses of Action should define, by convention, a public static
- method <CODE>getDefaultState</CODE>, returning a {@link
- net.java.joglutils.msg.misc.State State} object, which is used to
- enable the elements in the state which should be updated by the
- action's traversal of nodes. Each Action instance maintains a
- State object internally which is initialized from this
- default. Note that different actions may enable different elements
- of the global state.
+ Subclasses of Action should define, by convention, a method <BR>
+ <PRE> public static State getDefaultState()</PRE>
+ returning a {@link net.java.joglutils.msg.misc.State State}
+ object, which is used to enable the elements in the state which
+ should be updated by the action's traversal of nodes. Each Action
+ instance maintains a State object internally which is initialized
+ from this default. Note that different actions may enable
+ different elements of the global state. <P>
+
+ Subclasses of Action should also define, by convention, a method <BR>
+ <PRE> public static void addActionMethod(Class&lt;? extends Node&gt; nodeType, Method m)</PRE>
+ which is used to add action methods to the particular Action
+ class. This may be used by developers to attach new functionality
+ to the Action for new node types they define.
*/
public abstract class Action {
-
/** Applies this Action to a particular node. This is how operations
such as rendering are initiated. */
- public void apply(Node node) {
- node.doAction(this);
- }
+ public abstract void apply(Node node);
/** Returns the global state this action encompasses, which is
altered by the nodes the action traverses. */
public abstract State getState();
- // Visitor methods, one per node class
-
- // FIXME: should rethink this mechanism and make it extensible as
- // per the original Open Inventor
- public abstract void visit (Blend blend);
- public abstract void visit (Color4 colors);
- public abstract void visit (Coordinate3 coords);
- public abstract void visit (IndexedTriangleSet tris);
- public abstract void visit (PerspectiveCamera camera);
- public abstract void visitPre (Separator sep);
- public abstract void visitPost(Separator sep);
- public abstract void visit (Texture2 texture);
- public abstract void visit (TextureCoordinate2 texCoords);
- public abstract void visit (Transform transform);
- public abstract void visit (TriangleSet tris);
+ private Object[] argTmp = new Object[2];
+ /** Invokes the appropriate action method for the given Node. */
+ protected void apply(ActionTable table, Node node) {
+ try {
+ Method m = table.lookupActionMethod(node);
+ if (m != null) {
+ argTmp[0] = this;
+ argTmp[1] = node;
+ m.invoke(null, argTmp);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/src/net/java/joglutils/msg/actions/GLRenderAction.java b/src/net/java/joglutils/msg/actions/GLRenderAction.java
index 2274af1..7b2fb56 100644
--- a/src/net/java/joglutils/msg/actions/GLRenderAction.java
+++ b/src/net/java/joglutils/msg/actions/GLRenderAction.java
@@ -37,12 +37,12 @@
package net.java.joglutils.msg.actions;
+import java.lang.reflect.*;
+
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
-import com.sun.opengl.util.texture.*;
import net.java.joglutils.msg.elements.*;
-import net.java.joglutils.msg.math.*;
import net.java.joglutils.msg.misc.*;
import net.java.joglutils.msg.nodes.*;
@@ -64,6 +64,14 @@ public class GLRenderAction extends Action {
public static State getDefaultState() {
return defaults;
}
+ private static ActionTable table = new ActionTable(GLRenderAction.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() {
@@ -71,34 +79,31 @@ public class GLRenderAction extends Action {
}
static {
- // FIXME: may need to rethink when and where these elements are enabled
-
- // In Open Inventor, this is folded into the node's initialization
- // (i.e., the node needs to know which elements it might affect).
- // That in theory allows for fewer elements to be enabled, but it
- // isn't clear that this makes a difference, or that it results in
- // correct code elsewhere where certain elements implicitly expect
- // others to be enabled.
- GLBlendElement .enable(getDefaultState());
- GLColorElement .enable(getDefaultState());
- GLCoordinateElement .enable(getDefaultState());
- GLModelMatrixElement .enable(getDefaultState());
- GLProjectionMatrixElement .enable(getDefaultState());
- GLViewingMatrixElement .enable(getDefaultState());
- GLTextureCoordinateElement.enable(getDefaultState());
- GLTextureElement .enable(getDefaultState());
+ // 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, GLRenderAction.class.getMethod("render", GLRenderAction.class, Node.class));
+ } catch (Exception e) {
+ throw new RuntimeException("Error initializing action method for GLRenderAction class", e);
+ }
}
// For automatically setting the aspect ratios of cameras we encounter
private float curAspectRatio = 1.0f;
private int applyDepth = 0;
+ private GL gl;
public void apply(Node node) {
- GL gl = GLU.getCurrentGL();
int depth = applyDepth++;
try {
if (depth == 0) {
+ gl = GLU.getCurrentGL();
// Applying to the root of the scene graph
// Push necessary GL state
// FIXME: add in additional bits as we add more capabilities
@@ -115,116 +120,30 @@ public class GLRenderAction extends Action {
gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
curAspectRatio = (float) viewport[2] / (float) viewport[3];
}
- super.apply(node);
+ apply(table, node);
} finally {
if (depth == 0) {
gl.glPopClientAttrib();
gl.glPopAttrib();
+ gl = null;
}
--applyDepth;
}
}
- public void visit(Blend blend) {
- GLBlendElement.set(state,
- blend.getEnabled(),
- blend.getBlendColor(),
- blend.getSourceFunc(),
- blend.getDestFunc(),
- blend.getBlendEquation());
- }
-
- public void visit(Color4 colors) {
- GLColorElement.set(state, colors.getData().getData());
- }
-
- public void visit(Coordinate3 coords) {
- GLCoordinateElement.set(state, coords.getData().getData());
- }
-
- public void visit(IndexedTriangleSet tris) {
- throw new RuntimeException("Not yet implemented");
- }
-
- public void visit(PerspectiveCamera camera) {
- // FIXME: unclear whether we should be doing this, or whether we
- // should have a mechanism which doesn't require mutation of the
- // camera
- camera.setAspectRatio(curAspectRatio);
-
- GLViewingMatrixElement.set(state, camera.getViewingMatrix());
- GLProjectionMatrixElement.set(state, camera.getProjectionMatrix());
- }
-
- public void visitPre(Separator sep) {
- state.push();
- }
-
- public void visitPost(Separator sep) {
- state.pop();
+ /** Returns the GL instance being used for rendering. */
+ public GL getGL() {
+ return gl;
}
- public void visit(Texture2 texture) {
- GLTextureElement.set(state, texture.getTexture(), texture.getTexEnvMode());
- }
-
- public void visit(TextureCoordinate2 texCoords) {
- GLTextureCoordinateElement.set(state, texCoords.getData().getData());
- }
-
- public void visit(Transform transform) {
- GLModelMatrixElement.mult(state, transform.getTransform());
- }
-
- public void visit(TriangleSet tris) {
- if (CoordinateElement.get(state) != null) {
- // OK, we have coordinates to send down, at least
-
- GL gl = GLU.getCurrentGL();
-
- Texture tex = GLTextureElement.get(state);
- boolean haveTexCoords = (GLTextureCoordinateElement.get(state) != null);
-
- if (tex != null) {
- // Set up the texture matrix to uniformly map [0..1] to the used
- // portion of the texture image
- gl.glMatrixMode(GL.GL_TEXTURE);
- gl.glPushMatrix();
- gl.glLoadTransposeMatrixf(getTextureMatrix(tex).getRowMajorData(), 0);
- gl.glMatrixMode(GL.GL_MODELVIEW);
- } else if (haveTexCoords) {
- // Want to turn off the use of texture coordinates to avoid errors
- // FIXME: not 100% sure whether we need to do this, but think we should
- gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
- }
-
- // For now, assume the triangle set and the number of available
- // coordinates match -- may want to add debugging information
- // for this later
- gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3 * tris.getNumTriangles());
-
- if (tex != null) {
- gl.glMatrixMode(GL.GL_TEXTURE);
- gl.glPopMatrix();
- gl.glMatrixMode(GL.GL_MODELVIEW);
- } else if (haveTexCoords) {
- // Might want this the next time we render a shape
- gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
- }
- }
+ /** Fetches the current aspect ratio of the viewport this
+ GLRenderAction is rendering into. */
+ public float getCurAspectRatio() {
+ return curAspectRatio;
}
- private Mat4f textureMatrix = new Mat4f();
- private Mat4f getTextureMatrix(Texture texture) {
- textureMatrix.makeIdent();
- TextureCoords coords = texture.getImageTexCoords();
- // Horizontal scale
- textureMatrix.set(0, 0, coords.right() - coords.left());
- // Vertical scale (may be negative if texture needs to be flipped vertically)
- float vertScale = coords.top() - coords.bottom();
- textureMatrix.set(1, 1, vertScale);
- textureMatrix.set(0, 3, coords.left());
- textureMatrix.set(1, 3, coords.bottom());
- return textureMatrix;
+ /** Action method which dispatches to per-node rendering functionality. */
+ public static void render(GLRenderAction action, Node node) {
+ node.render(action);
}
}
diff --git a/src/net/java/joglutils/msg/elements/BlendElement.java b/src/net/java/joglutils/msg/elements/BlendElement.java
index 2a0d488..422811f 100644
--- a/src/net/java/joglutils/msg/elements/BlendElement.java
+++ b/src/net/java/joglutils/msg/elements/BlendElement.java
@@ -63,6 +63,11 @@ public class BlendElement extends Element {
BlendElement tmp = new BlendElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// These defaults match those in the Blend node -- is there a better way of factoring them out?
diff --git a/src/net/java/joglutils/msg/elements/ColorElement.java b/src/net/java/joglutils/msg/elements/ColorElement.java
index a725d61..a3a92d4 100644
--- a/src/net/java/joglutils/msg/elements/ColorElement.java
+++ b/src/net/java/joglutils/msg/elements/ColorElement.java
@@ -62,6 +62,11 @@ public class ColorElement extends Element {
ColorElement tmp = new ColorElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The actual color data
protected FloatBuffer colors;
diff --git a/src/net/java/joglutils/msg/elements/CoordinateElement.java b/src/net/java/joglutils/msg/elements/CoordinateElement.java
index 34b16bc..58a57c7 100644
--- a/src/net/java/joglutils/msg/elements/CoordinateElement.java
+++ b/src/net/java/joglutils/msg/elements/CoordinateElement.java
@@ -52,13 +52,21 @@ public class CoordinateElement extends Element {
public Element newInstance() {
return new CoordinateElement();
}
+ /** Returns the instance of this element in the passed State. */
public static CoordinateElement getInstance(State state) {
return (CoordinateElement) state.getElement(index);
}
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
public static void enable(State defaultState) {
CoordinateElement tmp = new CoordinateElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The actual coordinate data
protected FloatBuffer coords;
diff --git a/src/net/java/joglutils/msg/elements/ModelMatrixElement.java b/src/net/java/joglutils/msg/elements/ModelMatrixElement.java
index cfe726e..e4cdbb0 100644
--- a/src/net/java/joglutils/msg/elements/ModelMatrixElement.java
+++ b/src/net/java/joglutils/msg/elements/ModelMatrixElement.java
@@ -50,13 +50,21 @@ public class ModelMatrixElement extends Element {
public Element newInstance() {
return new ModelMatrixElement();
}
+ /** Returns the instance of this element in the passed State. */
public static ModelMatrixElement getInstance(State state) {
return (ModelMatrixElement) state.getElement(index);
}
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
public static void enable(State defaultState) {
Element tmp = new ModelMatrixElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The matrix data
protected Mat4f matrix;
diff --git a/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java b/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java
index dd70ca3..4635a83 100644
--- a/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java
+++ b/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java
@@ -50,13 +50,21 @@ public class ProjectionMatrixElement extends Element {
public Element newInstance() {
return new ProjectionMatrixElement();
}
+ /** Returns the instance of this element in the passed State. */
public static ProjectionMatrixElement getInstance(State state) {
return (ProjectionMatrixElement) state.getElement(index);
}
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
public static void enable(State defaultState) {
Element tmp = new ProjectionMatrixElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The matrix data
protected Mat4f matrix;
diff --git a/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java b/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java
index 6d36c6c..8d24bfc 100644
--- a/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java
+++ b/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java
@@ -52,13 +52,21 @@ public class TextureCoordinateElement extends Element {
public Element newInstance() {
return new TextureCoordinateElement();
}
+ /** Returns the instance of this element in the passed State. */
public static TextureCoordinateElement getInstance(State state) {
return (TextureCoordinateElement) state.getElement(index);
}
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
public static void enable(State defaultState) {
TextureCoordinateElement tmp = new TextureCoordinateElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The actual coordinate data
protected FloatBuffer coords;
diff --git a/src/net/java/joglutils/msg/elements/TextureElement.java b/src/net/java/joglutils/msg/elements/TextureElement.java
index 90a9ebc..199a113 100644
--- a/src/net/java/joglutils/msg/elements/TextureElement.java
+++ b/src/net/java/joglutils/msg/elements/TextureElement.java
@@ -57,13 +57,21 @@ public class TextureElement extends Element {
public Element newInstance() {
return new TextureElement();
}
+ /** Returns the instance of this element in the passed State. */
public static TextureElement getInstance(State state) {
return (TextureElement) state.getElement(index);
}
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
public static void enable(State defaultState) {
TextureElement tmp = new TextureElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The actual Texture object
protected Texture texture;
diff --git a/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java b/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java
index 5142678..b561bd8 100644
--- a/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java
+++ b/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java
@@ -50,13 +50,21 @@ public class ViewingMatrixElement extends Element {
public Element newInstance() {
return new ViewingMatrixElement();
}
+ /** Returns the instance of this element in the passed State. */
public static ViewingMatrixElement getInstance(State state) {
return (ViewingMatrixElement) state.getElement(index);
}
+ /** Enables this element in the passed state, which should be the
+ default for a given action. */
public static void enable(State defaultState) {
Element tmp = new ViewingMatrixElement();
defaultState.setElement(tmp.getStateIndex(), tmp);
}
+ /** Indicates whether this element is enabled in the given default
+ state for a particular action. */
+ public static boolean isEnabled(State state) {
+ return (state.getDefaults().getElement(index) != null);
+ }
// The matrix data
protected Mat4f matrix;
diff --git a/src/net/java/joglutils/msg/misc/State.java b/src/net/java/joglutils/msg/misc/State.java
index c718f71..b0279b7 100644
--- a/src/net/java/joglutils/msg/misc/State.java
+++ b/src/net/java/joglutils/msg/misc/State.java
@@ -87,6 +87,14 @@ public class State {
push();
}
+ /** Returns the default State, or this State if it corresponds to
+ the defaults for a given Action subclass. */
+ public State getDefaults() {
+ if (defaults != null)
+ return defaults;
+ return this;
+ }
+
/** Gets the state element at the given index. */
public Element getElement(StateIndex index) {
// The comments in the Open Inventor implementation indicate that
diff --git a/src/net/java/joglutils/msg/nodes/Blend.java b/src/net/java/joglutils/msg/nodes/Blend.java
index 18cd5a6..af95e00 100644
--- a/src/net/java/joglutils/msg/nodes/Blend.java
+++ b/src/net/java/joglutils/msg/nodes/Blend.java
@@ -38,6 +38,7 @@
package net.java.joglutils.msg.nodes;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
import net.java.joglutils.msg.math.*;
/** Provides control over OpenGL blending modes. */
@@ -49,6 +50,11 @@ public class Blend extends Node {
private int destFunc = ZERO;
private int blendEquation = FUNC_ADD;
+ static {
+ // Enable the elements this node affects for known actions
+ GLBlendElement.enable(GLRenderAction.getDefaultState());
+ }
+
/** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */
public static final int ZERO = 1;
/** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */
@@ -163,6 +169,13 @@ public class Blend extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ if (BlendElement.isEnabled(action.getState())) {
+ BlendElement.set(action.getState(),
+ getEnabled(),
+ getBlendColor(),
+ getSourceFunc(),
+ getDestFunc(),
+ getBlendEquation());
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/Camera.java b/src/net/java/joglutils/msg/nodes/Camera.java
index 9d1f965..5d405fe 100644
--- a/src/net/java/joglutils/msg/nodes/Camera.java
+++ b/src/net/java/joglutils/msg/nodes/Camera.java
@@ -37,6 +37,8 @@
package net.java.joglutils.msg.nodes;
+import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
import net.java.joglutils.msg.math.*;
/** Represents a camera which is used to view the scene. The camera
@@ -62,6 +64,14 @@ public abstract class Camera extends Node {
protected Mat4f projMatrix;
protected Mat4f viewMatrix;
+ 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());
+ }
+
public Camera() {
position = new Vec3f(0, 0, 1);
orientation = new Rotf();
@@ -123,4 +133,13 @@ public abstract class Camera extends Node {
/** Returns the projection matrix associated with this camera's parameters. */
public abstract Mat4f getProjectionMatrix();
+
+ public void doAction(Action action) {
+ if (ViewingMatrixElement.isEnabled(action.getState())) {
+ ViewingMatrixElement.set(action.getState(), getViewingMatrix());
+ }
+ if (ProjectionMatrixElement.isEnabled(action.getState())) {
+ ProjectionMatrixElement.set(action.getState(), getProjectionMatrix());
+ }
+ }
}
diff --git a/src/net/java/joglutils/msg/nodes/Color4.java b/src/net/java/joglutils/msg/nodes/Color4.java
index d6568e3..8d6696f 100644
--- a/src/net/java/joglutils/msg/nodes/Color4.java
+++ b/src/net/java/joglutils/msg/nodes/Color4.java
@@ -38,6 +38,7 @@
package net.java.joglutils.msg.nodes;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
import net.java.joglutils.msg.collections.*;
/** Represents a set of 4-valued colors which are applied on a
@@ -55,6 +56,11 @@ import net.java.joglutils.msg.collections.*;
public class Color4 extends Node {
private Vec4fCollection data;
+ static {
+ // Enable the elements this node affects for known actions
+ GLColorElement.enable(GLRenderAction.getDefaultState());
+ }
+
// private int colorBinding = AMBIENT_AND_DIFFUSE;
/******
@@ -90,6 +96,8 @@ public class Color4 extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ if (ColorElement.isEnabled(action.getState())) {
+ ColorElement.set(action.getState(), getData().getData());
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/Coordinate3.java b/src/net/java/joglutils/msg/nodes/Coordinate3.java
index 4e2b94b..e8e2631 100644
--- a/src/net/java/joglutils/msg/nodes/Coordinate3.java
+++ b/src/net/java/joglutils/msg/nodes/Coordinate3.java
@@ -38,6 +38,7 @@
package net.java.joglutils.msg.nodes;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
import net.java.joglutils.msg.collections.*;
/** Represents a set of 3-dimensional vertices which can be assembled
@@ -46,6 +47,11 @@ import net.java.joglutils.msg.collections.*;
public class Coordinate3 extends Node {
private Vec3fCollection data;
+ static {
+ // Enable the elements this node affects for known actions
+ GLCoordinateElement.enable(GLRenderAction.getDefaultState());
+ }
+
/** Sets the coordinate data in this node. */
public void setData(Vec3fCollection data) {
this.data = data;
@@ -57,6 +63,8 @@ public class Coordinate3 extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ if (CoordinateElement.isEnabled(action.getState())) {
+ CoordinateElement.set(action.getState(), getData().getData());
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java b/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java
index d2932c8..5e45367 100644
--- a/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java
+++ b/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java
@@ -62,6 +62,6 @@ public class IndexedTriangleSet extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ 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 6fc4eb9..e9eefc4 100644
--- a/src/net/java/joglutils/msg/nodes/Node.java
+++ b/src/net/java/joglutils/msg/nodes/Node.java
@@ -42,11 +42,13 @@ import net.java.joglutils.msg.actions.*;
/** The base class for all nodes in the scene graph. */
public class Node {
+ /** Performs the "typical" operation for this node when an action is
+ applied to it. The default implementation does nothing. */
+ public void doAction(Action action) {}
- /** This is an internal API not intended for public use. To apply an
- action to the scene graph or a portion of the scene graph, use
- {@link net.java.joglutils.msg.actions.Action#apply
- Action.apply}. */
- public void doAction(Action action) {
- }
+ /** Support for the built-in GLRenderAction. 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 render(GLRenderAction action) { doAction(action); }
}
diff --git a/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java b/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java
index b72507a..50c646b 100644
--- a/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java
+++ b/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java
@@ -91,7 +91,11 @@ public class PerspectiveCamera extends Camera {
return vertFOVScale * DEFAULT_HEIGHT_ANGLE;
}
- public void doAction(Action action) {
- action.visit(this);
+ public void render(GLRenderAction action) {
+ // FIXME: unclear whether we should be doing this, or whether we
+ // should have a mechanism which doesn't require mutation of the
+ // camera
+ setAspectRatio(action.getCurAspectRatio());
+ doAction(action);
}
}
diff --git a/src/net/java/joglutils/msg/nodes/Separator.java b/src/net/java/joglutils/msg/nodes/Separator.java
index c60ba45..fdebece 100644
--- a/src/net/java/joglutils/msg/nodes/Separator.java
+++ b/src/net/java/joglutils/msg/nodes/Separator.java
@@ -38,6 +38,7 @@
package net.java.joglutils.msg.nodes;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.misc.*;
/** Represents a push / pop of OpenGL state, "separating" the
sub-graph below this separator from the nodes which follow it in
@@ -45,8 +46,12 @@ import net.java.joglutils.msg.actions.*;
public class Separator extends Group {
public void doAction(Action action) {
- action.visitPre(this);
- super.doAction(action);
- action.visitPost(this);
+ State state = action.getState();
+ state.push();
+ try {
+ super.doAction(action);
+ } finally {
+ state.pop();
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/Texture2.java b/src/net/java/joglutils/msg/nodes/Texture2.java
index 441c2f5..fd1b82a 100644
--- a/src/net/java/joglutils/msg/nodes/Texture2.java
+++ b/src/net/java/joglutils/msg/nodes/Texture2.java
@@ -45,6 +45,7 @@ import javax.media.opengl.*;
import com.sun.opengl.util.texture.*;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
/** Represents a two-dimensional texture. */
@@ -54,6 +55,11 @@ public class Texture2 extends Node {
private int texEnvMode = MODULATE;
private boolean dirty;
+ static {
+ // Enable the elements this node affects for known actions
+ GLTextureElement.enable(GLRenderAction.getDefaultState());
+ }
+
/** Represents the OpenGL MODULATE texture environment mode. */
public static final int MODULATE = 1;
/** Represents the OpenGL DECAL texture environment mode. */
@@ -134,6 +140,8 @@ public class Texture2 extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ if (TextureElement.isEnabled(action.getState())) {
+ TextureElement.set(action.getState(), getTexture(), getTexEnvMode());
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java b/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java
index ed4ecf8..f7720d2 100644
--- a/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java
+++ b/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java
@@ -39,6 +39,7 @@ package net.java.joglutils.msg.nodes;
import net.java.joglutils.msg.actions.*;
import net.java.joglutils.msg.collections.*;
+import net.java.joglutils.msg.elements.*;
/** Represents a set of 2-dimensional texture coordinates which can be
used to texture geometric shapes. */
@@ -46,6 +47,11 @@ import net.java.joglutils.msg.collections.*;
public class TextureCoordinate2 extends Node {
private Vec2fCollection data;
+ static {
+ // Enable the elements this node affects for known actions
+ GLTextureCoordinateElement.enable(GLRenderAction.getDefaultState());
+ }
+
/** Sets the texture coordinate data in this node. */
public void setData(Vec2fCollection data) {
this.data = data;
@@ -57,6 +63,8 @@ public class TextureCoordinate2 extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ if (TextureCoordinateElement.isEnabled(action.getState())) {
+ TextureCoordinateElement.set(action.getState(), getData().getData());
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/Transform.java b/src/net/java/joglutils/msg/nodes/Transform.java
index 0faf8e6..ad5e1bd 100644
--- a/src/net/java/joglutils/msg/nodes/Transform.java
+++ b/src/net/java/joglutils/msg/nodes/Transform.java
@@ -38,6 +38,7 @@
package net.java.joglutils.msg.nodes;
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
import net.java.joglutils.msg.math.*;
/** Represents a generalized 4x4 matrix transformation. */
@@ -45,6 +46,14 @@ import net.java.joglutils.msg.math.*;
public class Transform extends Node {
private Mat4f transform;
+ 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());
+ }
+
public Transform() {
transform = new Mat4f();
transform.makeIdent();
@@ -61,6 +70,8 @@ public class Transform extends Node {
}
public void doAction(Action action) {
- action.visit(this);
+ if (ModelMatrixElement.isEnabled(action.getState())) {
+ ModelMatrixElement.mult(action.getState(), getTransform());
+ }
}
}
diff --git a/src/net/java/joglutils/msg/nodes/TriangleSet.java b/src/net/java/joglutils/msg/nodes/TriangleSet.java
index 775c622..0692738 100644
--- a/src/net/java/joglutils/msg/nodes/TriangleSet.java
+++ b/src/net/java/joglutils/msg/nodes/TriangleSet.java
@@ -37,7 +37,13 @@
package net.java.joglutils.msg.nodes;
+import javax.media.opengl.*;
+import com.sun.opengl.util.texture.*;
+
import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.elements.*;
+import net.java.joglutils.msg.math.*;
+import net.java.joglutils.msg.misc.*;
/** A TriangleSet assembles the coordinates specified by a Coordinate3
node, and any auxiliary nodes such as a TextureCoordinate2 node,
@@ -56,7 +62,67 @@ public class TriangleSet extends Node {
return numTriangles;
}
- public void doAction(Action action) {
- action.visit(this);
+ public void render(GLRenderAction action) {
+ State state = action.getState();
+ if (!CoordinateElement.isEnabled(state))
+ return;
+
+ if (CoordinateElement.get(state) != null) {
+ // OK, we have coordinates to send down, at least
+
+ GL gl = action.getGL();
+
+ Texture tex = null;
+ boolean haveTexCoords = false;
+
+ if (GLTextureElement.isEnabled(state) &&
+ GLTextureCoordinateElement.isEnabled(state)) {
+ tex = GLTextureElement.get(state);
+ haveTexCoords = (GLTextureCoordinateElement.get(state) != null);
+ }
+
+ if (tex != null) {
+ // Set up the texture matrix to uniformly map [0..1] to the used
+ // portion of the texture image
+ gl.glMatrixMode(GL.GL_TEXTURE);
+ gl.glPushMatrix();
+ gl.glLoadTransposeMatrixf(getTextureMatrix(tex).getRowMajorData(), 0);
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ } else if (haveTexCoords) {
+ // Want to turn off the use of texture coordinates to avoid errors
+ // FIXME: not 100% sure whether we need to do this, but think we should
+ gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
+ }
+
+ // For now, assume the triangle set and the number of available
+ // coordinates match -- may want to add debugging information
+ // for this later
+ gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3 * getNumTriangles());
+
+ if (tex != null) {
+ gl.glMatrixMode(GL.GL_TEXTURE);
+ gl.glPopMatrix();
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ } else if (haveTexCoords) {
+ // Might want this the next time we render a shape
+ gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+ }
+
+ // 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();
+ private Mat4f getTextureMatrix(Texture texture) {
+ textureMatrix.makeIdent();
+ TextureCoords coords = texture.getImageTexCoords();
+ // Horizontal scale
+ textureMatrix.set(0, 0, coords.right() - coords.left());
+ // Vertical scale (may be negative if texture needs to be flipped vertically)
+ float vertScale = coords.top() - coords.bottom();
+ textureMatrix.set(1, 1, vertScale);
+ textureMatrix.set(0, 3, coords.left());
+ textureMatrix.set(1, 3, coords.bottom());
+ return textureMatrix;
}
}