commit 1b85f172f8ec32369e6661146f94ce3bb8bf1978
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Sat Apr 10 17:45:01 2021 +0200

    Face cubit creation: progress: rounded corners

diff --git a/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java b/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java
index fad77dc..9b6619b 100644
--- a/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java
+++ b/src/main/java/org/distorted/examples/meshfile/FactoryCubit.java
@@ -19,11 +19,12 @@
 
 package org.distorted.examples.meshfile;
 
+import org.distorted.library.effect.MatrixEffect;
+import org.distorted.library.effect.MatrixEffectMove;
+import org.distorted.library.effect.MatrixEffectQuaternion;
+import org.distorted.library.effect.MatrixEffectScale;
 import org.distorted.library.effect.VertexEffect;
 import org.distorted.library.effect.VertexEffectDeform;
-import org.distorted.library.effect.VertexEffectMove;
-import org.distorted.library.effect.VertexEffectQuaternion;
-import org.distorted.library.effect.VertexEffectScale;
 import org.distorted.library.mesh.MeshBase;
 import org.distorted.library.mesh.MeshJoined;
 import org.distorted.library.mesh.MeshPolygon;
@@ -37,10 +38,6 @@ import java.util.ArrayList;
 
 class FactoryCubit
   {
-  static final float SQ5   = (float)Math.sqrt(5);
-  static final float SIN18 = (SQ5-1)/4;
-  static final float COS18 = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
-
   private static final float[] mBuffer = new float[3];
   private static final float[] mQuat1  = new float[4];
   private static final float[] mQuat2  = new float[4];
@@ -50,16 +47,22 @@ class FactoryCubit
 
   private static FactoryCubit mThis;
 
-  private static class FaceInfo
+  private static class StickerInfo
     {
     float[] vertices;
+    }
+
+  private static class FaceInfo
+    {
+    int sticker;
     float vx,vy,vz;
     float scale;
     float qx,qy,qz,qw;
     boolean flip;
     }
 
-  private static final ArrayList<FaceInfo> mFaceInfo = new ArrayList<>();
+  private static final ArrayList<FaceInfo>       mFaceInfo = new ArrayList<>();
+  private static final ArrayList<StickerInfo> mStickerInfo = new ArrayList<>();
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -189,7 +192,7 @@ class FactoryCubit
 
   private void roundCorners(MeshBase mesh, Static3D center, Static3D[] vertices, float strength, float regionRadius)
     {
-    Static4D reg= new Static4D(0,0,0,regionRadius);
+    Static4D region= new Static4D(0,0,0,regionRadius);
 
     float centX = center.get0();
     float centY = center.get1();
@@ -201,7 +204,7 @@ class FactoryCubit
       float y = strength*(centY - vertex.get1());
       float z = strength*(centZ - vertex.get2());
 
-      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, reg);
+      VertexEffect effect = new VertexEffectDeform(new Static3D(x,y,z), RADIUS, vertex, region);
       mesh.apply(effect);
       }
     }
@@ -229,12 +232,6 @@ class FactoryCubit
 
     float A = (float)Math.sqrt( (v1x*v1x+v1y*v1y+v1z*v1z) / (v2x*v2x+v2y*v2y+v2z*v2z) );
 
-//android.util.Log.e("D", "("+x1+","+y1+","+z1+") , ("+x2+","+y2+","+z2+") , ("+x3+","+y3+","+z3+")" );
-
-//boolean result = (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
-
-//android.util.Log.e("D", "are those colinear? : "+result);
-
     return (v1x==A*v2x && v1y==A*v2y && v1z==A*v2z);
     }
 
@@ -268,8 +265,6 @@ class FactoryCubit
     mBuffer[0] /= len;
     mBuffer[1] /= len;
     mBuffer[2] /= len;
-
-//android.util.Log.e("D", " normal: "+mBuffer[0]+" "+mBuffer[1]+" "+mBuffer[2]);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -316,12 +311,14 @@ class FactoryCubit
     info.scale = Math.max(maxX-minX,maxY-minY);
 
     int len = vert3D.length;
-    info.vertices = new float[2*len];
+    StickerInfo sInfo = new StickerInfo();
+    sInfo.vertices = new float[2*len];
+    mStickerInfo.add(sInfo);
 
     for( int vertex=0; vertex<len; vertex++ )
       {
-      info.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
-      info.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
+      sInfo.vertices[2*vertex  ] = vert3D[vertex][0] / info.scale;
+      sInfo.vertices[2*vertex+1] = vert3D[vertex][1] / info.scale;
       }
 
     info.flip = false;
