commit 0318e7e34dff3a1963b1ef72394bc24ddeea08cf
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Fri Jun 24 12:05:57 2016 +0100

    Important bugfix in the vertex shader: there was division by 0 in case Center point was on the edge of the Object, resulting in some vertices being shot into outer space.

diff --git a/src/main/java/org/distorted/library/EffectMessageSender.java b/src/main/java/org/distorted/library/EffectMessageSender.java
index 921415e..f67a02b 100644
--- a/src/main/java/org/distorted/library/EffectMessageSender.java
+++ b/src/main/java/org/distorted/library/EffectMessageSender.java
@@ -121,6 +121,7 @@ final class EffectMessageSender extends Thread
       }
 
     mThis = null;
+    mList.clear();
 
     //android.util.Log.i("SENDER", "sender thread finished...");
     }
diff --git a/src/main/java/org/distorted/library/EffectNames.java b/src/main/java/org/distorted/library/EffectNames.java
index a73f0bc..a1ca175 100644
--- a/src/main/java/org/distorted/library/EffectNames.java
+++ b/src/main/java/org/distorted/library/EffectNames.java
@@ -230,7 +230,7 @@ public enum EffectNames
         case 4: unities[MAXDIM*i+3] = name.unity[3];
         case 3: unities[MAXDIM*i+2] = name.unity[2];
         case 2: unities[MAXDIM*i+1] = name.unity[1];
-        case 1: unities[MAXDIM*i+0] = name.unity[0];
+        case 1: unities[MAXDIM*i  ] = name.unity[0];
         case 0: break;
         }
       
