From b3fb80b4e03818f1f7dfdddd1ffcb01e6a0a8acc Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Fri, 14 Mar 2014 07:50:20 +0100
Subject: Math and PMVMatrix: Cleanup and Refine

- Added final qualifier where possible

- Refined API doc

- FloatUtil:
  - Add machine EPSILON
    - fixed value and runtime computed (real machEps)
    - incl. isZero(..), isEqual(..)

  - Add makeRotationAxis(..)
    - Moved from PMVMatrix for reusage

  - Add makeRotationEuler(..)
    - New, not recommended due to Gimbal-Lock

  - Add copyMatrix[Column|Row](..)

  - Add more PI variations and trigo-func float mappings

  - Removed cross and normalize, use VectorUtil!

VectorUtil:
  - Add copyVec*
  - Add equals and isZero w/ and w/o EPSILON
  - Add distance[Square]
  - Add length[Square]

PMVMatrix:
  - Removed 'destroy' method in favor of making most fields 'final'.

AffineTransform:
  - Added AABBox transform
  - Public multiply
---
 .../classes/com/jogamp/opengl/math/FloatUtil.java  | 346 +++++++++++++++------
 .../classes/com/jogamp/opengl/math/VectorUtil.java | 253 +++++++++++----
 .../com/jogamp/opengl/math/geom/Frustum.java       |  24 +-
 .../classes/com/jogamp/opengl/util/PMVMatrix.java  | 125 ++------
 .../jogamp/graph/geom/plane/AffineTransform.java   |  78 ++++-
 src/jogl/classes/jogamp/opengl/ProjectFloat.java   |   9 +-
 .../jogamp/opengl/util/glsl/GLSLTextureRaster.java |   5 +-
 .../opengl/util/glsl/fixedfunc/FixedFuncHook.java  |   3 -
 .../test/junit/jogl/demos/es2/PointsDemoES2.java   |  55 ++--
 .../test/junit/jogl/demos/es2/RedSquareES2.java    |  55 ++--
 .../junit/jogl/demos/es2/RedSquareMappedES2.java   |   1 -
 .../jogl/demos/es2/TextureDraw01ES2Listener.java   |  89 +++---
 .../jogl/demos/es2/TextureSequenceCubeES2.java     |   5 +-
 .../test/junit/jogl/demos/es2/av/MovieSimple.java  |   1 -
 .../jogl/demos/gl3/GeomShader01TextureGL3.java     |  93 +++---
 15 files changed, 705 insertions(+), 437 deletions(-)

diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
index d2976357d..6177a6b2d 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -37,23 +37,23 @@ import com.jogamp.common.os.Platform;
  * Basic Float math utility functions.
  * <p>
  * Implementation assumes linear matrix layout in column-major order
- * matching OpenGL's implementation, translation matrix example:
+ * matching OpenGL's implementation, illustration:
  * <pre>
-   Row-Major Order:
-     1 0 0 x
-     0 1 0 y
-     0 0 1 z
-     0 0 0 1
- * </pre>
- * <pre>
-   Column-Major Order:
-     1 0 0 0
-     0 1 0 0
-     0 0 1 0
-     x y z 1
+  Row-Major                    Column-Major (OpenGL):
+
+        | 0  1  2  3  |            | 0  4  8  12 |
+        |             |            |             |
+        | 4  5  6  7  |            | 1  5  9  13 |
+    M = |             |        M = |             |
+        | 8  9  10 11 |            | 2  6  10 14 |
+        |             |            |             |
+        | 12 13 14 15 |            | 3  7  11 15 |
  * </pre>
  * </p>
  * <p>
+ * See <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a>
+ * </p>
+ * <p>
  * Derived from ProjectFloat.java - Created 11-jan-2004
  * </p>
  *
@@ -112,6 +112,92 @@ public class FloatUtil {
     m.position(oldPos);
   }
 
+  /**
+   * Make a rotation matrix from the given axis and angle in radians.
+   * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
+   */
+  public static final void makeRotationAxis(final float angrad, float x, float y, float z, final float[] mat, final int mat_offset, final float[] tmpVec3f) {
+        final float c = cos(angrad);
+        final float ic= 1.0f - c;
+        final float s = sin(angrad);
+
+        tmpVec3f[0]=x; tmpVec3f[1]=y; tmpVec3f[2]=z;
+        VectorUtil.normalize(tmpVec3f);
+        x = tmpVec3f[0]; y = tmpVec3f[1]; z = tmpVec3f[2];
+
+        // Rotation matrix (Row Order):
+        //      xx(1-c)+c  xy(1-c)+zs xz(1-c)-ys 0
+        //      xy(1-c)-zs yy(1-c)+c  yz(1-c)+xs 0
+        //      xz(1-c)+ys yz(1-c)-xs zz(1-c)+c  0
+        //      0          0          0          1
+        final float xy = x*y;
+        final float xz = x*z;
+        final float xs = x*s;
+        final float ys = y*s;
+        final float yz = y*z;
+        final float zs = z*s;
+        mat[0+0*4+mat_offset] = x*x*ic+c;
+        mat[1+0*4+mat_offset] = xy*ic+zs;
+        mat[2+0*4+mat_offset] = xz*ic-ys;
+
+        mat[0+1*4+mat_offset] = xy*ic-zs;
+        mat[1+1*4+mat_offset] = y*y*ic+c;
+        mat[2+1*4+mat_offset] = yz*ic+xs;
+
+        mat[0+2*4+mat_offset] = xz*ic+ys;
+        mat[1+2*4+mat_offset] = yz*ic-xs;
+        mat[2+2*4+mat_offset] = z*z*ic+c;
+  }
+
+  /**
+   * Make a concatenated rotation matrix in column-major order from the given Euler rotation angles in radians.
+   * <p>
+   * The rotations are applied in the given order:
+   * <ul>
+   *  <li>y - heading</li>
+   *  <li>z - attitude</li>
+   *  <li>x - bank</li>
+   * </ul>
+   * </p>
+   * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
+   * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
+   * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
+   * <p>
+   * Implementation does not use Quaternion and hence is exposed to
+   * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>
+   * </p>
+   * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
+   * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
+   */
+  public static final void makeRotationEuler(final float bankX, final float headingY, final float attitudeZ, final float[] mat, final int mat_offset) {
+      // Assuming the angles are in radians.
+      final float ch = cos(headingY);
+      final float sh = sin(headingY);
+      final float ca = cos(attitudeZ);
+      final float sa = sin(attitudeZ);
+      final float cb = cos(bankX);
+      final float sb = sin(bankX);
+
+      mat[0+0*4+mat_offset] =  ch*ca;
+      mat[0+1*4+mat_offset] =  sh*sb    - ch*sa*cb;
+      mat[0+2*4+mat_offset] =  ch*sa*sb + sh*cb;
+      mat[1+0*4+mat_offset] =  sa;
+      mat[1+1*4+mat_offset] =  ca*cb;
+      mat[1+2*4+mat_offset] = -ca*sb;
+      mat[2+0*4+mat_offset] = -sh*ca;
+      mat[2+1*4+mat_offset] =  sh*sa*cb + ch*sb;
+      mat[2+2*4+mat_offset] = -sh*sa*sb + ch*cb;
+
+      mat[3+0*4+mat_offset] =  0;
+      mat[3+1*4+mat_offset] =  0;
+      mat[3+2*4+mat_offset] =  0;
+
+      mat[0+3*4+mat_offset] =  0;
+      mat[1+3*4+mat_offset] =  0;
+      mat[2+3*4+mat_offset] =  0;
+      mat[3+3*4+mat_offset] =  1;
+  }
+
   /**
    * @param a 4x4 matrix in column-major order
    * @param b 4x4 matrix in column-major order
@@ -251,79 +337,6 @@ public class FloatUtil {
      }
   }
 
-  /**
-   * Normalize vector
-   *
-   * @param v makes len(v)==1
-   */
-  public static final void normalize(float[] v) {
-    float r = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
-
-    if ( r == 0.0 || r == 1.0) {
-      return;
-    }
-
-    r = 1.0f / r;
-
-    v[0] *= r;
-    v[1] *= r;
-    v[2] *= r;
-  }
-
-  /**
-   * Normalize vector
-   *
-   * @param v makes len(v)==1
-   */
-  public static final void normalize(FloatBuffer v) {
-    final int vPos = v.position();
-
-    float r = (float) Math.sqrt(v.get(0+vPos) * v.get(0+vPos) +
-                                v.get(1+vPos) * v.get(1+vPos) +
-                                v.get(2+vPos) * v.get(2+vPos));
-
-    if ( r == 0.0 || r == 1.0) {
-      return;
-    }
-
-    r = 1.0f / r;
-
-    v.put(0+vPos, v.get(0+vPos) * r);
-    v.put(1+vPos, v.get(1+vPos) * r);
-    v.put(2+vPos, v.get(2+vPos) * r);
-  }
-
-
-  /**
-   * Calculate cross-product of 2 vector
-   *
-   * @param v1 3-component vector
-   * @param v2 3-component vector
-   * @param result v1 X v2
-   */
-  public static final void cross(float[] v1, float[] v2, float[] result) {
-    result[0] = v1[1] * v2[2] - v1[2] * v2[1];
-    result[1] = v1[2] * v2[0] - v1[0] * v2[2];
-    result[2] = v1[0] * v2[1] - v1[1] * v2[0];
-  }
-
-  /**
-   * Calculate cross-product of 2 vector
-   *
-   * @param v1 3-component vector
-   * @param v2 3-component vector
-   * @param result v1 X v2
-   */
-  public static final void cross(FloatBuffer v1, FloatBuffer v2, FloatBuffer result) {
-    final int v1Pos = v1.position();
-    final int v2Pos = v2.position();
-    final int rPos  = result.position();
-
-    result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos));
-    result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos));
-    result.put(2+rPos, v1.get(0+v1Pos) * v2.get(1+v2Pos) - v1.get(1+v1Pos) * v2.get(0+v2Pos));
-  }
-
   /**
    * @param m_in 4x4 matrix in column-major order
    * @param m_in_off
@@ -411,6 +424,46 @@ public class FloatUtil {
     }
   }
 
+  /**
+   * Copy the named column of the given column-major matrix to v_out.
+   * <p>
+   * v_out may be 3 or 4 components long, hence the 4th row may not be stored.
+   * </p>
+   * @param m_in input column-major matrix
+   * @param m_in_off offset to input matrix
+   * @param column named column to copy
+   * @param v_out the column-vector storage, at least 3 components long
+   * @param v_out_off offset to storage
+   */
+  public static final void copyMatrixColumn(final float[] m_in, final int m_in_off, final int column, final float[] v_out, final int v_out_off) {
+      v_out[0+v_out_off]=m_in[0+column*4+m_in_off];
+      v_out[1+v_out_off]=m_in[1+column*4+m_in_off];
+      v_out[2+v_out_off]=m_in[2+column*4+m_in_off];
+      if( v_out.length > 3+v_out_off ) {
+          v_out[3+v_out_off]=m_in[3+column*4+m_in_off];
+      }
+  }
+
+  /**
+   * Copy the named row of the given column-major matrix to v_out.
+   * <p>
+   * v_out may be 3 or 4 components long, hence the 4th column may not be stored.
+   * </p>
+   * @param m_in input column-major matrix
+   * @param m_in_off offset to input matrix
+   * @param row named row to copy
+   * @param v_out the row-vector storage, at least 3 components long
+   * @param v_out_off offset to storage
+   */
+  public static final void copyMatrixRow(final float[] m_in, final int m_in_off, final int row, final float[] v_out, final int v_out_off) {
+      v_out[0+v_out_off]=m_in[row+0*4+m_in_off];
+      v_out[1+v_out_off]=m_in[row+1*4+m_in_off];
+      v_out[2+v_out_off]=m_in[row+2*4+m_in_off];
+      if( v_out.length > 3+v_out_off ) {
+          v_out[3+v_out_off]=m_in[row+3*4+m_in_off];
+      }
+  }
+
   /**
    * @param sb optional passed StringBuilder instance to be used
    * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
@@ -570,20 +623,129 @@ public class FloatUtil {
       return sb;
   }
 
+  @SuppressWarnings("unused")
+  private static void calculateMachineEpsilonFloat() {
+      final long t0;
+      if( DEBUG_EPSILON ) {
+          t0 = Platform.currentTimeMillis();
+      }
+      float machEps = 1.0f;
+      int i=0;
+      do {
+          machEps /= 2.0f;
+          i++;
+      } while (1.0f + (machEps / 2.0f) != 1.0f);
+      machEpsilon = machEps;
+      if( DEBUG_EPSILON ) {
+          final long t1 = Platform.currentTimeMillis();
+          System.err.println("MachineEpsilon: "+machEpsilon+", in "+i+" iterations within "+(t1-t0)+" ms");
+      }
+  }
+  private static volatile boolean machEpsilonAvail = false;
+  private static float machEpsilon = 0f;
+  private static final boolean DEBUG_EPSILON = false;
+
+  /**
+   * Return computed machine Epsilon value.
+   * <p>
+   * The machine Epsilon value is computed once.
+   * </p>
+   * <p>
+   * On a reference machine the result was {@link #EPSILON} in 23 iterations.
+   * </p>
+   * @see #EPSILON
+   */
+  public static float getMachineEpsilon() {
+      if( !machEpsilonAvail ) {
+          synchronized(FloatUtil.class) {
+              if( !machEpsilonAvail ) {
+                  machEpsilonAvail = true;
+                  calculateMachineEpsilonFloat();
+              }
+          }
+      }
+      return machEpsilon;
+  }
+
   public static final float E = 2.7182818284590452354f;
 
