2012-04-14 5 views
7

GRACIAS Torious, lo consiguió:Hacer una matriz para un effet smuge/oscilante (ver fotos) en el Android

private void smudge() { 


     for (int i = 0; i < COUNT*2; i += 2) { 

      float xOriginal = matrixOriganal[i+0]; 
      float yOriginal = matrixOriganal[i+1]; 

      float distX = Math.abs(pointX-xOriginal); 
      float distY = Math.abs(pointY-yOriginal); 

      float dist = FloatMath.sqrt(distX*distX + distY*distY); 

      float coof = (bubbleSize - dist)/bubbleSize; 

     float oc = (float) -Math.sin(coof * 2*Math.PI) * 0.15f ; 

      if (dist < bubbleSize) 
      { 
      matrixVertsMoved[i+0] = xOriginal + smudgeAmount * (coof+oc); 
      matrixVertsMoved[i+1] = yOriginal; 
      } 
      else 
      { 
      matrixVertsMoved[i+0] = xOriginal; 
      matrixVertsMoved[i+1] = yOriginal; 
      } 


     } 

     invalidate(); 
    } 

antigua: En este momento tengo este código que Hice basado en la muestra de API que viene con el SDK.

public class main extends Activity { 

    //////////////////////////////////////////////////////// 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.main); 

     LinearLayout ll01 = (LinearLayout)findViewById(R.id.linearLayout1); 

     SampleView sv = new SampleView(this); 
     ll01.addView(sv); 
    } 

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    private static class SampleView extends View { 
     static int WIDTH = 8; // sections 
     static int HEIGHT = 8; 
     static int COUNT = (WIDTH + 1) * (HEIGHT + 1); // total verts count 

     Bitmap mBitmap; // declaring a bitmap 
     float[] matrixVertsMoved = new float[COUNT*2]; // declaring an array with double amount of vert count, one for x and one for y 
     float[] matrixOriganal = new float[COUNT*2]; 

     float clickX; 
     float clickY; 

     static void setXY(float[] array, int index, float x, float y) { 
      array[index*2 + 0] = x; 
      array[index*2 + 1] = y; 
     } 

     /// 

     public SampleView(Context context) { 
      super(context); 
      setFocusable(true); 

      mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.w); 


      // construct our mesh 
      int index = 0; 
      for (int y = 0; y <= HEIGHT; y++) { 
       float fy = mBitmap.getHeight() * y/HEIGHT; 

       for (int x = 0; x <= WIDTH; x++) { 
        float fx = mBitmap.getWidth() * x/WIDTH; 
        setXY(matrixVertsMoved, index, fx, fy); 
        setXY(matrixOriganal, index, fx, fy); 
        index += 1; 
       } 

      } 

     } 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

     @Override 
     protected void onDraw(Canvas canvas) { 


      canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, matrixVertsMoved, 0, null, 0, null); 

      Paint p1 = new Paint(); 
      p1.setColor(0x660000FF); 

      Paint p2 = new Paint(); 
      p2.setColor(0x99FF0000); 

      Paint p3 = new Paint(); 
      p3.setColor(0xFFFFFB00); 

      for (int i = 0; i < COUNT*2; i += 2) { 
       float x = matrixOriganal[i+0]; 
       float y = matrixOriganal[i+1]; 
       canvas.drawCircle(x, y, 4, p1); 

       float x1 = matrixOriganal[i+0]; 
       float y1 = matrixOriganal[i+1]; 
       float x2 = matrixVertsMoved[i+0]; 
       float y2 = matrixVertsMoved[i+1]; 
       canvas.drawLine(x1, y1, x2, y2, p1); 
      } 

      for (int i = 0; i < COUNT*2; i += 2) { 
       float x = matrixVertsMoved[i+0]; 
       float y = matrixVertsMoved[i+1]; 
       canvas.drawCircle(x, y, 4, p2); 
      } 

      canvas.drawCircle(clickX, clickY, 6, p3); 


     } 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

     private void smudge() { 


      for (int i = 0; i < COUNT*2; i += 2) { 

       float xOriginal = matrixOriganal[i+0]; 
       float yOriginal = matrixOriganal[i+1]; 

       float dist_click_to_origin_x = clickX - xOriginal; // distance from current vertex in the original matrix to the place clicked. 
       float dist_click_to_origin_y = clickY - yOriginal; 

       float kv_kat = dist_click_to_origin_x*dist_click_to_origin_x + dist_click_to_origin_y*dist_click_to_origin_y; 

       float pull = (1000000/kv_kat/FloatMath.sqrt(kv_kat)); 

       if (pull >= 1) { 
        matrixVertsMoved[i+0] = clickX; 
        matrixVertsMoved[i+1] = clickY; 
       } else { 
        matrixVertsMoved[i+0] = xOriginal + dist_click_to_origin_x * pull; 
        matrixVertsMoved[i+1] = yOriginal + dist_click_to_origin_y * pull; 
       } 

      } 


     } 


