commit 46d463a4d7b6ff0d03319715d7db4685ee50378a
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Feb 24 10:40:46 2021 +0100

    Make per-component centers optional, controlled by API MeshBase.setUseCenters()

diff --git a/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java b/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
index 3cbe2be..8941cbc 100644
--- a/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
+++ b/src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
@@ -129,6 +129,7 @@ public class EffectQueuePostprocess extends EffectQueue
     String mainFragHeader= version + "\n";
 
     mainVertHeader += "#define MAX_COMPON " + MeshBase.getMaxEffComponents() + "\n";
+    if( MeshBase.getUseCenters() ) mainVertHeader += "#define COMP_CENTERS\n";
 
     String enabledEffectV= VertexEffect.getGLSL();
 
diff --git a/src/main/java/org/distorted/library/main/DistortedLibrary.java b/src/main/java/org/distorted/library/main/DistortedLibrary.java
index 88afb4a..5892931 100644
--- a/src/main/java/org/distorted/library/main/DistortedLibrary.java
+++ b/src/main/java/org/distorted/library/main/DistortedLibrary.java
@@ -115,8 +115,7 @@ public class DistortedLibrary
   private static int mFBOQueueSize;
   private static int mGLSL;
   private static String mGLSL_VERSION;
-  private static boolean mOITCompilationAttempted;
-  private static boolean mNeedsTransformFeedback;
+  private static boolean mOITCompilationAttempted, mNeedsTransformFeedback;
 
   private static int mMaxTextureSize         = Integer.MAX_VALUE;
   private static int mMaxNumberOfVerUniforms = Integer.MAX_VALUE;
@@ -248,6 +247,7 @@ public class DistortedLibrary
     String mainFragHeader= mGLSL_VERSION + ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n");
 
     mainVertHeader += "#define MAX_COMPON " + MeshBase.getMaxEffComponents() + "\n";
+    if( MeshBase.getUseCenters() ) mainVertHeader += "#define COMP_CENTERS\n";
 
     String enabledEffectV= VertexEffect.getGLSL();
     String enabledEffectF= FragmentEffect.getGLSL();
@@ -346,6 +346,7 @@ public class DistortedLibrary
     String fullFragHeader= mGLSL_VERSION + ("#define NUM_FRAGMENT " +                                         0   + "\n");
 
     fullVertHeader += "#define MAX_COMPON " + MeshBase.getMaxEffComponents() + "\n";
+    if( MeshBase.getUseCenters() ) fullVertHeader += "#define COMP_CENTERS\n";
 
     String enabledEffectV= VertexEffect.getAllGLSL();
     String enabledEffectF= "{}";
@@ -385,6 +386,7 @@ public class DistortedLibrary
     String mainFragHeader= mGLSL_VERSION + ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n") + ("#define OIT\n");
 
     mainVertHeader += "#define MAX_COMPON " + MeshBase.getMaxEffComponents() + "\n";
+    if( MeshBase.getUseCenters() ) mainVertHeader += "#define COMP_CENTERS\n";
 
     String enabledEffectV= VertexEffect.getGLSL();
     String enabledEffectF= FragmentEffect.getGLSL();
diff --git a/src/main/java/org/distorted/library/mesh/DeferredJobs.java b/src/main/java/org/distorted/library/mesh/DeferredJobs.java
index 9fa3b1f..fe4d6c2 100644
--- a/src/main/java/org/distorted/library/mesh/DeferredJobs.java
+++ b/src/main/java/org/distorted/library/mesh/DeferredJobs.java
@@ -48,20 +48,21 @@ public class DeferredJobs
   private static final int JOB_TYPE_CENTER       = 8;
   private static final int JOB_TYPE_ADD_EMPTY_TEX= 9;
 
