diff options
74 files changed, 8608 insertions, 0 deletions
diff --git a/build/joglutils.jar b/build/joglutils.jar Binary files differindex 16bdbe2..759c929 100644 --- a/build/joglutils.jar +++ b/build/joglutils.jar diff --git a/make/5-packages/package-list b/make/5-packages/package-list new file mode 100644 index 0000000..4878336 --- /dev/null +++ b/make/5-packages/package-list @@ -0,0 +1,166 @@ +java.applet +java.awt +java.awt.color +java.awt.datatransfer +java.awt.dnd +java.awt.event +java.awt.font +java.awt.geom +java.awt.im +java.awt.im.spi +java.awt.image +java.awt.image.renderable +java.awt.print +java.beans +java.beans.beancontext +java.io +java.lang +java.lang.annotation +java.lang.instrument +java.lang.management +java.lang.ref +java.lang.reflect +java.math +java.net +java.nio +java.nio.channels +java.nio.channels.spi +java.nio.charset +java.nio.charset.spi +java.rmi +java.rmi.activation +java.rmi.dgc +java.rmi.registry +java.rmi.server +java.security +java.security.acl +java.security.cert +java.security.interfaces +java.security.spec +java.sql +java.text +java.util +java.util.concurrent +java.util.concurrent.atomic +java.util.concurrent.locks +java.util.jar +java.util.logging +java.util.prefs +java.util.regex +java.util.zip +javax.accessibility +javax.activity +javax.crypto +javax.crypto.interfaces +javax.crypto.spec +javax.imageio +javax.imageio.event +javax.imageio.metadata +javax.imageio.plugins.bmp +javax.imageio.plugins.jpeg +javax.imageio.spi +javax.imageio.stream +javax.management +javax.management.loading +javax.management.modelmbean +javax.management.monitor +javax.management.openmbean +javax.management.relation +javax.management.remote +javax.management.remote.rmi +javax.management.timer +javax.naming +javax.naming.directory +javax.naming.event +javax.naming.ldap +javax.naming.spi +javax.net +javax.net.ssl +javax.print +javax.print.attribute +javax.print.attribute.standard +javax.print.event +javax.rmi +javax.rmi.CORBA +javax.rmi.ssl +javax.security.auth +javax.security.auth.callback +javax.security.auth.kerberos +javax.security.auth.login +javax.security.auth.spi +javax.security.auth.x500 +javax.security.cert +javax.security.sasl +javax.sound.midi +javax.sound.midi.spi +javax.sound.sampled +javax.sound.sampled.spi +javax.sql +javax.sql.rowset +javax.sql.rowset.serial +javax.sql.rowset.spi +javax.swing +javax.swing.border +javax.swing.colorchooser +javax.swing.event +javax.swing.filechooser +javax.swing.plaf +javax.swing.plaf.basic +javax.swing.plaf.metal +javax.swing.plaf.multi +javax.swing.plaf.synth +javax.swing.table +javax.swing.text +javax.swing.text.html +javax.swing.text.html.parser +javax.swing.text.rtf +javax.swing.tree +javax.swing.undo +javax.transaction +javax.transaction.xa +javax.xml +javax.xml.datatype +javax.xml.namespace +javax.xml.parsers +javax.xml.transform +javax.xml.transform.dom +javax.xml.transform.sax +javax.xml.transform.stream +javax.xml.validation +javax.xml.xpath +org.ietf.jgss +org.omg.CORBA +org.omg.CORBA.DynAnyPackage +org.omg.CORBA.ORBPackage +org.omg.CORBA.TypeCodePackage +org.omg.CORBA.portable +org.omg.CORBA_2_3 +org.omg.CORBA_2_3.portable +org.omg.CosNaming +org.omg.CosNaming.NamingContextExtPackage +org.omg.CosNaming.NamingContextPackage +org.omg.Dynamic +org.omg.DynamicAny +org.omg.DynamicAny.DynAnyFactoryPackage +org.omg.DynamicAny.DynAnyPackage +org.omg.IOP +org.omg.IOP.CodecFactoryPackage +org.omg.IOP.CodecPackage +org.omg.Messaging +org.omg.PortableInterceptor +org.omg.PortableInterceptor.ORBInitInfoPackage +org.omg.PortableServer +org.omg.PortableServer.CurrentPackage +org.omg.PortableServer.POAManagerPackage +org.omg.PortableServer.POAPackage +org.omg.PortableServer.ServantLocatorPackage +org.omg.PortableServer.portable +org.omg.SendingContext +org.omg.stub.java.rmi +org.w3c.dom +org.w3c.dom.bootstrap +org.w3c.dom.events +org.w3c.dom.ls +org.xml.sax +org.xml.sax.ext +org.xml.sax.helpers diff --git a/make/build.xml b/make/build.xml new file mode 100644 index 0000000..b407cf9 --- /dev/null +++ b/make/build.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - Ant build for the JOGL utilities. + - + - In order for this build to succeed the resulting jar file from this build + - (joglutils.jar) must not be on the CLASSPATH. + - + - This build requires that the jogl project has been checked out into a sibling + - directory to the joglutils top-level directory and that the jogl.jar has been + - built into its build directory. + --> +<project name="joglutils" basedir="." default="all"> + <property name="src.dir" value="../src" /> + <property name="output.dir" value="../build" /> + <property name="output.tmp.dir" value="../build/classes" /> + <property name="output.jar" value="${output.dir}/joglutils.jar" /> + <property name="jogl.jar" value="../../jogl/build/jogl.jar" /> + <property name="swinglayout.jar" value="${output.dir}/lib/swing-layout-1.0.jar" /> + <path id="build.classpath"> + <pathelement location="${jogl.jar}" /> + <pathelement location="${swinglayout.jar}" /> + </path> + + <property name="javadoc.link" value="http://java.sun.com/j2se/1.5.0/docs/api/" /> + + <property name="msg.javadoc.dir" value="../msg_javadoc" /> + <property name="msg.javadoc.packagenames" value="net.java.joglutils.msg.actions,net.java.joglutils.msg.collections,net.java.joglutils.msg.elements,net.java.joglutils.msg.math,net.java.joglutils.msg.misc,net.java.joglutils.msg.nodes,net.java.joglutils.msg.test" /> + <property name="msg.javadoc.overview" value="../src/net/java/joglutils/msg/overview.html" /> + <property name="msg.javadoc.windowtitle" value="Minimal Scene Graph (MSG)" /> + <target name="msg.javadoc"> + <javadoc packagenames="${msg.javadoc.packagenames}" + sourcepath="${src.dir}" + destdir="${msg.javadoc.dir}" windowtitle="${msg.javadoc.windowtitle}" + overview="${msg.javadoc.overview}" + source="1.5" + linkoffline="${javadoc.link} 5-packages" > + </javadoc> + </target> + + <target name="all"> + <mkdir dir="${output.tmp.dir}" /> + <javac destdir="${output.tmp.dir}" source="5" debug="true" debuglevel="source,lines"> + <src path="${src.dir}" /> + <classpath refid="build.classpath" /> + </javac> + <jar destfile="${output.jar}"> + <fileset dir="${output.tmp.dir}" /> + </jar> + </target> +</project> diff --git a/src/net/java/joglutils/msg/actions/Action.java b/src/net/java/joglutils/msg/actions/Action.java new file mode 100644 index 0000000..21ca2bc --- /dev/null +++ b/src/net/java/joglutils/msg/actions/Action.java @@ -0,0 +1,83 @@ +/* + * 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 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. +*/ + +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); + } + + /** 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); +} diff --git a/src/net/java/joglutils/msg/actions/GLRenderAction.java b/src/net/java/joglutils/msg/actions/GLRenderAction.java new file mode 100644 index 0000000..2274af1 --- /dev/null +++ b/src/net/java/joglutils/msg/actions/GLRenderAction.java @@ -0,0 +1,230 @@ +/* + * 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 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.*; + +/** An action which performs rendering of a scene graph via OpenGL. <P> + + When applied to the root of the scene graph, this action does not + perform any clearing of the color or depth buffer; this is the + responsibility of the caller. The render action pushes, pops, and + initializes enough OpenGL state to isolate itself, at least in + theory, from any surrounding OpenGL state that the application may + have set up. There should in theory be no user-visible OpenGL side + effects as a result of rendering with this action. +*/ + +public class GLRenderAction 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 State state = new State(defaults); + public State getState() { + return state; + } + + 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()); + } + + // For automatically setting the aspect ratios of cameras we encounter + private float curAspectRatio = 1.0f; + + private int applyDepth = 0; + + public void apply(Node node) { + GL gl = GLU.getCurrentGL(); + int depth = applyDepth++; + try { + if (depth == 0) { + // Applying to the root of the scene graph + // Push necessary GL state + // FIXME: add in additional bits as we add more capabilities + gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_CURRENT_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glColor4f(1, 1, 1, 1); + gl.glMatrixMode(GL.GL_TEXTURE); + gl.glLoadIdentity(); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT); + // Figure out the aspect ratio of the current viewport + int[] viewport = new int[4]; + gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); + curAspectRatio = (float) viewport[2] / (float) viewport[3]; + } + super.apply(node); + } finally { + if (depth == 0) { + gl.glPopClientAttrib(); + gl.glPopAttrib(); + } + --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(); + } + + 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); + } + } + } + + 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; + } +} diff --git a/src/net/java/joglutils/msg/actions/package.html b/src/net/java/joglutils/msg/actions/package.html new file mode 100644 index 0000000..a07291e --- /dev/null +++ b/src/net/java/joglutils/msg/actions/package.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +Actions which are applied to nodes to implement operations such as rendering. + +</body> +</html> diff --git a/src/net/java/joglutils/msg/collections/Vec2fCollection.java b/src/net/java/joglutils/msg/collections/Vec2fCollection.java new file mode 100644 index 0000000..a5ad3d3 --- /dev/null +++ b/src/net/java/joglutils/msg/collections/Vec2fCollection.java @@ -0,0 +1,155 @@ +/* + * 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.collections; + +import java.nio.*; + +import com.sun.opengl.util.*; + +import net.java.joglutils.msg.impl.*; +import net.java.joglutils.msg.math.*; + +/** Provides the abstraction of a collection of Vec2f objects while + allowing access to the backing store in the form of a direct + FloatBuffer to make it easy to pass down to OpenGL. */ + +public class Vec2fCollection { + // Data is stored as a direct FloatBuffer + private FloatBuffer data; + + private static final int ELEMENT_SIZE = 2; + + /** Creates an empty Vec2fCollection. */ + public Vec2fCollection() { + // Assume you'll probably want at least four vertices + this(4); + } + + /** Creates an empty Vec2fCollection with the backing store sized to + hold roughly the given number of vectors. */ + public Vec2fCollection(int estimatedSize) { + data = BufferFactory.newFloatBuffer(ELEMENT_SIZE * estimatedSize); + data.limit(0); + } + + /** Returns the number of Vec2fs currently in this collection. */ + public int size() { + return data.limit() / ELEMENT_SIZE; + } + + /** Stores the given Vec2f at the given index. If the collection has + not grown to the given size, throws an exception. */ + public void set(int index, Vec2f value) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + int base = index * ELEMENT_SIZE; + FloatBuffer buf = data; + buf.put(base, value.x()); + buf.put(base + 1, value.y()); + } + + /** Fetches the Vec2f at the given index. If the collection has not + grown to the given size, throws an exception. */ + public Vec2f get(int index) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + int base = index * ELEMENT_SIZE; + // Note: could use a small pool of Vec2fs here if allocation rate + // is an issue. However, escape analysis should eventually take + // care of this. + FloatBuffer buf = data; + return new Vec2f(buf.get(base), buf.get(base + 1)); + } + + /** Adds the given Vec2f to this collection, expanding it if + necessary. */ + public void add(Vec2f value) { + FloatBuffer buf = data; + if (buf.limit() == buf.capacity()) { + FloatBuffer newBuf = BufferUtil.newFloatBuffer(Math.max(buf.capacity() + ELEMENT_SIZE, + round((int) (buf.capacity() * 1.5f)))); + newBuf.put(buf); + newBuf.limit(buf.limit()); + data = newBuf; + buf = newBuf; + } + int pos = buf.limit(); + buf.limit(pos + ELEMENT_SIZE); + buf.put(pos, value.x()); + buf.put(pos + 1, value.y()); + } + + /** Removes the given Vec2f from this collection. Moves all Vec2fs + above it down one slot. */ + public Vec2f remove(int index) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + FloatBuffer buf = data; + int pos = index * ELEMENT_SIZE; + Vec2f res = new Vec2f(buf.get(pos), buf.get(pos + 1)); + if (index == size() - 1) { + // Simply lower the limit + buf.limit(buf.limit() - ELEMENT_SIZE); + } else { + buf.position(pos + 1); + FloatBuffer rest = buf.slice(); + buf.position(pos); + buf.put(rest); + buf.limit(buf.limit() - ELEMENT_SIZE); + } + return res; + } + + /** Returns the backing buffer of this collection. */ + public FloatBuffer getData() { + FloatBuffer buf = data; + buf.position(0); + return buf.slice(); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static int round(int size) { + return size - (size % ELEMENT_SIZE); + } +} diff --git a/src/net/java/joglutils/msg/collections/Vec3fCollection.java b/src/net/java/joglutils/msg/collections/Vec3fCollection.java new file mode 100644 index 0000000..698017d --- /dev/null +++ b/src/net/java/joglutils/msg/collections/Vec3fCollection.java @@ -0,0 +1,157 @@ +/* + * 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.collections; + +import java.nio.*; + +import com.sun.opengl.util.*; + +import net.java.joglutils.msg.impl.*; +import net.java.joglutils.msg.math.*; + +/** Provides the abstraction of a collection of Vec3f objects while + allowing access to the backing store in the form of a direct + FloatBuffer to make it easy to pass down to OpenGL. */ + +public class Vec3fCollection { + // Data is stored as a direct FloatBuffer + private FloatBuffer data; + + private static final int ELEMENT_SIZE = 3; + + /** Creates an empty Vec3fCollection. */ + public Vec3fCollection() { + // Assume you'll probably want at least four vertices + this(4); + } + + /** Creates an empty Vec3fCollection with the backing store sized to + hold roughly the given number of vectors. */ + public Vec3fCollection(int estimatedSize) { + data = BufferFactory.newFloatBuffer(ELEMENT_SIZE * estimatedSize); + data.limit(0); + } + + /** Returns the number of Vec3fs currently in this collection. */ + public int size() { + return data.limit() / ELEMENT_SIZE; + } + + /** Stores the given Vec3f at the given index. If the collection has + not grown to the given size, throws an exception. */ + public void set(int index, Vec3f value) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + int base = index * ELEMENT_SIZE; + FloatBuffer buf = data; + buf.put(base, value.x()); + buf.put(base + 1, value.y()); + buf.put(base + 2, value.z()); + } + + /** Fetches the Vec3f at the given index. If the collection has not + grown to the given size, throws an exception. */ + public Vec3f get(int index) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + int base = index * ELEMENT_SIZE; + // Note: could use a small pool of Vec3fs here if allocation rate + // is an issue. However, escape analysis should eventually take + // care of this. + FloatBuffer buf = data; + return new Vec3f(buf.get(base), buf.get(base + 1), buf.get(base + 2)); + } + + /** Adds the given Vec3f to this collection, expanding it if + necessary. */ + public void add(Vec3f value) { + FloatBuffer buf = data; + if (buf.limit() == buf.capacity()) { + FloatBuffer newBuf = BufferUtil.newFloatBuffer(Math.max(buf.capacity() + ELEMENT_SIZE, + round((int) (buf.capacity() * 1.5f)))); + newBuf.put(buf); + newBuf.limit(buf.limit()); + data = newBuf; + buf = newBuf; + } + int pos = buf.limit(); + buf.limit(pos + ELEMENT_SIZE); + buf.put(pos, value.x()); + buf.put(pos + 1, value.y()); + buf.put(pos + 2, value.z()); + } + + /** Removes the given Vec3f from this collection. Moves all Vec3fs + above it down one slot. */ + public Vec3f remove(int index) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + FloatBuffer buf = data; + int pos = index * ELEMENT_SIZE; + Vec3f res = new Vec3f(buf.get(pos), buf.get(pos + 1), buf.get(pos + 2)); + if (index == size() - 1) { + // Simply lower the limit + buf.limit(buf.limit() - ELEMENT_SIZE); + } else { + buf.position(pos + 1); + FloatBuffer rest = buf.slice(); + buf.position(pos); + buf.put(rest); + buf.limit(buf.limit() - ELEMENT_SIZE); + } + return res; + } + + /** Returns the backing buffer of this collection. */ + public FloatBuffer getData() { + FloatBuffer buf = data; + buf.position(0); + return buf.slice(); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static int round(int size) { + return size - (size % ELEMENT_SIZE); + } +} diff --git a/src/net/java/joglutils/msg/collections/Vec4fCollection.java b/src/net/java/joglutils/msg/collections/Vec4fCollection.java new file mode 100644 index 0000000..a1d1e86 --- /dev/null +++ b/src/net/java/joglutils/msg/collections/Vec4fCollection.java @@ -0,0 +1,159 @@ +/* + * 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.collections; + +import java.nio.*; + +import com.sun.opengl.util.*; + +import net.java.joglutils.msg.impl.*; +import net.java.joglutils.msg.math.*; + +/** Provides the abstraction of a collection of Vec4f objects while + allowing access to the backing store in the form of a direct + FloatBuffer to make it easy to pass down to OpenGL. */ + +public class Vec4fCollection { + // Data is stored as a direct FloatBuffer + private FloatBuffer data; + + private static final int ELEMENT_SIZE = 4; + + /** Creates an empty Vec4fCollection. */ + public Vec4fCollection() { + // Assume you'll probably want at least four vertices + this(4); + } + + /** Creates an empty Vec4fCollection with the backing store sized to + hold roughly the given number of vectors. */ + public Vec4fCollection(int estimatedSize) { + data = BufferFactory.newFloatBuffer(ELEMENT_SIZE * estimatedSize); + data.limit(0); + } + + /** Returns the number of Vec4fs currently in this collection. */ + public int size() { + return data.limit() / ELEMENT_SIZE; + } + + /** Stores the given Vec4f at the given index. If the collection has + not grown to the given size, throws an exception. */ + public void set(int index, Vec4f value) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + int base = index * ELEMENT_SIZE; + FloatBuffer buf = data; + buf.put(base, value.x()); + buf.put(base + 1, value.y()); + buf.put(base + 2, value.z()); + buf.put(base + 3, value.w()); + } + + /** Fetches the Vec4f at the given index. If the collection has not + grown to the given size, throws an exception. */ + public Vec4f get(int index) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + int base = index * ELEMENT_SIZE; + // Note: could use a small pool of Vec4fs here if allocation rate + // is an issue. However, escape analysis should eventually take + // care of this. + FloatBuffer buf = data; + return new Vec4f(buf.get(base), buf.get(base + 1), buf.get(base + 2), buf.get(base + 3)); + } + + /** Adds the given Vec4f to this collection, expanding it if + necessary. */ + public void add(Vec4f value) { + FloatBuffer buf = data; + if (buf.limit() == buf.capacity()) { + FloatBuffer newBuf = BufferUtil.newFloatBuffer(Math.max(buf.capacity() + ELEMENT_SIZE, + round((int) (buf.capacity() * 1.5f)))); + newBuf.put(buf); + newBuf.limit(buf.limit()); + data = newBuf; + buf = newBuf; + } + int pos = buf.limit(); + buf.limit(pos + ELEMENT_SIZE); + buf.put(pos, value.x()); + buf.put(pos + 1, value.y()); + buf.put(pos + 2, value.z()); + buf.put(pos + 3, value.w()); + } + + /** Removes the given Vec4f from this collection. Moves all Vec4fs + above it down one slot. */ + public Vec4f remove(int index) throws IndexOutOfBoundsException { + if (index >= size()) { + throw new IndexOutOfBoundsException("" + index + " >= " + size()); + } + FloatBuffer buf = data; + int pos = index * ELEMENT_SIZE; + Vec4f res = new Vec4f(buf.get(pos), buf.get(pos + 1), buf.get(pos + 2), buf.get(pos + 3)); + if (index == size() - 1) { + // Simply lower the limit + buf.limit(buf.limit() - ELEMENT_SIZE); + } else { + buf.position(pos + 1); + FloatBuffer rest = buf.slice(); + buf.position(pos); + buf.put(rest); + buf.limit(buf.limit() - ELEMENT_SIZE); + } + return res; + } + + /** Returns the backing buffer of this collection. */ + public FloatBuffer getData() { + FloatBuffer buf = data; + buf.position(0); + return buf.slice(); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static int round(int size) { + return size - (size % ELEMENT_SIZE); + } +} diff --git a/src/net/java/joglutils/msg/collections/package.html b/src/net/java/joglutils/msg/collections/package.html new file mode 100644 index 0000000..e917f3d --- /dev/null +++ b/src/net/java/joglutils/msg/collections/package.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +Collection classes for storing vector data in formats which can be +quickly sent down to OpenGL. + +</body> +</html> diff --git a/src/net/java/joglutils/msg/elements/BlendElement.java b/src/net/java/joglutils/msg/elements/BlendElement.java new file mode 100644 index 0000000..2a0d488 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/BlendElement.java @@ -0,0 +1,139 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; +import net.java.joglutils.msg.nodes.*; + +/** Represents the blending state of the OpenGL fixed-function pipeline. */ + +public class BlendElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new BlendElement(); + } + /** Returns the instance of this element in the passed State. */ + public static BlendElement getInstance(State state) { + return (BlendElement) 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) { + BlendElement tmp = new BlendElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // These defaults match those in the Blend node -- is there a better way of factoring them out? + + // Whether blending is enabled + protected boolean enabled; + protected Vec4f blendColor = new Vec4f(); + protected int srcFunc = Blend.ONE; + protected int destFunc = Blend.ZERO; + protected int blendEquation = Blend.FUNC_ADD; + + /** Sets all of the portions of the blending state in the passed State object. */ + public static void set(State state, + boolean enabled, + Vec4f blendColor, + int srcFunc, + int destFunc, + int blendEquation) { + getInstance(state).setElt(enabled, + blendColor, + srcFunc, + destFunc, + blendEquation); + } + + /** Returns whether blending is enabled. */ + public static boolean getEnabled(State state) { + return getInstance(state).enabled; + } + + /** Returns the blending color. */ + public static Vec4f getBlendColor(State state) { + return getInstance(state).blendColor; + } + + /** Returns the source function for blending. */ + public static int getSourceFunc(State state) { + return getInstance(state).srcFunc; + } + + /** Returns the destination function for blending. */ + public static int getDestFunc(State state) { + return getInstance(state).destFunc; + } + + /** Returns the blending equation. */ + public static int getBlendEquation(State state) { + return getInstance(state).blendEquation; + } + + public void push(State state) { + BlendElement prev = (BlendElement) getNextInStack(); + if (prev != null) { + // Pull down the data from the previous element + enabled = prev.enabled; + blendColor.set(prev.blendColor); + srcFunc = prev.srcFunc; + destFunc = prev.destFunc; + blendEquation = prev.blendEquation; + } + } + + /** Sets all of the portions of the blending state in this element. */ + public void setElt(boolean enabled, + Vec4f blendColor, + int srcFunc, + int destFunc, + int blendEquation) { + this.enabled = enabled; + this.blendColor.set(blendColor); + this.srcFunc = srcFunc; + this.destFunc = destFunc; + this.blendEquation = blendEquation; + } +} diff --git a/src/net/java/joglutils/msg/elements/ColorElement.java b/src/net/java/joglutils/msg/elements/ColorElement.java new file mode 100644 index 0000000..a725d61 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/ColorElement.java @@ -0,0 +1,93 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; + +import net.java.joglutils.msg.misc.*; + +/** Represents the current set of colors, which are applied on a + per-vertex basis to any drawn geometry. */ + +public class ColorElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new ColorElement(); + } + /** Returns the instance of this element in the passed State. */ + public static ColorElement getInstance(State state) { + return (ColorElement) 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) { + ColorElement tmp = new ColorElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The actual color data + protected FloatBuffer colors; + // The color binding to material parameter (not yet implemented) + protected int colorBinding; + + /** Sets the color data in the passed state. */ + public static void set(State state, FloatBuffer colors) { + getInstance(state).setElt(colors); + } + + /** Returns the color data in the passed state. */ + public static FloatBuffer get(State state) { + return getInstance(state).colors; + } + + public void push(State state) { + ColorElement prev = (ColorElement) getNextInStack(); + if (prev != null) { + // Pull down the data from the previous element + colors = prev.colors; + } + } + + /** Sets the color data in this element. */ + public void setElt(FloatBuffer colors) { + this.colors = colors; + } +} diff --git a/src/net/java/joglutils/msg/elements/CoordinateElement.java b/src/net/java/joglutils/msg/elements/CoordinateElement.java new file mode 100644 index 0000000..34b16bc --- /dev/null +++ b/src/net/java/joglutils/msg/elements/CoordinateElement.java @@ -0,0 +1,88 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; + +import net.java.joglutils.msg.misc.*; + +/** Represents the current set of coordinates, which are assembled to + draw geometry. */ + +public class CoordinateElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new CoordinateElement(); + } + public static CoordinateElement getInstance(State state) { + return (CoordinateElement) state.getElement(index); + } + public static void enable(State defaultState) { + CoordinateElement tmp = new CoordinateElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The actual coordinate data + protected FloatBuffer coords; + + /** Sets the coordinate data in the passed state. */ + public static void set(State state, FloatBuffer coords) { + getInstance(state).setElt(coords); + } + + /** Returns the coordinate data in the passed state. */ + public static FloatBuffer get(State state) { + return getInstance(state).coords; + } + + public void push(State state) { + CoordinateElement prev = (CoordinateElement) getNextInStack(); + if (prev != null) { + // Pull down the data from the previous element + coords = prev.coords; + } + } + + /** Sets the coordinate data in this element. */ + public void setElt(FloatBuffer coords) { + this.coords = coords; + } +} diff --git a/src/net/java/joglutils/msg/elements/Element.java b/src/net/java/joglutils/msg/elements/Element.java new file mode 100644 index 0000000..5937b65 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/Element.java @@ -0,0 +1,103 @@ +/* + * 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.elements; + +import net.java.joglutils.msg.misc.*; + +/** Represents an element in the global {@link + net.java.joglutils.msg.misc.State state}, such as the current 3D + coordinates or texture to be applied. The organization of the + global state into elements is one of the key mechanisms for + extendability of the library which was pioneered by Open Inventor. +*/ + +public abstract class Element { + // Elements are organized into stacks. When we descend past (for + // example) a Separator node, we need to push all of the state + // elements, traverse the children, and then pop the state elements + // so afterward we restore the original state. This is implemented + // in the State class using a linked list of Elements, where the + // State keeps track of the top of each element stack. + private Element nextInStack; + + // Additionally we maintain a linked list through all Element + // instances pushed and popped in the State, so that we don't have + // to traverse all Element slots when performing a state pop. + private Element next; + + // Elements need to keep track of their depth in the stack in order + // for the State to maintain itself + private int depth; + + protected Element() {} + + /** Creates a new instance initialized to the default values for the + state element. All concrete Element subclasses must implement + this operation. */ + public abstract Element newInstance(); + + /** Returns the next element in the stack. */ + public Element getNextInStack() { return nextInStack; } + /** Sets the next element in the stack. */ + public void setNextInStack(Element nextInStack) { this.nextInStack = nextInStack; } + + /** Returns the next element in the linked list of elements which + were modified since the last state push. */ + public Element getNext() { return next; } + /** Sets the next element in the linked list of elements which were + modified since the last state push. */ + public void setNext(Element next) { this.next = next; } + + /** Returns the depth of this element in its stack, used to implement lazy state pushing. */ + public int getDepth() { return depth; } + /** Sets the depth of this element in its stack, used to implement lazy state pushing. */ + public void setDepth(int depth) { this.depth = depth; } + + /** Pushes the element, allowing for side effects to occur. Default method does nothing. */ + public void push(State state) {} + /** Pops the element, allowing for side effects to occur. Default + method does nothing. NOTE that it is not legal to call + State.getElement() in the implementation of this method, which + is why the previous top element is provided as an argument. */ + public void pop (State state, Element previousTopElement) {} + + /** All concrete element subclasses must register themselves with + the State in order to reserve a slot, or index, in the + state. This method must be overridden to return this slot. */ + public abstract StateIndex getStateIndex(); +} diff --git a/src/net/java/joglutils/msg/elements/GLBlendElement.java b/src/net/java/joglutils/msg/elements/GLBlendElement.java new file mode 100644 index 0000000..7955533 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLBlendElement.java @@ -0,0 +1,138 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; +import net.java.joglutils.msg.nodes.*; + +/** Represents the blending state of the OpenGL fixed-function + pipeline and causes side-effects in OpenGL for rendering. */ + +public class GLBlendElement extends BlendElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLBlendElement(); + } + public static GLBlendElement getInstance(State state) { + return (GLBlendElement) BlendElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLBlendElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + public void pop(State state, Element previousTopElement) { + send(); + } + + public void setElt(boolean enabled, + Vec4f blendColor, + int srcFunc, + int destFunc, + int blendEquation) { + super.setElt(enabled, blendColor, srcFunc, destFunc, blendEquation); + send(); + } + + private static int oglBlendFunc(int func) { + switch (func) { + case Blend.ZERO: return GL.GL_ZERO; + case Blend.ONE: return GL.GL_ONE; + case Blend.SRC_COLOR: return GL.GL_SRC_COLOR; + case Blend.ONE_MINUS_SRC_COLOR: return GL.GL_ONE_MINUS_SRC_COLOR; + case Blend.DST_COLOR: return GL.GL_DST_COLOR; + case Blend.ONE_MINUS_DST_COLOR: return GL.GL_ONE_MINUS_DST_COLOR; + case Blend.SRC_ALPHA: return GL.GL_SRC_ALPHA; + case Blend.ONE_MINUS_SRC_ALPHA: return GL.GL_ONE_MINUS_SRC_ALPHA; + case Blend.DST_ALPHA: return GL.GL_DST_ALPHA; + case Blend.ONE_MINUS_DST_ALPHA: return GL.GL_ONE_MINUS_DST_ALPHA; + case Blend.SRC_ALPHA_SATURATE: return GL.GL_SRC_ALPHA_SATURATE; + case Blend.CONSTANT_COLOR: return GL.GL_CONSTANT_COLOR; + case Blend.ONE_MINUS_CONSTANT_COLOR: return GL.GL_ONE_MINUS_CONSTANT_COLOR; + case Blend.CONSTANT_ALPHA: return GL.GL_CONSTANT_ALPHA; + case Blend.ONE_MINUS_CONSTANT_ALPHA: return GL.GL_ONE_MINUS_CONSTANT_ALPHA; + } + throw new InternalError("Illegal blend function " + func); + } + + private int oglBlendEquation(int equation) { + switch (equation) { + case Blend.FUNC_ADD: return GL.GL_FUNC_ADD; + case Blend.FUNC_SUBTRACT: return GL.GL_FUNC_SUBTRACT; + case Blend.FUNC_REVERSE_SUBTRACT: return GL.GL_FUNC_REVERSE_SUBTRACT; + case Blend.MIN: return GL.GL_MIN; + case Blend.MAX: return GL.GL_MAX; + } + throw new InternalError("Illegal blend equation " + equation); + } + + private static void validateFunc(GL gl, int func) { + if (func == GL.GL_CONSTANT_COLOR || + func == GL.GL_ONE_MINUS_CONSTANT_COLOR || + func == GL.GL_CONSTANT_ALPHA || + func == GL.GL_ONE_MINUS_CONSTANT_ALPHA) { + if (!gl.isExtensionAvailable("GL_ARB_imaging")) { + throw new RuntimeException("Blend function requires GL_ARB_imaging extension"); + } + } + } + + private void send() { + GL gl = GLU.getCurrentGL(); + // Don't try to optimize what we send to OpenGL at this point -- too complicated + if (enabled) { + gl.glEnable(GL.GL_BLEND); + int oglSrcFunc = oglBlendFunc(srcFunc); + int oglDestFunc = oglBlendFunc(destFunc); + validateFunc(gl, oglSrcFunc); + validateFunc(gl, oglDestFunc); + gl.glBlendFunc(oglSrcFunc, oglDestFunc); + if (gl.isExtensionAvailable("GL_ARB_imaging")) { + gl.glBlendEquation(oglBlendEquation(blendEquation)); + gl.glBlendColor(blendColor.x(), blendColor.y(), blendColor.z(), blendColor.w()); + } + } else { + gl.glDisable(GL.GL_BLEND); + } + } +} diff --git a/src/net/java/joglutils/msg/elements/GLColorElement.java b/src/net/java/joglutils/msg/elements/GLColorElement.java new file mode 100644 index 0000000..732ee98 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLColorElement.java @@ -0,0 +1,102 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.misc.*; + +/** Represents the current set of colors, which are applied on a + per-vertex basis to any drawn geometry, and causes side-effects in + OpenGL for rendering. */ + +public class GLColorElement extends ColorElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLColorElement(); + } + public static GLColorElement getInstance(State state) { + return (GLColorElement) ColorElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLColorElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // Whether the OpenGL state is currently enabled + private boolean enabled; + + public void push(State state) { + super.push(state); + // Copy enabled state from previous element if any + GLColorElement prev = (GLColorElement) getNextInStack(); + if (prev != null) { + enabled = prev.enabled; + } + } + + public void pop(State state, Element previousTopElement) { + GLColorElement prev = (GLColorElement) previousTopElement; + boolean shouldBeEnabled = enabled; + enabled = prev.enabled; + // Put things back the way they were + setEnabled(shouldBeEnabled); + } + + public void setElt(FloatBuffer colors) { + super.setElt(colors); + setEnabled(colors != null); + } + + private void setEnabled(boolean enabled) { + if (this.enabled == enabled) + return; // No OpenGL work to do + this.enabled = enabled; + GL gl = GLU.getCurrentGL(); + if (enabled) { + gl.glColorPointer(4, GL.GL_FLOAT, 0, colors); + gl.glEnableClientState(GL.GL_COLOR_ARRAY); + } else { + gl.glDisableClientState(GL.GL_COLOR_ARRAY); + // Assume we have to reset the current color to the default + gl.glColor4f(1, 1, 1, 1); + } + } +} diff --git a/src/net/java/joglutils/msg/elements/GLCoordinateElement.java b/src/net/java/joglutils/msg/elements/GLCoordinateElement.java new file mode 100644 index 0000000..d33e4ec --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLCoordinateElement.java @@ -0,0 +1,99 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.misc.*; + +/** Represents the current set of coordinates, which are assembled to + draw geometry, and causes side-effects in OpenGL. */ + +public class GLCoordinateElement extends CoordinateElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLCoordinateElement(); + } + public static GLCoordinateElement getInstance(State state) { + return (GLCoordinateElement) CoordinateElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLCoordinateElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // Whether the OpenGL state is currently enabled + private boolean enabled; + + public void push(State state) { + super.push(state); + // Copy enabled state from previous element if any + GLCoordinateElement prev = (GLCoordinateElement) getNextInStack(); + if (prev != null) { + enabled = prev.enabled; + } + } + + public void pop(State state, Element previousTopElement) { + GLCoordinateElement prev = (GLCoordinateElement) previousTopElement; + boolean shouldBeEnabled = enabled; + enabled = prev.enabled; + // Put things back the way they were + setEnabled(shouldBeEnabled); + } + + public void setElt(FloatBuffer coords) { + super.setElt(coords); + setEnabled(coords != null); + } + + private void setEnabled(boolean enabled) { + if (this.enabled == enabled) + return; // No OpenGL work to do + this.enabled = enabled; + GL gl = GLU.getCurrentGL(); + if (enabled) { + gl.glVertexPointer(3, GL.GL_FLOAT, 0, coords); + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + } else { + gl.glDisableClientState(GL.GL_VERTEX_ARRAY); + } + } +} diff --git a/src/net/java/joglutils/msg/elements/GLModelMatrixElement.java b/src/net/java/joglutils/msg/elements/GLModelMatrixElement.java new file mode 100644 index 0000000..24097bc --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLModelMatrixElement.java @@ -0,0 +1,97 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; + +/** Represents the model matrix, which is the transformation applied + to objects in the scene, and causes side-effects in OpenGL. */ + +public class GLModelMatrixElement extends ModelMatrixElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLModelMatrixElement(); + } + public static GLModelMatrixElement getInstance(State state) { + return (GLModelMatrixElement) ModelMatrixElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLModelMatrixElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // State which we need in order to reset the modelview matrix + private State state; + + public void push(State state) { + super.push(state); + this.state = state; + + // Cause side-effects in OpenGL + GL gl = GLU.getCurrentGL(); + gl.glPushMatrix(); + } + + public void pop(State state, Element previousTopElement) { + super.pop(state, previousTopElement); + + // Cause side-effects in OpenGL + GL gl = GLU.getCurrentGL(); + gl.glPopMatrix(); + } + + public void makeEltIdent() { + super.makeEltIdent(); + // Cause side-effects in OpenGL + // Recompute the complete modelview matrix + Mat4f mat = ViewingMatrixElement.getInstance(state).getMatrix(); + GL gl = GLU.getCurrentGL(); + gl.glLoadTransposeMatrixf(mat.getRowMajorData(), 0); + } + + public void multElt(Mat4f matrix) { + super.multElt(matrix); + GL gl = GLU.getCurrentGL(); + gl.glMultTransposeMatrixf(matrix.getRowMajorData(), 0); + } +} diff --git a/src/net/java/joglutils/msg/elements/GLProjectionMatrixElement.java b/src/net/java/joglutils/msg/elements/GLProjectionMatrixElement.java new file mode 100644 index 0000000..6c8d7d2 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLProjectionMatrixElement.java @@ -0,0 +1,75 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; + +/** Represents the projection matrix, which transforms view-space + coordinates into screen-space coordinates, and performs + side-effects in OpenGL. */ + +public class GLProjectionMatrixElement extends ProjectionMatrixElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLProjectionMatrixElement(); + } + public static GLProjectionMatrixElement getInstance(State state) { + return (GLProjectionMatrixElement) ProjectionMatrixElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLProjectionMatrixElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + public void push(State state) { + super.push(state); + } + + public void setElt(Mat4f matrix) { + super.setElt(matrix); + GL gl = GLU.getCurrentGL(); + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadTransposeMatrixf(matrix.getRowMajorData(), 0); + gl.glMatrixMode(GL.GL_MODELVIEW); + } +} diff --git a/src/net/java/joglutils/msg/elements/GLTextureCoordinateElement.java b/src/net/java/joglutils/msg/elements/GLTextureCoordinateElement.java new file mode 100644 index 0000000..111d0a9 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLTextureCoordinateElement.java @@ -0,0 +1,104 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.misc.*; + +/** Represents the current set of texture coordinates, which are + applied on a per-vertex basis to any drawn geometry, and performs + side-effects in OpenGL. */ + +public class GLTextureCoordinateElement extends TextureCoordinateElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLTextureCoordinateElement(); + } + public static GLTextureCoordinateElement getInstance(State state) { + return (GLTextureCoordinateElement) TextureCoordinateElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLTextureCoordinateElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // Whether the OpenGL state is currently enabled + private boolean enabled; + + public void push(State state) { + super.push(state); + // Copy enabled state from previous element if any + GLTextureCoordinateElement prev = (GLTextureCoordinateElement) getNextInStack(); + if (prev != null) { + enabled = prev.enabled; + } + } + + public void pop(State state, Element previousTopElement) { + GLTextureCoordinateElement prev = (GLTextureCoordinateElement) previousTopElement; + boolean shouldBeEnabled = enabled; + enabled = prev.enabled; + // Put things back the way they were + setEnabled(shouldBeEnabled); + } + + public void setElt(FloatBuffer coords) { + super.setElt(coords); + setEnabled(coords != null); + } + + private void setEnabled(boolean enabled) { + if (this.enabled == enabled) + return; // No OpenGL work to do + this.enabled = enabled; + GL gl = GLU.getCurrentGL(); + if (enabled) { + // FIXME: may want to link this up with the GLTextureElement so + // that we only enable the texture coordinate array if we both + // have a TextureCoordinateElement and a TextureElement active + // (a little error checking for the application) + gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, coords); + gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); + } else { + gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); + } + } +} diff --git a/src/net/java/joglutils/msg/elements/GLTextureElement.java b/src/net/java/joglutils/msg/elements/GLTextureElement.java new file mode 100644 index 0000000..5241b09 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLTextureElement.java @@ -0,0 +1,96 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.sun.opengl.util.texture.*; + +import net.java.joglutils.msg.misc.*; +import net.java.joglutils.msg.nodes.*; + +/** Represents the current texture, which is applied to any drawn + geometry if texture coordinates are also supplied, and performs + side-effects in OpenGL. */ + +public class GLTextureElement extends TextureElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLTextureElement(); + } + public static GLTextureElement getInstance(State state) { + return (GLTextureElement) TextureElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLTextureElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + public void pop(State state, Element previousTopElement) { + // Put things back the way they were + switchTextures(((GLTextureElement) previousTopElement).texture, texture, texEnvMode); + } + + public void setElt(Texture texture, int texEnvMode) { + Texture prev = this.texture; + super.setElt(texture, texEnvMode); + switchTextures(prev, texture, texEnvMode); + } + + private void switchTextures(Texture prev, Texture texture, int texEnvMode) { + GL gl = GLU.getCurrentGL(); + // FIXME: should be smarter about this; if the target is the same + // for the previous and current textures, just bind the new one + if (prev != null) { + prev.disable(); + } + if (texture != null) { + texture.enable(); + texture.bind(); + int glEnvMode = 0; + switch (texEnvMode) { + case Texture2.MODULATE: glEnvMode = GL.GL_MODULATE; break; + case Texture2.DECAL: glEnvMode = GL.GL_DECAL; break; + case Texture2.BLEND: glEnvMode = GL.GL_BLEND; break; + case Texture2.REPLACE: glEnvMode = GL.GL_REPLACE; break; + } + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, glEnvMode); + } + } +} diff --git a/src/net/java/joglutils/msg/elements/GLViewingMatrixElement.java b/src/net/java/joglutils/msg/elements/GLViewingMatrixElement.java new file mode 100644 index 0000000..5848413 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/GLViewingMatrixElement.java @@ -0,0 +1,81 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; + +/** Represents the viewing matrix, which contains the transformation + between the camera and the model, and performs side-effects in + OpenGL. */ + +public class GLViewingMatrixElement extends ViewingMatrixElement { + // Boilerplate for concrete element subclasses + public Element newInstance() { + return new GLViewingMatrixElement(); + } + public static GLViewingMatrixElement getInstance(State state) { + return (GLViewingMatrixElement) ViewingMatrixElement.getInstance(state); + } + public static void enable(State defaultState) { + Element tmp = new GLViewingMatrixElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // State which we need in order to reset the modelview matrix + private State state; + protected Mat4f temp = new Mat4f(); + + public void push(State state) { + super.push(state); + this.state = state; + } + + public void setElt(Mat4f matrix) { + super.setElt(matrix); + // Must push the combined viewing and modelview matrices down to OpenGL + Mat4f mdl = ModelMatrixElement.getInstance(state).getMatrix(); + temp.mul(matrix, mdl); + GL gl = GLU.getCurrentGL(); + gl.glLoadTransposeMatrixf(temp.getRowMajorData(), 0); + } +} diff --git a/src/net/java/joglutils/msg/elements/ModelMatrixElement.java b/src/net/java/joglutils/msg/elements/ModelMatrixElement.java new file mode 100644 index 0000000..cfe726e --- /dev/null +++ b/src/net/java/joglutils/msg/elements/ModelMatrixElement.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.elements; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; + +/** Represents the model matrix, which is the transformation applied + to objects in the scene. */ + +public class ModelMatrixElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new ModelMatrixElement(); + } + public static ModelMatrixElement getInstance(State state) { + return (ModelMatrixElement) state.getElement(index); + } + public static void enable(State defaultState) { + Element tmp = new ModelMatrixElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The matrix data + protected Mat4f matrix; + protected Mat4f temp = new Mat4f(); + + public ModelMatrixElement() { + matrix = new Mat4f(); + matrix.makeIdent(); + } + + public void push(State state) { + ModelMatrixElement prev = (ModelMatrixElement) getNextInStack(); + if (prev != null) { + matrix.set(prev.matrix); + } + } + + /** Returns the current model matrix; callers should not mutate this + directly but instead use the accessor methods to change it. */ + public Mat4f getMatrix() { + return matrix; + } + + /** Sets the current element to the identity matrix. */ + public static void makeIdent(State state) { + ModelMatrixElement elt = getInstance(state); + elt.makeEltIdent(); + } + + /** Sets this element to the identity matrix. */ + public void makeEltIdent() { + matrix.makeIdent(); + } + + /** Multiplies the current element by the given matrix. */ + public static void mult(State state, Mat4f matrix) { + ModelMatrixElement elt = getInstance(state); + elt.multElt(matrix); + } + + /** Multiplies this element by the given matrix. */ + public void multElt(Mat4f matrix) { + temp.set(this.matrix); + this.matrix.mul(temp, matrix); + } +} diff --git a/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java b/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java new file mode 100644 index 0000000..dd70ca3 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/ProjectionMatrixElement.java @@ -0,0 +1,93 @@ +/* + * 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.elements; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; + +/** Represents the projection matrix, which transforms view-space + coordinates into screen-space coordinates. */ + +public class ProjectionMatrixElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new ProjectionMatrixElement(); + } + public static ProjectionMatrixElement getInstance(State state) { + return (ProjectionMatrixElement) state.getElement(index); + } + public static void enable(State defaultState) { + Element tmp = new ProjectionMatrixElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The matrix data + protected Mat4f matrix; + + public ProjectionMatrixElement() { + matrix = new Mat4f(); + matrix.makeIdent(); + } + + /** Returns the current projection matrix; callers should not mutate + this directly but instead use the accessor methods to change + it. */ + public Mat4f getMatrix() { + return matrix; + } + + public void push(State state) { + ProjectionMatrixElement prev = (ProjectionMatrixElement) getNextInStack(); + if (prev != null) { + matrix.set(prev.matrix); + } + } + + /** Sets the projection matrix in the given state to the given one. */ + public static void set(State state, Mat4f matrix) { + ProjectionMatrixElement elt = getInstance(state); + elt.setElt(matrix); + } + + /** Sets the projection matrix in this element to the given one. */ + public void setElt(Mat4f matrix) { + this.matrix.set(matrix); + } +} diff --git a/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java b/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java new file mode 100644 index 0000000..6d36c6c --- /dev/null +++ b/src/net/java/joglutils/msg/elements/TextureCoordinateElement.java @@ -0,0 +1,88 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; + +import net.java.joglutils.msg.misc.*; + +/** Represents the current set of texture coordinates, which are + applied on a per-vertex basis to any drawn geometry. */ + +public class TextureCoordinateElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new TextureCoordinateElement(); + } + public static TextureCoordinateElement getInstance(State state) { + return (TextureCoordinateElement) state.getElement(index); + } + public static void enable(State defaultState) { + TextureCoordinateElement tmp = new TextureCoordinateElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The actual coordinate data + protected FloatBuffer coords; + + /** Sets the texture coordinate data in the passed state. */ + public static void set(State state, FloatBuffer coords) { + getInstance(state).setElt(coords); + } + + /** Returns the texture coordinate data in the passed state. */ + public static FloatBuffer get(State state) { + return getInstance(state).coords; + } + + public void push(State state) { + TextureCoordinateElement prev = (TextureCoordinateElement) getNextInStack(); + if (prev != null) { + // Pull down the data from the previous element + coords = prev.coords; + } + } + + /** Sets the texture coordinate data in this element. */ + public void setElt(FloatBuffer coords) { + this.coords = coords; + } +} diff --git a/src/net/java/joglutils/msg/elements/TextureElement.java b/src/net/java/joglutils/msg/elements/TextureElement.java new file mode 100644 index 0000000..90a9ebc --- /dev/null +++ b/src/net/java/joglutils/msg/elements/TextureElement.java @@ -0,0 +1,101 @@ +/* + * 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.elements; + +import java.nio.*; +import javax.media.opengl.*; +import com.sun.opengl.util.texture.*; + +import net.java.joglutils.msg.misc.*; + +// FIXME: the TextureElement / GLTextureElement distinction doesn't +// make much sense here, because the Texture object the TextureElement +// contains already implicitly relies on OpenGL + +/** Represents the current texture, which is applied to any drawn + geometry if texture coordinates are also supplied. */ + +public class TextureElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new TextureElement(); + } + public static TextureElement getInstance(State state) { + return (TextureElement) state.getElement(index); + } + public static void enable(State defaultState) { + TextureElement tmp = new TextureElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The actual Texture object + protected Texture texture; + // The texture environment mode + protected int texEnvMode; + + /** Sets the texture and environment mode in the given state. */ + public static void set(State state, Texture texture, int texEnvMode) { + getInstance(state).setElt(texture, texEnvMode); + } + + /** Returns the current texture in the state. */ + public static Texture get(State state) { + return getInstance(state).texture; + } + + /** Returns the texture environment mode in the state. */ + public static int getEnvMode(State state) { + return getInstance(state).texEnvMode; + } + + public void push(State state) { + TextureElement prev = (TextureElement) getNextInStack(); + if (prev != null) { + // Pull down the texture from the previous element + texture = prev.texture; + } + } + + /** Sets the texture and environment mode in this element. */ + public void setElt(Texture texture, int texEnvMode) { + this.texture = texture; + this.texEnvMode = texEnvMode; + } +} diff --git a/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java b/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java new file mode 100644 index 0000000..5142678 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/ViewingMatrixElement.java @@ -0,0 +1,93 @@ +/* + * 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.elements; + +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; + +/** Represents the viewing matrix, which contains the transformation + between the camera and the model. */ + +public class ViewingMatrixElement extends Element { + // Boilerplate + private static StateIndex index = State.registerElementType(); + public StateIndex getStateIndex() { return index; } + public Element newInstance() { + return new ViewingMatrixElement(); + } + public static ViewingMatrixElement getInstance(State state) { + return (ViewingMatrixElement) state.getElement(index); + } + public static void enable(State defaultState) { + Element tmp = new ViewingMatrixElement(); + defaultState.setElement(tmp.getStateIndex(), tmp); + } + + // The matrix data + protected Mat4f matrix; + + public ViewingMatrixElement() { + matrix = new Mat4f(); + matrix.makeIdent(); + } + + /** Returns the current viewing matrix; callers should not mutate + this directly but instead use the accessor methods to change + it. */ + public Mat4f getMatrix() { + return matrix; + } + + public void push(State state) { + ViewingMatrixElement prev = (ViewingMatrixElement) getNextInStack(); + if (prev != null) { + matrix.set(prev.matrix); + } + } + + /** Sets the viewing matrix in the given state to the given one. */ + public static void set(State state, Mat4f matrix) { + ViewingMatrixElement elt = getInstance(state); + elt.setElt(matrix); + } + + /** Sets the viewing matrix in this element to the given one. */ + public void setElt(Mat4f matrix) { + this.matrix.set(matrix); + } +} diff --git a/src/net/java/joglutils/msg/elements/package.html b/src/net/java/joglutils/msg/elements/package.html new file mode 100644 index 0000000..870e605 --- /dev/null +++ b/src/net/java/joglutils/msg/elements/package.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +Elements of the global state affected by actions' traversal of +nodes. Only developers of the library will typically have to interact +with the classes in this package. + +<P> + +In similar fashion to Open Inventor, each element in this package is +typically partitioned into two classes, one which holds the storage +for the element and one which implements the OpenGL side-effects. This +organization allows certain actions to traverse the scene graph +without requiring an OpenGL context to be current. + +</body> +</html> diff --git a/src/net/java/joglutils/msg/impl/BufferFactory.java b/src/net/java/joglutils/msg/impl/BufferFactory.java new file mode 100644 index 0000000..191c5c7 --- /dev/null +++ b/src/net/java/joglutils/msg/impl/BufferFactory.java @@ -0,0 +1,139 @@ +/* + * 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 java.nio.*; +import java.util.*; +import com.sun.opengl.util.*; + +/** Assists in allocation of direct Buffers. On some platforms when a + small direct Buffer is allocated there is a large amount of + rounding up which occurs. This BufferFactory allocates direct + Buffers in chunks and hands out slices of those chunks to + clients. */ + +public class BufferFactory { + private static ByteBuffer curByteBuf; + private static ShortBuffer curShortBuf; + private static IntBuffer curIntBuf; + private static FloatBuffer curFloatBuf; + private static DoubleBuffer curDoubleBuf; + + // I believe the rounding-up size of direct Buffers on Unix platforms is 8K + private static final int CHUNK_SIZE = 8 * 1024; + + public static synchronized ByteBuffer newByteBuffer(int numElements) { + int sz = numElements * BufferUtil.SIZEOF_BYTE; + if (sz > CHUNK_SIZE) { + // Just allocate a fresh ByteBuffer and don't worry about + // rounding up its allocation size and re-using the end portion + return BufferUtil.newByteBuffer(numElements); + } + if (curByteBuf == null || curByteBuf.remaining() < numElements) { + curByteBuf = BufferUtil.newByteBuffer(CHUNK_SIZE / BufferUtil.SIZEOF_BYTE); + } + curByteBuf.limit(curByteBuf.position() + numElements); + ByteBuffer res = curByteBuf.slice(); + curByteBuf.position(curByteBuf.limit()); + return res; + } + + public static synchronized ShortBuffer newShortBuffer(int numElements) { + int sz = numElements * BufferUtil.SIZEOF_SHORT; + if (sz > CHUNK_SIZE) { + // Just allocate a fresh ShortBuffer and don't worry about + // rounding up its allocation size and re-using the end portion + return BufferUtil.newShortBuffer(numElements); + } + if (curShortBuf == null || curShortBuf.remaining() < numElements) { + curShortBuf = BufferUtil.newShortBuffer(CHUNK_SIZE / BufferUtil.SIZEOF_SHORT); + } + curShortBuf.limit(curShortBuf.position() + numElements); + ShortBuffer res = curShortBuf.slice(); + curShortBuf.position(curShortBuf.limit()); + return res; + } + + public static synchronized IntBuffer newIntBuffer(int numElements) { + int sz = numElements * BufferUtil.SIZEOF_INT; + if (sz > CHUNK_SIZE) { + // Just allocate a fresh IntBuffer and don't worry about + // rounding up its allocation size and re-using the end portion + return BufferUtil.newIntBuffer(numElements); + } + if (curIntBuf == null || curIntBuf.remaining() < numElements) { + curIntBuf = BufferUtil.newIntBuffer(CHUNK_SIZE / BufferUtil.SIZEOF_INT); + } + curIntBuf.limit(curIntBuf.position() + numElements); + IntBuffer res = curIntBuf.slice(); + curIntBuf.position(curIntBuf.limit()); + return res; + } + + public static synchronized FloatBuffer newFloatBuffer(int numElements) { + int sz = numElements * BufferUtil.SIZEOF_FLOAT; + if (sz > CHUNK_SIZE) { + // Just allocate a fresh FloatBuffer and don't worry about + // rounding up its allocation size and re-using the end portion + return BufferUtil.newFloatBuffer(numElements); + } + if (curFloatBuf == null || curFloatBuf.remaining() < numElements) { + curFloatBuf = BufferUtil.newFloatBuffer(CHUNK_SIZE / BufferUtil.SIZEOF_FLOAT); + } + curFloatBuf.limit(curFloatBuf.position() + numElements); + FloatBuffer res = curFloatBuf.slice(); + curFloatBuf.position(curFloatBuf.limit()); + return res; + } + + public static synchronized DoubleBuffer newDoubleBuffer(int numElements) { + int sz = numElements * BufferUtil.SIZEOF_DOUBLE; + if (sz > CHUNK_SIZE) { + // Just allocate a fresh DoubleBuffer and don't worry about + // rounding up its allocation size and re-using the end portion + return BufferUtil.newDoubleBuffer(numElements); + } + if (curDoubleBuf == null || curDoubleBuf.remaining() < numElements) { + curDoubleBuf = BufferUtil.newDoubleBuffer(CHUNK_SIZE / BufferUtil.SIZEOF_DOUBLE); + } + curDoubleBuf.limit(curDoubleBuf.position() + numElements); + DoubleBuffer res = curDoubleBuf.slice(); + curDoubleBuf.position(curDoubleBuf.limit()); + return res; + } +} diff --git a/src/net/java/joglutils/msg/math/Box3f.java b/src/net/java/joglutils/msg/math/Box3f.java new file mode 100644 index 0000000..1dafd7c --- /dev/null +++ b/src/net/java/joglutils/msg/math/Box3f.java @@ -0,0 +1,82 @@ +/* + * 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.math; + +/** Represents an axis-aligned box in 3D space. */ + +public class Box3f { + private Vec3f min = new Vec3f(); + private Vec3f max = new Vec3f(); + + public Box3f() {} + + public Box3f(Vec3f min, Vec3f max) { + setMin(min); + setMax(max); + } + + public void setMin(Vec3f min) { this.min.set(min); } + public Vec3f getMin() { return min; } + + public void setMax(Vec3f max) { this.max.set(max); } + public Vec3f getMax() { return max; } + + public Vec3f getCenter() { + return new Vec3f(0.5f * (min.x() + max.x()), + 0.5f * (min.y() + max.y()), + 0.5f * (min.z() + max.z())); + } + + public void extendBy(Vec3f point) { + if (point.x() < min.x()) min.setX(point.x()); + if (point.y() < min.y()) min.setY(point.y()); + if (point.z() < min.z()) min.setZ(point.z()); + if (point.x() > max.x()) max.setX(point.x()); + if (point.y() > max.y()) max.setY(point.y()); + if (point.z() > max.z()) max.setZ(point.z()); + } + + public void extendBy(Box3f box) { + if (box.min.x() < min.x()) min.setX(box.min.x()); + if (box.min.y() < min.y()) min.setY(box.min.y()); + if (box.min.z() < min.z()) min.setZ(box.min.z()); + if (box.max.x() > max.x()) max.setX(box.max.x()); + if (box.max.y() > max.y()) max.setY(box.max.y()); + if (box.max.z() > max.z()) max.setZ(box.max.z()); + } +} diff --git a/src/net/java/joglutils/msg/math/DimensionMismatchException.java b/src/net/java/joglutils/msg/math/DimensionMismatchException.java new file mode 100644 index 0000000..a29c6c9 --- /dev/null +++ b/src/net/java/joglutils/msg/math/DimensionMismatchException.java @@ -0,0 +1,51 @@ +/* + * 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.math; + +/** Thrown to indicate a mismatch of dimensionality of a matrix or + vector. */ + +public class DimensionMismatchException extends RuntimeException { + public DimensionMismatchException() { + super(); + } + + public DimensionMismatchException(String msg) { + super(msg); + } +} diff --git a/src/net/java/joglutils/msg/math/IntersectionPoint.java b/src/net/java/joglutils/msg/math/IntersectionPoint.java new file mode 100644 index 0000000..5a76312 --- /dev/null +++ b/src/net/java/joglutils/msg/math/IntersectionPoint.java @@ -0,0 +1,61 @@ +/* + * 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.math; + +/** Wraps a 3D point and parametric time value. */ + +public class IntersectionPoint { + private Vec3f intPt = new Vec3f(); + private float t; + + public Vec3f getIntersectionPoint() { + return intPt; + } + + public void setIntersectionPoint(Vec3f newPt) { + intPt.set(newPt); + } + + public float getT() { + return t; + } + + public void setT(float t) { + this.t = t; + } +} diff --git a/src/net/java/joglutils/msg/math/Line.java b/src/net/java/joglutils/msg/math/Line.java new file mode 100644 index 0000000..2004c08 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Line.java @@ -0,0 +1,150 @@ +/* + * 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.math; + +/** Represents a line in 3D space. */ + +public class Line { + private Vec3f point; + /** Normalized */ + private Vec3f direction; + /** For computing projections along line */ + private Vec3f alongVec; + + /** Default constructor initializes line to point (0, 0, 0) and + direction (1, 0, 0) */ + public Line() { + point = new Vec3f(0, 0, 0); + direction = new Vec3f(1, 0, 0); + alongVec = new Vec3f(); + recalc(); + } + + /** Line goes in direction <b>direction</b> through the point + <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); + alongVec = new Vec3f(); + recalc(); + } + + /** Setter does some work to maintain internal caches. + <b>direction</b> does not need to be normalized but must not be + the zero vector. */ + public void setDirection(Vec3f direction) { + this.direction.set(direction); + this.direction.normalize(); + recalc(); + } + + /** Direction is normalized internally, so <b>direction</b> is not + necessarily equal to <code>plane.setDirection(direction); + plane.getDirection();</code> */ + public Vec3f getDirection() { + return direction; + } + + /** Setter does some work to maintain internal caches. */ + public void setPoint(Vec3f point) { + this.point.set(point); + recalc(); + } + + public Vec3f getPoint() { + return point; + } + + /** Project a point onto the line */ + public void projectPoint(Vec3f pt, + Vec3f projPt) { + float dotp = direction.dot(pt); + projPt.set(direction); + projPt.scale(dotp); + projPt.add(alongVec); + } + + /** Find closest point on this line to the given ray, specified by + start point and direction. If ray is parallel to this line, + returns false and closestPoint is not modified. */ + public boolean closestPointToRay(Vec3f rayStart, + Vec3f rayDirection, + Vec3f closestPoint) { + // Line 1 is this one. Line 2 is the incoming one. + Mat2f A = new Mat2f(); + A.set(0, 0, -direction.lengthSquared()); + A.set(1, 1, -rayDirection.lengthSquared()); + A.set(0, 1, direction.dot(rayDirection)); + A.set(1, 0, A.get(0, 1)); + if (Math.abs(A.determinant()) == 0.0f) { + return false; + } + if (!A.invert()) { + return false; + } + Vec2f b = new Vec2f(); + b.setX(point.dot(direction) - rayStart.dot(direction)); + b.setY(rayStart.dot(rayDirection) - point.dot(rayDirection)); + Vec2f x = new Vec2f(); + A.xformVec(b, x); + if (x.y() < 0) { + // Means that ray start is closest point to this line + closestPoint.set(rayStart); + } else { + closestPoint.set(direction); + closestPoint.scale(x.x()); + closestPoint.add(point); + } + return true; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void recalc() { + float denom = direction.lengthSquared(); + if (denom == 0.0f) { + throw new RuntimeException("Line.recalc: ERROR: direction was the zero vector " + + "(not allowed)"); + } + alongVec.set(point.minus(direction.times(point.dot(direction)))); + } +} diff --git a/src/net/java/joglutils/msg/math/Mat2f.java b/src/net/java/joglutils/msg/math/Mat2f.java new file mode 100644 index 0000000..80e8131 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Mat2f.java @@ -0,0 +1,167 @@ +/* + * 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.math; + +/** 2x2 matrix class useful for simple linear algebra. Representation + is (as Mat4f) in row major order and assumes multiplication by + column vectors on the right. */ + +public class Mat2f { + private float[] data; + + /** Creates new matrix initialized to the zero matrix */ + public Mat2f() { + data = new float[4]; + } + + /** Initialize to the identity matrix. */ + public void makeIdent() { + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + if (i == j) { + set(i, j, 1.0f); + } else { + set(i, j, 0.0f); + } + } + } + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[2 * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[2 * i + j] = val; + } + + /** Set column i (i=[0..1]) to vector v. */ + public void setCol(int i, Vec2f v) { + set(0, i, v.x()); + set(1, i, v.y()); + } + + /** Set row i (i=[0..1]) to vector v. */ + public void setRow(int i, Vec2f v) { + set(i, 0, v.x()); + set(i, 1, v.y()); + } + + /** Transpose this matrix in place. */ + public void transpose() { + float t = get(0, 1); + set(0, 1, get(1, 0)); + set(1, 0, t); + } + + /** Return the determinant. */ + public float determinant() { + return (get(0, 0) * get(1, 1) - get(1, 0) * get(0, 1)); + } + + /** Full matrix inversion in place. If matrix is singular, returns + false and matrix contents are untouched. If you know the matrix + is orthonormal, you can call transpose() instead. */ + public boolean invert() { + float det = determinant(); + if (det == 0.0f) + return false; + + // Create transpose of cofactor matrix in place + float t = get(0, 0); + set(0, 0, get(1, 1)); + set(1, 1, t); + set(0, 1, -get(0, 1)); + set(1, 0, -get(1, 0)); + + // Now divide by determinant + for (int i = 0; i < 4; i++) { + data[i] /= det; + } + return true; + } + + /** Multiply a 2D vector by this matrix. NOTE: src and dest must be + different vectors. */ + public void xformVec(Vec2f src, Vec2f dest) { + dest.set(get(0, 0) * src.x() + + get(0, 1) * src.y(), + + get(1, 0) * src.x() + + get(1, 1) * src.y()); + } + + /** Returns this * b; creates new matrix */ + public Mat2f mul(Mat2f b) { + Mat2f tmp = new Mat2f(); + tmp.mul(this, b); + return tmp; + } + + /** this = a * b */ + public void mul(Mat2f a, Mat2f b) { + for (int rc = 0; rc < 2; rc++) + for (int cc = 0; cc < 2; cc++) { + float tmp = 0.0f; + for (int i = 0; i < 2; i++) + tmp += a.get(rc, i) * b.get(i, cc); + set(rc, cc, tmp); + } + } + + public Matf toMatf() { + Matf out = new Matf(2, 2); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + out.set(i, j, get(i, j)); + } + } + return out; + } + + public String toString() { + String endl = System.getProperty("line.separator"); + return "(" + + get(0, 0) + ", " + get(0, 1) + endl + + get(1, 0) + ", " + get(1, 1) + ")"; + } +} diff --git a/src/net/java/joglutils/msg/math/Mat3f.java b/src/net/java/joglutils/msg/math/Mat3f.java new file mode 100644 index 0000000..976699f --- /dev/null +++ b/src/net/java/joglutils/msg/math/Mat3f.java @@ -0,0 +1,191 @@ +/* + * 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.math; + +/** 3x3 matrix class useful for simple linear algebra. Representation + is (as Mat4f) in row major order and assumes multiplication by + column vectors on the right. */ + +public class Mat3f { + private float[] data; + + /** Creates new matrix initialized to the zero matrix */ + public Mat3f() { + data = new float[9]; + } + + /** Initialize to the identity matrix. */ + public void makeIdent() { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (i == j) { + set(i, j, 1.0f); + } else { + set(i, j, 0.0f); + } + } + } + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[3 * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[3 * i + j] = val; + } + + /** Set column i (i=[0..2]) to vector v. */ + public void setCol(int i, Vec3f v) { + set(0, i, v.x()); + set(1, i, v.y()); + set(2, i, v.z()); + } + + /** Set row i (i=[0..2]) to vector v. */ + public void setRow(int i, Vec3f v) { + set(i, 0, v.x()); + set(i, 1, v.y()); + set(i, 2, v.z()); + } + + /** Transpose this matrix in place. */ + public void transpose() { + float t; + t = get(0, 1); + set(0, 1, get(1, 0)); + set(1, 0, t); + + t = get(0, 2); + set(0, 2, get(2, 0)); + set(2, 0, t); + + t = get(1, 2); + set(1, 2, get(2, 1)); + set(2, 1, t); + } + + /** Return the determinant. Computed across the zeroth row. */ + public float determinant() { + return (get(0, 0) * (get(1, 1) * get(2, 2) - get(2, 1) * get(1, 2)) + + get(0, 1) * (get(2, 0) * get(1, 2) - get(1, 0) * get(2, 2)) + + get(0, 2) * (get(1, 0) * get(2, 1) - get(2, 0) * get(1, 1))); + } + + /** Full matrix inversion in place. If matrix is singular, throws + SingularMatrixException. If you know the matrix is orthonormal, + you can call transpose() instead. */ + public void invert() throws SingularMatrixException { + float det = determinant(); + if (det == 0.0f) + throw new SingularMatrixException(); + + // Form cofactor matrix + Mat3f cf = new Mat3f(); + cf.set(0, 0, get(1, 1) * get(2, 2) - get(2, 1) * get(1, 2)); + cf.set(0, 1, get(2, 0) * get(1, 2) - get(1, 0) * get(2, 2)); + cf.set(0, 2, get(1, 0) * get(2, 1) - get(2, 0) * get(1, 1)); + cf.set(1, 0, get(2, 1) * get(0, 2) - get(0, 1) * get(2, 2)); + cf.set(1, 1, get(0, 0) * get(2, 2) - get(2, 0) * get(0, 2)); + cf.set(1, 2, get(2, 0) * get(0, 1) - get(0, 0) * get(2, 1)); + cf.set(2, 0, get(0, 1) * get(1, 2) - get(1, 1) * get(0, 2)); + cf.set(2, 1, get(1, 0) * get(0, 2) - get(0, 0) * get(1, 2)); + cf.set(2, 2, get(0, 0) * get(1, 1) - get(1, 0) * get(0, 1)); + + // Now copy back transposed + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + set(i, j, cf.get(j, i) / det); + } + + /** Multiply a 3D vector by this matrix. NOTE: src and dest must be + different vectors. */ + public void xformVec(Vec3f src, Vec3f dest) { + dest.set(get(0, 0) * src.x() + + get(0, 1) * src.y() + + get(0, 2) * src.z(), + + get(1, 0) * src.x() + + get(1, 1) * src.y() + + get(1, 2) * src.z(), + + get(2, 0) * src.x() + + get(2, 1) * src.y() + + get(2, 2) * src.z()); + } + + /** Returns this * b; creates new matrix */ + public Mat3f mul(Mat3f b) { + Mat3f tmp = new Mat3f(); + tmp.mul(this, b); + return tmp; + } + + /** this = a * b */ + public void mul(Mat3f a, Mat3f b) { + for (int rc = 0; rc < 3; rc++) + for (int cc = 0; cc < 3; cc++) { + float tmp = 0.0f; + for (int i = 0; i < 3; i++) + tmp += a.get(rc, i) * b.get(i, cc); + set(rc, cc, tmp); + } + } + + public Matf toMatf() { + Matf out = new Matf(3, 3); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + out.set(i, j, get(i, j)); + } + } + return out; + } + + public String toString() { + String endl = System.getProperty("line.separator"); + return "(" + + get(0, 0) + ", " + get(0, 1) + ", " + get(0, 2) + endl + + get(1, 0) + ", " + get(1, 1) + ", " + get(1, 2) + endl + + get(2, 0) + ", " + get(2, 1) + ", " + get(2, 2) + ")"; + } +} diff --git a/src/net/java/joglutils/msg/math/Mat4f.java b/src/net/java/joglutils/msg/math/Mat4f.java new file mode 100644 index 0000000..b0cc67e --- /dev/null +++ b/src/net/java/joglutils/msg/math/Mat4f.java @@ -0,0 +1,574 @@ +/* + * 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.math; + +/** A (very incomplete) 4x4 matrix class. Representation assumes + row-major order and multiplication by column vectors on the + right. */ + +public class Mat4f { + private float[] data; + + /** Creates new matrix initialized to the zero matrix */ + public Mat4f() { + data = new float[16]; + } + + /** Creates new matrix initialized to argument's contents */ + public Mat4f(Mat4f arg) { + this(); + set(arg); + } + + /** Sets this matrix to the identity matrix */ + public void makeIdent() { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (i == j) { + set(i, j, 1.0f); + } else { + set(i, j, 0.0f); + } + } + } + } + + /** Sets this matrix to be equivalent to the given one */ + public void set(Mat4f arg) { + float[] mine = data; + float[] yours = arg.data; + for (int i = 0; i < mine.length; i++) { + mine[i] = yours[i]; + } + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[4 * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[4 * i + j] = val; + } + + /** Sets the translation component of this matrix (i.e., the three + top elements of the third column) without touching any of the + other parts of the matrix */ + public void setTranslation(Vec3f trans) { + set(0, 3, trans.x()); + set(1, 3, trans.y()); + set(2, 3, trans.z()); + } + + /** Sets the rotation component of this matrix (i.e., the upper left + 3x3) without touching any of the other parts of the matrix */ + public void setRotation(Rotf rot) { + rot.toMatrix(this); + } + + /** Sets the upper-left 3x3 of this matrix assuming that the given + x, y, and z vectors form an orthonormal basis */ + public void setRotation(Vec3f x, Vec3f y, Vec3f z) { + set(0, 0, x.x()); + set(1, 0, x.y()); + set(2, 0, x.z()); + + set(0, 1, y.x()); + set(1, 1, y.y()); + set(2, 1, y.z()); + + set(0, 2, z.x()); + set(1, 2, z.y()); + set(2, 2, z.z()); + } + + /** Gets the upper left 3x3 of this matrix as a rotation. Currently + does not work if there are scales. Ignores translation + component. */ + public void getRotation(Rotf rot) { + rot.fromMatrix(this); + } + + /** Sets the elements (0, 0), (1, 1), and (2, 2) with the + appropriate elements of the given three-dimensional scale + vector. Does not perform a full multiplication of the upper-left + 3x3; use this with an identity matrix in conjunction with + <code>mul</code> for that. */ + public void setScale(Vec3f scale) { + set(0, 0, scale.x()); + set(1, 1, scale.y()); + set(2, 2, scale.z()); + } + + /** Inverts this matrix assuming that it represents a rigid + transform (i.e., some combination of rotations and + translations). Assumes column vectors. Algorithm: transposes + upper left 3x3; negates translation in rightmost column and + transforms by inverted rotation. */ + public void invertRigid() { + float t; + // Transpose upper left 3x3 + t = get(0, 1); + set(0, 1, get(1, 0)); + set(1, 0, t); + t = get(0, 2); + set(0, 2, get(2, 0)); + set(2, 0, t); + t = get(1, 2); + set(1, 2, get(2, 1)); + set(2, 1, t); + // Transform negative translation by this + Vec3f negTrans = new Vec3f(-get(0, 3), -get(1, 3), -get(2, 3)); + Vec3f trans = new Vec3f(); + xformDir(negTrans, trans); + set(0, 3, trans.x()); + set(1, 3, trans.y()); + set(2, 3, trans.z()); + } + + /** Performs general 4x4 matrix inversion. + @throws SingularMatrixException if this matrix is singular (i.e., non-invertible) + */ + public void invert() throws SingularMatrixException { + invertGeneral(this); + } + + /** Returns this * b; creates new matrix */ + public Mat4f mul(Mat4f b) { + Mat4f tmp = new Mat4f(); + tmp.mul(this, b); + return tmp; + } + + /** this = a * b */ + public void mul(Mat4f a, Mat4f b) { + for (int rc = 0; rc < 4; rc++) + for (int cc = 0; cc < 4; cc++) { + float tmp = 0.0f; + for (int i = 0; i < 4; i++) + tmp += a.get(rc, i) * b.get(i, cc); + set(rc, cc, tmp); + } + } + + /** Transpose this matrix in place. */ + public void transpose() { + float t; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < i; j++) { + t = get(i, j); + set(i, j, get(j, i)); + set(j, i, t); + } + } + } + + /** Multiply a 4D vector by this matrix. NOTE: src and dest must be + different vectors. */ + public void xformVec(Vec4f src, Vec4f dest) { + for (int rc = 0; rc < 4; rc++) { + float tmp = 0.0f; + for (int cc = 0; cc < 4; cc++) { + tmp += get(rc, cc) * src.get(cc); + } + dest.set(rc, tmp); + } + } + + /** Transforms a 3D vector as though it had a homogeneous coordinate + and assuming that this matrix represents only rigid + transformations; i.e., is not a full transformation. NOTE: src + and dest must be different vectors. */ + public void xformPt(Vec3f src, Vec3f dest) { + for (int rc = 0; rc < 3; rc++) { + float tmp = 0.0f; + for (int cc = 0; cc < 3; cc++) { + tmp += get(rc, cc) * src.get(cc); + } + tmp += get(rc, 3); + dest.set(rc, tmp); + } + } + + /** Transforms src using only the upper left 3x3. NOTE: src and dest + must be different vectors. */ + public void xformDir(Vec3f src, Vec3f dest) { + for (int rc = 0; rc < 3; rc++) { + float tmp = 0.0f; + for (int cc = 0; cc < 3; cc++) { + tmp += get(rc, cc) * src.get(cc); + } + dest.set(rc, tmp); + } + } + + /** Copies data in column-major (OpenGL format) order into passed + float array, which must have length 16 or greater. */ + public void getColumnMajorData(float[] out) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + out[4 * j + i] = get(i, j); + } + } + } + + /** Returns the matrix data in row-major format, which is the + opposite of OpenGL's convention. */ + public float[] getRowMajorData() { + return data; + } + + public Matf toMatf() { + Matf out = new Matf(4, 4); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + out.set(i, j, get(i, j)); + } + } + return out; + } + + public String toString() { + String endl = System.getProperty("line.separator"); + return "(" + + get(0, 0) + ", " + get(0, 1) + ", " + get(0, 2) + ", " + get(0, 3) + endl + + get(1, 0) + ", " + get(1, 1) + ", " + get(1, 2) + ", " + get(1, 3) + endl + + get(2, 0) + ", " + get(2, 1) + ", " + get(2, 2) + ", " + get(2, 3) + endl + + get(3, 0) + ", " + get(3, 1) + ", " + get(3, 2) + ", " + get(3, 3) + ")"; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // The following code was borrowed from Java 3D's vecmath implementation + + private void invertGeneral(Mat4f m1) { + double temp[] = new double[16]; + double result[] = new double[16]; + int row_perm[] = new int[4]; + int i, r, c; + + // Use LU decomposition and backsubstitution code specifically + // for floating-point 4x4 matrices. + + // Copy source matrix to t1tmp + temp[0] = m1.get(0, 0); + temp[1] = m1.get(0, 1); + temp[2] = m1.get(0, 2); + temp[3] = m1.get(0, 3); + + temp[4] = m1.get(1, 0); + temp[5] = m1.get(1, 1); + temp[6] = m1.get(1, 2); + temp[7] = m1.get(1, 3); + + temp[8] = m1.get(2, 0); + temp[9] = m1.get(2, 1); + temp[10] = m1.get(2, 2); + temp[11] = m1.get(2, 3); + + temp[12] = m1.get(3, 0); + temp[13] = m1.get(3, 1); + temp[14] = m1.get(3, 2); + temp[15] = m1.get(3, 3); + + // Calculate LU decomposition: Is the matrix singular? + if (!luDecomposition(temp, row_perm)) { + // Matrix has no inverse + throw new SingularMatrixException(); + } + + // Perform back substitution on the identity matrix + for(i=0;i<16;i++) result[i] = 0.0; + result[0] = 1.0; result[5] = 1.0; result[10] = 1.0; result[15] = 1.0; + luBacksubstitution(temp, row_perm, result); + + set(0, 0, (float)result[0]); + set(0, 1, (float)result[1]); + set(0, 2, (float)result[2]); + set(0, 3, (float)result[3]); + + set(1, 0, (float)result[4]); + set(1, 1, (float)result[5]); + set(1, 2, (float)result[6]); + set(1, 3, (float)result[7]); + + set(2, 0, (float)result[8]); + set(2, 1, (float)result[9]); + set(2, 2, (float)result[10]); + set(2, 3, (float)result[11]); + + set(3, 0, (float)result[12]); + set(3, 1, (float)result[13]); + set(3, 2, (float)result[14]); + set(3, 3, (float)result[15]); + } + + /** + * Given a 4x4 array "matrix0", this function replaces it with the + * LU decomposition of a row-wise permutation of itself. The input + * parameters are "matrix0" and "dimen". The array "matrix0" is also + * an output parameter. The vector "row_perm[4]" is an output + * parameter that contains the row permutations resulting from partial + * pivoting. The output parameter "even_row_xchg" is 1 when the + * number of row exchanges is even, or -1 otherwise. Assumes data + * type is always double. + * + * This function is similar to luDecomposition, except that it + * is tuned specifically for 4x4 matrices. + * + * @return true if the matrix is nonsingular, or false otherwise. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 40-45. + // + static boolean luDecomposition(double[] matrix0, + int[] row_perm) { + + double row_scale[] = new double[4]; + + // Determine implicit scaling information by looping over rows + { + int i, j; + int ptr, rs; + double big, temp; + + ptr = 0; + rs = 0; + + // For each row ... + i = 4; + while (i-- != 0) { + big = 0.0; + + // For each column, find the largest element in the row + j = 4; + while (j-- != 0) { + temp = matrix0[ptr++]; + temp = Math.abs(temp); + if (temp > big) { + big = temp; + } + } + + // Is the matrix singular? + if (big == 0.0) { + return false; + } + row_scale[rs++] = 1.0 / big; + } + } + + { + int j; + int mtx; + + mtx = 0; + + // For all columns, execute Crout's method + for (j = 0; j < 4; j++) { + int i, imax, k; + int target, p1, p2; + double sum, big, temp; + + // Determine elements of upper diagonal matrix U + for (i = 0; i < j; i++) { + target = mtx + (4*i) + j; + sum = matrix0[target]; + k = i; + p1 = mtx + (4*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 4; + } + matrix0[target] = sum; + } + + // Search for largest pivot element and calculate + // intermediate elements of lower diagonal matrix L. + big = 0.0; + imax = -1; + for (i = j; i < 4; i++) { + target = mtx + (4*i) + j; + sum = matrix0[target]; + k = j; + p1 = mtx + (4*i); + p2 = mtx + j; + while (k-- != 0) { + sum -= matrix0[p1] * matrix0[p2]; + p1++; + p2 += 4; + } + matrix0[target] = sum; + + // Is this the best pivot so far? + if ((temp = row_scale[i] * Math.abs(sum)) >= big) { + big = temp; + imax = i; + } + } + + if (imax < 0) { + throw new RuntimeException("Logic error: imax < 0"); + } + + // Is a row exchange necessary? + if (j != imax) { + // Yes: exchange rows + k = 4; + p1 = mtx + (4*imax); + p2 = mtx + (4*j); + while (k-- != 0) { + temp = matrix0[p1]; + matrix0[p1++] = matrix0[p2]; + matrix0[p2++] = temp; + } + + // Record change in scale factor + row_scale[imax] = row_scale[j]; + } + + // Record row permutation + row_perm[j] = imax; + + // Is the matrix singular + if (matrix0[(mtx + (4*j) + j)] == 0.0) { + return false; + } + + // Divide elements of lower diagonal matrix L by pivot + if (j != (4-1)) { + temp = 1.0 / (matrix0[(mtx + (4*j) + j)]); + target = mtx + (4*(j+1)) + j; + i = 3 - j; + while (i-- != 0) { + matrix0[target] *= temp; + target += 4; + } + } + } + } + + return true; + } + + /** + * Solves a set of linear equations. The input parameters "matrix1", + * and "row_perm" come from luDecompostionD4x4 and do not change + * here. The parameter "matrix2" is a set of column vectors assembled + * into a 4x4 matrix of floating-point values. The procedure takes each + * column of "matrix2" in turn and treats it as the right-hand side of the + * matrix equation Ax = LUx = b. The solution vector replaces the + * original column of the matrix. + * + * If "matrix2" is the identity matrix, the procedure replaces its contents + * with the inverse of the matrix from which "matrix1" was originally + * derived. + */ + // + // Reference: Press, Flannery, Teukolsky, Vetterling, + // _Numerical_Recipes_in_C_, Cambridge University Press, + // 1988, pp 44-45. + // + static void luBacksubstitution(double[] matrix1, + int[] row_perm, + double[] matrix2) { + + int i, ii, ip, j, k; + int rp; + int cv, rv; + + // rp = row_perm; + rp = 0; + + // For each column vector of matrix2 ... + for (k = 0; k < 4; k++) { + // cv = &(matrix2[0][k]); + cv = k; + ii = -1; + + // Forward substitution + for (i = 0; i < 4; i++) { + double sum; + + ip = row_perm[rp+i]; + sum = matrix2[cv+4*ip]; + matrix2[cv+4*ip] = matrix2[cv+4*i]; + if (ii >= 0) { + // rv = &(matrix1[i][0]); + rv = i*4; + for (j = ii; j <= i-1; j++) { + sum -= matrix1[rv+j] * matrix2[cv+4*j]; + } + } + else if (sum != 0.0) { + ii = i; + } + matrix2[cv+4*i] = sum; + } + + // Backsubstitution + // rv = &(matrix1[3][0]); + rv = 3*4; + matrix2[cv+4*3] /= matrix1[rv+3]; + + rv -= 4; + matrix2[cv+4*2] = (matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+2]; + + rv -= 4; + matrix2[cv+4*1] = (matrix2[cv+4*1] - + matrix1[rv+2] * matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+1]; + + rv -= 4; + matrix2[cv+4*0] = (matrix2[cv+4*0] - + matrix1[rv+1] * matrix2[cv+4*1] - + matrix1[rv+2] * matrix2[cv+4*2] - + matrix1[rv+3] * matrix2[cv+4*3]) / matrix1[rv+0]; + } + } +} diff --git a/src/net/java/joglutils/msg/math/Matf.java b/src/net/java/joglutils/msg/math/Matf.java new file mode 100644 index 0000000..483e246 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Matf.java @@ -0,0 +1,166 @@ +/* + * 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.math; + +/** Arbitrary-size single-precision matrix class. Currently very + simple and only supports a few needed operations. */ + +public class Matf { + private float[] data; + private int nCol; // number of columns + private int nRow; // number of columns + + public Matf(int nRow, int nCol) { + data = new float[nRow * nCol]; + this.nCol = nCol; + this.nRow = nRow; + } + + public Matf(Matf arg) { + nRow = arg.nRow; + nCol = arg.nCol; + data = new float[nRow * nCol]; + System.arraycopy(arg.data, 0, data, 0, data.length); + } + + public int nRow() { + return nRow; + } + + public int nCol() { + return nCol; + } + + /** Gets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public float get(int i, int j) { + return data[nCol * i + j]; + } + + /** Sets the (i,j)th element of this matrix, where i is the row + index and j is the column index */ + public void set(int i, int j, float val) { + data[nCol * i + j] = val; + } + + /** Returns transpose of this matrix; creates new matrix */ + public Matf transpose() { + Matf tmp = new Matf(nCol, nRow); + for (int i = 0; i < nRow; i++) { + for (int j = 0; j < nCol; j++) { + tmp.set(j, i, get(i, j)); + } + } + return tmp; + } + + /** Returns this * b; creates new matrix */ + public Matf mul(Matf b) throws DimensionMismatchException { + if (nCol() != b.nRow()) + throw new DimensionMismatchException(); + Matf tmp = new Matf(nRow(), b.nCol()); + for (int i = 0; i < nRow(); i++) { + for (int j = 0; j < b.nCol(); j++) { + float val = 0; + for (int t = 0; t < nCol(); t++) { + val += get(i, t) * b.get(t, j); + } + tmp.set(i, j, val); + } + } + return tmp; + } + + /** Returns this * v, assuming v is a column vector. */ + public Vecf mul(Vecf v) throws DimensionMismatchException { + if (nCol() != v.length()) { + throw new DimensionMismatchException(); + } + Vecf out = new Vecf(nRow()); + for (int i = 0; i < nRow(); i++) { + float tmp = 0; + for (int j = 0; j < nCol(); j++) { + tmp += get(i, j) * v.get(j); + } + out.set(i, tmp); + } + return out; + } + + /** If this is a 2x2 matrix, returns it as a Mat2f. */ + public Mat2f toMat2f() throws DimensionMismatchException { + if (nRow() != 2 || nCol() != 2) { + throw new DimensionMismatchException(); + } + Mat2f tmp = new Mat2f(); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + tmp.set(i, j, get(i, j)); + } + } + return tmp; + } + + /** If this is a 3x3 matrix, returns it as a Mat3f. */ + public Mat3f toMat3f() throws DimensionMismatchException { + if (nRow() != 3 || nCol() != 3) { + throw new DimensionMismatchException(); + } + Mat3f tmp = new Mat3f(); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + tmp.set(i, j, get(i, j)); + } + } + return tmp; + } + + /** If this is a 4x4 matrix, returns it as a Mat4f. */ + public Mat4f toMat4f() throws DimensionMismatchException { + if (nRow() != 4 || nCol() != 4) { + throw new DimensionMismatchException(); + } + Mat4f tmp = new Mat4f(); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + tmp.set(i, j, get(i, j)); + } + } + return tmp; + } +} diff --git a/src/net/java/joglutils/msg/math/MathUtil.java b/src/net/java/joglutils/msg/math/MathUtil.java new file mode 100644 index 0000000..db115d2 --- /dev/null +++ b/src/net/java/joglutils/msg/math/MathUtil.java @@ -0,0 +1,88 @@ +/* + * 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.math; + +/** Utility math routines. */ + +public class MathUtil { + /** Makes an arbitrary vector perpendicular to <B>src</B> and + inserts it into <B>dest</B>. Returns false if the source vector + was equal to (0, 0, 0). */ + public static boolean makePerpendicular(Vec3f src, + Vec3f dest) { + if ((src.x() == 0.0f) && (src.y() == 0.0f) && (src.z() == 0.0f)) { + return false; + } + + if (src.x() != 0.0f) { + if (src.y() != 0.0f) { + dest.set(-src.y(), src.x(), 0.0f); + } else { + dest.set(-src.z(), 0.0f, src.x()); + } + } else { + dest.set(1.0f, 0.0f, 0.0f); + } + return true; + } + + /** Returns 1 if the sign of the given argument is positive; -1 if + negative; 0 if 0. */ + public static int sgn(float f) { + if (f > 0) { + return 1; + } else if (f < 0) { + return -1; + } + return 0; + } + + /** Clamps argument between min and max values. */ + public static float clamp(float val, float min, float max) { + if (val < min) return min; + if (val > max) return max; + return val; + } + + /** Clamps argument between min and max values. */ + public static int clamp(int val, int min, int max) { + if (val < min) return min; + if (val > max) return max; + return val; + } +} diff --git a/src/net/java/joglutils/msg/math/NonSquareMatrixException.java b/src/net/java/joglutils/msg/math/NonSquareMatrixException.java new file mode 100644 index 0000000..52a37af --- /dev/null +++ b/src/net/java/joglutils/msg/math/NonSquareMatrixException.java @@ -0,0 +1,51 @@ +/* + * 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.math; + +/** Thrown to indicate a non-square matrix during an operation + requiring one. */ + +public class NonSquareMatrixException extends RuntimeException { + public NonSquareMatrixException() { + super(); + } + + public NonSquareMatrixException(String msg) { + super(msg); + } +} diff --git a/src/net/java/joglutils/msg/math/Plane.java b/src/net/java/joglutils/msg/math/Plane.java new file mode 100644 index 0000000..7c34636 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Plane.java @@ -0,0 +1,119 @@ +/* + * 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.math; + +/** Represents a plane in 3D space. */ + +public class Plane { + /** Normalized */ + private Vec3f normal; + private Vec3f point; + /** Constant for faster projection and intersection */ + float c; + + /** Default constructor initializes normal to (0, 1, 0) and point to + (0, 0, 0) */ + public Plane() { + normal = new Vec3f(0, 1, 0); + point = new Vec3f(0, 0, 0); + recalc(); + } + + /** Sets all parameters of plane. Plane has normal <b>normal</b> and + goes through the point <b>point</b>. Normal does not need to be + unit length but must not be the zero vector. */ + public Plane(Vec3f normal, Vec3f point) { + this.normal = new Vec3f(normal); + this.normal.normalize(); + this.point = new Vec3f(point); + recalc(); + } + + /** Setter does some work to maintain internal caches. Normal does + not need to be unit length but must not be the zero vector. */ + public void setNormal(Vec3f normal) { + this.normal.set(normal); + this.normal.normalize(); + recalc(); + } + + /** Normal is normalized internally, so <b>normal</b> is not + necessarily equal to <code>plane.setNormal(normal); + plane.getNormal();</code> */ + public Vec3f getNormal() { + return normal; + } + + /** Setter does some work to maintain internal caches */ + public void setPoint(Vec3f point) { + this.point.set(point); + recalc(); + } + + public Vec3f getPoint() { + return point; + } + + /** Project a point onto the plane */ + public void projectPoint(Vec3f pt, + Vec3f projPt) { + float scale = normal.dot(pt) - c; + projPt.set(pt.minus(normal.times(normal.dot(point) - c))); + } + + /** Intersect a ray with the plane. Returns true if intersection occurred, false + otherwise. This is a two-sided ray cast. */ + public boolean intersectRay(Vec3f rayStart, + Vec3f rayDirection, + IntersectionPoint intPt) { + float denom = normal.dot(rayDirection); + if (denom == 0) + return false; + intPt.setT((c - normal.dot(rayStart)) / denom); + intPt.setIntersectionPoint(rayStart.plus(rayDirection.times(intPt.getT()))); + return true; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void recalc() { + c = normal.dot(point); + } +} diff --git a/src/net/java/joglutils/msg/math/PlaneUV.java b/src/net/java/joglutils/msg/math/PlaneUV.java new file mode 100644 index 0000000..5d3a8a2 --- /dev/null +++ b/src/net/java/joglutils/msg/math/PlaneUV.java @@ -0,0 +1,201 @@ +/* + * 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.math; + +/** This differs from the Plane class in that it maintains an origin + and orthonormal U, V axes in the plane so that it can project a 3D + point to a 2D one. U cross V = normal. U and V coordinates are + computed with respect to the origin. */ + +public class PlaneUV { + private Vec3f origin = new Vec3f(); + /** Normalized */ + private Vec3f normal = new Vec3f(); + private Vec3f uAxis = new Vec3f(); + private Vec3f vAxis = new Vec3f(); + + /** Default constructor initializes normal to (0, 1, 0), origin to + (0, 0, 0), U axis to (1, 0, 0) and V axis to (0, 0, -1). */ + public PlaneUV() { + setEverything(new Vec3f(0, 1, 0), + new Vec3f(0, 0, 0), + new Vec3f(1, 0, 0), + new Vec3f(0, 0, -1)); + } + + /** Takes normal vector and a point which the plane goes through + (which becomes the plane's "origin"). Normal does NOT have to be + normalized, but may not be zero vector. U and V axes are + initialized to arbitrary values. */ + public PlaneUV(Vec3f normal, Vec3f origin) { + setOrigin(origin); + setNormal(normal); + } + + /** Takes normal vector, point which plane goes through, and the "u" + axis in the plane. Computes the "v" axis by taking the cross + product of the normal and the u axis. Axis must be perpendicular + to normal. Normal and uAxis do NOT have to be normalized, but + neither may be the zero vector. */ + public PlaneUV(Vec3f normal, + Vec3f origin, + Vec3f uAxis) { + setOrigin(origin); + setNormalAndU(normal, uAxis); + } + + /** Takes normal vector, point which plane goes through, and both + the u and v axes. u axis cross v axis = normal. Normal, uAxis, and + vAxis do NOT have to be normalized, but none may be the zero + vector. */ + public PlaneUV(Vec3f normal, + Vec3f origin, + Vec3f uAxis, + Vec3f vAxis) { + setEverything(normal, origin, uAxis, vAxis); + } + + /** Set the origin, through which this plane goes and with respect + to which U and V coordinates are computed */ + public void setOrigin(Vec3f origin) { + this.origin.set(origin); + } + + public Vec3f getOrigin() { + return new Vec3f(origin); + } + + /** Normal, U and V axes must be orthogonal and satisfy U cross V = + normal, do not need to be unit length but must not be the zero + vector. */ + public void setNormalAndUV(Vec3f normal, + Vec3f uAxis, + Vec3f vAxis) { + setEverything(normal, origin, uAxis, vAxis); + } + + /** This version sets the normal vector and generates new U and V + axes. */ + public void setNormal(Vec3f normal) { + Vec3f uAxis = new Vec3f(); + MathUtil.makePerpendicular(normal, uAxis); + Vec3f vAxis = normal.cross(uAxis); + setEverything(normal, origin, uAxis, vAxis); + } + + /** This version computes the V axis from (normal cross U). */ + public void setNormalAndU(Vec3f normal, + Vec3f uAxis) { + Vec3f vAxis = normal.cross(uAxis); + setEverything(normal, origin, uAxis, vAxis); + } + + /** Normal, U and V axes are normalized internally, so, for example, + <b>normal</b> is not necessarily equal to + <code>plane.setNormal(normal); plane.getNormal();</code> */ + public Vec3f getNormal() { + return normal; + } + + public Vec3f getUAxis() { + return uAxis; + } + + public Vec3f getVAxis() { + return vAxis; + } + + /** Project a point onto the plane */ + public void projectPoint(Vec3f point, + Vec3f projPt, + Vec2f uvCoords) { + // Using projPt as a temporary + projPt.sub(point, origin); + float dotp = normal.dot(projPt); + // Component perpendicular to plane + Vec3f tmpDir = new Vec3f(); + tmpDir.set(normal); + tmpDir.scale(dotp); + projPt.sub(projPt, tmpDir); + // Take dot products with basis vectors + uvCoords.set(projPt.dot(uAxis), + projPt.dot(vAxis)); + // Add on center to intersection point + projPt.add(origin); + } + + /** Intersect a ray with this plane, outputting not only the 3D + intersection point but also the U, V coordinates of the + intersection. Returns true if intersection occurred, false + otherwise. This is a two-sided ray cast. */ + public boolean intersectRay(Vec3f rayStart, + Vec3f rayDirection, + IntersectionPoint intPt, + Vec2f uvCoords) { + float denom = rayDirection.dot(normal); + if (denom == 0.0f) + return false; + Vec3f tmpDir = new Vec3f(); + tmpDir.sub(origin, rayStart); + float t = tmpDir.dot(normal) / denom; + // Find intersection point + Vec3f tmpPt = new Vec3f(); + tmpPt.set(rayDirection); + tmpPt.scale(t); + tmpPt.add(rayStart); + intPt.setIntersectionPoint(tmpPt); + intPt.setT(t); + // Find UV coords + tmpDir.sub(intPt.getIntersectionPoint(), origin); + uvCoords.set(tmpDir.dot(uAxis), tmpDir.dot(vAxis)); + return true; + } + + private void setEverything(Vec3f normal, + Vec3f origin, + Vec3f uAxis, + Vec3f vAxis) { + this.normal.set(normal); + this.origin.set(origin); + this.uAxis.set(uAxis); + this.vAxis.set(vAxis); + this.normal.normalize(); + this.uAxis.normalize(); + this.vAxis.normalize(); + } +} diff --git a/src/net/java/joglutils/msg/math/Rotf.java b/src/net/java/joglutils/msg/math/Rotf.java new file mode 100644 index 0000000..ed14a19 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Rotf.java @@ -0,0 +1,309 @@ +/* + * 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.math; + +/** Represents a rotation in 3D space with single-precision + components. Uses a quaternion as the internal representation. */ + +public class Rotf { + private static float EPSILON = 1.0e-7f; + + // Representation is a quaternion. Element 0 is the scalar part (= + // cos(theta/2)), elements 1..3 the imaginary/"vector" part (= + // sin(theta/2) * axis). + private float q0; + private float q1; + private float q2; + private float q3; + + /** Default constructor initializes to the identity quaternion */ + public Rotf() { + init(); + } + + public Rotf(Rotf arg) { + set(arg); + } + + /** Axis does not need to be normalized but must not be the zero + vector. Angle is in radians. */ + public Rotf(Vec3f axis, float angle) { + set(axis, angle); + } + + /** Creates a rotation which will rotate vector "from" into vector + "to". */ + public Rotf(Vec3f from, Vec3f to) { + set(from, to); + } + + /** Re-initialize this quaternion to be the identity quaternion "e" + (i.e., no rotation) */ + public void init() { + q0 = 1; + q1 = q2 = q3 = 0; + } + + /** Test for "approximate equality" -- performs componentwise test + to see whether difference between all components is less than + epsilon. */ + public boolean withinEpsilon(Rotf arg, float epsilon) { + return ((Math.abs(q0 - arg.q0) < epsilon) && + (Math.abs(q1 - arg.q1) < epsilon) && + (Math.abs(q2 - arg.q2) < epsilon) && + (Math.abs(q3 - arg.q3) < epsilon)); + } + + /** Axis does not need to be normalized but must not be the zero + vector. Angle is in radians. */ + public void set(Vec3f axis, float angle) { + float halfTheta = angle / 2.0f; + q0 = (float) Math.cos(halfTheta); + float sinHalfTheta = (float) Math.sin(halfTheta); + Vec3f realAxis = new Vec3f(axis); + realAxis.normalize(); + q1 = realAxis.x() * sinHalfTheta; + q2 = realAxis.y() * sinHalfTheta; + q3 = realAxis.z() * sinHalfTheta; + } + + /** Sets this rotation to the contents of the passed one. */ + public void set(Rotf arg) { + q0 = arg.q0; + q1 = arg.q1; + q2 = arg.q2; + q3 = arg.q3; + } + + /** Sets this rotation to that which will rotate vector "from" into + vector "to". from and to do not have to be the same length. */ + public void set(Vec3f from, Vec3f to) { + Vec3f axis = from.cross(to); + if (axis.lengthSquared() < EPSILON) { + init(); + return; + } + float dotp = from.dot(to); + float denom = from.length() * to.length(); + if (denom < EPSILON) { + init(); + return; + } + dotp /= denom; + set(axis, (float) Math.acos(dotp)); + } + + /** Returns angle (in radians) and mutates the given vector to be + the axis. */ + public float get(Vec3f axis) { + // FIXME: Is this numerically stable? Is there a better way to + // extract the angle from a quaternion? + // NOTE: remove (float) to illustrate compiler bug + float retval = (float) (2.0f * Math.acos(q0)); + axis.set(q1, q2, q3); + float len = axis.length(); + if (len == 0.0f) { + axis.set(0, 0, 1); + } else { + axis.scale(1.0f / len); + } + return retval; + } + + /** Returns inverse of this rotation; creates a new rotation. */ + public Rotf inverse() { + Rotf tmp = new Rotf(this); + tmp.invert(); + return tmp; + } + + /** Mutate this quaternion to be its inverse. This is equivalent to + the conjugate of the quaternion. */ + public void invert() { + q1 = -q1; + q2 = -q2; + q3 = -q3; + } + + /** Returns the length of this quaternion in four-space. */ + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + /** This dotted with this */ + public float lengthSquared() { + return (q0 * q0 + + q1 * q1 + + q2 * q2 + + q3 * q3); + } + + /** Make this quaternion a unit quaternion again. If you are + composing dozens of quaternions you probably should call this + periodically to ensure that you have a valid rotation. */ + public void normalize() { + float len = length(); + q0 /= len; + q1 /= len; + q2 /= len; + q3 /= len; + } + + /** Returns this * b, in that order; creates new rotation */ + public Rotf times(Rotf b) { + Rotf tmp = new Rotf(); + tmp.mul(this, b); + return tmp; + } + + /** Compose two rotations: this = A * B in that order. NOTE that + because we assume a column vector representation that this + implies that a vector rotated by the cumulative rotation will be + rotated first by B, then A. NOTE: "this" must be different than + both a and b. */ + public void mul(Rotf a, Rotf b) { + q0 = (a.q0 * b.q0 - a.q1 * b.q1 - + a.q2 * b.q2 - a.q3 * b.q3); + q1 = (a.q0 * b.q1 + a.q1 * b.q0 + + a.q2 * b.q3 - a.q3 * b.q2); + q2 = (a.q0 * b.q2 + a.q2 * b.q0 - + a.q1 * b.q3 + a.q3 * b.q1); + q3 = (a.q0 * b.q3 + a.q3 * b.q0 + + a.q1 * b.q2 - a.q2 * b.q1); + } + + /** Turns this rotation into a 3x3 rotation matrix. NOTE: only + mutates the upper-left 3x3 of the passed Mat4f. Implementation + from B. K. P. Horn's <u>Robot Vision</u> textbook. */ + public void toMatrix(Mat4f mat) { + float q00 = q0 * q0; + float q11 = q1 * q1; + float q22 = q2 * q2; + float q33 = q3 * q3; + // Diagonal elements + mat.set(0, 0, q00 + q11 - q22 - q33); + mat.set(1, 1, q00 - q11 + q22 - q33); + mat.set(2, 2, q00 - q11 - q22 + q33); + // 0,1 and 1,0 elements + float q03 = q0 * q3; + float q12 = q1 * q2; + mat.set(0, 1, 2.0f * (q12 - q03)); + mat.set(1, 0, 2.0f * (q03 + q12)); + // 0,2 and 2,0 elements + float q02 = q0 * q2; + float q13 = q1 * q3; + mat.set(0, 2, 2.0f * (q02 + q13)); + mat.set(2, 0, 2.0f * (q13 - q02)); + // 1,2 and 2,1 elements + float q01 = q0 * q1; + float q23 = q2 * q3; + mat.set(1, 2, 2.0f * (q23 - q01)); + mat.set(2, 1, 2.0f * (q01 + q23)); + } + + /** Turns the upper left 3x3 of the passed matrix into a rotation. + Implementation from Watt and Watt, <u>Advanced Animation and + Rendering Techniques</u>. + @see Mat4f#getRotation */ + public void fromMatrix(Mat4f mat) { + // FIXME: Should reimplement to follow Horn's advice of using + // eigenvector decomposition to handle roundoff error in given + // matrix. + + float tr, s; + int i, j, k; + + tr = mat.get(0, 0) + mat.get(1, 1) + mat.get(2, 2); + if (tr > 0.0) { + s = (float) Math.sqrt(tr + 1.0f); + q0 = s * 0.5f; + s = 0.5f / s; + q1 = (mat.get(2, 1) - mat.get(1, 2)) * s; + q2 = (mat.get(0, 2) - mat.get(2, 0)) * s; + q3 = (mat.get(1, 0) - mat.get(0, 1)) * s; + } else { + i = 0; + if (mat.get(1, 1) > mat.get(0, 0)) + i = 1; + if (mat.get(2, 2) > mat.get(i, i)) + i = 2; + j = (i+1)%3; + k = (j+1)%3; + s = (float) Math.sqrt( (mat.get(i, i) - (mat.get(j, j) + mat.get(k, k))) + 1.0f); + setQ(i+1, s * 0.5f); + s = 0.5f / s; + q0 = (mat.get(k, j) - mat.get(j, k)) * s; + setQ(j+1, (mat.get(j, i) + mat.get(i, j)) * s); + setQ(k+1, (mat.get(k, i) + mat.get(i, k)) * s); + } + } + + /** Rotate a vector by this quaternion. Implementation is from + Horn's <u>Robot Vision</u>. NOTE: src and dest must be different + vectors. */ + public void rotateVector(Vec3f src, Vec3f dest) { + Vec3f qVec = new Vec3f(q1, q2, q3); + Vec3f qCrossX = qVec.cross(src); + Vec3f qCrossXCrossQ = qCrossX.cross(qVec); + qCrossX.scale(2.0f * q0); + qCrossXCrossQ.scale(-2.0f); + dest.add(src, qCrossX); + dest.add(dest, qCrossXCrossQ); + } + + /** Rotate a vector by this quaternion, returning newly-allocated result. */ + public Vec3f rotateVector(Vec3f src) { + Vec3f tmp = new Vec3f(); + rotateVector(src, tmp); + return tmp; + } + + public String toString() { + return "(" + q0 + ", " + q1 + ", " + q2 + ", " + q3 + ")"; + } + + private void setQ(int i, float val) { + switch (i) { + case 0: q0 = val; break; + case 1: q1 = val; break; + case 2: q2 = val; break; + case 3: q3 = val; break; + default: throw new IndexOutOfBoundsException(); + } + } +} diff --git a/src/net/java/joglutils/msg/math/SingularMatrixException.java b/src/net/java/joglutils/msg/math/SingularMatrixException.java new file mode 100644 index 0000000..8fefb80 --- /dev/null +++ b/src/net/java/joglutils/msg/math/SingularMatrixException.java @@ -0,0 +1,51 @@ +/* + * 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.math; + +/** Thrown to indicate a singular matrix during an inversion or + related operation. */ + +public class SingularMatrixException extends RuntimeException { + public SingularMatrixException() { + super(); + } + + public SingularMatrixException(String msg) { + super(msg); + } +} diff --git a/src/net/java/joglutils/msg/math/Sphere.java b/src/net/java/joglutils/msg/math/Sphere.java new file mode 100644 index 0000000..232d81b --- /dev/null +++ b/src/net/java/joglutils/msg/math/Sphere.java @@ -0,0 +1,183 @@ +/* + * 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.math; + +/** Represents a sphere. */ + +public class Sphere { + private Vec3f center = new Vec3f(); + private float radius; + private float radSq; + + /** Default constructor creates a sphere with center (0, 0, 0) and + radius 0 */ + public Sphere() { + makeEmpty(); + } + + public Sphere(Vec3f center, float radius) { + set(center, radius); + } + + public Sphere(Sphere other) { + set(other); + } + + public Sphere(Box3f box) { + set(box); + } + + /** Re-initialize this sphere to center (0, 0, 0) and radius 0 */ + public void makeEmpty() { + center.set(0, 0, 0); + radius = radSq = 0; + } + + public void setCenter(Vec3f center) { this.center.set(center); } + public Vec3f getCenter() { return center; } + + public void setRadius(float radius) { this.radius = radius; + radSq = radius * radius; } + public float getRadius() { return radius; } + + public void set(Vec3f center, float radius) { + setCenter(center); setRadius(radius); + } + /** Returns radius and mutates passed "center" vector */ + float get(Vec3f center) { + center.set(this.center); return radius; + } + + /** Sets the parameters of this sphere to those of the given one */ + public void set(Sphere other) { + set(other.center, other.radius); + } + + /** Sets this sphere to encompass the given box */ + public void set(Box3f box) { + Vec3f max = box.getMax(); + Vec3f ctr = box.getCenter(); + Vec3f diff = max.minus(ctr); + set(ctr, diff.length()); + } + + /** Mutate this sphere to encompass both itself and the argument. + Ignores zero-size arguments. */ + public void extendBy(Sphere arg) { + if ((radius == 0.0f) || (arg.radius == 0.0f)) + return; + // FIXME: This algorithm is a quick hack -- minimum bounding + // sphere of a set of other spheres is a well studied problem, but + // not by me + Vec3f diff = arg.center.minus(center); + if (diff.lengthSquared() == 0.0f) { + setRadius(Math.max(radius, arg.radius)); + return; + } + IntersectionPoint[] intPt = new IntersectionPoint[4]; + for (int i = 0; i < intPt.length; i++) { + intPt[i] = new IntersectionPoint(); + } + int numIntersections; + numIntersections = intersectRay(center, diff, intPt[0], intPt[1]); + assert numIntersections == 2; + numIntersections = intersectRay(center, diff, intPt[2], intPt[3]); + assert numIntersections == 2; + IntersectionPoint minIntPt = intPt[0]; + IntersectionPoint maxIntPt = intPt[0]; + // Find minimum and maximum t values, take associated intersection + // points, find midpoint and half length of line segment --> + // center and radius. + for (int i = 0; i < 4; i++) { + if (intPt[i].getT() < minIntPt.getT()) { + minIntPt = intPt[i]; + } else if (intPt[i].getT() > maxIntPt.getT()) { + maxIntPt = intPt[i]; + } + } + // Compute the average -- this is the new center + center.add(minIntPt.getIntersectionPoint(), + maxIntPt.getIntersectionPoint()); + center.scale(0.5f); + // Compute half the length -- this is the radius + setRadius( + 0.5f * + minIntPt.getIntersectionPoint(). + minus(maxIntPt.getIntersectionPoint()). + length() + ); + } + + /** Intersect a ray with the sphere. This is a one-sided ray + cast. Mutates one or both of intPt0 and intPt1. Returns number + of intersections which occurred. */ + int intersectRay(Vec3f rayStart, + Vec3f rayDirection, + IntersectionPoint intPt0, + IntersectionPoint intPt1) { + // Solve quadratic equation + float a = rayDirection.lengthSquared(); + if (a == 0.0) + return 0; + float b = 2.0f * (rayStart.dot(rayDirection) - rayDirection.dot(center)); + Vec3f tempDiff = center.minus(rayStart); + float c = tempDiff.lengthSquared() - radSq; + float disc = b * b - 4 * a * c; + if (disc < 0.0f) + return 0; + int numIntersections; + if (disc == 0.0f) + numIntersections = 1; + else + numIntersections = 2; + intPt0.setT((0.5f * (-1.0f * b + (float) Math.sqrt(disc))) / a); + if (numIntersections == 2) + intPt1.setT((0.5f * (-1.0f * b - (float) Math.sqrt(disc))) / a); + Vec3f tmp = new Vec3f(rayDirection); + tmp.scale(intPt0.getT()); + tmp.add(tmp, rayStart); + intPt0.setIntersectionPoint(tmp); + if (numIntersections == 2) { + tmp.set(rayDirection); + tmp.scale(intPt1.getT()); + tmp.add(tmp, rayStart); + intPt1.setIntersectionPoint(tmp); + } + return numIntersections; + } +} diff --git a/src/net/java/joglutils/msg/math/Vec2f.java b/src/net/java/joglutils/msg/math/Vec2f.java new file mode 100644 index 0000000..a50338d --- /dev/null +++ b/src/net/java/joglutils/msg/math/Vec2f.java @@ -0,0 +1,184 @@ +/* + * 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.math; + +/** 2-element single-precision vector */ + +public class Vec2f { + private float x; + private float y; + + public Vec2f() {} + + public Vec2f(Vec2f arg) { + this(arg.x, arg.y); + } + + public Vec2f(float x, float y) { + set(x, y); + } + + public Vec2f copy() { + return new Vec2f(this); + } + + public void set(Vec2f arg) { + set(arg.x, arg.y); + } + + public void set(float x, float y) { + this.x = x; + this.y = y; + } + + /** Sets the ith component, 0 <= i < 2 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 2 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + + public float dot(Vec2f arg) { + return x * arg.x + y * arg.y; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec2f times(float val) { + Vec2f tmp = new Vec2f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec2f plus(Vec2f arg) { + Vec2f tmp = new Vec2f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec2f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec2f a, Vec2f b) { + x = a.x + b.x; + y = a.y + b.y; + } + + /** Returns this + s * arg; creates new vector */ + public Vec2f addScaled(float s, Vec2f arg) { + Vec2f tmp = new Vec2f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec2f a, float s, Vec2f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + } + + /** Returns this - arg; creates new vector */ + public Vec2f minus(Vec2f arg) { + Vec2f tmp = new Vec2f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec2f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec2f a, Vec2f b) { + x = a.x - b.x; + y = a.y - b.y; + } + + public Vecf toVecf() { + Vecf out = new Vecf(2); + for (int i = 0; i < 2; i++) { + out.set(i, get(i)); + } + return out; + } + + public String toString() { + return "(" + x + ", " + y + ")"; + } +} diff --git a/src/net/java/joglutils/msg/math/Vec3d.java b/src/net/java/joglutils/msg/math/Vec3d.java new file mode 100644 index 0000000..aa3f4b8 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Vec3d.java @@ -0,0 +1,206 @@ +/* + * 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.math; + +/** 3-element double-precision vector */ + +public class Vec3d { + private double x; + private double y; + private double z; + + public Vec3d() {} + + public Vec3d(Vec3d arg) { + set(arg); + } + + public Vec3d(double x, double y, double z) { + set(x, y, z); + } + + public Vec3d copy() { + return new Vec3d(this); + } + + /** Convert to single-precision */ + public Vec3f toFloat() { + return new Vec3f((float) x, (float) y, (float) z); + } + + public void set(Vec3d arg) { + set(arg.x, arg.y, arg.z); + } + + public void set(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** Sets the ith component, 0 <= i < 3 */ + public void set(int i, double val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 3 */ + public double get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfBoundsException(); + } + } + + public double x() { return x; } + public double y() { return y; } + public double z() { return z; } + + public void setX(double x) { this.x = x; } + public void setY(double y) { this.y = y; } + public void setZ(double z) { this.z = z; } + + public double dot(Vec3d arg) { + return x * arg.x + y * arg.y + z * arg.z; + } + + public double length() { + return Math.sqrt(lengthSquared()); + } + + public double lengthSquared() { + return this.dot(this); + } + + public void normalize() { + double len = length(); + if (len == 0.0) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec3d times(double val) { + Vec3d tmp = new Vec3d(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(double val) { + x *= val; + y *= val; + z *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec3d plus(Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec3d b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec3d a, Vec3d b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + } + + /** Returns this + s * arg; creates new vector */ + public Vec3d addScaled(double s, Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec3d a, double s, Vec3d b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + } + + /** Returns this - arg; creates new vector */ + public Vec3d minus(Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec3d b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec3d a, Vec3d b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + } + + /** Returns this cross arg; creates new vector */ + public Vec3d cross(Vec3d arg) { + Vec3d tmp = new Vec3d(); + tmp.cross(this, arg); + return tmp; + } + + /** this = a cross b. NOTE: "this" must be a different vector than + both a and b. */ + public void cross(Vec3d a, Vec3d b) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/net/java/joglutils/msg/math/Vec3f.java b/src/net/java/joglutils/msg/math/Vec3f.java new file mode 100644 index 0000000..7e18d9c --- /dev/null +++ b/src/net/java/joglutils/msg/math/Vec3f.java @@ -0,0 +1,230 @@ +/* + * 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.math; + +/** 3-element single-precision vector */ + +public class Vec3f { + public static final Vec3f X_AXIS = new Vec3f( 1, 0, 0); + public static final Vec3f Y_AXIS = new Vec3f( 0, 1, 0); + public static final Vec3f Z_AXIS = new Vec3f( 0, 0, 1); + public static final Vec3f NEG_X_AXIS = new Vec3f(-1, 0, 0); + public static final Vec3f NEG_Y_AXIS = new Vec3f( 0, -1, 0); + public static final Vec3f NEG_Z_AXIS = new Vec3f( 0, 0, -1); + + private float x; + private float y; + private float z; + + public Vec3f() {} + + public Vec3f(Vec3f arg) { + set(arg); + } + + public Vec3f(float x, float y, float z) { + set(x, y, z); + } + + public Vec3f copy() { + return new Vec3f(this); + } + + /** Convert to double-precision */ + public Vec3d toDouble() { + return new Vec3d(x, y, z); + } + + public void set(Vec3f arg) { + set(arg.x, arg.y, arg.z); + } + + public void set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** Sets the ith component, 0 <= i < 3 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 3 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + public float z() { return z; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + public void setZ(float z) { this.z = z; } + + public float dot(Vec3f arg) { + return x * arg.x + y * arg.y + z * arg.z; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec3f times(float val) { + Vec3f tmp = new Vec3f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + z *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec3f plus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec3f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec3f a, Vec3f b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + } + + /** Returns this + s * arg; creates new vector */ + public Vec3f addScaled(float s, Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec3f a, float s, Vec3f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + } + + /** Returns this - arg; creates new vector */ + public Vec3f minus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec3f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec3f a, Vec3f b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + } + + /** Returns this cross arg; creates new vector */ + public Vec3f cross(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.cross(this, arg); + return tmp; + } + + /** this = a cross b. NOTE: "this" must be a different vector than + both a and b. */ + public void cross(Vec3f a, Vec3f b) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + } + + /** Sets each component of this vector to the product of the + component with the corresponding component of the argument + vector. */ + public void componentMul(Vec3f arg) { + x *= arg.x; + y *= arg.y; + z *= arg.z; + } + + public Vecf toVecf() { + Vecf out = new Vecf(3); + for (int i = 0; i < 3; i++) { + out.set(i, get(i)); + } + return out; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/net/java/joglutils/msg/math/Vec4f.java b/src/net/java/joglutils/msg/math/Vec4f.java new file mode 100644 index 0000000..8b120e0 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Vec4f.java @@ -0,0 +1,214 @@ +/* + * 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.math; + +/** 4-element single-precision vector */ + +public class Vec4f { + private float x; + private float y; + private float z; + private float w; + + public Vec4f() {} + + public Vec4f(Vec4f arg) { + set(arg); + } + + public Vec4f(float x, float y, float z, float w) { + set(x, y, z, w); + } + + public Vec4f copy() { + return new Vec4f(this); + } + + public void set(Vec4f arg) { + set(arg.x, arg.y, arg.z, arg.w); + } + + public void set(float x, float y, float z, float w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /** Sets the ith component, 0 <= i < 4 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + case 3: w = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 4 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + public float z() { return z; } + public float w() { return w; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + public void setZ(float z) { this.z = z; } + public void setW(float w) { this.w = w; } + + public float dot(Vec4f arg) { + return x * arg.x + y * arg.y + z * arg.z + w * arg.w; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec4f times(float val) { + Vec4f tmp = new Vec4f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + z *= val; + w *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec4f plus(Vec4f arg) { + Vec4f tmp = new Vec4f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec4f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec4f a, Vec4f b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + w = a.w + b.w; + } + + /** Returns this + s * arg; creates new vector */ + public Vec4f addScaled(float s, Vec4f arg) { + Vec4f tmp = new Vec4f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec4f a, float s, Vec4f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + w = a.w + s * b.w; + } + + /** Returns this - arg; creates new vector */ + public Vec4f minus(Vec4f arg) { + Vec4f tmp = new Vec4f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec4f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec4f a, Vec4f b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + w = a.w - b.w; + } + + /** Sets each component of this vector to the product of the + component with the corresponding component of the argument + vector. */ + public void componentMul(Vec4f arg) { + x *= arg.x; + y *= arg.y; + z *= arg.z; + w *= arg.w; + } + + public Vecf toVecf() { + Vecf out = new Vecf(4); + for (int i = 0; i < 4; i++) { + out.set(i, get(i)); + } + return out; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/net/java/joglutils/msg/math/Vecf.java b/src/net/java/joglutils/msg/math/Vecf.java new file mode 100644 index 0000000..070bfab --- /dev/null +++ b/src/net/java/joglutils/msg/math/Vecf.java @@ -0,0 +1,94 @@ +/* + * 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.math; + +/** Arbitrary-length single-precision vector class. Currently very + simple and only supports a few needed operations. */ + +public class Vecf { + private float[] data; + + public Vecf(int n) { + data = new float[n]; + } + + public Vecf(Vecf arg) { + data = new float[arg.data.length]; + System.arraycopy(arg.data, 0, data, 0, data.length); + } + + public int length() { + return data.length; + } + + public float get(int i) { + return data[i]; + } + + public void set(int i, float val) { + data[i] = val; + } + + public Vec2f toVec2f() throws DimensionMismatchException { + if (length() != 2) + throw new DimensionMismatchException(); + Vec2f out = new Vec2f(); + for (int i = 0; i < 2; i++) { + out.set(i, get(i)); + } + return out; + } + + public Vec3f toVec3f() throws DimensionMismatchException { + if (length() != 3) + throw new DimensionMismatchException(); + Vec3f out = new Vec3f(); + for (int i = 0; i < 3; i++) { + out.set(i, get(i)); + } + return out; + } + + public Veci toInt() { + Veci out = new Veci(length()); + for (int i = 0; i < length(); i++) { + out.set(i, (int) get(i)); + } + return out; + } +} diff --git a/src/net/java/joglutils/msg/math/Veci.java b/src/net/java/joglutils/msg/math/Veci.java new file mode 100644 index 0000000..00302e9 --- /dev/null +++ b/src/net/java/joglutils/msg/math/Veci.java @@ -0,0 +1,94 @@ +/* + * 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.math; + +/** Arbitrary-length integer vector class. Currently very simple and + only supports a few needed operations. */ + +public class Veci { + private int[] data; + + public Veci(int n) { + data = new int[n]; + } + + public Veci(Veci arg) { + data = new int[arg.data.length]; + System.arraycopy(arg.data, 0, data, 0, data.length); + } + + public int length() { + return data.length; + } + + public int get(int i) { + return data[i]; + } + + public void set(int i, int val) { + data[i] = val; + } + + public Vec2f toVec2f() throws DimensionMismatchException { + if (length() != 2) + throw new DimensionMismatchException(); + Vec2f out = new Vec2f(); + for (int i = 0; i < 2; i++) { + out.set(i, get(i)); + } + return out; + } + + public Vec3f toVec3f() throws DimensionMismatchException { + if (length() != 3) + throw new DimensionMismatchException(); + Vec3f out = new Vec3f(); + for (int i = 0; i < 3; i++) { + out.set(i, get(i)); + } + return out; + } + + public Vecf toVecf() { + Vecf out = new Vecf(length()); + for (int i = 0; i < length(); i++) { + out.set(i, get(i)); + } + return out; + } +} diff --git a/src/net/java/joglutils/msg/math/package.html b/src/net/java/joglutils/msg/math/package.html new file mode 100644 index 0000000..be2d23c --- /dev/null +++ b/src/net/java/joglutils/msg/math/package.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +Linear algebra and classes implementing basic 3D operations. + +</body> +</html> diff --git a/src/net/java/joglutils/msg/misc/State.java b/src/net/java/joglutils/msg/misc/State.java new file mode 100644 index 0000000..c718f71 --- /dev/null +++ b/src/net/java/joglutils/msg/misc/State.java @@ -0,0 +1,220 @@ +/* + * 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.elements.*; + +/** Represents a collection of state elements, which are updated by + actions during scene graph traversal. */ + +public class State { + // Provides each concrete Element subclass a unique slot in the State. + // Note that subclasses of concrete Element subclasses share the + // slot with their parent class. Which one is used for a given + // Action is decided by which elements are enabled for that action. + private static int curStateIndex = 0; + + // The representation of the State. + private List<Element> elements = new ArrayList<Element>(); + + // The default enabled elements for this State. The State instances + // created by each Action instance point to the default enabled + // elements; this is where the individual Action's State is + // initialized from. + // Note that this mechanism is needed because different actions + // install different Element subclasses (i.e., ModelMatrixElement + // vs. GLModelMatrixElement) into the same element slot. + private State defaults; + + // A linked list of elements touched since the last push, used to + // reduce the number of elements that need to be accessed during a + // pop() operation. + private Element topElement; + + // The depth at which we are operating, to implement lazy pushing + // and popping of state elements + private int depth; + + /** This constructor should only be used for the default State for a + given Action subclass. */ + public State() { + } + + /** This constructor should be used to create the concrete State + instances for each Action instance. The default State given + should be that for the particular Action class. */ + public State(State defaults) { + this.defaults = defaults; + // Do a push() to ensure that we always have a non-null and + // pristine entry at the top of each stack + push(); + } + + /** Gets the state element at the given index. */ + public Element getElement(StateIndex index) { + // The comments in the Open Inventor implementation indicate that + // a bug that was found and fixed was that this method must not be + // called in the process of popping the state. This assert + // attempts to guard against that happening. + assert depth >= ((topElement == null) ? 0 : topElement.getDepth()) : + "Elements must not be changed while the state is being popped (element being changed: " + + elements.get(index.getIndex()).getClass().getName() + ")."; + + int idx = index.getIndex(); + + if (defaults == null) { + // This State contains the defaults for a particular Action + // class. Don't do anything fancy -- just return the element at + // the particular index. + if (idx >= elements.size()) { + return null; + } + return elements.get(idx); + } + + if (idx >= elements.size()) { + // Expand list to the needed size + while (idx >= elements.size()) { + elements.add(null); + } + } + + Element elt = elements.get(idx); + if (elt == null) { + // Lazily create a copy of the default and put it in place + elt = defaults.getElement(index); + if (elt == null) { + throw new RuntimeException("Error in initialization of default element for state index " + idx); + } + elt = elt.newInstance(); + elt.setDepth(0); + elements.set(idx, elt); + } + + // If element is not at current depth, we have to push a new + // element on the stack + if (elt.getDepth() < depth) { + // FIXME: consider doubly-linked-list scheme as in Inventor to + // avoid excessive object creation during scene graph traversal + Element newElt = elt.newInstance(); + newElt.setNextInStack(elt); + newElt.setDepth(depth); + // Add newly-created element to the all-element stack + newElt.setNext(topElement); + topElement = newElt; + elements.set(idx, newElt); + // Call push on new element in case it has side effects + newElt.push(this); + // Return new element + elt = newElt; + } + + return elt; + } + + /** Sets the element at the given state index. This should only be + used by Action, Element and Node subclasses to initialize the + default state for a given Action class. */ + public void setElement(StateIndex index, Element element) { + if (defaults != null) { + throw new RuntimeException("Misuse of setElement(); should only be used to initialize default State for an Action"); + } + int idx = index.getIndex(); + if (idx >= elements.size()) { + while (idx >= elements.size()) { + elements.add(null); + } + } + elements.set(idx, element); + } + + /** Pushes (saves) the current state until a pop() restores it. The + push is done lazily: this just increments the depth in the + state. When an element is accessed with getElement() and its + depth is less than the current depth, it is then pushed + individually. */ + public void push() { + ++depth; + } + + /** Pops the state, restoring the state to just before the last push(). */ + public void pop() { + --depth; + + Element poppedElt = null; + Element nextInStack = null; + + // As in Open Inventor, the popping is done in two passes. This is + // apparently needed if Open Inventor-style caching is added in + // the future. The first pass calls pop() on all of the elements + // that will be popped; the second pass actually removes the + // elements from their respective stacks. + for (poppedElt = topElement; + poppedElt != null && poppedElt.getDepth() > depth; + poppedElt = poppedElt.getNext()) { + + // Find the next element in the same stack as the element being + // popped. This element will become the new top of that stack. + nextInStack = poppedElt.getNextInStack(); + + // Give the new top element in the stack a chance to update + // things. Pass old element instance just in case. + poppedElt.getNextInStack().pop(this, poppedElt); + } + + // Remove all such elements from their respective stacks + while (topElement != null && topElement.getDepth() > depth) { + poppedElt = topElement; + + // Remove from main element list + topElement = topElement.getNext(); + + // Remove from element stack + elements.set(poppedElt.getStateIndex().getIndex(), poppedElt.getNextInStack()); + } + } + + /** Should be called by Element subclasses to register themselves + with the State class. This provides them a StateIndex with which + they can index into the State. */ + public static synchronized StateIndex registerElementType() { + return new StateIndex(curStateIndex++); + } +} diff --git a/src/net/java/joglutils/msg/misc/StateIndex.java b/src/net/java/joglutils/msg/misc/StateIndex.java new file mode 100644 index 0000000..982a4c7 --- /dev/null +++ b/src/net/java/joglutils/msg/misc/StateIndex.java @@ -0,0 +1,56 @@ +/* + * 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 an index into the global state managed by the State + class. This class is an opaque data type that is created by + calling {@link State#registerElementType + State.registerElementType()}. */ + +public class StateIndex { + private int index; + + /** Constructor is package-private to avoid leakage of representation */ + StateIndex(int index) { + this.index = index; + } + + int getIndex() { + return index; + } +} diff --git a/src/net/java/joglutils/msg/misc/SystemTime.java b/src/net/java/joglutils/msg/misc/SystemTime.java new file mode 100644 index 0000000..6342d58 --- /dev/null +++ b/src/net/java/joglutils/msg/misc/SystemTime.java @@ -0,0 +1,108 @@ +/* + * 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; + +/** Implementation of {@link Time Time} interface based on {@link + java.lang.System#currentTimeMillis System.currentTimeMillis}. + Performs smoothing internally to avoid effects of poor granularity + of currentTimeMillis on Windows platform in particular. */ + +public class SystemTime implements Time { + private static final int DEFAULT_NUM_SMOOTHING_SAMPLES = 10; + private long[] samples = new long[DEFAULT_NUM_SMOOTHING_SAMPLES]; + private int numSmoothingSamples; + private int curSmoothingSample; // Index of current sample to be replaced + private long baseTime = System.currentTimeMillis(); + private boolean hasCurTime; + private double curTime; + private double deltaT; + + /** Sets number of smoothing samples. Defaults to 10. Note that + there may be a discontinuity in the reported time after a call + to this method. */ + public void setNumSmoothingSamples(int num) { + samples = new long[num]; + numSmoothingSamples = 0; + curSmoothingSample = 0; + hasCurTime = false; + } + + /** Returns number of smoothing samples; default is 10. */ + public int getNumSmoothingSamples() { + return samples.length; + } + + /** Rebases this timer. After very long periods of time the + resolution of this timer may decrease; the application can call + this to restore higher resolution. Note that there may be a + discontinuity in the reported time after a call to this + method. */ + public void rebase() { + baseTime = System.currentTimeMillis(); + setNumSmoothingSamples(samples.length); + } + + public void update() { + long tmpTime = System.currentTimeMillis(); + long diffSinceBase = tmpTime - baseTime; + samples[curSmoothingSample] = diffSinceBase; + curSmoothingSample = (curSmoothingSample + 1) % samples.length; + numSmoothingSamples = Math.min(1 + numSmoothingSamples, samples.length); + // Average of samples is current time + double newCurTime = 0.0; + for (int i = 0; i < numSmoothingSamples; i++) { + newCurTime += samples[i]; + } + newCurTime /= (1000.0f * numSmoothingSamples); + double lastTime = curTime; + if (!hasCurTime) { + lastTime = newCurTime; + hasCurTime = true; + } + deltaT = newCurTime - lastTime; + curTime = newCurTime; + } + + public double time() { + return curTime; + } + + public double deltaT() { + return deltaT; + } +} diff --git a/src/net/java/joglutils/msg/misc/Time.java b/src/net/java/joglutils/msg/misc/Time.java new file mode 100644 index 0000000..a0428c3 --- /dev/null +++ b/src/net/java/joglutils/msg/misc/Time.java @@ -0,0 +1,50 @@ +/* + * 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; + +/** Interface abstracting concept of time from applications. */ + +public interface Time { + /** Updates this Time object. Call update() each frame before + calling the accessor routines. */ + public void update(); + /** Time in seconds since beginning of application. */ + public double time(); + /** Time in seconds since last update. */ + public double deltaT(); +} diff --git a/src/net/java/joglutils/msg/misc/package.html b/src/net/java/joglutils/msg/misc/package.html new file mode 100644 index 0000000..56976d3 --- /dev/null +++ b/src/net/java/joglutils/msg/misc/package.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +Defines miscellaneous classes most users will not need to interact +with. Includes the State class which encapsulates Elements and is used +by Actions. + +</body> +</html> diff --git a/src/net/java/joglutils/msg/nodes/Blend.java b/src/net/java/joglutils/msg/nodes/Blend.java new file mode 100644 index 0000000..18cd5a6 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Blend.java @@ -0,0 +1,168 @@ +/* + * 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 net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.math.*; + +/** Provides control over OpenGL blending modes. */ + +public class Blend extends Node { + private boolean enabled; + private Vec4f blendColor = new Vec4f(); + private int srcFunc = ONE; + private int destFunc = ZERO; + private int blendEquation = FUNC_ADD; + + /** 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. */ + public static final int ONE = 2; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int SRC_COLOR = 3; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int ONE_MINUS_SRC_COLOR = 4; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int DST_COLOR = 5; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int ONE_MINUS_DST_COLOR = 6; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int SRC_ALPHA = 7; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int ONE_MINUS_SRC_ALPHA = 8; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int DST_ALPHA = 9; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int ONE_MINUS_DST_ALPHA = 10; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int SRC_ALPHA_SATURATE = 11; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int CONSTANT_COLOR = 12; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int ONE_MINUS_CONSTANT_COLOR = 13; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int CONSTANT_ALPHA = 14; + /** One of the blend functions. See the OpenGL documentation for glBlendFunc for more details. */ + public static final int ONE_MINUS_CONSTANT_ALPHA = 15; + + /** One of the blend equations. See the OpenGL documentation for glBlendEquation for more details. */ + public static final int FUNC_ADD = 1; + /** One of the blend equations. See the OpenGL documentation for glBlendEquation for more details. */ + public static final int FUNC_SUBTRACT = 2; + /** One of the blend equations. See the OpenGL documentation for glBlendEquation for more details. */ + public static final int FUNC_REVERSE_SUBTRACT = 3; + /** One of the blend equations. See the OpenGL documentation for glBlendEquation for more details. */ + public static final int MIN = 4; + /** One of the blend equations. See the OpenGL documentation for glBlendEquation for more details. */ + public static final int MAX = 5; + + /** Sets whether blending is enabled. Defaults to false. */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + /** Returns whether blending is enabled. Defaults to false. */ + public boolean getEnabled() { + return enabled; + } + + /** Sets the source blending function to one of ZERO, ONE, + SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR, + SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, + SRC_ALPHA_SATURATE, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR, + CONSTANT_ALPHA, or ONE_MINUS_CONSTANT_ALPHA. The default is ONE. */ + public void setSourceFunc(int func) { + if (func < ZERO || func > ONE_MINUS_CONSTANT_ALPHA) { + throw new IllegalArgumentException("Illegal source blending function " + func); + } + srcFunc = func; + } + + /** Returns the source blending function. The default is ONE. */ + public int getSourceFunc() { + return srcFunc; + } + + /** Sets the destination blending function to one of ZERO, ONE, + SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR, + SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, + SRC_ALPHA_SATURATE, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR, + CONSTANT_ALPHA, or ONE_MINUS_CONSTANT_ALPHA. The default is + ZERO. */ + public void setDestFunc(int func) { + if (func < ZERO || func > ONE_MINUS_CONSTANT_ALPHA) { + throw new IllegalArgumentException("Illegal destination blending function " + func); + } + destFunc = func; + } + + /** Returns the destination blending function. The default is ZERO. */ + public int getDestFunc() { + return destFunc; + } + + /** Sets the blending equation to one of FUNC_ADD, FUNC_SUBTRACT, + FUNC_REVERSE_SUBTRACT, MIN, or MAX. Defaults to FUNC_ADD. */ + public void setBlendEquation(int equation) { + if (equation < FUNC_ADD || equation > MAX) { + throw new IllegalArgumentException("Illegal blending equation " + equation); + } + this.blendEquation = equation; + } + + /** Returns the blending equation. Defaults to FUNC_ADD. */ + public int getBlendEquation() { + return blendEquation; + } + + /** Sets the blending color; see the documentation for glBlendColor + for more details. Defaults to [0, 0, 0, 0]. */ + public void setBlendColor(Vec4f color) { + blendColor.set(color); + } + + /** Gets the blending color; see the documentation for glBlendColor + for more details. Defaults to [0, 0, 0, 0]. */ + public Vec4f getBlendColor() { + return blendColor; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Camera.java b/src/net/java/joglutils/msg/nodes/Camera.java new file mode 100644 index 0000000..9d1f965 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Camera.java @@ -0,0 +1,126 @@ +/* + * 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 net.java.joglutils.msg.math.*; + +/** Represents a camera which is used to view the scene. The camera + should be added to the scene graph before the geometry it is + intended to view. <P> + + The camera's default parameters are a position at (0, 0, 1), + facing down the negative Z axis with the Y axis up, an aspect + ratio of 1.0, a near distance of 1.0, a far distance of 100.0, and + a focal distance of 10.0. +*/ + +public abstract class Camera extends Node { + private Vec3f position; + private Rotf orientation; + private float aspectRatio = 1.0f; + private float nearDistance = 1.0f; + private float farDistance = 100.0f; + private float focalDistance = 10.0f; + + protected boolean projDirty; + protected boolean viewDirty; + protected Mat4f projMatrix; + protected Mat4f viewMatrix; + + public Camera() { + position = new Vec3f(0, 0, 1); + orientation = new Rotf(); + // orientation = new Rotf(new Vec3f(0, 1, 0), (float) (Math.PI)); + + projMatrix = new Mat4f(); + viewMatrix = new Mat4f(); + projDirty = true; + viewDirty = true; + } + + /** Sets the position of the camera. */ + public void setPosition(Vec3f position) { this.position.set(position); viewDirty = true; } + /** Returns the position of the camera. */ + public Vec3f getPosition() { return position; } + + /** Sets the orientation of the camera. */ + public void setOrientation(Rotf orientation) { this.orientation.set(orientation); viewDirty = true; } + /** Returns the orientation of the camera. */ + public Rotf getOrientation() { return orientation; } + + /** Sets the aspect ratio of the camera. */ + public void setAspectRatio(float aspectRatio) { this.aspectRatio = aspectRatio; projDirty = true; } + /** Returns the aspect ratio of the camera. */ + 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; } + /** Returns the distance from the eye point to the near clipping plane. */ + 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; } + /** Returns the distance from the eye point to the far clipping plane. */ + 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; } + /** 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; } + + /** Returns the viewing matrix associated with this camera's parameters. */ + public Mat4f getViewingMatrix() { + if (viewDirty) { + viewMatrix.makeIdent(); + viewDirty = false; + + viewMatrix.setRotation(getOrientation()); + viewMatrix.setTranslation(getPosition()); + viewMatrix.invertRigid(); + } + + return viewMatrix; + } + + /** Returns the projection matrix associated with this camera's parameters. */ + public abstract Mat4f getProjectionMatrix(); +} diff --git a/src/net/java/joglutils/msg/nodes/Color4.java b/src/net/java/joglutils/msg/nodes/Color4.java new file mode 100644 index 0000000..d6568e3 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Color4.java @@ -0,0 +1,95 @@ +/* + * 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 net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.collections.*; + +/** Represents a set of 4-valued colors which are applied on a + per-vertex basis to any drawn polygons. Currently the color can + only be bound to one material parameter of the fixed-function + OpenGL pipeline, defaulting to "ambient and diffuse". <P> + + For correct rendering results, the colors stored in this node + should have their alpha premultiplied; in other words, the red, + green, and blue (x, y, and z components of the stored vectors) + should be multiplied by the alpha value (the w component) before + storing them in this node. +*/ + +public class Color4 extends Node { + private Vec4fCollection data; + + // private int colorBinding = AMBIENT_AND_DIFFUSE; + + /****** + + * Note: these aren't needed until we have lighting + + // FIXME: factor this out into a separate ColorBinding node + public static final int EMISSION = 1; + public static final int AMBIENT = 2; + public static final int DIFFUSE = 3; + public static final int SPECULAR = 4; + public static final int AMBIENT_AND_DIFFUSE = 5; + + public void setColorBinding(int colorBinding) { + if (binding < EMISSION || binding > AMBIENT_AND_DIFFUSE) { + throw new IllegalArgumentException("Illegal color binding " + binding); + } + this.colorBinding = colorBinding; + } + + public int getColorBinding() { + return colorBinding; + } + + */ + + public void setData(Vec4fCollection data) { + this.data = data; + } + + public Vec4fCollection getData() { + return data; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Coordinate3.java b/src/net/java/joglutils/msg/nodes/Coordinate3.java new file mode 100644 index 0000000..4e2b94b --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Coordinate3.java @@ -0,0 +1,62 @@ +/* + * 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 net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.collections.*; + +/** Represents a set of 3-dimensional vertices which can be assembled + into shapes. */ + +public class Coordinate3 extends Node { + private Vec3fCollection data; + + /** Sets the coordinate data in this node. */ + public void setData(Vec3fCollection data) { + this.data = data; + } + + /** Returns the coordinate data in this node. */ + public Vec3fCollection getData() { + return data; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Group.java b/src/net/java/joglutils/msg/nodes/Group.java new file mode 100644 index 0000000..f9a961b --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Group.java @@ -0,0 +1,124 @@ +/* + * 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.*; + +/** A node which manages other Node instances. */ + +public class Group extends Node { + private List<Node> children = new ArrayList<Node>(); + + /** Append a child node to the list of children nodes this group node is managing. */ + public void addChild(Node child) { + children.add(child); + } + + /** Adds a child so that it becomes the one with the given index. */ + public void insertChild(Node child, int index) { + children.add(index, child); + } + + /** Returns the child node with the given index. */ + public Node getChild(int index) { + return children.get(index); + } + + /** Finds the index of given child within the group. Returns -1 if not found. */ + public int findChild(Node node) { + return children.indexOf(node); + } + + /** Returns number of children. */ + public int getNumChildren() { + return children.size(); + } + + /** Removes the child with given index from the group. + + @throws IndexOutOfBoundsException if the index is less than 0 or + greater than the number of children + */ + public void removeChild(int index) throws IndexOutOfBoundsException { + children.remove(index); + } + + /** Removes the given child from the group. This is a convenience + method equivalent to calling {@link #findChild findChild} and, + if the node is found, passing the index to {@link #removeChild + removeChild}. + */ + public void removeChild(Node node) { + int idx = findChild(node); + if (idx >= 0) + removeChild(idx); + } + + /** Removes all children from this Group node. */ + public void removeAllChildren() { + children.clear(); + } + + /** Replaces the child at the given index with the new child. + + @throws IndexOutOfBoundsException if the index is less than 0 or + greater than the number of children + */ + public void replaceChild(int index, Node newChild) throws IndexOutOfBoundsException { + removeChild(index); + insertChild(newChild, index); + } + + /** Replaces the old child with the new child. This is a convenience + method. It will simply call {@link #findChild findChild} with + oldChild as argument, and call replaceChild(int, SoNode*) if the + child is found. */ + public void replaceChild(Node oldChild, Node newChild) { + int idx = findChild(oldChild); + if (idx >= 0) + replaceChild(idx, newChild); + } + + public void doAction(Action action) { + for (int i = 0; i < getNumChildren(); i++) { + action.apply(getChild(i)); + } + } +} diff --git a/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java b/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java new file mode 100644 index 0000000..d2932c8 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/IndexedTriangleSet.java @@ -0,0 +1,67 @@ +/* + * 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.nio.*; + +import net.java.joglutils.msg.actions.*; + +/** An IndexedTriangleSet assembles the coordinates specified by a + Coordinate3 node, and any auxiliary nodes such as a + TextureCoordinate2 node, into a set of triangles by indexing into + the pools of coordinates set up by these other nodes. (NOTE: + (FIXME) rendering support for this node is not yet + implemented.) */ + +public class IndexedTriangleSet extends Node { + private IntBuffer indices; + + /** Sets the indices this node uses to group vertices into triangles. */ + public void setIndices(IntBuffer indices) { + this.indices = indices; + } + + /** Returns the indices this node uses to group vertices into triangles. */ + public IntBuffer getIndices() { + return indices; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Node.java b/src/net/java/joglutils/msg/nodes/Node.java new file mode 100644 index 0000000..6fc4eb9 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Node.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.nodes; + +import net.java.joglutils.msg.actions.*; + +/** The base class for all nodes in the scene graph. */ + +public class Node { + + /** 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) { + } +} diff --git a/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java b/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java new file mode 100644 index 0000000..b72507a --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/PerspectiveCamera.java @@ -0,0 +1,97 @@ +/* + * 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 net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.math.*; + +/** Represents a camera utilizing a perspective projection. <P> + + The default height angle is Math.PI / 4 radians (45 degrees), + meaning that the camera has a total vertical field of view of 90 + degrees. +*/ + +public class PerspectiveCamera extends Camera { + private static final float DEFAULT_HEIGHT_ANGLE = (float) (Math.PI / 4); + // Amount the most recently set height angle differed from the default + private float vertFOVScale = 1.0f; + + public Mat4f getProjectionMatrix() { + if (projDirty) { + projMatrix.makeIdent(); + projDirty = false; + + // Recompute matrix based on current parameters + float zNear = getNearDistance(); + float zFar = getFarDistance(); + float deltaZ = zFar - zNear; + float aspect = getAspectRatio(); + float radians = vertFOVScale * DEFAULT_HEIGHT_ANGLE; + float sine = (float) Math.sin(radians); + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { + return projMatrix; + } + + float cotangent = (float) Math.cos(radians) / sine; + projMatrix.set(0, 0, cotangent / aspect); + projMatrix.set(1, 1, cotangent); + projMatrix.set(2, 2, -(zFar + zNear) / deltaZ); + projMatrix.set(3, 2, -1); + projMatrix.set(2, 3, -2 * zNear * zFar / deltaZ); + projMatrix.set(3, 3, 0); + } + + return projMatrix; + } + + /** Sets the height angle of this perspective camera. */ + public void setHeightAngle(float heightAngle) { + vertFOVScale = heightAngle / DEFAULT_HEIGHT_ANGLE; + projDirty = true; + } + + /** Returns the height angle of this perspective camera. */ + public float getHeightAngle() { + return vertFOVScale * DEFAULT_HEIGHT_ANGLE; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Separator.java b/src/net/java/joglutils/msg/nodes/Separator.java new file mode 100644 index 0000000..c60ba45 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Separator.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.nodes; + +import net.java.joglutils.msg.actions.*; + +/** Represents a push / pop of OpenGL state, "separating" the + sub-graph below this separator from the nodes which follow it in + the graph. */ + +public class Separator extends Group { + public void doAction(Action action) { + action.visitPre(this); + super.doAction(action); + action.visitPost(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Texture2.java b/src/net/java/joglutils/msg/nodes/Texture2.java new file mode 100644 index 0000000..441c2f5 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Texture2.java @@ -0,0 +1,139 @@ +/* + * 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.awt.image.*; +import java.io.*; +import java.net.*; + +import javax.media.opengl.*; +import com.sun.opengl.util.texture.*; + +import net.java.joglutils.msg.actions.*; + +/** Represents a two-dimensional texture. */ + +public class Texture2 extends Node { + private TextureData data; + private Texture texture; + private int texEnvMode = MODULATE; + private boolean dirty; + + /** Represents the OpenGL MODULATE texture environment mode. */ + public static final int MODULATE = 1; + /** Represents the OpenGL DECAL texture environment mode. */ + public static final int DECAL = 2; + /** Represents the OpenGL BLEND texture environment mode. */ + public static final int BLEND = 3; + /** Represents the OpenGL REPLACE texture environment mode. */ + public static final int REPLACE = 4; + + /** Initializes this texture from the given file. No OpenGL work is + done during this call; it is done lazily when the Texture is + fetched. */ + public void setTexture(File file, boolean mipmap, String fileSuffix) throws IOException { + data = TextureIO.newTextureData(file, mipmap, fileSuffix); + dirty = true; + } + + /** Initializes this texture from the given InputStream. No OpenGL + work is done during this call; it is done lazily when the + Texture is fetched. */ + public void setTexture(InputStream stream, boolean mipmap, String fileSuffix) throws IOException { + data = TextureIO.newTextureData(stream, mipmap, fileSuffix); + dirty = true; + } + + /** Initializes this texture from the given URL. No OpenGL work is + done during this call; it is done lazily when the Texture is + fetched. */ + public void setTexture(URL url, boolean mipmap, String fileSuffix) throws IOException { + data = TextureIO.newTextureData(url, mipmap, fileSuffix); + dirty = true; + } + + /** Initializes this texture from the given BufferedImage. No OpenGL + work is done during this call; it is done lazily when the + Texture is fetched. */ + public void setTexture(BufferedImage image, boolean mipmap) { + data = TextureIO.newTextureData(image, mipmap); + dirty = true; + } + + /** Initializes this texture from the given TextureData. No OpenGL + work is done during this call; it is done lazily when the + Texture is fetched. */ + public void setTexture(TextureData data) { + this.data = data; + dirty = true; + } + + /** Fetches the Texture object associated with this Texture2 node. + An OpenGL context must be current at the time this method is + called or a GLException will be thrown. */ + public Texture getTexture() throws GLException { + if (dirty) { + if (texture != null) { + texture.dispose(); + texture = null; + } + texture = TextureIO.newTexture(data); + data = null; + dirty = false; + } + return texture; + } + + /** Sets the texture environment mode. Default is MODULATE. */ + public void setTexEnvMode(int mode) { + if (mode < MODULATE || mode > REPLACE) { + throw new IllegalArgumentException("Illegal texture environment mode"); + } + this.texEnvMode = mode; + } + + /** Returns the texture environment mode: one of MODULATE, DECAL, + BLEND, or REPLACE. */ + public int getTexEnvMode() { + return texEnvMode; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java b/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java new file mode 100644 index 0000000..ed4ecf8 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/TextureCoordinate2.java @@ -0,0 +1,62 @@ +/* + * 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 net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.collections.*; + +/** Represents a set of 2-dimensional texture coordinates which can be + used to texture geometric shapes. */ + +public class TextureCoordinate2 extends Node { + private Vec2fCollection data; + + /** Sets the texture coordinate data in this node. */ + public void setData(Vec2fCollection data) { + this.data = data; + } + + /** Returns the texture coordinate data in this node. */ + public Vec2fCollection getData() { + return data; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/Transform.java b/src/net/java/joglutils/msg/nodes/Transform.java new file mode 100644 index 0000000..0faf8e6 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/Transform.java @@ -0,0 +1,66 @@ +/* + * 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 net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.math.*; + +/** Represents a generalized 4x4 matrix transformation. */ + +public class Transform extends Node { + private Mat4f transform; + + public Transform() { + transform = new Mat4f(); + transform.makeIdent(); + } + + /** Sets the transformation in thie node. */ + public void setTransform(Mat4f transform) { + this.transform.set(transform); + } + + /** Returns the transformation in thie node. */ + public Mat4f getTransform() { + return transform; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/TriangleSet.java b/src/net/java/joglutils/msg/nodes/TriangleSet.java new file mode 100644 index 0000000..775c622 --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/TriangleSet.java @@ -0,0 +1,62 @@ +/* + * 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 net.java.joglutils.msg.actions.*; + +/** A TriangleSet assembles the coordinates specified by a Coordinate3 + node, and any auxiliary nodes such as a TextureCoordinate2 node, + into a set of triangles. */ + +public class TriangleSet extends Node { + private int numTriangles; + + /** Sets the number of triangles this TriangleSet references. */ + public void setNumTriangles(int numTriangles) { + this.numTriangles = numTriangles; + } + + /** Returns the number of triangles this TriangleSet references. */ + public int getNumTriangles() { + return numTriangles; + } + + public void doAction(Action action) { + action.visit(this); + } +} diff --git a/src/net/java/joglutils/msg/nodes/package.html b/src/net/java/joglutils/msg/nodes/package.html new file mode 100644 index 0000000..a7ce71e --- /dev/null +++ b/src/net/java/joglutils/msg/nodes/package.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +The primary package of the MSG library, defining the node types in the scene graph. + +</body> +</html> diff --git a/src/net/java/joglutils/msg/overview.html b/src/net/java/joglutils/msg/overview.html new file mode 100644 index 0000000..828dc12 --- /dev/null +++ b/src/net/java/joglutils/msg/overview.html @@ -0,0 +1,50 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> + <title>The Minimal Scene Graph (MSG)</title> +</head> +<body> +<h2>Overview</h2> + +<P> + +The Minimal Scene Graph (MSG) is a small, lightweight 3D scene graph +library layered on top of the <a href="http://jogl.dev.java.net">Java(tm) +Binding to the OpenGL(r) API</a> (JOGL). MSG is heavily inspired by +the Open Inventor(tm) library developed by Silicon Graphics, Inc. and +derives most of its concepts and internal structure from this library, +which was released in open-source form in 2000. Many implementation +decisions were informed by studying the Open Inventor source code. + +</P> +<P> + +MSG is more free-form in style than many contemporary scene graphs. +The traversal order of the scene graph is significant, and occurs in +top-down, left-to-right order. Nodes placed in the scene graph affect +the global state when they are traversed. When geometry is rendered, +it acquires its visual characteristics from the current settings in +the global state. Actions are applied to nodes to cause operations +such as rendering. + +</P> +<P> + +Group nodes collect children nodes underneath them, but have no effect +on the global state, which propagates both upward and downward through +them. Separator nodes, which are a subclass of Group, prevent state +changes underneath them from propagating out and affecting nodes which +follow them in the graph. This allows them to be used as an effective +means of collecting reusable pieces of scene graph structure. Global +state propagates downward through Separators. + +</P> +<P> + +The current set of nodes is minimal (as indicated by the name of the +library) and the current set of actions is incomplete. + +</P> + +</body> +</html> diff --git a/src/net/java/joglutils/msg/test/DisplayShelf.java b/src/net/java/joglutils/msg/test/DisplayShelf.java new file mode 100644 index 0000000..73a63de --- /dev/null +++ b/src/net/java/joglutils/msg/test/DisplayShelf.java @@ -0,0 +1,433 @@ +/* + * 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.test; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.DisplayMode; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.event.*; +import java.awt.image.*; +import java.net.*; +import java.util.*; +import javax.imageio.*; +import javax.swing.*; +import javax.swing.event.*; + +import javax.media.opengl.*; + +import net.java.joglutils.msg.actions.*; +import net.java.joglutils.msg.collections.*; +import net.java.joglutils.msg.math.*; +import net.java.joglutils.msg.misc.*; +import net.java.joglutils.msg.nodes.*; + +/** A test implementing a 3D display shelf component. */ + +public class DisplayShelf extends Container { + private GLCanvas canvas; + + private float DEFAULT_ASPECT_RATIO = 0.665f; + // This also affects the spacing + private float DEFAULT_HEIGHT = 1.5f; + + // The camera + private PerspectiveCamera camera; + + static class TitleGraph { + String url; + Transform xform = new Transform(); + Texture2 texture = new Texture2(); + Coordinate3 coords = new Coordinate3(); + + TitleGraph(String url) { + this.url = url; + } + } + + private Group root; + private String[] images; + private List<TitleGraph> titles = new ArrayList<TitleGraph>(); + private int targetIndex; + // This encodes both the current position and the animation alpha + private float currentIndex; + // If the difference between the current index and target index is > + // EPSILON, then we will continue repainting + private static final float EPSILON = 1.0e-3f; + private SystemTime time; + private boolean animating; + // A scale factor for the animation speed + private static final float ANIM_SCALE_FACTOR = 3.0f; + // The rotation angle of the titles + private static final float ROT_ANGLE = (float) Math.toRadians(60); + // Constant rotations + private static final Rotf POS_ANGLE = new Rotf(Vec3f.Y_AXIS, ROT_ANGLE); + private static final Rotf NEG_ANGLE = new Rotf(Vec3f.Y_AXIS, -ROT_ANGLE); + + private void computeCoords(Coordinate3 coordNode, float aspectRatio) { + Vec3fCollection coords = coordNode.getData(); + if (coords == null) { + coords = new Vec3fCollection(); + Vec3f zero = new Vec3f(); + for (int i = 0; i < 6; i++) { + coords.add(zero); + } + coordNode.setData(coords); + } + // Now compute the actual values + Vec3f lowerLeft = new Vec3f(-0.5f * DEFAULT_HEIGHT * aspectRatio, 0, 0); + Vec3f lowerRight = new Vec3f( 0.5f * DEFAULT_HEIGHT * aspectRatio, 0, 0); + Vec3f upperLeft = new Vec3f(-0.5f * DEFAULT_HEIGHT * aspectRatio, DEFAULT_HEIGHT, 0); + Vec3f upperRight = new Vec3f( 0.5f * DEFAULT_HEIGHT * aspectRatio, DEFAULT_HEIGHT, 0); + // First triangle + coords.set(0, upperRight); + coords.set(1, upperLeft); + coords.set(2, lowerLeft); + // Second triangle + coords.set(3, upperRight); + coords.set(4, lowerLeft); + coords.set(5, lowerRight); + } + + private void startLoading() { + final List<TitleGraph> queuedGraphs = new ArrayList<TitleGraph>(); + queuedGraphs.addAll(titles); + + new Thread(new Runnable() { + public void run() { + while (queuedGraphs.size() > 0) { + TitleGraph graph = queuedGraphs.remove(0); + BufferedImage img = null; + try { + img = ImageIO.read(new URL(graph.url)); + } catch (Exception e) { + System.out.println("Exception loading " + graph.url + ":"); + e.printStackTrace(); + } + if (img != null) { + graph.texture.setTexture(img, false); + // Figure out the new aspect ratio based on the image's width and height + float aspectRatio = (float) img.getWidth() / (float) img.getHeight(); + // Compute new coordinates + computeCoords(graph.coords, aspectRatio); + // Schedule a repaint + canvas.repaint(); + } + } + } + }).start(); + } + + private void setTargetIndex(int index) { + this.targetIndex = index; + if (!animating) { + time.rebase(); + } + canvas.repaint(); + } + + private boolean recompute(boolean force) { + if (!force) { + if (Math.abs(targetIndex - currentIndex) < EPSILON) + return false; + } + + time.update(); + float deltaT = (float) time.deltaT(); + + // Make the animation speed independent of frame rate + currentIndex = currentIndex + (targetIndex - currentIndex) * deltaT * ANIM_SCALE_FACTOR; + + // Now recompute the position of the camera + camera.setPosition(new Vec3f(currentIndex, 0.5f * DEFAULT_HEIGHT, DEFAULT_HEIGHT)); + + // Now recompute the orientations of each title + int firstIndex = (int) Math.floor(currentIndex); + int secondIndex = (int) Math.ceil(currentIndex); + + float alpha = currentIndex - firstIndex; + + int idx = 0; + for (TitleGraph graph : titles) { + if (idx < firstIndex) { + graph.xform.getTransform().setRotation(POS_ANGLE); + graph.xform.getTransform().setTranslation(new Vec3f(idx, 0, 0)); + } else if (idx > secondIndex) { + graph.xform.getTransform().setRotation(NEG_ANGLE); + graph.xform.getTransform().setTranslation(new Vec3f(idx, 0, 0)); + } else if (idx == firstIndex) { + // Interpolate + graph.xform.getTransform().setRotation(new Rotf(Vec3f.Y_AXIS, alpha * ROT_ANGLE)); + graph.xform.getTransform().setTranslation(new Vec3f(idx, 0, (1.0f - alpha) * 0.4f * DEFAULT_HEIGHT)); + } else { + // Interpolate + graph.xform.getTransform().setRotation(new Rotf(Vec3f.Y_AXIS, (1.0f - alpha) * -ROT_ANGLE)); + graph.xform.getTransform().setTranslation(new Vec3f(idx, 0, alpha * 0.4f * DEFAULT_HEIGHT)); + } + + ++idx; + } + + return true; + } + + public DisplayShelf(Group root, String[] images) { + this.images = images; + this.root = root; + time = new SystemTime(); + time.rebase(); + setLayout(new BorderLayout()); + camera = new PerspectiveCamera(); + camera.setNearDistance(0.1f); + camera.setFarDistance(20.0f); + canvas = new GLCanvas(); + canvas.addGLEventListener(new Listener()); + add(canvas, BorderLayout.CENTER); + final JSlider slider = new JSlider(0, images.length - 1, 0); + slider.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + setTargetIndex(slider.getValue()); + } + }); + add(slider, BorderLayout.SOUTH); + } + + class Listener implements GLEventListener { + private GLRenderAction ra = new GLRenderAction(); + + public void init(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + + // Build the scene graph + root.removeAllChildren(); + + // The images + Separator imageRoot = new Separator(); + + // The mirrored images, under the floor + Separator mirrorRoot = new Separator(); + + Transform mirrorXform = new Transform(); + // Mirror vertically + mirrorXform.getTransform().set(1, 1, -1.0f); + mirrorRoot.addChild(mirrorXform); + // Assume we know what we're doing here with setting per-vertex + // colors for each piece of geometry in one shot + Color4 colorNode = new Color4(); + Vec4fCollection colors = new Vec4fCollection(); + Vec4f fadeTop = new Vec4f(0.75f, 0.75f, 0.75f, 0.75f); + Vec4f fadeBot = new Vec4f(0.25f, 0.25f, 0.25f, 0.25f); + // First triangle + colors.add(fadeTop); + colors.add(fadeTop); + colors.add(fadeBot); + // Second triangle + colors.add(fadeTop); + colors.add(fadeBot); + colors.add(fadeBot); + colorNode.setData(colors); + mirrorRoot.addChild(colorNode); + + TriangleSet tris = new TriangleSet(); + tris.setNumTriangles(2); + + int i = 0; + for (String image : images) { + TitleGraph graph = new TitleGraph(image); + titles.add(graph); + computeCoords(graph.coords, DEFAULT_ASPECT_RATIO); + graph.xform.getTransform().setTranslation(new Vec3f(i, 0, 0)); + Separator sep = new Separator(); + sep.addChild(graph.xform); + sep.addChild(graph.coords); + sep.addChild(graph.texture); + TextureCoordinate2 texCoordNode = new TextureCoordinate2(); + Vec2fCollection texCoords = new Vec2fCollection(); + // Texture coordinates for two triangles + // First triangle + texCoords.add(new Vec2f( 1, 1)); + texCoords.add(new Vec2f( 0, 1)); + texCoords.add(new Vec2f( 0, 0)); + // Second triangle + texCoords.add(new Vec2f( 1, 1)); + texCoords.add(new Vec2f( 0, 0)); + texCoords.add(new Vec2f( 1, 0)); + texCoordNode.setData(texCoords); + sep.addChild(texCoordNode); + + sep.addChild(tris); + + // Add this to each rendering root + imageRoot.addChild(sep); + mirrorRoot.addChild(sep); + + ++i; + } + + // Now produce the floor geometry + float minx = -i; + float maxx = 2 * i; + // Furthest back from the camera + float minz = -2 * DEFAULT_HEIGHT; + // Assume this will be close enough to cover all of the mirrored geometry + float maxz = DEFAULT_HEIGHT; + Separator floorRoot = new Separator(); + Blend blend = new Blend(); + blend.setEnabled(true); + blend.setSourceFunc(Blend.ONE); + blend.setDestFunc(Blend.ONE_MINUS_SRC_ALPHA); + floorRoot.addChild(blend); + Coordinate3 floorCoords = new Coordinate3(); + floorCoords.setData(new Vec3fCollection()); + // First triangle + floorCoords.getData().add(new Vec3f(maxx, 0, minz)); + floorCoords.getData().add(new Vec3f(minx, 0, minz)); + floorCoords.getData().add(new Vec3f(minx, 0, maxz)); + // Second triangle + floorCoords.getData().add(new Vec3f(maxx, 0, minz)); + floorCoords.getData().add(new Vec3f(minx, 0, maxz)); + floorCoords.getData().add(new Vec3f(maxx, 0, maxz)); + floorRoot.addChild(floorCoords); + // Colors + Vec4f gray = new Vec4f(0.4f, 0.4f, 0.4f, 0.4f); + Vec4f clearGray = new Vec4f(0.0f, 0.0f, 0.0f, 0.0f); + Color4 floorColors = new Color4(); + floorColors.setData(new Vec4fCollection()); + // First triangle + floorColors.getData().add(gray); + floorColors.getData().add(gray); + floorColors.getData().add(clearGray); + // Second triangle + floorColors.getData().add(gray); + floorColors.getData().add(clearGray); + floorColors.getData().add(clearGray); + floorRoot.addChild(floorColors); + + floorRoot.addChild(tris); + + // Now set up the overall scene graph + root.addChild(camera); + root.addChild(imageRoot); + root.addChild(mirrorRoot); + root.addChild(floorRoot); + + startLoading(); + recompute(true); + } + + public void display(GLAutoDrawable drawable) { + // Recompute position of camera and orientation of images + boolean repaintAgain = recompute(false); + + // Redraw + GL gl = drawable.getGL(); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + ra.apply(root); + + if (repaintAgain) { + animating = true; + canvas.repaint(); + } else { + animating = false; + } + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + } + + public static void main(String[] args) { + Frame f = new Frame("Display Shelf test"); + f.setLayout(new BorderLayout()); + f.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + new Thread(new Runnable() { + public void run() { + System.exit(0); + } + }).start(); + } + }); + + // 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" + }; + + Separator root = new Separator(); + + DisplayShelf shelf = new DisplayShelf(root, images); + f.add(shelf); + GraphicsDevice dev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + DisplayMode curMode = dev.getDisplayMode(); + int height = (int) (0.5f * curMode.getWidth()); + f.setSize(curMode.getWidth(), height); + f.setLocation(0, (curMode.getHeight() - height) / 2); + f.setVisible(true); + } +} diff --git a/src/net/java/joglutils/msg/test/Test.java b/src/net/java/joglutils/msg/test/Test.java new file mode 100644 index 0000000..a782e3e --- /dev/null +++ b/src/net/java/joglutils/msg/test/Test.java @@ -0,0 +1,150 @@ +/* + * 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.test;
+
+import java.awt.Frame;
+import java.awt.event.*;
+import java.io.*;
+
+import javax.media.opengl.*;
+import com.sun.opengl.util.texture.*;
+
+import net.java.joglutils.msg.actions.*;
+import net.java.joglutils.msg.collections.*;
+import net.java.joglutils.msg.math.*;
+import net.java.joglutils.msg.nodes.*;
+
+/** A very basic test of the Minimal Scene Graph library. */
+
+public class Test {
+ public static void main(String[] args) {
+ Frame frame = new Frame("Minimal Scene Graph (MSG) Test");
+ GLCanvas canvas = new GLCanvas();
+ canvas.addGLEventListener(new Listener());
+ frame.add(canvas);
+ frame.setSize(512, 512);
+ frame.setVisible(true);
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ new Thread(new Runnable() {
+ public void run() {
+ System.exit(0);
+ }
+ }).start();
+ }
+ });
+ }
+
+ static class Listener implements GLEventListener {
+ private Separator root;
+ private GLRenderAction renderAction;
+
+ public void init(GLAutoDrawable drawable) {
+ root = new Separator();
+ PerspectiveCamera cam = new PerspectiveCamera();
+ cam.setPosition(new Vec3f(0, 0, 2));
+ root.addChild(cam);
+ Coordinate3 coordNode = new Coordinate3();
+ Vec3fCollection coords = new Vec3fCollection();
+ // First triangle
+ coords.add(new Vec3f( 1, 1, 0));
+ coords.add(new Vec3f(-1, 1, 0));
+ coords.add(new Vec3f(-1, -1, 0));
+ // Second triangle
+ coords.add(new Vec3f( 1, 1, 0));
+ coords.add(new Vec3f(-1, -1, 0));
+ coords.add(new Vec3f( 1, -1, 0));
+ coordNode.setData(coords);
+ root.addChild(coordNode);
+
+ // Texture coordinates
+ TextureCoordinate2 texCoordNode = new TextureCoordinate2();
+ Vec2fCollection texCoords = new Vec2fCollection();
+ // First triangle
+ texCoords.add(new Vec2f( 1, 1));
+ texCoords.add(new Vec2f( 0, 1));
+ texCoords.add(new Vec2f( 0, 0));
+ // Second triangle
+ texCoords.add(new Vec2f( 1, 1));
+ texCoords.add(new Vec2f( 0, 0));
+ texCoords.add(new Vec2f( 1, 0));
+ texCoordNode.setData(texCoords);
+ root.addChild(texCoordNode);
+
+ // Colors
+ Color4 colorNode = new Color4();
+ Vec4fCollection colors = new Vec4fCollection();
+ // First triangle
+ colors.add(new Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
+ colors.add(new Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
+ colors.add(new Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
+ // Second triangle
+ colors.add(new Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
+ colors.add(new Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
+ colors.add(new Vec4f(0.0f, 0.0f, 0.0f, 0.0f));
+ colorNode.setData(colors);
+ root.addChild(colorNode);
+
+ TriangleSet tris = new TriangleSet();
+ tris.setNumTriangles(2);
+ root.addChild(tris);
+
+ // Testing transforms
+ Transform xform = new Transform();
+ xform.getTransform().setTranslation(new Vec3f(2, -2, 0));
+ // xform.getTransform().setRotation(new Rotf(new Vec3f(0, 1, 0), (float) (-Math.PI / 4)));
+ root.addChild(xform);
+
+ root.addChild(tris);
+
+ GL gl = drawable.getGL();
+ gl.glEnable(GL.GL_DEPTH_TEST);
+
+ renderAction = new GLRenderAction();
+ }
+
+ public void display(GLAutoDrawable drawable) {
+ GL gl = drawable.getGL();
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ renderAction.apply(root);
+ }
+
+ public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {}
+ public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
+ }
+}
diff --git a/src/net/java/joglutils/msg/test/package.html b/src/net/java/joglutils/msg/test/package.html new file mode 100644 index 0000000..8697264 --- /dev/null +++ b/src/net/java/joglutils/msg/test/package.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<body> + +Test programs. + +</body> +</html> |