//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

     @Override 
     public boolean onTouchEvent(MotionEvent event) { 

       clickX = event.getX(); 
       clickY = event.getY(); 
       smudge(); // change the matrix. 
       invalidate(); // calls a redraw on the canvas. 

      return true; 
     } 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    } 

Lo importante es la función de envolver al final. Esto es lo que produce.

// los puntos azules son los vértices de la matriz original, mientras que los rojos muestran cómo se movieron desde el clic (punto amarillo).

enter image description here

embargo que lo que necesito es que no pellizcar en un vértice, sino a una especie de mancha que, como este.

enter image description here

Por ejemplo, esta función mancha podría tomar en píxeles o vértice coordenadas desde donde comenzar la mancha, X e Y de desplazamiento y la fuerza de la mancha, es decir, lo difícil debe ser verán afectados los vértices de los alrededores.

¿Alguna idea de cómo hacer eso?

edición: básicamente estoy tratando de hacer algo similar a http://www.andwobble.com/

Gracias!

Respuesta

2

Ok, tengo una demo (Flash) funcionando que parece ser lo que necesita.

No he transformado una malla texturizada, sino solo vértices, por lo que es difícil verificar si el efecto es exactamente el deseado, pero parece ser un paso en la dirección correcta.

De todos modos, aquí está el código; está en AS3 pero dudo que sea difícil de entender.

Algunas notas:

  • CENTER en el código de abajo serían el punto de partida de la operación de mancha, que usted describe anteriormente. El controlPoint sería el punto final.
  • Estoy usando Vector3D, pero solo usando sus coordenadas 2D.
  • CENTER, controlPoint y la entrada vertex se tratan como si estuvieran en el mismo sistema de coordenadas. En su lugar, podría preprocesar CENTER en relación con el sistema de coordenadas local de su malla. Luego, podría quitar las transformaciones al/del sistema de coordenadas local/relativo que se encuentran en el código a continuación.
  • La función logística se utiliza para la transición desde el borde del círculo de influencia sin influencia, a la plena influencia. Probablemente pueda usar varias otras funciones para un efecto similar.
  • Creo que el uso de una segunda operación adicional de "extracción al punto de control" con una fuerza menor y una transición menos pronunciada mejoraría el efecto; en este momento todos los vértices que están completamente en transición a (cerca de) 100% de influencia se mueven un poco hacia el punto de control al unísono, creo.

Pruébalo y avísame si tienes problemas para entender el código AS3.

private function log(t:Number):Number { 
     return 1/(1 + Math.pow(Math.E, -t)); 
    } 

    private function transformVertex(vertex:Vector3D, controlPoint:Vector3D):Vector3D { 

     // get control point relative to center of influence 
     // (this could actually be calculated in pre-processing, as 
     // it doesn't change between vertices) 
     var controlPointRel:Vector3D = controlPoint.subtract(CENTER); 

     // get vertex relative to center of influence 
     var rel:Vector3D = vertex.subtract(CENTER); 

     // get distance of vertex from center 
     var dst:Number = rel.length/RADIUS; 
     if (dst > 1) return vertex; // vertex outside circle of influence 


     // PULL TO CONTROL POINT 

     // tScale controls the steepness of the transition from the 
     // edge of the circle. 1 = logistic transition, >1 = steeper 
     var tScale:Number = 1.7; 
     var t:Number = (1 - dst) * 12 * tScale - 6; // [-6, 6] 
     t = log(t); 

     controlPointRel = controlPointRel.clone(); 
     controlPointRel.scaleBy(t); 
     // ALTERNATIVE, try this too: 
     // controlPointRel.scaleBy(t * (1 - dst)); 

     rel = rel.add(controlPointRel); 

     // relative to absolute 
     return rel.add(CENTER); 

    } 
+0

Gracias, en su mayoría, me di cuenta de para qué era la función original. Vea el código editado con los comentarios anteriores. :) –

Cuestiones relacionadas