THANKS Torious, got it:
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();
}
old: Right now I have this code that I made based on the api sample that comes with the 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;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
The important this is the wrap function at the end. Here's what it produces.
// blue dots are the vertexes of the original matrix, while the red ones show how they moved from the click ( yellow dot ).
Yet that I need is it not to pinch in a vertex, but to sort of smudge it, like this.
For example, this smudge function could take in pixel or vertex coordinates from where to start the smudge, x and y offset and strength of the smudge, i.e. how hard should be the surrounding vertexes be affected.
Any ideas how to do that?
edit: basically I'm trying to make something similar to http://www.andwobble.com/
Thanks!
Ok, I got a (Flash) demo working that looks to be what you need.
I haven't transformed a textured mesh, but only vertices, so it's hard to verify if the effect is exactly as intended, but it looks to be a step in the right direction.
Anyway, here is the code; it's in AS3 but I doubt it'll be hard to understand.
Some notes:
CENTER
in the code below would be the starting point of the smudge operation, as you describe it above. The controlPoint
would be the end point.Vector3D
, but only using its 2D coordinates.CENTER
, controlPoint
and the input vertex
are treated as if in the same coordinate system. You could instead pre-process CENTER
to be relative to your mesh's local coordinate system. Then you could strip the transforms to/from the relative/local coordinate system that are in the code below.Try it out and let me know if you have trouble understanding the AS3 code.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With