aboutsummaryrefslogtreecommitdiffstats
path: root/src/classes/javax/media
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes/javax/media')
-rw-r--r--src/classes/javax/media/opengl/GLArrayData.java153
-rw-r--r--src/classes/javax/media/opengl/GLArrayDataClient.java498
-rw-r--r--src/classes/javax/media/opengl/GLArrayDataServer.java265
-rw-r--r--src/classes/javax/media/opengl/GLContext.java59
-rw-r--r--src/classes/javax/media/opengl/GLProfile.java302
-rw-r--r--src/classes/javax/media/opengl/GLUniformData.java159
-rw-r--r--src/classes/javax/media/opengl/util/ImmModeSink.java455
-rwxr-xr-xsrc/classes/javax/media/opengl/util/PMVMatrix.java283
-rw-r--r--src/classes/javax/media/opengl/util/VBOBufferDraw.java392
-rw-r--r--src/classes/javax/media/opengl/util/glsl/ShaderCode.java122
-rw-r--r--src/classes/javax/media/opengl/util/glsl/ShaderProgram.java201
-rw-r--r--src/classes/javax/media/opengl/util/glsl/ShaderState.java583
12 files changed, 2917 insertions, 555 deletions
diff --git a/src/classes/javax/media/opengl/GLArrayData.java b/src/classes/javax/media/opengl/GLArrayData.java
new file mode 100644
index 000000000..db017b00a
--- /dev/null
+++ b/src/classes/javax/media/opengl/GLArrayData.java
@@ -0,0 +1,153 @@
+
+package javax.media.opengl;
+
+import java.nio.*;
+
+public interface GLArrayData {
+
+ /**
+ * Returns true if this data set is intended for a GLSL vertex shader attribute,
+ * otherwise false, ie intended for fixed function vertex pointer
+ */
+ public boolean isVertexAttribute();
+
+ /**
+ * The index of the predefined array index, see list below,
+ * or -1 in case of a shader attribute array.
+ *
+ * @see javax.media.opengl.GL#GL_VERTEX_ARRAY
+ * @see javax.media.opengl.GL#GL_NORMAL_ARRAY
+ * @see javax.media.opengl.GL#GL_COLOR_ARRAY
+ * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY
+ */
+ public int getIndex();
+
+ /**
+ * The name of the reflecting shader array attribute.
+ */
+ public String getName();
+
+ /**
+ * Set a new name for this array.
+ */
+ public void setName(String newName);
+
+
+ /**
+ * Returns the shader attribute location for this name,
+ * -1 if not yet determined
+ */
+ public int getLocation();
+
+ /**
+ * Sets the determined location of the shader attribute
+ * This is usually done within ShaderState.
+ *
+ * @see javax.media.opengl.util.glsl.ShaderState#glVertexAttribPointer(GL2ES2, GLArrayData)
+ */
+ public void setLocation(int v);
+
+
+ public boolean sealed();
+
+ /**
+ * The offset, if it's an VBO, otherwise -1
+ */
+ public long getOffset();
+
+ /**
+ * The Buffer holding the data, may be null in case of VBO
+ */
+ public Buffer getBuffer();
+
+ /**
+ * Determines wheather the data is server side (VBO),
+ * or a client side array (false).
+ */
+ public boolean isVBO();
+
+ /**
+ * The number of components per element
+ */
+ public int getComponents();
+
+ /**
+ * The GL data type of the components, ie. GL_FLOAT
+ */
+ public int getDataType();
+
+ /**
+ * True, if GL shall normalize fixed point data while converting
+ * them into float
+ */
+ public boolean getNormalized();
+
+ /**
+ * The distance to the next payload,
+ * allowing interleaved arrays.
+ */
+ public int getStride();
+
+ public int getVerticeNumber();
+
+ public int getBufferCompSize();
+
+ public String toString();
+
+ //
+ // Data and GL state modification ..
+ //
+
+ public void destroy(GL gl);
+
+ public void reset(GL gl);
+
+ /**
+ * If seal is true, it
+ * disable write operations to the buffer.
+ * Calls flip, ie limit:=position and position:=0.
+ * Also enables the buffer for OpenGL, and passes the data.
+ *
+ * If seal is false, it
+ * enable write operations continuing
+ * at the buffer position, where you left off at seal(true),
+ * ie position:=limit and limit:=capacity.
+ * Also disables the buffer for OpenGL.
+ *
+ * @see #seal(boolean)
+ */
+ public void seal(GL gl, boolean seal);
+
+ public void enableBuffer(GL gl, boolean enable);
+
+ //
+ // Data modification ..
+ //
+
+ public void reset();
+
+ /**
+ * If seal is true, it
+ * disable write operations to the buffer.
+ * Calls flip, ie limit:=position and position:=0.
+ *
+ * If seal is false, it
+ * enable write operations continuing
+ * at the buffer position, where you left off at seal(true),
+ * ie position:=limit and limit:=capacity.
+ *
+ */
+ public void seal(boolean seal);
+
+ public void rewind();
+ public void padding(int done);
+ public void put(Buffer v);
+ public void putb(byte v);
+ public void puts(short v);
+ public void puti(int v);
+ public void putx(int v);
+ public void putf(float v);
+ public void putd(double v);
+
+}
+
diff --git a/src/classes/javax/media/opengl/GLArrayDataClient.java b/src/classes/javax/media/opengl/GLArrayDataClient.java
new file mode 100644
index 000000000..5048e15c3
--- /dev/null
+++ b/src/classes/javax/media/opengl/GLArrayDataClient.java
@@ -0,0 +1,498 @@
+
+package javax.media.opengl;
+
+import javax.media.opengl.util.*;
+import com.sun.opengl.impl.GLReflection;
+
+import java.nio.*;
+
+public class GLArrayDataClient implements GLArrayData {
+
+ /**
+ * @arg index The GL array index
+ * @arg name The optional custom name for the GL array index, maybe null.
+ * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'.
+ * This name might be used as the shader attribute name.
+ * @arg comps The array component number
+ * @arg dataType The array index GL data type
+ * @arg normalized Wheather the data shall be normalized
+ *
+ * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ */
+ public static GLArrayDataClient createFixed(int index, String name, int comps, int dataType, boolean normalized,
+ int initialSize)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, false, true);
+ GLArrayDataClient adc = new GLArrayDataClient();
+ adc.init(name, index, comps, dataType, normalized, 0, null, initialSize, false);
+ return adc;
+ }
+
+ public static GLArrayDataClient createFixed(int index, String name, int comps, int dataType, boolean normalized,
+ int stride, Buffer buffer)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, false, true);
+ GLArrayDataClient adc = new GLArrayDataClient();
+ adc.init(name, index, comps, dataType, normalized, stride, buffer, comps*comps, false);
+ return adc;
+ }
+
+ public static GLArrayDataClient createGLSL(int index, String name, int comps, int dataType, boolean normalized,
+ int initialSize)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, true, true);
+ GLArrayDataClient adc = new GLArrayDataClient();
+ adc.init(name, index, comps, dataType, normalized, 0, null, initialSize, true);
+ return adc;
+ }
+
+ public static GLArrayDataClient createGLSL(int index, String name, int comps, int dataType, boolean normalized,
+ int stride, Buffer buffer)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, true, true);
+ GLArrayDataClient adc = new GLArrayDataClient();
+ adc.init(name, index, comps, dataType, normalized, stride, buffer, comps*comps, true);
+ return adc;
+ }
+
+ //
+ // Data read access
+ //
+
+ public boolean isVertexAttribute() { return isVertexAttribute; }
+
+ public int getIndex() { return index; }
+
+ public int getLocation() { return location; }
+
+ public void setLocation(int v) { location = v; }
+
+ public String getName() { return name; }
+
+ public long getOffset() { return -1; }
+
+ public Buffer getBuffer() { return buffer; }
+
+ public boolean isVBO() { return false; }
+
+ public int getComponents() { return components; }
+
+ public int getDataType() { return dataType; }
+
+ public boolean getNormalized() { return normalized; }
+
+ public int getStride() { return stride; }
+
+ public boolean sealed() { return sealed; }
+
+ public Class getBufferClass() {
+ return clazz;
+ }
+
+ public int getVerticeNumber() {
+ return ( buffer!=null ) ? ( buffer.limit() / components ) : 0 ;
+ }
+
+ //
+ // Data and GL state modification ..
+ //
+
+ public void setName(String newName) {
+ location = -1;
+ name = newName;
+ }
+
+ public void destroy(GL gl) {
+ reset(gl);
+ }
+
+ public void reset(GL gl) {
+ enableBuffer(gl, false);
+ reset();
+ }
+
+ public void seal(GL gl, boolean seal)
+ {
+ seal(seal);
+ if(sealedGL==seal) return;
+ sealedGL = seal;
+ if(seal) {
+ init_vbo(gl);
+
+ enableBuffer(gl, true);
+ } else {
+ enableBuffer(gl, false);
+ }
+ }
+
+ public void enableBuffer(GL gl, boolean enable)
+ {
+ if(enable) {
+ checkSeal(true);
+ if(!bufferEnabled && null!=buffer) {
+ buffer.rewind();
+ enableBufferGLImpl(gl, true);
+ }
+ } else if(bufferEnabled) {
+ enableBufferGLImpl(gl, false);
+ }
+ }
+
+ //
+ // Data modification ..
+ //
+
+ public void reset() {
+ if(buffer!=null) {
+ buffer.clear();
+ }
+ this.sealed=false;
+ this.bufferEnabled=false;
+ this.bufferWritten=false;
+ }
+
+ public void seal(boolean seal)
+ {
+ if(sealed==seal) return;
+ sealed = seal;
+ if(seal) {
+ bufferWritten=false;
+ if (null!=buffer) {
+ buffer.flip();
+ }
+ } else {
+ if (null!=buffer) {
+ buffer.position(buffer.limit());
+ buffer.limit(buffer.capacity());
+ }
+ }
+ }
+
+
+ public void rewind() {
+ if(buffer!=null) {
+ buffer.rewind();
+ }
+ }
+
+ public void padding(int done) {
+ if ( buffer==null || sealed ) return;
+ while(done<strideL) {
+ if(clazz==ByteBuffer.class) {
+ ((ByteBuffer)buffer).put((byte)0);
+ } else if(clazz==ShortBuffer.class) {
+ ((ShortBuffer)buffer).put((short)0);
+ } else if(clazz==IntBuffer.class) {
+ ((IntBuffer)buffer).put(0);
+ } else if(clazz==FloatBuffer.class) {
+ ((FloatBuffer)buffer).put(0f);
+ } else {
+ throw new GLException("Given Buffer Class not supported: "+clazz+" :\n\t"+this);
+ }
+ done++;
+ }
+ }
+
+ /**
+ * Generic buffer relative put method.
+ *
+ * This class buffer Class must match the arguments buffer class.
+ * The arguments remaining elements must be a multiple of this arrays element stride.
+ */
+ public void put(Buffer v) {
+ if ( buffer==null || sealed ) return;
+ if(0!=(v.remaining() % strideL)) {
+ throw new GLException("Buffer length ("+v.remaining()+") is not a multiple of component-stride:\n\t"+this);
+ }
+ Class vClazz = v.getClass();
+ if(!GLReflection.instanceOf(vClazz, clazz.getName())) {
+ throw new GLException("This array's buffer class "+clazz+" doesn't match the argument's Class: "+vClazz+" :\n\t"+this);
+ }
+ growBufferIfNecessary(v.remaining());
+ if(clazz==ByteBuffer.class) {
+ ((ByteBuffer)buffer).put((ByteBuffer)v);
+ } else if(clazz==ShortBuffer.class) {
+ ((ShortBuffer)buffer).put((ShortBuffer)v);
+ } else if(clazz==IntBuffer.class) {
+ ((IntBuffer)buffer).put((IntBuffer)v);
+ } else if(clazz==FloatBuffer.class) {
+ ((FloatBuffer)buffer).put((FloatBuffer)v);
+ }
+ }
+
+ public void putb(byte v) {
+ if ( buffer==null || sealed ) return;
+ growBufferIfNecessary(1);
+ if(clazz==ByteBuffer.class) {
+ ((ByteBuffer)buffer).put(v);
+ } else if(clazz==ShortBuffer.class) {
+ ((ShortBuffer)buffer).put((short)v);
+ } else if(clazz==IntBuffer.class) {
+ ((IntBuffer)buffer).put((int)v);
+ } else {
+ throw new GLException("Byte doesn't match Buffer Class: "+clazz+" :\n\t"+this);
+ }
+ }
+
+ public void puts(short v) {
+ if ( buffer==null || sealed ) return;
+ growBufferIfNecessary(1);
+ if(clazz==ShortBuffer.class) {
+ ((ShortBuffer)buffer).put(v);
+ } else if(clazz==IntBuffer.class) {
+ ((IntBuffer)buffer).put((int)v);
+ } else {
+ throw new GLException("Short doesn't match Buffer Class: "+clazz+" :\n\t"+this);
+ }
+ }
+
+ public void puti(int v) {
+ if ( buffer==null || sealed ) return;
+ growBufferIfNecessary(1);
+ if(clazz==IntBuffer.class) {
+ ((IntBuffer)buffer).put(v);
+ } else {
+ throw new GLException("Integer doesn't match Buffer Class: "+clazz+" :\n\t"+this);
+ }
+ }
+
+ public void putx(int v) {
+ puti(v);
+ }
+
+ public void putf(float v) {
+ if ( buffer==null || sealed ) return;
+ growBufferIfNecessary(1);
+ if(clazz==FloatBuffer.class) {
+ ((FloatBuffer)buffer).put(v);
+ } else if(clazz==IntBuffer.class) {
+ ((IntBuffer)buffer).put(FixedPoint.toFixed(v));
+ } else {
+ throw new GLException("Float doesn't match Buffer Class: "+clazz+" :\n\t"+this);
+ }
+ }
+
+ public void putd(double v) {
+ if ( buffer==null || sealed ) return;
+ growBufferIfNecessary(1);
+ if(clazz==FloatBuffer.class) {
+ ((FloatBuffer)buffer).put((float)v);
+ } else {
+ throw new GLException("Double doesn't match Buffer Class: "+clazz+" :\n\t"+this);
+ }
+ }
+
+ public String toString() {
+ return "GLArrayDataClient["+name+
+ ", index "+index+
+ ", location "+location+
+ ", isVertexAttribute "+isVertexAttribute+
+ ", dataType "+dataType+
+ ", bufferClazz "+clazz+
+ ", vertices "+getVerticeNumber()+
+ ", components "+components+
+ ", stride "+stride+"u "+strideB+"b "+strideL+"c"+
+ ", initialSize "+initialSize+
+ ", sealed "+sealed+
+ ", bufferEnabled "+bufferEnabled+
+ ", bufferWritten "+bufferWritten+
+ ", buffer "+buffer+
+ "]";
+ }
+
+ public static final Class getBufferClass(int dataType) {
+ switch(dataType) {
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_BYTE:
+ return ByteBuffer.class;
+ case GL.GL_SHORT:
+ case GL.GL_UNSIGNED_SHORT:
+ return ShortBuffer.class;
+ case GL2ES1.GL_FIXED:
+ return IntBuffer.class;
+ case GL.GL_FLOAT:
+ return FloatBuffer.class;
+ default:
+ throw new GLException("Given OpenGL data type not supported: "+dataType);
+ }
+ }
+
+ public final int getBufferCompSize() {
+ if(clazz==ByteBuffer.class) {
+ return BufferUtil.SIZEOF_BYTE;
+ }
+ if(clazz==ShortBuffer.class) {
+ return BufferUtil.SIZEOF_SHORT;
+ }
+ if(clazz==IntBuffer.class) {
+ return BufferUtil.SIZEOF_INT;
+ }
+ if(clazz==FloatBuffer.class) {
+ return BufferUtil.SIZEOF_FLOAT;
+ }
+ throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this);
+ }
+
+ // non public matters
+
+ protected final boolean growBufferIfNecessary(int spare) {
+ if(buffer==null || buffer.remaining()<spare) {
+ growBuffer(initialSize);
+ return true;
+ }
+ return false;
+ }
+
+ protected final void growBuffer(int additional) {
+ if(sealed || 0==additional || 0==components) return;
+
+ // add the stride delta
+ additional += (additional/components)*(strideL-components);
+
+ if(components>0) {
+ int osize = (buffer!=null)?buffer.capacity():0;
+ if(clazz==ByteBuffer.class) {
+ ByteBuffer newBBuffer = BufferUtil.newByteBuffer( (osize+additional) * components );
+ if(buffer!=null) {
+ buffer.flip();
+ newBBuffer.put((ByteBuffer)buffer);
+ }
+ buffer = newBBuffer;
+ } else if(clazz==ShortBuffer.class) {
+ ShortBuffer newSBuffer = BufferUtil.newShortBuffer( (osize+additional) * components );
+ if(buffer!=null) {
+ buffer.flip();
+ newSBuffer.put((ShortBuffer)buffer);
+ }
+ buffer = newSBuffer;
+ } else if(clazz==IntBuffer.class) {
+ IntBuffer newIBuffer = BufferUtil.newIntBuffer( (osize+additional) * components );
+ if(buffer!=null) {
+ buffer.flip();
+ newIBuffer.put((IntBuffer)buffer);
+ }
+ buffer = newIBuffer;
+ } else if(clazz==FloatBuffer.class) {
+ FloatBuffer newFBuffer = BufferUtil.newFloatBuffer( (osize+additional) * components );
+ if(buffer!=null) {
+ buffer.flip();
+ newFBuffer.put((FloatBuffer)buffer);
+ }
+ buffer = newFBuffer;
+ } else {
+ throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this);
+ }
+ }
+ }
+
+ protected final void checkSeal(boolean test) throws GLException {
+ if(sealed!=test) {
+ if(test) {
+ throw new GLException("Not Sealed yet, seal first:\n\t"+this);
+ } else {
+ throw new GLException("Already Sealed, can't modify VBO:\n\t"+this);
+ }
+ }
+ }
+
+ protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data,
+ int initialSize, boolean isVertexAttribute)
+ throws GLException
+ {
+ this.isVertexAttribute = isVertexAttribute;
+ this.index = index;
+ this.location = -1;
+ this.name = (null==name)?GLContext.getPredefinedArrayIndexName(index):name;
+ if(null==this.name) {
+ throw new GLException("Not a valid GL array index: "+index);
+ }
+ this.dataType = dataType;
+ this.clazz = getBufferClass(dataType);
+ switch(dataType) {
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL2ES1.GL_FIXED:
+ this.normalized = normalized;
+ break;
+ default:
+ this.normalized = false;
+ }
+
+ int bpc = getBufferCompSize();
+ if(0<stride && stride<comps*bpc) {
+ throw new GLException("stride ("+stride+") lower than component bytes, "+comps+" * "+bpc);
+ }
+ if(0<stride && stride%bpc!=0) {
+ throw new GLException("stride ("+stride+") not a multiple of bpc "+bpc);
+ }
+ this.buffer = data;
+ this.components = comps;
+ this.stride=stride;
+ this.strideB=(0==stride)?comps*bpc:stride;
+ this.strideL=(0==stride)?comps:strideB/bpc;
+ this.initialSize = initialSize;
+ this.sealed=false;
+ this.sealedGL=false;
+ this.bufferEnabled=false;
+ this.bufferWritten=false;
+ if(null==buffer) {
+ growBuffer(initialSize);
+ }
+ }
+
+ protected void enableBufferGLImpl(GL gl, boolean enable) {
+ if(enable) {
+ gl.glEnableClientState(index);
+ bufferEnabled = true;
+
+ switch(index) {
+ case GL.GL_VERTEX_ARRAY:
+ gl.glVertexPointer(this);
+ break;
+ case GL.GL_NORMAL_ARRAY:
+ gl.glNormalPointer(this);
+ break;
+ case GL.GL_COLOR_ARRAY:
+ gl.glColorPointer(this);
+ break;
+ case GL.GL_TEXTURE_COORD_ARRAY:
+ gl.glTexCoordPointer(this);
+ break;
+ default:
+ throw new GLException("invalid glArrayIndex: "+index+":\n\t"+this);
+ }
+ bufferWritten=true;
+ } else {
+ gl.glDisableClientState(index);
+ bufferEnabled = false;
+ }
+ }
+
+ protected void init_vbo(GL gl) {}
+
+ protected GLArrayDataClient() { }
+
+ protected int index;
+ protected int location;
+ protected String name;
+ protected int components;
+ protected int dataType;
+ protected boolean normalized;
+ protected int stride; // user given stride
+ protected int strideB; // stride in bytes
+ protected int strideL; // stride in logical components
+ protected Class clazz;
+ protected Buffer buffer;
+ protected int initialSize;
+ protected boolean isVertexAttribute;
+ protected boolean sealed, sealedGL;
+ protected boolean bufferEnabled;
+ protected boolean bufferWritten;
+}
+
diff --git a/src/classes/javax/media/opengl/GLArrayDataServer.java b/src/classes/javax/media/opengl/GLArrayDataServer.java
new file mode 100644
index 000000000..d4f2604fd
--- /dev/null
+++ b/src/classes/javax/media/opengl/GLArrayDataServer.java
@@ -0,0 +1,265 @@
+
+package javax.media.opengl;
+
+import javax.media.opengl.*;
+import java.nio.*;
+import com.sun.opengl.impl.*;
+
+public class GLArrayDataServer extends GLArrayDataClient implements GLArrayData {
+
+ //
+ // lifetime matters
+ //
+
+ /**
+ * Create a VBOBuffer object, using a predefined fixed function array index
+ * and starting with a given Buffer object incl it's stride
+ *
+ * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected.
+ * On profile ES2 the fixed function emulation will transform these calls to
+ * EnableVertexAttribArray and VertexAttribPointer calls,
+ * and a predefined vertex attribute variable name will be choosen.
+ *
+ * @arg index The GL array index
+ * @arg name The optional custom name for the GL array index, maybe null.
+ * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'.
+ * This name might be used as the shader attribute name.
+ * @arg comps The array component number
+ * @arg dataType The array index GL data type
+ * @arg normalized Wheather the data shall be normalized
+ *
+ * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ */
+ public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized,
+ int stride, Buffer buffer, int glBufferUsage)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, false, true);
+
+ GLArrayDataServer ads = new GLArrayDataServer();
+ ads.init(name, index, comps, dataType, normalized, stride, buffer, 0, buffer.limit(), glBufferUsage, false);
+ return ads;
+ }
+
+ /**
+ * Create a VBOBuffer object, using a predefined fixed function array index
+ * and starting with a new created Buffer object with initialSize size
+ *
+ * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected.
+ * On profile ES2 the fixed function emulation will transform these calls to
+ * EnableVertexAttribArray and VertexAttribPointer calls,
+ * and a predefined vertex attribute variable name will be choosen.
+ *
+ * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ */
+ public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized,
+ int initialSize, int glBufferUsage)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, false, true);
+
+ GLArrayDataServer ads = new GLArrayDataServer();
+ ads.init(name, index, comps, dataType, normalized, 0, null, 0, initialSize, glBufferUsage, false);
+ return ads;
+ }
+
+ /**
+ * Create a VBOBuffer object, using a predefined fixed function array index
+ * and starting with a given Buffer offset incl it's stride
+ *
+ * This object can neither be enabled, nor rendered, since no knowledge of the buffer
+ * itself is available. This object is only a VBO variant of GLArrayData
+ * and cannot being drawn.
+ *
+ * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ */
+ public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized,
+ int stride, long bufferOffset)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(index, comps, dataType, false, true);
+
+ GLArrayDataServer ads = new GLArrayDataServer();
+ ads.init(name, index, comps, dataType, normalized, stride, null, bufferOffset, 0, -1, false);
+ return ads;
+ }
+
+ /**
+ * Create a VBOBuffer object, using a custom GLSL array attribute name
+ * and starting with a new created Buffer object with initialSize size
+ *
+ * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ */
+ public static GLArrayDataServer createGLSL(String name, int comps, int dataType, boolean normalized,
+ int initialSize, int glBufferUsage)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(-1, comps, dataType, true, true);
+ Class[] types = new Class[]{ String.class, int.class, int.class, boolean.class, int.class, int.class };
+ Object[] args = new Object[]{ name, new Integer(comps), new Integer(dataType),
+ new Boolean(normalized), new Integer(initialSize), new Integer(glBufferUsage) } ;
+
+ if(GLProfile.isGL2ES2()) {
+ return (GLArrayDataServer) GLReflection.createInstance("com.sun.opengl.impl.glsl.GLSLArrayDataServer", types, args);
+ }
+ throw new GLException("GLArrayDataServer not supported for profile: "+GLProfile.getProfile());
+ }
+
+ /**
+ * Create a VBOBuffer object, using a custom GLSL array attribute name
+ * and starting with a given Buffer object incl it's stride
+ *
+ * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int)
+ */
+ public static GLArrayDataServer createGLSL(String name, int comps, int dataType, boolean normalized,
+ int stride, Buffer buffer, int glBufferUsage)
+ throws GLException
+ {
+ GLProfile.isValidateArrayDataType(-1, comps, dataType, true, true);
+ Class[] types = new Class[]{ String.class, int.class, int.class, boolean.class, int.class, Buffer.class, int.class };
+ Object[] args = new Object[]{ name, new Integer(comps), new Integer(dataType),
+ new Boolean(normalized), new Integer(stride), buffer, new Integer(glBufferUsage) } ;
+
+ if(GLProfile.isGL2ES2()) {
+ return (GLArrayDataServer) GLReflection.createInstance("com.sun.opengl.impl.glsl.GLSLArrayDataServer", types, args);
+ }
+ throw new GLException("GLArrayDataServer not supported for profile: "+GLProfile.getProfile());
+ }
+
+ //
+ // Data matters GLArrayData
+ //
+
+ public long getOffset() { return vboUsage?bufferOffset:-1; }
+
+ public boolean isVBO() { return vboUsage; }
+
+ //
+ // Data and GL state modification ..
+ //
+
+ public void destroy(GL gl) {
+ super.destroy(gl);
+ if(vboName!=0) {
+ int[] tmp = new int[1];
+ tmp[0] = vboName;
+ gl.glDeleteBuffers(1, tmp, 0);
+ vboName = 0;
+ }
+ }
+
+ //
+ // data matters
+ //
+
+ /**
+ * Convenient way do disable the VBO behavior and
+ * switch to client side data one
+ * Only possible if buffer is defined.
+ */
+ public void setVBOUsage(boolean vboUsage) {
+ checkSeal(false);
+ this.vboUsage=(null!=buffer)?vboUsage:true;
+ }
+
+ public int getBufferUsage() {
+ return glBufferUsage;
+ }
+
+ public String toString() {
+ return "GLArrayDataServer["+name+
+ ", index "+index+
+ ", location "+location+
+ ", isVertexAttribute "+isVertexAttribute+
+ ", dataType "+dataType+
+ ", bufferClazz "+clazz+
+ ", vertices "+getVerticeNumber()+
+ ", components "+components+
+ ", stride "+stride+"u "+strideB+"b "+strideL+"c"+
+ ", initialSize "+initialSize+
+ ", glBufferUsage "+glBufferUsage+
+ ", vboUsage "+vboUsage+
+ ", vboName "+vboName+
+ ", sealed "+sealed+
+ ", bufferEnabled "+bufferEnabled+
+ ", bufferWritten "+bufferWritten+
+ ", buffer "+buffer+
+ ", offset "+bufferOffset+
+ "]";
+ }
+
+ //
+ // non public matters ..
+ //
+
+ protected void init(String name, int index, int comps, int dataType, boolean normalized,
+ int stride, Buffer data, long offset, int initialSize, int glBufferUsage, boolean isVertexAttribute)
+ throws GLException
+ {
+ super.init(name, index, comps, dataType, normalized, stride, data, initialSize, isVertexAttribute);
+
+ vboUsage=true;
+
+ if( ! (GLProfile.isGL2ES2() && glBufferUsage==GL2ES2.GL_STREAM_DRAW) ) {
+ switch(glBufferUsage) {
+ case -1: // nop
+ case GL2ES1.GL_STATIC_DRAW:
+ case GL2ES1.GL_DYNAMIC_DRAW:
+ break;
+ default:
+ throw new GLException("invalid glBufferUsage: "+glBufferUsage+":\n\t"+this);
+ }
+ }
+ this.bufferOffset=offset;
+ this.glBufferUsage = glBufferUsage;
+ this.vboName = 0;
+ }
+
+ protected void enableBufferGLImpl(GL gl, boolean enable) {
+ if(enable) {
+ gl.glEnableClientState(index);
+ bufferEnabled = true;
+
+ if(vboUsage) {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName);
+ if(!bufferWritten) {
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * getBufferCompSize(), buffer, glBufferUsage);
+ }
+ }
+ switch(index) {
+ case GL.GL_VERTEX_ARRAY:
+ gl.glVertexPointer(this);
+ break;
+ case GL.GL_NORMAL_ARRAY:
+ gl.glNormalPointer(this);
+ break;
+ case GL.GL_COLOR_ARRAY:
+ gl.glColorPointer(this);
+ break;
+ case GL.GL_TEXTURE_COORD_ARRAY:
+ gl.glTexCoordPointer(this);
+ break;
+ default:
+ throw new GLException("invalid glArrayIndex: "+index+":\n\t"+this);
+ }
+ bufferWritten=true;
+ } else {
+ gl.glDisableClientState(index);
+ bufferEnabled = false;
+ }
+ }
+ protected void init_vbo(GL gl) {
+ if(vboUsage && vboName==0) {
+ int[] tmp = new int[1];
+ gl.glGenBuffers(1, tmp, 0);
+ vboName = tmp[0];
+ }
+ }
+
+ protected long bufferOffset;
+ protected int glBufferUsage;
+ protected int vboName;
+ protected boolean vboUsage;
+
+}
+
diff --git a/src/classes/javax/media/opengl/GLContext.java b/src/classes/javax/media/opengl/GLContext.java
index 02345ef04..998ede419 100644
--- a/src/classes/javax/media/opengl/GLContext.java
+++ b/src/classes/javax/media/opengl/GLContext.java
@@ -193,4 +193,63 @@ public abstract class GLContext {
"(GL: "+getGL().getClass().getName()+","+
" Factory: "+ getGLDrawable().getFactory().getClass().getName()+")";
}
+
+ /**
+ * Mapping fixed function (client) array indices to
+ * GLSL array attribute names.
+ *
+ * Useful for uniq mapping of canonical array index names as listed.
+ *
+ * @see #mgl_Vertex
+ * @see javax.media.opengl.GL#GL_VERTEX_ARRAY
+ * @see #mgl_Normal
+ * @see javax.media.opengl.GL#GL_NORMAL_ARRAY
+ * @see #mgl_Color
+ * @see javax.media.opengl.GL#GL_COLOR_ARRAY
+ * @see #mgl_MultiTexCoord
+ * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY
+ * @see javax.media.opengl.GL#glEnableClientState
+ * @see javax.media.opengl.GL#glVertexPointer
+ * @see javax.media.opengl.GL#glColorPointer
+ * @see javax.media.opengl.GL#glNormalPointer
+ * @see javax.media.opengl.GL#glTexCoordPointer
+ */
+ public static String getPredefinedArrayIndexName(int glArrayIndex) {
+ switch(glArrayIndex) {
+ case GL.GL_VERTEX_ARRAY:
+ return mgl_Vertex;
+ case GL.GL_NORMAL_ARRAY:
+ return mgl_Normal;
+ case GL.GL_COLOR_ARRAY:
+ return mgl_Color;
+ case GL.GL_TEXTURE_COORD_ARRAY:
+ return mgl_MultiTexCoord;
+ }
+ return null;
+ }
+
+ /**
+ * String name for
+ * @see javax.media.opengl.GL#GL_VERTEX_ARRAY
+ */
+ public static final String mgl_Vertex = "mgl_Vertex";
+
+ /**
+ * String name for
+ * @see javax.media.opengl.GL#GL_NORMAL_ARRAY
+ */
+ public static final String mgl_Normal = "mgl_Normal";
+
+ /**
+ * String name for
+ * @see javax.media.opengl.GL#GL_COLOR_ARRAY
+ */
+ public static final String mgl_Color = "mgl_Color";
+
+ /**
+ * String name for
+ * @see javax.media.opengl.GL#GL_TEXTURE_COORD_ARRAY
+ */
+ public static final String mgl_MultiTexCoord = "mgl_MultiTexCoord" ;
+
}
diff --git a/src/classes/javax/media/opengl/GLProfile.java b/src/classes/javax/media/opengl/GLProfile.java
index ff68a6d38..67e427f5a 100644
--- a/src/classes/javax/media/opengl/GLProfile.java
+++ b/src/classes/javax/media/opengl/GLProfile.java
@@ -212,4 +212,306 @@ public class GLProfile {
throw new GLUnsupportedException("unsupported profile \"" + profile + "\"");
}
}
+
+ /**
+ * General validation if type is a valid GL data type
+ * for the current profile
+ */
+ public static boolean isValidDataType(int type, boolean throwException) {
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case GL.GL_FIXED:
+ return true;
+ case javax.media.opengl.GL2ES2.GL_INT:
+ case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
+ if( isGL2ES2() ) {
+ return true;
+ }
+ case javax.media.opengl.GL2.GL_DOUBLE:
+ case javax.media.opengl.GL2.GL_2_BYTES:
+ case javax.media.opengl.GL2.GL_3_BYTES:
+ case javax.media.opengl.GL2.GL_4_BYTES:
+ if( isGL2ES12() || isGL2() ) {
+ return true;
+ }
+ }
+ if(throwException) {
+ throw new GLException("Illegal data type on profile "+GLProfile.getProfile()+": "+type);
+ }
+ return false;
+ }
+
+ public static boolean isValidateArrayDataType(int index, int comps, int type,
+ boolean isVertexAttribPointer, boolean throwException) {
+ String indexName = GLContext.getPredefinedArrayIndexName(index);
+ if(GLProfile.isGLES1()) {
+ if(isVertexAttribPointer) {
+ if(throwException) {
+ throw new GLException("Illegal array type for "+indexName+" on profile GLES1: VertexAttribPointer");
+ }
+ return false;
+ }
+ switch(index) {
+ case GL.GL_VERTEX_ARRAY:
+ case GL.GL_TEXTURE_COORD_ARRAY:
+ switch(type) {
+ case GL.GL_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_FIXED:
+ case GL.GL_FLOAT:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GLES1: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GL.GL_NORMAL_ARRAY:
+ switch(type) {
+ case GL.GL_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_FIXED:
+ case GL.GL_FLOAT:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GLES1: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 3:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GL.GL_COLOR_ARRAY:
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_FIXED:
+ case GL.GL_FLOAT:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GLES1: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ }
+ } else if(GLProfile.isGLES2()) {
+ // simply ignore !isVertexAttribPointer case, since it is simulated anyway ..
+
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case GL.GL_FIXED:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GLES2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ } else if(GLProfile.isGL2ES12() || GLProfile.isGL2()) {
+ if(isVertexAttribPointer) {
+ switch(index) {
+ case GL.GL_VERTEX_ARRAY:
+ case GL.GL_TEXTURE_COORD_ARRAY:
+ case GL.GL_NORMAL_ARRAY:
+ case GL.GL_COLOR_ARRAY:
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case javax.media.opengl.GL2ES2.GL_INT:
+ case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
+ case javax.media.opengl.GL2.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ }
+ } else {
+ switch(index) {
+ case GL.GL_VERTEX_ARRAY:
+ switch(type) {
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case javax.media.opengl.GL2ES2.GL_INT:
+ case javax.media.opengl.GL2.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GL.GL_NORMAL_ARRAY:
+ switch(type) {
+ case GL.GL_BYTE:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case javax.media.opengl.GL2ES2.GL_INT:
+ case javax.media.opengl.GL2.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 3:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GLES1: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GL.GL_COLOR_ARRAY:
+ switch(type) {
+ case GL.GL_UNSIGNED_BYTE:
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case javax.media.opengl.GL2ES2.GL_INT:
+ case javax.media.opengl.GL2ES2.GL_UNSIGNED_INT:
+ case javax.media.opengl.GL2.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ case GL.GL_TEXTURE_COORD_ARRAY:
+ switch(type) {
+ case GL.GL_SHORT:
+ case GL.GL_FLOAT:
+ case javax.media.opengl.GL2ES2.GL_INT:
+ case javax.media.opengl.GL2.GL_DOUBLE:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal data type for "+indexName+" on profile GL2: "+type);
+ }
+ return false;
+ }
+ switch(comps) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ default:
+ if(throwException) {
+ throw new GLException("Illegal component number for "+indexName+" on profile GL2: "+comps);
+ }
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ return true;
+ }
+
}
diff --git a/src/classes/javax/media/opengl/GLUniformData.java b/src/classes/javax/media/opengl/GLUniformData.java
new file mode 100644
index 000000000..929a59a2a
--- /dev/null
+++ b/src/classes/javax/media/opengl/GLUniformData.java
@@ -0,0 +1,159 @@
+
+package javax.media.opengl;
+
+import java.nio.*;
+
+public class GLUniformData {
+
+ /**
+ * int atom
+ *
+ * Number of objects is 1
+ *
+ * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
+ */
+ public GLUniformData(String name, int val) {
+ init(name, 1, new Integer(val));
+ }
+
+ /**
+ * float atom
+ *
+ * Number of objects is 1
+ *
+ * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
+ */
+ public GLUniformData(String name, float val) {
+ init(name, 1, new Float(val));
+ }
+
+ /**
+ * Multiple IntBuffer Vector
+ *
+ * Number of objects is calculated by data.limit()/components
+ *
+ * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
+ */
+ public GLUniformData(String name, int components, IntBuffer data) {
+ init(name, components, data);
+ }
+
+ /**
+ * Multiple FloatBuffer Vector
+ *
+ * Number of objects is calculated by data.limit()/components
+ *
+ * @arg components number of elements of one object, ie 4 for GL_FLOAT_VEC4,
+ */
+ public GLUniformData(String name, int components, FloatBuffer data) {
+ init(name, components, data);
+ }
+
+ /**
+ * Multiple FloatBuffer Matrix
+ *
+ * Number of objects is calculated by data.limit()/(rows*columns)
+ *
+ * @arg rows the matrix rows
+ * @arg column the matrix column
+ */
+ public GLUniformData(String name, int rows, int columns, FloatBuffer data) {
+ init(name, rows, columns, data);
+ }
+
+ public void setData(int data) { init(new Integer(data)); }
+ public void setData(float data) { init(new Float(data)); }
+ public void setData(IntBuffer data) { init(data); }
+ public void setData(FloatBuffer data) { init(data); }
+
+ public int intValue() { return ((Integer)data).intValue(); };
+ public float floatValue() { return ((Float)data).floatValue(); };
+ public IntBuffer intBufferValue() { return (IntBuffer)data; };
+ public FloatBuffer floatBufferValue() { return (FloatBuffer)data; };
+
+ public String toString() {
+ return "GLUniformData[name "+name+
+ ", location "+location+
+ ", size "+rows+"*"+columns+
+ ", count "+count+
+ ", matrix "+isMatrix+
+ ", data "+data+
+ "]";
+ }
+
+ private void init(String name, int rows, int columns, Object data) {
+ if( 2>rows || rows>4 || 2>columns || columns>4 ) {
+ throw new GLException("rowsXcolumns must be within [2..4]X[2..4], is: "+rows+"X"+columns);
+ }
+ this.name=name;
+ this.rows=rows;
+ this.columns=columns;
+ this.isMatrix=true;
+ this.location=-1;
+ init(data);
+ }
+
+ private void init(String name, int components, Object data) {
+ if( 1>components || components>4 ) {
+ throw new GLException("components must be within [1..4], is: "+components);
+ }
+ this.name=name;
+ this.columns=components;
+ this.rows=1;
+ this.isMatrix=false;
+ this.location=-1;
+ init(data);
+ }
+
+ private void init(Object data) {
+ if(data instanceof Buffer) {
+ int sz = rows*columns;
+ Buffer buffer = (Buffer)data;
+ if(buffer.limit()<sz || 0!=buffer.limit()%sz) {
+ throw new GLException("data buffer size invalid: new buffer limit: "+buffer.limit()+"\n\t"+this);
+ }
+ this.count=buffer.limit()/(rows*columns);
+ } else {
+ if(isMatrix) {
+ throw new GLException("Atom type not allowed for matrix : "+this);
+ }
+ this.count=1;
+ }
+ this.data=data;
+ }
+
+ public String getName() { return name; }
+
+ public int getLocation() { return location; }
+
+ /**
+ * Sets the determined location of the shader uniform
+ * This is usually done within ShaderState.
+ *
+ * @see javax.media.opengl.util.glsl.ShaderState#glUniform(GL2ES2, GLUniformData)
+ */
+ public void setLocation(int location) { this.location=location; }
+
+ public Object getObject() {
+ return data;
+ }
+ public Buffer getBuffer() {
+ return (data instanceof Buffer)?(Buffer)data:null;
+ }
+ public boolean isBuffer() {
+ return (data instanceof Buffer);
+ }
+ public boolean isMatrix() { return isMatrix; }
+
+ public int count() { return count; }
+ public int components() { return rows*columns; }
+ public int rows() { return rows; }
+ public int columns() { return columns; }
+
+ private String name;
+ private int location;
+ private int rows, columns;
+ private int count;
+ private Object data;
+ private boolean isMatrix;
+}
diff --git a/src/classes/javax/media/opengl/util/ImmModeSink.java b/src/classes/javax/media/opengl/util/ImmModeSink.java
index 459372d94..5de9df99a 100644
--- a/src/classes/javax/media/opengl/util/ImmModeSink.java
+++ b/src/classes/javax/media/opengl/util/ImmModeSink.java
@@ -2,6 +2,7 @@
package javax.media.opengl.util;
import javax.media.opengl.*;
+import com.sun.opengl.impl.GLReflection;
import java.nio.*;
import java.util.Iterator;
import java.util.ArrayList;
@@ -10,24 +11,39 @@ public class ImmModeSink {
public static final boolean DEBUG_BEGIN_END = false;
public static final boolean DEBUG_DRAW = false;
- public static final boolean FLOAT2FIXED = false;
- public static final int GL_QUADS = 0x0007;
+ // public static final int GL_QUADS = 0x0007; // Needs data manipulation
public static final int GL_QUAD_STRIP = 0x0008;
public static final int GL_POLYGON = 0x0009;
- public ImmModeSink(int glDataType, int glDrawUsage,
- int vComps, int nComps, int cComps, int tComps, int initialSize) {
-
- vboSet = new VBOSet(glDataType, glDrawUsage, vComps, nComps, cComps, tComps, initialSize);
- this.vboSetList = new ArrayList();
+ /**
+ * Uses a GL2ES1, or ES2 fixed function emulation immediate mode sink
+ */
+ public static ImmModeSink createFixed(int glBufferUsage, int initialSize,
+ int vComps, int vDataType,
+ int cComps, int cDataType,
+ int nComps, int nDataType,
+ int tComps, int tDataType) {
+ return new ImmModeSink(glBufferUsage, initialSize,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false);
}
- private void destroyList(GL gl) {
- for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) {
- ((VBOSet)i.next()).destroy(gl);
- }
- vboSetList.clear();
+ /**
+ * Uses a GL2ES2 GLSL shader immediate mode sink.
+ * To issue the draw() command,
+ * a ShaderState must be current, using ShaderState.glUseProgram().
+ *
+ * @see #draw(GL, boolean)
+ * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean)
+ * @see javax.media.opengl.util.glsl.ShaderState#getCurrent()
+ */
+ public static ImmModeSink createGLSL(int glBufferUsage, int initialSize,
+ int vComps, int vDataType,
+ int cComps, int cDataType,
+ int nComps, int nDataType,
+ int tComps, int tDataType) {
+ return new ImmModeSink(glBufferUsage, initialSize,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true);
}
public void destroy(GL gl) {
@@ -46,9 +62,20 @@ public class ImmModeSink {
}
public String toString() {
- return "ImmModeSink[listsz: "+vboSetList.size()+
- ",\n"+vboSet+
- "]";
+ StringBuffer sb = new StringBuffer("ImmModeSink[");
+ sb.append(",\n\tVBO list: "+vboSetList.size()+" [");
+ for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) {
+ sb.append("\n\t");
+ sb.append( (VBOSet)i.next() );
+ }
+ if(vboSetList.size()>0) {
+ sb.append("\n\t],\nVBO current: NOP]");
+ } else {
+ sb.append("\n\t],\nVBO current: \n");
+ sb.append(vboSet);
+ sb.append("\n]");
+ }
+ return sb.toString();
}
public void draw(GL gl, boolean disableBufferAfterDraw) {
@@ -58,7 +85,18 @@ public class ImmModeSink {
}
int n=0;
for(Iterator i=vboSetList.iterator(); i.hasNext() ; n++) {
- ((VBOSet)i.next()).draw(gl, disableBufferAfterDraw, n);
+ ((VBOSet)i.next()).draw(gl, null, disableBufferAfterDraw, n);
+ }
+ }
+
+ public void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw) {
+ if(DEBUG_DRAW) {
+ Exception e = new Exception("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
+ e.printStackTrace();
+ }
+ int n=0;
+ for(Iterator i=vboSetList.iterator(); i.hasNext() ; n++) {
+ ((VBOSet)i.next()).draw(gl, indices, disableBufferAfterDraw, n);
}
}
@@ -69,9 +107,10 @@ public class ImmModeSink {
}
vboSet.modeOrig = mode;
switch(mode) {
- case GL_QUADS:
- mode=GL.GL_TRIANGLE_STRIP;
- break;
+ // Needs data manipulation ..
+ //case GL_QUADS:
+ // mode=GL.GL_LINES;
+ // break;
case GL_QUAD_STRIP:
mode=GL.GL_TRIANGLE_STRIP;
break;
@@ -84,17 +123,25 @@ public class ImmModeSink {
}
public final void glEnd(GL gl) {
- glEnd(gl, true);
+ glEnd(gl, null, true);
}
public void glEnd(GL gl, boolean immediateDraw) {
+ glEnd(gl, null, immediateDraw);
+ }
+
+ public final void glEnd(GL gl, Buffer indices) {
+ glEnd(gl, indices, true);
+ }
+
+ private void glEnd(GL gl, Buffer indices, boolean immediateDraw) {
if(DEBUG_BEGIN_END) {
Exception e = new Exception("ImmModeSink START glEnd(immediate: "+immediateDraw+"):\n\t"+this);
e.printStackTrace();
}
if(immediateDraw) {
vboSet.seal(gl, false);
- vboSet.draw(gl, true, -1);
+ vboSet.draw(gl, indices, true, -1);
reset(gl);
} else {
vboSet.seal(gl, true);
@@ -103,6 +150,9 @@ public class ImmModeSink {
}
}
+ public void glVertexv(Buffer v) {
+ vboSet.glVertexv(v);
+ }
public final void glVertex2f(float x, float y) {
vboSet.glVertex2f(x,y);
}
@@ -111,14 +161,27 @@ public class ImmModeSink {
vboSet.glVertex3f(x,y,z);
}
+ public void glNormalv(Buffer v) {
+ vboSet.glNormalv(v);
+ }
public final void glNormal3f(float x, float y, float z) {
vboSet.glNormal3f(x,y,z);
}
+ public void glColorv(Buffer v) {
+ vboSet.glColorv(v);
+ }
public final void glColor3f(float x, float y, float z) {
vboSet.glColor3f(x,y,z);
}
+ public final void glColor4f(float x, float y, float z, float a) {
+ vboSet.glColor4f(x,y,z, a);
+ }
+
+ public void glTexCoordv(Buffer v) {
+ vboSet.glTexCoordv(v);
+ }
public final void glTexCoord2f(float x, float y) {
vboSet.glTexCoord2f(x,y);
}
@@ -127,29 +190,114 @@ public class ImmModeSink {
vboSet.glTexCoord3f(x,y,z);
}
+ public final void glVertex2s(short x, short y) {
+ vboSet.glVertex2s(x,y);
+ }
+
+ public final void glVertex3s(short x, short y, short z) {
+ vboSet.glVertex3s(x,y,z);
+ }
+
+ public final void glNormal3s(short x, short y, short z) {
+ vboSet.glNormal3s(x,y,z);
+ }
+
+ public final void glColor3s(short x, short y, short z) {
+ vboSet.glColor3s(x,y,z);
+ }
+
+ public final void glColor4s(short x, short y, short z, short a) {
+ vboSet.glColor4s(x,y,z,a);
+ }
+
+ public final void glTexCoord2s(short x, short y) {
+ vboSet.glTexCoord2s(x,y);
+ }
+
+ public final void glTexCoord3s(short x, short y, short z) {
+ vboSet.glTexCoord3s(x,y,z);
+ }
+
+ public final void glVertex2b(byte x, byte y) {
+ vboSet.glVertex2b(x,y);
+ }
+
+ public final void glVertex3b(byte x, byte y, byte z) {
+ vboSet.glVertex3b(x,y,z);
+ }
+
+ public final void glNormal3b(byte x, byte y, byte z) {
+ vboSet.glNormal3b(x,y,z);
+ }
+
+ public final void glColor3b(byte x, byte y, byte z) {
+ vboSet.glColor3b(x,y,z);
+ }
+
+ public final void glColor4b(byte x, byte y, byte z, byte a) {
+ vboSet.glColor4b(x,y,z,a);
+ }
+
+ public final void glTexCoord2b(byte x, byte y) {
+ vboSet.glTexCoord2b(x,y);
+ }
+
+ public final void glTexCoord3b(byte x, byte y, byte z) {
+ vboSet.glTexCoord3b(x,y,z);
+ }
+
+ protected ImmModeSink(int glBufferUsage, int initialSize,
+ int vComps, int vDataType,
+ int cComps, int cDataType,
+ int nComps, int nDataType,
+ int tComps, int tDataType, boolean useGLSL) {
+ if(useGLSL && !GLProfile.isGL2ES2()) {
+ throw new GLException("ImmModeSink GLSL usage not supported for profile: "+GLProfile.getProfile());
+ }
+ vboSet = new VBOSet(glBufferUsage, initialSize,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL);
+ this.vboSetList = new ArrayList();
+ }
+
+ private void destroyList(GL gl) {
+ for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) {
+ ((VBOSet)i.next()).destroy(gl);
+ }
+ vboSetList.clear();
+ }
+
private VBOSet vboSet;
private ArrayList vboSetList;
protected static class VBOSet {
- protected VBOSet(int glDataType, int glDrawUsage,
- int vComps, int nComps, int cComps, int tComps, int initialSize) {
- nComps = 0;
- tComps = 0;
- if(FLOAT2FIXED && glDataType==GL.GL_FLOAT) {
- glDataType=GL2ES1.GL_FIXED;
- }
- this.glDataType=glDataType;
- this.glDrawUsage=glDrawUsage;
+ protected VBOSet (int glBufferUsage, int initialSize,
+ int vComps, int vDataType,
+ int cComps, int cDataType,
+ int nComps, int nDataType,
+ int tComps, int tDataType, boolean useGLSL) {
+ this.glBufferUsage=glBufferUsage;
+ this.initialSize=initialSize;
+ this.vDataType=vDataType;
this.vComps=vComps;
- this.nComps=nComps;
+ this.cDataType=cDataType;
this.cComps=cComps;
+ this.nDataType=nDataType;
+ this.nComps=nComps;
+ this.tDataType=tDataType;
this.tComps=tComps;
- this.initialSize=initialSize;
-
- this.vertexVBO = VBOBufferDraw.create(GL2ES1.GL_VERTEX_ARRAY, glDataType, glDrawUsage, vComps, initialSize);
- this.normalVBO = VBOBufferDraw.create(GL2ES1.GL_NORMAL_ARRAY, glDataType, glDrawUsage, nComps, initialSize);
- this.colorVBO = VBOBufferDraw.create(GL2ES1.GL_COLOR_ARRAY, glDataType, glDrawUsage, cComps, initialSize);
- this.texcoordVBO = VBOBufferDraw.create(GL2ES1.GL_TEXTURE_COORD_ARRAY, glDataType, glDrawUsage, tComps, initialSize);
+ this.useGLSL=useGLSL;
+
+ if(!useGLSL) {
+ this.vertexVBO = GLArrayDataServer.createFixed(GL.GL_VERTEX_ARRAY, null, vComps, vDataType, false, initialSize, glBufferUsage);
+ this.colorVBO = GLArrayDataServer.createFixed(GL.GL_COLOR_ARRAY, null, cComps, cDataType, false, initialSize, glBufferUsage);
+ this.normalVBO = GLArrayDataServer.createFixed(GL.GL_NORMAL_ARRAY, null, nComps, nDataType, false, initialSize, glBufferUsage);
+ this.texcoordVBO = GLArrayDataServer.createFixed(GL.GL_TEXTURE_COORD_ARRAY, null, tComps, tDataType, false, initialSize, glBufferUsage);
+ } else {
+ this.vertexVBO = GLArrayDataServer.createGLSL(GLContext.mgl_Vertex, vComps, vDataType, false, initialSize, glBufferUsage);
+ this.colorVBO = GLArrayDataServer.createGLSL(GLContext.mgl_Color, cComps, cDataType, false, initialSize, glBufferUsage);
+ this.normalVBO = GLArrayDataServer.createGLSL(GLContext.mgl_Normal, nComps, nDataType, false, initialSize, glBufferUsage);
+ this.texcoordVBO = GLArrayDataServer.createGLSL(GLContext.mgl_MultiTexCoord, tComps, tDataType, false, initialSize, glBufferUsage);
+ }
this.sealed=false;
this.mode = -1;
@@ -157,7 +305,8 @@ public class ImmModeSink {
}
protected final VBOSet regenerate() {
- return new VBOSet(glDataType, glDrawUsage, vComps, nComps, cComps, tComps, initialSize);
+ return new VBOSet(glBufferUsage, initialSize,
+ vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL);
}
protected void destroy(GL gl) {
@@ -186,10 +335,10 @@ public class ImmModeSink {
return "VBOSet[mode "+mode+
", modeOrig "+modeOrig+
", sealed "+sealed+
- ",\n\t vertexVBO "+vertexVBO+
- ",\n\t normalVBO "+normalVBO+
- ",\n\t colorVBO "+colorVBO+
- ",\n\t texcoordVBO "+texcoordVBO+
+ ",\n\t"+vertexVBO+
+ ",\n\t"+normalVBO+
+ ",\n\t"+colorVBO+
+ ",\n\t"+texcoordVBO+
"]";
}
@@ -220,35 +369,60 @@ public class ImmModeSink {
checkSeal(false);
sealed = true;
- vertexVBO.seal(gl, disableBufferAfterSeal);
- normalVBO.seal(gl, disableBufferAfterSeal);
- colorVBO.seal(gl, disableBufferAfterSeal);
- texcoordVBO.seal(gl, disableBufferAfterSeal);
+ vertexVBO.seal(gl, true);
+ normalVBO.seal(gl, true);
+ colorVBO.seal(gl, true);
+ texcoordVBO.seal(gl, true);
+
+ if(disableBufferAfterSeal) {
+ vertexVBO.enableBuffer(gl, false);
+ normalVBO.enableBuffer(gl, false);
+ colorVBO.enableBuffer(gl, false);
+ texcoordVBO.enableBuffer(gl, false);
+ }
}
- protected void draw(GL gl, boolean disableBufferAfterDraw, int i)
+ protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i)
{
if(DEBUG_DRAW) {
Exception e = new Exception("ImmModeSink.draw["+i+"](disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this);
e.printStackTrace();
}
- vertexVBO.enableBuffer(gl);
- normalVBO.enableBuffer(gl);
- colorVBO.enableBuffer(gl);
- texcoordVBO.enableBuffer(gl);
+ vertexVBO.enableBuffer(gl, true);
+ normalVBO.enableBuffer(gl, true);
+ colorVBO.enableBuffer(gl, true);
+ texcoordVBO.enableBuffer(gl, true);
if (vertexVBO.getBuffer()!=null) {
- gl.glDrawArrays(mode, 0, vertexVBO.getVerticeNumber());
+ if(null==indices) {
+ gl.glDrawArrays(mode, 0, vertexVBO.getVerticeNumber());
+ } else {
+ Class clazz = indices.getClass();
+ int type=-1;
+ if(GLReflection.instanceOf(clazz, ByteBuffer.class.getName())) {
+ type = GL.GL_UNSIGNED_BYTE;
+ } else if(GLReflection.instanceOf(clazz, ShortBuffer.class.getName())) {
+ type = GL.GL_UNSIGNED_SHORT;
+ }
+ if(0>type) {
+ throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this);
+ }
+ gl.glDrawElements(mode, indices.remaining(), type, indices);
+ }
}
if(disableBufferAfterDraw) {
- vertexVBO.disableBuffer(gl);
- normalVBO.disableBuffer(gl);
- colorVBO.disableBuffer(gl);
- texcoordVBO.disableBuffer(gl);
+ vertexVBO.enableBuffer(gl, false);
+ normalVBO.enableBuffer(gl, false);
+ colorVBO.enableBuffer(gl, false);
+ texcoordVBO.enableBuffer(gl, false);
}
}
+ protected void glVertexv(Buffer v) {
+ checkSeal(false);
+ vertexVBO.put(v);
+ }
protected void glVertex2f(float x, float y) {
checkSeal(false);
vertexVBO.putf(x);
@@ -256,7 +430,6 @@ public class ImmModeSink {
vertexVBO.putf(y);
vertexVBO.padding(2);
}
-
protected void glVertex3f(float x, float y, float z) {
checkSeal(false);
vertexVBO.putf(x);
@@ -267,6 +440,10 @@ public class ImmModeSink {
vertexVBO.padding(3);
}
+ protected void glNormalv(Buffer v) {
+ checkSeal(false);
+ normalVBO.put(v);
+ }
protected void glNormal3f(float x, float y, float z) {
checkSeal(false);
normalVBO.putf(x);
@@ -277,6 +454,10 @@ public class ImmModeSink {
normalVBO.padding(3);
}
+ protected void glColorv(Buffer v) {
+ checkSeal(false);
+ colorVBO.put(v);
+ }
protected void glColor3f(float x, float y, float z) {
checkSeal(false);
colorVBO.putf(x);
@@ -286,7 +467,22 @@ public class ImmModeSink {
colorVBO.putf(z);
colorVBO.padding(3);
}
+ protected void glColor4f(float x, float y, float z, float a) {
+ checkSeal(false);
+ colorVBO.putf(x);
+ if(colorVBO.getComponents()>1)
+ colorVBO.putf(y);
+ if(colorVBO.getComponents()>2)
+ colorVBO.putf(z);
+ if(colorVBO.getComponents()>3)
+ colorVBO.putf(a);
+ colorVBO.padding(4);
+ }
+ protected void glTexCoordv(Buffer v) {
+ checkSeal(false);
+ texcoordVBO.put(v);
+ }
protected void glTexCoord2f(float x, float y) {
checkSeal(false);
texcoordVBO.putf(x);
@@ -294,7 +490,6 @@ public class ImmModeSink {
texcoordVBO.putf(y);
texcoordVBO.padding(2);
}
-
protected void glTexCoord3f(float x, float y, float z) {
checkSeal(false);
texcoordVBO.putf(x);
@@ -305,13 +500,145 @@ public class ImmModeSink {
texcoordVBO.padding(3);
}
- VBOBufferDraw vertexVBO;
- VBOBufferDraw normalVBO;
- VBOBufferDraw colorVBO;
- VBOBufferDraw texcoordVBO;
+ protected void glVertex2s(short x, short y) {
+ checkSeal(false);
+ vertexVBO.puts(x);
+ if(vertexVBO.getComponents()>1)
+ vertexVBO.puts(y);
+ vertexVBO.padding(2);
+ }
+ protected void glVertex3s(short x, short y, short z) {
+ checkSeal(false);
+ vertexVBO.puts(x);
+ if(vertexVBO.getComponents()>1)
+ vertexVBO.puts(y);
+ if(vertexVBO.getComponents()>2)
+ vertexVBO.puts(z);
+ vertexVBO.padding(3);
+ }
+
+ protected void glNormal3s(short x, short y, short z) {
+ checkSeal(false);
+ normalVBO.puts(x);
+ if(normalVBO.getComponents()>1)
+ normalVBO.puts(y);
+ if(normalVBO.getComponents()>2)
+ normalVBO.puts(z);
+ normalVBO.padding(3);
+ }
+
+ protected void glColor3s(short x, short y, short z) {
+ checkSeal(false);
+ colorVBO.puts(x);
+ if(colorVBO.getComponents()>1)
+ colorVBO.puts(y);
+ if(colorVBO.getComponents()>2)
+ colorVBO.puts(z);
+ colorVBO.padding(3);
+ }
+ protected void glColor4s(short x, short y, short z, short a) {
+ checkSeal(false);
+ colorVBO.puts(x);
+ if(colorVBO.getComponents()>1)
+ colorVBO.puts(y);
+ if(colorVBO.getComponents()>2)
+ colorVBO.puts(z);
+ if(colorVBO.getComponents()>3)
+ colorVBO.puts(a);
+ colorVBO.padding(4);
+ }
+
+ protected void glTexCoord2s(short x, short y) {
+ checkSeal(false);
+ texcoordVBO.puts(x);
+ if(texcoordVBO.getComponents()>1)
+ texcoordVBO.puts(y);
+ texcoordVBO.padding(2);
+ }
+ protected void glTexCoord3s(short x, short y, short z) {
+ checkSeal(false);
+ texcoordVBO.puts(x);
+ if(texcoordVBO.getComponents()>1)
+ texcoordVBO.puts(y);
+ if(texcoordVBO.getComponents()>2)
+ texcoordVBO.puts(z);
+ texcoordVBO.padding(3);
+ }
+
+ protected void glVertex2b(byte x, byte y) {
+ checkSeal(false);
+ vertexVBO.putb(x);
+ if(vertexVBO.getComponents()>1)
+ vertexVBO.putb(y);
+ vertexVBO.padding(2);
+ }
+ protected void glVertex3b(byte x, byte y, byte z) {
+ checkSeal(false);
+ vertexVBO.putb(x);
+ if(vertexVBO.getComponents()>1)
+ vertexVBO.putb(y);
+ if(vertexVBO.getComponents()>2)
+ vertexVBO.putb(z);
+ vertexVBO.padding(3);
+ }
+
+ protected void glNormal3b(byte x, byte y, byte z) {
+ checkSeal(false);
+ normalVBO.putb(x);
+ if(normalVBO.getComponents()>1)
+ normalVBO.putb(y);
+ if(normalVBO.getComponents()>2)
+ normalVBO.putb(z);
+ normalVBO.padding(3);
+ }
+
+ protected void glColor3b(byte x, byte y, byte z) {
+ checkSeal(false);
+ colorVBO.putb(x);
+ if(colorVBO.getComponents()>1)
+ colorVBO.putb(y);
+ if(colorVBO.getComponents()>2)
+ colorVBO.putb(z);
+ colorVBO.padding(3);
+ }
+ protected void glColor4b(byte x, byte y, byte z, byte a) {
+ checkSeal(false);
+ colorVBO.putb(x);
+ if(colorVBO.getComponents()>1)
+ colorVBO.putb(y);
+ if(colorVBO.getComponents()>2)
+ colorVBO.putb(z);
+ if(colorVBO.getComponents()>3)
+ colorVBO.putb(a);
+ colorVBO.padding(4);
+ }
+ protected void glTexCoord2b(byte x, byte y) {
+ checkSeal(false);
+ texcoordVBO.putb(x);
+ if(texcoordVBO.getComponents()>1)
+ texcoordVBO.putb(y);
+ texcoordVBO.padding(2);
+ }
+
+ protected void glTexCoord3b(byte x, byte y, byte z) {
+ checkSeal(false);
+ texcoordVBO.putb(x);
+ if(texcoordVBO.getComponents()>1)
+ texcoordVBO.putb(y);
+ if(texcoordVBO.getComponents()>2)
+ texcoordVBO.putb(z);
+ texcoordVBO.padding(3);
+ }
+
+ GLArrayDataServer vertexVBO;
+ GLArrayDataServer normalVBO;
+ GLArrayDataServer colorVBO;
+ GLArrayDataServer texcoordVBO;
int mode, modeOrig;
- int glDataType, glDrawUsage, vComps, nComps, cComps, tComps, initialSize;
- boolean sealed;
+ int glBufferUsage, initialSize;
+ int vComps, cComps, nComps, tComps;
+ int vDataType, cDataType, nDataType, tDataType;
+ boolean sealed, useGLSL;
}
}
diff --git a/src/classes/javax/media/opengl/util/PMVMatrix.java b/src/classes/javax/media/opengl/util/PMVMatrix.java
index 4e8693be0..37472dfe6 100755
--- a/src/classes/javax/media/opengl/util/PMVMatrix.java
+++ b/src/classes/javax/media/opengl/util/PMVMatrix.java
@@ -9,55 +9,54 @@ import java.util.List;
public class PMVMatrix {
- protected ProjectFloat pvmProjectf = null;
- protected FloatBuffer matrixPMV, matrixP, matrixMV;
- protected FloatBuffer matrixTemp, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixPersp, matrixFrustum;
- protected float[] vec3f;
- protected List/*FloatBuffer*/ matrixPStack, matrixMVStack;
- protected int matrixMode = GL.GL_MODELVIEW;
- protected boolean modifiedPMV = false;
-
public PMVMatrix() {
- pvmProjectf = new ProjectFloat();
+ projectFloat = new ProjectFloat();
+
+ matrixIdent = BufferUtil.newFloatBuffer(1*16);
+ projectFloat.gluMakeIdentityf(matrixIdent);
+ matrixIdent.rewind();
+
+ matrixPMvMviT = BufferUtil.newFloatBuffer(4*16); // grouping P + Mv + Mvi + MviT
+ matrixPMvMvi = slice(matrixPMvMviT, 0*16, 3*16); // grouping P + Mv + Mvi
+ matrixPMv = slice(matrixPMvMviT, 0*16, 2*16); // grouping P + Mv
+ matrixP = slice(matrixPMvMviT, 0*16, 1*16);
+ matrixMv = slice(matrixPMvMviT, 1*16, 1*16);
+ matrixMvi = slice(matrixPMvMviT, 2*16, 1*16);
+ matrixMvit = slice(matrixPMvMviT, 3*16, 1*16);
+ matrixPMvMviT.rewind();
- matrixPMV = BufferUtil.newFloatBuffer(2*16);
- matrixP = slice(matrixPMV, 0*16, 16);
- matrixMV = slice(matrixPMV, 1*16, 16);
- matrixPMV.rewind();
+ matrixMvit3 = BufferUtil.newFloatBuffer(3*3);
- FloatBuffer buf = BufferUtil.newFloatBuffer(7*16);
+ FloatBuffer buf = BufferUtil.newFloatBuffer(6*16);
- matrixTemp=slice(buf, 0*16, 16);
+ matrixMult=slice(buf, 0*16, 16);
matrixTrans=slice(buf, 1*16, 16);
- pvmProjectf.gluMakeIdentityf(matrixTrans);
+ projectFloat.gluMakeIdentityf(matrixTrans);
matrixRot=slice(buf, 2*16, 16);
- pvmProjectf.gluMakeIdentityf(matrixRot);
+ projectFloat.gluMakeIdentityf(matrixRot);
matrixScale=slice(buf, 3*16, 16);
- pvmProjectf.gluMakeIdentityf(matrixScale);
+ projectFloat.gluMakeIdentityf(matrixScale);
matrixOrtho=slice(buf, 4*16, 16);
- pvmProjectf.gluMakeIdentityf(matrixOrtho);
+ projectFloat.gluMakeIdentityf(matrixOrtho);
matrixFrustum=slice(buf, 5*16, 16);
- pvmProjectf.gluMakeZero(matrixFrustum);
-
- matrixPersp=slice(buf, 6*16, 16);
- pvmProjectf.gluMakeIdentityf(matrixPersp);
+ projectFloat.gluMakeZero(matrixFrustum);
vec3f=new float[3];
matrixPStack = new ArrayList();
- matrixMVStack= new ArrayList();
+ matrixMvStack= new ArrayList();
// default values and mode
glMatrixMode(GL.GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL.GL_MODELVIEW);
glLoadIdentity();
- modifiedPMV = true;
+ modified = true;
}
private static FloatBuffer slice(FloatBuffer buf, int pos, int len) {
@@ -67,11 +66,16 @@ public class PMVMatrix {
}
public boolean isDirty() {
- return modifiedPMV;
+ return modified;
}
- public void clear() {
- modifiedPMV=false;
+ public boolean update() {
+ boolean res = modified;
+ if(res) {
+ setMviMvit();
+ modified=false;
+ }
+ return res;
}
public final int glGetMatrixMode() {
@@ -89,8 +93,24 @@ public class PMVMatrix {
matrixMode = matrixName;
}
- public final FloatBuffer glGetPMVMatrixf() {
- return matrixPMV;
+ public final FloatBuffer glGetPMvMviTMatrixf() {
+ return matrixPMvMviT;
+ }
+
+ public final FloatBuffer glGetPMvMviMatrixf() {
+ return matrixPMvMvi;
+ }
+
+ public final FloatBuffer glGetPMvMatrixf() {
+ return matrixPMv;
+ }
+
+ public final FloatBuffer glGetMviMatrixf() {
+ return matrixMvi;
+ }
+
+ public final FloatBuffer glGetNormalMatrixf() {
+ return matrixMvit3;
}
public final FloatBuffer glGetMatrixf() {
@@ -99,82 +119,116 @@ public class PMVMatrix {
public final FloatBuffer glGetMatrixf(int matrixName) {
if(matrixName==GL.GL_MODELVIEW) {
- return matrixMV;
+ return matrixMv;
} else if(matrixName==GL.GL_PROJECTION) {
return matrixP;
}
return null;
}
+ public void glLoadMatrixf(float[] values, int offset) {
+ int len = values.length-offset;
+ if(matrixMode==GL.GL_MODELVIEW) {
+ matrixMv.clear();
+ matrixMv.put(values, offset, len);
+ matrixMv.rewind();
+ } else if(matrixMode==GL.GL_PROJECTION) {
+ matrixP.clear();
+ matrixP.put(values, offset, len);
+ matrixP.rewind();
+ }
+ modified = true;
+ }
+
public void glLoadMatrixf(java.nio.FloatBuffer m) {
+ int spos = m.position();
if(matrixMode==GL.GL_MODELVIEW) {
- matrixMV.clear();
- matrixMV.put(m);
- matrixMV.rewind();
+ matrixMv.clear();
+ matrixMv.put(m);
+ matrixMv.rewind();
} else if(matrixMode==GL.GL_PROJECTION) {
matrixP.clear();
matrixP.put(m);
matrixP.rewind();
}
- modifiedPMV = true;
+ m.position(spos);
+ modified = true;
}
public void glPopMatrix() {
+ float[] stackEntry=null;
if(matrixMode==GL.GL_MODELVIEW) {
- matrixMV=(FloatBuffer)matrixMVStack.remove(0);
+ stackEntry = (float[])matrixMvStack.remove(0);
} else if(matrixMode==GL.GL_PROJECTION) {
- matrixP=(FloatBuffer)matrixPStack.remove(0);
+ stackEntry = (float[])matrixPStack.remove(0);
}
- modifiedPMV = true;
+ glLoadMatrixf(stackEntry, 0);
}
public void glPushMatrix() {
+ float[] stackEntry = new float[1*16];
if(matrixMode==GL.GL_MODELVIEW) {
- matrixMVStack.add(0, matrixMV);
+ matrixMv.get(stackEntry);
+ matrixMv.rewind();
+ matrixMvStack.add(0, stackEntry);
} else if(matrixMode==GL.GL_PROJECTION) {
- matrixPStack.add(0, matrixP);
- }
+ matrixP.get(stackEntry);
+ matrixP.rewind();
+ matrixPStack.add(0, stackEntry);
+ }
}
public void glLoadIdentity() {
if(matrixMode==GL.GL_MODELVIEW) {
- matrixMV.clear();
- pvmProjectf.gluMakeIdentityf(matrixMV);
- matrixMV.rewind();
+ matrixMv.clear();
+ matrixMv.put(matrixIdent);
+ matrixMv.rewind();
+ matrixIdent.rewind();
} else if(matrixMode==GL.GL_PROJECTION) {
matrixP.clear();
- pvmProjectf.gluMakeIdentityf(matrixP);
+ matrixP.put(matrixIdent);
matrixP.rewind();
+ matrixIdent.rewind();
}
- modifiedPMV = true;
+ modified = true;
+ }
+
+ public void glMultMatrixf(FloatBuffer a, FloatBuffer b, FloatBuffer p) {
+ for (int i = 0; i < 4; i++) {
+ final float ai0=a.get(i+0*4), ai1=a.get(i+1*4), ai2=a.get(i+2*4), ai3=a.get(i+3*4);
+ p.put(i+0*4 , ai0 * b.get(0+0*4) + ai1 * b.get(1+0*4) + ai2 * b.get(2+0*4) + ai3 * b.get(3+0*4) );
+ p.put(i+1*4 , ai0 * b.get(0+1*4) + ai1 * b.get(1+1*4) + ai2 * b.get(2+1*4) + ai3 * b.get(3+1*4) );
+ p.put(i+2*4 , ai0 * b.get(0+2*4) + ai1 * b.get(1+2*4) + ai2 * b.get(2+2*4) + ai3 * b.get(3+2*4) );
+ p.put(i+3*4 , ai0 * b.get(0+3*4) + ai1 * b.get(1+3*4) + ai2 * b.get(2+3*4) + ai3 * b.get(3+3*4) );
+ }
+ // or .. projectFloat.gluMultMatricesf(b, a, p);
}
public void glMultMatrixf(FloatBuffer m) {
if(matrixMode==GL.GL_MODELVIEW) {
- pvmProjectf.gluMultMatricesf(m, matrixMV, matrixTemp);
- matrixMV.clear();
- matrixMV.put(matrixTemp);
- matrixMV.rewind();
+ glMultMatrixf(matrixMv, m, matrixMult);
+ matrixMv.clear();
+ matrixMv.put(matrixMult);
+ matrixMv.rewind();
} else if(matrixMode==GL.GL_PROJECTION) {
- pvmProjectf.gluMultMatricesf(m, matrixP, matrixTemp);
+ glMultMatrixf(matrixP, m, matrixMult);
matrixP.clear();
- matrixP.put(matrixTemp);
+ matrixP.put(matrixMult);
matrixP.rewind();
}
- matrixTemp.rewind();
- modifiedPMV = true;
+ matrixMult.rewind();
+ modified = true;
}
public void glTranslatef(float x, float y, float z) {
// Translation matrix:
- // 1 0 0 0
- // 0 1 0 0
- // 0 0 1 0
- // x y z 1
- matrixTrans.put(3*4+0, x);
- matrixTrans.put(3*4+1, y);
- matrixTrans.put(3*4+2, z);
-
+ // 1 0 0 x
+ // 0 1 0 y
+ // 0 0 1 z
+ // 0 0 0 1
+ matrixTrans.put(0+4*3, x);
+ matrixTrans.put(1+4*3, y);
+ matrixTrans.put(2+4*3, z);
glMultMatrixf(matrixTrans);
}
@@ -185,7 +239,7 @@ public class PMVMatrix {
float s = (float)Math.sin(angrad);
vec3f[0]=x; vec3f[1]=y; vec3f[2]=z;
- pvmProjectf.normalize(vec3f);
+ projectFloat.normalize(vec3f);
x = vec3f[0]; y = vec3f[1]; z = vec3f[2];
// Rotation matrix:
@@ -199,6 +253,19 @@ public class PMVMatrix {
float ys = y*s;
float yz = y*z;
float zs = z*s;
+ if(false) {
+ matrixRot.put(0+4*0, x*x*ic+c);
+ matrixRot.put(0+4*1, xy*ic+zs);
+ matrixRot.put(0+4*2, xz*ic-ys);
+
+ matrixRot.put(1+4*0, xy*ic+zs);
+ matrixRot.put(1+4*1, y*y*ic+c);
+ matrixRot.put(1+4*2, yz*ic-xs);
+
+ matrixRot.put(2+4*0, xz*ic-ys);
+ matrixRot.put(2+4*1, yz*ic+xs);
+ matrixRot.put(2+4*2, z*z*ic+c);
+ } else {
matrixRot.put(0*4+0, x*x*ic+c);
matrixRot.put(0*4+1, xy*ic+zs);
matrixRot.put(0*4+2, xz*ic-ys);
@@ -210,6 +277,7 @@ public class PMVMatrix {
matrixRot.put(2*4+0, xz*ic+ys);
matrixRot.put(2*4+1, yz*ic-xs);
matrixRot.put(2*4+2, z*z*ic+c);
+ }
glMultMatrixf(matrixRot);
}
@@ -220,19 +288,19 @@ public class PMVMatrix {
// 0 y 0 0
// 0 0 z 0
// 0 0 0 1
- matrixScale.put(0*4+0, x);
- matrixScale.put(1*4+1, y);
- matrixScale.put(2*4+2, z);
+ matrixScale.put(0+4*0, x);
+ matrixScale.put(1+4*1, y);
+ matrixScale.put(2+4*2, z);
glMultMatrixf(matrixScale);
}
public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) {
// Ortho matrix:
- // 2/dx 0 0 0
- // 0 2/dy 0 0
- // 0 0 2/dz 0
- // tx tx tx 1
+ // 2/dx 0 0 tx
+ // 0 2/dy 0 ty
+ // 0 0 2/dz tz
+ // 0 0 0 1
float dx=right-left;
float dy=top-bottom;
float dz=zFar-zNear;
@@ -240,12 +308,12 @@ public class PMVMatrix {
float ty=-1.0f*(top+bottom)/dy;
float tz=-1.0f*(zFar+zNear)/dz;
- matrixOrtho.put(0*4+0, 2.0f/dx);
- matrixOrtho.put(1*4+1, 2.0f/dy);
- matrixOrtho.put(2*4+2, -2.0f/dz);
- matrixOrtho.put(3*4+0, tx);
- matrixOrtho.put(3*4+1, ty);
- matrixOrtho.put(3*4+2, tz);
+ matrixOrtho.put(0+4*0, 2.0f/dx);
+ matrixOrtho.put(1+4*1, 2.0f/dy);
+ matrixOrtho.put(2+4*2, -2.0f/dz);
+ matrixOrtho.put(0+4*3, tx);
+ matrixOrtho.put(1+4*3, ty);
+ matrixOrtho.put(2+4*3, tz);
glMultMatrixf(matrixOrtho);
}
@@ -271,40 +339,57 @@ public class PMVMatrix {
float C=-1.0f*(zFar+zNear)/dz;
float D=-2.0f*(zFar*zNear)/dz;
- matrixFrustum.put(0*4+0, zNear2/dx);
- matrixFrustum.put(1*4+1, zNear2/dy);
- matrixFrustum.put(2*4+2, C);
- matrixFrustum.put(0*4+2, A);
- matrixFrustum.put(1*4+2, B);
- matrixFrustum.put(2*4+3, D);
- matrixFrustum.put(3*4+2, -1.0f);
+ matrixFrustum.put(0+4*0, zNear2/dx);
+ matrixFrustum.put(1+4*1, zNear2/dy);
+ matrixFrustum.put(2+4*2, C);
+
+ matrixFrustum.put(0+4*2, A);
+ matrixFrustum.put(1+4*2, B);
+
+ matrixFrustum.put(2+4*3, D);
+ matrixFrustum.put(3+4*2, -1.0f);
glMultMatrixf(matrixFrustum);
}
public void gluPerspective(float fovy, float aspect, float zNear, float zFar) {
- float radians = fovy/2 * (float) Math.PI / 180;
-
- float sine, cotangent, deltaZ;
+ float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
+ float bottom=-1.0f*top;
+ float left=aspect*bottom;
+ float right=aspect*top;
+ glFrustumf(left, right, bottom, top, zNear, zFar);
+ }
- deltaZ = zFar - zNear;
- sine = (float) Math.sin(radians);
+ private void setMviMvit() {
+ if(!projectFloat.gluInvertMatrixf(matrixMv, matrixMvi)) {
+ throw new GLException("Invalid source Mv matrix, can't compute inverse");
+ }
- if ((deltaZ == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) {
- return;
+ // transpose matrix
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ matrixMvit.put(j+i*4, matrixMvi.get(i+j*4));
+ }
}
- cotangent = (float) Math.cos(radians) / sine;
+ // fetch 3x3
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ matrixMvit3.put(i+j*3, matrixMvit.get(i+j*4));
+ }
+ }
+ }
- matrixPersp.put(0 * 4 + 0, cotangent / aspect);
- matrixPersp.put(1 * 4 + 1, cotangent);
- matrixPersp.put(2 * 4 + 2, - (zFar + zNear) / deltaZ);
- matrixPersp.put(2 * 4 + 3, -1);
- matrixPersp.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ);
- matrixPersp.put(3 * 4 + 3, 0);
+ protected FloatBuffer matrixIdent;
+ protected FloatBuffer matrixPMvMviT, matrixPMvMvi, matrixPMv, matrixP, matrixMv, matrixMvi, matrixMvit;
+ protected FloatBuffer matrixMvit3;
+ protected FloatBuffer matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum;
+ protected float[] vec3f;
+ protected List/*FloatBuffer*/ matrixPStack, matrixMvStack;
+ protected int matrixMode = GL.GL_MODELVIEW;
+ protected boolean modified = false;
+ protected ProjectFloat projectFloat;
- glMultMatrixf(matrixPersp);
- }
}
diff --git a/src/classes/javax/media/opengl/util/VBOBufferDraw.java b/src/classes/javax/media/opengl/util/VBOBufferDraw.java
deleted file mode 100644
index 8ce1b3232..000000000
--- a/src/classes/javax/media/opengl/util/VBOBufferDraw.java
+++ /dev/null
@@ -1,392 +0,0 @@
-
-package javax.media.opengl.util;
-
-import javax.media.opengl.*;
-import java.nio.*;
-import com.sun.opengl.impl.*;
-
-public abstract class VBOBufferDraw {
-
- public static VBOBufferDraw create(int glArrayType, int glDataType, int glBufferUsage, int comps, int initialSize)
- throws GLException
- {
- Class[] types = new Class[]{ int.class, int.class, int.class, int.class, int.class };
- Object[] args = new Integer[]{ new Integer(glArrayType), new Integer(glDataType), new Integer(glBufferUsage),
- new Integer(comps), new Integer(initialSize) } ;
-
- if(GLProfile.isGL2ES1()) {
- return (VBOBufferDraw) GLReflection.createInstance("com.sun.opengl.impl.gl2es1.VBOBufferDrawGL2ES1", types, args);
- } else if(GLProfile.isGLES2()) {
- return (VBOBufferDraw) GLReflection.createInstance("com.sun.opengl.impl.es2.VBOBufferDrawGLES2", types, args);
- }
- throw new GLException("VBOBufferDraw not supported for profile: "+GLProfile.getProfile());
- }
-
- protected void init(int glArrayType, int glDataType, int glBufferUsage, int comps, int initialSize)
- throws GLException
- {
- vboUsage=true;
-
- switch(glArrayType) {
- case GL2ES1.GL_VERTEX_ARRAY:
- case GL2ES1.GL_NORMAL_ARRAY:
- if(3!=comps && 0!=comps) {
- throw new GLException("component size for NORMAL_ARRAY must be 3 or 0: "+comps+" \n\t"+this);
- }
- case GL2ES1.GL_COLOR_ARRAY:
- case GL2ES1.GL_TEXTURE_COORD_ARRAY:
- break;
- default:
- throw new GLException("invalid glArrayType: "+glArrayType+":\n\t"+this);
- }
- this.glArrayType = glArrayType;
- this.glDataType = glDataType;
- this.clazz = getBufferClass(glDataType);
- this.buffer = null;
- this.components = comps;
- this.initialSize = initialSize;
- if( ! (GLProfile.isGL2ES2() && glBufferUsage==GL2ES2.GL_STREAM_DRAW) ) {
- switch(glBufferUsage) {
- case GL2ES1.GL_STATIC_DRAW:
- case GL2ES1.GL_DYNAMIC_DRAW:
- break;
- default:
- throw new GLException("invalid glBufferUsage: "+glBufferUsage+":\n\t"+this);
- }
- }
- this.glBufferUsage = glBufferUsage;
- this.vboName = 0;
- this.sealed=false;
- this.bufferEnabled=false;
- growVBO(initialSize);
- }
-
- public boolean usesVBO() { return vboUsage; }
-
- public void setVBOUsage(boolean vboUsage) {
- checkSeal(false);
- this.vboUsage=vboUsage;
- }
-
- public int getGLArrayType() {
- return glArrayType;
- }
-
- public int getGlDataType() {
- return glDataType;
- }
-
- public int getComponents() {
- return components;
- }
-
- public Class getBufferClass() {
- return clazz;
- }
-
- public Buffer getBuffer() {
- return buffer;
- }
-
- public int getBufferUsage() {
- return glBufferUsage;
- }
-
- public void destroy(GL gl) {
- reset(gl);
- if(vboName!=0) {
- int[] tmp = new int[1];
- tmp[0] = vboName;
- gl.glDeleteBuffers(1, tmp, 0);
- vboName = 0;
- }
- }
-
- public void reset() {
- reset(null);
- }
-
- public void reset(GL gl) {
- if(gl!=null) {
- disableBuffer(gl);
- }
- this.sealed=false;
- if(buffer!=null) {
- buffer.clear();
- }
- }
-
- private final void init_vbo(GL gl) {
- if(vboUsage && vboName==0) {
- int[] tmp = new int[1];
- gl.glGenBuffers(1, tmp, 0);
- vboName = tmp[0];
- }
- }
-
- private final void checkSeal(boolean test) throws GLException {
- if(sealed!=test) {
- if(test) {
- throw new GLException("Not Sealed yet, seal first:\n\t"+this);
- } else {
- throw new GLException("Already Sealed, can't modify VBO:\n\t"+this);
- }
- }
- }
-
- public final boolean growVBOIfNecessary(int spare) {
- if(buffer==null) {
- throw new GLException("buffer no configured:\n\t"+this);
- }
- if(buffer!=null && buffer.remaining()<spare) {
- growVBO();
- return true;
- }
- return false;
- }
-
- public final void growVBO() {
- growVBO(initialSize);
- }
-
- public static final Class getBufferClass(int glDataType) {
- switch(glDataType) {
- case GL2ES1.GL_BYTE:
- case GL2ES1.GL_UNSIGNED_BYTE:
- return ByteBuffer.class;
- case GL2ES1.GL_SHORT:
- case GL2ES1.GL_UNSIGNED_SHORT:
- return ShortBuffer.class;
- case GL2ES1.GL_FIXED:
- return IntBuffer.class;
- case GL2ES1.GL_FLOAT:
- return FloatBuffer.class;
- default:
- throw new GLException("Given OpenGL data type not supported: "+glDataType);
- }
- }
-
- public final int getBufferCompSize() {
- if(clazz==ByteBuffer.class) {
- return BufferUtil.SIZEOF_BYTE;
- }
- if(clazz==ShortBuffer.class) {
- return BufferUtil.SIZEOF_SHORT;
- }
- if(clazz==IntBuffer.class) {
- return BufferUtil.SIZEOF_INT;
- }
- if(clazz==FloatBuffer.class) {
- return BufferUtil.SIZEOF_FLOAT;
- }
- throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this);
- }
-
- public final void growVBO(int additional) {
- int osize;
-
- checkSeal(false);
-
- if(components>0) {
- osize = (buffer!=null)?buffer.capacity():0;
- if(clazz==ByteBuffer.class) {
- ByteBuffer newBBuffer = BufferUtil.newByteBuffer( (osize+additional) * components );
- if(buffer!=null) {
- buffer.flip();
- newBBuffer.put((ByteBuffer)buffer);
- }
- buffer = newBBuffer;
- } else if(clazz==ShortBuffer.class) {
- ShortBuffer newSBuffer = BufferUtil.newShortBuffer( (osize+additional) * components );
- if(buffer!=null) {
- buffer.flip();
- newSBuffer.put((ShortBuffer)buffer);
- }
- buffer = newSBuffer;
- } else if(clazz==IntBuffer.class) {
- IntBuffer newIBuffer = BufferUtil.newIntBuffer( (osize+additional) * components );
- if(buffer!=null) {
- buffer.flip();
- newIBuffer.put((IntBuffer)buffer);
- }
- buffer = newIBuffer;
- } else if(clazz==FloatBuffer.class) {
- FloatBuffer newFBuffer = BufferUtil.newFloatBuffer( (osize+additional) * components );
- if(buffer!=null) {
- buffer.flip();
- newFBuffer.put((FloatBuffer)buffer);
- }
- buffer = newFBuffer;
- } else {
- throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this);
- }
- }
- }
-
- public void rewind() {
- checkSeal(true);
-
- if(buffer!=null) {
- buffer.rewind();
- }
- }
-
- public int getVerticeNumber() {
- return ( buffer!=null ) ? ( buffer.limit() / components ) : 0 ;
- }
-
- public void seal(GL gl, boolean disableAfterSeal)
- {
- checkSeal(false);
- sealed = true;
- init_vbo(gl);
-
- if (null!=buffer) {
- buffer.flip();
- enableBuffer(gl, true);
- }
- if(null==buffer || disableAfterSeal) {
- disableBuffer(gl);
- }
-
- }
-
- public void enableBuffer(GL gl)
- {
- enableBuffer(gl, false);
- }
-
- private void enableBuffer(GL gl, boolean newData)
- {
- checkSeal(true);
- enableBufferGLImpl(gl, newData);
- }
-
- protected abstract void enableBufferGLImpl(GL gl, boolean newData);
-
- public void disableBuffer(GL gl) {
- disableBufferGLImpl(gl);
- }
-
- protected abstract void disableBufferGLImpl(GL gl) ;
-
- public void padding(int done) {
- if(buffer==null) return; // JAU
- if(buffer==null) {
- throw new GLException("buffer no configured:\n\t"+this);
- }
- while(done<components) {
- if(clazz==ByteBuffer.class) {
- ((ByteBuffer)buffer).put((byte)0);
- } else if(clazz==ShortBuffer.class) {
- ((ShortBuffer)buffer).put((short)0);
- } else if(clazz==IntBuffer.class) {
- ((IntBuffer)buffer).put(0);
- } else if(clazz==FloatBuffer.class) {
- ((FloatBuffer)buffer).put(0f);
- } else {
- throw new GLException("Given Buffer Class not supported: "+clazz+" :\n\t"+this);
- }
- done++;
- }
- }
-
- public void putb(byte v) {
- if(buffer==null) return; // JAU
- growVBOIfNecessary(1);
- if(clazz==ByteBuffer.class) {
- ((ByteBuffer)buffer).put(v);
- } else if(clazz==ShortBuffer.class) {
- ((ShortBuffer)buffer).put((short)v);
- } else if(clazz==IntBuffer.class) {
- ((IntBuffer)buffer).put((int)v);
- } else {
- throw new GLException("Byte doesn't match Buffer Class: "+clazz+" :\n\t"+this);
- }
- }
-
- public void puts(short v) {
- if(buffer==null) return; // JAU
- growVBOIfNecessary(1);
- if(clazz==ShortBuffer.class) {
- ((ShortBuffer)buffer).put(v);
- } else if(clazz==IntBuffer.class) {
- ((IntBuffer)buffer).put((int)v);
- } else {
- throw new GLException("Short doesn't match Buffer Class: "+clazz+" :\n\t"+this);
- }
- }
-
- public void puti(int v) {
- if(buffer==null) return; // JAU
- growVBOIfNecessary(1);
- if(clazz==IntBuffer.class) {
- ((IntBuffer)buffer).put(v);
- } else {
- throw new GLException("Integer doesn't match Buffer Class: "+clazz+" :\n\t"+this);
- }
- }
-
- public void putx(int v) {
- if(buffer==null) return; // JAU
- growVBOIfNecessary(1);
- if(clazz==IntBuffer.class) {
- ((IntBuffer)buffer).put(v);
- } else {
- throw new GLException("Fixed doesn't match Buffer Class: "+clazz+" :\n\t"+this);
- }
- }
-
- public void putf(float v) {
- if(buffer==null) return; // JAU
- growVBOIfNecessary(1);
- if(clazz==FloatBuffer.class) {
- ((FloatBuffer)buffer).put(v);
- } else if(clazz==IntBuffer.class) {
- ((IntBuffer)buffer).put(FixedPoint.toFixed(v));
- } else {
- throw new GLException("Float doesn't match Buffer Class: "+clazz+" :\n\t"+this);
- }
- }
-
- public void putd(double v) {
- if(buffer==null) return; // JAU
- growVBOIfNecessary(1);
- if(clazz==FloatBuffer.class) {
- // FIXME: ok ?
- ((FloatBuffer)buffer).put((float)v);
- } else {
- throw new GLException("Double doesn't match Buffer Class: "+clazz+" :\n\t"+this);
- }
- }
-
- public String toString() {
- return "VBOBufferDraw[vertices "+getVerticeNumber()+
- ", glArrayType "+glArrayType+
- ", glDataType "+glDataType+
- ", bufferClazz "+clazz+
- ", components "+components+
- ", initialSize "+initialSize+
- ", glBufferUsage "+glBufferUsage+
- ", vboUsage "+vboUsage+
- ", vboName "+vboName+
- ", sealed "+sealed+
- ", bufferEnabled "+bufferEnabled+
- ",\n\tbuffer "+buffer+
- "]";
- }
-
- protected int glArrayType;
- protected int glDataType;
- protected Class clazz;
- protected Buffer buffer;
- protected int components;
- protected int initialSize;
- protected int glBufferUsage;
- protected int vboName;
- protected boolean sealed;
- protected boolean bufferEnabled;
- protected boolean vboUsage;
-
-}
-
diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderCode.java b/src/classes/javax/media/opengl/util/glsl/ShaderCode.java
new file mode 100644
index 000000000..46ead1b30
--- /dev/null
+++ b/src/classes/javax/media/opengl/util/glsl/ShaderCode.java
@@ -0,0 +1,122 @@
+
+package javax.media.opengl.util.glsl;
+
+import javax.media.opengl.util.*;
+import javax.media.opengl.*;
+
+import java.nio.*;
+import java.io.PrintStream;
+
+public class ShaderCode {
+ public ShaderCode(int type, int number,
+ int binFormat, Buffer binary, String[][] source) {
+ switch (type) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ break;
+ default:
+ throw new GLException("Unknown shader type: "+type);
+ }
+ shaderSource = source;
+ shaderBinaryFormat = binFormat;
+ shaderBinary = binary;
+ shaderType = type;
+ shader = BufferUtil.newIntBuffer(number);
+ id = getNextID();
+ }
+
+ /**
+ * returns the uniq shader id as an integer
+ * @see #key()
+ */
+ public int id() { return id.intValue(); }
+
+ /**
+ * returns the uniq shader id as an Integer
+ *
+ * @see #id()
+ */
+ public Integer key() { return id; }
+
+ public int shaderType() { return shaderType; }
+ public String shaderTypeStr() { return shaderTypeStr(shaderType); }
+
+ public static String shaderTypeStr(int type) {
+ switch (type) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ return "VERTEX_SHADER";
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ return "FRAGMENT_SHADER";
+ }
+ return "UNKNOWN_SHADER";
+ }
+
+ public int shaderBinaryFormat() { return shaderBinaryFormat; }
+ public Buffer shaderBinary() { return shaderBinary; }
+ public String[][] shaderSource() { return shaderSource; }
+
+ public boolean isValid() { return valid; }
+
+ public IntBuffer shader() { return shader; }
+
+ public boolean compile(GL2ES2 gl) {
+ return compile(gl, null);
+ }
+ public boolean compile(GL2ES2 gl, PrintStream verboseOut) {
+ if(isValid()) return true;
+
+ // Create & Compile the vertex/fragment shader objects
+ valid=gl.glCreateCompileShader(shader, shaderType,
+ shaderBinaryFormat, shaderBinary,
+ shaderSource, verboseOut);
+ shader.clear();
+ return valid;
+ }
+
+ public void release(GL2ES2 gl) {
+ if(isValid()) {
+ gl.glDeleteShader(shader());
+ valid=false;
+ }
+ }
+
+ public boolean equals(Object obj) {
+ if(this==obj) return true;
+ if(obj instanceof ShaderCode) {
+ return id()==((ShaderCode)obj).id();
+ }
+ return false;
+ }
+ public int hashCode() {
+ return id.intValue();
+ }
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ShaderCode [id="+id+", type="+shaderTypeStr()+", valid="+valid);
+ /*
+ if(shaderSource!=null) {
+ for(int i=0; i<shaderSource.length; i++) {
+ for(int j=0; j<shaderSource[i].length; j++) {
+ buf.append("\n\t, ShaderSource["+i+"]["+j+"]:\n");
+ buf.append(shaderSource[i][j]);
+ }
+ }
+ } */
+ buf.append("]");
+ return buf.toString();
+ }
+
+ protected String[][] shaderSource = null;
+ protected Buffer shaderBinary = null;
+ protected int shaderBinaryFormat = -1;
+ protected IntBuffer shader = null;
+ protected int shaderType = -1;
+ protected Integer id = null;
+
+ protected boolean valid=false;
+
+ private static synchronized Integer getNextID() {
+ return new Integer(nextID++);
+ }
+ protected static int nextID = 1;
+}
+
diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java b/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java
new file mode 100644
index 000000000..5628f3332
--- /dev/null
+++ b/src/classes/javax/media/opengl/util/glsl/ShaderProgram.java
@@ -0,0 +1,201 @@
+
+package javax.media.opengl.util.glsl;
+
+import javax.media.opengl.util.*;
+import javax.media.opengl.*;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.nio.*;
+import java.io.PrintStream;
+
+public class ShaderProgram {
+ public ShaderProgram() {
+ id = getNextID();
+ }
+
+ public boolean linked() {
+ return programLinked;
+ }
+
+ public boolean inUse() {
+ return programInUse;
+ }
+
+ public int program() { return shaderProgram; }
+
+ /**
+ * returns the uniq shader id as an integer
+ * @see #key()
+ */
+ public int id() { return id.intValue(); }
+
+ /**
+ * returns the uniq shader id as an Integer
+ *
+ * @see #id()
+ */
+ public Integer key() { return id; }
+
+ /**
+ * @see #glReleaseAllVertexAttributes
+ */
+ public synchronized void release(GL2ES2 gl) {
+ release(gl, false);
+ }
+
+ /**
+ * @see #glReleaseAllVertexAttributes
+ */
+ public synchronized void release(GL2ES2 gl, boolean releaseShaderToo) {
+ glUseProgram(gl, false);
+ for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) {
+ ShaderCode shaderCode = (ShaderCode) iter.next();
+ gl.glDetachShader(shaderProgram, shaderCode.shader());
+ if(releaseShaderToo) {
+ shaderCode.release(gl);
+ }
+ }
+ shaderMap.clear();
+ gl.glDeleteProgram(shaderProgram);
+ shaderProgram=-1;
+ }
+
+ //
+ // ShaderCode handling
+ //
+
+ /**
+ * Adds a new shader to a this non running program.
+ *
+ * @return false if the program is in use, or the shader already exist,
+ * otherwise true.
+ */
+ public synchronized boolean add(ShaderCode shaderCode) {
+ if(shaderMap.containsKey(shaderCode.key())) return false;
+ shaderMap.put(shaderCode.key(), shaderCode);
+ return true;
+ }
+
+ public synchronized ShaderCode getShader(int id) {
+ return (ShaderCode) shaderMap.get(new Integer(id));
+ }
+
+ //
+ // Program handling
+ //
+
+ /**
+ * Replace a shader in a 'running' program.
+ * Refetches all previously bin/get attribute names
+ * and resets all attribute data as well
+ *
+ * @see getAttribLocation
+ * @param gl
+ * @param oldShaderID the to be replace Shader
+ * @param newShader the new ShaderCode
+ * @param verboseOut the optional verbose outputstream
+ * @throws GLException is the program is not linked
+ *
+ * @see #glRefetchAttribLocations
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public synchronized boolean glReplaceShader(GL2ES2 gl, int oldShaderID, ShaderCode newShader, PrintStream verboseOut) {
+ if(!programLinked) throw new GLException("Program is not linked");
+ boolean shaderWasInUse = programInUse;
+ glUseProgram(gl, false);
+ if(!newShader.compile(gl, verboseOut)) {
+ return false;
+ }
+ if(oldShaderID>=0) {
+ ShaderCode oldShader = (ShaderCode) shaderMap.remove(new Integer(oldShaderID));
+ if(null!=oldShader) {
+ gl.glDetachShader(shaderProgram, oldShader.shader());
+ }
+ }
+ add(newShader);
+
+ gl.glAttachShader(shaderProgram, newShader.shader());
+ gl.glLinkProgram(shaderProgram);
+ if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) {
+ return false;
+ }
+
+ if(shaderWasInUse) {
+ glUseProgram(gl, true);
+ }
+ return true;
+ }
+
+ public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) {
+ if(programLinked) throw new GLException("Program is already linked");
+
+ if(0>shaderProgram) {
+ shaderProgram = gl.glCreateProgram();
+ }
+
+ for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) {
+ ShaderCode shaderCode = (ShaderCode) iter.next();
+ if(!shaderCode.compile(gl, verboseOut)) {
+ return false;
+ }
+ gl.glAttachShader(shaderProgram, shaderCode.shader());
+ }
+
+ // Link the program
+ gl.glLinkProgram(shaderProgram);
+
+ if ( ! gl.glIsProgramValid(shaderProgram, System.err) ) {
+ return false;
+ }
+ programLinked=true;
+
+ return true;
+ }
+
+ public boolean equals(Object obj) {
+ if(this==obj) return true;
+ if(obj instanceof ShaderCode) {
+ return id()==((ShaderCode)obj).id();
+ }
+ return false;
+ }
+ public int hashCode() {
+ return id.intValue();
+ }
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("ShaderProgram[id="+id);
+ buf.append(", linked="+programLinked+", inUse="+programInUse+", program: "+shaderProgram+", [");
+ for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) {
+ buf.append((ShaderCode) iter.next());
+ buf.append(" ");
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ protected synchronized void glUseProgram(GL2ES2 gl, boolean on) {
+ if(!programLinked) throw new GLException("Program is not linked");
+ if(programInUse==on) return;
+ gl.glUseProgram(on?shaderProgram:0);
+ programInUse = on;
+
+ //Throwable tX = new Throwable("Info: ShaderProgram.glUseProgram: "+on);
+ //tX.printStackTrace();
+
+ }
+
+ protected boolean programLinked = false;
+ protected boolean programInUse = false;
+ protected int shaderProgram=-1;
+ protected HashMap shaderMap = new HashMap();
+ protected Integer id = null;
+
+ private static synchronized Integer getNextID() {
+ return new Integer(nextID++);
+ }
+ protected static int nextID = 1;
+}
+
diff --git a/src/classes/javax/media/opengl/util/glsl/ShaderState.java b/src/classes/javax/media/opengl/util/glsl/ShaderState.java
new file mode 100644
index 000000000..7f917cc07
--- /dev/null
+++ b/src/classes/javax/media/opengl/util/glsl/ShaderState.java
@@ -0,0 +1,583 @@
+
+package javax.media.opengl.util.glsl;
+
+import javax.media.opengl.util.*;
+import javax.media.opengl.*;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.nio.*;
+import java.io.PrintStream;
+
+public class ShaderState {
+
+ public ShaderState() {
+ }
+
+ public boolean verbose() { return verbose; }
+
+ public void setVerbose(boolean v) { verbose=v; }
+
+ /**
+ * Fetches the current shader state
+ *
+ * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean)
+ * @see javax.media.opengl.util.glsl.ShaderState#getCurrent()
+ */
+ public static synchronized ShaderState getCurrent() { return currentShaderState; }
+
+ /**
+ * Turns the shader program on
+ * and set this ShaderState to current if on equals true
+ *
+ * @see javax.media.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean)
+ * @see javax.media.opengl.util.glsl.ShaderState#getCurrent()
+ */
+ public synchronized void glUseProgram(GL2ES2 gl, boolean on) {
+ if(on) {
+ if(null!=shaderProgram) {
+ shaderProgram.glUseProgram(gl, true);
+ } else {
+ throw new GLException("No program is attached");
+ }
+ if(currentShaderState!=this) {
+ currentShaderState = this;
+ }
+ } else if(null!=shaderProgram) {
+ shaderProgram.glUseProgram(gl, false);
+ }
+ }
+
+ public boolean linked() {
+ return (null!=shaderProgram)?shaderProgram.linked():false;
+ }
+
+ public boolean inUse() {
+ return (null!=shaderProgram)?shaderProgram.inUse():false;
+ }
+
+ /**
+ * Attach or switch a shader program
+ *
+ * Attaching a shader program the first time,
+ * as well as switching to another program on the fly,
+ * while managing all attribute and uniform data.
+ */
+ public synchronized void attachShaderProgram(GL2ES2 gl, ShaderProgram prog) {
+ boolean prgInUse = false; // earmarked state
+
+ if(null!=shaderProgram) {
+ if(shaderProgram.equals(prog)) {
+ // nothing to do ..
+ if(DEBUG) {
+ System.err.println("Info: attachShaderProgram: NOP: equal id: "+shaderProgram.id());
+ }
+ return;
+ }
+ prgInUse = shaderProgram.inUse();
+ }
+ if(DEBUG) {
+ Throwable tX = new Throwable("Info: attachShaderProgram: BEGIN "+shaderProgram+" -> "+prog);
+ tX.printStackTrace();
+ }
+
+ // register new one
+ shaderProgram = prog;
+
+ if(null!=shaderProgram) {
+ // reinstall all data ..
+ shaderProgram.glUseProgram(gl, true);
+ glResetAllVertexAttributes(gl);
+ glResetAllUniforms(gl);
+ if(!prgInUse) {
+ shaderProgram.glUseProgram(gl, false);
+ }
+ }
+ if(DEBUG) {
+ System.err.println("Info: attachShaderProgram: END");
+ }
+ }
+
+ public ShaderProgram shaderProgram() { return shaderProgram; }
+
+ /**
+ * @see #glReleaseAllVertexAttributes
+ * @see #glReleaseAllUniforms
+ */
+ public synchronized void release(GL2ES2 gl) {
+ release(gl, false, false);
+ }
+
+ public synchronized void release(GL2ES2 gl, boolean releaseProgramToo, boolean releaseShaderToo) {
+ boolean prgInUse = false;
+ if(null!=shaderProgram) {
+ prgInUse = shaderProgram.inUse();
+ if(!prgInUse) {
+ shaderProgram.glUseProgram(gl, true);
+ }
+ }
+ glReleaseAllVertexAttributes(gl);
+ glReleaseAllUniforms(gl);
+ if(null!=shaderProgram) {
+ if(releaseProgramToo) {
+ shaderProgram.release(gl, releaseShaderToo);
+ } else if(!prgInUse) {
+ shaderProgram.glUseProgram(gl, false);
+ }
+ }
+ }
+
+ //
+ // Shader attribute handling
+ //
+
+ /**
+ * Binds an attribute to the shader.
+ * This must be done before the program is linked !
+ * n name - 1 idx, where name is a uniq key
+ *
+ * @throws GLException is the program is already linked
+ *
+ * @see #glBindAttribLocation
+ * @see javax.media.opengl.GL2ES2#glBindAttribLocation
+ * @see #glGetAttribLocation
+ * @see javax.media.opengl.GL2ES2#glGetAttribLocation
+ * @see #getAttribLocation
+ * @see #glReplaceShader
+ */
+ public void glBindAttribLocation(GL2ES2 gl, int index, String name) {
+ if(null==shaderProgram) throw new GLException("No program is attached");
+ if(shaderProgram.linked()) throw new GLException("Program is already linked");
+ Integer idx = new Integer(index);
+ if(!attribMap2Idx.containsKey(name)) {
+ attribMap2Idx.put(name, idx);
+ gl.glBindAttribLocation(shaderProgram.program(), index, name);
+ }
+ }
+
+ /**
+ * Gets the index of a shader attribute.
+ * This must be done after the program is linked !
+ *
+ * @return -1 if there is no such attribute available,
+ * otherwise >= 0
+ * @throws GLException is the program is not linked
+ *
+ * @see #glBindAttribLocation
+ * @see javax.media.opengl.GL2ES2#glBindAttribLocation
+ * @see #glGetAttribLocation
+ * @see javax.media.opengl.GL2ES2#glGetAttribLocation
+ * @see #getAttribLocation
+ * @see #glReplaceShader
+ */
+ public int glGetAttribLocation(GL2ES2 gl, String name) {
+ if(!shaderProgram.linked()) throw new GLException("Program is not linked");
+ int index = getAttribLocation(name);
+ if(0>index) {
+ index = gl.glGetAttribLocation(shaderProgram.program(), name);
+ if(0<=index) {
+ Integer idx = new Integer(index);
+ attribMap2Idx.put(name, idx);
+ } else if(verbose) {
+ Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", index: "+index);
+ tX.printStackTrace();
+ }
+ }
+ return index;
+ }
+
+ protected int getAttribLocation(String name) {
+ Integer idx = (Integer) attribMap2Idx.get(name);
+ return (null!=idx)?idx.intValue():-1;
+ }
+
+
+ //
+ // Enabled Vertex Arrays and its data
+ //
+
+ /**
+ * Enable a vertex attribute array
+ *
+ * Even if the attribute is not found in the current shader,
+ * it is stored in this state.
+ *
+ * @returns false, if the name is not found, otherwise true
+ *
+ * @throws GLException if the program is not in use
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public boolean glEnableVertexAttribArray(GL2ES2 gl, String name) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ enabledVertexAttribArraySet.add(name);
+ int index = glGetAttribLocation(gl, name);
+ if(0>index) {
+ if(verbose) {
+ Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name);
+ tX.printStackTrace();
+ }
+ return false;
+ }
+ if(DEBUG) {
+ System.err.println("Info: glEnableVertexAttribArray: "+name);
+ }
+ gl.glEnableVertexAttribArray(index);
+ return true;
+ }
+
+ public boolean isVertexAttribArrayEnabled(String name) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ return enabledVertexAttribArraySet.contains(name);
+ }
+
+ /**
+ * Disables a vertex attribute array
+ *
+ * Even if the attribute is not found in the current shader,
+ * it is removed from this state.
+ *
+ * @returns false, if the name is not found, otherwise true
+ *
+ * @throws GLException if the program is not in use
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public boolean glDisableVertexAttribArray(GL2ES2 gl, String name) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ enabledVertexAttribArraySet.remove(name);
+ int index = glGetAttribLocation(gl, name);
+ if(0>index) {
+ if(verbose) {
+ Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name);
+ tX.printStackTrace();
+ }
+ return false;
+ }
+ if(DEBUG) {
+ System.err.println("Info: glDisableVertexAttribArray: "+name);
+ }
+ gl.glDisableVertexAttribArray(index);
+ return true;
+ }
+
+ /**
+ * Set the vertex attribute data.
+ * Enable the attribute, if it is not enabled yet.
+ *
+ * Even if the attribute is not found in the current shader,
+ * it is stored in this state.
+ *
+ * @arg data the GLArrayData's name must match the attributes one,
+ * it's index will be set with the attribute's location,
+ * if found.
+ *
+ * @returns false, if the name is not found, otherwise true
+ *
+ * @throws GLException if the program is not in use
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public boolean glVertexAttribPointer(GL2ES2 gl, GLArrayData data) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ if(!enabledVertexAttribArraySet.contains(data.getName())) {
+ if(!glEnableVertexAttribArray(gl, data.getName())) {
+ if(verbose) {
+ Throwable tX = new Throwable("Info: glVertexAttribPointer: couldn't enable: "+data);
+ tX.printStackTrace();
+ }
+ }
+ }
+ int index = getAttribLocation(data.getName());
+ if(0>index) {
+ if(verbose) {
+ Throwable tX = new Throwable("Info: glVertexAttribPointer failed, no index for: "+data);
+ tX.printStackTrace();
+ }
+ }
+ data.setLocation(index);
+ vertexAttribMap2Data.put(data.getName(), data);
+ if(0<=index) {
+ // only pass the data, if the attribute exists in the current shader
+ if(DEBUG) {
+ System.err.println("Info: glVertexAttribPointer: "+data);
+ }
+ gl.glVertexAttribPointer(data);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the vertex attribute data, previously set.
+ *
+ * @returns the GLArrayData object, null if not previously set.
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public GLArrayData getVertexAttribPointer(String name) {
+ return (GLArrayData) vertexAttribMap2Data.get(name);
+ }
+
+ /**
+ * Releases all mapped vertex attribute data,
+ * disables all enabled attributes and loses all indices
+ *
+ * @throws GLException is the program is not in use but the shaderProgram is set
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public void glReleaseAllVertexAttributes(GL2ES2 gl) {
+ if(null!=shaderProgram) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ for(Iterator iter = vertexAttribMap2Data.keySet().iterator(); iter.hasNext(); ) {
+ if(!glDisableVertexAttribArray(gl, (String) iter.next())) {
+ throw new GLException("Internal Error: mapped vertex attribute couldn't be disabled");
+ }
+ }
+ for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) {
+ if(!glDisableVertexAttribArray(gl, (String) iter.next())) {
+ throw new GLException("Internal Error: prev enabled vertex attribute couldn't be disabled");
+ }
+ }
+ }
+ vertexAttribMap2Data.clear();
+ enabledVertexAttribArraySet.clear();
+ attribMap2Idx.clear();
+ }
+
+ /**
+ * Disables all vertex attribute arrays.
+ *
+ * Their enabled stated will be removed from this state only
+ * if 'removeFromState' is true.
+ *
+ * This method purpose is more for debugging.
+ *
+ * @throws GLException is the program is not in use but the shaderProgram is set
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public void glDisableAllVertexAttributeArrays(GL2ES2 gl, boolean removeFromState) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+
+ for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) {
+ String name = (String) iter.next();
+ if(removeFromState) {
+ enabledVertexAttribArraySet.remove(name);
+ }
+ int index = glGetAttribLocation(gl, name);
+ if(0<=index) {
+ gl.glDisableVertexAttribArray(index);
+ }
+ }
+ }
+
+ /**
+ * Reset all previously mapped vertex attribute data,
+ * incl enabling them
+ *
+ * @throws GLException is the program is not in use
+ *
+ * @see #glEnableVertexAttribArray
+ * @see #glDisableVertexAttribArray
+ * @see #glVertexAttribPointer
+ * @see #getVertexAttributePointer
+ * @see #glReleaseAllVertexAttributes
+ * @see #glResetAllVertexAttributes
+ * @see #glReplaceShader
+ */
+ public void glResetAllVertexAttributes(GL2ES2 gl) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ attribMap2Idx.clear();
+
+ for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) {
+ glEnableVertexAttribArray(gl, (String) iter.next());
+ }
+
+ for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) {
+ glVertexAttribPointer(gl, (GLArrayData) iter.next());
+ }
+ }
+
+ //
+ // Shader Uniform handling
+ //
+
+ /**
+ * Gets the index of a shader uniform.
+ * This must be done when the program is in use !
+ *
+ * @return -1 if there is no such attribute available,
+ * otherwise >= 0
+
+ * @throws GLException is the program is not linked
+ *
+ * @see #glGetUniformLocation
+ * @see javax.media.opengl.GL2ES2#glGetUniformLocation
+ * @see #getUniformLocation
+ * @see #glReplaceShader
+ */
+ protected int glGetUniformLocation(GL2ES2 gl, String name) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ int index = getUniformLocation(name);
+ if(0>index) {
+ index = gl.glGetUniformLocation(shaderProgram.program(), name);
+ if(0<=index) {
+ Integer idx = new Integer(index);
+ uniformMap2Idx.put(name, idx);
+ } else if(verbose) {
+ Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+index);
+ tX.printStackTrace();
+ }
+ }
+ return index;
+ }
+
+ protected int getUniformLocation(String name) {
+ Integer idx = (Integer) uniformMap2Idx.get(name);
+ return (null!=idx)?idx.intValue():-1;
+ }
+
+ /**
+ * Set the uniform data.
+ *
+ * Even if the uniform is not found in the current shader,
+ * it is stored in this state.
+ *
+ * @arg data the GLUniforms's name must match the uniform one,
+ * it's index will be set with the uniforms's location,
+ * if found.
+ *
+ *
+ * @returns false, if the name is not found, otherwise true
+ *
+ * @throws GLException if the program is not in use
+ *
+ * @see #glGetUniformLocation
+ * @see javax.media.opengl.GL2ES2#glGetUniformLocation
+ * @see #getUniformLocation
+ * @see #glReplaceShader
+ */
+ public boolean glUniform(GL2ES2 gl, GLUniformData data) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ int location = glGetUniformLocation(gl, data.getName());
+ data.setLocation(location);
+ uniformMap2Data.put(data.getName(), data);
+ if(0<=location) {
+ // only pass the data, if the uniform exists in the current shader
+ if(DEBUG) {
+ System.err.println("Info: glUniform: "+data);
+ }
+ gl.glUniform(data);
+ }
+ return true;
+ }
+
+ /**
+ * Get the uniform data, previously set.
+ *
+ * @returns the GLUniformData object, null if not previously set.
+ */
+ public GLUniformData getUniform(String name) {
+ return (GLUniformData) uniformMap2Data.get(name);
+ }
+
+ /**
+ * Releases all mapped uniform data
+ * and loses all indices
+ *
+ * @throws GLException is the program is not in use
+ */
+ public void glReleaseAllUniforms(GL2ES2 gl) {
+ uniformMap2Data.clear();
+ uniformMap2Idx.clear();
+ }
+
+ /**
+ * Reset all previously mapped uniform data
+ *
+ * @throws GLException is the program is not in use
+ */
+ public void glResetAllUniforms(GL2ES2 gl) {
+ if(!shaderProgram.inUse()) throw new GLException("Program is not in use");
+ uniformMap2Idx.clear();
+ for(Iterator iter = uniformMap2Data.values().iterator(); iter.hasNext(); ) {
+ glUniform(gl, (GLUniformData) iter.next());
+ }
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("ShaderState[");
+ buf.append(shaderProgram.toString());
+ buf.append(",EnabledStates: [");
+ for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) {
+ buf.append("\n ");
+ buf.append((String)iter.next());
+ }
+ buf.append("], [");
+ for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) {
+ buf.append("\n ");
+ buf.append((GLArrayData) iter.next());
+ }
+ buf.append("], [");
+ for(Iterator iter=uniformMap2Data.values().iterator(); iter.hasNext(); ) {
+ buf.append("\n ");
+ buf.append((GLUniformData) iter.next());
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ protected static final boolean DEBUG = false;
+ protected boolean verbose = false;
+ protected ShaderProgram shaderProgram=null;
+ protected HashMap attribMap2Idx = new HashMap();
+ protected HashSet enabledVertexAttribArraySet = new HashSet();
+ protected HashMap vertexAttribMap2Data = new HashMap();
+ protected HashMap uniformMap2Idx = new HashMap();
+ protected HashMap uniformMap2Data = new HashMap();
+ protected static ShaderState currentShaderState = null;
+
+}
+