OSDN Git Service

Added support for int arrays uniforms. thanks to abies.
authorremy.bouquet@gmail.com <remy.bouquet@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Wed, 20 Mar 2013 17:53:50 +0000 (17:53 +0000)
committerremy.bouquet@gmail.com <remy.bouquet@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Wed, 20 Mar 2013 17:53:50 +0000 (17:53 +0000)
git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@10495 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
engine/src/core/com/jme3/shader/Uniform.java
engine/src/core/com/jme3/shader/VarType.java
engine/src/core/com/jme3/util/BufferUtils.java
engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java

index 6cb1a4a..e3b2a0c 100644 (file)
@@ -643,6 +643,7 @@ public class OGLESShaderRenderer implements Renderer {
 \r
         uniform.clearUpdateNeeded();\r
         FloatBuffer fb;\r
+        IntBuffer ib;\r
         switch (uniform.getVarType()) {\r
             case Float:\r
                 Float f = (Float) uniform.getValue();\r
@@ -683,6 +684,10 @@ public class OGLESShaderRenderer implements Renderer {
                 assert fb.remaining() == 16;\r
                 GLES20.glUniformMatrix4fv(loc, 1, false, fb);\r
                 break;\r
+            case IntArray:\r
+                ib = (IntBuffer) uniform.getValue();\r
+                GLES20.glUniform1iv(loc, ib.limit(), ib);\r
+                break;\r
             case FloatArray:\r
                 fb = (FloatBuffer) uniform.getValue();\r
                 GLES20.glUniform1fv(loc, fb.limit(), fb);\r
index af522d5..077df3c 100644 (file)
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.shader;
-
-import com.jme3.math.*;
-import com.jme3.util.BufferUtils;
-import java.nio.FloatBuffer;
-
-public class Uniform extends ShaderVariable {
-
-    private static final Integer ZERO_INT = Integer.valueOf(0);
-    private static final Float ZERO_FLT = Float.valueOf(0);
-    private static final FloatBuffer ZERO_BUF = BufferUtils.createFloatBuffer(4*4);
-
-    /**
-     * Currently set value of the uniform.
-     */
-    protected Object value = null;
-    
-    /**
-     * For arrays or matrices, efficient format
-     * that can be sent to GL faster.
-     */
-    protected FloatBuffer multiData = null;
-
-    /**
-     * Type of uniform
-     */
-    protected VarType varType;
-
-    /**
-     * Binding to a renderer value, or null if user-defined uniform
-     */
-    protected UniformBinding binding;
-
-    /**
-     * Used to track which uniforms to clear to avoid
-     * values leaking from other materials that use that shader.
-     */
-    protected boolean setByCurrentMaterial = false;
-
-    @Override
-    public String toString(){
-        StringBuilder sb = new StringBuilder();
-        sb.append("Uniform[name=");
-        sb.append(name);
-        if (varType != null){
-            sb.append(", type=");
-            sb.append(varType);
-            sb.append(", value=");
-            sb.append(value);
-        }else{
-            sb.append(", value=<not set>");
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-
-    public void setBinding(UniformBinding binding){
-        this.binding = binding;
-    }
-
-    public UniformBinding getBinding(){
-        return binding;
-    }
-
-    public VarType getVarType() {
-        return varType;
-    }
-
-    public Object getValue(){
-        return value;
-    }
-
-    public boolean isSetByCurrentMaterial() {
-        return setByCurrentMaterial;
-    }
-
-    public void clearSetByCurrentMaterial(){
-        setByCurrentMaterial = false;
-    }
-
-    private static void setVector4(Vector4f vec, Object value) {
-        if (value instanceof ColorRGBA) {
-            ColorRGBA color = (ColorRGBA) value;
-            vec.set(color.r, color.g, color.b, color.a);
-        } else if (value instanceof Quaternion) {
-            Quaternion quat = (Quaternion) value;
-            vec.set(quat.getX(), quat.getY(), quat.getZ(), quat.getW());
-        } else if (value instanceof Vector4f) {
-            Vector4f vec4 = (Vector4f) value;
-            vec.set(vec4);
-        } else{
-            throw new IllegalArgumentException();
-        }
-    }
-    
-    public void clearValue(){
-        updateNeeded = true;
-
-        if (multiData != null){
-            ZERO_BUF.clear();
-            multiData.clear();
-
-            while (multiData.remaining() > 0){
-                ZERO_BUF.limit( Math.min(multiData.remaining(), 16) );
-                multiData.put(ZERO_BUF);
-            }
-
-            multiData.clear();
-
-            return;
-        }
-
-        if (varType == null) {
-            return;
-        }
-            
-        switch (varType){
-            case Int:
-                this.value = ZERO_INT;
-                break;
-            case Boolean:
-                this.value = Boolean.FALSE;
-                break;
-            case Float:
-                this.value = ZERO_FLT; 
-                break;
-            case Vector2:
-                this.value = Vector2f.ZERO;
-                break;
-            case Vector3:
-                this.value = Vector3f.ZERO;
-                break;
-            case Vector4:
-                this.value = Vector4f.ZERO;
-                break;
-            default:
-                // won't happen because those are either textures
-                // or multidata types
-        }
-    }
-    
-    public void setValue(VarType type, Object value){
-        if (location == LOC_NOT_DEFINED) {
-            return;
-        }
-
-        if (varType != null && varType != type) {
-            throw new IllegalArgumentException("Expected a " + varType.name() + " value!");
-        }
-
-        if (value == null) {
-            throw new NullPointerException();
-        }
-
-        setByCurrentMaterial = true;
-
-        switch (type){
-            case Matrix3:
-                Matrix3f m3 = (Matrix3f) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(9);
-                }
-                m3.fillFloatBuffer(multiData, true);
-                multiData.clear();
-                break;
-            case Matrix4:
-                Matrix4f m4 = (Matrix4f) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(16);
-                }
-                m4.fillFloatBuffer(multiData, true);
-                multiData.clear();
-                break;
-            case FloatArray:
-                float[] fa = (float[]) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(fa);
-                } else {
-                    multiData = BufferUtils.ensureLargeEnough(multiData, fa.length);
-                }
-                multiData.put(fa);
-                multiData.clear();
-                break;
-            case Vector2Array:
-                Vector2f[] v2a = (Vector2f[]) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(v2a);
-                } else {
-                    multiData = BufferUtils.ensureLargeEnough(multiData, v2a.length * 2);
-                }
-                for (int i = 0; i < v2a.length; i++) {
-                    BufferUtils.setInBuffer(v2a[i], multiData, i);
-                }
-                multiData.clear();
-                break;
-            case Vector3Array:
-                Vector3f[] v3a = (Vector3f[]) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(v3a);
-                } else {
-                    multiData = BufferUtils.ensureLargeEnough(multiData, v3a.length * 3);
-                }
-                for (int i = 0; i < v3a.length; i++) {
-                    BufferUtils.setInBuffer(v3a[i], multiData, i);
-                }
-                multiData.clear();
-                break;
-            case Vector4Array:
-                Vector4f[] v4a = (Vector4f[]) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(v4a);
-                } else {
-                    multiData = BufferUtils.ensureLargeEnough(multiData, v4a.length * 4);
-                }
-                for (int i = 0; i < v4a.length; i++) {
-                    BufferUtils.setInBuffer(v4a[i], multiData, i);
-                }
-                multiData.clear();
-                break;
-            case Matrix3Array:
-                Matrix3f[] m3a = (Matrix3f[]) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(m3a.length * 9);
-                } else {
-                    multiData = BufferUtils.ensureLargeEnough(multiData, m3a.length * 9);
-                }
-                for (int i = 0; i < m3a.length; i++) {
-                    m3a[i].fillFloatBuffer(multiData, true);
-                }
-                multiData.clear();
-                break;
-            case Matrix4Array:
-                Matrix4f[] m4a = (Matrix4f[]) value;
-                if (multiData == null) {
-                    multiData = BufferUtils.createFloatBuffer(m4a.length * 16);
-                } else {
-                    multiData = BufferUtils.ensureLargeEnough(multiData, m4a.length * 16);
-                }
-                for (int i = 0; i < m4a.length; i++) {
-                    m4a[i].fillFloatBuffer(multiData, true);
-                }
-                multiData.clear();
-                break;
-                // Only use check if equals optimization for primitive values
-            case Int:
-            case Float:
-            case Boolean:
-                if (this.value != null && this.value.equals(value)) {
-                    return;
-                }
-                this.value = value;
-                break;
-            default:
-                this.value = value;
-                break;
-        }
-
-        if (multiData != null) {
-            this.value = multiData;
-        }
-
-        varType = type;
-        updateNeeded = true;
-    }
-
-    public void setVector4Length(int length){
-        if (location == -1)
-            return;
-
-        FloatBuffer fb = (FloatBuffer) value;
-        if (fb == null || fb.capacity() < length) {
-            value = BufferUtils.createFloatBuffer(length * 4);
-        }
-
-        varType = VarType.Vector4Array;
-        updateNeeded = true;
-        setByCurrentMaterial = true;
-    }
-
-    public void setVector4InArray(float x, float y, float z, float w, int index){
-        if (location == -1)
-            return;
-
-        if (varType != null && varType != VarType.Vector4Array)
-            throw new IllegalArgumentException("Expected a "+varType.name()+" value!");
-
-        FloatBuffer fb = (FloatBuffer) value;
-        fb.position(index * 4);
-        fb.put(x).put(y).put(z).put(w);
-        fb.rewind();
-        updateNeeded = true;
-        setByCurrentMaterial = true;
-    }
-    
-    public boolean isUpdateNeeded(){
-        return updateNeeded;
-    }
-
-    public void clearUpdateNeeded(){
-        updateNeeded = false;
-    }
-
-    public void reset(){
-        setByCurrentMaterial = false;
-        location = -2;
-        updateNeeded = true;
-    }
-
-}
+/*\r
+ * Copyright (c) 2009-2012 jMonkeyEngine\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are\r
+ * met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * * Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in the\r
+ *   documentation and/or other materials provided with the distribution.\r
+ *\r
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors\r
+ *   may be used to endorse or promote products derived from this software\r
+ *   without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\r
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+package com.jme3.shader;\r
+\r
+import com.jme3.math.*;\r
+import com.jme3.util.BufferUtils;\r
+import java.nio.FloatBuffer;\r
+import java.nio.IntBuffer;\r
+\r
+public class Uniform extends ShaderVariable {\r
+\r
+    private static final Integer ZERO_INT = Integer.valueOf(0);\r
+    private static final Float ZERO_FLT = Float.valueOf(0);\r
+    private static final FloatBuffer ZERO_BUF = BufferUtils.createFloatBuffer(4*4);\r
+\r
+    /**\r
+     * Currently set value of the uniform.\r
+     */\r
+    protected Object value = null;\r
+    \r
+    /**\r
+     * For arrays or matrices, efficient format\r
+     * that can be sent to GL faster.\r
+     */\r
+    protected FloatBuffer multiData = null;\r
+\r
+    /**\r
+     * Type of uniform\r
+     */\r
+    protected VarType varType;\r
+\r
+    /**\r
+     * Binding to a renderer value, or null if user-defined uniform\r
+     */\r
+    protected UniformBinding binding;\r
+\r
+    /**\r
+     * Used to track which uniforms to clear to avoid\r
+     * values leaking from other materials that use that shader.\r
+     */\r
+    protected boolean setByCurrentMaterial = false;\r
+\r
+    @Override\r
+    public String toString(){\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("Uniform[name=");\r
+        sb.append(name);\r
+        if (varType != null){\r
+            sb.append(", type=");\r
+            sb.append(varType);\r
+            sb.append(", value=");\r
+            sb.append(value);\r
+        }else{\r
+            sb.append(", value=<not set>");\r
+        }\r
+        sb.append("]");\r
+        return sb.toString();\r
+    }\r
+\r
+    public void setBinding(UniformBinding binding){\r
+        this.binding = binding;\r
+    }\r
+\r
+    public UniformBinding getBinding(){\r
+        return binding;\r
+    }\r
+\r
+    public VarType getVarType() {\r
+        return varType;\r
+    }\r
+\r
+    public Object getValue(){\r
+        return value;\r
+    }\r
+\r
+    public boolean isSetByCurrentMaterial() {\r
+        return setByCurrentMaterial;\r
+    }\r
+\r
+    public void clearSetByCurrentMaterial(){\r
+        setByCurrentMaterial = false;\r
+    }\r
+\r
+    private static void setVector4(Vector4f vec, Object value) {\r
+        if (value instanceof ColorRGBA) {\r
+            ColorRGBA color = (ColorRGBA) value;\r
+            vec.set(color.r, color.g, color.b, color.a);\r
+        } else if (value instanceof Quaternion) {\r
+            Quaternion quat = (Quaternion) value;\r
+            vec.set(quat.getX(), quat.getY(), quat.getZ(), quat.getW());\r
+        } else if (value instanceof Vector4f) {\r
+            Vector4f vec4 = (Vector4f) value;\r
+            vec.set(vec4);\r
+        } else{\r
+            throw new IllegalArgumentException();\r
+        }\r
+    }\r
+    \r
+    public void clearValue(){\r
+        updateNeeded = true;\r
+\r
+        if (multiData != null){           \r
+            multiData.clear();\r
+\r
+            while (multiData.remaining() > 0){\r
+                ZERO_BUF.clear();\r
+                ZERO_BUF.limit( Math.min(multiData.remaining(), 16) );\r
+                multiData.put(ZERO_BUF);\r
+            }\r
+\r
+            multiData.clear();\r
+\r
+            return;\r
+        }\r
+\r
+        if (varType == null) {\r
+            return;\r
+        }\r
+            \r
+        switch (varType){\r
+            case Int:\r
+                this.value = ZERO_INT;\r
+                break;\r
+            case Boolean:\r
+                this.value = Boolean.FALSE;\r
+                break;\r
+            case Float:\r
+                this.value = ZERO_FLT; \r
+                break;\r
+            case Vector2:\r
+                this.value = Vector2f.ZERO;\r
+                break;\r
+            case Vector3:\r
+                this.value = Vector3f.ZERO;\r
+                break;\r
+            case Vector4:\r
+                this.value = Vector4f.ZERO;\r
+                break;\r
+            default:\r
+                // won't happen because those are either textures\r
+                // or multidata types\r
+        }\r
+    }\r
+    \r
+    public void setValue(VarType type, Object value){\r
+        if (location == LOC_NOT_DEFINED) {\r
+            return;\r
+        }\r
+\r
+        if (varType != null && varType != type) {\r
+            throw new IllegalArgumentException("Expected a " + varType.name() + " value!");\r
+        }\r
+\r
+        if (value == null) {\r
+            throw new NullPointerException();\r
+        }\r
+\r
+        setByCurrentMaterial = true;\r
+\r
+        switch (type){\r
+            case Matrix3:\r
+                Matrix3f m3 = (Matrix3f) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(9);\r
+                }\r
+                m3.fillFloatBuffer(multiData, true);\r
+                multiData.clear();\r
+                break;\r
+            case Matrix4:\r
+                Matrix4f m4 = (Matrix4f) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(16);\r
+                }\r
+                m4.fillFloatBuffer(multiData, true);\r
+                multiData.clear();\r
+                break;\r
+            case IntArray:\r
+                int[] ia = (int[]) value;\r
+                if (this.value == null) {\r
+                    this.value = BufferUtils.createIntBuffer(ia);\r
+                } else {\r
+                    this.value = BufferUtils.ensureLargeEnough((IntBuffer)this.value, ia.length);\r
+                }\r
+                ((IntBuffer)this.value).clear();\r
+                break;\r
+            case FloatArray:\r
+                float[] fa = (float[]) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(fa);\r
+                } else {\r
+                    multiData = BufferUtils.ensureLargeEnough(multiData, fa.length);\r
+                }\r
+                multiData.put(fa);\r
+                multiData.clear();\r
+                break;\r
+            case Vector2Array:\r
+                Vector2f[] v2a = (Vector2f[]) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(v2a);\r
+                } else {\r
+                    multiData = BufferUtils.ensureLargeEnough(multiData, v2a.length * 2);\r
+                }\r
+                for (int i = 0; i < v2a.length; i++) {\r
+                    BufferUtils.setInBuffer(v2a[i], multiData, i);\r
+                }\r
+                multiData.clear();\r
+                break;\r
+            case Vector3Array:\r
+                Vector3f[] v3a = (Vector3f[]) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(v3a);\r
+                } else {\r
+                    multiData = BufferUtils.ensureLargeEnough(multiData, v3a.length * 3);\r
+                }\r
+                for (int i = 0; i < v3a.length; i++) {\r
+                    BufferUtils.setInBuffer(v3a[i], multiData, i);\r
+                }\r
+                multiData.clear();\r
+                break;\r
+            case Vector4Array:\r
+                Vector4f[] v4a = (Vector4f[]) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(v4a);\r
+                } else {\r
+                    multiData = BufferUtils.ensureLargeEnough(multiData, v4a.length * 4);\r
+                }\r
+                for (int i = 0; i < v4a.length; i++) {\r
+                    BufferUtils.setInBuffer(v4a[i], multiData, i);\r
+                }\r
+                multiData.clear();\r
+                break;\r
+            case Matrix3Array:\r
+                Matrix3f[] m3a = (Matrix3f[]) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(m3a.length * 9);\r
+                } else {\r
+                    multiData = BufferUtils.ensureLargeEnough(multiData, m3a.length * 9);\r
+                }\r
+                for (int i = 0; i < m3a.length; i++) {\r
+                    m3a[i].fillFloatBuffer(multiData, true);\r
+                }\r
+                multiData.clear();\r
+                break;\r
+            case Matrix4Array:\r
+                Matrix4f[] m4a = (Matrix4f[]) value;\r
+                if (multiData == null) {\r
+                    multiData = BufferUtils.createFloatBuffer(m4a.length * 16);\r
+                } else {\r
+                    multiData = BufferUtils.ensureLargeEnough(multiData, m4a.length * 16);\r
+                }\r
+                for (int i = 0; i < m4a.length; i++) {\r
+                    m4a[i].fillFloatBuffer(multiData, true);\r
+                }\r
+                multiData.clear();\r
+                break;\r
+                // Only use check if equals optimization for primitive values\r
+            case Int:\r
+            case Float:\r
+            case Boolean:\r
+                if (this.value != null && this.value.equals(value)) {\r
+                    return;\r
+                }\r
+                this.value = value;\r
+                break;\r
+            default:\r
+                this.value = value;\r
+                break;\r
+        }\r
+\r
+        if (multiData != null) {\r
+            this.value = multiData;\r
+        }\r
+\r
+        varType = type;\r
+        updateNeeded = true;\r
+    }\r
+\r
+    public void setVector4Length(int length){\r
+        if (location == -1)\r
+            return;\r
+\r
+        FloatBuffer fb = (FloatBuffer) value;\r
+        if (fb == null || fb.capacity() < length) {\r
+            value = BufferUtils.createFloatBuffer(length * 4);\r
+        }\r
+\r
+        varType = VarType.Vector4Array;\r
+        updateNeeded = true;\r
+        setByCurrentMaterial = true;\r
+    }\r
+\r
+    public void setVector4InArray(float x, float y, float z, float w, int index){\r
+        if (location == -1)\r
+            return;\r
+\r
+        if (varType != null && varType != VarType.Vector4Array)\r
+            throw new IllegalArgumentException("Expected a "+varType.name()+" value!");\r
+\r
+        FloatBuffer fb = (FloatBuffer) value;\r
+        fb.position(index * 4);\r
+        fb.put(x).put(y).put(z).put(w);\r
+        fb.rewind();\r
+        updateNeeded = true;\r
+        setByCurrentMaterial = true;\r
+    }\r
+    \r
+    public boolean isUpdateNeeded(){\r
+        return updateNeeded;\r
+    }\r
+\r
+    public void clearUpdateNeeded(){\r
+        updateNeeded = false;\r
+    }\r
+\r
+    public void reset(){\r
+        setByCurrentMaterial = false;\r
+        location = -2;\r
+        updateNeeded = true;\r
+    }\r
+\r
+}\r
index e8310e6..6a8049d 100644 (file)
@@ -1,88 +1,89 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.shader;
-
-public enum VarType {
-
-    Float("float"),
-    Vector2("vec2"),
-    Vector3("vec3"),
-    Vector4("vec4"),
-
-    FloatArray(true,false,"float[]"),
-    Vector2Array(true,false,"vec2[]"),
-    Vector3Array(true,false,"vec3[]"),
-    Vector4Array(true,false,"vec4[]"),
-
-    Boolean("bool"),
-
-    Matrix3(true,false,"mat3"),
-    Matrix4(true,false,"mat4"),
-
-    Matrix3Array(true,false,"mat3[]"),
-    Matrix4Array(true,false,"mat4[]"),
-    
-    TextureBuffer(false,true,"sampler1D|sampler1DShadow"),
-    Texture2D(false,true,"sampler2D|sampler2DShadow"),
-    Texture3D(false,true,"sampler3D"),
-    TextureArray(false,true,"sampler2DArray"),
-    TextureCubeMap(false,true,"samplerCube"),
-    Int("int");
-
-    private boolean usesMultiData = false;
-    private boolean textureType = false;
-    private String glslType;
-
-    
-    VarType(String glslType){
-        this.glslType = glslType;
-    }
-
-    VarType(boolean multiData, boolean textureType,String glslType){
-        usesMultiData = multiData;
-        this.textureType = textureType;
-        this.glslType = glslType;
-    }
-
-    public boolean isTextureType() {
-        return textureType;
-    }
-
-    public boolean usesMultiData() {
-        return usesMultiData;
-    }
-
-    public String getGlslType() {
-        return glslType;
-    }    
-
-}
+/*\r
+ * Copyright (c) 2009-2012 jMonkeyEngine\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are\r
+ * met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * * Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in the\r
+ *   documentation and/or other materials provided with the distribution.\r
+ *\r
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors\r
+ *   may be used to endorse or promote products derived from this software\r
+ *   without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\r
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+package com.jme3.shader;\r
+\r
+public enum VarType {\r
+\r
+    Float("float"),\r
+    Vector2("vec2"),\r
+    Vector3("vec3"),\r
+    Vector4("vec4"),\r
+\r
+    IntArray(true,false,"int[]"),\r
+    FloatArray(true,false,"float[]"),\r
+    Vector2Array(true,false,"vec2[]"),\r
+    Vector3Array(true,false,"vec3[]"),\r
+    Vector4Array(true,false,"vec4[]"),\r
+\r
+    Boolean("bool"),\r
+\r
+    Matrix3(true,false,"mat3"),\r
+    Matrix4(true,false,"mat4"),\r
+\r
+    Matrix3Array(true,false,"mat3[]"),\r
+    Matrix4Array(true,false,"mat4[]"),\r
+    \r
+    TextureBuffer(false,true,"sampler1D|sampler1DShadow"),\r
+    Texture2D(false,true,"sampler2D|sampler2DShadow"),\r
+    Texture3D(false,true,"sampler3D"),\r
+    TextureArray(false,true,"sampler2DArray"),\r
+    TextureCubeMap(false,true,"samplerCube"),\r
+    Int("int");\r
+\r
+    private boolean usesMultiData = false;\r
+    private boolean textureType = false;\r
+    private String glslType;\r
+\r
+    \r
+    VarType(String glslType){\r
+        this.glslType = glslType;\r
+    }\r
+\r
+    VarType(boolean multiData, boolean textureType,String glslType){\r
+        usesMultiData = multiData;\r
+        this.textureType = textureType;\r
+        this.glslType = glslType;\r
+    }\r
+\r
+    public boolean isTextureType() {\r
+        return textureType;\r
+    }\r
+\r
+    public boolean usesMultiData() {\r
+        return usesMultiData;\r
+    }\r
+\r
+    public String getGlslType() {\r
+        return glslType;\r
+    }    \r
+\r
+}\r
index e39e0b9..dcc6ab3 100644 (file)
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.util;
-
-import com.jme3.math.ColorRGBA;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.math.Vector4f;
-import java.lang.ref.PhantomReference;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.DoubleBuffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.nio.LongBuffer;
-import java.nio.ShortBuffer;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * <code>BufferUtils</code> is a helper class for generating nio buffers from
- * jME data classes such as Vectors and ColorRGBA.
- * 
- * @author Joshua Slack
- * @version $Id: BufferUtils.java,v 1.16 2007/10/29 16:56:18 nca Exp $
- */
-public final class BufferUtils {
-
-    private static boolean trackDirectMemory = false;
-    private static ReferenceQueue<Buffer> removeCollected = new ReferenceQueue<Buffer>();
-    private static ConcurrentHashMap<BufferInfo, BufferInfo> trackedBuffers = new ConcurrentHashMap<BufferInfo, BufferInfo>();
-    static ClearReferences cleanupthread;
-
-    /**
-     * Set it to true if you want to enable direct memory tracking for debugging purpose.
-     * Default is false.
-     * To print direct memory usage use BufferUtils.printCurrentDirectMemory(StringBuilder store);
-     * @param enabled 
-     */
-    public static void setTrackDirectMemoryEnabled(boolean enabled) {
-        trackDirectMemory = enabled;
-    }
-
-    /**
-     * Creates a clone of the given buffer. The clone's capacity is 
-     * equal to the given buffer's limit.
-     * 
-     * @param buf The buffer to clone
-     * @return The cloned buffer
-     */
-    public static Buffer clone(Buffer buf) {
-        if (buf instanceof FloatBuffer) {
-            return clone((FloatBuffer) buf);
-        } else if (buf instanceof ShortBuffer) {
-            return clone((ShortBuffer) buf);
-        } else if (buf instanceof ByteBuffer) {
-            return clone((ByteBuffer) buf);
-        } else if (buf instanceof IntBuffer) {
-            return clone((IntBuffer) buf);
-        } else if (buf instanceof DoubleBuffer) {
-            return clone((DoubleBuffer) buf);
-        } else {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    private static void onBufferAllocated(Buffer buffer) {
-        /**
-         * StackTraceElement[] stackTrace = new Throwable().getStackTrace(); int
-         * initialIndex = 0;
-         * 
-         * for (int i = 0; i < stackTrace.length; i++){ if
-         * (!stackTrace[i].getClassName().equals(BufferUtils.class.getName())){
-         * initialIndex = i; break; } }
-         * 
-         * int allocated = buffer.capacity(); int size = 0;
-         * 
-         * if (buffer instanceof FloatBuffer){ size = 4; }else if (buffer
-         * instanceof ShortBuffer){ size = 2; }else if (buffer instanceof
-         * ByteBuffer){ size = 1; }else if (buffer instanceof IntBuffer){ size =
-         * 4; }else if (buffer instanceof DoubleBuffer){ size = 8; }
-         * 
-         * allocated *= size;
-         * 
-         * for (int i = initialIndex; i < stackTrace.length; i++){
-         * StackTraceElement element = stackTrace[i]; if
-         * (element.getClassName().startsWith("java")){ break; }
-         * 
-         * try { Class clazz = Class.forName(element.getClassName()); if (i ==
-         * initialIndex){
-         * System.out.println(clazz.getSimpleName()+"."+element.getMethodName
-         * ()+"():" + element.getLineNumber() + " allocated " + allocated);
-         * }else{ System.out.println(" at " +
-         * clazz.getSimpleName()+"."+element.getMethodName()+"()"); } } catch
-         * (ClassNotFoundException ex) { } }
-         */
-        if (BufferUtils.trackDirectMemory) {
-
-            if (BufferUtils.cleanupthread == null) {
-                BufferUtils.cleanupthread = new ClearReferences();
-                BufferUtils.cleanupthread.start();
-            }
-            if (buffer instanceof ByteBuffer) {
-                BufferInfo info = new BufferInfo(ByteBuffer.class, buffer.capacity(), buffer, BufferUtils.removeCollected);
-                BufferUtils.trackedBuffers.put(info, info);
-            } else if (buffer instanceof FloatBuffer) {
-                BufferInfo info = new BufferInfo(FloatBuffer.class, buffer.capacity() * 4, buffer, BufferUtils.removeCollected);
-                BufferUtils.trackedBuffers.put(info, info);
-            } else if (buffer instanceof IntBuffer) {
-                BufferInfo info = new BufferInfo(IntBuffer.class, buffer.capacity() * 4, buffer, BufferUtils.removeCollected);
-                BufferUtils.trackedBuffers.put(info, info);
-            } else if (buffer instanceof ShortBuffer) {
-                BufferInfo info = new BufferInfo(ShortBuffer.class, buffer.capacity() * 2, buffer, BufferUtils.removeCollected);
-                BufferUtils.trackedBuffers.put(info, info);
-            } else if (buffer instanceof DoubleBuffer) {
-                BufferInfo info = new BufferInfo(DoubleBuffer.class, buffer.capacity() * 8, buffer, BufferUtils.removeCollected);
-                BufferUtils.trackedBuffers.put(info, info);
-            }
-
-        }
-    }
-
-    /**
-     * Generate a new FloatBuffer using the given array of Vector3f objects. 
-     * The FloatBuffer will be 3 * data.length long and contain the vector data 
-     * as data[0].x, data[0].y, data[0].z, data[1].x... etc.
-     * 
-     * @param data array of Vector3f objects to place into a new FloatBuffer
-     */
-    public static FloatBuffer createFloatBuffer(Vector3f... data) {
-        if (data == null) {
-            return null;
-        }
-        FloatBuffer buff = createFloatBuffer(3 * data.length);
-        for (Vector3f element : data) {
-            if (element != null) {
-                buff.put(element.x).put(element.y).put(element.z);
-            } else {
-                buff.put(0).put(0).put(0);
-            }
-        }
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Generate a new FloatBuffer using the given array of Quaternion objects.
-     * The FloatBuffer will be 4 * data.length long and contain the vector data.
-     * 
-     * @param data array of Quaternion objects to place into a new FloatBuffer
-     */
-    public static FloatBuffer createFloatBuffer(Quaternion... data) {
-        if (data == null) {
-            return null;
-        }
-        FloatBuffer buff = createFloatBuffer(4 * data.length);
-        for (Quaternion element : data) {
-            if (element != null) {
-                buff.put(element.getX()).put(element.getY()).put(element.getZ()).put(element.getW());
-            } else {
-                buff.put(0).put(0).put(0).put(0);
-            }
-        }
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Generate a new FloatBuffer using the given array of Vector4 objects.
-     * The FloatBuffer will be 4 * data.length long and contain the vector data.
-     *
-     * @param data array of Vector4 objects to place into a new FloatBuffer
-     */
-    public static FloatBuffer createFloatBuffer(Vector4f... data) {
-        if (data == null) {
-            return null;
-        }
-        FloatBuffer buff = createFloatBuffer(4 * data.length);
-        for (int x = 0; x < data.length; x++) {
-            if (data[x] != null) {
-                buff.put(data[x].getX()).put(data[x].getY()).put(data[x].getZ()).put(data[x].getW());
-            } else {
-                buff.put(0).put(0).put(0).put(0);
-            }
-        }
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Generate a new FloatBuffer using the given array of float primitives.
-     * @param data array of float primitives to place into a new FloatBuffer
-     */
-    public static FloatBuffer createFloatBuffer(float... data) {
-        if (data == null) {
-            return null;
-        }
-        FloatBuffer buff = createFloatBuffer(data.length);
-        buff.clear();
-        buff.put(data);
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Create a new FloatBuffer of an appropriate size to hold the specified
-     * number of Vector3f object data.
-     * 
-     * @param vertices
-     *            number of vertices that need to be held by the newly created
-     *            buffer
-     * @return the requested new FloatBuffer
-     */
-    public static FloatBuffer createVector3Buffer(int vertices) {
-        FloatBuffer vBuff = createFloatBuffer(3 * vertices);
-        return vBuff;
-    }
-
-    /**
-     * Create a new FloatBuffer of an appropriate size to hold the specified
-     * number of Vector3f object data only if the given buffer if not already
-     * the right size.
-     * 
-     * @param buf
-     *            the buffer to first check and rewind
-     * @param vertices
-     *            number of vertices that need to be held by the newly created
-     *            buffer
-     * @return the requested new FloatBuffer
-     */
-    public static FloatBuffer createVector3Buffer(FloatBuffer buf, int vertices) {
-        if (buf != null && buf.limit() == 3 * vertices) {
-            buf.rewind();
-            return buf;
-        }
-
-        return createFloatBuffer(3 * vertices);
-    }
-
-    /**
-     * Sets the data contained in the given color into the FloatBuffer at the
-     * specified index.
-     * 
-     * @param color
-     *            the data to insert
-     * @param buf
-     *            the buffer to insert into
-     * @param index
-     *            the postion to place the data; in terms of colors not floats
-     */
-    public static void setInBuffer(ColorRGBA color, FloatBuffer buf,
-            int index) {
-        buf.position(index * 4);
-        buf.put(color.r);
-        buf.put(color.g);
-        buf.put(color.b);
-        buf.put(color.a);
-    }
-
-    /**
-     * Sets the data contained in the given quaternion into the FloatBuffer at the 
-     * specified index.
-     * 
-     * @param quat
-     *            the {@link Quaternion} to insert
-     * @param buf
-     *            the buffer to insert into
-     * @param index
-     *            the postion to place the data; in terms of quaternions not floats
-     */
-    public static void setInBuffer(Quaternion quat, FloatBuffer buf,
-            int index) {
-        buf.position(index * 4);
-        buf.put(quat.getX());
-        buf.put(quat.getY());
-        buf.put(quat.getZ());
-        buf.put(quat.getW());
-    }
-
-    /**
-     * Sets the data contained in the given vector4 into the FloatBuffer at the
-     * specified index.
-     *
-     * @param vec
-     *            the {@link Vector4f} to insert
-     * @param buf
-     *            the buffer to insert into
-     * @param index
-     *            the postion to place the data; in terms of vector4 not floats
-     */
-    public static void setInBuffer(Vector4f vec, FloatBuffer buf,
-            int index) {
-        buf.position(index * 4);
-        buf.put(vec.getX());
-        buf.put(vec.getY());
-        buf.put(vec.getZ());
-        buf.put(vec.getW());
-    }
-
-    /**
-     * Sets the data contained in the given Vector3F into the FloatBuffer at the
-     * specified index.
-     * 
-     * @param vector
-     *            the data to insert
-     * @param buf
-     *            the buffer to insert into
-     * @param index
-     *            the postion to place the data; in terms of vectors not floats
-     */
-    public static void setInBuffer(Vector3f vector, FloatBuffer buf, int index) {
-        if (buf == null) {
-            return;
-        }
-        if (vector == null) {
-            buf.put(index * 3, 0);
-            buf.put((index * 3) + 1, 0);
-            buf.put((index * 3) + 2, 0);
-        } else {
-            buf.put(index * 3, vector.x);
-            buf.put((index * 3) + 1, vector.y);
-            buf.put((index * 3) + 2, vector.z);
-        }
-    }
-
-    /**
-     * Updates the values of the given vector from the specified buffer at the
-     * index provided.
-     * 
-     * @param vector
-     *            the vector to set data on
-     * @param buf
-     *            the buffer to read from
-     * @param index
-     *            the position (in terms of vectors, not floats) to read from
-     *            the buf
-     */
-    public static void populateFromBuffer(Vector3f vector, FloatBuffer buf, int index) {
-        vector.x = buf.get(index * 3);
-        vector.y = buf.get(index * 3 + 1);
-        vector.z = buf.get(index * 3 + 2);
-    }
-
-    /**
-     * Generates a Vector3f array from the given FloatBuffer.
-     * 
-     * @param buff
-     *            the FloatBuffer to read from
-     * @return a newly generated array of Vector3f objects
-     */
-    public static Vector3f[] getVector3Array(FloatBuffer buff) {
-        buff.clear();
-        Vector3f[] verts = new Vector3f[buff.limit() / 3];
-        for (int x = 0; x < verts.length; x++) {
-            Vector3f v = new Vector3f(buff.get(), buff.get(), buff.get());
-            verts[x] = v;
-        }
-        return verts;
-    }
-
-    /**
-     * Copies a Vector3f from one position in the buffer to another. The index
-     * values are in terms of vector number (eg, vector number 0 is postions 0-2
-     * in the FloatBuffer.)
-     * 
-     * @param buf
-     *            the buffer to copy from/to
-     * @param fromPos
-     *            the index of the vector to copy
-     * @param toPos
-     *            the index to copy the vector to
-     */
-    public static void copyInternalVector3(FloatBuffer buf, int fromPos, int toPos) {
-        copyInternal(buf, fromPos * 3, toPos * 3, 3);
-    }
-
-    /**
-     * Normalize a Vector3f in-buffer.
-     * 
-     * @param buf
-     *            the buffer to find the Vector3f within
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            to normalize
-     */
-    public static void normalizeVector3(FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector3f tempVec3 = vars.vect1;
-        populateFromBuffer(tempVec3, buf, index);
-        tempVec3.normalizeLocal();
-        setInBuffer(tempVec3, buf, index);
-        vars.release();
-    }
-
-    /**
-     * Add to a Vector3f in-buffer.
-     * 
-     * @param toAdd
-     *            the vector to add from
-     * @param buf
-     *            the buffer to find the Vector3f within
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            to add to
-     */
-    public static void addInBuffer(Vector3f toAdd, FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector3f tempVec3 = vars.vect1;
-        populateFromBuffer(tempVec3, buf, index);
-        tempVec3.addLocal(toAdd);
-        setInBuffer(tempVec3, buf, index);
-        vars.release();
-    }
-
-    /**
-     * Multiply and store a Vector3f in-buffer.
-     * 
-     * @param toMult
-     *            the vector to multiply against
-     * @param buf
-     *            the buffer to find the Vector3f within
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            to multiply
-     */
-    public static void multInBuffer(Vector3f toMult, FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector3f tempVec3 = vars.vect1;
-        populateFromBuffer(tempVec3, buf, index);
-        tempVec3.multLocal(toMult);
-        setInBuffer(tempVec3, buf, index);
-        vars.release();
-    }
-
-    /**
-     * Checks to see if the given Vector3f is equals to the data stored in the
-     * buffer at the given data index.
-     * 
-     * @param check
-     *            the vector to check against - null will return false.
-     * @param buf
-     *            the buffer to compare data with
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            in the buffer to check against
-     * @return true if the data is equivalent, otherwise false.
-     */
-    public static boolean equals(Vector3f check, FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector3f tempVec3 = vars.vect1;
-        populateFromBuffer(tempVec3, buf, index);
-        boolean eq = tempVec3.equals(check);
-        vars.release();
-        return eq;
-    }
-
-    // // -- VECTOR2F METHODS -- ////
-    /**
-     * Generate a new FloatBuffer using the given array of Vector2f objects.
-     * The FloatBuffer will be 2 * data.length long and contain the vector data
-     * as data[0].x, data[0].y, data[1].x... etc.
-     * 
-     * @param data array of Vector2f objects to place into a new FloatBuffer
-     */
-    public static FloatBuffer createFloatBuffer(Vector2f... data) {
-        if (data == null) {
-            return null;
-        }
-        FloatBuffer buff = createFloatBuffer(2 * data.length);
-        for (Vector2f element : data) {
-            if (element != null) {
-                buff.put(element.x).put(element.y);
-            } else {
-                buff.put(0).put(0);
-            }
-        }
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Create a new FloatBuffer of an appropriate size to hold the specified
-     * number of Vector2f object data.
-     * 
-     * @param vertices
-     *            number of vertices that need to be held by the newly created
-     *            buffer
-     * @return the requested new FloatBuffer
-     */
-    public static FloatBuffer createVector2Buffer(int vertices) {
-        FloatBuffer vBuff = createFloatBuffer(2 * vertices);
-        return vBuff;
-    }
-
-    /**
-     * Create a new FloatBuffer of an appropriate size to hold the specified
-     * number of Vector2f object data only if the given buffer if not already
-     * the right size.
-     * 
-     * @param buf
-     *            the buffer to first check and rewind
-     * @param vertices
-     *            number of vertices that need to be held by the newly created
-     *            buffer
-     * @return the requested new FloatBuffer
-     */
-    public static FloatBuffer createVector2Buffer(FloatBuffer buf, int vertices) {
-        if (buf != null && buf.limit() == 2 * vertices) {
-            buf.rewind();
-            return buf;
-        }
-
-        return createFloatBuffer(2 * vertices);
-    }
-
-    /**
-     * Sets the data contained in the given Vector2F into the FloatBuffer at the
-     * specified index.
-     * 
-     * @param vector
-     *            the data to insert
-     * @param buf
-     *            the buffer to insert into
-     * @param index
-     *            the postion to place the data; in terms of vectors not floats
-     */
-    public static void setInBuffer(Vector2f vector, FloatBuffer buf, int index) {
-        buf.put(index * 2, vector.x);
-        buf.put((index * 2) + 1, vector.y);
-    }
-
-    /**
-     * Updates the values of the given vector from the specified buffer at the
-     * index provided.
-     * 
-     * @param vector
-     *            the vector to set data on
-     * @param buf
-     *            the buffer to read from
-     * @param index
-     *            the position (in terms of vectors, not floats) to read from
-     *            the buf
-     */
-    public static void populateFromBuffer(Vector2f vector, FloatBuffer buf, int index) {
-        vector.x = buf.get(index * 2);
-        vector.y = buf.get(index * 2 + 1);
-    }
-
-    /**
-     * Generates a Vector2f array from the given FloatBuffer.
-     * 
-     * @param buff
-     *            the FloatBuffer to read from
-     * @return a newly generated array of Vector2f objects
-     */
-    public static Vector2f[] getVector2Array(FloatBuffer buff) {
-        buff.clear();
-        Vector2f[] verts = new Vector2f[buff.limit() / 2];
-        for (int x = 0; x < verts.length; x++) {
-            Vector2f v = new Vector2f(buff.get(), buff.get());
-            verts[x] = v;
-        }
-        return verts;
-    }
-
-    /**
-     * Copies a Vector2f from one position in the buffer to another. The index
-     * values are in terms of vector number (eg, vector number 0 is postions 0-1
-     * in the FloatBuffer.)
-     * 
-     * @param buf
-     *            the buffer to copy from/to
-     * @param fromPos
-     *            the index of the vector to copy
-     * @param toPos
-     *            the index to copy the vector to
-     */
-    public static void copyInternalVector2(FloatBuffer buf, int fromPos, int toPos) {
-        copyInternal(buf, fromPos * 2, toPos * 2, 2);
-    }
-
-    /**
-     * Normalize a Vector2f in-buffer.
-     * 
-     * @param buf
-     *            the buffer to find the Vector2f within
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            to normalize
-     */
-    public static void normalizeVector2(FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector2f tempVec2 = vars.vect2d;
-        populateFromBuffer(tempVec2, buf, index);
-        tempVec2.normalizeLocal();
-        setInBuffer(tempVec2, buf, index);
-        vars.release();
-    }
-
-    /**
-     * Add to a Vector2f in-buffer.
-     * 
-     * @param toAdd
-     *            the vector to add from
-     * @param buf
-     *            the buffer to find the Vector2f within
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            to add to
-     */
-    public static void addInBuffer(Vector2f toAdd, FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector2f tempVec2 = vars.vect2d;
-        populateFromBuffer(tempVec2, buf, index);
-        tempVec2.addLocal(toAdd);
-        setInBuffer(tempVec2, buf, index);
-        vars.release();
-    }
-
-    /**
-     * Multiply and store a Vector2f in-buffer.
-     * 
-     * @param toMult
-     *            the vector to multiply against
-     * @param buf
-     *            the buffer to find the Vector2f within
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            to multiply
-     */
-    public static void multInBuffer(Vector2f toMult, FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector2f tempVec2 = vars.vect2d;
-        populateFromBuffer(tempVec2, buf, index);
-        tempVec2.multLocal(toMult);
-        setInBuffer(tempVec2, buf, index);
-        vars.release();
-    }
-
-    /**
-     * Checks to see if the given Vector2f is equals to the data stored in the
-     * buffer at the given data index.
-     * 
-     * @param check
-     *            the vector to check against - null will return false.
-     * @param buf
-     *            the buffer to compare data with
-     * @param index
-     *            the position (in terms of vectors, not floats) of the vector
-     *            in the buffer to check against
-     * @return true if the data is equivalent, otherwise false.
-     */
-    public static boolean equals(Vector2f check, FloatBuffer buf, int index) {
-        TempVars vars = TempVars.get();
-        Vector2f tempVec2 = vars.vect2d;
-        populateFromBuffer(tempVec2, buf, index);
-        boolean eq = tempVec2.equals(check);
-        vars.release();
-        return eq;
-    }
-
-    ////  -- INT METHODS -- ////
-    /**
-     * Generate a new IntBuffer using the given array of ints. The IntBuffer
-     * will be data.length long and contain the int data as data[0], data[1]...
-     * etc.
-     * 
-     * @param data
-     *            array of ints to place into a new IntBuffer
-     */
-    public static IntBuffer createIntBuffer(int... data) {
-        if (data == null) {
-            return null;
-        }
-        IntBuffer buff = createIntBuffer(data.length);
-        buff.clear();
-        buff.put(data);
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Create a new int[] array and populate it with the given IntBuffer's
-     * contents.
-     * 
-     * @param buff
-     *            the IntBuffer to read from
-     * @return a new int array populated from the IntBuffer
-     */
-    public static int[] getIntArray(IntBuffer buff) {
-        if (buff == null) {
-            return null;
-        }
-        buff.clear();
-        int[] inds = new int[buff.limit()];
-        for (int x = 0; x < inds.length; x++) {
-            inds[x] = buff.get();
-        }
-        return inds;
-    }
-
-    /**
-     * Create a new float[] array and populate it with the given FloatBuffer's
-     * contents.
-     * 
-     * @param buff
-     *            the FloatBuffer to read from
-     * @return a new float array populated from the FloatBuffer
-     */
-    public static float[] getFloatArray(FloatBuffer buff) {
-        if (buff == null) {
-            return null;
-        }
-        buff.clear();
-        float[] inds = new float[buff.limit()];
-        for (int x = 0; x < inds.length; x++) {
-            inds[x] = buff.get();
-        }
-        return inds;
-    }
-
-    //// -- GENERAL DOUBLE ROUTINES -- ////
-    /**
-     * Create a new DoubleBuffer of the specified size.
-     * 
-     * @param size
-     *            required number of double to store.
-     * @return the new DoubleBuffer
-     */
-    public static DoubleBuffer createDoubleBuffer(int size) {
-        DoubleBuffer buf = ByteBuffer.allocateDirect(8 * size).order(ByteOrder.nativeOrder()).asDoubleBuffer();
-        buf.clear();
-        onBufferAllocated(buf);
-        return buf;
-    }
-
-    /**
-     * Create a new DoubleBuffer of an appropriate size to hold the specified
-     * number of doubles only if the given buffer if not already the right size.
-     * 
-     * @param buf
-     *            the buffer to first check and rewind
-     * @param size
-     *            number of doubles that need to be held by the newly created
-     *            buffer
-     * @return the requested new DoubleBuffer
-     */
-    public static DoubleBuffer createDoubleBuffer(DoubleBuffer buf, int size) {
-        if (buf != null && buf.limit() == size) {
-            buf.rewind();
-            return buf;
-        }
-
-        buf = createDoubleBuffer(size);
-        return buf;
-    }
-
-    /**
-     * Creates a new DoubleBuffer with the same contents as the given
-     * DoubleBuffer. The new DoubleBuffer is seperate from the old one and
-     * changes are not reflected across. If you want to reflect changes,
-     * consider using Buffer.duplicate().
-     * 
-     * @param buf
-     *            the DoubleBuffer to copy
-     * @return the copy
-     */
-    public static DoubleBuffer clone(DoubleBuffer buf) {
-        if (buf == null) {
-            return null;
-        }
-        buf.rewind();
-
-        DoubleBuffer copy;
-        if (isDirect(buf)) {
-            copy = createDoubleBuffer(buf.limit());
-        } else {
-            copy = DoubleBuffer.allocate(buf.limit());
-        }
-        copy.put(buf);
-
-        return copy;
-    }
-
-    //// -- GENERAL FLOAT ROUTINES -- ////
-    /**
-     * Create a new FloatBuffer of the specified size.
-     * 
-     * @param size
-     *            required number of floats to store.
-     * @return the new FloatBuffer
-     */
-    public static FloatBuffer createFloatBuffer(int size) {
-        FloatBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer();
-        buf.clear();
-        onBufferAllocated(buf);
-        return buf;
-    }
-
-    /**
-     * Copies floats from one position in the buffer to another.
-     * 
-     * @param buf
-     *            the buffer to copy from/to
-     * @param fromPos
-     *            the starting point to copy from
-     * @param toPos
-     *            the starting point to copy to
-     * @param length
-     *            the number of floats to copy
-     */
-    public static void copyInternal(FloatBuffer buf, int fromPos, int toPos, int length) {
-        float[] data = new float[length];
-        buf.position(fromPos);
-        buf.get(data);
-        buf.position(toPos);
-        buf.put(data);
-    }
-
-    /**
-     * Creates a new FloatBuffer with the same contents as the given
-     * FloatBuffer. The new FloatBuffer is seperate from the old one and changes
-     * are not reflected across. If you want to reflect changes, consider using
-     * Buffer.duplicate().
-     * 
-     * @param buf
-     *            the FloatBuffer to copy
-     * @return the copy
-     */
-    public static FloatBuffer clone(FloatBuffer buf) {
-        if (buf == null) {
-            return null;
-        }
-        buf.rewind();
-
-        FloatBuffer copy;
-        if (isDirect(buf)) {
-            copy = createFloatBuffer(buf.limit());
-        } else {
-            copy = FloatBuffer.allocate(buf.limit());
-        }
-        copy.put(buf);
-
-        return copy;
-    }
-
-    //// -- GENERAL INT ROUTINES -- ////
-    /**
-     * Create a new IntBuffer of the specified size.
-     * 
-     * @param size
-     *            required number of ints to store.
-     * @return the new IntBuffer
-     */
-    public static IntBuffer createIntBuffer(int size) {
-        IntBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asIntBuffer();
-        buf.clear();
-        onBufferAllocated(buf);
-        return buf;
-    }
-
-    /**
-     * Create a new IntBuffer of an appropriate size to hold the specified
-     * number of ints only if the given buffer if not already the right size.
-     * 
-     * @param buf
-     *            the buffer to first check and rewind
-     * @param size
-     *            number of ints that need to be held by the newly created
-     *            buffer
-     * @return the requested new IntBuffer
-     */
-    public static IntBuffer createIntBuffer(IntBuffer buf, int size) {
-        if (buf != null && buf.limit() == size) {
-            buf.rewind();
-            return buf;
-        }
-
-        buf = createIntBuffer(size);
-        return buf;
-    }
-
-    /**
-     * Creates a new IntBuffer with the same contents as the given IntBuffer.
-     * The new IntBuffer is seperate from the old one and changes are not
-     * reflected across. If you want to reflect changes, consider using
-     * Buffer.duplicate().
-     * 
-     * @param buf
-     *            the IntBuffer to copy
-     * @return the copy
-     */
-    public static IntBuffer clone(IntBuffer buf) {
-        if (buf == null) {
-            return null;
-        }
-        buf.rewind();
-
-        IntBuffer copy;
-        if (isDirect(buf)) {
-            copy = createIntBuffer(buf.limit());
-        } else {
-            copy = IntBuffer.allocate(buf.limit());
-        }
-        copy.put(buf);
-
-        return copy;
-    }
-
-    //// -- GENERAL BYTE ROUTINES -- ////
-    /**
-     * Create a new ByteBuffer of the specified size.
-     * 
-     * @param size
-     *            required number of ints to store.
-     * @return the new IntBuffer
-     */
-    public static ByteBuffer createByteBuffer(int size) {
-        ByteBuffer buf = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
-        buf.clear();
-        onBufferAllocated(buf);
-        return buf;
-    }
-
-    /**
-     * Create a new ByteBuffer of an appropriate size to hold the specified
-     * number of ints only if the given buffer if not already the right size.
-     * 
-     * @param buf
-     *            the buffer to first check and rewind
-     * @param size
-     *            number of bytes that need to be held by the newly created
-     *            buffer
-     * @return the requested new IntBuffer
-     */
-    public static ByteBuffer createByteBuffer(ByteBuffer buf, int size) {
-        if (buf != null && buf.limit() == size) {
-            buf.rewind();
-            return buf;
-        }
-
-        buf = createByteBuffer(size);
-        return buf;
-    }
-
-    public static ByteBuffer createByteBuffer(byte... data) {
-        ByteBuffer bb = createByteBuffer(data.length);
-        bb.put(data);
-        bb.flip();
-        return bb;
-    }
-
-    public static ByteBuffer createByteBuffer(String data) {
-        byte[] bytes = data.getBytes();
-        ByteBuffer bb = createByteBuffer(bytes.length);
-        bb.put(bytes);
-        bb.flip();
-        return bb;
-    }
-
-    /**
-     * Creates a new ByteBuffer with the same contents as the given ByteBuffer.
-     * The new ByteBuffer is seperate from the old one and changes are not
-     * reflected across. If you want to reflect changes, consider using
-     * Buffer.duplicate().
-     * 
-     * @param buf
-     *            the ByteBuffer to copy
-     * @return the copy
-     */
-    public static ByteBuffer clone(ByteBuffer buf) {
-        if (buf == null) {
-            return null;
-        }
-        buf.rewind();
-
-        ByteBuffer copy;
-        if (isDirect(buf)) {
-            copy = createByteBuffer(buf.limit());
-        } else {
-            copy = ByteBuffer.allocate(buf.limit());
-        }
-        copy.put(buf);
-
-        return copy;
-    }
-
-    //// -- GENERAL SHORT ROUTINES -- ////
-    /**
-     * Create a new ShortBuffer of the specified size.
-     * 
-     * @param size
-     *            required number of shorts to store.
-     * @return the new ShortBuffer
-     */
-    public static ShortBuffer createShortBuffer(int size) {
-        ShortBuffer buf = ByteBuffer.allocateDirect(2 * size).order(ByteOrder.nativeOrder()).asShortBuffer();
-        buf.clear();
-        onBufferAllocated(buf);
-        return buf;
-    }
-
-    /**
-     * Create a new ShortBuffer of an appropriate size to hold the specified
-     * number of shorts only if the given buffer if not already the right size.
-     * 
-     * @param buf
-     *            the buffer to first check and rewind
-     * @param size
-     *            number of shorts that need to be held by the newly created
-     *            buffer
-     * @return the requested new ShortBuffer
-     */
-    public static ShortBuffer createShortBuffer(ShortBuffer buf, int size) {
-        if (buf != null && buf.limit() == size) {
-            buf.rewind();
-            return buf;
-        }
-
-        buf = createShortBuffer(size);
-        return buf;
-    }
-
-    public static ShortBuffer createShortBuffer(short... data) {
-        if (data == null) {
-            return null;
-        }
-        ShortBuffer buff = createShortBuffer(data.length);
-        buff.clear();
-        buff.put(data);
-        buff.flip();
-        return buff;
-    }
-
-    /**
-     * Creates a new ShortBuffer with the same contents as the given ShortBuffer.
-     * The new ShortBuffer is seperate from the old one and changes are not
-     * reflected across. If you want to reflect changes, consider using
-     * Buffer.duplicate().
-     * 
-     * @param buf
-     *            the ShortBuffer to copy
-     * @return the copy
-     */
-    public static ShortBuffer clone(ShortBuffer buf) {
-        if (buf == null) {
-            return null;
-        }
-        buf.rewind();
-
-        ShortBuffer copy;
-        if (isDirect(buf)) {
-            copy = createShortBuffer(buf.limit());
-        } else {
-            copy = ShortBuffer.allocate(buf.limit());
-        }
-        copy.put(buf);
-
-        return copy;
-    }
-
-    /**
-     * Ensures there is at least the <code>required</code> number of entries left after the current position of the
-     * buffer. If the buffer is too small a larger one is created and the old one copied to the new buffer.
-     * @param buffer buffer that should be checked/copied (may be null)
-     * @param required minimum number of elements that should be remaining in the returned buffer
-     * @return a buffer large enough to receive at least the <code>required</code> number of entries, same position as
-     * the input buffer, not null
-     */
-    public static FloatBuffer ensureLargeEnough(FloatBuffer buffer, int required) {
-        if (buffer != null) {
-            buffer.limit(buffer.capacity());
-        }
-        if (buffer == null || (buffer.remaining() < required)) {
-            int position = (buffer != null ? buffer.position() : 0);
-            FloatBuffer newVerts = createFloatBuffer(position + required);
-            if (buffer != null) {
-                buffer.flip();
-                newVerts.put(buffer);
-                newVerts.position(position);
-            }
-            buffer = newVerts;
-        }
-        return buffer;
-    }
-
-    public static ShortBuffer ensureLargeEnough(ShortBuffer buffer, int required) {
-        if (buffer != null) {
-            buffer.limit(buffer.capacity());
-        }
-        if (buffer == null || (buffer.remaining() < required)) {
-            int position = (buffer != null ? buffer.position() : 0);
-            ShortBuffer newVerts = createShortBuffer(position + required);
-            if (buffer != null) {
-                buffer.flip();
-                newVerts.put(buffer);
-                newVerts.position(position);
-            }
-            buffer = newVerts;
-        }
-        return buffer;
-    }
-
-    public static ByteBuffer ensureLargeEnough(ByteBuffer buffer, int required) {
-        if (buffer != null) {
-            buffer.limit(buffer.capacity());
-        }
-        if (buffer == null || (buffer.remaining() < required)) {
-            int position = (buffer != null ? buffer.position() : 0);
-            ByteBuffer newVerts = createByteBuffer(position + required);
-            if (buffer != null) {
-                buffer.flip();
-                newVerts.put(buffer);
-                newVerts.position(position);
-            }
-            buffer = newVerts;
-        }
-        return buffer;
-    }
-
-    public static void printCurrentDirectMemory(StringBuilder store) {
-        long totalHeld = 0;
-        long heapMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
-
-        boolean printStout = store == null;
-        if (store == null) {
-            store = new StringBuilder();
-        }
-        if (trackDirectMemory) {
-            // make a new set to hold the keys to prevent concurrency issues.
-            int fBufs = 0, bBufs = 0, iBufs = 0, sBufs = 0, dBufs = 0;
-            int fBufsM = 0, bBufsM = 0, iBufsM = 0, sBufsM = 0, dBufsM = 0;
-            for (BufferInfo b : BufferUtils.trackedBuffers.values()) {
-                if (b.type == ByteBuffer.class) {
-                    totalHeld += b.size;
-                    bBufsM += b.size;
-                    bBufs++;
-                } else if (b.type == FloatBuffer.class) {
-                    totalHeld += b.size;
-                    fBufsM += b.size;
-                    fBufs++;
-                } else if (b.type == IntBuffer.class) {
-                    totalHeld += b.size;
-                    iBufsM += b.size;
-                    iBufs++;
-                } else if (b.type == ShortBuffer.class) {
-                    totalHeld += b.size;
-                    sBufsM += b.size;
-                    sBufs++;
-                } else if (b.type == DoubleBuffer.class) {
-                    totalHeld += b.size;
-                    dBufsM += b.size;
-                    dBufs++;
-                }
-            }
-
-            store.append("Existing buffers: ").append(BufferUtils.trackedBuffers.size()).append("\n");
-            store.append("(b: ").append(bBufs).append("  f: ").append(fBufs).append("  i: ").append(iBufs).append("  s: ").append(sBufs).append("  d: ").append(dBufs).append(")").append("\n");
-            store.append("Total   heap memory held: ").append(heapMem / 1024).append("kb\n");
-            store.append("Total direct memory held: ").append(totalHeld / 1024).append("kb\n");
-            store.append("(b: ").append(bBufsM / 1024).append("kb  f: ").append(fBufsM / 1024).append("kb  i: ").append(iBufsM / 1024).append("kb  s: ").append(sBufsM / 1024).append("kb  d: ").append(dBufsM / 1024).append("kb)").append("\n");
-        } else {
-            store.append("Total   heap memory held: ").append(heapMem / 1024).append("kb\n");
-            store.append("Only heap memory available, if you want to monitor direct memory use BufferUtils.setTrackDirectMemoryEnabled(true) during initialization.").append("\n");
-        }
-        if (printStout) {
-            System.out.println(store.toString());
-        }
-    }
-    private static final AtomicBoolean loadedMethods = new AtomicBoolean(false);
-    private static Method cleanerMethod = null;
-    private static Method cleanMethod = null;
-    private static Method viewedBufferMethod = null;
-    private static Method freeMethod = null;
-
-    private static Method loadMethod(String className, String methodName) {
-        try {
-            Method method = Class.forName(className).getMethod(methodName);
-            method.setAccessible(true);
-            return method;
-        } catch (NoSuchMethodException ex) {
-            return null; // the method was not found
-        } catch (SecurityException ex) {
-            return null; // setAccessible not allowed by security policy
-        } catch (ClassNotFoundException ex) {
-            return null; // the direct buffer implementation was not found
-        }
-    }
-
-    private static void loadCleanerMethods() {
-        // If its already true, exit, if not, set it to true.
-        if (BufferUtils.loadedMethods.getAndSet(true)) {
-            return;
-        }
-        // This could potentially be called many times if used from multiple
-        // threads
-        synchronized (BufferUtils.loadedMethods) {
-            // Oracle JRE / OpenJDK
-            cleanerMethod = loadMethod("sun.nio.ch.DirectBuffer", "cleaner");
-            cleanMethod = loadMethod("sun.misc.Cleaner", "clean");
-            viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "viewedBuffer");
-            if (viewedBufferMethod == null) {
-                // They changed the name in Java 7 (???)
-                viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "attachment");
-            }
-
-            // Apache Harmony
-            ByteBuffer bb = BufferUtils.createByteBuffer(1);
-            Class<?> clazz = bb.getClass();
-            try {
-                freeMethod = clazz.getMethod("free");
-            } catch (NoSuchMethodException ex) {
-            } catch (SecurityException ex) {
-            }
-        }
-    }
-
-    /**
-     * Direct buffers are garbage collected by using a phantom reference and a
-     * reference queue. Every once a while, the JVM checks the reference queue and
-     * cleans the direct buffers. However, as this doesn't happen
-     * immediately after discarding all references to a direct buffer, it's
-     * easy to OutOfMemoryError yourself using direct buffers. This function
-     * explicitly calls the Cleaner method of a direct buffer.
-     * 
-     * @param toBeDestroyed
-     *          The direct buffer that will be "cleaned". Utilizes reflection.
-     * 
-     */
-    public static void destroyDirectBuffer(Buffer toBeDestroyed) {
-        if (!isDirect(toBeDestroyed)) {
-            return;
-        }
-
-        BufferUtils.loadCleanerMethods();
-
-        try {
-            if (freeMethod != null) {
-                freeMethod.invoke(toBeDestroyed);
-            } else {
-                Object cleaner = cleanerMethod.invoke(toBeDestroyed);
-                if (cleaner != null) {
-                    cleanMethod.invoke(cleaner);
-                } else {
-                    // Try the alternate approach of getting the viewed buffer first
-                    Object viewedBuffer = viewedBufferMethod.invoke(toBeDestroyed);
-                    if (viewedBuffer != null) {
-                        destroyDirectBuffer((Buffer) viewedBuffer);
-                    } else {
-                        Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "Buffer cannot be destroyed: {0}", toBeDestroyed);
-                    }
-                }
-            }
-        } catch (IllegalAccessException ex) {
-            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
-        } catch (IllegalArgumentException ex) {
-            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
-        } catch (InvocationTargetException ex) {
-            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
-        } catch (SecurityException ex) {
-            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);
-        }
-    }
-    
-    /*
-     * FIXME when java 1.5 supprt is dropped - replace calls to this method with Buffer.isDirect 
-     * 
-     * Buffer.isDirect() is only java 6. Java 5 only have this method on Buffer subclasses : 
-     * FloatBuffer, IntBuffer, ShortBuffer, ByteBuffer,DoubleBuffer, LongBuffer.   
-     * CharBuffer has been excluded as we don't use it.
-     * 
-     */
-    private static boolean isDirect(Buffer buf) {
-        if (buf instanceof FloatBuffer) {
-            return ((FloatBuffer) buf).isDirect();
-        }
-        if (buf instanceof IntBuffer) {
-            return ((IntBuffer) buf).isDirect();
-        }
-        if (buf instanceof ShortBuffer) {
-            return ((ShortBuffer) buf).isDirect();
-        }
-        if (buf instanceof ByteBuffer) {
-            return ((ByteBuffer) buf).isDirect();
-        }
-        if (buf instanceof DoubleBuffer) {
-            return ((DoubleBuffer) buf).isDirect();
-        }
-        if (buf instanceof LongBuffer) {
-            return ((LongBuffer) buf).isDirect();
-        }
-        throw new UnsupportedOperationException(" BufferUtils.isDirect was called on " + buf.getClass().getName());
-    }
-
-    private static class BufferInfo extends PhantomReference<Buffer> {
-
-        private Class type;
-        private int size;
-
-        public BufferInfo(Class type, int size, Buffer referent, ReferenceQueue<? super Buffer> q) {
-            super(referent, q);
-            this.type = type;
-            this.size = size;
-        }
-    }
-
-    private static class ClearReferences extends Thread {
-
-        ClearReferences() {
-            this.setDaemon(true);
-        }
-
-        @Override
-        public void run() {
-            try {
-                while (true) {
-                    Reference<? extends Buffer> toclean = BufferUtils.removeCollected.remove();
-                    BufferUtils.trackedBuffers.remove(toclean);
-                }
-
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
-    }
-}
\ No newline at end of file
+/*\r
+ * Copyright (c) 2009-2012 jMonkeyEngine\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are\r
+ * met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * * Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in the\r
+ *   documentation and/or other materials provided with the distribution.\r
+ *\r
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors\r
+ *   may be used to endorse or promote products derived from this software\r
+ *   without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\r
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+package com.jme3.util;\r
+\r
+import com.jme3.math.ColorRGBA;\r
+import com.jme3.math.Quaternion;\r
+import com.jme3.math.Vector2f;\r
+import com.jme3.math.Vector3f;\r
+import com.jme3.math.Vector4f;\r
+import java.lang.ref.PhantomReference;\r
+import java.lang.ref.Reference;\r
+import java.lang.ref.ReferenceQueue;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.lang.reflect.Method;\r
+import java.nio.Buffer;\r
+import java.nio.ByteBuffer;\r
+import java.nio.ByteOrder;\r
+import java.nio.DoubleBuffer;\r
+import java.nio.FloatBuffer;\r
+import java.nio.IntBuffer;\r
+import java.nio.LongBuffer;\r
+import java.nio.ShortBuffer;\r
+import java.util.concurrent.ConcurrentHashMap;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+/**\r
+ * <code>BufferUtils</code> is a helper class for generating nio buffers from\r
+ * jME data classes such as Vectors and ColorRGBA.\r
+ * \r
+ * @author Joshua Slack\r
+ * @version $Id: BufferUtils.java,v 1.16 2007/10/29 16:56:18 nca Exp $\r
+ */\r
+public final class BufferUtils {\r
+\r
+    private static boolean trackDirectMemory = false;\r
+    private static ReferenceQueue<Buffer> removeCollected = new ReferenceQueue<Buffer>();\r
+    private static ConcurrentHashMap<BufferInfo, BufferInfo> trackedBuffers = new ConcurrentHashMap<BufferInfo, BufferInfo>();\r
+    static ClearReferences cleanupthread;\r
+\r
+    /**\r
+     * Set it to true if you want to enable direct memory tracking for debugging purpose.\r
+     * Default is false.\r
+     * To print direct memory usage use BufferUtils.printCurrentDirectMemory(StringBuilder store);\r
+     * @param enabled \r
+     */\r
+    public static void setTrackDirectMemoryEnabled(boolean enabled) {\r
+        trackDirectMemory = enabled;\r
+    }\r
+\r
+    /**\r
+     * Creates a clone of the given buffer. The clone's capacity is \r
+     * equal to the given buffer's limit.\r
+     * \r
+     * @param buf The buffer to clone\r
+     * @return The cloned buffer\r
+     */\r
+    public static Buffer clone(Buffer buf) {\r
+        if (buf instanceof FloatBuffer) {\r
+            return clone((FloatBuffer) buf);\r
+        } else if (buf instanceof ShortBuffer) {\r
+            return clone((ShortBuffer) buf);\r
+        } else if (buf instanceof ByteBuffer) {\r
+            return clone((ByteBuffer) buf);\r
+        } else if (buf instanceof IntBuffer) {\r
+            return clone((IntBuffer) buf);\r
+        } else if (buf instanceof DoubleBuffer) {\r
+            return clone((DoubleBuffer) buf);\r
+        } else {\r
+            throw new UnsupportedOperationException();\r
+        }\r
+    }\r
+\r
+    private static void onBufferAllocated(Buffer buffer) {\r
+        /**\r
+         * StackTraceElement[] stackTrace = new Throwable().getStackTrace(); int\r
+         * initialIndex = 0;\r
+         * \r
+         * for (int i = 0; i < stackTrace.length; i++){ if\r
+         * (!stackTrace[i].getClassName().equals(BufferUtils.class.getName())){\r
+         * initialIndex = i; break; } }\r
+         * \r
+         * int allocated = buffer.capacity(); int size = 0;\r
+         * \r
+         * if (buffer instanceof FloatBuffer){ size = 4; }else if (buffer\r
+         * instanceof ShortBuffer){ size = 2; }else if (buffer instanceof\r
+         * ByteBuffer){ size = 1; }else if (buffer instanceof IntBuffer){ size =\r
+         * 4; }else if (buffer instanceof DoubleBuffer){ size = 8; }\r
+         * \r
+         * allocated *= size;\r
+         * \r
+         * for (int i = initialIndex; i < stackTrace.length; i++){\r
+         * StackTraceElement element = stackTrace[i]; if\r
+         * (element.getClassName().startsWith("java")){ break; }\r
+         * \r
+         * try { Class clazz = Class.forName(element.getClassName()); if (i ==\r
+         * initialIndex){\r
+         * System.out.println(clazz.getSimpleName()+"."+element.getMethodName\r
+         * ()+"():" + element.getLineNumber() + " allocated " + allocated);\r
+         * }else{ System.out.println(" at " +\r
+         * clazz.getSimpleName()+"."+element.getMethodName()+"()"); } } catch\r
+         * (ClassNotFoundException ex) { } }\r
+         */\r
+        if (BufferUtils.trackDirectMemory) {\r
+\r
+            if (BufferUtils.cleanupthread == null) {\r
+                BufferUtils.cleanupthread = new ClearReferences();\r
+                BufferUtils.cleanupthread.start();\r
+            }\r
+            if (buffer instanceof ByteBuffer) {\r
+                BufferInfo info = new BufferInfo(ByteBuffer.class, buffer.capacity(), buffer, BufferUtils.removeCollected);\r
+                BufferUtils.trackedBuffers.put(info, info);\r
+            } else if (buffer instanceof FloatBuffer) {\r
+                BufferInfo info = new BufferInfo(FloatBuffer.class, buffer.capacity() * 4, buffer, BufferUtils.removeCollected);\r
+                BufferUtils.trackedBuffers.put(info, info);\r
+            } else if (buffer instanceof IntBuffer) {\r
+                BufferInfo info = new BufferInfo(IntBuffer.class, buffer.capacity() * 4, buffer, BufferUtils.removeCollected);\r
+                BufferUtils.trackedBuffers.put(info, info);\r
+            } else if (buffer instanceof ShortBuffer) {\r
+                BufferInfo info = new BufferInfo(ShortBuffer.class, buffer.capacity() * 2, buffer, BufferUtils.removeCollected);\r
+                BufferUtils.trackedBuffers.put(info, info);\r
+            } else if (buffer instanceof DoubleBuffer) {\r
+                BufferInfo info = new BufferInfo(DoubleBuffer.class, buffer.capacity() * 8, buffer, BufferUtils.removeCollected);\r
+                BufferUtils.trackedBuffers.put(info, info);\r
+            }\r
+\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Generate a new FloatBuffer using the given array of Vector3f objects. \r
+     * The FloatBuffer will be 3 * data.length long and contain the vector data \r
+     * as data[0].x, data[0].y, data[0].z, data[1].x... etc.\r
+     * \r
+     * @param data array of Vector3f objects to place into a new FloatBuffer\r
+     */\r
+    public static FloatBuffer createFloatBuffer(Vector3f... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        FloatBuffer buff = createFloatBuffer(3 * data.length);\r
+        for (Vector3f element : data) {\r
+            if (element != null) {\r
+                buff.put(element.x).put(element.y).put(element.z);\r
+            } else {\r
+                buff.put(0).put(0).put(0);\r
+            }\r
+        }\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Generate a new FloatBuffer using the given array of Quaternion objects.\r
+     * The FloatBuffer will be 4 * data.length long and contain the vector data.\r
+     * \r
+     * @param data array of Quaternion objects to place into a new FloatBuffer\r
+     */\r
+    public static FloatBuffer createFloatBuffer(Quaternion... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        FloatBuffer buff = createFloatBuffer(4 * data.length);\r
+        for (Quaternion element : data) {\r
+            if (element != null) {\r
+                buff.put(element.getX()).put(element.getY()).put(element.getZ()).put(element.getW());\r
+            } else {\r
+                buff.put(0).put(0).put(0).put(0);\r
+            }\r
+        }\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Generate a new FloatBuffer using the given array of Vector4 objects.\r
+     * The FloatBuffer will be 4 * data.length long and contain the vector data.\r
+     *\r
+     * @param data array of Vector4 objects to place into a new FloatBuffer\r
+     */\r
+    public static FloatBuffer createFloatBuffer(Vector4f... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        FloatBuffer buff = createFloatBuffer(4 * data.length);\r
+        for (int x = 0; x < data.length; x++) {\r
+            if (data[x] != null) {\r
+                buff.put(data[x].getX()).put(data[x].getY()).put(data[x].getZ()).put(data[x].getW());\r
+            } else {\r
+                buff.put(0).put(0).put(0).put(0);\r
+            }\r
+        }\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Generate a new FloatBuffer using the given array of float primitives.\r
+     * @param data array of float primitives to place into a new FloatBuffer\r
+     */\r
+    public static FloatBuffer createFloatBuffer(float... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        FloatBuffer buff = createFloatBuffer(data.length);\r
+        buff.clear();\r
+        buff.put(data);\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Create a new FloatBuffer of an appropriate size to hold the specified\r
+     * number of Vector3f object data.\r
+     * \r
+     * @param vertices\r
+     *            number of vertices that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new FloatBuffer\r
+     */\r
+    public static FloatBuffer createVector3Buffer(int vertices) {\r
+        FloatBuffer vBuff = createFloatBuffer(3 * vertices);\r
+        return vBuff;\r
+    }\r
+\r
+    /**\r
+     * Create a new FloatBuffer of an appropriate size to hold the specified\r
+     * number of Vector3f object data only if the given buffer if not already\r
+     * the right size.\r
+     * \r
+     * @param buf\r
+     *            the buffer to first check and rewind\r
+     * @param vertices\r
+     *            number of vertices that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new FloatBuffer\r
+     */\r
+    public static FloatBuffer createVector3Buffer(FloatBuffer buf, int vertices) {\r
+        if (buf != null && buf.limit() == 3 * vertices) {\r
+            buf.rewind();\r
+            return buf;\r
+        }\r
+\r
+        return createFloatBuffer(3 * vertices);\r
+    }\r
+\r
+    /**\r
+     * Sets the data contained in the given color into the FloatBuffer at the\r
+     * specified index.\r
+     * \r
+     * @param color\r
+     *            the data to insert\r
+     * @param buf\r
+     *            the buffer to insert into\r
+     * @param index\r
+     *            the postion to place the data; in terms of colors not floats\r
+     */\r
+    public static void setInBuffer(ColorRGBA color, FloatBuffer buf,\r
+            int index) {\r
+        buf.position(index * 4);\r
+        buf.put(color.r);\r
+        buf.put(color.g);\r
+        buf.put(color.b);\r
+        buf.put(color.a);\r
+    }\r
+\r
+    /**\r
+     * Sets the data contained in the given quaternion into the FloatBuffer at the \r
+     * specified index.\r
+     * \r
+     * @param quat\r
+     *            the {@link Quaternion} to insert\r
+     * @param buf\r
+     *            the buffer to insert into\r
+     * @param index\r
+     *            the postion to place the data; in terms of quaternions not floats\r
+     */\r
+    public static void setInBuffer(Quaternion quat, FloatBuffer buf,\r
+            int index) {\r
+        buf.position(index * 4);\r
+        buf.put(quat.getX());\r
+        buf.put(quat.getY());\r
+        buf.put(quat.getZ());\r
+        buf.put(quat.getW());\r
+    }\r
+\r
+    /**\r
+     * Sets the data contained in the given vector4 into the FloatBuffer at the\r
+     * specified index.\r
+     *\r
+     * @param vec\r
+     *            the {@link Vector4f} to insert\r
+     * @param buf\r
+     *            the buffer to insert into\r
+     * @param index\r
+     *            the postion to place the data; in terms of vector4 not floats\r
+     */\r
+    public static void setInBuffer(Vector4f vec, FloatBuffer buf,\r
+            int index) {\r
+        buf.position(index * 4);\r
+        buf.put(vec.getX());\r
+        buf.put(vec.getY());\r
+        buf.put(vec.getZ());\r
+        buf.put(vec.getW());\r
+    }\r
+\r
+    /**\r
+     * Sets the data contained in the given Vector3F into the FloatBuffer at the\r
+     * specified index.\r
+     * \r
+     * @param vector\r
+     *            the data to insert\r
+     * @param buf\r
+     *            the buffer to insert into\r
+     * @param index\r
+     *            the postion to place the data; in terms of vectors not floats\r
+     */\r
+    public static void setInBuffer(Vector3f vector, FloatBuffer buf, int index) {\r
+        if (buf == null) {\r
+            return;\r
+        }\r
+        if (vector == null) {\r
+            buf.put(index * 3, 0);\r
+            buf.put((index * 3) + 1, 0);\r
+            buf.put((index * 3) + 2, 0);\r
+        } else {\r
+            buf.put(index * 3, vector.x);\r
+            buf.put((index * 3) + 1, vector.y);\r
+            buf.put((index * 3) + 2, vector.z);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Updates the values of the given vector from the specified buffer at the\r
+     * index provided.\r
+     * \r
+     * @param vector\r
+     *            the vector to set data on\r
+     * @param buf\r
+     *            the buffer to read from\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) to read from\r
+     *            the buf\r
+     */\r
+    public static void populateFromBuffer(Vector3f vector, FloatBuffer buf, int index) {\r
+        vector.x = buf.get(index * 3);\r
+        vector.y = buf.get(index * 3 + 1);\r
+        vector.z = buf.get(index * 3 + 2);\r
+    }\r
+\r
+    /**\r
+     * Generates a Vector3f array from the given FloatBuffer.\r
+     * \r
+     * @param buff\r
+     *            the FloatBuffer to read from\r
+     * @return a newly generated array of Vector3f objects\r
+     */\r
+    public static Vector3f[] getVector3Array(FloatBuffer buff) {\r
+        buff.clear();\r
+        Vector3f[] verts = new Vector3f[buff.limit() / 3];\r
+        for (int x = 0; x < verts.length; x++) {\r
+            Vector3f v = new Vector3f(buff.get(), buff.get(), buff.get());\r
+            verts[x] = v;\r
+        }\r
+        return verts;\r
+    }\r
+\r
+    /**\r
+     * Copies a Vector3f from one position in the buffer to another. The index\r
+     * values are in terms of vector number (eg, vector number 0 is postions 0-2\r
+     * in the FloatBuffer.)\r
+     * \r
+     * @param buf\r
+     *            the buffer to copy from/to\r
+     * @param fromPos\r
+     *            the index of the vector to copy\r
+     * @param toPos\r
+     *            the index to copy the vector to\r
+     */\r
+    public static void copyInternalVector3(FloatBuffer buf, int fromPos, int toPos) {\r
+        copyInternal(buf, fromPos * 3, toPos * 3, 3);\r
+    }\r
+\r
+    /**\r
+     * Normalize a Vector3f in-buffer.\r
+     * \r
+     * @param buf\r
+     *            the buffer to find the Vector3f within\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            to normalize\r
+     */\r
+    public static void normalizeVector3(FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector3f tempVec3 = vars.vect1;\r
+        populateFromBuffer(tempVec3, buf, index);\r
+        tempVec3.normalizeLocal();\r
+        setInBuffer(tempVec3, buf, index);\r
+        vars.release();\r
+    }\r
+\r
+    /**\r
+     * Add to a Vector3f in-buffer.\r
+     * \r
+     * @param toAdd\r
+     *            the vector to add from\r
+     * @param buf\r
+     *            the buffer to find the Vector3f within\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            to add to\r
+     */\r
+    public static void addInBuffer(Vector3f toAdd, FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector3f tempVec3 = vars.vect1;\r
+        populateFromBuffer(tempVec3, buf, index);\r
+        tempVec3.addLocal(toAdd);\r
+        setInBuffer(tempVec3, buf, index);\r
+        vars.release();\r
+    }\r
+\r
+    /**\r
+     * Multiply and store a Vector3f in-buffer.\r
+     * \r
+     * @param toMult\r
+     *            the vector to multiply against\r
+     * @param buf\r
+     *            the buffer to find the Vector3f within\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            to multiply\r
+     */\r
+    public static void multInBuffer(Vector3f toMult, FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector3f tempVec3 = vars.vect1;\r
+        populateFromBuffer(tempVec3, buf, index);\r
+        tempVec3.multLocal(toMult);\r
+        setInBuffer(tempVec3, buf, index);\r
+        vars.release();\r
+    }\r
+\r
+    /**\r
+     * Checks to see if the given Vector3f is equals to the data stored in the\r
+     * buffer at the given data index.\r
+     * \r
+     * @param check\r
+     *            the vector to check against - null will return false.\r
+     * @param buf\r
+     *            the buffer to compare data with\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            in the buffer to check against\r
+     * @return true if the data is equivalent, otherwise false.\r
+     */\r
+    public static boolean equals(Vector3f check, FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector3f tempVec3 = vars.vect1;\r
+        populateFromBuffer(tempVec3, buf, index);\r
+        boolean eq = tempVec3.equals(check);\r
+        vars.release();\r
+        return eq;\r
+    }\r
+\r
+    // // -- VECTOR2F METHODS -- ////\r
+    /**\r
+     * Generate a new FloatBuffer using the given array of Vector2f objects.\r
+     * The FloatBuffer will be 2 * data.length long and contain the vector data\r
+     * as data[0].x, data[0].y, data[1].x... etc.\r
+     * \r
+     * @param data array of Vector2f objects to place into a new FloatBuffer\r
+     */\r
+    public static FloatBuffer createFloatBuffer(Vector2f... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        FloatBuffer buff = createFloatBuffer(2 * data.length);\r
+        for (Vector2f element : data) {\r
+            if (element != null) {\r
+                buff.put(element.x).put(element.y);\r
+            } else {\r
+                buff.put(0).put(0);\r
+            }\r
+        }\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Create a new FloatBuffer of an appropriate size to hold the specified\r
+     * number of Vector2f object data.\r
+     * \r
+     * @param vertices\r
+     *            number of vertices that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new FloatBuffer\r
+     */\r
+    public static FloatBuffer createVector2Buffer(int vertices) {\r
+        FloatBuffer vBuff = createFloatBuffer(2 * vertices);\r
+        return vBuff;\r
+    }\r
+\r
+    /**\r
+     * Create a new FloatBuffer of an appropriate size to hold the specified\r
+     * number of Vector2f object data only if the given buffer if not already\r
+     * the right size.\r
+     * \r
+     * @param buf\r
+     *            the buffer to first check and rewind\r
+     * @param vertices\r
+     *            number of vertices that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new FloatBuffer\r
+     */\r
+    public static FloatBuffer createVector2Buffer(FloatBuffer buf, int vertices) {\r
+        if (buf != null && buf.limit() == 2 * vertices) {\r
+            buf.rewind();\r
+            return buf;\r
+        }\r
+\r
+        return createFloatBuffer(2 * vertices);\r
+    }\r
+\r
+    /**\r
+     * Sets the data contained in the given Vector2F into the FloatBuffer at the\r
+     * specified index.\r
+     * \r
+     * @param vector\r
+     *            the data to insert\r
+     * @param buf\r
+     *            the buffer to insert into\r
+     * @param index\r
+     *            the postion to place the data; in terms of vectors not floats\r
+     */\r
+    public static void setInBuffer(Vector2f vector, FloatBuffer buf, int index) {\r
+        buf.put(index * 2, vector.x);\r
+        buf.put((index * 2) + 1, vector.y);\r
+    }\r
+\r
+    /**\r
+     * Updates the values of the given vector from the specified buffer at the\r
+     * index provided.\r
+     * \r
+     * @param vector\r
+     *            the vector to set data on\r
+     * @param buf\r
+     *            the buffer to read from\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) to read from\r
+     *            the buf\r
+     */\r
+    public static void populateFromBuffer(Vector2f vector, FloatBuffer buf, int index) {\r
+        vector.x = buf.get(index * 2);\r
+        vector.y = buf.get(index * 2 + 1);\r
+    }\r
+\r
+    /**\r
+     * Generates a Vector2f array from the given FloatBuffer.\r
+     * \r
+     * @param buff\r
+     *            the FloatBuffer to read from\r
+     * @return a newly generated array of Vector2f objects\r
+     */\r
+    public static Vector2f[] getVector2Array(FloatBuffer buff) {\r
+        buff.clear();\r
+        Vector2f[] verts = new Vector2f[buff.limit() / 2];\r
+        for (int x = 0; x < verts.length; x++) {\r
+            Vector2f v = new Vector2f(buff.get(), buff.get());\r
+            verts[x] = v;\r
+        }\r
+        return verts;\r
+    }\r
+\r
+    /**\r
+     * Copies a Vector2f from one position in the buffer to another. The index\r
+     * values are in terms of vector number (eg, vector number 0 is postions 0-1\r
+     * in the FloatBuffer.)\r
+     * \r
+     * @param buf\r
+     *            the buffer to copy from/to\r
+     * @param fromPos\r
+     *            the index of the vector to copy\r
+     * @param toPos\r
+     *            the index to copy the vector to\r
+     */\r
+    public static void copyInternalVector2(FloatBuffer buf, int fromPos, int toPos) {\r
+        copyInternal(buf, fromPos * 2, toPos * 2, 2);\r
+    }\r
+\r
+    /**\r
+     * Normalize a Vector2f in-buffer.\r
+     * \r
+     * @param buf\r
+     *            the buffer to find the Vector2f within\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            to normalize\r
+     */\r
+    public static void normalizeVector2(FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector2f tempVec2 = vars.vect2d;\r
+        populateFromBuffer(tempVec2, buf, index);\r
+        tempVec2.normalizeLocal();\r
+        setInBuffer(tempVec2, buf, index);\r
+        vars.release();\r
+    }\r
+\r
+    /**\r
+     * Add to a Vector2f in-buffer.\r
+     * \r
+     * @param toAdd\r
+     *            the vector to add from\r
+     * @param buf\r
+     *            the buffer to find the Vector2f within\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            to add to\r
+     */\r
+    public static void addInBuffer(Vector2f toAdd, FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector2f tempVec2 = vars.vect2d;\r
+        populateFromBuffer(tempVec2, buf, index);\r
+        tempVec2.addLocal(toAdd);\r
+        setInBuffer(tempVec2, buf, index);\r
+        vars.release();\r
+    }\r
+\r
+    /**\r
+     * Multiply and store a Vector2f in-buffer.\r
+     * \r
+     * @param toMult\r
+     *            the vector to multiply against\r
+     * @param buf\r
+     *            the buffer to find the Vector2f within\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            to multiply\r
+     */\r
+    public static void multInBuffer(Vector2f toMult, FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector2f tempVec2 = vars.vect2d;\r
+        populateFromBuffer(tempVec2, buf, index);\r
+        tempVec2.multLocal(toMult);\r
+        setInBuffer(tempVec2, buf, index);\r
+        vars.release();\r
+    }\r
+\r
+    /**\r
+     * Checks to see if the given Vector2f is equals to the data stored in the\r
+     * buffer at the given data index.\r
+     * \r
+     * @param check\r
+     *            the vector to check against - null will return false.\r
+     * @param buf\r
+     *            the buffer to compare data with\r
+     * @param index\r
+     *            the position (in terms of vectors, not floats) of the vector\r
+     *            in the buffer to check against\r
+     * @return true if the data is equivalent, otherwise false.\r
+     */\r
+    public static boolean equals(Vector2f check, FloatBuffer buf, int index) {\r
+        TempVars vars = TempVars.get();\r
+        Vector2f tempVec2 = vars.vect2d;\r
+        populateFromBuffer(tempVec2, buf, index);\r
+        boolean eq = tempVec2.equals(check);\r
+        vars.release();\r
+        return eq;\r
+    }\r
+\r
+    ////  -- INT METHODS -- ////\r
+    /**\r
+     * Generate a new IntBuffer using the given array of ints. The IntBuffer\r
+     * will be data.length long and contain the int data as data[0], data[1]...\r
+     * etc.\r
+     * \r
+     * @param data\r
+     *            array of ints to place into a new IntBuffer\r
+     */\r
+    public static IntBuffer createIntBuffer(int... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        IntBuffer buff = createIntBuffer(data.length);\r
+        buff.clear();\r
+        buff.put(data);\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Create a new int[] array and populate it with the given IntBuffer's\r
+     * contents.\r
+     * \r
+     * @param buff\r
+     *            the IntBuffer to read from\r
+     * @return a new int array populated from the IntBuffer\r
+     */\r
+    public static int[] getIntArray(IntBuffer buff) {\r
+        if (buff == null) {\r
+            return null;\r
+        }\r
+        buff.clear();\r
+        int[] inds = new int[buff.limit()];\r
+        for (int x = 0; x < inds.length; x++) {\r
+            inds[x] = buff.get();\r
+        }\r
+        return inds;\r
+    }\r
+\r
+    /**\r
+     * Create a new float[] array and populate it with the given FloatBuffer's\r
+     * contents.\r
+     * \r
+     * @param buff\r
+     *            the FloatBuffer to read from\r
+     * @return a new float array populated from the FloatBuffer\r
+     */\r
+    public static float[] getFloatArray(FloatBuffer buff) {\r
+        if (buff == null) {\r
+            return null;\r
+        }\r
+        buff.clear();\r
+        float[] inds = new float[buff.limit()];\r
+        for (int x = 0; x < inds.length; x++) {\r
+            inds[x] = buff.get();\r
+        }\r
+        return inds;\r
+    }\r
+\r
+    //// -- GENERAL DOUBLE ROUTINES -- ////\r
+    /**\r
+     * Create a new DoubleBuffer of the specified size.\r
+     * \r
+     * @param size\r
+     *            required number of double to store.\r
+     * @return the new DoubleBuffer\r
+     */\r
+    public static DoubleBuffer createDoubleBuffer(int size) {\r
+        DoubleBuffer buf = ByteBuffer.allocateDirect(8 * size).order(ByteOrder.nativeOrder()).asDoubleBuffer();\r
+        buf.clear();\r
+        onBufferAllocated(buf);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Create a new DoubleBuffer of an appropriate size to hold the specified\r
+     * number of doubles only if the given buffer if not already the right size.\r
+     * \r
+     * @param buf\r
+     *            the buffer to first check and rewind\r
+     * @param size\r
+     *            number of doubles that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new DoubleBuffer\r
+     */\r
+    public static DoubleBuffer createDoubleBuffer(DoubleBuffer buf, int size) {\r
+        if (buf != null && buf.limit() == size) {\r
+            buf.rewind();\r
+            return buf;\r
+        }\r
+\r
+        buf = createDoubleBuffer(size);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Creates a new DoubleBuffer with the same contents as the given\r
+     * DoubleBuffer. The new DoubleBuffer is seperate from the old one and\r
+     * changes are not reflected across. If you want to reflect changes,\r
+     * consider using Buffer.duplicate().\r
+     * \r
+     * @param buf\r
+     *            the DoubleBuffer to copy\r
+     * @return the copy\r
+     */\r
+    public static DoubleBuffer clone(DoubleBuffer buf) {\r
+        if (buf == null) {\r
+            return null;\r
+        }\r
+        buf.rewind();\r
+\r
+        DoubleBuffer copy;\r
+        if (isDirect(buf)) {\r
+            copy = createDoubleBuffer(buf.limit());\r
+        } else {\r
+            copy = DoubleBuffer.allocate(buf.limit());\r
+        }\r
+        copy.put(buf);\r
+\r
+        return copy;\r
+    }\r
+\r
+    //// -- GENERAL FLOAT ROUTINES -- ////\r
+    /**\r
+     * Create a new FloatBuffer of the specified size.\r
+     * \r
+     * @param size\r
+     *            required number of floats to store.\r
+     * @return the new FloatBuffer\r
+     */\r
+    public static FloatBuffer createFloatBuffer(int size) {\r
+        FloatBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer();\r
+        buf.clear();\r
+        onBufferAllocated(buf);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Copies floats from one position in the buffer to another.\r
+     * \r
+     * @param buf\r
+     *            the buffer to copy from/to\r
+     * @param fromPos\r
+     *            the starting point to copy from\r
+     * @param toPos\r
+     *            the starting point to copy to\r
+     * @param length\r
+     *            the number of floats to copy\r
+     */\r
+    public static void copyInternal(FloatBuffer buf, int fromPos, int toPos, int length) {\r
+        float[] data = new float[length];\r
+        buf.position(fromPos);\r
+        buf.get(data);\r
+        buf.position(toPos);\r
+        buf.put(data);\r
+    }\r
+\r
+    /**\r
+     * Creates a new FloatBuffer with the same contents as the given\r
+     * FloatBuffer. The new FloatBuffer is seperate from the old one and changes\r
+     * are not reflected across. If you want to reflect changes, consider using\r
+     * Buffer.duplicate().\r
+     * \r
+     * @param buf\r
+     *            the FloatBuffer to copy\r
+     * @return the copy\r
+     */\r
+    public static FloatBuffer clone(FloatBuffer buf) {\r
+        if (buf == null) {\r
+            return null;\r
+        }\r
+        buf.rewind();\r
+\r
+        FloatBuffer copy;\r
+        if (isDirect(buf)) {\r
+            copy = createFloatBuffer(buf.limit());\r
+        } else {\r
+            copy = FloatBuffer.allocate(buf.limit());\r
+        }\r
+        copy.put(buf);\r
+\r
+        return copy;\r
+    }\r
+\r
+    //// -- GENERAL INT ROUTINES -- ////\r
+    /**\r
+     * Create a new IntBuffer of the specified size.\r
+     * \r
+     * @param size\r
+     *            required number of ints to store.\r
+     * @return the new IntBuffer\r
+     */\r
+    public static IntBuffer createIntBuffer(int size) {\r
+        IntBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asIntBuffer();\r
+        buf.clear();\r
+        onBufferAllocated(buf);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Create a new IntBuffer of an appropriate size to hold the specified\r
+     * number of ints only if the given buffer if not already the right size.\r
+     * \r
+     * @param buf\r
+     *            the buffer to first check and rewind\r
+     * @param size\r
+     *            number of ints that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new IntBuffer\r
+     */\r
+    public static IntBuffer createIntBuffer(IntBuffer buf, int size) {\r
+        if (buf != null && buf.limit() == size) {\r
+            buf.rewind();\r
+            return buf;\r
+        }\r
+\r
+        buf = createIntBuffer(size);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Creates a new IntBuffer with the same contents as the given IntBuffer.\r
+     * The new IntBuffer is seperate from the old one and changes are not\r
+     * reflected across. If you want to reflect changes, consider using\r
+     * Buffer.duplicate().\r
+     * \r
+     * @param buf\r
+     *            the IntBuffer to copy\r
+     * @return the copy\r
+     */\r
+    public static IntBuffer clone(IntBuffer buf) {\r
+        if (buf == null) {\r
+            return null;\r
+        }\r
+        buf.rewind();\r
+\r
+        IntBuffer copy;\r
+        if (isDirect(buf)) {\r
+            copy = createIntBuffer(buf.limit());\r
+        } else {\r
+            copy = IntBuffer.allocate(buf.limit());\r
+        }\r
+        copy.put(buf);\r
+\r
+        return copy;\r
+    }\r
+\r
+    //// -- GENERAL BYTE ROUTINES -- ////\r
+    /**\r
+     * Create a new ByteBuffer of the specified size.\r
+     * \r
+     * @param size\r
+     *            required number of ints to store.\r
+     * @return the new IntBuffer\r
+     */\r
+    public static ByteBuffer createByteBuffer(int size) {\r
+        ByteBuffer buf = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());\r
+        buf.clear();\r
+        onBufferAllocated(buf);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Create a new ByteBuffer of an appropriate size to hold the specified\r
+     * number of ints only if the given buffer if not already the right size.\r
+     * \r
+     * @param buf\r
+     *            the buffer to first check and rewind\r
+     * @param size\r
+     *            number of bytes that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new IntBuffer\r
+     */\r
+    public static ByteBuffer createByteBuffer(ByteBuffer buf, int size) {\r
+        if (buf != null && buf.limit() == size) {\r
+            buf.rewind();\r
+            return buf;\r
+        }\r
+\r
+        buf = createByteBuffer(size);\r
+        return buf;\r
+    }\r
+\r
+    public static ByteBuffer createByteBuffer(byte... data) {\r
+        ByteBuffer bb = createByteBuffer(data.length);\r
+        bb.put(data);\r
+        bb.flip();\r
+        return bb;\r
+    }\r
+\r
+    public static ByteBuffer createByteBuffer(String data) {\r
+        byte[] bytes = data.getBytes();\r
+        ByteBuffer bb = createByteBuffer(bytes.length);\r
+        bb.put(bytes);\r
+        bb.flip();\r
+        return bb;\r
+    }\r
+\r
+    /**\r
+     * Creates a new ByteBuffer with the same contents as the given ByteBuffer.\r
+     * The new ByteBuffer is seperate from the old one and changes are not\r
+     * reflected across. If you want to reflect changes, consider using\r
+     * Buffer.duplicate().\r
+     * \r
+     * @param buf\r
+     *            the ByteBuffer to copy\r
+     * @return the copy\r
+     */\r
+    public static ByteBuffer clone(ByteBuffer buf) {\r
+        if (buf == null) {\r
+            return null;\r
+        }\r
+        buf.rewind();\r
+\r
+        ByteBuffer copy;\r
+        if (isDirect(buf)) {\r
+            copy = createByteBuffer(buf.limit());\r
+        } else {\r
+            copy = ByteBuffer.allocate(buf.limit());\r
+        }\r
+        copy.put(buf);\r
+\r
+        return copy;\r
+    }\r
+\r
+    //// -- GENERAL SHORT ROUTINES -- ////\r
+    /**\r
+     * Create a new ShortBuffer of the specified size.\r
+     * \r
+     * @param size\r
+     *            required number of shorts to store.\r
+     * @return the new ShortBuffer\r
+     */\r
+    public static ShortBuffer createShortBuffer(int size) {\r
+        ShortBuffer buf = ByteBuffer.allocateDirect(2 * size).order(ByteOrder.nativeOrder()).asShortBuffer();\r
+        buf.clear();\r
+        onBufferAllocated(buf);\r
+        return buf;\r
+    }\r
+\r
+    /**\r
+     * Create a new ShortBuffer of an appropriate size to hold the specified\r
+     * number of shorts only if the given buffer if not already the right size.\r
+     * \r
+     * @param buf\r
+     *            the buffer to first check and rewind\r
+     * @param size\r
+     *            number of shorts that need to be held by the newly created\r
+     *            buffer\r
+     * @return the requested new ShortBuffer\r
+     */\r
+    public static ShortBuffer createShortBuffer(ShortBuffer buf, int size) {\r
+        if (buf != null && buf.limit() == size) {\r
+            buf.rewind();\r
+            return buf;\r
+        }\r
+\r
+        buf = createShortBuffer(size);\r
+        return buf;\r
+    }\r
+\r
+    public static ShortBuffer createShortBuffer(short... data) {\r
+        if (data == null) {\r
+            return null;\r
+        }\r
+        ShortBuffer buff = createShortBuffer(data.length);\r
+        buff.clear();\r
+        buff.put(data);\r
+        buff.flip();\r
+        return buff;\r
+    }\r
+\r
+    /**\r
+     * Creates a new ShortBuffer with the same contents as the given ShortBuffer.\r
+     * The new ShortBuffer is seperate from the old one and changes are not\r
+     * reflected across. If you want to reflect changes, consider using\r
+     * Buffer.duplicate().\r
+     * \r
+     * @param buf\r
+     *            the ShortBuffer to copy\r
+     * @return the copy\r
+     */\r
+    public static ShortBuffer clone(ShortBuffer buf) {\r
+        if (buf == null) {\r
+            return null;\r
+        }\r
+        buf.rewind();\r
+\r
+        ShortBuffer copy;\r
+        if (isDirect(buf)) {\r
+            copy = createShortBuffer(buf.limit());\r
+        } else {\r
+            copy = ShortBuffer.allocate(buf.limit());\r
+        }\r
+        copy.put(buf);\r
+\r
+        return copy;\r
+    }\r
+\r
+    /**\r
+     * Ensures there is at least the <code>required</code> number of entries left after the current position of the\r
+     * buffer. If the buffer is too small a larger one is created and the old one copied to the new buffer.\r
+     * @param buffer buffer that should be checked/copied (may be null)\r
+     * @param required minimum number of elements that should be remaining in the returned buffer\r
+     * @return a buffer large enough to receive at least the <code>required</code> number of entries, same position as\r
+     * the input buffer, not null\r
+     */\r
+    public static FloatBuffer ensureLargeEnough(FloatBuffer buffer, int required) {\r
+        if (buffer != null) {\r
+            buffer.limit(buffer.capacity());\r
+        }\r
+        if (buffer == null || (buffer.remaining() < required)) {\r
+            int position = (buffer != null ? buffer.position() : 0);\r
+            FloatBuffer newVerts = createFloatBuffer(position + required);\r
+            if (buffer != null) {\r
+                buffer.flip();\r
+                newVerts.put(buffer);\r
+                newVerts.position(position);\r
+            }\r
+            buffer = newVerts;\r
+        }\r
+        return buffer;\r
+    }\r
+    \r
+    public static IntBuffer ensureLargeEnough(IntBuffer buffer, int required) {\r
+        if (buffer != null) {\r
+            buffer.limit(buffer.capacity());\r
+        }\r
+        if (buffer == null || (buffer.remaining() < required)) {\r
+            int position = (buffer != null ? buffer.position() : 0);\r
+            IntBuffer newVerts = createIntBuffer(position + required);\r
+            if (buffer != null) {\r
+                buffer.flip();\r
+                newVerts.put(buffer);\r
+                newVerts.position(position);\r
+            }\r
+            buffer = newVerts;\r
+        }\r
+        return buffer;\r
+    }\r
+    \r
+\r
+    public static ShortBuffer ensureLargeEnough(ShortBuffer buffer, int required) {\r
+        if (buffer != null) {\r
+            buffer.limit(buffer.capacity());\r
+        }\r
+        if (buffer == null || (buffer.remaining() < required)) {\r
+            int position = (buffer != null ? buffer.position() : 0);\r
+            ShortBuffer newVerts = createShortBuffer(position + required);\r
+            if (buffer != null) {\r
+                buffer.flip();\r
+                newVerts.put(buffer);\r
+                newVerts.position(position);\r
+            }\r
+            buffer = newVerts;\r
+        }\r
+        return buffer;\r
+    }\r
+\r
+    public static ByteBuffer ensureLargeEnough(ByteBuffer buffer, int required) {\r
+        if (buffer != null) {\r
+            buffer.limit(buffer.capacity());\r
+        }\r
+        if (buffer == null || (buffer.remaining() < required)) {\r
+            int position = (buffer != null ? buffer.position() : 0);\r
+            ByteBuffer newVerts = createByteBuffer(position + required);\r
+            if (buffer != null) {\r
+                buffer.flip();\r
+                newVerts.put(buffer);\r
+                newVerts.position(position);\r
+            }\r
+            buffer = newVerts;\r
+        }\r
+        return buffer;\r
+    }\r
+\r
+    public static void printCurrentDirectMemory(StringBuilder store) {\r
+        long totalHeld = 0;\r
+        long heapMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();\r
+\r
+        boolean printStout = store == null;\r
+        if (store == null) {\r
+            store = new StringBuilder();\r
+        }\r
+        if (trackDirectMemory) {\r
+            // make a new set to hold the keys to prevent concurrency issues.\r
+            int fBufs = 0, bBufs = 0, iBufs = 0, sBufs = 0, dBufs = 0;\r
+            int fBufsM = 0, bBufsM = 0, iBufsM = 0, sBufsM = 0, dBufsM = 0;\r
+            for (BufferInfo b : BufferUtils.trackedBuffers.values()) {\r
+                if (b.type == ByteBuffer.class) {\r
+                    totalHeld += b.size;\r
+                    bBufsM += b.size;\r
+                    bBufs++;\r
+                } else if (b.type == FloatBuffer.class) {\r
+                    totalHeld += b.size;\r
+                    fBufsM += b.size;\r
+                    fBufs++;\r
+                } else if (b.type == IntBuffer.class) {\r
+                    totalHeld += b.size;\r
+                    iBufsM += b.size;\r
+                    iBufs++;\r
+                } else if (b.type == ShortBuffer.class) {\r
+                    totalHeld += b.size;\r
+                    sBufsM += b.size;\r
+                    sBufs++;\r
+                } else if (b.type == DoubleBuffer.class) {\r
+                    totalHeld += b.size;\r
+                    dBufsM += b.size;\r
+                    dBufs++;\r
+                }\r
+            }\r
+\r
+            store.append("Existing buffers: ").append(BufferUtils.trackedBuffers.size()).append("\n");\r
+            store.append("(b: ").append(bBufs).append("  f: ").append(fBufs).append("  i: ").append(iBufs).append("  s: ").append(sBufs).append("  d: ").append(dBufs).append(")").append("\n");\r
+            store.append("Total   heap memory held: ").append(heapMem / 1024).append("kb\n");\r
+            store.append("Total direct memory held: ").append(totalHeld / 1024).append("kb\n");\r
+            store.append("(b: ").append(bBufsM / 1024).append("kb  f: ").append(fBufsM / 1024).append("kb  i: ").append(iBufsM / 1024).append("kb  s: ").append(sBufsM / 1024).append("kb  d: ").append(dBufsM / 1024).append("kb)").append("\n");\r
+        } else {\r
+            store.append("Total   heap memory held: ").append(heapMem / 1024).append("kb\n");\r
+            store.append("Only heap memory available, if you want to monitor direct memory use BufferUtils.setTrackDirectMemoryEnabled(true) during initialization.").append("\n");\r
+        }\r
+        if (printStout) {\r
+            System.out.println(store.toString());\r
+        }\r
+    }\r
+    private static final AtomicBoolean loadedMethods = new AtomicBoolean(false);\r
+    private static Method cleanerMethod = null;\r
+    private static Method cleanMethod = null;\r
+    private static Method viewedBufferMethod = null;\r
+    private static Method freeMethod = null;\r
+\r
+    private static Method loadMethod(String className, String methodName) {\r
+        try {\r
+            Method method = Class.forName(className).getMethod(methodName);\r
+            method.setAccessible(true);\r
+            return method;\r
+        } catch (NoSuchMethodException ex) {\r
+            return null; // the method was not found\r
+        } catch (SecurityException ex) {\r
+            return null; // setAccessible not allowed by security policy\r
+        } catch (ClassNotFoundException ex) {\r
+            return null; // the direct buffer implementation was not found\r
+        }\r
+    }\r
+\r
+    private static void loadCleanerMethods() {\r
+        // If its already true, exit, if not, set it to true.\r
+        if (BufferUtils.loadedMethods.getAndSet(true)) {\r
+            return;\r
+        }\r
+        // This could potentially be called many times if used from multiple\r
+        // threads\r
+        synchronized (BufferUtils.loadedMethods) {\r
+            // Oracle JRE / OpenJDK\r
+            cleanerMethod = loadMethod("sun.nio.ch.DirectBuffer", "cleaner");\r
+            cleanMethod = loadMethod("sun.misc.Cleaner", "clean");\r
+            viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "viewedBuffer");\r
+            if (viewedBufferMethod == null) {\r
+                // They changed the name in Java 7 (???)\r
+                viewedBufferMethod = loadMethod("sun.nio.ch.DirectBuffer", "attachment");\r
+            }\r
+\r
+            // Apache Harmony\r
+            ByteBuffer bb = BufferUtils.createByteBuffer(1);\r
+            Class<?> clazz = bb.getClass();\r
+            try {\r
+                freeMethod = clazz.getMethod("free");\r
+            } catch (NoSuchMethodException ex) {\r
+            } catch (SecurityException ex) {\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Direct buffers are garbage collected by using a phantom reference and a\r
+     * reference queue. Every once a while, the JVM checks the reference queue and\r
+     * cleans the direct buffers. However, as this doesn't happen\r
+     * immediately after discarding all references to a direct buffer, it's\r
+     * easy to OutOfMemoryError yourself using direct buffers. This function\r
+     * explicitly calls the Cleaner method of a direct buffer.\r
+     * \r
+     * @param toBeDestroyed\r
+     *          The direct buffer that will be "cleaned". Utilizes reflection.\r
+     * \r
+     */\r
+    public static void destroyDirectBuffer(Buffer toBeDestroyed) {\r
+        if (!isDirect(toBeDestroyed)) {\r
+            return;\r
+        }\r
+\r
+        BufferUtils.loadCleanerMethods();\r
+\r
+        try {\r
+            if (freeMethod != null) {\r
+                freeMethod.invoke(toBeDestroyed);\r
+            } else {\r
+                Object cleaner = cleanerMethod.invoke(toBeDestroyed);\r
+                if (cleaner != null) {\r
+                    cleanMethod.invoke(cleaner);\r
+                } else {\r
+                    // Try the alternate approach of getting the viewed buffer first\r
+                    Object viewedBuffer = viewedBufferMethod.invoke(toBeDestroyed);\r
+                    if (viewedBuffer != null) {\r
+                        destroyDirectBuffer((Buffer) viewedBuffer);\r
+                    } else {\r
+                        Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "Buffer cannot be destroyed: {0}", toBeDestroyed);\r
+                    }\r
+                }\r
+            }\r
+        } catch (IllegalAccessException ex) {\r
+            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);\r
+        } catch (IllegalArgumentException ex) {\r
+            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);\r
+        } catch (InvocationTargetException ex) {\r
+            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);\r
+        } catch (SecurityException ex) {\r
+            Logger.getLogger(BufferUtils.class.getName()).log(Level.SEVERE, "{0}", ex);\r
+        }\r
+    }\r
+    \r
+    /*\r
+     * FIXME when java 1.5 supprt is dropped - replace calls to this method with Buffer.isDirect \r
+     * \r
+     * Buffer.isDirect() is only java 6. Java 5 only have this method on Buffer subclasses : \r
+     * FloatBuffer, IntBuffer, ShortBuffer, ByteBuffer,DoubleBuffer, LongBuffer.   \r
+     * CharBuffer has been excluded as we don't use it.\r
+     * \r
+     */\r
+    private static boolean isDirect(Buffer buf) {\r
+        if (buf instanceof FloatBuffer) {\r
+            return ((FloatBuffer) buf).isDirect();\r
+        }\r
+        if (buf instanceof IntBuffer) {\r
+            return ((IntBuffer) buf).isDirect();\r
+        }\r
+        if (buf instanceof ShortBuffer) {\r
+            return ((ShortBuffer) buf).isDirect();\r
+        }\r
+        if (buf instanceof ByteBuffer) {\r
+            return ((ByteBuffer) buf).isDirect();\r
+        }\r
+        if (buf instanceof DoubleBuffer) {\r
+            return ((DoubleBuffer) buf).isDirect();\r
+        }\r
+        if (buf instanceof LongBuffer) {\r
+            return ((LongBuffer) buf).isDirect();\r
+        }\r
+        throw new UnsupportedOperationException(" BufferUtils.isDirect was called on " + buf.getClass().getName());\r
+    }\r
+\r
+    private static class BufferInfo extends PhantomReference<Buffer> {\r
+\r
+        private Class type;\r
+        private int size;\r
+\r
+        public BufferInfo(Class type, int size, Buffer referent, ReferenceQueue<? super Buffer> q) {\r
+            super(referent, q);\r
+            this.type = type;\r
+            this.size = size;\r
+        }\r
+    }\r
+\r
+    private static class ClearReferences extends Thread {\r
+\r
+        ClearReferences() {\r
+            this.setDaemon(true);\r
+        }\r
+\r
+        @Override\r
+        public void run() {\r
+            try {\r
+                while (true) {\r
+                    Reference<? extends Buffer> toclean = BufferUtils.removeCollected.remove();\r
+                    BufferUtils.trackedBuffers.remove(toclean);\r
+                }\r
+\r
+            } catch (InterruptedException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+    }\r
+}\r
index cbdb71a..544c28f 100644 (file)
@@ -877,6 +877,7 @@ public class JoglRenderer implements Renderer {
 
         uniform.clearUpdateNeeded();
         FloatBuffer fb;
+        IntBuffer ib;
         GL gl = GLContext.getCurrentGL();
         switch (uniform.getVarType()) {
             case Float:
@@ -918,6 +919,10 @@ public class JoglRenderer implements Renderer {
                 assert fb.remaining() == 16;
                 gl.getGL2ES2().glUniformMatrix4fv(loc, 1, false, fb);
                 break;
+            case IntArray:
+                ib = (IntBuffer) uniform.getValue();
+                gl.getGL2ES2().glUniform1iv(loc, ib.remaining(), ib);
+                break;
             case FloatArray:
                 fb = (FloatBuffer) uniform.getValue();
                 gl.getGL2ES2().glUniform1fv(loc, fb.remaining(), fb);
index 4434fd3..cbe7837 100644 (file)
@@ -823,6 +823,7 @@ public class LwjglRenderer implements Renderer {
 \r
         uniform.clearUpdateNeeded();\r
         FloatBuffer fb;\r
+        IntBuffer ib;\r
         switch (uniform.getVarType()) {\r
             case Float:\r
                 Float f = (Float) uniform.getValue();\r
@@ -863,6 +864,10 @@ public class LwjglRenderer implements Renderer {
                 assert fb.remaining() == 16;\r
                 glUniformMatrix4(loc, false, fb);\r
                 break;\r
+            case IntArray:\r
+                ib = (IntBuffer) uniform.getValue();\r
+                glUniform1(loc, ib);\r
+                break;\r
             case FloatArray:\r
                 fb = (FloatBuffer) uniform.getValue();\r
                 glUniform1(loc, fb);\r