java - 在 Android 中为涂抹/Swing 效果制作矩阵(参见图片)

标签 java android matrix

谢谢 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;
        }

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

    }

重要的是最后的包装功能。这是它产生的结果。

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

enter image description here

然而,我需要的不是捏住一个顶点,而是像这样涂抹它。

enter image description here

例如,这个涂抹函数可以获取开始涂抹的像素或顶点坐标、x 和 y 偏移以及涂抹的强度,即影响周围顶点的强度。

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

编辑:基本上我正在尝试制作类似于 http://www.andwobble.com/ 的东西

谢谢!

最佳答案

好的,我有一个看起来是你需要的(Flash)演示。

我没有转换纹理网格,而只是转换顶点,因此很难验证效果是否完全符合预期,但它看起来是朝着正确方向迈出的一步。

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

一些注意事项:

  • CENTER正如您在上面描述的那样,在下面的代码中将是涂抹操作的起点。 controlPoint将是终点。
  • 我正在使用 Vector3D ,但仅使用其二维坐标。
  • 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);
    
        }
    

    关于java - 在 Android 中为涂抹/Swing 效果制作矩阵(参见图片),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10154781/

    相关文章:

    java - 扩展类和静态变量

    java - 无限递归帮助-Java

    java - 使用 try-with-resources java 关闭数据库连接

    java - 在Android服务中安排的AsyncTask仅正确执行一次

    android - Google Play 上的应用程序始终显示 "Update"而不是打开

    algorithm - 寻找一个“正周期”

    java - 用于 Java 的 Vim 自动完成

    android - IAC(查询访问代码)设置不同于GIAC的设备的蓝牙查询?

    r - R中多行的一种热编码

    haskell - 代码在 Elm 中编译,但在 Haskell 中不编译