+  /** The value PI, i.e. 180 degrees in radians. */
   public static final float PI = 3.14159265358979323846f;
 
-  public static float abs(float a) { return java.lang.Math.abs(a);  }
+  /** The value 2PI, i.e. 360 degrees in radians. */
+  public static final float TWO_PI = 2f * PI;
+
+  /** The value PI/2, i.e. 90 degrees in radians. */
+  public static final float HALF_PI = PI / 2f;
+
+  /** The value PI/4, i.e. 45 degrees in radians. */
+  public static final float QUARTER_PI = PI / 4f;
+
+  /** The value PI^2. */
+  public final static float SQUARED_PI = PI * PI;
+
+  /**
+   * Epsilon for floating point {@value}, as once computed via {@link #getMachineEpsilon()} on an AMD-64 CPU.
+   * <p>
+   * Definition of machine epsilon guarantees that:
+   * <pre>
+   *        1.0f + EPSILON != 1.0f
+   * </pre>
+   * In other words: <i>machEps</i> is the maximum relative error of the chosen rounding procedure.
+   * </p>
+   * <p>
+   * A number can be considered zero if it is in the range (or in the set):
+   * <pre>
+   *    <b>MaybeZeroSet</b> e ]-<i>machEps</i> .. <i>machEps</i>[  <i>(exclusive)</i>
+   * </pre>
+   * While comparing floating point values, <i>machEps</i> allows to clip the relative error:
+   * <pre>
+   *    boolean isZero    = afloat < EPSILON;
+   *    boolean isNotZero = afloat >= EPSILON;
+   *
+   *    boolean isEqual    = abs(bfloat - afloat) < EPSILON;
+   *    boolean isNotEqual = abs(bfloat - afloat) >= EPSILON;
+   * </pre>
+   * </p>
+   * @see #equals(float, float, float)
+   * @see #isZero(float, float)
+   */
+  public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d
+
+  /**
+   * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>.
+   * @see #EPSILON
+   */
+  public static boolean equals(final float a, final float b, final float epsilon) {
+      return Math.abs(a - b) < epsilon;
+  }
+
+  /**
+   * Return true if value is zero, i.e. it's absolute value < <code>epsilon</code>.
+   * @see #EPSILON
+   */
+  public static boolean isZero(final float a, final float epsilon) {
+      return Math.abs(a) < epsilon;
+  }
+
+  public static float abs(final float a) { return java.lang.Math.abs(a);  }
+
+  public static float pow(final float a, final float b) { return (float) java.lang.Math.pow(a, b);  }
+
+  public static float sin(final float a) { return (float) java.lang.Math.sin(a);  }
+
+  public static float asin(final float a) { return (float) java.lang.Math.asin(a);  }
+
+  public static float cos(final float a) { return (float) java.lang.Math.cos(a);  }
 
-  public static float pow(float a, float b) { return (float) java.lang.Math.pow(a, b);  }
+  public static float acos(final float a) { return (float) java.lang.Math.acos(a);  }
 
-  public static float sin(float a) { return (float) java.lang.Math.sin(a);  }
+  public static float tan(final float a) { return (float) java.lang.Math.tan(a); }
 
-  public static float cos(float a) { return (float) java.lang.Math.cos(a);  }
+  public static float atan(final float a) { return (float) java.lang.Math.atan(a); }
 
-  public static float acos(float a) { return (float) java.lang.Math.acos(a);  }
+  public static float atan2(final float y, final float x) { return (float) java.lang.Math.atan2(y, x); }
 
-  public static float sqrt(float a) { return (float) java.lang.Math.sqrt(a);  }
+  public static float sqrt(final float a) { return (float) java.lang.Math.sqrt(a);  }
 
 }
\ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
index 734b7459b..ff16fba79 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -31,6 +31,9 @@ import java.util.ArrayList;
 
 public class VectorUtil {
 
+    /** Zero vector */
+    public static final float[] ZERO       = new float[] {  0f,  0f,  0f };
+
     public enum Winding {
         CW(-1), CCW(1);
 
@@ -43,41 +46,171 @@ public class VectorUtil {
 
     public static final int COLLINEAR = 0;
 
+    /**
+     * Copies a vector of length 3
+     * @param dst output vector
+     * @param dstOffset offset of dst in array
+     * @param src input vector
+     * @param srcOffset offset of src in array
+     * @return copied output vector for chaining
+     */
+    public static float[] copyVec3(final float[] dst, int dstOffset, final float[] src, int srcOffset)
+    {
+        System.arraycopy(src, srcOffset, dst, dstOffset, 3);
+        return dst;
+    }
+
+    /**
+     * Copies a vector of length 4
+     * @param dst output vector
+     * @param dstOffset offset of dst in array
+     * @param src input vector
+     * @param srcOffset offset of src in array
+     * @return copied output vector for chaining
+     */
+    public static float[] copyVec4(final float[] dst, int dstOffset, final float[] src, int srcOffset)
+    {
+        System.arraycopy(src, srcOffset, dst, dstOffset, 4);
+        return dst;
+    }
+
+    /**
+     * Return true if both vectors are equal, no {@link FloatUtil#EPSILON} is taken into consideration.
+     */
+    public static boolean equals(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset) {
+        return vec1[0+vec1Offset] == vec2[0+vec2Offset] &&
+               vec1[1+vec1Offset] == vec2[1+vec2Offset] &&
+               vec1[2+vec1Offset] == vec2[2+vec2Offset];
+    }
+
+    /**
+     * Return true if both vectors are equal, i.e. their absolute delta < <code>epsilon</code>.
+     * @see FloatUtil#EPSILON
+     */
+    public static boolean equals(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset, final float epsilon) {
+        return Math.abs(vec1[0+vec1Offset] - vec2[0+vec2Offset]) < epsilon &&
+               Math.abs(vec1[1+vec1Offset] - vec2[1+vec2Offset]) < epsilon &&
+               Math.abs(vec1[2+vec1Offset] - vec2[2+vec2Offset]) < epsilon ;
+    }
+
+    /**
+     * Return true if vector is zero, no {@link FloatUtil#EPSILON} is taken into consideration.
+     */
+    public static boolean isZero(final float[] vec, final int vecOffset) {
+        return 0f == vec[0+vecOffset] && 0f == vec[1+vecOffset] && 0f == vec[2+vecOffset];
+    }
+
+    /**
+     * Return true if vector is zero, i.e. it's absolute components < <code>epsilon</code>.
+     * @see FloatUtil#EPSILON
+     */
+    public static boolean isZero(final float[] vec, final int vecOffset, final float epsilon) {
+        return isZero(vec[0+vecOffset], vec[1+vecOffset], vec[2+vecOffset], epsilon);
+    }
+
+    /**
+     * Return true if all three vector components are zero, i.e. it's their absolute value < <code>epsilon</code>.
+     * @see FloatUtil#EPSILON
+     */
+    public static boolean isZero(final float x, final float y, final float z, final float epsilon) {
+        return Math.abs(x) < epsilon &&
+               Math.abs(y) < epsilon &&
+               Math.abs(z) < epsilon ;
+    }
+
+    /**
+     * Return the squared distance between the given two points described vector v1 and v2.
+     * <p>
+     * When comparing the relative distance between two points it is usually sufficient to compare the squared
+     * distances, thus avoiding an expensive square root operation.
+     * </p>
+     */
+    public static float distanceSquared(final float[] v1, final float[] v2) {
+        final float dx = v1[0] - v2[0];
+        final float dy = v1[1] - v2[1];
+        final float dz = v1[2] - v2[2];
+        return dx * dx + dy * dy + dz * dz;
+    }
+
+    /**
+     * Return the distance between the given two points described vector v1 and v2.
+     */
+    public static float distance(final float[] v1, final float[] v2) {
+        return FloatUtil.sqrt(distanceSquared(v1, v2));
+    }
+
     /** compute the dot product of two points
      * @param vec1 vector 1
      * @param vec2 vector 2
      * @return the dot product as float
      */
-    public static float dot(float[] vec1, float[] vec2)
+    public static float dot(final float[] vec1, final float[] vec2)
     {
         return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]);
     }
 
+    /**
+     * Compute the squared length of a vector, a.k.a the squared <i>norm</i>
+     */
+    public static float lengthSquared(final float[] vec) {
+        return vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
+    }
+    /**
+     * Compute the length of a vector, a.k.a the <i>norm</i>
+     */
+    public static float length(final float[] vec) {
+        return FloatUtil.sqrt(lengthSquared(vec));
+    }
+
     /**
      * Normalize a vector
+     * @param result output vector
      * @param vector input vector
-     * @return normalized vector
+     * @return normalized output vector
      */
-    public static float[] normalize(final float[] result, float[] vector)
-    {
-        final float d = FloatUtil.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]);
-        if(d> 0.0f)
-        {
-            result[0] = vector[0]/d;
-            result[1] = vector[1]/d;
-            result[2] = vector[2]/d;
+    public static float[] normalize(final float[] result, final float[] vector) {
+        final float lengthSq = lengthSquared(vector);
+        if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+            result[0] = 0f;
+            result[1] = 0f;
+            result[2] = 0f;
+        } else {
+            final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+            result[0] = vector[0] * invSqr;
+            result[1] = vector[1] * invSqr;
+            result[2] = vector[2] * invSqr;
         }
         return result;
     }
 
