Commits

Michael Ludwig committed 9f532cd

Add shapes and reorganize packages, add jar descriptions for release.

  • Participants
  • Parent commits a1bb15e

Comments (0)

Files changed (104)

data/binaryJar.jardesc

+<?xml version="1.0" encoding="MacRoman"?>
+<jardesc>
+<jar path="/Users/michaelludwig/Desktop/ferox-bin.jar"/>
+<options buildIfNeeded="true" compress="true" descriptionLocation="/Ferox2/data/binaryJar.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
+<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
+<selectedProjects/>
+<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
+<sealing sealJar="false">
+<packagesToSeal/>
+<packagesToUnSeal/>
+</sealing>
+</manifest>
+<selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
+<javaElement handleIdentifier="=Ferox2/test"/>
+<javaElement handleIdentifier="=Ferox2/src"/>
+</selectedElements>
+<fatjar builder="org.eclipse.jdt.ui.plain_jar_builder" launchConfig=""/>
+</jardesc>

data/ferox-textures.jar

Binary file modified.

data/srcJar.jardesc

+<?xml version="1.0" encoding="MacRoman"?>
+<jardesc>
+<jar path="/Users/michaelludwig/Desktop/ferox-src.jar"/>
+<options buildIfNeeded="true" compress="true" descriptionLocation="/Ferox2/data/srcJar.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
+<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
+<selectedProjects/>
+<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
+<sealing sealJar="false">
+<packagesToSeal/>
+<packagesToUnSeal/>
+</sealing>
+</manifest>
+<selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false">
+<javaElement handleIdentifier="=Ferox2/test"/>
+<javaElement handleIdentifier="=Ferox2/src"/>
+</selectedElements>
+<fatjar builder="org.eclipse.jdt.ui.plain_jar_builder" launchConfig=""/>
+</jardesc>

lib/openmali.jar

Binary file modified.

src/com/ferox/renderer/Renderer.java

 import com.ferox.resource.Resource;
 import com.ferox.resource.ResourceManager;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 import com.ferox.state.State.Role;
 
 /** The Renderer is the core component of rendering a scene with

src/com/ferox/renderer/TextureSurface.java

 package com.ferox.renderer;
 
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** A TextureSurface represents a surface that renders its content
  * directly into multiple, usable textures.  This can be used for a variety

src/com/ferox/renderer/impl/AbstractRenderer.java

 import com.ferox.resource.Geometry;
 import com.ferox.resource.Resource;
 import com.ferox.resource.ResourceManager;
-import com.ferox.resource.TextureImage;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 import com.ferox.state.Appearance;
 import com.ferox.state.DepthTest;
 import com.ferox.state.Material;
 	public static enum RenderState {
 		WAITING_INIT, /** State of the renderer before init() is called */
 		IDLE,		  /** State of the renderer when it's not doing anything */
-		RESOURCE,	  /** State of the renderer when it's managing resources or creating surfaces */
-		PIPELINE,	  /** State of the renderer when it's okay to call applyInfluence and renderAtom */ 
+		RENDERING,    /** State of the renderer when it's in flushRenderer(). */
 		DESTROYED 	  /** State of the renderer after destroy() is called */
 	}
 	

src/com/ferox/renderer/impl/SurfaceFactory.java

 import com.ferox.renderer.RenderException;
 import com.ferox.renderer.TextureSurface;
 import com.ferox.renderer.WindowSurface;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** SurfaceFactory is one of the major backbones of
  * an AbstractRenderer subclass. It provides a more specific

src/com/ferox/renderer/impl/jogl/BasicGeometryDriverFactory.java

  * drivers for a Geometry if there's an implementation of GeometryDriver
  * matching this pattern:
  *		com.ferox.renderer.impl.jogl.drivers.Jogl<GeometrySimpleClassName>Driver
- * 
+ * If no class is found, it will search for drivers matching the geometry's superclasses.
+ *  
  * It will load that class, make sure it implements GeometryDriver and return one
  * instance of that class per factory lifetime.  The GeometryDriver must declare a 
  * constructor that takes a JoglSurfaceFactory as an argument.
 		this.factory = factory;
 	}
 	
+	@SuppressWarnings("unchecked")
 	@Override
 	public GeometryDriver getDriver(Class<? extends Geometry> type) {
 		if (type != null) {
-			GeometryDriver driver = this.loadedDrivers.get(type);
-			if (driver == null)
-				driver = this.loadNewDriver(type);
-			return driver;
+			while(true) {
+				GeometryDriver driver = this.loadedDrivers.get(type);
+				if (driver == null) // try to load the type
+					driver = this.loadNewDriver(type);
+				
+				if (driver == null) {
+					// move type to super-class
+					Class<?> spr = type.getSuperclass();
+					if (Geometry.class.isAssignableFrom(spr))
+						type = (Class<? extends Geometry>) spr;
+					else
+						return null;
+				} else
+					return driver;
+			}		
 		}
 		
 		return null;

src/com/ferox/renderer/impl/jogl/BasicResourceDriverFactory.java

  * drivers for a Resource if there's an implementation of ResourceDriver
  * matching this pattern:
  *		com.ferox.renderer.impl.jogl.drivers.Jogl<ResourceSimpleClassName>ResourceDriver
+ * If no class is found, it will search for drivers matching the resource's superclasses.
  *
  * It will load that class, make sure it implements ResourceDriver and return one
  * instance of that class per factory lifetime.  The ResourceDriver must declare
 		this.factory = factory;
 	}
 	
