java 矩阵 图片,java - 在Android中制作污点/摆动效果的矩阵(参见图片)

,感谢Torious,明白了: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();

}

旧版:

现在,我有了基于SDK附带的api示例制作的这段代码。

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;

}

}

重要的是最后的换行功能。这就是它产生的东西。

//蓝色圆点是原始矩阵的顶点,红色圆点表示它们如何从点击中移动(黄色圆点)。

但是,我需要的是不要像这样捏顶点,而要对其进行涂抹。

例如,此污迹函数可以获取开始污迹的像素或顶点坐标,x和y偏移量以及污迹的强度,即周围顶点受到的影响程度。

任何想法如何做到这一点?

最佳答案

好的,我得到了一个(Flash)演示,看起来很符合您的需求。

我没有变换纹理化的网格,而是仅变换了顶点,因此很难验证效果是否完全符合预期,但这似乎是朝着正确方向迈出的一步。

无论如何,这是代码;它在AS3中,但我怀疑它很难理解。

一些注意事项:

如上面所描述的,下面代码中的

CENTER将是涂抹操作的起点。 controlPoint将是终点。

我正在使用Vector3D,但仅使用其2D坐标。

CENTER,controlPoint和输入的vertex被视为在同一坐标系中。相反,您可以预处理CENTER以使其相对于网格的局部坐标系。然后,您可以剥离下面代码中相对于/相对于本地坐标系的变换。

逻辑函数用于从没有影响的影响圆的边缘过渡到完全影响。您可能还可以使用其他几个功能来达到类似的效果。

我认为使用额外的第二个“拉至控制点”操作,以较小的强度和较小的陡峭过渡将使效果更好;现在,我感觉所有完全过渡到(接近)100%影响力的顶点朝着控制点的移动都太多了。

尝试一下,如果您在理解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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值