@@ -267,16 +267,16 @@ public enum EffectNames
     switch(dimensions[ordinal])
       {
       case 0: break;
-      case 1: buffer[index+0]=unities[MAXDIM*ordinal+0];
+      case 1: buffer[index  ]=unities[MAXDIM*ordinal  ];
               break;
-      case 2: buffer[index+0]=unities[MAXDIM*ordinal+0]; 
+      case 2: buffer[index  ]=unities[MAXDIM*ordinal  ];
               buffer[index+1]=unities[MAXDIM*ordinal+1];
               break;
-      case 3: buffer[index+0]=unities[MAXDIM*ordinal+0]; 
+      case 3: buffer[index  ]=unities[MAXDIM*ordinal  ];
               buffer[index+1]=unities[MAXDIM*ordinal+1]; 
               buffer[index+2]=unities[MAXDIM*ordinal+2];
               break;
-      case 4: buffer[index+0]=unities[MAXDIM*ordinal+0]; 
+      case 4: buffer[index  ]=unities[MAXDIM*ordinal  ];
               buffer[index+1]=unities[MAXDIM*ordinal+1]; 
               buffer[index+2]=unities[MAXDIM*ordinal+2];
               buffer[index+3]=unities[MAXDIM*ordinal+3];
@@ -291,13 +291,13 @@ public enum EffectNames
     switch(dimensions[ordinal])
       {
       case 0: return true;
-      case 1: return buffer[index+0]==unities[MAXDIM*ordinal+0];
-      case 2: return buffer[index+0]==unities[MAXDIM*ordinal+0] && 
+      case 1: return buffer[index  ]==unities[MAXDIM*ordinal  ];
+      case 2: return buffer[index  ]==unities[MAXDIM*ordinal  ] &&
                      buffer[index+1]==unities[MAXDIM*ordinal+1];
-      case 3: return buffer[index+0]==unities[MAXDIM*ordinal+0] && 
+      case 3: return buffer[index  ]==unities[MAXDIM*ordinal  ] &&
                      buffer[index+1]==unities[MAXDIM*ordinal+1] && 
                      buffer[index+2]==unities[MAXDIM*ordinal+2];
-      case 4: return buffer[index+0]==unities[MAXDIM*ordinal+0] && 
+      case 4: return buffer[index  ]==unities[MAXDIM*ordinal  ] &&
                      buffer[index+1]==unities[MAXDIM*ordinal+1] && 
                      buffer[index+2]==unities[MAXDIM*ordinal+2] &&
                      buffer[index+3]==unities[MAXDIM*ordinal+3];
diff --git a/src/main/java/org/distorted/library/EffectQueue.java b/src/main/java/org/distorted/library/EffectQueue.java
index e7b388d..4ee88b5 100644
--- a/src/main/java/org/distorted/library/EffectQueue.java
+++ b/src/main/java/org/distorted/library/EffectQueue.java
@@ -34,7 +34,7 @@ abstract class EffectQueue
   
   protected int[] mName;
   protected float[] mUniforms;
-  protected Dynamic[][] mInter;  // center of the effect
+  protected Dynamic[][] mInter;
   protected long[] mCurrentDuration;
   protected byte[] mFreeIndexes;
   protected byte[] mIDIndex;
diff --git a/src/main/java/org/distorted/library/EffectQueueMatrix.java b/src/main/java/org/distorted/library/EffectQueueMatrix.java
index 4144a4d..27b172f 100644
--- a/src/main/java/org/distorted/library/EffectQueueMatrix.java
+++ b/src/main/java/org/distorted/library/EffectQueueMatrix.java
@@ -89,7 +89,7 @@ class EffectQueueMatrix extends EffectQueue
 
   static void getUniforms(int mProgramH)
     {
-    mBmpDH     = GLES20.glGetUniformLocation(mProgramH, "u_bmpD");
+    mBmpDH     = GLES20.glGetUniformLocation(mProgramH, "u_objD");
     mDepthH    = GLES20.glGetUniformLocation(mProgramH, "u_Depth");
     mMVPMatrixH= GLES20.glGetUniformLocation(mProgramH, "u_MVPMatrix");
     mMVMatrixH = GLES20.glGetUniformLocation(mProgramH, "u_MVMatrix"); 
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 2be84f3..4c5b18d 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -17,7 +17,7 @@
 // along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                       //
 //////////////////////////////////////////////////////////////////////////////////////////////
 
-uniform vec3 u_bmpD;                      // half of object width x half of object height X half the depth; 
+uniform vec3 u_objD;                      // half of object width x half of object height X half the depth;
                                           // point (0,0,0) is the center of the object
 
 uniform float u_Depth;                    // max absolute value of v.z ; beyond that the vertex would be culled by the near or far planes.
@@ -90,9 +90,9 @@ uniform vec3 vUniforms[3*NUM_VERTEX];     // i-th effect is 3 consecutive vec3's
 //
 //    If we are dragging the top edge:    
 //
-//    Now point (x,u_bmpD.x) on the top edge will move by vector (X(t),Y(t)) where those functions are given by (*) and
-//    t =  x < dSx ? (u_bmpD.x+x)/(u_bmpD.x+dSx) : (u_bmpD.x-x)/(u_bmpD.x-dSx)   
-//    Any point (x,y) will move by vector (a*X(t),a*Y(t)) where a is (y+u_bmpD.y)/(2*u_bmpD.y)
+//    Now point (x,u_objD.x) on the top edge will move by vector (X(t),Y(t)) where those functions are given by (*) and
+//    t =  x < dSx ? (u_objD.x+x)/(u_objD.x+dSx) : (u_objD.x-x)/(u_objD.x-dSx)
+//    Any point (x,y) will move by vector (a*X(t),a*Y(t)) where a is (y+u_objD.y)/(2*u_objD.y)
   
 void deform(in int effect, inout vec4 v)
   {
@@ -100,14 +100,14 @@ void deform(in int effect, inout vec4 v)
   vec2 w = vUniforms[effect].xy;    // w = vec(MM')
   vec2 vert_vec, horz_vec; 
   vec2 signXY = sign(p-v.xy);  
-  vec2 time = (u_bmpD.xy+signXY*v.xy)/(u_bmpD.xy+signXY*p);
-  vec2 factorV = vec2(0.5,0.5) + sign(p)*v.xy/(4.0*u_bmpD.xy);
-  vec2 factorD = (u_bmpD.xy-signXY*p)/(2.0*u_bmpD.xy);
+  vec2 time = (u_objD.xy+signXY*v.xy)/(u_objD.xy+signXY*p);
+  vec2 factorV = vec2(0.5,0.5) + sign(p)*v.xy/(4.0*u_objD.xy);
+  vec2 factorD = (u_objD.xy-signXY*p)/(2.0*u_objD.xy);
   vec2 vert_d = factorD.x*w;
   vec2 horz_d = factorD.y*w;
-  vec2 corr = 0.33 / ( 1.0 + (4.0*u_bmpD.x*u_bmpD.x)/dot(w,w) ) * (p+w+signXY*u_bmpD.xy); // .x = the vector tangent to X(t) at Fl = 0.3*vec(LM')  (or vec(RM') if signXY.x=-1). 
-                                                                                       // .y = the vector tangent to X(t) at Fb = 0.3*vec(BM')  (or vec(TM') if signXY.y=-1)
-                                                                                       // the scalar: make the length of the speed vectors at Fl and Fr be 0 when force vector 'w' is zero 
+  vec2 corr = 0.33 / ( 1.0 + (4.0*u_objD.x*u_objD.x)/dot(w,w) ) * (p+w+signXY*u_objD.xy); // .x = the vector tangent to X(t) at Fl = 0.3*vec(LM')  (or vec(RM') if signXY.x=-1).
+                                                                                          // .y = the vector tangent to X(t) at Fb = 0.3*vec(BM')  (or vec(TM') if signXY.y=-1)
+                                                                                          // the scalar: make the length of the speed vectors at Fl and Fr be 0 when force vector 'w' is zero
   vert_vec.x = ( w.x-vert_d.x-corr.x )*time.x*time.x + corr.x*time.x + vert_d.x;
   horz_vec.y = (-w.y+horz_d.y+corr.y )*time.y*time.y - corr.y*time.y - horz_d.y;
   vert_vec.y = (-3.0*vert_d.y+2.0*w.y )*time.x*time.x*time.x + (-3.0*w.y+5.0*vert_d.y )*time.x*time.x - vert_d.y*time.x - vert_d.y;
@@ -133,18 +133,24 @@ void deform(in int effect, inout vec4 v)
 //
 // the trick below is the if-less version of the
 // 
-// t = dx<0.0 ? (u_bmpD.x-v.x) / (u_bmpD.x-ux) : (u_bmpD.x+v.x) / (u_bmpD.x+ux);
-// h = dy<0.0 ? (u_bmpD.y-v.y) / (u_bmpD.y-uy) : (u_bmpD.y+v.y) / (u_bmpD.y+uy);
+// t = dx<0.0 ? (u_objD.x-v.x) / (u_objD.x-ux) : (u_objD.x+v.x) / (u_objD.x+ux);
+// h = dy<0.0 ? (u_objD.y-v.y) / (u_objD.y-uy) : (u_objD.y+v.y) / (u_objD.y+uy);
 // d = min(t,h);      
 //
-// float d = min(-ps.x/(sign(ps.x)*u_bmpD.x+p.x),-ps.y/(sign(ps.y)*u_bmpD.y+p.y))+1.0;    
-
+// float d = min(-ps.x/(sign(ps.x)*u_objD.x+p.x),-ps.y/(sign(ps.y)*u_objD.y+p.y))+1.0;
+//
+// We still have to avoid division by 0 when p.x = +- u_objD.x or p.y = +- u_objD.y (i.e on the edge of the Object)
+// We do that by first multiplying the above 'float d' with sign(denominator1*denominator2)^2.
+//
 //////////////////////////////////////////////////////////////////////////////////////////////
 // return degree of the point as defined by the bitmap rectangle
    
 float degree_bitmap(in vec2 S, in vec2 PS)
   {
-  return min(-PS.x/(sign(PS.x)*u_bmpD.x+S.x),-PS.y/(sign(PS.y)*u_bmpD.y+S.y))+1.0;    
+  vec2 A = sign(PS)*u_objD.xy + S;
+  float B = sign(A.x*A.y);
+
+  return B*B*(1.0 + min(-PS.x/A.x,-PS.y/A.y));
   }
 
 //////////////////////////////////////////////////////////////////////////////////////////////
@@ -168,7 +174,9 @@ float degree(in vec3 region, in vec2 S, in vec2 PS)
   {
   vec2 PO  = PS + region.xy;
   float D = region.z*region.z-dot(PO,PO);      // D = |OX|^2 - |PO|^2
-  float E = min(-PS.x/(sign(PS.x)*u_bmpD.x+S.x),-PS.y/(sign(PS.y)*u_bmpD.y+S.y))+1.0;    
+  vec2 A = sign(PS)*u_objD.xy + S;
+  float B = sign(A.x*A.y);
+  float E = B*B*(1.0 + min(-PS.x/A.x,-PS.y/A.y));
   float ps_sq = dot(PS,PS);
   float DOT  = dot(PS,PO)/ps_sq;
   
@@ -311,7 +319,7 @@ void restrict(inout float v)
   		  
 void main()                                                 	
   {              
-  vec4 v = vec4( 2.0*u_bmpD*a_Position,1.0 );
+  vec4 v = vec4( 2.0*u_objD*a_Position,1.0 );
   vec4 n = vec4(a_Normal,0.0);
 
 #if NUM_VERTEX>0