+	@SuppressWarnings("unchecked")
 	@Override
 	public ResourceDriver getDriver(Class<? extends Resource> type) {
 		if (type != null) {
-			ResourceDriver driver = this.loadedDrivers.get(type);
-			if (driver == null)
-				driver = this.loadNewDriver(type);
-			return driver;
+			while(true) {
+				ResourceDriver driver = this.loadedDrivers.get(type);
+				if (driver == null) // try to load the type
+					driver = this.loadNewDriver(type);
+				
+				if (driver == null) {
+					// move type to super-class
+					Class<?> spr = type.getSuperclass();
+					if (Resource.class.isAssignableFrom(spr))
+						type = (Class<? extends Resource>) spr;
+					else
+						return null;
+				} else
+					return driver;
+			}	
 		}
 		
 		return null;

src/com/ferox/renderer/impl/jogl/EnumUtil.java

 
 import javax.media.opengl.GL;
 
-import com.ferox.resource.TextureCubeMap;
-import com.ferox.resource.TextureFormat;
 import com.ferox.resource.BufferData.DataType;
-import com.ferox.resource.BufferedGeometry.PolygonType;
-import com.ferox.resource.GlslUniform.UniformType;
-import com.ferox.resource.GlslVertexAttribute.AttributeType;
-import com.ferox.resource.TextureImage.DepthMode;
-import com.ferox.resource.TextureImage.Filter;
-import com.ferox.resource.TextureImage.TextureTarget;
-import com.ferox.resource.TextureImage.TextureWrap;
-import com.ferox.resource.VertexBufferObject.UsageHint;
+import com.ferox.resource.geometry.BufferedGeometry.PolygonType;
+import com.ferox.resource.geometry.VertexBufferObject.UsageHint;
+import com.ferox.resource.glsl.GlslUniform.UniformType;
+import com.ferox.resource.glsl.GlslVertexAttribute.AttributeType;
+import com.ferox.resource.texture.TextureCubeMap;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.TextureImage.DepthMode;
+import com.ferox.resource.texture.TextureImage.Filter;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage.TextureWrap;
 import com.ferox.scene.Fog.FogEquation;
 import com.ferox.state.BlendMode.BlendEquation;
 import com.ferox.state.BlendMode.BlendFactor;

src/com/ferox/renderer/impl/jogl/FboDelegate.java

 
 import com.ferox.renderer.DisplayOptions;
 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** Provides fbo support for JoglTextureSurface.  These should only
  * be instantiated when fbo support is available.

src/com/ferox/renderer/impl/jogl/JoglCapabilitiesDetector.java

 import com.ferox.renderer.impl.CapabilitiesDetector;
 
 public class JoglCapabilitiesDetector implements CapabilitiesDetector {
+	private static final boolean FORCE_NO_FBO = false;
 	private static final boolean FORCE_NO_PBUFFER = false;
 	
 	private RenderCapabilities capabilities;
 		
 		boolean pointSpriteSupported = gl.isExtensionAvailable("GL_ARB_point_sprite") || vNum >= 2f;
 		boolean glslSupported = gl.isExtensionAvailable("GL_ARB_shading_language_100") || vNum >= 2f;
-		boolean fboSupported = gl.isExtensionAvailable("GL_EXT_framebuffer_object");
-		boolean pbufferSupported = GLDrawableFactory.getFactory().canCreateGLPbuffer();
+		boolean fboSupported = !FORCE_NO_FBO && gl.isExtensionAvailable("GL_EXT_framebuffer_object");
+		boolean pbufferSupported = !FORCE_NO_PBUFFER && GLDrawableFactory.getFactory().canCreateGLPbuffer();
 		
 		boolean multiTexSupported = vNum >= 1.3f || gl.isExtensionAvailable("GL_ARB_multitexture");
 		boolean npotTextures = vNum >= 2.0f || gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two");

src/com/ferox/renderer/impl/jogl/JoglFbo.java

 import com.ferox.renderer.impl.jogl.drivers.TextureHandle;
 import com.ferox.renderer.impl.jogl.record.FramebufferRecord;
 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
-import com.ferox.resource.TextureCubeMap;
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureCubeMap;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** A wrapper around framebuffer object functionality to make it slightly easier
  * to use with FboDelegate.

src/com/ferox/renderer/impl/jogl/JoglSurfaceFactory.java

 import com.ferox.renderer.impl.SurfaceFactory;
 import com.ferox.renderer.impl.jogl.drivers.JoglTransformDriver;
 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** The JoglSurfaceFactory provides an implementation of SurfaceFactory
  * for use with jogl based renderers.  Its internals with context management

src/com/ferox/renderer/impl/jogl/JoglTextureSurface.java

 import com.ferox.renderer.DisplayOptions.PixelFormat;
 import com.ferox.renderer.DisplayOptions.StencilFormat;
 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
-import com.ferox.resource.Texture1D;
-import com.ferox.resource.Texture2D;
-import com.ferox.resource.Texture3D;
-import com.ferox.resource.TextureCubeMap;
-import com.ferox.resource.TextureFormat;
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureRectangle;
 import com.ferox.resource.BufferData.DataType;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.Texture1D;
+import com.ferox.resource.texture.Texture2D;
+import com.ferox.resource.texture.Texture3D;
+import com.ferox.resource.texture.TextureCubeMap;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureRectangle;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** JoglTextureSurface provides the ability to render into either pbuffers or
  * fbos, depending on the support of the current hardware.  This functionality

src/com/ferox/renderer/impl/jogl/PbufferDelegate.java

 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
 import com.ferox.renderer.impl.jogl.record.TextureRecord;
 import com.ferox.renderer.impl.jogl.record.TextureRecord.TextureUnit;
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** Provides GLPBuffer support for the JoglTextureSurface. */
 public class PbufferDelegate extends TextureSurfaceDelegate {
 			gl.glCopyTexSubImage1D(handle.glTarget, 0, 0, 0, 0, this.getWidth());
 			break;
 		case GL.GL_TEXTURE_2D: case GL.GL_TEXTURE_RECTANGLE_ARB:
-			gl.glCopyTexImage2D(handle.glTarget, 0, 0, 0, 0, 0, this.getWidth(), this.getHeight());
+			gl.glCopyTexSubImage2D(handle.glTarget, 0, 0, 0, 0, 0, this.getWidth(), this.getHeight());
 			break;
 		case GL.GL_TEXTURE_CUBE_MAP:	
 			int face = EnumUtil.getGLCubeFace(this.swapBuffersLayer);
 			gl.glCopyTexSubImage2D(face, 0, 0, 0, 0, 0, this.getWidth(), this.getHeight());
 		case GL.GL_TEXTURE_3D:
-			gl.glCopyTexSubImage3D(handle.glTarget, 0, 0, this.swapBuffersLayer, 0, 0, 0, this.getWidth(), this.getHeight());
+			gl.glCopyTexSubImage3D(handle.glTarget, 0, 0, 0, this.swapBuffersLayer, 0, 0, this.getWidth(), this.getHeight());
 			break;
 		}
 	}

src/com/ferox/renderer/impl/jogl/TextureSurfaceDelegate.java

 
 import com.ferox.renderer.DisplayOptions;
 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureImage.TextureTarget;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureTarget;
 
 /** Provide a flexible implementation for rendering-to-texture.
  * Implementations of this will be instantiated by JoglTextureSurface.

src/com/ferox/renderer/impl/jogl/drivers/BufferedGeometryDriver.java

 
 import com.ferox.renderer.impl.ResourceData.Handle;
 import com.ferox.renderer.impl.jogl.EnumUtil;
-import com.ferox.resource.BufferedGeometry;
-import com.ferox.resource.VertexArray;
 import com.ferox.resource.BufferData.DataType;
-import com.ferox.resource.BufferedGeometry.GeometryArray;
 import com.ferox.resource.UnitList.Unit;
+import com.ferox.resource.geometry.BufferedGeometry;
+import com.ferox.resource.geometry.VertexArray;
+import com.ferox.resource.geometry.BufferedGeometry.GeometryArray;
 
 /** BufferedGeometryDriver provides some utility functions
  * that will be common for any GeometryDriver implemented
 		}
 		
 		// check the data types of all present arrays, they must be FLOAT
-		if (normals != null && normals.getEffectiveType() != DataType.FLOAT)
+		if (normals != null && normals.getType() != DataType.FLOAT)
 			return -1;
-		if (texCoords != null && texCoords.getEffectiveType() != DataType.FLOAT)
+		if (texCoords != null && texCoords.getType() != DataType.FLOAT)
 			return -1;
-		if (vertices.getEffectiveType() != DataType.FLOAT)
+		if (vertices.getType() != DataType.FLOAT)
 			return -1;
 				
 		// check if the element sizes, offset and strides make sense
 				VertexArray v = vertices.getAccessor();
 				
 				if (n.getElementSize() == 3 && t.getElementSize() == 2 && v.getElementSize() == 3) {
-					if (t.getOffset() == 0 && n.getOffset() == 2 && t.getOffset() == 5) {
+					if (t.getOffset() == 0 && n.getOffset() == 2 && v.getOffset() == 5) {
 						if (t.getStride() == 6 && n.getStride() == 5 && v.getStride() == 5)
 							return GL.GL_T2F_N3F_V3F;
 					}

src/com/ferox/renderer/impl/jogl/drivers/JoglGlslProgramResourceDriver.java

 import com.ferox.renderer.impl.ResourceData.Handle;
 import com.ferox.renderer.impl.jogl.EnumUtil;
 import com.ferox.renderer.impl.jogl.JoglSurfaceFactory;
-import com.ferox.resource.GlslProgram;
-import com.ferox.resource.GlslUniform;
-import com.ferox.resource.GlslVertexAttribute;
 import com.ferox.resource.Resource;
-import com.ferox.resource.GlslProgram.GlslProgramDirtyDescriptor;
-import com.ferox.resource.GlslUniform.UniformType;
-import com.ferox.resource.GlslVertexAttribute.AttributeType;
 import com.ferox.resource.Resource.Status;
+import com.ferox.resource.glsl.GlslProgram;
+import com.ferox.resource.glsl.GlslUniform;
+import com.ferox.resource.glsl.GlslVertexAttribute;
+import com.ferox.resource.glsl.GlslProgram.GlslProgramDirtyDescriptor;
+import com.ferox.resource.glsl.GlslUniform.UniformType;
+import com.ferox.resource.glsl.GlslVertexAttribute.AttributeType;
 
 public class JoglGlslProgramResourceDriver implements ResourceDriver {
 	/* Handle subclass used for GlslPrograms. */

src/com/ferox/renderer/impl/jogl/drivers/JoglGlslUniformResourceDriver.java

 import com.ferox.renderer.impl.ResourceData.Handle;
 import com.ferox.renderer.impl.jogl.EnumUtil;
 import com.ferox.renderer.impl.jogl.JoglSurfaceFactory;
-import com.ferox.resource.GlslUniform;
 import com.ferox.resource.Resource;
-import com.ferox.resource.GlslUniform.UniformType;
 import com.ferox.resource.Resource.Status;
+import com.ferox.resource.glsl.GlslUniform;
+import com.ferox.resource.glsl.GlslUniform.UniformType;
 
 /** JoglGlslUniformResourceDriver detects a uniform's index within
  * its owning GlslProgram and verifies that its type and length are

src/com/ferox/renderer/impl/jogl/drivers/JoglShaderStateDriver.java

 import com.ferox.renderer.impl.jogl.JoglSurfaceFactory;
 import com.ferox.renderer.impl.jogl.record.GlslShaderRecord;
 import com.ferox.renderer.impl.jogl.record.JoglStateRecord;
-import com.ferox.resource.GlslUniform;
+import com.ferox.resource.glsl.GlslUniform;
 import com.ferox.state.GlslShader;
 import com.ferox.state.GlslShader.UniformBinding;
 

src/com/ferox/renderer/impl/jogl/drivers/JoglTexture1DResourceDriver.java

 import com.ferox.renderer.impl.jogl.record.TextureRecord.TextureUnit;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Resource;
-import com.ferox.resource.Texture1D;
-import com.ferox.resource.TextureFormat;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.Texture1D.Texture1DDirtyDescriptor;
-import com.ferox.resource.TextureImage.MipmapDirtyRegion;
-import com.ferox.resource.util.TextureConverter;
+import com.ferox.resource.texture.Texture1D;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.Texture1D.Texture1DDirtyDescriptor;
+import com.ferox.resource.texture.TextureImage.MipmapDirtyRegion;
+import com.ferox.resource.texture.converter.TextureConverter;
 
 /** JoglTexture1DResourceDriver provides the functionality to load
  * and delete Texture1D instances in the graphics card.  It will

src/com/ferox/renderer/impl/jogl/drivers/JoglTexture2DResourceDriver.java

 import com.ferox.renderer.impl.jogl.record.TextureRecord.TextureUnit;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Resource;
-import com.ferox.resource.Texture2D;
-import com.ferox.resource.TextureFormat;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.Texture2D.Texture2DDirtyDescriptor;
-import com.ferox.resource.TextureImage.MipmapDirtyRegion;
-import com.ferox.resource.util.TextureConverter;
+import com.ferox.resource.texture.Texture2D;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.Texture2D.Texture2DDirtyDescriptor;
+import com.ferox.resource.texture.TextureImage.MipmapDirtyRegion;
+import com.ferox.resource.texture.converter.TextureConverter;
 
 /** JoglTexture2DResourceDriver provides the functionality to load
  * and delete Texture2D instances in the graphics card.  It will

src/com/ferox/renderer/impl/jogl/drivers/JoglTexture3DResourceDriver.java

 import com.ferox.renderer.impl.jogl.record.TextureRecord.TextureUnit;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Resource;
-import com.ferox.resource.Texture3D;
-import com.ferox.resource.TextureFormat;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.Texture3D.Texture3DDirtyDescriptor;
-import com.ferox.resource.TextureImage.MipmapDirtyRegion;
-import com.ferox.resource.util.TextureConverter;
+import com.ferox.resource.texture.Texture3D;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.Texture3D.Texture3DDirtyDescriptor;
+import com.ferox.resource.texture.TextureImage.MipmapDirtyRegion;
+import com.ferox.resource.texture.converter.TextureConverter;
 
 /** JoglTexture3DResourceDriver provides the functionality to load
  * and delete Texture3D instances in the graphics card.  It will

src/com/ferox/renderer/impl/jogl/drivers/JoglTextureCubeMapResourceDriver.java

 import com.ferox.renderer.impl.jogl.record.TextureRecord.TextureUnit;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Resource;
-import com.ferox.resource.TextureCubeMap;
-import com.ferox.resource.TextureFormat;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.TextureCubeMap.TextureCubeMapDirtyDescriptor;
-import com.ferox.resource.TextureImage.MipmapDirtyRegion;
-import com.ferox.resource.util.TextureConverter;
+import com.ferox.resource.texture.TextureCubeMap;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.TextureCubeMap.TextureCubeMapDirtyDescriptor;
+import com.ferox.resource.texture.TextureImage.MipmapDirtyRegion;
+import com.ferox.resource.texture.converter.TextureConverter;
 
 /** JoglTextureCubeMapResourceDriver provides the functionality to load
  * and delete TextureCubeMap instances in the graphics card.  It will

src/com/ferox/renderer/impl/jogl/drivers/JoglTextureRectangleResourceDriver.java

 import com.ferox.renderer.impl.jogl.record.TextureRecord.TextureUnit;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Resource;
-import com.ferox.resource.TextureFormat;
-import com.ferox.resource.TextureRectangle;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.TextureImage.MipmapDirtyRegion;
-import com.ferox.resource.TextureRectangle.TextureRectangleDirtyDescriptor;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.TextureRectangle;
+import com.ferox.resource.texture.TextureImage.MipmapDirtyRegion;
+import com.ferox.resource.texture.TextureRectangle.TextureRectangleDirtyDescriptor;
 
 /** JoglTextureRectangleResourceDriver provides the functionality to load
  * and delete TextureRectangle instances in the graphics card.

src/com/ferox/renderer/impl/jogl/drivers/JoglVertexArrayGeometryDriver.java

 package com.ferox.renderer.impl.jogl.drivers;
 
 import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
 
 import javax.media.opengl.GL;
 
 import com.ferox.renderer.impl.jogl.drivers.BufferedGeometryDriver.BufferedGeometryHandle;
 import com.ferox.renderer.impl.jogl.drivers.BufferedGeometryDriver.PointerType;
 import com.ferox.renderer.impl.jogl.record.VertexArrayRecord;
+import com.ferox.resource.BufferData;
 import com.ferox.resource.Geometry;
 import com.ferox.resource.Resource;
-import com.ferox.resource.VertexArray;
-import com.ferox.resource.VertexArrayGeometry;
 import com.ferox.resource.BufferData.DataType;
-import com.ferox.resource.BufferedGeometry.GeometryArray;
 import com.ferox.resource.Resource.Status;
+import com.ferox.resource.geometry.VertexArray;
+import com.ferox.resource.geometry.VertexArrayGeometry;
+import com.ferox.resource.geometry.BufferedGeometry.GeometryArray;
+import com.sun.opengl.util.BufferUtil;
 
 /** JoglVertexArrayGeometryDriver handles the rendering of VertexArrayGeometries.
  * It is somewhat liberal in its assumptions about the state record.  To be
  * efficient, it assumes that no state driver modifies the VertexArrayRecord 
  * and that other geometry drivers properly reset the state that they've modified.
  * 
+ * This maintains a mapping of BufferDatas to the native, direct buffers used
+ * in the actual opengl calls.  When no BufferData references the Buffer anymore,
+ * the references are cleared.
+ * 
  * @author Michael Ludwig
  *
  */
 public class JoglVertexArrayGeometryDriver implements GeometryDriver {
+	/* Class used to keep track of Buffers and the geometries that use them. */
+	private static class BufferMap {
+		Buffer buffer; // must be direct, with native byte ordering
+		Set<VertexArrayGeometry> references;
+		
+		public BufferMap(Buffer data) {
+			this.buffer = data;
+			this.references = new HashSet<VertexArrayGeometry>();
+		}
+	}
+	
 	private JoglSurfaceFactory factory;
-	private BufferedGeometryDriver<Buffer, VertexArrayGeometry> geomDriver;
+	private BufferedGeometryDriver<BufferData, VertexArrayGeometry> geomDriver;
+	private Map<BufferData, BufferMap> bufferMap;
 	
 	private int maxTextureUnits;
 	private int maxVertexAttribs;
 	
-	private BufferedGeometryHandle<Buffer> lastRendered;
+	private BufferedGeometryHandle<BufferData> lastRendered;
 	
 	public JoglVertexArrayGeometryDriver(JoglSurfaceFactory factory) {
 		this.factory = factory;
-		this.geomDriver = new BufferedGeometryDriver<Buffer, VertexArrayGeometry>();
+		this.geomDriver = new BufferedGeometryDriver<BufferData, VertexArrayGeometry>();
+		this.bufferMap = new HashMap<BufferData, BufferMap>();
 		
 		this.maxTextureUnits = factory.getRenderer().getCapabilities().getMaxTextureCoordinates();
 		this.maxVertexAttribs = factory.getRenderer().getCapabilities().getMaxVertexAttributes();
 	@SuppressWarnings("unchecked")
 	public int render(Geometry geom, ResourceData data) {
 		GL gl = this.factory.getGL();
-		VertexArrayRecord vr = this.factory.getRecord().vertexArrayRecord;
-		
-		BufferedGeometryHandle<Buffer> toRender = (BufferedGeometryHandle<Buffer>) data.getHandle();
+		VertexArrayRecord vr = this.factory.getRecord().vertexArrayRecord;		
+		BufferedGeometryHandle<BufferData> toRender = (BufferedGeometryHandle<BufferData>) data.getHandle();
 
 		if (toRender != this.lastRendered) {
 			// disable unused pointers
 			if (this.lastRendered != null)
-				disablePointers(gl, vr, this.lastRendered, toRender);
+				this.disablePointers(gl, vr, this.lastRendered, toRender);
 			
 			// update the vertex pointers to match this geometry
 			if (toRender.glInterleavedType < 0)
-				setVertexPointers(gl, vr, toRender);
+				this.setVertexPointers(gl, vr, toRender);
 			else
-				setInterleavedArray(gl, vr, toRender);
+				this.setInterleavedArray(gl, vr, toRender);
 			this.lastRendered = toRender;
 		}
 		
 		// render the geometry
-		GeometryArray<Buffer> indices = toRender.indices;
-		Buffer bd = indices.getArray();
+		GeometryArray<BufferData> indices = toRender.indices;
+		Buffer bd = this.getBuffer(indices.getArray());
 		bd.position(indices.getAccessor().getOffset());
-		bd.limit(bd.capacity());
+		bd.limit(bd.position() + indices.getElementCount());
 		gl.glDrawRangeElements(toRender.glPolyType, 0, toRender.vertexCount, indices.getElementCount(), 
-							   EnumUtil.getGLType(indices.getEffectiveType()), indices.getArray().clear());
+							   EnumUtil.getGLType(indices.getType()), bd);
 		
 		return toRender.polyCount;
 	}
 	}
 
 	@Override
+	@SuppressWarnings("unchecked")
 	public void cleanUp(Resource resource, ResourceData data) {
-		// do nothing -> no cleanUp necessary
+		// cleanup the Buffer mappings for this resource
+		BufferedGeometryHandle<BufferData> handle = (BufferedGeometryHandle<BufferData>) data.getHandle();
+		
+		int count = handle.compiledPointers.size();
+		BufferMap bm;
+		BufferData bd;
+		for (int i = 0; i < count; i++) {
+			bd = handle.compiledPointers.get(i).array.getArray();
+			bm = this.bufferMap.get(bd);
+			if (bm != null && bm.references.contains(resource)) {
+				bm.references.remove(resource);
+				if (bm.references.size() == 0) {
+					// no more references left, so remove it
+					this.bufferMap.remove(bd);
+				}
+			}
+		}
+		
+		// do indices now
+		bd = handle.indices.getArray();
+		bm = this.bufferMap.get(bd);
+		if (bm != null && bm.references.contains(resource)) {
+			bm.references.remove(resource);
+			if (bm.references.size() == 0) {
+				this.bufferMap.remove(bd);
+			}
+		}
 	}
 
 	@Override
 	@SuppressWarnings("unchecked")
 	public void update(Resource resource, ResourceData data, boolean fullUpdate) {
-		BufferedGeometryHandle<Buffer> handle = (BufferedGeometryHandle<Buffer>) data.getHandle();
-		handle = this.geomDriver.updateHandle((VertexArrayGeometry) resource, handle, this.maxTextureUnits, this.maxVertexAttribs);
+		VertexArrayGeometry geom = (VertexArrayGeometry) resource;
+		BufferedGeometryHandle<BufferData> handle = (BufferedGeometryHandle<BufferData>) data.getHandle();
+		handle = this.geomDriver.updateHandle(geom, handle, this.maxTextureUnits, this.maxVertexAttribs);
 		data.setHandle(handle);
 		
 		if (!this.geomDriver.getElementCountsValid(handle)) {
 		} else {
 			data.setStatus(Status.OK);
 			data.setStatusMessage("");
+			
+			// make sure bufferMap is up-to-date
+			BufferMap bm;
+			BufferData bd;
+			Set<BufferData> usedKeys = new HashSet<BufferData>();
+			int count = handle.compiledPointers.size();
+			for (int i = 0; i < count; i++) {
+				bd = handle.compiledPointers.get(i).array.getArray();
+				bm = this.bufferMap.get(bd);
+				if (this.updateBufferDataEntry(bd, bm, geom, data))
+					usedKeys.add(bd);
+			}
+			// now do indices
+			bd = handle.indices.getArray();
+			if (this.updateBufferDataEntry(bd, this.bufferMap.get(bd), geom, data))
+				usedKeys.add(bd);
+			
+			// clean-up Buffers no longer used by this geometry,
+			// correctly handles indices
+			List<BufferData> toRemove = new ArrayList<BufferData>();
+			for (Entry<BufferData, BufferMap> entry: this.bufferMap.entrySet()) {
+				bd = entry.getKey();
+				bm = entry.getValue();
+				if (!usedKeys.contains(bd)) {
+					bm.references.remove(resource);
+					if (bm.references.size() == 0) {
+						// no more references left, so remove it
+						toRemove.add(bd);
+					}
+				}
+			}
+			// must do this in a separate list, to prevent concurrent modifications above
+			for (BufferData tr: toRemove)
+				this.bufferMap.remove(tr);
 		}
 		
 		// not really necessary, but just in case
 		resource.clearDirtyDescriptor();
 	}
 	
+	private boolean updateBufferDataEntry(BufferData bd, BufferMap bm, VertexArrayGeometry geom, ResourceData data) {
+		if (bd.getData() == null) {
+			// error check
+			data.setStatus(Status.ERROR);
+			data.setStatusMessage("Cannot update a VertexArrayGeometry that uses a BufferData with a null array");
+			
+			return false;
+		} else {
+			if (bm == null) {
+				// need a new Buffer
+				bm = new BufferMap(wrap(bd));
+				bm.references.add(geom);
+				this.bufferMap.put(bd, bm);
+			} else {
+				// refill the Buffer
+				fill(bm.buffer, bd);
+			}
+			
+			return true;
+		}
+	}
+	
+	// Must only be called if the VertexArrayGeometry has been updated
+	// otherwise there might not be an associated key.
+	private Buffer getBuffer(BufferData data) {
+		return this.bufferMap.get(data).buffer;
+	}
+	
 	/* Disable all client vertex arrays that were in use by lastUsed that will not be used by
 	 * next.  If next is null, then no client arrays are used by next. */
-	private static void disablePointers(GL gl, VertexArrayRecord vr, BufferedGeometryHandle<Buffer> lastUsed, BufferedGeometryHandle<Buffer> next) {
-		ArrayPointer<Buffer> ap;
+	private void disablePointers(GL gl, VertexArrayRecord vr, BufferedGeometryHandle<BufferData> lastUsed, BufferedGeometryHandle<BufferData> next) {
+		ArrayPointer<BufferData> ap;
 		int count = lastUsed.compiledPointers.size();
 		for (int i = 0; i < count; i++) {
 			ap = lastUsed.compiledPointers.get(i);
 	 * one of the formats chosen by BufferedGeometryDriver.  It correctly sets the client active texture
 	 * and updates the vr record to have the correct pointers enabled.  It doesn't flag anything as
 	 * disabled, since this should have been done before a call to this method. */
-	private static void setInterleavedArray(GL gl, VertexArrayRecord vr, BufferedGeometryHandle<Buffer> toRender) {
+	private void setInterleavedArray(GL gl, VertexArrayRecord vr, BufferedGeometryHandle<BufferData> toRender) {
 		int texUnit = -1; // will be >= 0 if a tex coord is present
 		
 		// search for the texture unit in use by the interleaved array
-		ArrayPointer<Buffer> ap;
+		ArrayPointer<BufferData> ap;
 		int count = toRender.compiledPointers.size();
 		// this loop is short, will be at most 3 iterations (T2F_N3F_V3F has 3 compiled buffers).
 		for (int i = 0; i < count; i++) {
 			vr.enableTexCoordArrays[texUnit] = toRender.glInterleavedType != GL.GL_N3F_V3F;
 		}
 		
-		Buffer interleaved = toRender.compiledPointers.get(0).array.getArray().clear();
+		Buffer interleaved = this.getBuffer(toRender.compiledPointers.get(0).array.getArray()).clear();
 		gl.glInterleavedArrays(toRender.glInterleavedType, 0, interleaved);
 	}
 	
 	/* Enable and set the client array pointers based on the given handle.  It is
 	 * assumed that it is not null, and that any unused pointers will be disabled
 	 * elsewhere. */
-	private static void setVertexPointers(GL gl, VertexArrayRecord vr, BufferedGeometryHandle<Buffer> toRender) {
-		ArrayPointer<Buffer> ap;
+	private void setVertexPointers(GL gl, VertexArrayRecord vr, BufferedGeometryHandle<BufferData> toRender) {
+		ArrayPointer<BufferData> ap;
 		
 		VertexArray va;
 		DataType type;
 		for (int i = 0; i < count; i++) {
 			ap = toRender.compiledPointers.get(i);
 			
-			type = ap.array.getEffectiveType();
-			binding = ap.array.getArray();
+			type = ap.array.getType();
+			binding = this.getBuffer(ap.array.getArray());
 			
 			va = ap.array.getAccessor();
 			byteStride = va.getStride() * type.getByteSize();
 			}
 		}
 	}
+	
+	/* Return a nio buffer wrapping bd's array, can't be null. */
+	private static Buffer wrap(BufferData bd) {
+		switch(bd.getType()) {
+		case BYTE: case UNSIGNED_BYTE: {
+			byte[] array = (byte[]) bd.getData();
+			ByteBuffer buffer = BufferUtil.newByteBuffer(array.length);
+			buffer.put(array);
+			return buffer; }
+		case INT: case UNSIGNED_INT: {
+			int[] array = (int[]) bd.getData();
+			IntBuffer buffer = BufferUtil.newIntBuffer(array.length);
+			buffer.put(array);
+			return buffer; }
+		case SHORT: case UNSIGNED_SHORT: {
+			short[] array = (short[]) bd.getData();
+			ShortBuffer buffer = BufferUtil.newShortBuffer(array.length);
+			buffer.put(array);
+			return buffer; }
+		case FLOAT: {
+			float[] array = (float[]) bd.getData();
+			FloatBuffer buffer = BufferUtil.newFloatBuffer(array.length);
+			buffer.put(array);
+			return buffer; }
+		}
+		
+		// shouldn't happen
+		return null;
+	}
+	
+	/* Fill an existing array with the given BufferData, can't be null. */
+	private static void fill(Buffer nioBuff, BufferData bd) {
+		switch(bd.getType()) {
+		case BYTE: case UNSIGNED_BYTE: {
+			byte[] array = (byte[]) bd.getData();
+			ByteBuffer buffer = (ByteBuffer) nioBuff.clear();
+			buffer.put(array); }
+		case INT: case UNSIGNED_INT: {
+			int[] array = (int[]) bd.getData();
+			IntBuffer buffer = (IntBuffer) nioBuff.clear();
+			buffer.put(array); }
+		case SHORT: case UNSIGNED_SHORT: {
+			short[] array = (short[]) bd.getData();
+			ShortBuffer buffer = (ShortBuffer) nioBuff.clear();
+			buffer.put(array); }
+		case FLOAT: {
+			float[] array = (float[]) bd.getData();
+			FloatBuffer buffer = (FloatBuffer) nioBuff.clear();
+			buffer.put(array); }
+		}
+	}
 }

src/com/ferox/renderer/impl/jogl/drivers/JoglVertexBufferGeometryDriver.java

 import com.ferox.renderer.impl.jogl.record.VertexArrayRecord;
 import com.ferox.resource.Geometry;
 import com.ferox.resource.Resource;
-import com.ferox.resource.VertexArray;
-import com.ferox.resource.VertexBufferGeometry;
-import com.ferox.resource.VertexBufferObject;
 import com.ferox.resource.BufferData.DataType;
-import com.ferox.resource.BufferedGeometry.GeometryArray;
 import com.ferox.resource.Resource.Status;
+import com.ferox.resource.geometry.VertexArray;
+import com.ferox.resource.geometry.VertexBufferGeometry;
+import com.ferox.resource.geometry.VertexBufferObject;
+import com.ferox.resource.geometry.BufferedGeometry.GeometryArray;
 
 /** JoglVertexBufferGeometryDriver handles the rendering of VertexBufferGeometries.
  * It is somewhat liberal in its assumptions about the state record.  To be
 				gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, vr.elementBufferBinding);
 			}
 			
-			DataType type = indices.getEffectiveType();
+			DataType type = indices.getType();
 			int byteOffset = indices.getAccessor().getOffset() * type.getByteSize();
 			gl.glDrawRangeElements(toRender.glPolyType, 0, toRender.vertexCount, indices.getElementCount(), 
 							       EnumUtil.getGLType(type), byteOffset);
 			if (vbo == null)
 				return false; // abort
 			
-			type = ap.array.getEffectiveType();
+			type = ap.array.getType();
 			
 			va = ap.array.getAccessor();
 			byteStride = va.getStride() * type.getByteSize();

src/com/ferox/renderer/impl/jogl/drivers/JoglVertexBufferObjectResourceDriver.java

 import com.ferox.renderer.impl.jogl.record.VertexArrayRecord;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Resource;
-import com.ferox.resource.VertexBufferObject;
 import com.ferox.resource.BufferData.DataType;
 import com.ferox.resource.Resource.Status;
-import com.ferox.resource.VertexBufferObject.VboDirtyDescriptor;
+import com.ferox.resource.geometry.VertexBufferObject;
+import com.ferox.resource.geometry.VertexBufferObject.VboDirtyDescriptor;
 
 /** JoglVertexBufferObjectResourceDriver implements the necessary opengl
  * operations to allocate, update and clean-up vbos on the graphics card.

src/com/ferox/renderer/impl/jogl/drivers/TextureHandle.java

 
 import com.ferox.renderer.impl.ResourceData.Handle;
 import com.ferox.renderer.impl.jogl.EnumUtil;
-import com.ferox.resource.TextureImage.DepthMode;
-import com.ferox.resource.TextureImage.Filter;
-import com.ferox.resource.TextureImage.TextureWrap;
+import com.ferox.resource.texture.TextureImage.DepthMode;
+import com.ferox.resource.texture.TextureImage.Filter;
+import com.ferox.resource.texture.TextureImage.TextureWrap;
 import com.ferox.state.State.PixelTest;
 
 /** All ResourceDrivers for any of the TextureImage subclasses must use 

src/com/ferox/renderer/impl/jogl/drivers/TextureImageDriver.java

 import com.ferox.renderer.impl.jogl.EnumUtil;
 import com.ferox.renderer.impl.jogl.record.PackUnpackRecord;
 import com.ferox.resource.BufferData;
-import com.ferox.resource.TextureFormat;
-import com.ferox.resource.TextureImage;
-import com.ferox.resource.TextureImage.TextureDirtyDescriptor;
+import com.ferox.resource.texture.TextureFormat;
+import com.ferox.resource.texture.TextureImage;
+import com.ferox.resource.texture.TextureImage.TextureDirtyDescriptor;
 
 /** TextureImageDriver is a class that provides common functionality
  * and utilities that will be useful to any TextureImage driver (of any target type).

src/com/ferox/resource/BufferedGeometry.java

-package com.ferox.resource;
-
-import java.util.List;
-
-import com.ferox.math.AxisAlignedBox;
-import com.ferox.math.BoundSphere;
-import com.ferox.math.BoundVolume;
-import com.ferox.math.Boundable;
-import com.ferox.resource.BufferData.DataType;
-import com.ferox.resource.UnitList.Unit;
-
-/** BufferedGeometry represents the abstract class for geometry that
- * can be represented as blocks/buffers of primitive data, accessed
- * by an array of indices.  This is then interpreted into polygons based
- * on the polygon type of the BufferedGeometry.
- * 
- * None of the methods validate the number of elements in each buffer.
- * This is because if they're are adjusted in odd orders, it may be temporarily
- * broken.  It is the renderer's duty to make sure that the element counts
- * match and set a status of ERROR when updated if they don't.
- * 
- * It is theoretically possible to arrange the bound data and VertexArray's
- * so that its components are all in the same data object with different
- * offsets and strides.  In many simple cases of this, the renderer can
- * provide even more efficient rendering.
- * 
- * BufferedGeometry doesn't use a dirty descriptor by default.
- * 
- * When a buffer is set/bound, a new GeometryArray is created instead of
- * modifying the original array.  This allows the renderer to more easily
- * remember the state of the Geometry when it was updated.
- * 
- * @author Michael Ludwig
- *
- */
-public abstract class BufferedGeometry<T> implements Geometry {
-	/** Represents how consecutive elements in the geometry's
-	 * indices form polygons. */
-	public static enum PolygonType {
-		POINTS, LINES, TRIANGLES, QUADS, TRIANGLE_STRIP, QUAD_STRIP;
-		
-		/** Compute the number of polygons, based on the input
-		 * vertices.  This assumes that numVertices > 0. */
-		public int getPolygonCount(int numVertices) {
-			switch(this) {
-			case POINTS: return numVertices;
-			case LINES: return numVertices >> 1;
-			case TRIANGLES: return numVertices / 3;
-			case QUADS: return numVertices >> 2;
-			
-			case TRIANGLE_STRIP: return numVertices - 2;
-			case QUAD_STRIP: return (numVertices - 2) >> 1;
-			}
-			
-			return -1;
-		}
-	}
-
-	/** Store the intersection of a T and its accessing VertexArray,
-	 * as well some metadata to make it easier to analyze a BufferedGeometry
-	 * without knowing the type T. */
-	public static class GeometryArray<T> {
-		private T data;
-		private DataType type;
-		private VertexArray accessor;
-		private int elementCount;
-		
-		private GeometryArray(T data, DataType type, VertexArray accessor, int elementCount) {
-			this.data = data;
-			this.accessor = accessor;
-			this.type = type;
-			this.elementCount = elementCount;
-		}
-		
-		/** Return the geometry data array. This will not be null. */
-		public T getArray() {
-			return this.data;
-		}
-		
-		/** Return the VertexArray accessor into the data array.
-		 * This will not be null. */
-		public VertexArray getAccessor() {
-			return this.accessor;
-		}
-		
-		/** Return the "effective" type of the data represented
-		 * in the array of this GeometryArray. */
-		public DataType getEffectiveType() {
-			return this.type;
-		}
-		
-		/** Return the number of elements present in the
-		 * array, based off of its accessor. */
-		public int getElementCount() {
-			return this.elementCount;
-		}
-	}
-	
-	private BoundSphere sphereCache;
-	private AxisAlignedBox axisCache;
-	
-	private GeometryArray<T> vertices;
-	private GeometryArray<T> normals;
-	private GeometryArray<T> fogCoords;
-	
-	private UnitList<GeometryArray<T>> texCoords;
-	private UnitList<GeometryArray<T>> vertexAttribs;
-	
-	private GeometryArray<T> indices;
-	private PolygonType type;
-	
-	// cached counts
-	private int polyCount;
-	
-	private Object resourceData;
-
-	/** Construct a BufferedGeometry with the given vertices and indices.
-	 * The constructor requires the vertices and indices because a BufferedGeometry
-	 * is not allowed to have null vertices or indices.  The same rules
-	 * apply as in setVertices() and setIndices().
-	 * 
-	 * Any other geometry data must be set after construction time. */
-	public BufferedGeometry(T vertices, VertexArray vertAccessor, T indices, VertexArray indexAccessor, PolygonType type) {
-		this.texCoords = new UnitList<GeometryArray<T>>();
-		this.vertexAttribs = new UnitList<GeometryArray<T>>();
-		
-		this.setVertices(vertices, vertAccessor);
-		this.setIndices(indices, indexAccessor, type);
-	}
-	
-	/*
-	 * Vertices: must not be null, must have an element size of 2, 3, or 4
-	 * Type of FLOAT, INT, or SHORT
-	 */
-	
-	/** Get the GeometryArray that holds the vertex information, and
-	 * how to access it for this Geometry. */
-	public GeometryArray<T> getVertices() {
-		return this.vertices;
-	}
-	
-	/** Set the vertex data and its accessor on this Geometry.  The following
-	 * rules must be met:
-	 * 1. vertices and accessor cannot be null
-	 * 2. accessor must have an element size of 2, 3, or 4
-	 * 3. vertices' effective type must be FLOAT, INT, or SHORT
-	 * 
-	 * If the element size is 4, the fourth coordinate represents
-	 * the homogenous coordinate of all vertices.  Each other component
-	 * will be divided by it, before making the final vertex value.
-	 * It should never have a value of 0.
-	 * 
-	 * This method invokes clearBoundsCache().
-	 * 
-	 * If these rules aren't met, then an exception is thrown. */
-	public void setVertices(T vertices, VertexArray accessor) throws NullPointerException, IllegalArgumentException {
-		if (vertices == null)
-			throw new NullPointerException("Cannot have have a BufferedGeometry with a null vertices");
-		if (accessor == null)
-			throw new NullPointerException("Must specify a non-null VertexArray accessor");
-		
-		DataType type = this.getEffectiveDataType(vertices, false);
-		if (type != DataType.FLOAT && type != DataType.INT && type != DataType.SHORT)
-			throw new IllegalArgumentException("Invalid type for vertices, expected an effective type of FLOAT, INT, or SHORT; not " + type);
-		if (accessor.getElementSize() != 2 && accessor.getElementSize() != 3 && accessor.getElementSize() != 4)
-			throw new IllegalArgumentException("VertexArray can only have element sizes of 2, 3, or 4; not: " + accessor.getElementSize());
-		
-		this.vertices = new GeometryArray<T>(vertices, type, accessor, this.getNumElements(vertices, accessor));
-		this.clearBoundsCache();
-	}
-	
-	/*
-	 * Normals: can be null, must have an element size of 3
-	 * Type of FLOAT, INT, SHORT, BYTE
-	 */
-	
-	/** Get the GeometryArray that holds the normal information, and
-	 * how to access it for this Geometry. 
-	 * 
-	 * If null is returned, it means that this geometry has no normal
-	 * information specified. */
-	public GeometryArray<T> getNormals() {
-		return this.normals;
-	}
-	
-	/** Set the normal data and its accessor on this Geometry.  The following
-	 * rules must be met if normals is not null:
-	 * 1. accessor can't be null
-	 * 2. accessor must have an element size of 3
-	 * 3. normal's effective type must be FLOAT, INT, SHORT, or BYTE
-	 * 
-	 * If normals is null, then accessor is ignored and any previous normal data
-	 * is discarded.
-	 * 
-	 * It is is assumed that the normals have already been normalized.  Undefined
-	 * results occur if not (likely it will be odd lighting effects).
-	 * 
-	 * If these rules aren't met, then an exception is thrown. */
-	public void setNormals(T normals, VertexArray accessor) throws NullPointerException, IllegalArgumentException {
-		if (normals != null) {
-			if (accessor == null)
-				throw new NullPointerException("accessor must be non-null if normals isn't null");
-
-			DataType type = this.getEffectiveDataType(normals, false);
-			if (type != DataType.FLOAT && type != DataType.INT && type != DataType.SHORT && type != DataType.BYTE)
-				throw new IllegalArgumentException("Invalid type for vertices, expected an effective type of FLOAT, INT, SHORT or BYTE; not " + type);
-			if (accessor.getElementSize() != 3)
-				throw new IllegalArgumentException("VertexArray can only have an element size of 3; not: " + accessor.getElementSize());
-			
-			this.normals = new GeometryArray<T>(normals, type, accessor, this.getNumElements(normals, accessor));
-		} else
-			this.normals = null;
-	}
-	
-	/*
-	 * Fog coordinates: can be null, must have an element size of 1
-	 * Type must be FLOAT
-	 */
-	
-	/** Get the GeometryArray that holds the fog coordinate information, and
-	 * how to access it for this Geometry. 
-	 * 
-	 * If null is returned, it means that this geometry has no fog coordinate
-	 * information specified. */
-	public GeometryArray<T> getFogCoordinates() {
-		return this.fogCoords;
-	}
-	
-	/** Set the fog coordinate data and its accessor on this Geometry.  The following
-	 * rules must be met if fog is not null:
-	 * 1. accessor can't be null
-	 * 2. accessor must have an element size of 1
-	 * 3. fog's effective type must be FLOAT
-	 * 
-	 * If fog is null, then accessor is ignored and any previous normal data
-	 * is discarded.
-	 * 
-	 * For fog coordinates to have any effect, the fog depth source must be
-	 * set to FOG_COORDINATE in the active FogReceiver.  If its FRAGMENT_DEPTH,
-	 * it will behave as if fog coordinates were null.  It is undefined what happens
-	 * if the Geometry has no fog coordinates, and the depth source is FOG_COORDINATE.
-	 * 
-	 * It is is assumed that the normals have already been normalized.  Undefined
-	 * results occur if not (likely it will be odd lighting effects).
-	 * 
-	 * If these rules aren't met, then an exception is thrown. */
-	public void setFogCoordinates(T fog, VertexArray accessor) throws NullPointerException, IllegalArgumentException {
-		if (fog != null) {
-			if (accessor == null)
-				throw new NullPointerException("accessor must be non-null if fog isn't null");
-
-			DataType type = this.getEffectiveDataType(fog, false);
-			if (type != DataType.FLOAT)
-				throw new IllegalArgumentException("Invalid type for vertices, expected an effective type of FLOAT; not " + type);
-			if (accessor.getElementSize() != 1)
-				throw new IllegalArgumentException("VertexArray can only have an element size of 1; not: " + accessor.getElementSize());
-			
-			this.fogCoords = new GeometryArray<T>(fog, type, accessor, this.getNumElements(fog, accessor));
-		} else
-			this.fogCoords = null;
-	}
-	
-	/*
-	 * Texture coordinates: can be null, must have an element size of 1, 2, 3, or 4
-	 * Unit must be >= 0. Type of FLOAT, INT, or SHORT.
-	 */
-	
-	/** Get the GeometryArray that holds texture coordinate data for
-	 * the given texture unit.  This unit matches the units in a MultiTexture.
-	 * 
-	 * If null is returned, then there are no texture coordinates for the given
-	 * unit.  
-	 * 
-	 * Throws an exception if unit is < 0. */
-	public GeometryArray<T> getTextureCoordinates(int unit) throws IllegalArgumentException {
-		return this.texCoords.getItem(unit);
-	}
-	
-	/** Return a list of all bound texture coordinates and the units that they
-	 * are bound to.  This will not be null.  If no texture coordinates are bound,
-	 * an empty list is returned. 
-	 * 
-	 * The returned list is immutable. */
-	public List<Unit<GeometryArray<T>>> getTextureCoordinates() {
-		return this.texCoords.getItems();
-	}
-	
-	/** Set the texture coordinate data and its accessor on this Geometry for
-	 * the given texture unit.  The following rules must be met if tcs is not null:
-	 * 1. accessor can't be null
-	 * 2. accessor must have an element size of 1, 2, or 3
-	 * 3. normal's effective type must be FLOAT, INT, or SHORT
-	 * 
-	 * If tcs is null, then accessor is ignored and any previous texture data
-	 * is discarded for the given unit.
-	 * 
-	 * There is a maximum supported unit, depending on the hardware.  If a coordinate
-	 * unit is set that is above that unit, it will be ignored.
-	 * 
-	 * If these rules aren't met, then an exception is thrown. 
-	 * Also, if unit is < 0, then an exception is thrown. */
-	public void setTextureCoordinates(int unit, T tcs, VertexArray accessor) throws NullPointerException, IllegalArgumentException {
-		if (tcs != null) {
-			if (accessor == null)
-				throw new NullPointerException("accessor must be non-null if tcs isn't null");
-			
-			DataType type = this.getEffectiveDataType(tcs, false);
-			if (type != DataType.FLOAT && type != DataType.INT && type != DataType.SHORT)
-				throw new IllegalArgumentException("Invalid type for vertices, expected an effective type of FLOAT, INT, or SHORT; not " + type);
-			if (accessor.getElementSize() != 1 && accessor.getElementSize() != 2 && accessor.getElementSize() != 3)
-				throw new IllegalArgumentException("VertexArray can only have an element size of 1, 2, or 3; not: " + accessor.getElementSize());
-
-			this.texCoords.setItem(unit, new GeometryArray<T>(tcs, type, accessor, this.getNumElements(tcs, accessor)));
-		} else {
-			this.texCoords.setItem(unit, null);
-		}
-	}
-	
-	/*
-	 * Vertex attributes: can be null, must have an element size of 1, 2, 3, or 4
-	 * Unit must be >= 0.
-	 */
-	
-	/** Get the GeometryArray that holds vertex attribute data for
-	 * the given vertex attribute.  This unit matches the units of any active
-	 * glsl attributes.
-	 * 
-	 * If null is returned, then there are no vertex attribtues for the given
-	 * unit.  
-	 * 
-	 * Throws an exception if unit is < 0. */
-	public GeometryArray<T> getVertexAttributes(int unit) throws IllegalArgumentException {
-		return this.vertexAttribs.getItem(unit);
-	}
-	
-	/** Return a list of all bound vertex attributes and the units that they
-	 * are bound to.  This will not be null.  If no vertex attributes are bound,
-	 * an empty list is returned. 
-	 * 
-	 * The returned list is immutable. */
-	public List<Unit<GeometryArray<T>>> getVertexAttributes() {
-		return this.vertexAttribs.getItems();
-	}
-	
-	/** Set the vertex attribute data and its accessor on this Geometry for
-	 * the given unit.  The following rules must be met if vas is not null:
-	 * 1. accessor can't be null
-	 * 2. accessor must have an element size of 1, 2, 3 or 4
-	 * 
-	 * If vas is null, then accessor is ignored and any previous vertex attribute data
-	 * is discarded for the given unit.
-	 * 
-	 * There is a maximum supported unit, depending on the hardware.  If a coordinate
-	 * unit is set that is above that unit, it will be ignored.
-	 * 
-	 * Matrices can be loaded into shader attributes, too.  An attribute slot corresponds
-	 * to a column of the matrix.  The matrix is loaded in column-major order, and columns
-	 * must be in consecutive units.
-	 * 
-	 * If these rules aren't met, then an exception is thrown. 
-	 * Also, if unit is < 0, then an exception is thrown. */
-	public void setVertexAttributes(int unit, T vas, VertexArray accessor) throws NullPointerException, IllegalArgumentException {
-		if (vas != null) {
-			if (accessor == null)
-				throw new NullPointerException("accessor must be non-null if vas isn't null");
-			
-			if (accessor.getElementSize() != 1 && accessor.getElementSize() != 2 && accessor.getElementSize() != 3 && accessor.getElementSize() != 4)
-				throw new IllegalArgumentException("VertexArray can only have an element size of 1, 2, 3, or 4; not: " + accessor.getElementSize());
-
-			this.vertexAttribs.setItem(unit, new GeometryArray<T>(vas, this.getEffectiveDataType(vas, false), accessor, this.getNumElements(vas, accessor)));
-		} else {
-			this.vertexAttribs.setItem(unit, null);
-		}
-	}
-	
-	/*
-	 * Indices: must not be null, must have an element size of 1, 
-	 * Type must be one of UNSIGNED_xyz.
-	 */
-	
-	/** Get the GeometryArray that holds the index information, and
-	 * how to access it for this Geometry. */
-	public GeometryArray<T> getIndices() {
-		return this.indices;
-	}
-	
-	/** Set the index data and its accessor on this Geometry.  The following
-	 * rules must be met:
-	 * 1. indices and accessor can't be null
-	 * 2. accessor must have an element size of 1 and a stride of 0
-	 * 3. indices's effective type must be UNSIGNED_INT, UNSIGNED_SHORT, or UNSIGNED_BYTE
-	 * 4. polyType cannot be null
-	 * 
-	 * If these rules aren't met, then an exception is thrown. */
-	public void setIndices(T indices, VertexArray accessor, PolygonType polyType) throws NullPointerException, IllegalArgumentException {
-		if (indices == null)
-			throw new NullPointerException("Cannot have have a BufferedGeometry with a null indices");
-		if (accessor == null)
-			throw new NullPointerException("Must specify a non-null VertexArray accessor");
-		if (polyType == null)
-			throw new NullPointerException("Must specify a non-null polygon type");
-		
-		DataType type = this.getEffectiveDataType(indices, true);
-		if (type != DataType.UNSIGNED_INT && type != DataType.UNSIGNED_SHORT && type != DataType.UNSIGNED_BYTE)
-			throw new IllegalArgumentException("Invalid type for vertices, expected an effective type of UNSIGNED_INT, UNSIGNED_SHORT, or UNSIGNED_BYTE; not " + type);
-		if (accessor.getElementSize() != 1)
-			throw new IllegalArgumentException("VertexArray can only have an element size of 1; not: " + accessor.getElementSize());
-		if (accessor.getStride() != 0)
-			throw new IllegalArgumentException("VertexArray must have a stride of 0; not: " + accessor.getStride());
-		
-		this.indices = new GeometryArray<T>(indices, type, accessor, this.getNumElements(indices, accessor));
-		this.type = polyType;
-		this.polyCount = polyType.getPolygonCount(this.indices.getElementCount());
-	}
-	
-	/*
-	 * Misc methods
-	 */
-	
-	/** Return the PolygonType for this BufferedGeometry. */
-	public PolygonType getPolygonType() {
-		return this.type;
-	}
-	
-	/** Return the number of polygons that are present in this BufferedGeometry. */
-	public int getPolygonCount() {
-		return this.polyCount;
-	}
-	
-	/** Force the bound volume caches to be re-updated,
-	 * possibly before a call to getBounds().  It is recommended
-	 * to call this before prior to clearing the client memory
-	 * for the vertices. */
-	public void computeBoundsCache() {
-		this.axisCache = new AxisAlignedBox();
-		this.axisCache.enclose(this);
-		
-		this.sphereCache = new BoundSphere();
-		this.sphereCache.enclose(this);
-	}
-	
-	/** Clear the cached bounding volumes.  The next time
-	 * getBounds is called with either a AxisAlignedBox,
-	 * or BoundSphere, the cached bounds for that type will
-	 * be re-computed from scratch. */
-	public void clearBoundsCache() {
-		this.axisCache = null;
-		this.sphereCache = null;
-	}
-	
-	/*
-	 * Internal methods for sub-classes
-	 */
-	
-	/** Return the DataType that "matches" the given data instance.  If 
-	 * asIndices is true, then UNSIGNED types are preferred over the signed
-	 * versions.  Return null if there's not an effective matching type. */
-	protected abstract DataType getEffectiveDataType(T data, boolean asIndices);
-	
-	/** Return a floating point value stored at the given index in data.
-	 * If the data doesn't hold a floating value, it should just cast it
-	 * (and not use multiple primitives to create a fp value). 
-	 * 
-	 * It can be assumed that the data is meant for vertices, and thus
-	 * not unsigned. */
-	protected abstract float get(T data, int index);
-	
-	/** Return the number of vector elements present in the given data,
-	 * if were accessed by the given VertexArray. */
-	protected abstract int getNumElements(T data, VertexArray accessor);
-	
-	/*
-	 * The implementation of Geometry and Boundable
-	 */
-	
-	@Override
-	public void getBounds(BoundVolume result) {
-		if (result != null) {
-			if (result instanceof AxisAlignedBox) {
-				if (this.axisCache == null) {
-					this.axisCache = new AxisAlignedBox();
-					this.axisCache.enclose(this);
-				}
-				this.axisCache.clone(result);
-			} else if (result instanceof BoundSphere) {
-				if (this.sphereCache == null) {
-					this.sphereCache = new BoundSphere();
-					this.sphereCache.enclose(this);
-				}
-				this.sphereCache.clone(result);
-			} else
-				result.enclose(this);
-		}
-	}
-
-	@Override
-	public float getVertex(int index, int coord) throws IllegalArgumentException {
-		if (index < 0 || index >= this.getVertexCount())
-			throw new IllegalArgumentException("Illegal vertex index: " + index + " must be in [0, " + this.getVertexCount() + "]");
-		if (coord < 0 || coord > 3)
-			throw new IllegalArgumentException("Illegal vertex coordinate: " + coord + " must be in [0, 3]");
-		
-		int vertexSize = this.vertices.accessor.getElementSize();
-		
-		if (coord >= vertexSize) {
-			if (coord == Boundable.Z_COORD)
-				return 0f; // missing z
-			else
-				return 1f; // missing w
-		} else {
-			// coord is present in this geometry, so we can access the value directly
-			return this.get(this.vertices.data, this.vertices.accessor.getIndex(index) + coord);
-		}
-	}
-
-	@Override
-	public int getVertexCount() {
-		return this.vertices.getElementCount();
-	}
-
-	/** Returns null by default. */
-	@Override
-	public Object getDirtyDescriptor() {
-		return null;
-	}
-
-	@Override
-	public void clearDirtyDescriptor() {
-		// do nothing in base class
-	}
-	
-	@Override
-	public Object getResourceData() {
-		return this.resourceData;
-	}
-
-	@Override
-	public void setResourceData(Object data) {
-		this.resourceData = data;
-	}
-}

src/com/ferox/resource/Geometry.java

  * Geometry provides no additional methods to Boundable 
  * and Resource.
  * 
+ * See com.ferox.resource.geometry package for some basic shapes
+ * and general implementations that should prove sufficient for more
+ * needs.  com.ferox.resource.text also has a useful Geometry implementation.
+ * 
  * @author Michael Ludwig
  *
  */

src/com/ferox/resource/GlslProgram.java

-package com.ferox.resource;
-
-import java.util.BitSet;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.ferox.resource.GlslUniform.UniformType;
-import com.ferox.resource.GlslVertexAttribute.AttributeType;
-
-/** GlslProgram represents a custom shader program written in glsl.
- * The exact shader model and glsl syntax supported depends on the 
- * hardware support for that model.  At the moment only vertex and
- * fragment shaders are allowed.  When geometry shaders become more
- * common, they will likely be added in.
- * 
- * GlslPrograms are a fairly complicated resource for the Renderer
- * to deal with.  Here are a few guidelines:
- * - If either shader fails to compile, it should have a status of ERROR
- * - Overlapping attribute slots cause a status of ERROR.
- * - If it fails to link, it has a status of ERROR.  Uniforms and attributes
- *   are left attached (uniforms status should be changed, though)
- * - If it does link, uniforms and attributes not declared in the code
- *   should be detached and cleaned-up
- * - Attributes and uniforms declared in the glsl code should be bound/attached
- *   on a success if they aren't already attached, when successfully linked.
- *   
- * Care should be given when using the uniforms and attributes attached
- * to a program.  If the program undergoes significant source code change, it
- * is likely that the uniforms will have been detached.  Only attach a Uniform
- * or attribute if you know that they are present in the code (even with compile errors);
- * if not, use the automatically attached uniforms after a successful update.
- * 
- * @author Michael Ludwig
- *
- */
-// FIXME: vertex attributes should start at 1, not 0
-public class GlslProgram implements Resource {
-	/** The dirty descriptor used by instances of GlslProgram. */
-	public static class GlslProgramDirtyDescriptor {
-		private boolean uniformsDirty;
-		private boolean attrsDirty;
-		private boolean glslDirty;
-		
-		/** Return true if a GlslUniform was attached or detached. */
-		public boolean getUniformsDirty() { return this.uniformsDirty; }
-		
-		/** Return true if a GlslVertexAttribute was attached or detached. */
-		public boolean getAttributesDirty() { return this.attrsDirty; }
-		
-		/** Return true if the glsl source code has changed for this program.
-		 * If this is true, then the program's uniforms and attributes should
-		 * be reloaded, too. */
-		public boolean getGlslCodeDirty() { return this.glslDirty; }
-		
-		protected void clear() {
-			this.uniformsDirty = false;
-			this.attrsDirty = false;
-			this.glslDirty = false;
-		}
-	}
-	
-	private String[] vertexShader;
-	private String[] fragmentShader;
-	
-	private final Map<String, GlslUniform> attachedUniforms;
-	private final Map<String, GlslVertexAttribute> boundAttrs;
-	private final BitSet usedAttributeSlots;
-
-	private final Map<String, GlslUniform> readOnlyUniforms;
-	private final Map<String, GlslVertexAttribute> readOnlyAttrs;
-	
-	
-	private final GlslProgramDirtyDescriptor dirty;
-	
-	private Object renderData;
-	
-	/** Create a new GlslProgram with the given vertex and fragment
-	 * shaders.  These string arrays will be passed directly into
-	 * setVertexShader() and setFragmentShader(). */
-	public GlslProgram(String[] vertex, String[] fragment) {
-		this.dirty = this.createDescriptor();
-		if (this.dirty == null)
-			throw new NullPointerException("Sub-class returned a null dirty descriptor");
-		
-		this.attachedUniforms = new HashMap<String, GlslUniform>();
-		this.boundAttrs = new HashMap<String, GlslVertexAttribute>();
-		
-		this.readOnlyUniforms = Collections.unmodifiableMap(this.attachedUniforms);
-		this.readOnlyAttrs = Collections.unmodifiableMap(this.boundAttrs);
-		
-		this.usedAttributeSlots = new BitSet();
-		
-		this.setShaderCode(vertex, fragment);
-	}
-	
-	/** Functions identically to attachUniform() except that it is for GlslVertexAttributes.
-	 * This also fails if the requested attribute cannot fit within the available slots.
-	 * 
-	 * Instead of length, however, bindingSlot is used for the attribute.  See GlslVertexAttribute
-	 * for how the binding slot is used. */
-	public GlslVertexAttribute bindAttribute(String name, AttributeType type, int bindingSlot) throws IllegalStateException, IllegalArgumentException, NullPointerException {
-		if (name == null)
-			throw new NullPointerException("Name cannot be null");
-		
-		GlslVertexAttribute u = this.boundAttrs.get(name);
-		if (u != null)
-			throw new IllegalStateException("Cannot re-bind an attribute with the same name: " + name);
-		else
-			u = new GlslVertexAttribute(name, type, bindingSlot, this); // throws IllegalArgumentException/NullPointerException
-		
-		// check if they're used
-		int maxSlot = bindingSlot + type.getSlotCount();
-		for (int i = bindingSlot; i < maxSlot; i++) {
-			if (this.usedAttributeSlots.get(i))
-				throw new IllegalStateException("Requested attribute does not have enough room at the given slot: " + bindingSlot);
-		}
-		
-		// mark slots as used
-		for (int i = bindingSlot; i < maxSlot; i++)
-			this.usedAttributeSlots.set(i, true);
-		
-		this.boundAttrs.put(name, u);
-		this.dirty.attrsDirty = true;
-		return u;
-	}
-	
-	/** Unbind an attribute so that it is no longer stored by this
-	 * GlslProgram.  After a GlslVertexAttribute is unbound, it
-	 * should no longer be used, since it represents invalid information.
-	 * 
-	 * Because a GlslVertexAttribute is not a resource, and is only 
-	 * a convenient packaging for the binding of glsl attributes, a Renderer
-	 * will unbind any attribute that is invalid (don't unbind if the
-	 * shader doesn't compile, since the attribute may be "valid"). */
-	public GlslVertexAttribute unbindAttribute(String name) {
-		if (name == null)
-			return null;
-		
-		GlslVertexAttribute a = this.boundAttrs.remove(name);
-		if (a != null) {
-			// mark the used slots as unused
-			int maxSlot = a.getBindingSlot() + a.getType().getSlotCount();
-			for (int i = a.getBindingSlot(); i < maxSlot; i++)
-				this.usedAttributeSlots.set(i, false);