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

I'm trying to use Camera (android.graphics.Camera, not a hardware camera) to rotate the canvas of views around a certain point, in this case, in the middle of the canvas.

In dispatchDraw (Canvas Canvas) - for brevity, I leave all the unimportant parts.

camera.save(); camera.rotateX(0); camera.rotateY(0); camera.rotateZ(angle); camera.getMatrix(cameraMatrix); camera.restore(); canvas.concat( cameraMatrix ); 

The canvas rotates, but always from the upper left corner.

NOTE. Since the canvas was designed to be larger than the display area, I also need to translate the final result so that it is centered on the display, I can do this with

 canvas.translate(xOffset,yOffset) PRIOR to calling the camera methods 

OR

 cameraMatrix.preTranslate(xOffset,yOffset) AFTER the camera methods 

Both correctly center the canvas on the display, but I can't get the pivot point to be the center for calling camera.rotateZ (angle) by trying to use methods in a 3D android sample, but so far they seem to work for the X / Y axis, it does not seem to affect Z axis

Any help would be appreciated; the document is not exactly detailed.

+6
source share
4 answers

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

Drag the canvas first to center the large canvas on the display

Then apply camera rotation

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

The missing bits should have done the canvas transfer first, and I also did not use the large canvas size to calculate the offsets for the pre and post translate methods.

Here is a modified code if it helps someone else.

 // 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 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 someone has a better way or sees a problem, leave a comment.

+8
source

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); } 
+3
source

I like to do something in a difficult way and "collapse my own." Moreover, if you are doing an animation, cumulative errors can creep into the matrix concatenation.

 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. 
+1
source

Use this as a transform 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
source

Source: https://habr.com/ru/post/892187/


All Articles