commit fa8bc9983bb2e57a889fb2fa160f2499cec4b80b
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Feb 24 16:31:09 2020 +0000

    New API MeshBase.apply(MatrixEffect[])

diff --git a/src/main/java/org/distorted/library/effect/MatrixEffect.java b/src/main/java/org/distorted/library/effect/MatrixEffect.java
index 125f532..4d76d81 100644
--- a/src/main/java/org/distorted/library/effect/MatrixEffect.java
+++ b/src/main/java/org/distorted/library/effect/MatrixEffect.java
@@ -19,6 +19,8 @@
 
 package org.distorted.library.effect;
 
+import android.opengl.Matrix;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Abstract class that represents an Effect that works by modifying the ModelView matrix.
@@ -30,6 +32,8 @@ public abstract class MatrixEffect extends Effect
  */
   public static final int NUM_UNIFORMS = 7;
 
+  private float[] mMatrix,mTmpArray;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 /**
  * Only for use by the library itself.
@@ -38,6 +42,104 @@ public abstract class MatrixEffect extends Effect
  */
   public abstract void apply(float[] matrix, float[] uniforms, int index);
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Only for use by the library itself.
+ * <p>
+ * The three values buffer[index], buffer[index+1], buffer[index+2] are assumed to contain the
+ * x,y,z coordinates of a point. We apply this Matrix effect to this point and overwrite those
+ * three values.
+ *
+ * This is on purpose a static evaluation - if this Effect contains any Dynamics, they will be
+ * evaluated at 0.
+ *
+ * @y.exclude
+ */
+ public void applyToPoint(float[] buffer, int index)
+   {
+   Matrix.setIdentityM(mMatrix,0);
+   compute(mTmpArray,0,0,0);
+   apply(mMatrix, mTmpArray, 0);
+
+   float x = buffer[index  ];
+   float y = buffer[index+1];
+   float z = buffer[index+2];
+
+   buffer[index  ] = mMatrix[0]*x + mMatrix[4]*y + mMatrix[ 8]*z + mMatrix[12];
+   buffer[index+1] = mMatrix[1]*x + mMatrix[5]*y + mMatrix[ 9]*z + mMatrix[13];
+   buffer[index+2] = mMatrix[2]*x + mMatrix[6]*y + mMatrix[10]*z + mMatrix[14];
+   }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Only for use by the library itself.
+ * <p>
+ * The three values buffer[index], buffer[index+1], buffer[index+2] are assumed to contain the
+ * x,y,z coordinates of a vector. We apply this Matrix effect to this vector and overwrite those
+ * three values.
+ *
+ * This is on purpose a static evaluation - if this Effect contains any Dynamics, they will be
+ * evaluated at 0.
+ *
+ * @y.exclude
+ */
+ public void applyToVector(float[] buffer, int index)
+   {
+   Matrix.setIdentityM(mMatrix,0);
+   compute(mTmpArray,0,0,0);
+   apply(mMatrix, mTmpArray, 0);
+
+   float x = buffer[index  ];
+   float y = buffer[index+1];
+   float z = buffer[index+2];
+
+   buffer[index  ] = mMatrix[0]*x + mMatrix[4]*y + mMatrix[ 8]*z;
+   buffer[index+1] = mMatrix[1]*x + mMatrix[5]*y + mMatrix[ 9]*z;
+   buffer[index+2] = mMatrix[2]*x + mMatrix[6]*y + mMatrix[10]*z;
+   }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Only for use by the library itself.
+ * <p>
+ * The 9 floats starting at buffer[index] are assumed to contain info about a vertex arranged in
+ * MeshBase way, i.e.  coord point (x,y,z) ; normal vector (x,y,z) ; inflate vector (x,y,z)
+ *
+ * @y.exclude
+ */
+ public void applyToVertex(float[] buffer, int index)
+   {
+   float x,y,z;
+
+   Matrix.setIdentityM(mMatrix,0);
+   compute(mTmpArray,0,0,0);
+   apply(mMatrix, mTmpArray, 0);
+
+   x = buffer[index  ];
+   y = buffer[index+1];
+   z = buffer[index+2];
+
+   buffer[index  ] = mMatrix[0]*x + mMatrix[4]*y + mMatrix[ 8]*z + mMatrix[12];
+   buffer[index+1] = mMatrix[1]*x + mMatrix[5]*y + mMatrix[ 9]*z + mMatrix[13];
+   buffer[index+2] = mMatrix[2]*x + mMatrix[6]*y + mMatrix[10]*z + mMatrix[14];
+
+   x = buffer[index+3];
+   y = buffer[index+4];
+   z = buffer[index+5];
+
+   buffer[index+3] = mMatrix[0]*x + mMatrix[4]*y + mMatrix[ 8]*z;
+   buffer[index+4] = mMatrix[1]*x + mMatrix[5]*y + mMatrix[ 9]*z;
+   buffer[index+5] = mMatrix[2]*x + mMatrix[6]*y + mMatrix[10]*z;
+
+   x = buffer[index+6];
+   y = buffer[index+7];
+   z = buffer[index+8];
+
+   buffer[index+6] = mMatrix[0]*x + mMatrix[4]*y + mMatrix[ 8]*z;
+   buffer[index+7] = mMatrix[1]*x + mMatrix[5]*y + mMatrix[ 9]*z;
+   buffer[index+8] = mMatrix[2]*x + mMatrix[6]*y + mMatrix[10]*z;
+   }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // empty function for completeness
 
