commit 82ee855ae8333d33c145c4b035b9b7cdc4b517c0
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Mon Nov 14 22:50:43 2016 +0000

    New vertex effect 'PINCH'

diff --git a/src/main/java/org/distorted/library/DistortedObject.java b/src/main/java/org/distorted/library/DistortedObject.java
index 86c00c7..239fda7 100644
--- a/src/main/java/org/distorted/library/DistortedObject.java
+++ b/src/main/java/org/distorted/library/DistortedObject.java
@@ -789,6 +789,35 @@ public abstract class DistortedObject
     return mV.add(EffectNames.SINK, sink, center);
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Pull all points around the center of the Effect towards a line passing through the center
+ * (that's if degree>=1) or push them away from the line (degree<=1)
+ *
+ * @param pinch  The current degree of the Effect + angle the line forms with X-axis
+ * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @param region Region that masks the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
+ */
+  public long pinch(Data2D pinch, Data3D center, Data4D region)
+    {
+    return mV.add(EffectNames.PINCH, pinch, center, region);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Pull all points around the center of the Effect towards a line passing through the center
+ * (that's if degree>=1) or push them away from the line (degree<=1)
+ *
+ * @param pinch  The current degree of the Effect + angle the line forms with X-axis
+ * @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
+ * @return       ID of the effect added, or -1 if we failed to add one.
+ */
+  public long pinch(Data2D pinch, Data3D center)
+    {
+    return mV.add(EffectNames.PINCH, pinch, center);
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////  
 /**
  * Rotate part of the Object around the Center of the Effect by a certain angle.
diff --git a/src/main/java/org/distorted/library/EffectNames.java b/src/main/java/org/distorted/library/EffectNames.java
index 43d00f9..97f4e19 100644
--- a/src/main/java/org/distorted/library/EffectNames.java
+++ b/src/main/java/org/distorted/library/EffectNames.java
@@ -41,7 +41,7 @@ package org.distorted.library;
  */
 public enum EffectNames
   {
-  // EFFECT NAME /////// EFFECT TYPE ////////////// UNITY /////////////////////////
+  // EFFECT NAME /////// EFFECT TYPE ////////////// UNITY /////////////// DIM // REGION // CENTER
 
   /////////////////////////////////////////////////////////////////////////////////
   // MATRIX EFFECTS.
@@ -96,7 +96,7 @@ public enum EffectNames
    * Apply a 3D vector of force to area around a point on the surface of the Object.
    * <p>
    * Uniforms: (forceX ,forceY ,forceZ  ,UNUSED  ,
-   *            UNUSED , UNUSED,centerX ,centerY ,
+   *            UNUSED , centerX ,centerY , centerZ,
    *            regionX,regionY,regionRX,regionRY)
    * <p>
    * Unity: (forceX,forceY,forceZ) = (0,0,0)
@@ -106,7 +106,7 @@ public enum EffectNames
    * Deform the whole Object by applying a 2D vector of force to a center point.
    * <p>
    * Uniforms: (forceX,forceY,UNUSED,UNUSED,
-   *            UNUSED,UNUSED,centerX,centerY,
+   *            UNUSED,centerX,centerY,centerZ,
    *            UNUSED,UNUSED,UNUSED,UNUSED)
    * <p>
    * Unity: (forceX,forceY) = (0,0)
@@ -116,17 +116,27 @@ public enum EffectNames
    * Pull (or push away) all points around a center point to (from) it.
    * <p>
    * Uniforms: (sinkFactor,UNUSED,UNUSED,UNUSED,
-   *            UNUSED,UNUSED,centerX,centerY,
+   *            UNUSED,centerX,centerY,centerZ,
    *            regionX,regionY,regionRX,regionRY)
    * <p>
    * Unity: sinkFactor = 1
    */
   SINK             ( EffectTypes.VERTEX  ,   new float[] {1.0f}           , 1, true, true ),
+  /**
+   * Pull (or push away) all points around a line to (from) it.
+   * <p>
+   * Uniforms: (pinchFactor,lineAngle,UNUSED,UNUSED,
+   *            UNUSED,centerX,centerY,centerZ,
+   *            regionX,regionY,regionRX,regionRY)
+   * <p>
+   * Unity: sinkFactor = 1
+   */
+  PINCH            ( EffectTypes.VERTEX  ,   new float[] {1.0f}           , 2, true, true ),
  /**
    * Smoothly rotate a limited area around a center point.
    * <p>
    * Uniforms: (swirlAngle,UNUSED,UNUSED,UNUSED,
-   *            UNUSED, UNUSED,centerX,centerY,
+   *            UNUSED, centerX,centerY,centerZ,
    *            regionX,regionY,regionRX,regionRY)
    * <p>
    * Unity: swirlAngle = 0
@@ -137,7 +147,7 @@ public enum EffectNames
    * parameters. Details: {@link DistortedObject#wave(Data5D,Data2D)}
    * <p>
    * Uniforms: (amplitude,length,phase,angleAlpha,
-   *            angleBeta, UNUSED,centerX,centerY,
+   *            angleBeta, centerX,centerY,centerZ,
    *            regionX,regionY,regionRX,regionRY)
    * <p>
    * Unity: amplitude  = 0
diff --git a/src/main/java/org/distorted/library/EffectQueueVertex.java b/src/main/java/org/distorted/library/EffectQueueVertex.java
index f8734ae..3a08cbf 100644
--- a/src/main/java/org/distorted/library/EffectQueueVertex.java
+++ b/src/main/java/org/distorted/library/EffectQueueVertex.java
@@ -23,14 +23,17 @@ import android.opengl.GLES20;
 
 import org.distorted.library.message.EffectMessage;
 import org.distorted.library.type.Data1D;
+import org.distorted.library.type.Data2D;
 import org.distorted.library.type.Data3D;
 import org.distorted.library.type.Data4D;
 import org.distorted.library.type.Data5D;
 import org.distorted.library.type.Dynamic1D;
+import org.distorted.library.type.Dynamic2D;
 import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Dynamic4D;
 import org.distorted.library.type.Dynamic5D;
 import org.distorted.library.type.Static1D;
+import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.type.Static5D;
@@ -161,7 +164,7 @@ class EffectQueueVertex extends EffectQueue
 // Do various post-processing on already computed effects.
 // 1) here unlike in the fragment queue, we don't have to multiply the points by ModelView matrix because that gets done in the shader.
 // 2) in case of SWIRL, switch the angles from degrees to radians
-// 3) likewise in case of WAVE
+// 3) likewise in case of WAVE and PINCH
 // 4) In case of DISTORT, invert the Y-axis
   
   private void postprocess(int effect)
@@ -170,6 +173,10 @@ class EffectQueueVertex extends EffectQueue
       {
       mUniforms[NUM_UNIFORMS*effect  ] = (float)(Math.PI*mUniforms[NUM_UNIFORMS*effect  ]/180);
       }
+    if( mName[effect]==EffectNames.PINCH.ordinal() )
+      {
+      mUniforms[NUM_UNIFORMS*effect+1] = (float)(Math.PI*mUniforms[NUM_UNIFORMS*effect+1]/180);
+      }
     if( mName[effect]==EffectNames.WAVE.ordinal() )
       {
       mUniforms[NUM_UNIFORMS*effect+2] = (float)(Math.PI*mUniforms[NUM_UNIFORMS*effect+2]/180);
@@ -292,6 +299,58 @@ class EffectQueueVertex extends EffectQueue
     return -1;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// pinch
+
+  synchronized long add(EffectNames eln, Data2D data, Data3D center, Data4D region)
+    {
+    if( mMax[INDEX]>mNumEffects )
+      {
+      EffectNames.fillWithUnities(eln.ordinal(), mUniforms, NUM_UNIFORMS*mNumEffects);
+
+      if( data instanceof Dynamic2D)
+        {
+        mInter[0][mNumEffects] = (Dynamic2D)data;
+        }
+      else if( data instanceof Static2D)
+        {
+        mInter[0][mNumEffects] = null;
+        mUniforms[NUM_UNIFORMS*mNumEffects  ] = ((Static2D)data).getX();
+        mUniforms[NUM_UNIFORMS*mNumEffects+1] = ((Static2D)data).getY();
+        }
+
+      return addPriv(eln,center,region);
+      }
+
+    return -1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// pinch
+
+  synchronized long add(EffectNames eln, Data2D data, Data3D center)
+    {
+    if( mMax[INDEX]>mNumEffects )
+      {
+      EffectNames.fillWithUnities(eln.ordinal(), mUniforms, NUM_UNIFORMS*mNumEffects);
+
+      if( data instanceof Dynamic2D)
+        {
+        mInter[0][mNumEffects] = (Dynamic2D)data;
+        }
+      else if( data instanceof Static2D)
+        {
+        mInter[0][mNumEffects] = null;
+        mUniforms[NUM_UNIFORMS*mNumEffects  ] = ((Static2D)data).getX();
+        mUniforms[NUM_UNIFORMS*mNumEffects+1] = ((Static2D)data).getY();
+        }
+
+      return addPriv(eln,center,null);
+      }
+
+    return -1;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
   
   private long addPriv(EffectNames eln, Data3D center, Data4D region)
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 09c950d..ed65634 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -309,8 +309,8 @@ void distort(in int effect, inout vec4 v, inout vec4 n)
 //////////////////////////////////////////////////////////////////////////////////////////////
 // SINK EFFECT
 //
-// Pull P=(v.x,v.y) towards S=vPoint[effect] with P' = P + (1-h)d(S-P)
-// when h>1 we are pushing points away from S: P' = P + (1/h-1)d(S-P)
+// Pull P=(v.x,v.y) towards center of the effect with P' = P + (1-h)*dist(S-P)
+// when h>1 we are pushing points away from S: P' = P + (1/h-1)*dist(S-P)
  
 void sink(in int effect,inout vec4 v)
   {
@@ -322,6 +322,27 @@ void sink(in int effect,inout vec4 v)
   v.xy += t*ps;           
   }
 
+//////////////////////////////////////////////////////////////////////////////////////////////
+// PINCH EFFECT
+//
+// Pull P=(v.x,v.y) towards the line that
+// a) passes through the center of the effect
+// b) forms angle defined in the 2nd interpolated value with the X-axis
+// with P' = P + (1-h)*dist(line to P)
+// when h>1 we are pushing points away from S: P' = P + (1/h-1)*dist(line to P)
+
+void pinch(in int effect,inout vec4 v)
+  {
+  vec2 center = vUniforms[effect+1].yz;
+  vec2 ps = center-v.xy;
+  float h = vUniforms[effect].x;
+  float t = degree(vUniforms[effect+2],center,ps) * (1.0-h)/max(1.0,h);
+  float angle = vUniforms[effect].y;
+  vec2 dir = vec2(sin(angle),-cos(angle));
+
+  v.xy += t*dot(ps,dir)*dir;
+  }
+
 //////////////////////////////////////////////////////////////////////////////////////////////
 // SWIRL EFFECT
 //
@@ -492,6 +513,7 @@ void main()
          if( vType[i]==DISTORT) distort(3*i,v,n);
     else if( vType[i]==DEFORM ) deform (3*i,v);
     else if( vType[i]==SINK   ) sink   (3*i,v);
+    else if( vType[i]==PINCH  ) pinch  (3*i,v);
     else if( vType[i]==SWIRL  ) swirl  (3*i,v);
     else if( vType[i]==WAVE   ) wave   (3*i,v,n);
     }
