Package advanced.touchTail

Source Code of advanced.touchTail.TailGesture

package advanced.touchTail;

import java.awt.Polygon;

import org.mt4j.util.MTColor;
import org.mt4j.util.math.ToolsMath;
import org.mt4j.util.math.Vector3D;

import processing.core.PApplet;

/**
* The Class TailGesture.
*
* Yellowtail by Golan Levin (www.flong.com)
* Yellowtail (1998-2000) is an interactive software system for the gestural creation
* and performance of real-time abstract animation. Yellowtail repeats a user's strokes end-over-end,
* enabling simultaneous specification of a line's shape and quality of movement.
* Each line repeats according to its own period,
* producing an ever-changing and responsive display of lively, worm-like textures.
*/
public class TailGesture {

//  private float  damp = 5.0f; //ORIGINAL
  private float  damp = 5.0f;
  private float  dampInv = 1.0f / damp;
  private float  damp1 = damp - 1;

  private int w;
  private int h;
  private int capacity;

  private float INIT_TH = 14; //ORIGINAL
//  private float INIT_TH = 24;
  private float   thickness = INIT_TH;

  Vector3D path[];
  int crosses[];
  Polygon polygons[];
  int nPoints;
  int nPolys;

  float jumpDx;
  float jumpDy;
  boolean exists;
  private MTColor color;

  public TailGesture(int mw, int mh) {
    w = mw;
    h = mh;
    capacity = 600;
    path = new Vector3D[capacity];
    polygons = new Polygon[capacity];
    crosses  = new int[capacity];
    for (int i=0;i<capacity;i++) {
      polygons[i] = new Polygon();
      polygons[i].npoints = 4;
      path[i] = new Vector3D();
      crosses[i] = 0;
    }
    nPoints = 0;
    nPolys = 0;

    exists = false;
    jumpDx = 0;
    jumpDy = 0;
   
//    this.color = new MTColor(Tools3D.getRandom(50, 255), Tools3D.getRandom(50, 255), Tools3D.getRandom(50, 255), 255);
    this.color = new MTColor(ToolsMath.getRandom(0, 255), ToolsMath.getRandom(0, 255), ToolsMath.getRandom(0, 255), 255);
  }

  public void clear() {
    nPoints = 0;
    exists = false;
    thickness = INIT_TH;
  }

  public void clearPolys() {
    nPolys = 0;
  }

  public void addPoint(float x, float y) {
    if (nPoints >= capacity) {
      // there are all sorts of possible solutions here,
      // but for abject simplicity, I don't do anything.
    }
    else {
      float v = distToLast(x, y);
      float p = getPressureFromVelocity(v);
      path[nPoints++].setXYZ(x,y,p);

      if (nPoints > 1) {
        exists = true;
        jumpDx = path[nPoints-1].x - path[0].x;
        jumpDy = path[nPoints-1].y - path[0].y;
      }
    }

  }

  private float getPressureFromVelocity(float v) {
    final float scale = 18;
    final float minP = 0.02f;
    final float oldP = (nPoints > 0) ? path[nPoints-1].z : 0;
    return ((minP + PApplet.max(0, 1.0f - v/scale)) + (damp1*oldP))*dampInv;
  }

  private void setPressures() {
    // pressures vary from 0...1
    float pressure;
    Vector3D tmp;
    float t = 0;
    float u = 1.0f / (nPoints - 1)*PApplet.TWO_PI;
    for (int i = 0; i < nPoints; i++) {
      pressure = PApplet.sqrt((1.0f - PApplet.cos(t)) * 0.5f);
      path[i].z = pressure;
      t += u;
    }
  }

  public float distToLast(float ix, float iy) {
    if (nPoints > 0) {
      Vector3D v = path[nPoints-1];
      float dx = v.x - ix;
      float dy = v.y - iy;
      return PApplet.mag(dx, dy);
    }
    else {
      return 30;
    }
  }