@@ -51,5 +153,8 @@ public abstract class MatrixEffect extends Effect
   MatrixEffect(EffectName name)
     {
     super(name);
+
+    mMatrix  = new float[16];
+    mTmpArray= new float[4];
     }
   }
diff --git a/src/main/java/org/distorted/library/mesh/MeshBase.java b/src/main/java/org/distorted/library/mesh/MeshBase.java
index 674e7d4..b2930af 100644
--- a/src/main/java/org/distorted/library/mesh/MeshBase.java
+++ b/src/main/java/org/distorted/library/mesh/MeshBase.java
@@ -21,6 +21,7 @@ package org.distorted.library.mesh;
 
 import android.opengl.GLES31;
 
+import org.distorted.library.effect.MatrixEffect;
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.main.InternalBuffer;
 import org.distorted.library.program.DistortedProgram;
@@ -60,12 +61,12 @@ public abstract class MeshBase
    private static final int TRAN_SIZE  = TRAN_ATTRIBS*BYTES_PER_FLOAT;
    private static final int VERT_SIZE  = VERT_ATTRIBS*BYTES_PER_FLOAT;
 
-   private boolean mShowNormals;       // when rendering this mesh, draw normal vectors?
-   private InternalBuffer mVBO, mTFO;  // main vertex buffer and transform feedback buffer
-   private final float zFactor;        // strange workaround for the fact that we need to somehow store the 'depth'
-                                       // of the Mesh. Used in DistortedEffects. See DistortedTexture.getDepth().
+   private boolean mShowNormals;      // when rendering this mesh, draw normal vectors?
+   private InternalBuffer mVBO, mTFO; // main vertex buffer and transform feedback buffer
+   private final float zFactor;       // strange workaround for the fact that we need to somehow store the 'depth'
+                                      // of the Mesh. Used in DistortedEffects. See DistortedTexture.getDepth().
    private int mNumVertices;
-   private FloatBuffer mVertAttribs;   // packed: PosX,PosY,PosZ, NorX,NorY,NorZ, InfX,InfY,InfZ, TexS,TexT
+   private float[] mVertAttribs;      // packed: PosX,PosY,PosZ, NorX,NorY,NorZ, InfX,InfY,InfZ, TexS,TexT
    private float mInflate;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -85,12 +86,13 @@ public abstract class MeshBase
    void setAttribs(float[] vertexAttribs)
      {
      mNumVertices = vertexAttribs.length/VERT_ATTRIBS;
+     mVertAttribs = vertexAttribs;
 
-     mVertAttribs = ByteBuffer.allocateDirect(mNumVertices*VERT_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
-     mVertAttribs.put(vertexAttribs).position(0);
+     FloatBuffer attribs = ByteBuffer.allocateDirect(mNumVertices*VERT_SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
+     attribs.put(vertexAttribs).position(0);
 
-     mVBO.setData(mNumVertices*VERT_SIZE, mVertAttribs);
-     mTFO.setData(mNumVertices*TRAN_SIZE, null        );
+     mVBO.setData(mNumVertices*VERT_SIZE, attribs);
+     mTFO.setData(mNumVertices*TRAN_SIZE, null   );
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -209,11 +211,35 @@ public abstract class MeshBase
  */
    public void markForDeletion()
      {
-     mVertAttribs.clear();
+     mVertAttribs = null;
 
      mVBO.markForDeletion();
      mTFO.markForDeletion();
      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Multiply all coordinates, normal and inflate vectors by the matrix.
+ * <p>
+ * This is a static, permanent modification of the vertices contained in this Mesh. If the Effect
+ * contains any Dynamics, they will be evaluated at 0.
+ *
+ * Please note that calling this once with the complete list of Effects will be much faster than
+ * calling it repeatedly with one Effect at a time, as we have to reallocate the array of vertices
+ * each time.
+ */
+   public void apply(MatrixEffect[] effects)
+     {
+     for(int v=0; v<mNumVertices; v++)
+       {
+       for(MatrixEffect eff: effects)
+         {
+         if( eff!=null ) eff.applyToVertex( mVertAttribs, v*VERT_ATTRIBS );
+         }
+       }
+
+     setAttribs(mVertAttribs);
+     }
    }
 
 