-  private static ArrayList<JobNode> mJobs = new ArrayList<>();
+  private static final ArrayList<JobNode> mJobs = new ArrayList<>();
 
   //////////////////////////////////////////////////////////////////////////
 
   private static class Job
     {
-    private int mType;
-    private MeshBase mTarget;
-    private MeshBase[] mSource;
+    private final int mType;
+    private final MeshBase mTarget;
+    private final MeshBase[] mSource;
+    private final MatrixEffect mMatrixEffect;
+    private final Static4D[] mMaps;
+    private final int mComp, mAndAssoc, mEquAssoc;
+    private final float mX,mY,mZ;
+
     private EffectQueueVertex mVertexEffects;
-    private MatrixEffect mMatrixEffect;
-    private Static4D[] mMaps;
-    private int mComp, mAndAssoc, mEquAssoc;
-    private float mX,mY,mZ;
 
     Job(int type, MeshBase target, MeshBase[] source, VertexEffect vEff, MatrixEffect mEff,
         Static4D[] maps, int comp, int and, int equ, float x, float y, float z)
diff --git a/src/main/java/org/distorted/library/mesh/MeshBase.java b/src/main/java/org/distorted/library/mesh/MeshBase.java
index a5b773f..dcf28eb 100644
--- a/src/main/java/org/distorted/library/mesh/MeshBase.java
+++ b/src/main/java/org/distorted/library/mesh/MeshBase.java
@@ -51,7 +51,7 @@ public abstract class MeshBase
    {
    private static final int ASSOC_UBO_BINDING  = 3;
    private static final int CENTER_UBO_BINDING = 4;
-   public  static final int MAX_EFFECT_COMPONENTS= 100;
+   public  static final int MAX_EFFECT_COMPONENTS= 98;
 
    // sizes of attributes of an individual vertex.
    private static final int POS_DATA_SIZE= 3; // vertex coordinates: x,y,z
@@ -79,6 +79,13 @@ public abstract class MeshBase
    private static final int VERT1_SIZE = VERT1_ATTRIBS*BYTES_PER_FLOAT;
    private static final int VERT2_SIZE = VERT2_ATTRIBS*BYTES_PER_FLOAT;
 
+   private static final int[] mCenterBlockIndex = new int[EffectQueue.MAIN_VARIANTS];
+   private static final int[] mAssocBlockIndex  = new int[EffectQueue.MAIN_VARIANTS];
+
+   private static final int TEX_COMP_SIZE = 5; // 5 four-byte entities inside the component
+
+   private static boolean mUseCenters;
+
    private boolean mShowNormals;              // when rendering this mesh, draw normal vectors?
    private InternalBuffer mVBO1, mVBO2, mTFO; // main vertex buffer and transform feedback buffer
    private int mNumVertices;
@@ -86,15 +93,10 @@ public abstract class MeshBase
    private float[] mVertAttribs2;             // packed: TexS,TexT, Component
    private float mInflate;
    private final UniformBlockAssociation mUBA;
-   private final UniformBlockCenter mUBC;
+   private UniformBlockCenter mUBC;
 
    DeferredJobs.JobNode[] mJobNode;
 
-   private static final int[] mCenterBlockIndex = new int[EffectQueue.MAIN_VARIANTS];
-   private static final int[] mAssocBlockIndex  = new int[EffectQueue.MAIN_VARIANTS];
-
-   private static final int TEX_COMP_SIZE = 5; // 5 four-byte entities inside the component
-
    private static class TexComponent
      {
      private int mEndIndex;
@@ -137,7 +139,8 @@ public abstract class MeshBase
      mJobNode = new DeferredJobs.JobNode[1];
 
      mUBA = new UniformBlockAssociation();
-     mUBC = new UniformBlockCenter();
+
+     if( mUseCenters ) mUBC = new UniformBlockCenter();
 
      mVBO1= new InternalBuffer(GLES30.GL_ARRAY_BUFFER             , GLES30.GL_STATIC_READ);
      mVBO2= new InternalBuffer(GLES30.GL_ARRAY_BUFFER             , GLES30.GL_STATIC_READ);
@@ -154,7 +157,8 @@ public abstract class MeshBase
      mNumVertices= original.mNumVertices;
 
      mUBA = new UniformBlockAssociation(original.mUBA);
-     mUBC = new UniformBlockCenter(original.mUBC);
+
+     if( mUseCenters ) mUBC = new UniformBlockCenter(original.mUBC);
 
      if( deep )
        {
@@ -326,7 +330,10 @@ public abstract class MeshBase
 
    void setComponentCenterNow(int component, float x, float y, float z)
      {
-     mUBC.setEffectCenterNow(component, x, y, z);
+     if( mUBC!=null )
+       {
+       mUBC.setEffectCenterNow(component, x, y, z);
+       }
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -393,7 +400,7 @@ public abstract class MeshBase
          if( origEffComponents<MAX_EFFECT_COMPONENTS )
            {
            mUBA.copy(origEffComponents, mesh.mUBA, j);
-           mUBC.copy(origEffComponents, mesh.mUBC, j);
+           if( mUseCenters ) mUBC.copy(origEffComponents, mesh.mUBC, j);
            origEffComponents++;
            }
          }
@@ -538,6 +545,25 @@ public abstract class MeshBase
      mVBO2.invalidate();
      }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Are we going to need per-component centers (needed for correct postprocessing of concave meshes)
+ * Switching this on allocates 16*MAX_EFFECT_COMPONENTS bytes for uniforms in the vertex shader.
+ */
+   public static void setUseCenters()
+     {
+     mUseCenters = true;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Are we using per-component centers?
+ */
+   public static boolean getUseCenters()
+     {
+     return mUseCenters;
+     }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    public static int getMaxEffComponents()
@@ -704,9 +730,12 @@ public abstract class MeshBase
      GLES30.glBindBufferBase(GLES30.GL_UNIFORM_BUFFER, ASSOC_UBO_BINDING, indexA);
      GLES30.glUniformBlockBinding(programH, mAssocBlockIndex[variant], ASSOC_UBO_BINDING);
 
-     int indexC = mUBC.getIndex();
-     GLES30.glBindBufferBase(GLES30.GL_UNIFORM_BUFFER, CENTER_UBO_BINDING, indexC);
-     GLES30.glUniformBlockBinding(programH, mCenterBlockIndex[variant], CENTER_UBO_BINDING);
+     if( mUseCenters )
+       {
+       int indexC = mUBC.getIndex();
+       GLES30.glBindBufferBase(GLES30.GL_UNIFORM_BUFFER, CENTER_UBO_BINDING, indexC);
+       GLES30.glUniformBlockBinding(programH, mCenterBlockIndex[variant], CENTER_UBO_BINDING);
+       }
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -902,9 +931,12 @@ public abstract class MeshBase
          case 2 : float[] centers = new float[3*numEff];
                   floatBuf.get(centers,0,3*numEff);
 
-                  for(int eff=0; eff<numEff; eff++)
+                  if( mUseCenters )
                     {
-                    mUBC.setEffectCenterNow(eff, centers[3*eff], centers[3*eff+1], centers[3*eff+2]);
+                    for(int eff=0; eff<numEff; eff++)
+                      {
+                      mUBC.setEffectCenterNow(eff, centers[3*eff], centers[3*eff+1], centers[3*eff+2]);
+                      }
                     }
 
                   floatBuf.get(mVertAttribs1, 0, VERT1_ATTRIBS*mNumVertices);
@@ -983,7 +1015,7 @@ public abstract class MeshBase
          stream.writeFloat((float)mEffComponent.get(i));
          }
 
-       float[] centers = mUBC.getBackingArray();
+       float[] centers = mUseCenters ? mUBC.getBackingArray() : new float[4*numEff];
 
        for(int i=0; i<numEff; i++)
          {
@@ -1075,7 +1107,11 @@ public abstract class MeshBase
      mVBO2.markForDeletion();
      mTFO.markForDeletion();
      mUBA.markForDeletion();
-     mUBC.markForDeletion();
+
+     if( mUBC!=null )
+       {
+       mUBC.markForDeletion();
+       }
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 4f3eeb9..28c4d6d 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -39,10 +39,12 @@ uniform mat4 u_MVMatrixV;             // the combined model/view matrix. (for ve
 uniform float u_Inflate;              // how much should we inflate (>0.0) or deflate (<0.0) the mesh.
 uniform int u_TransformFeedback;      // are we doing the transform feedback now?
 
+#ifdef COMP_CENTERS
 layout (std140) uniform componentCenter
   {
   vec4 vComCenter[MAX_COMPON];        // centers of mesh components. 4 floats: (x,y,z,unused)
   };
+#endif
 
 #if NUM_VERTEX>0
 uniform int vNumEffects;              // total number of vertex effects
@@ -117,8 +119,12 @@ float degree(in vec4 region, in vec3 PS)
 void main()
   {
   int component = int(a_Component);
-  vec3 v = a_Position + u_Inflate*(a_Position - vComCenter[component].xyz);
   vec3 n = a_Normal;
+#ifdef COMP_CENTERS
+  vec3 v = a_Position + u_Inflate*(a_Position - vComCenter[component].xyz);
+#else
+  vec3 v = a_Position + u_Inflate*a_Position;
+#endif
 
 #if NUM_VERTEX>0
   int effect=0;
