How to rotate a canvas at a specific point using android.graphics.Camera.rotateX(angle)

前端 未结 4 1049
一向
一向 2021-02-06 12:27

I am trying to use the Camera (android.graphics.Camera not the hardware camera) to rotate a views canvas around a specific point, in this instance the middle of the canvas.

相关标签:
4条回答
  • 2021-02-06 12:48

    I like to do things the difficult way and "roll my own". Moreover, if you are doing animations cumulative errors can creep in concat'ing Matrix's.

    float rotate; // rotation in degrees
    
    float vcx; // center of rotation of view
    float vcy;
    
    float gcx; // center of rotation of graphic
    float gcy;
    
    float theta = (float) (Math.PI/180.0*rotate);
    float sin = (float) Math.sin(theta);
    float cos = (float) Math.cos(theta);
    
    float[] a = new float[9];
    a[Matrix.MSCALE_X] = cos;
    a[Matrix.MSKEW_X] = sin;
    a[Matrix.MTRANS_X] = vcx-gcx*cos-gcy*sin;
    a[Matrix.MSCALE_Y] = cos;
    a[Matrix.MSKEW_Y] = -sin;
    a[Matrix.MTRANS_Y] = vcy-gcy*cos+gcx*sin;
    a[Matrix.MPERSP_0] = 0.0f;
    a[Matrix.MPERSP_1] = 0.0f;
    a[Matrix.MPERSP_2] = 1.0f;
    
    Matrix m = new Matrix();
    m.setValues(a);
    view.setImageMatrix(m); // or setMatrix or whatever you're using.
    
    0 讨论(0)
  • 2021-02-06 12:50

    Use this as the transformation in your animation class

    protected void applyTransformation(float interpolatedTime, Transformation t) {
    
        final float fromDegrees = 0;
    
        float degrees = fromDegrees
    
        + ((180- fromDegrees) * interpolatedTime);
    
        final float centerX = mCenterX;
    
        final float centerY = mCenterY;
    
        final Camera camera = mCamera;
    
        final Matrix matrix = t.getMatrix();
    
        camera.save();
    
        camera.rotateX(degrees);
    
        camera.getMatrix(matrix);
    
        camera.restore();
    
        matrix.preTranslate(-centerX, -centerY);
    
        matrix.postTranslate(centerX, centerY);
    
    }
    
    0 讨论(0)
  • 2021-02-06 13:06

    This worked for me:

    @Override
    public void drawPixmap3D(Pixmap pixmap, int x, int y, int r) {
        Camera camera = mCamera;
        int cx = pixmap.getWidth()/2;
        camera.save();
        camera.rotateY(r);
        camera.getMatrix(mtx);
        mtx.preTranslate(-cx, 0);
        mtx.postTranslate(x, y);
        camera.restore();
        canvas.drawBitmap(((AndroidPixmap)pixmap).bitmap, mtx, this.paint);
    }
    
    0 讨论(0)
  • 2021-02-06 13:09

    Solved this, not sure if it's the best way but it works. The solution was to

    Translate the canvas first to center the larger canvas in the display

    Then apply the camera rotations

    Then to use the pre and post translate methods on the matrix to change the rotation point similar to what the android sample did.

    The missing bits were to do the canvas translation first, and I was also not using the larger canvas size to calculate the offsets for the pre and post translate methods.

    Here is the modified code if it helps anyone else out.

    // Center larger canvas in display (was made larger so
    // corners will not show when rotated) 
    canvas.translate(-translateX, -translateY); 
    
    // Use the camera to rotate a view on any axis
    camera.save();
        camera.rotateX(0);
        camera.rotateY(0);
        camera.rotateZ(angle); // Rotate around Z access (similar to canvas.rotate)                                 
    
        camera.getMatrix(cameraMatrix);
    
        // This moves the center of the view into the upper left corner (0,0) 
        // which is necessary because Matrix always uses 0,0, as it's transform point 
        cameraMatrix.preTranslate(-centerScaled, -centerScaled);
    
        // NOTE: Camera Rotations logically happens here when the canvas has the 
        // matrix applied in the canvas.concat method 
    
        // This happens after the camera rotations are applied, moving the view 
        // back to where it belongs, allowing us to rotate around the center or 
        // any point we choose 
        cameraMatrix.postTranslate(centerScaled, centerScaled);
    camera.restore();
    
    canvas.concat(cameraMatrix);
    

    If anyone has a better way or sees a problem please leave a comment.

    0 讨论(0)
提交回复
热议问题