+    /**
+     * Normalize a vector in place
+     * @param result output vector
+     * @param vector input vector
+     * @return normalized output vector
+     */
+    public static float[] normalize(final float[] vector) {
+        final float lengthSq = lengthSquared(vector);
+        if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) {
+            vector[0] = 0f;
+            vector[1] = 0f;
+            vector[2] = 0f;
+        } else {
+            final float invSqr = 1f / FloatUtil.sqrt(lengthSq);
+            vector[0] *= invSqr;
+            vector[1] *= invSqr;
+            vector[2] *= invSqr;
+        }
+        return vector;
+    }
+
     /**
      * Scales a vector by param using given result float[]
      * @param result vector for the result
      * @param vector input vector
      * @param scale single scale constant for all vector components
      */
-    public static float[] scale(float[] result, float[] vector, float scale)
-    {
+    public static float[] scale(final float[] result, final float[] vector, final float scale) {
         result[0] = vector[0] * scale;
         result[1] = vector[1] * scale;
         result[2] = vector[2] * scale;
@@ -90,7 +223,7 @@ public class VectorUtil {
      * @param scale 3 component scale constant for each vector component
      * @return given result vector
      */
-    public static float[] scale(float[] result, float[] vector, float[] scale)
+    public static float[] scale(final float[] result, final float[] vector, final float[] scale)
     {
         result[0] = vector[0] * scale[0];
         result[1] = vector[1] * scale[1];
@@ -99,31 +232,42 @@ public class VectorUtil {
     }
 
     /**
-     * Adds to vectors
+     * Adds two vectors
      * @param v1 vector 1
      * @param v2 vector 2
      * @return v1 + v2
      */
-    public static float[] vectorAdd(float[] result, float[] v1, float[] v2)
-    {
+    public static float[] vectorAdd(final float[] result, final float[] v1, final float[] v2) {
         result[0] = v1[0] + v2[0];
         result[1] = v1[1] + v2[1];
         result[2] = v1[2] + v2[2];
         return result;
     }
 
+    /**
+     * Subtracts two vectors
+     * @param v1 vector 1
+     * @param v2 vector 2
+     * @return v1 - v2
+     */
+    public static float[] vectorSub(final float[] result, final float[] v1, final float[] v2) {
+        result[0] = v1[0] - v2[0];
+        result[1] = v1[1] - v2[1];
+        result[2] = v1[2] - v2[2];
+        return result;
+    }
+
     /**
      * cross product vec1 x vec2
-     * @param vec1 vector 1
-     * @param vec2 vecttor 2
+     * @param v1 vector 1
+     * @param v2 vector 2
      * @return the resulting vector
      */
-    public static float[] cross(final float[] result, float[] vec1, float[] vec2)
+    public static float[] cross(final float[] result, final float[] v1, final float[] v2)
     {
-        result[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2];
-        result[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0];
-        result[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1];
-
+        result[0] = v1[1] * v2[2] - v1[2] * v2[1];
+        result[1] = v1[2] * v2[0] - v1[0] * v2[2];
+        result[2] = v1[0] * v2[1] - v1[1] * v2[0];
         return result;
     }
 
@@ -132,7 +276,7 @@ public class VectorUtil {
      * @param vec vector(x,y,z)
      * @return result
      */
-    public static float[] colMatrixVectorMult(final float[] result, float[] colMatrix, float[] vec)
+    public static float[] colMatrixVectorMult(final float[] result, final float[] colMatrix, final float[] vec)
     {
         result[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12];
         result[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13];
@@ -146,7 +290,7 @@ public class VectorUtil {
      * @param vec vector(x,y,z)
      * @return result
      */
-    public static float[] rowMatrixVectorMult(final float[] result, float[] rawMatrix, float[] vec)
+    public static float[] rowMatrixVectorMult(final float[] result, final float[] rawMatrix, final float[] vec)
     {
         result[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3];
         result[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7];
@@ -160,7 +304,7 @@ public class VectorUtil {
      * @param p2 second vale
      * @return midpoint
      */
-    public static float mid(float p1, float p2)
+    public static float mid(final float p1, final float p2)
     {
         return (p1+p2)/2.0f;
     }
@@ -171,7 +315,7 @@ public class VectorUtil {
      * @param p2 second point
      * @return midpoint
      */
-    public static float[] mid(final float[] result, float[] p1, float[] p2)
+    public static float[] mid(final float[] result, final float[] p1, final float[] p2)
     {
         result[0] = (p1[0] + p2[0])*0.5f;
         result[1] = (p1[1] + p2[1])*0.5f;
@@ -180,22 +324,13 @@ public class VectorUtil {
         return result;
     }
 
-    /** Compute the norm of a vector
-     * @param vec vector
-     * @return vorm
-     */
-    public static float norm(float[] vec)
-    {
-        return FloatUtil.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
-    }
-
     /** Compute distance between 2 points
      * @param p0 a ref point on the line
      * @param vec vector representing the direction of the line
      * @param point the point to compute the relative distance of
      * @return distance float
      */
-    public static float computeLength(float[] p0, float[] point)
+    public static float computeLength(final float[] p0, final float[] point)
     {
         final float w0 = point[0]-p0[0];
         final float w1 = point[1]-p0[1];
@@ -209,7 +344,7 @@ public class VectorUtil {
      * @param v2 vertex 2
      * @return
      */
-    public static boolean checkEquality(float[] v1, float[] v2)
+    public static boolean checkEquality(final float[] v1, final float[] v2)
     {
         return Float.compare(v1[0], v2[0]) == 0 &&
                Float.compare(v1[1], v2[1]) == 0 &&
@@ -221,7 +356,7 @@ public class VectorUtil {
      * @param v2 vertex 2
      * @return
      */
-    public static boolean checkEqualityVec2(float[] v1, float[] v2)
+    public static boolean checkEqualityVec2(final float[] v1, final float[] v2)
     {
         return Float.compare(v1[0], v2[0]) == 0 &&
                Float.compare(v1[1], v2[1]) == 0 ;
@@ -233,7 +368,7 @@ public class VectorUtil {
      * @param c vector 3
      * @return the determinant value
      */
-    public static float computeDeterminant(float[] a, float[] b, float[] c)
+    public static float computeDeterminant(final float[] a, final float[] b, final float[] c)
     {
         return a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0];
     }
@@ -244,7 +379,7 @@ public class VectorUtil {
      * @param v3 vertex 3
      * @return true if collinear, false otherwise
      */
-    public static boolean checkCollinear(float[] v1, float[] v2, float[] v3)
+    public static boolean checkCollinear(final float[] v1, final float[] v2, final float[] v3)
     {
         return (computeDeterminant(v1, v2, v3) == VectorUtil.COLLINEAR);
     }
@@ -254,7 +389,7 @@ public class VectorUtil {
      * @param v1 vertex 1
      * @param v2 vertex2 2
      */
-    public static void computeVector(float[] vector, float[] v1, float[] v2) {
+    public static void computeVector(final float[] vector, final float[] v1, final float[] v2) {
         vector[0] = v2[0] - v1[0];
         vector[1] = v2[1] - v1[1];
         vector[2] = v2[2] - v1[2];
@@ -268,7 +403,7 @@ public class VectorUtil {
      * @return true if the vertex d is inside the circle defined by the
      * vertices a, b, c. from paper by Guibas and Stolfi (1985).
      */
-    public static boolean inCircle(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
+    public static boolean inCircle(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) {
         final float[] A = a.getCoord();
         final float[] B = b.getCoord();
         final float[] C = c.getCoord();
@@ -286,7 +421,7 @@ public class VectorUtil {
      * @return compute twice the area of the oriented triangle (a,b,c), the area
      * is positive if the triangle is oriented counterclockwise.
      */
-    public static float triArea(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c){
+    public static float triArea(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c){
         final float[] A = a.getCoord();
         final float[] B = b.getCoord();
         final float[] C = c.getCoord();
@@ -300,7 +435,7 @@ public class VectorUtil {
      * @return compute twice the area of the oriented triangle (a,b,c), the area
      * is positive if the triangle is oriented counterclockwise.
      */
-    public static float triArea(float[] A, float[] B, float[] C){
+    public static float triArea(final float[] A, final float[] B, final float[] C){
         return (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1])*(C[0] - A[0]);
     }
 
@@ -312,9 +447,9 @@ public class VectorUtil {
      * @param p the vertex in question
      * @return true if p is in triangle (a, b, c), false otherwise.
      */
-    public static boolean vertexInTriangle(float[] a, float[]  b, float[]  c,
-                                           float[] p,
-                                           float[] ac, float[] ab, float[] ap){
+    public static boolean vertexInTriangle(final float[] a, final float[]  b, final float[]  c,
+                                           final float[] p,
+                                           final float[] ac, final float[] ab, final float[] ap){
         // Compute vectors
         computeVector(ac, a, c); //v0
         computeVector(ab, a, b); //v1
@@ -350,9 +485,9 @@ public class VectorUtil {
      * @param tmpAP
      * @return true if p1 or p2 or p3 is in triangle (a, b, c), false otherwise.
      */
-    public static boolean vertexInTriangle3(float[] a, float[]  b, float[]  c,
-                                            float[] p1, float[] p2, float[] p3,
-                                            float[] tmpAC, float[] tmpAB, float[] tmpAP){
+    public static boolean vertexInTriangle3(final float[] a, final float[]  b, final float[]  c,
+                                            final float[] p1, final float[] p2, final float[] p3,
+                                            final float[] tmpAC, final float[] tmpAB, final float[] tmpAP){
         // Compute vectors
         computeVector(tmpAC, a, c); //v0
         computeVector(tmpAB, a, b); //v1
@@ -412,7 +547,7 @@ public class VectorUtil {
      * @param c third vertex
      * @return true if the points a,b,c are in a ccw order
      */
-    public static boolean ccw(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c){
+    public static boolean ccw(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c){
         return triArea(a,b,c) > 0;
     }
 
@@ -422,7 +557,7 @@ public class VectorUtil {
      * @param c third vertex
      * @return Winding
      */
-    public static Winding getWinding(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c) {
+    public static Winding getWinding(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c) {
         return triArea(a,b,c) > 0 ? Winding.CCW : Winding.CW ;
     }
 
@@ -430,7 +565,7 @@ public class VectorUtil {
      * @param vertices
      * @return positive area if ccw else negative area value
      */
-    public static float area(ArrayList<? extends Vert2fImmutable> vertices) {
+    public static float area(final ArrayList<? extends Vert2fImmutable> vertices) {
         final int n = vertices.size();
         float area = 0.0f;
         for (int p = n - 1, q = 0; q < n; p = q++)
@@ -446,7 +581,7 @@ public class VectorUtil {
      * @param vertices array of Vertices
      * @return CCW or CW {@link Winding}
      */
-    public static Winding getWinding(ArrayList<? extends Vert2fImmutable> vertices) {
+    public static Winding getWinding(final ArrayList<? extends Vert2fImmutable> vertices) {
         return area(vertices) >= 0 ? Winding.CCW : Winding.CW ;
     }
 
@@ -458,7 +593,7 @@ public class VectorUtil {
      * @param d vertex 2 of second segment
      * @return the intersection coordinates if the segments intersect, otherwise returns null
      */
-    public static float[] seg2SegIntersection(final float[] result, Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
+    public static float[] seg2SegIntersection(final float[] result, final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) {
         final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
 
         if (determinant == 0)
@@ -487,7 +622,7 @@ public class VectorUtil {
      * @param d vertex 2 of second segment
      * @return true if the segments intersect, otherwise returns false
      */
-    public static boolean testSeg2SegIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
+    public static boolean testSeg2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) {
         final float[] A = a.getCoord();
         final float[] B = b.getCoord();
         final float[] C = c.getCoord();
@@ -520,7 +655,7 @@ public class VectorUtil {
      * @return the intersection coordinates if the lines intersect, otherwise
      * returns null
      */
-    public static float[] line2lineIntersection(final float[] result, Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d) {
+    public static float[] line2lineIntersection(final float[] result, final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) {
         final float determinant = (a.getX()-b.getX())*(c.getY()-d.getY()) - (a.getY()-b.getY())*(c.getX()-d.getX());
 
         if (determinant == 0)
@@ -545,7 +680,7 @@ public class VectorUtil {
      * @param e vertex 2 of first segment
      * @return true if the segment intersects at least one segment of the triangle, false otherwise
      */
-    public static boolean testTri2SegIntersection(Vert2fImmutable a, Vert2fImmutable b, Vert2fImmutable c, Vert2fImmutable d, Vert2fImmutable e){
+    public static boolean testTri2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d, final Vert2fImmutable e){
         return testSeg2SegIntersection(a, b, d, e) ||
                testSeg2SegIntersection(b, c, d, e) ||
                testSeg2SegIntersection(a, c, d, e) ;
diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java
index fb311083f..8b4eba222 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java
@@ -186,8 +186,8 @@ public class Frustum {
      * </p>
      */
     public void updateByPMV(float[] pmv, int pmv_off) {
-        // Left:   a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14  - [1..4] row-major
-        // Left:   a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03  - [0..3] row-major
+        // Left:   a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14  - [1..4] column-major
+        // Left:   a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03  - [0..3] column-major
         {
             final Plane p = planes[LEFT];
             final float[] p_n = p.n;
@@ -197,8 +197,8 @@ public class Frustum {
             p.d    = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 0 + 3 * 4 ];
         }
 
-        // Right:  a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14  - [1..4] row-major
-        // Right:  a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03  - [0..3] row-major
+        // Right:  a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14  - [1..4] column-major
+        // Right:  a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03  - [0..3] column-major
         {
             final Plane p = planes[RIGHT];
             final float[] p_n = p.n;
@@ -208,8 +208,8 @@ public class Frustum {
             p.d    = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 0 + 3 * 4 ];
         }
 
-        // Bottom: a = m41 + m21, b = m42 + m22, c = m43 + m23, d = m44 + m24  - [1..4] row-major
-        // Bottom: a = m30 + m10, b = m31 + m11, c = m32 + m12, d = m33 + m13  - [0..3] row-major
+        // Bottom: a = m41 + m21, b = m42 + m22, c = m43 + m23, d = m44 + m24  - [1..4] column-major
+        // Bottom: a = m30 + m10, b = m31 + m11, c = m32 + m12, d = m33 + m13  - [0..3] column-major
         {
             final Plane p = planes[BOTTOM];
             final float[] p_n = p.n;
@@ -219,8 +219,8 @@ public class Frustum {
             p.d    = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 1 + 3 * 4 ];
         }
 
-        // Top:   a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24  - [1..4] row-major
-        // Top:   a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13  - [0..3] row-major
+        // Top:   a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24  - [1..4] column-major
+        // Top:   a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13  - [0..3] column-major
         {
             final Plane p = planes[TOP];
             final float[] p_n = p.n;
@@ -230,8 +230,8 @@ public class Frustum {
             p.d    = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 1 + 3 * 4 ];
         }
 
-        // Near:  a = m41 + m31, b = m42 + m32, c = m43 + m33, d = m44 + m34  - [1..4] row-major
-        // Near:  a = m30 + m20, b = m31 + m21, c = m32 + m22, d = m33 + m23  - [0..3] row-major
+        // Near:  a = m41 + m31, b = m42 + m32, c = m43 + m33, d = m44 + m34  - [1..4] column-major
+        // Near:  a = m30 + m20, b = m31 + m21, c = m32 + m22, d = m33 + m23  - [0..3] column-major
         {
             final Plane p = planes[NEAR];
             final float[] p_n = p.n;
@@ -241,8 +241,8 @@ public class Frustum {
             p.d    = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 2 + 3 * 4 ];
         }
 
-        // Far:   a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34  - [1..4] row-major
-        // Far:   a = m30 - m20, b = m31 - m21, c = m32 + m22, d = m33 + m23  - [0..3] row-major
+        // Far:   a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34  - [1..4] column-major
+        // Far:   a = m30 - m20, b = m31 - m21, c = m32 + m22, d = m33 + m23  - [0..3] column-major
         {
             final Plane p = planes[FAR];
             final float[] p_n = p.n;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
index 270bf34f6..2001f8cdf 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java
@@ -247,10 +247,11 @@ public class PMVMatrix implements GLMatrixFunc {
           }
           FloatUtil.makeIdentityf(matrixIdent);
 
-          vec3f         = new float[3];
+          tmpVec3f      = new float[3];
+          tmpMatrix     = new float[16];
+          matrixRot     = new float[16];
           matrixMult    = new float[16];
           matrixTrans   = new float[16];
-          matrixRot     = new float[16];
           matrixScale   = new float[16];
           matrixOrtho   = new float[16];
           matrixFrustum = new float[16];
@@ -277,45 +278,12 @@ public class PMVMatrix implements GLMatrixFunc {
           requestMask = 0;
           matrixMode = GL_MODELVIEW;
 
-          mulPMV = null;
           frustum = null;
     }
 
     /** @see #PMVMatrix(boolean) */
     public final boolean usesBackingArray() { return usesBackingArray; }
 
-    public final void destroy() {
-        if(null!=projectFloat) {
-            projectFloat.destroy(); projectFloat=null;
-        }
-
-        matrixBuffer=null;
-        matrixBuffer=null; matrixPMvMvit=null; matrixPMvMvi=null; matrixPMv=null;
-        matrixP=null; matrixTex=null; matrixMv=null; matrixMvi=null; matrixMvit=null;
-
-        vec3f         = null;
-        matrixMult    = null;
-        matrixTrans   = null;
-        matrixRot     = null;
-        matrixScale   = null;
-        matrixOrtho   = null;
-        matrixFrustum = null;
-
-        if(null!=matrixPStack) {
-            matrixPStack=null;
-        }
-        if(null!=matrixMvStack) {
-            matrixMvStack=null;
-        }
-        if(null!=matrixPStack) {
-            matrixPStack=null;
-        }
-        if(null!=matrixTStack) {
-            matrixTStack=null;
-        }
-    }
-
-
     /** Returns the current matrix-mode, one of {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE}. */
     public final int  glGetMatrixMode() {
         return matrixMode;
@@ -651,11 +619,11 @@ public class PMVMatrix implements GLMatrixFunc {
 
     @Override
     public final void glTranslatef(final float x, final float y, final float z) {
-        // Translation matrix:
-        //  1 0 0 x
-        //  0 1 0 y
-        //  0 0 1 z
-        //  0 0 0 1
+        // Translation matrix (Column Order):
+        //  1 0 0 0
+        //  0 1 0 0
+        //  0 0 1 0
+        //  x y z 1
         matrixTrans[0+4*3] = x;
         matrixTrans[1+4*3] = y;
         matrixTrans[2+4*3] = z;
@@ -663,45 +631,15 @@ public class PMVMatrix implements GLMatrixFunc {
     }
 
     @Override
-    public final void glRotatef(final float angdeg, float x, float y, float z) {
-        final float angrad = angdeg   * (float) Math.PI / 180.0f;
-        final float c = (float)Math.cos(angrad);
-        final float ic= 1.0f - c;
-        final float s = (float)Math.sin(angrad);
-
-        vec3f[0]=x; vec3f[1]=y; vec3f[2]=z;
-        FloatUtil.normalize(vec3f);
-        x = vec3f[0]; y = vec3f[1]; z = vec3f[2];
-
-        // Rotation matrix:
-        //      xx(1-c)+c  xy(1-c)+zs xz(1-c)-ys 0
-        //      xy(1-c)-zs yy(1-c)+c  yz(1-c)+xs 0
-        //      xz(1-c)+ys yz(1-c)-xs zz(1-c)+c  0
-        //      0          0          0          1
-        final float xy = x*y;
-        final float xz = x*z;
-        final float xs = x*s;
-        final float ys = y*s;
-        final float yz = y*z;
-        final float zs = z*s;
-        matrixRot[0*4+0] = x*x*ic+c;
-        matrixRot[0*4+1] = xy*ic+zs;
-        matrixRot[0*4+2] = xz*ic-ys;
-
-        matrixRot[1*4+0] = xy*ic-zs;
-        matrixRot[1*4+1] = y*y*ic+c;
-        matrixRot[1*4+2] = yz*ic+xs;
-
-        matrixRot[2*4+0] = xz*ic+ys;
-        matrixRot[2*4+1] = yz*ic-xs;
-        matrixRot[2*4+2] = z*z*ic+c;
-
+    public final void glRotatef(final float angdeg, final float x, final float y, final float z) {
+        final float angrad = angdeg   * FloatUtil.PI / 180.0f;
+        FloatUtil.makeRotationAxis(angrad, x, y, z, matrixRot, 0, tmpVec3f);
         glMultMatrixf(matrixRot, 0);
     }
 
     @Override
     public final void glScalef(final float x, final float y, final float z) {
-        // Scale matrix:
+        // Scale matrix (Any Order):
         //  x 0 0 0
         //  0 y 0 0
         //  0 0 z 0
@@ -715,11 +653,11 @@ public class PMVMatrix implements GLMatrixFunc {
 
     @Override
     public final void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) {
-        // Ortho matrix:
-        //  2/dx  0     0    tx
-        //  0     2/dy  0    ty
-        //  0     0     2/dz tz
-        //  0     0     0    1
+        // Ortho matrix (Column Order):
+        //  2/dx  0     0    0
+        //  0     2/dy  0    0
+        //  0     0     2/dz 0
+        //  tx    ty    tz   1
         final float dx=right-left;
         final float dy=top-bottom;
         final float dz=zFar-zNear;
@@ -745,11 +683,11 @@ public class PMVMatrix implements GLMatrixFunc {
         if(left==right || top==bottom) {
             throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal");
         }
-        // Frustum matrix:
-        //  2*zNear/dx   0          A  0
-        //  0            2*zNear/dy B  0
-        //  0            0          C  D
-        //  0            0         -1  0
+        // Frustum matrix (Column Order):
+        //  2*zNear/dx   0          0   0
+        //  0            2*zNear/dy 0   0
+        //  A            B          C  -1
+        //  0            0          D   0
         final float zNear2 = 2.0f*zNear;
         final float dx=right-left;
         final float dy=top-bottom;
@@ -1041,10 +979,9 @@ public class PMVMatrix implements GLMatrixFunc {
         if( 0 != ( dirtyBits & ( DIRTY_FRUSTUM & requestMask ) ) ) {
             if( null == frustum ) {
                 frustum = new Frustum();
-                mulPMV = new float[16];
             }
-            FloatUtil.multMatrixf(matrixP, matrixMv, mulPMV, 0);
-            frustum.updateByPMV(mulPMV, 0);
+            FloatUtil.multMatrixf(matrixP, matrixMv, tmpMatrix, 0);
+            frustum.updateByPMV(tmpMatrix, 0);
             dirtyBits &= ~DIRTY_FRUSTUM;
             mod = true;
         }
@@ -1118,17 +1055,17 @@ public class PMVMatrix implements GLMatrixFunc {
         return res;
     }
 
-    protected final float[] matrixBufferArray;
     protected final boolean usesBackingArray;
-    protected Buffer matrixBuffer;
-    protected FloatBuffer matrixIdent, matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit;
-    protected float[] matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum, vec3f;
-    protected FloatStack matrixTStack, matrixPStack, matrixMvStack;
+    protected final float[] matrixBufferArray;
+    protected final Buffer matrixBuffer;
+    protected final FloatBuffer matrixIdent, matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit;
+    protected final float[] matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum, tmpVec3f;
+    protected final float[] tmpMatrix;
+    protected final FloatStack matrixTStack, matrixPStack, matrixMvStack;
+    protected final ProjectFloat projectFloat;
     protected int matrixMode = GL_MODELVIEW;
     protected int modifiedBits = MODIFIED_ALL;
     protected int dirtyBits = DIRTY_ALL; // contains the dirty bits, i.e. hinting for update operation
     protected int requestMask = 0; // may contain the requested dirty bits: DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW
-    protected ProjectFloat projectFloat;
-    protected float[] mulPMV; // premultiplied PMV
     protected Frustum frustum;
 }
diff --git a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
index 621802c36..362c29204 100644
--- a/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
+++ b/src/jogl/classes/jogamp/graph/geom/plane/AffineTransform.java
@@ -24,6 +24,7 @@ package jogamp.graph.geom.plane;
 import com.jogamp.graph.geom.Vertex;
 import com.jogamp.graph.geom.Vertex.Factory;
 import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.AABBox;
 
 public class AffineTransform implements Cloneable {
 
@@ -355,27 +356,63 @@ public class AffineTransform implements Cloneable {
     /**
      * Multiply matrix of two AffineTransform objects.
      * The first argument's {@link Vertex.Factory} is being used.
+     * @param tL - the AffineTransform object is a multiplicand (left argument)
+     * @param tR - the AffineTransform object is a multiplier (right argument)
      *
-     * @param t1 - the AffineTransform object is a multiplicand
-     * @param t2 - the AffineTransform object is a multiplier
-     * @return an AffineTransform object that is a result of t1 multiplied by matrix t2.
+     * @return A new AffineTransform object containing the result of [tL] X [tR].
      */
-    AffineTransform multiply(AffineTransform t1, AffineTransform t2) {
-        return new AffineTransform(t1.pointFactory,
-                t1.m00 * t2.m00 + t1.m10 * t2.m01,          // m00
-                t1.m00 * t2.m10 + t1.m10 * t2.m11,          // m01
-                t1.m01 * t2.m00 + t1.m11 * t2.m01,          // m10
-                t1.m01 * t2.m10 + t1.m11 * t2.m11,          // m11
-                t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02
-                t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12);// m12
+    public final static AffineTransform multiply(final AffineTransform tL, final AffineTransform tR) {
+        return new AffineTransform(tR.pointFactory,
+                tR.m00 * tL.m00 + tR.m10 * tL.m01,          // m00
+                tR.m00 * tL.m10 + tR.m10 * tL.m11,          // m10
+                tR.m01 * tL.m00 + tR.m11 * tL.m01,          // m01
+                tR.m01 * tL.m10 + tR.m11 * tL.m11,          // m11
+                tR.m02 * tL.m00 + tR.m12 * tL.m01 + tL.m02, // m02
+                tR.m02 * tL.m10 + tR.m12 * tL.m11 + tL.m12);// m12
     }
 
-    public final void concatenate(AffineTransform t) {
-        setTransform(multiply(t, this));
+    /**
+     * Concatenates the given matrix to this.
+     * <p>
+     * Implementations performs the matrix multiplication:
+     * <pre>
+     *   [this] = [this] X [tR]
+     * </pre>
+     * </p>
+     * @param tR the right-argument of the matrix multiplication
+     */
+    public final void concatenate(AffineTransform tR) {
+        // setTransform(multiply(this, tR));
+        type = TYPE_UNKNOWN;
+        setTransform(
+                tR.m00 * m00 + tR.m10 * m01,       // m00
+                tR.m00 * m10 + tR.m10 * m11,       // m10
+                tR.m01 * m00 + tR.m11 * m01,       // m01
+                tR.m01 * m10 + tR.m11 * m11,       // m11
+                tR.m02 * m00 + tR.m12 * m01 + m02, // m02
+                tR.m02 * m10 + tR.m12 * m11 + m12);// m12
     }
 
-    public final void preConcatenate(AffineTransform t) {
-        setTransform(multiply(this, t));
+    /**
+     * Pre-concatenates the given matrix to this.
+     * <p>
+     * Implementations performs the matrix multiplication:
+     * <pre>
+     *   [this] = [tL] X [this]
+     * </pre>
+     * </p>
+     * @param tL the left-argument of the matrix multiplication
+     */
+    public final void preConcatenate(AffineTransform tL) {
+        // setTransform(multiply(tL, this));
+        type = TYPE_UNKNOWN;
+        setTransform(
+                m00 * tL.m00 + m10 * tL.m01,          // m00
+                m00 * tL.m10 + m10 * tL.m11,          // m10
+                m01 * tL.m00 + m11 * tL.m01,          // m01
+                m01 * tL.m10 + m11 * tL.m11,          // m11
+                m02 * tL.m00 + m12 * tL.m01 + tL.m02, // m02
+                m02 * tL.m10 + m12 * tL.m11 + tL.m12);// m12
     }
 
     public final AffineTransform createInverse() throws NoninvertibleTransformException {
@@ -394,6 +431,17 @@ public class AffineTransform implements Cloneable {
         );
     }
 
+    public final AABBox transform(final AABBox src, AABBox dst) {
+        if (dst == null) {
+            dst = new AABBox();
+        }
+        final float[] srcLo = src.getLow();
+        final float[] srcHi = src.getHigh();
+        dst.setSize(srcLo[0] * m00 + srcLo[1] * m01 + m02, srcLo[0] * m10 + srcLo[1] * m11 + m12, srcLo[2],
+                    srcHi[0] * m00 + srcHi[1] * m01 + m02, srcHi[0] * m10 + srcHi[1] * m11 + m12, srcHi[2]);
+        return dst;
+    }
+
     public final Vertex transform(final Vertex src, Vertex dst) {
         if (dst == null) {
             dst = pointFactory.create(src.getId(), src.isOnCurve(), src.getTexCoord());
diff --git a/src/jogl/classes/jogamp/opengl/ProjectFloat.java b/src/jogl/classes/jogamp/opengl/ProjectFloat.java
index d4fd1c935..80c142429 100644
--- a/src/jogl/classes/jogamp/opengl/ProjectFloat.java
+++ b/src/jogl/classes/jogamp/opengl/ProjectFloat.java
@@ -123,6 +123,7 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
 
 import com.jogamp.common.nio.Buffers;
 import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.VectorUtil;
 
 /**
  * ProjectFloat.java
@@ -407,14 +408,14 @@ public class ProjectFloat {
     up[1] = upy;
     up[2] = upz;
 
-    FloatUtil.normalize(forward);
+    VectorUtil.normalize(forward);
 
     /* Side = forward x up */
-    FloatUtil.cross(forward, up, side);
-    FloatUtil.normalize(side);
+    VectorUtil.cross(side, forward, up);
+    VectorUtil.normalize(side);
 
     /* Recompute up as: up = side x forward */
-    FloatUtil.cross(side, forward, up);
+    VectorUtil.cross(up, side, forward);
 
     FloatUtil.makeIdentityf(matrixBuf);
     final int mPos = matrixBuf.position();
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
index dba408554..09da8c9ee 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
@@ -147,10 +147,7 @@ public class GLSLTextureRaster  {
         if(null != pmvMatrixUniform) {
             pmvMatrixUniform = null;
         }
-        if(null != pmvMatrix) {
-            pmvMatrix.destroy();
-            pmvMatrix=null;
-        }
+        pmvMatrix=null;
         if(null != interleavedVBO) {
             interleavedVBO.destroy(gl);
             interleavedVBO=null;
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
index 458a9c94f..ff8006cf8 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
@@ -101,9 +101,6 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
     public void destroy() {
         fixedFunction.destroy(gl);
         fixedFunction = null;
-        if(ownsPMVMatrix) {
-            pmvMatrix.destroy();
-        }
         pmvMatrix=null;
         gl=null;
     }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
index 52af4916c..573c91636 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
@@ -54,9 +54,9 @@ public class PointsDemoES2 extends PointsDemo {
     final int edge = 8; // 8*8
     /** vec4[2]: { (sz, smooth, attnMinSz, attnMaxSz), (attnCoeff(3), attnFadeTs) } */
     private static final String mgl_PointParams     = "mgl_PointParams";
-    
+
     /** ( pointSize, pointSmooth, attn. pointMinSize, attn. pointMaxSize ) , ( attenuation coefficients 1f 0f 0f, attenuation fade theshold 1f )   */
-    private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] {  1.0f, 0.0f, 0.0f, 4096.0f, 1.0f, 0.0f, 0.0f, 1.0f }); 
+    private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] {  1.0f, 0.0f, 0.0f, 4096.0f, 1.0f, 0.0f, 0.0f, 1.0f });
 
     public PointsDemoES2(int swapInterval) {
         this.swapInterval = swapInterval;
@@ -65,29 +65,29 @@ public class PointsDemoES2 extends PointsDemo {
     public PointsDemoES2() {
         this.swapInterval = 1;
     }
-    
-    public void setSmoothPoints(boolean v) { 
-        pointParams.put(1, v ? 1.0f : 0.0f); 
+
+    public void setSmoothPoints(boolean v) {
+        pointParams.put(1, v ? 1.0f : 0.0f);
     }
-        
+
     public void setPointParams(float minSize, float maxSize, float distAttenConst, float distAttenLinear, float distAttenQuadratic, float fadeThreshold) {
         pointParams.put(2, minSize);
         pointParams.put(3, maxSize);
         pointParams.put(4+0, distAttenConst);
         pointParams.put(4+1, distAttenLinear);
         pointParams.put(4+2, distAttenQuadratic);
-        pointParams.put(4+3, fadeThreshold);        
+        pointParams.put(4+3, fadeThreshold);
     }
-    
+
     public void init(GLAutoDrawable glad) {
         GL2ES2 gl = glad.getGL().getGL2ES2();
-        
+
         System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
         System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
         System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
         System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
         System.err.println("GL Profile: "+gl.getGLProfile());
-        
+
         st = new ShaderState();
         st.setVerbose(true);
         final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
@@ -100,23 +100,23 @@ public class PointsDemoES2 extends PointsDemo {
         sp0.add(gl, vp0, System.err);
         sp0.add(gl, fp0, System.err);
         st.attachShaderProgram(gl, sp0, true);
-        
+
         // setup mgl_PMVMatrix
         pmvMatrix = new PMVMatrix();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
         pmvMatrix.glLoadIdentity();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
-        pmvMatrix.glLoadIdentity();       
+        pmvMatrix.glLoadIdentity();
         pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
         st.ownUniform(pmvMatrixUniform);
-        st.uniform(gl, pmvMatrixUniform);        
-        
+        st.uniform(gl, pmvMatrixUniform);
+
         st.uniform(gl, new GLUniformData(mgl_PointParams, 4, pointParams));
-        
+
         final GLUniformData colorStaticUniform = new GLUniformData("mgl_ColorStatic", 4, Buffers.newDirectFloatBuffer(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }) );
         st.uniform(gl, colorStaticUniform);
         st.ownUniform(colorStaticUniform);
-        
+
         // Allocate Vertex Array
         vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
         pointSizes = GLArrayDataServer.createGLSL("mgl_PointSize", 1, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
@@ -139,7 +139,7 @@ public class PointsDemoES2 extends PointsDemo {
 
         // OpenGL Render Settings
         gl.glEnable(GL2ES2.GL_DEPTH_TEST);
-        st.useProgram(gl, false);        
+        st.useProgram(gl, false);
     }
 
     public void display(GLAutoDrawable glad) {
@@ -150,17 +150,17 @@ public class PointsDemoES2 extends PointsDemo {
         pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
         pmvMatrix.glLoadIdentity();
         pmvMatrix.glTranslatef(0, 0, -10);
-        st.uniform(gl, pmvMatrixUniform);        
+        st.uniform(gl, pmvMatrixUniform);
 
         GLUniformData ud = st.getUniform(mgl_PointParams);
         if(null!=ud) {
-            // same data object 
+            // same data object
             st.uniform(gl, ud);
         }
-        
+
         vertices.enableBuffer(gl, true);
         pointSizes.enableBuffer(gl, true);
-        
+
         if(gl.isGL2GL3()) {
             gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
         }
@@ -171,11 +171,11 @@ public class PointsDemoES2 extends PointsDemo {
         gl.glBlendFunc ( GL.GL_SRC_ALPHA, GL.GL_ONE );
 
         gl.glDrawArrays(GL.GL_POINTS, 0, edge*edge);
-        
+
         if(gl.isGL2GL3()) {
             gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
         }
-        
+
         pointSizes.enableBuffer(gl, false);
         vertices.enableBuffer(gl, false);
         st.useProgram(gl, false);
@@ -184,11 +184,11 @@ public class PointsDemoES2 extends PointsDemo {
     public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
         // Thread.dumpStack();
         GL2ES2 gl = glad.getGL().getGL2ES2();
-        
-        if(-1 != swapInterval) {        
+
+        if(-1 != swapInterval) {
             gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
         }
-        
+
         st.useProgram(gl, true);
         // Set location in front of camera
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
@@ -203,7 +203,6 @@ public class PointsDemoES2 extends PointsDemo {
         GL2ES2 gl = glad.getGL().getGL2ES2();
         st.destroy(gl);
         st = null;
-        pmvMatrix.destroy();
         pmvMatrix = null;
-    }    
+    }
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
index 715a97d63..9f850c35b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
@@ -62,17 +62,17 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
     public RedSquareES2() {
         this.swapInterval = 1;
     }
-        
+
     @Override
     public void addTileRendererNotify(TileRendererBase tr) {
         tileRendererInUse = tr;
         doRotateBeforePrinting = doRotate;
-        setDoRotation(false);      
+        setDoRotation(false);
     }
     @Override
     public void removeTileRendererNotify(TileRendererBase tr) {
         tileRendererInUse = null;
-        setDoRotation(doRotateBeforePrinting);      
+        setDoRotation(doRotateBeforePrinting);
     }
     @Override
     public void startTileRendering(TileRendererBase tr) {
@@ -82,16 +82,16 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
     public void endTileRendering(TileRendererBase tr) {
         System.err.println("RedSquareES2.endTileRendering: "+tr);
     }
-    
+
     public void setAspect(float aspect) { this.aspect = aspect; }
     public void setDoRotation(boolean rotate) { this.doRotate = rotate; }
     public void setClearBuffers(boolean v) { clearBuffers = v; }
-    
+
     @Override
     public void init(GLAutoDrawable glad) {
         System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse);
         final GL2ES2 gl = glad.getGL().getGL2ES2();
-        
+
         System.err.println("RedSquareES2 init on "+Thread.currentThread());
         System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities());
         System.err.println("INIT GL IS: " + gl.getClass().getName());
@@ -112,17 +112,17 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
         sp0.add(gl, vp0, System.err);
         sp0.add(gl, fp0, System.err);
         st.attachShaderProgram(gl, sp0, true);
-        
+
         // setup mgl_PMVMatrix
         pmvMatrix = new PMVMatrix();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
         pmvMatrix.glLoadIdentity();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
-        pmvMatrix.glLoadIdentity();       
+        pmvMatrix.glLoadIdentity();
         pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
         st.ownUniform(pmvMatrixUniform);
-        st.uniform(gl, pmvMatrixUniform);        
-        
+        st.uniform(gl, pmvMatrixUniform);
+
         // Allocate Vertex Array
         vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
         vertices.putf(-2); vertices.putf( 2); vertices.putf( 0);
@@ -132,20 +132,20 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
         vertices.seal(gl, true);
         st.ownAttribute(vertices, true);
         vertices.enableBuffer(gl, false);
-        
+
         // Allocate Color Array
         colors= GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
         colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
         colors.putf(0); colors.putf(0); colors.putf(1); colors.putf(1);
         colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
         colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
-        colors.seal(gl, true);          
+        colors.seal(gl, true);
         st.ownAttribute(colors, true);
         colors.enableBuffer(gl, false);
-        
+
         // OpenGL Render Settings
         gl.glEnable(GL2ES2.GL_DEPTH_TEST);
-        st.useProgram(gl, false);        
+        st.useProgram(gl, false);
 
         t0 = System.currentTimeMillis();
         System.err.println(Thread.currentThread()+" RedSquareES2.init FIN");
@@ -173,11 +173,11 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
         pmvMatrix.glLoadIdentity();
         pmvMatrix.glTranslatef(0, 0, -10);
         if(doRotate) {
-            float ang = ((float) (t1 - t0) * 360.0F) / 4000.0F;
+            float ang = ((t1 - t0) * 360.0F) / 4000.0F;
             pmvMatrix.glRotatef(ang, 0, 0, 1);
             pmvMatrix.glRotatef(ang, 0, 1, 0);
         }
-        st.uniform(gl, pmvMatrixUniform);        
+        st.uniform(gl, pmvMatrixUniform);
 
         // Draw a square
         vertices.enableBuffer(gl, true);
@@ -191,39 +191,39 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
     @Override
     public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) {
         final GL2ES2 gl = glad.getGL().getGL2ES2();
-        if(-1 != swapInterval) {        
+        if(-1 != swapInterval) {
             gl.setSwapInterval(swapInterval);
         }
         reshapeImpl(gl, x, y, width, height, width, height);
     }
-    
+
     @Override
     public void reshapeTile(TileRendererBase tr,
-                            int tileX, int tileY, int tileWidth, int tileHeight, 
+                            int tileX, int tileY, int tileWidth, int tileHeight,
                             int imageWidth, int imageHeight) {
         final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2();
         gl.setSwapInterval(0);
         reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
     }
-    
+
     void reshapeImpl(GL2ES2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) {
         System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
         // Thread.dumpStack();
         if( !gl.hasGLSL() ) {
             return;
         }
-        
+
         st.useProgram(gl, true);
         // Set location in front of camera
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
         pmvMatrix.glLoadIdentity();
-        
+
         // compute projection parameters 'normal' perspective
         final float fovy=45f;
         final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect;
         final float zNear=1f;
         final float zFar=100f;
-        
+
         // compute projection parameters 'normal' frustum
         final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
         final float bottom=-1.0f*top;
@@ -231,18 +231,18 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
         final float right=aspect2*top;
         final float w = right - left;
         final float h = top - bottom;
-        
+
         // compute projection parameters 'tiled'
         final float l = left + tileX * w / imageWidth;
         final float r = l + tileWidth * w / imageWidth;
         final float b = bottom + tileY * h / imageHeight;
         final float t = b + tileHeight * h / imageHeight;
-        
+
         pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
         //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
         st.uniform(gl, pmvMatrixUniform);
         st.useProgram(gl, false);
-        
+
         System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN");
     }
 
@@ -255,8 +255,7 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende
         }
         st.destroy(gl);
         st = null;
-        pmvMatrix.destroy();
         pmvMatrix = null;
         System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN");
-    }    
+    }
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java
index f0c9fc6ed..113cbee26 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java
@@ -274,7 +274,6 @@ public class RedSquareMappedES2 implements GLEventListener, TileRendererBase.Til
         }
         st.destroy(gl);
         st = null;
-        pmvMatrix.destroy();
         pmvMatrix = null;
         System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN");
     }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
index 8aa3a006c..fb30ef6b5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
@@ -3,14 +3,14 @@
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
- * 
+ *
  *    1. Redistributions of source code must retain the above copyright notice, this list of
  *       conditions and the following disclaimer.
- * 
+ *
  *    2. 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.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
@@ -20,12 +20,12 @@
  * 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.
- * 
+ *
  * The views and conclusions contained in the software and documentation are those of the
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
  */
- 
+
 package com.jogamp.opengl.test.junit.jogl.demos.es2;
 
 import java.nio.FloatBuffer;
@@ -53,15 +53,15 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
     Texture  texture;
     int textureUnit;
     boolean keepTextureBound;
-    
+
     ShaderState st;
     PMVMatrix pmvMatrix;
     GLUniformData pmvMatrixUniform;
     GLArrayDataServer interleavedVBO;
     float[] clearColor = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
-    
+
     /**
-     * 
+     *
      * @param td
      * @param textureUnit of range [0..]
      */
@@ -70,7 +70,7 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
         this.textureUnit = textureUnit;
         this.keepTextureBound = false;
     }
-    
+
     public void setClearColor(float[] clearColor) {
         this.clearColor = clearColor;
     }
@@ -83,7 +83,7 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
     public Texture getTexture( ) {
         return this.texture;
     }
-    
+
     /**
     public void setTextureData(GL gl, TextureData textureData ) {
         if(null!=texture) {
@@ -95,21 +95,21 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
         }
         this.textureData = textureData;
         this.texture = TextureIO.newTexture(this.textureData);
-        
+
         // fix VBO !
     } */
 
     static final String shaderBasename = "texture01_xxx";
-       
+
     private void initShader(GL2ES2 gl, boolean use_program) {
         // Create & Compile the shader objects
-        ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), 
+        ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
                                             "shader", "shader/bin", shaderBasename, true);
-        ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), 
+        ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
                                             "shader", "shader/bin", shaderBasename, true);
         rsVp.defaultShaderCustomization(gl, true, true);
         rsFp.defaultShaderCustomization(gl, true, true);
-        
+
         // Create & Link the shader program
         ShaderProgram sp = new ShaderProgram();
         sp.add(rsVp);
@@ -122,24 +122,24 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
         st = new ShaderState();
         st.attachShaderProgram(gl, sp, use_program);
     }
-    
+
     @Override
     public void init(GLAutoDrawable glad) {
         if(null!=textureData) {
             this.texture = TextureIO.newTexture(glad.getGL(), textureData);
         }
         GL2ES2 gl = glad.getGL().getGL2ES2();
-        
+
         initShader(gl, true);
-                
+
         // setup mgl_PMVMatrix
         pmvMatrix = new PMVMatrix();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
         pmvMatrix.glLoadIdentity();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
-        pmvMatrix.glLoadIdentity();       
+        pmvMatrix.glLoadIdentity();
         pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
-        
+
         st.ownUniform(pmvMatrixUniform);
         if(!st.uniform(gl, pmvMatrixUniform)) {
             throw new GLException("Error setting PMVMatrix in shader: "+st);
@@ -150,31 +150,31 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
 
         // fetch the flipped texture coordinates
         texture.getImageTexCoords().getST_LB_RB_LT_RT(s_quadTexCoords, 0, 1f, 1f);
-        
+
         interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
-        {        
-            interleavedVBO.addGLSLSubArray("mgl_Vertex",        3, GL.GL_ARRAY_BUFFER);            
-            interleavedVBO.addGLSLSubArray("mgl_Color",         4, GL.GL_ARRAY_BUFFER);            
+        {
+            interleavedVBO.addGLSLSubArray("mgl_Vertex",        3, GL.GL_ARRAY_BUFFER);
+            interleavedVBO.addGLSLSubArray("mgl_Color",         4, GL.GL_ARRAY_BUFFER);
             //interleavedVBO.addGLSLSubArray("mgl_Normal",        3, GL.GL_ARRAY_BUFFER);
             interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
 
             FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
-            
+
             for(int i=0; i<4; i++) {
                 ib.put(s_quadVertices,  i*3, 3);
-                ib.put(s_quadColors,    i*4, 4);  
+                ib.put(s_quadColors,    i*4, 4);
                 //ib.put(s_cubeNormals,   i*3, 3);
                 ib.put(s_quadTexCoords, i*2, 2);
-            }                        
+            }
         }
         interleavedVBO.seal(gl, true);
         interleavedVBO.enableBuffer(gl, false);
         st.ownAttribute(interleavedVBO, true);
-        
+
         // OpenGL Render Settings
         gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
         gl.glEnable(GL2ES2.GL_DEPTH_TEST);
-        
+
         if( keepTextureBound && null != texture  ) {
             gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit);
             texture.enable(gl);
@@ -186,21 +186,21 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
     @Override
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
         GL2ES2 gl = drawable.getGL().getGL2ES2();
-        
+
         // Clear background to white
         gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
         if(null != st) {
             pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
             pmvMatrix.glLoadIdentity();
             pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
-    
+
             pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
             pmvMatrix.glLoadIdentity();
-            
+
             st.useProgram(gl, true);
             st.uniform(gl, pmvMatrixUniform);
             st.useProgram(gl, false);
-        }        
+        }
     }
 
     @Override
@@ -215,7 +215,6 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
         }
 
         pmvMatrixUniform = null;
-        pmvMatrix.destroy();
         pmvMatrix=null;
         st.destroy(gl);
         st=null;
@@ -227,38 +226,38 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
 
         gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
 
-        st.useProgram(gl, true);        
+        st.useProgram(gl, true);
         interleavedVBO.enableBuffer(gl, true);
         if( !keepTextureBound && null != texture ) {
-            gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit);        
+            gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit);
             texture.enable(gl);
             texture.bind(gl);
         }
-        
+
         gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
-        
+
         if( !keepTextureBound && null != texture  ) {
             texture.disable(gl);
         }
-        interleavedVBO.enableBuffer(gl, false);        
+        interleavedVBO.enableBuffer(gl, false);
         st.useProgram(gl, false);
     }
-    
-    private static final float[] s_quadVertices = { 
+
+    private static final float[] s_quadVertices = {
       -1f, -1f, 0f, // LB
        1f, -1f, 0f, // RB
       -1f,  1f, 0f, // LT
-       1f,  1f, 0f  // RT 
+       1f,  1f, 0f  // RT
     };
-    private static final float[] s_quadColors = { 
+    private static final float[] s_quadColors = {
       1f, 1f, 1f, 1f,
       1f, 1f, 1f, 1f,
       1f, 1f, 1f, 1f,
       1f, 1f, 1f, 1f };
-    private static final float[] s_quadTexCoords = { 
+    private static final float[] s_quadTexCoords = {
             0f, 0f, // LB
             1f, 0f, // RB
-            0f, 1f, // LT   
+            0f, 1f, // LT
             1f, 1f  // RT
     };
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
index 79e0655e3..cdee78fe9 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java
@@ -348,10 +348,7 @@ public class TextureSequenceCubeES2 implements GLEventListener {
 
         texSeq = null;
         pmvMatrixUniform = null;
-        if( null != pmvMatrix ) {
-            pmvMatrix.destroy();
-            pmvMatrix=null;
-        }
+        pmvMatrix=null;
         if( null != st ) {
             st.destroy(gl);
             st=null;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index 6cee4066b..cb78165be 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -713,7 +713,6 @@ public class MovieSimple implements GLEventListener {
         }
         pmvMatrixUniform = null;
         if(null != pmvMatrix) {
-            pmvMatrix.destroy();
             pmvMatrix=null;
         }
         if(null != st) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
index e69286311..13f299aeb 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
@@ -3,14 +3,14 @@
  *
  * Redistribution and use in source and binary forms, with or without modification, are
  * permitted provided that the following conditions are met:
- * 
+ *
  *    1. Redistributions of source code must retain the above copyright notice, this list of
  *       conditions and the following disclaimer.
- * 
+ *
  *    2. 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.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community OR
@@ -20,7 +20,7 @@
  * 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.
- * 
+ *
  * The views and conclusions contained in the software and documentation are those of the
  * authors and should not be interpreted as representing official policies, either expressed
  * or implied, of JogAmp Community.
@@ -60,10 +60,10 @@ import com.jogamp.opengl.util.texture.TextureIO;
  * geometry shader.
  * </p>
  * <p>
- * If the <code>XYZ flipping</code> geometry shader functions properly, 
+ * If the <code>XYZ flipping</code> geometry shader functions properly,
  * the texture will be flipped horizontally and vertically.
- * </p> 
- * 
+ * </p>
+ *
  * @author Chuck Ritola December 2012
  * @author Sven Gothel (GL3 core, pass-though, core geometry shader)
  */
@@ -77,7 +77,7 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
 
     static final String shaderBasename = "texture01_xxx";
     static final String[] geomShaderBaseNames = new String[] { "passthrough01_xxx", "flipXYZ01_xxx" };
-    
+
     public GeomShader01TextureGL3(int geomShader) {
         this.geomShader = geomShader;
     }
@@ -100,22 +100,22 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
             if( !ShaderUtil.isGeometryShaderSupported(gl) ) {
                 throw new RuntimeException("GL object not >= 3.2, i.e. no geometry shader support.: "+gl);
             }
-        }        
+        }
         final GL3 gl = drawable.getGL().getGL3();
 
         final ShaderProgram sp;
         {
             final ShaderCode vs, gs, fs;
-            vs = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), 
+            vs = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(),
                                    "shader", "shader/bin", shaderBasename, true);
-            gs = ShaderCode.create(gl, GL3.GL_GEOMETRY_SHADER, this.getClass(), 
+            gs = ShaderCode.create(gl, GL3.GL_GEOMETRY_SHADER, this.getClass(),
                                    "shader", "shader/bin", geomShaderBaseNames[geomShader], true);
-            fs = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), 
-                                   "shader", "shader/bin", shaderBasename, true);        
+            fs = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
+                                   "shader", "shader/bin", shaderBasename, true);
             vs.defaultShaderCustomization(gl, true, true);
             gs.defaultShaderCustomization(gl, true, true);
             fs.defaultShaderCustomization(gl, true, true);
-            
+
             sp = new ShaderProgram();
             sp.add(gl, vs, System.err);
             sp.add(gl, gs, System.err);
@@ -124,20 +124,20 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
                 throw new GLException("Couldn't link program: "+sp);
             }
         }
-        
+
         st=new ShaderState();
         st.attachShaderProgram(gl, sp, true);
-        
+
         // setup mgl_PMVMatrix
         pmvMatrix = new PMVMatrix();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
         pmvMatrix.glLoadIdentity();
         pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
-        pmvMatrix.glLoadIdentity();       
+        pmvMatrix.glLoadIdentity();
         pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
         st.ownUniform(pmvMatrixUniform);
-        st.uniform(gl, pmvMatrixUniform);        
-        
+        st.uniform(gl, pmvMatrixUniform);
+
         st.ownUniform(pmvMatrixUniform);
         if(!st.uniform(gl, pmvMatrixUniform)) {
             throw new GLException("Error setting PMVMatrix in shader: "+st);
@@ -154,13 +154,13 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
         if(null == texture) {
             throw new RuntimeException("Could not load test texture");
         }
-        
+
         // Tri order:
         //   TL, BL, BR
         //   TL, TR, BR
         {
             int i=0;
-            TextureCoords tc = texture.getImageTexCoords();        
+            TextureCoords tc = texture.getImageTexCoords();
             s_triTexCoords[i++] = tc.left();  s_triTexCoords[i++] = tc.top();
             s_triTexCoords[i++] = tc.left();  s_triTexCoords[i++] = tc.bottom();
             s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.bottom();
@@ -168,25 +168,25 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
             s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.top();
             s_triTexCoords[i++] = tc.right(); s_triTexCoords[i++] = tc.bottom();
         }
-        
+
         interleavedVBO = GLArrayDataServer.createGLSLInterleaved(2+4+2, GL.GL_FLOAT, false, 3*6, GL.GL_STATIC_DRAW);
-        {        
+        {
             interleavedVBO.addGLSLSubArray("mgl_Vertex",        2, GL.GL_ARRAY_BUFFER);
             interleavedVBO.addGLSLSubArray("mgl_Color",         4, GL.GL_ARRAY_BUFFER);
             interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
 
             FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
-            
+
             for(int i=0; i<6; i++) {
                 ib.put(s_triVertices,  i*2, 2);
                 ib.put(s_triColors,    i*4, 4);
                 ib.put(s_triTexCoords, i*2, 2);
-            }                        
+            }
         }
         interleavedVBO.seal(gl, true);
         interleavedVBO.enableBuffer(gl, false);
         st.ownAttribute(interleavedVBO, true);
-        
+
         gl.glClearColor(0f, 0f, 0f, 0f);
         gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
         st.useProgram(gl, false);
@@ -202,7 +202,7 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
         texData.destroy();
         return res;
     }
-    
+
     @Override
     public void dispose(GLAutoDrawable drawable) {
         final GL3 gl = drawable.getGL().getGL3();
@@ -213,19 +213,18 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
 
         if(null != st) {
             pmvMatrixUniform = null;
-            pmvMatrix.destroy();
             pmvMatrix=null;
             st.destroy(gl);
             st=null;
         }
     }
-    
+
     @Override
     public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
         GL3 gl = drawable.getGL().getGL3();
-        
+
         gl.setSwapInterval(1);
-        
+
         // Clear background to white
         gl.glClearColor(1.0f, 1.0f, 1.0f, 0.4f);
 
@@ -233,42 +232,42 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
             pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
             pmvMatrix.glLoadIdentity();
             pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f);
-    
+
             pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
             pmvMatrix.glLoadIdentity();
-            
+
             st.useProgram(gl, true);
             st.uniform(gl, pmvMatrixUniform);
             st.useProgram(gl, false);
-        }        
+        }
     }
-    
+
     @Override
     public void display(GLAutoDrawable drawable)  {
         final GL3 gl = drawable.getGL().getGL3();
-        
+
         gl.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT);
 
         if(null != st) {
             //Draw the image as a pseudo-quad using two triangles
-            st.useProgram(gl, true);        
+            st.useProgram(gl, true);
             interleavedVBO.enableBuffer(gl, true);
             gl.glActiveTexture(GL.GL_TEXTURE0);
             texture.enable(gl);
             texture.bind(gl);
-            
+
             gl.glDrawArrays(GL.GL_TRIANGLES, 0, 6);
-            
-            texture.disable(gl);                                
-            interleavedVBO.enableBuffer(gl, false);        
+
+            texture.disable(gl);
+            interleavedVBO.enableBuffer(gl, false);
             st.useProgram(gl, false);
         }
     }//end display()
-    
-    private static final float[] s_triVertices = { 
+
+    private static final float[] s_triVertices = {
            -1f,  1f, // TL
            -1f, -1f, // BL
-            1f, -1f, // BR   
+            1f, -1f, // BR
            -1f,  1f, // TL
             1f,  1f, // TR
             1f, -1f  // BR
@@ -281,13 +280,13 @@ public class GeomShader01TextureGL3 implements GLEventListener  {
             1f, 1f, 1f, 1f,
             1f, 1f, 1f, 1f
     };
-    private static final float[] s_triTexCoords = { 
+    private static final float[] s_triTexCoords = {
             0f, 1f, // TL
             0f, 0f, // BL
-            1f, 0f, // BR   
+            1f, 0f, // BR
             0f, 1f, // TL
             1f, 1f, // TR
             1f, 0f  // BR
     };
-    
+
 }//end Test
-- 
cgit v1.2.3