@@ -399,8 +396,6 @@ class FactoryCubit
       }
 
     float cosTheta = mBuffer[2];
-  //float sinTheta = axiLen / vecLen;
-
     float sinHalfTheta = (float)Math.sqrt(0.5f*(1-cosTheta));
     float cosHalfTheta = (float)Math.sqrt(0.5f*(1+cosTheta));
 
@@ -486,14 +481,12 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void correctInfo(FaceInfo info, float[] rotatedVertices, int len, float[] originalVertices, float sin, float cos, boolean flip)
+  private void correctInfo(FaceInfo info, float scale, float sin, float cos, int oldSticker, boolean flip)
     {
-    info.flip = flip;
+    mStickerInfo.remove(info.sticker);
 
-    System.arraycopy(originalVertices, 0, info.vertices, 0, 2*len);
-
-    float scale = rotatedVertices[0]!=0.0f ? originalVertices[0]/rotatedVertices[0] :
-                                             originalVertices[1]/rotatedVertices[1];
+    info.flip = flip;
+    info.sticker = oldSticker;
     info.scale *= scale;
 
     mQuat1[0] = 0.0f;
@@ -516,21 +509,23 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean foundVertex(FaceInfo info, float[] buffer, int len, boolean inverted, float[] vertices, float[] vert2D, float lenVert)
+  private boolean foundVertex(FaceInfo info, float[] buffer, int len, float[] preVert,
+                              float[] newVert, float lenVert, int oldSticker, boolean inverted)
     {
     for(int vertex=0; vertex<len; vertex++)
       {
-      float xR = vertices[2*vertex  ];
-      float yR = vertices[2*vertex+1];
+      float xR = newVert[2*vertex  ];
+      float yR = newVert[2*vertex+1];
       float lenRotV = (float)Math.sqrt(xR*xR+yR*yR);
-      float cos = computeCos(xR,yR,vert2D[0],vert2D[1], lenRotV, lenVert);
-      float sin = computeSin(xR,yR,vert2D[0],vert2D[1], lenRotV, lenVert);
+      float cos = computeCos(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
+      float sin = computeSin(xR,yR,preVert[0],preVert[1], lenRotV, lenVert);
 
-      rotateAllVertices(buffer,len,vertices,sin,cos);
+      rotateAllVertices(buffer,len,newVert,sin,cos);
 
-      if( isScaledVersionOf(buffer,vert2D,len) )
+      if( isScaledVersionOf(buffer,preVert,len) )
         {
-        correctInfo(info,buffer,len,vert2D,sin,cos,inverted);
+        float scale = preVert[0]!=0.0f ? buffer[0]/preVert[0] : buffer[1]/preVert[1];
+        correctInfo(info,scale,sin,cos,oldSticker,inverted);
         return true;
         }
       }
@@ -540,18 +535,22 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private boolean tryFindingRotation(final FaceInfo info, final float[] vert2D)
+  private boolean successfullyCollapsedStickers(final FaceInfo newInfo, final FaceInfo preInfo)
     {
-    int len = vert2D.length/2;
+    StickerInfo sNewInfo = mStickerInfo.get(newInfo.sticker);
+    StickerInfo sPreInfo = mStickerInfo.get(preInfo.sticker);
+    int len = sPreInfo.vertices.length;
+    float[] newVert = sNewInfo.vertices;
 
-    if( len == info.vertices.length/2 )
+    if( len == newVert.length )
       {
-      float[] tmp1 = new float[2*len];
-      float lenVert = (float)Math.sqrt(vert2D[0]*vert2D[0] + vert2D[1]*vert2D[1]);
-      if( foundVertex(info,tmp1,len,false,info.vertices,vert2D,lenVert) ) return true;
-      float[] tmp2 = new float[2*len];
-      mirrorAllVertices(tmp2,len,info.vertices);
-      if( foundVertex(info,tmp1,len,true ,tmp2         ,vert2D,lenVert) ) return true;
+      int oldSticker = preInfo.sticker;
+      float[] tmp1 = new float[len];
+      float lenVert = (float)Math.sqrt(newVert[0]*newVert[0] + newVert[1]*newVert[1]);
+      if( foundVertex(newInfo, tmp1, len/2, sPreInfo.vertices, newVert, lenVert, oldSticker, false) ) return true;
+      float[] tmp2 = new float[len];
+      mirrorAllVertices(tmp2,len/2,sPreInfo.vertices);
+      if( foundVertex(newInfo, tmp1, len/2, tmp2             , newVert, lenVert, oldSticker, true ) ) return true;
       }
 
     return false;
@@ -580,9 +579,10 @@ class FactoryCubit
   private void prepareFaceInfo( final float[][] vertices, final int[][] indexes)
     {
     mFaceInfo.clear();
+    mStickerInfo.clear();
 
     int numFaces = indexes.length;
-    FaceInfo info;
+    FaceInfo preInfo;
 
     for(int face=0; face<numFaces; face++)
       {
@@ -593,12 +593,8 @@ class FactoryCubit
 
       for(int previous=0; previous<face; previous++)
         {
-        info = mFaceInfo.get(previous);
-        if( tryFindingRotation(newInfo,info.vertices) )
-          {
-          android.util.Log.e("D", "comparing face "+face+" to "+previous+" SUCCESS!!");
-          break;
-          }
+        preInfo = mFaceInfo.get(previous);
+        if( successfullyCollapsedStickers(newInfo,preInfo) ) break;
         }
 
       mFaceInfo.add(newInfo);
@@ -607,19 +603,78 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void printInfo(FaceInfo info)
+  private void prepareAndRoundCorners(MeshBase mesh, float[][] vertices, int[][] vertIndexes,
+                                      float[][] corners, int[] cornerIndexes )
     {
-    android.util.Log.e("D", "vx="+info.vx+" vy="+info.vy+" vz="+info.vz);
-    android.util.Log.e("D", "qx="+info.qx+" qy="+info.qy+" qz="+info.qz+" qw="+info.qw);
-    android.util.Log.e("D", "scale="+info.scale);
+    int numNeig, lenFV;
+    int lenV = vertices.length;
+    int[] verts = new int[2*(lenV-1)];
+    Static3D[] staticVert = new Static3D[1];
+    Static3D center = new Static3D(0,0,0);
+    float cx, cy, cz;
+    float[] singleV;
 
-    String ver="";
+    for(int v=0; v<lenV; v++)
+      {
+      // prepare verts[]
+      numNeig = 0;
 
-    int len = info.vertices.length/2;
+      for (int[] vertIndex : vertIndexes)
+        {
+        lenFV = vertIndex.length;
 
-    for(int i =0; i<len; i++)
+        for (int fv = 0; fv < lenFV; fv++)
+          if (vertIndex[fv] == v)
+            {
+            int prev = fv > 0 ? fv - 1 : lenFV - 1;
+            int next = fv < lenFV - 1 ? fv + 1 : 0;
+
+            verts[numNeig++] = vertIndex[prev];
+            verts[numNeig++] = vertIndex[next];
+            }
+        }
+
+      cx=cy=cz=0.0f;
+
+      // from verts[] prepare center
+      for(int n=0; n<numNeig; n++)
+        {
+        singleV = vertices[verts[n]];
+
+        cx += singleV[0];
+        cy += singleV[1];
+        cz += singleV[2];
+        }
+      center.set(cx/numNeig - vertices[v][0],cy/numNeig - vertices[v][1],cz/numNeig - vertices[v][2]);
+
+      // round Corners
+      staticVert[0] = new Static3D(vertices[v][0], vertices[v][1], vertices[v][2]);
+
+      int corn = cornerIndexes[v];
+      float strength = corners[corn][0];
+      float radius   = corners[corn][1];
+
+      roundCorners(mesh, center, staticVert, strength, radius);
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void printStickerInfo()
+    {
+    String ver="";
+    int stickers = mStickerInfo.size();
+
+    for(int s=0; s<stickers; s++)
       {
-      ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
+      ver = "";
+      StickerInfo info = mStickerInfo.get(s);
+      int len = info.vertices.length/2;
+
+      for(int i =0; i<len; i++)
+        {
+        ver += ("("+info.vertices[2*i]+","+info.vertices[2*i+1]+") ");
+        }
       }
 
     android.util.Log.e("D", "vertices= "+ver);
@@ -627,7 +682,17 @@ class FactoryCubit
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes, final float[][] bands, final int[] bandIndexes)
+  private void printFaceInfo(FaceInfo info)
+    {
+    android.util.Log.e("D", "q=("+info.qx+", "+info.qy+", "+info.qz+", "+info.qw+") v=("
+                       +info.vx+", "+info.vy+", "+info.vz+") scale="+info.scale+" sticker="+info.sticker);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  MeshBase createRoundedSolid(final float[][] vertices, final int[][] vertIndexes,
+                              final float[][] bands   , final int[]   bandIndexes,
+                              final float[][] corners , final int[]   cornerIndexes)
     {
     int EFFECTS_PER_FACE = 3;
 
@@ -636,44 +701,47 @@ class FactoryCubit
     int numFaces = vertIndexes.length;
     float[] band, bandsComputed;
     MeshBase[] meshes = new MeshBase[numFaces];
-    FaceInfo info;
+    FaceInfo fInfo;
+    StickerInfo sInfo;
+
+    //printStickerInfo();
 
     for(int face=0; face<numFaces; face++)
       {
-      info = mFaceInfo.get(face);
+      fInfo = mFaceInfo.get(face);
+      sInfo = mStickerInfo.get(fInfo.sticker);
 
-      android.util.Log.d("D", "--------------");
-      printInfo(info);
+      //printFaceInfo(fInfo);
 
       band = bands[bandIndexes[face]];
       bandsComputed = computeBands( band[0], (int)band[1], band[2], band[3], (int)band[4]);
-      meshes[face] = new MeshPolygon(info.vertices,bandsComputed,(int)band[5],(int)band[6]);
+      meshes[face] = new MeshPolygon(sInfo.vertices,bandsComputed,(int)band[5],(int)band[6]);
       meshes[face].setEffectAssociation(0,(1<<face),0);
       }
 
     MeshBase mesh = new MeshJoined(meshes);
-    VertexEffect[] effects = new VertexEffect[EFFECTS_PER_FACE*numFaces];
+    MatrixEffect[] effects = new MatrixEffect[EFFECTS_PER_FACE*numFaces];
     Static3D center = new Static3D(0,0,0);
 
     for(int face=0; face<numFaces; face++)
       {
       int assoc = (1<<face);
-      info = mFaceInfo.get(face);
+      fInfo = mFaceInfo.get(face);
 
-      Static3D move3D= new Static3D(info.vx,info.vy,info.vz);
-      Static3D scale = new Static3D(info.scale,info.scale, info.flip ? -info.scale : info.scale);
-      Static4D quat  = new Static4D(info.qx,info.qy,info.qz,info.qw);
+      Static3D move3D= new Static3D(fInfo.vx,fInfo.vy,fInfo.vz);
+      Static3D scale = new Static3D(fInfo.scale,fInfo.scale, fInfo.flip ? -fInfo.scale : fInfo.scale);
+      Static4D quat  = new Static4D(fInfo.qx,fInfo.qy,fInfo.qz,fInfo.qw);
 
-      effects[EFFECTS_PER_FACE*face  ] = new VertexEffectScale(scale);
-      effects[EFFECTS_PER_FACE*face+1] = new VertexEffectQuaternion(quat,center);
-      effects[EFFECTS_PER_FACE*face+2] = new VertexEffectMove(move3D);
+      effects[EFFECTS_PER_FACE*face  ] = new MatrixEffectScale(scale);
+      effects[EFFECTS_PER_FACE*face+1] = new MatrixEffectQuaternion(quat,center);
+      effects[EFFECTS_PER_FACE*face+2] = new MatrixEffectMove(move3D);
 
-      effects[EFFECTS_PER_FACE*face  ].setMeshAssociation(assoc,-1);
-      effects[EFFECTS_PER_FACE*face+1].setMeshAssociation(assoc,-1);
-      effects[EFFECTS_PER_FACE*face+2].setMeshAssociation(assoc,-1);
+      mesh.apply(effects[EFFECTS_PER_FACE*face  ],assoc,-1);
+      mesh.apply(effects[EFFECTS_PER_FACE*face+1],assoc,-1);
+      mesh.apply(effects[EFFECTS_PER_FACE*face+2],assoc,-1);
       }
 
-    for( VertexEffect effect : effects ) mesh.apply(effect);
+    prepareAndRoundCorners(mesh, vertices, vertIndexes, corners, cornerIndexes);
 
     return mesh;
     }
diff --git a/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java b/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
index 4cae4f5..87128c7 100644
--- a/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
+++ b/src/main/java/org/distorted/examples/meshfile/MeshFileRenderer.java
@@ -320,8 +320,15 @@ class MeshFileRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Excep
 
       final int[] bandIndexes = new int[] { 0,0,0,0,0,0 };
 
+      final float[][] corners = new float[][]
+          {
+              { 0.01f, 0.10f }
+          };
+
+      final int[] cornerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
+
       FactoryCubit factory = FactoryCubit.getInstance();
-      mMesh = factory.createRoundedSolid(vertices, vertIndexes, bands, bandIndexes);
+      mMesh = factory.createRoundedSolid(vertices, vertIndexes, bands, bandIndexes, corners, cornerIndexes);
 
       int numEff = mMesh.numEffComponents();
 