  public  void compile() {
    // compute the polygons from the path of Vector3D's
    if (exists) {
      clearPolys();

      Vector3D p0, p1, p2;
      float radius0, radius1;
      float ax, bx, cx, dx;
      float ay, by, cy, dy;
      int   axi, bxi, cxi, dxi, axip, axid;
      int   ayi, byi, cyi, dyi, ayip, ayid;
      float p1x, p1y;
      float dx01, dy01, hp01, si01, co01;
      float dx02, dy02, hp02, si02, co02;
      float dx13, dy13, hp13, si13, co13;
      float taper = 1.0f;

      int  nPathPoints = nPoints - 1;
      int  lastPolyIndex = nPathPoints - 1;
      float npm1finv =  1.0f / PApplet.max(1, nPathPoints - 1);

      // handle the first point
      p0 = path[0];
      p1 = path[1];
      radius0 = p0.z * thickness;
      dx01 = p1.x - p0.x;
      dy01 = p1.y - p0.y;
      hp01 = PApplet.sqrt(dx01*dx01 + dy01*dy01);
      if (hp01 == 0) {
        hp02 = 0.0001f;
      }
      co01 = radius0 * dx01 / hp01;
      si01 = radius0 * dy01 / hp01;
      ax = p0.x - si01;
      ay = p0.y + co01;
      bx = p0.x + si01;
      by = p0.y - co01;

      int xpts[];
      int ypts[];

      int LC = 20;
      int RC = w-LC;
      int TC = 20;
      int BC = h-TC;
      float mint = 0.618f;
      float tapow = 0.4f;

      // handle the middle points
      int i = 1;
      Polygon apoly;
      for (i = 1; i < nPathPoints; i++) {
        taper = PApplet.pow((lastPolyIndex-i) * npm1finv, tapow);

        p0 = path[i-1];
        p1 = path[];
        p2 = path[i+1];
        p1x = p1.x;
        p1y = p1.y;
        radius1 = Math.max(mint, taper * p1.z * thickness);

        // assumes all segments are roughly the same length...
        dx02 = p2.x - p0.x;
        dy02 = p2.y - p0.y;
        hp02 = (float) Math.sqrt(dx02*dx02 + dy02*dy02);
        if (hp02 != 0) {
          hp02 = radius1/hp02;
        }
        co02 = dx02 * hp02;
        si02 = dy02 * hp02;

        // translate the integer coordinates to the viewing rectangle
        axi = axip = (int)ax;
        ayi = ayip = (int)ay;
        axi=(axi<0)?(w-((-axi)%w)):axi%w;
        axid = axi-axip;
        ayi=(ayi<0)?(h-((-ayi)%h)):ayi%h;
        ayid = ayi-ayip;

        // set the vertices of the polygon
        apoly = polygons[nPolys++];
        xpts = apoly.xpoints;
        ypts = apoly.ypoints;
        xpts[0] = axi = axid + axip;
        xpts[1] = bxi = axid + (int) bx;
        xpts[2] = cxi = axid + (int)(cx = p1x + si02);
        xpts[3] = dxi = axid + (int)(dx = p1x - si02);
        ypts[0] = ayi = ayid + ayip;
        ypts[1] = byi = ayid + (int) by;
        ypts[2] = cyi = ayid + (int)(cy = p1y - co02);
        ypts[3] = dyi = ayid + (int)(dy = p1y + co02);

        // keep a record of where we cross the edge of the screen
        crosses[i] = 0;
        if ((axi<=LC)||(bxi<=LC)||(cxi<=LC)||(dxi<=LC)) {
          crosses[i]|=1;
        }
        if ((axi>=RC)||(bxi>=RC)||(cxi>=RC)||(dxi>=RC)) {
          crosses[i]|=2;
        }
        if ((ayi<=TC)||(byi<=TC)||(cyi<=TC)||(dyi<=TC)) {
          crosses[i]|=4;
        }
        if ((ayi>=BC)||(byi>=BC)||(cyi>=BC)||(dyi>=BC)) {
          crosses[i]|=8;
        }

        //swap data for next time
        ax = dx;
        ay = dy;
        bx = cx;
        by = cy;
      }

      // handle the last point
      p2 = path[nPathPoints];
      apoly = polygons[nPolys++];
      xpts = apoly.xpoints;
      ypts = apoly.ypoints;

      xpts[0] = (int)ax;
      xpts[1] = (int)bx;
      xpts[2] = (int)(p2.x);
      xpts[3] = (int)(p2.x);

      ypts[0] = (int)ay;
      ypts[1] = (int)by;
      ypts[2] = (int)(p2.y);
      ypts[3] = (int)(p2.y);
    }
  }

  public void smooth() {
    // average neighboring points
    final float weight = 18;
    final float scale  = 1.0f / (weight + 2);
    int nPointsMinusTwo = nPoints - 2;
    Vector3D lower, upper, center;

    for (int i = 1; i < nPointsMinusTwo; i++) {
      lower = path[i-1];
      center = path[i];
      upper = path[i+1];

      center.x = (lower.x + weight*center.x + upper.x)*scale;
      center.y = (lower.y + weight*center.y + upper.y)*scale;
    }
  }

  public MTColor getColor() {
    return color;
  }

  public void setColor(MTColor color) {
    this.color = color;
  }
 
 

}

TOP

Related Classes of advanced.touchTail.TailGesture

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.