如何使用android.graphics.Camera.rotateX(角度)在特定点旋转画布
我正在尝试使用相机(android.graphics.Camera而不是硬件相机)围绕特定点旋转视图画布,在本例中是画布的中间 在dispatchDraw(Canvas Canvas)——为简洁起见,我省略了所有不重要的部分如何使用android.graphics.Camera.rotateX(角度)在特定点旋转画布,android,canvas,3d,camera,rotation,Android,Canvas,3d,Camera,Rotation,我正在尝试使用相机(android.graphics.Camera而不是硬件相机)围绕特定点旋转视图画布,在本例中是画布的中间 在dispatchDraw(Canvas Canvas)——为简洁起见,我省略了所有不重要的部分 camera.save(); camera.rotateX(0); camera.rotateY(0); camera.rotateZ(angle); camera.getMatrix(cameraMatrix); camera.restore()
camera.save();
camera.rotateX(0);
camera.rotateY(0);
camera.rotateZ(angle);
camera.getMatrix(cameraMatrix);
camera.restore();
canvas.concat( cameraMatrix );
画布旋转,但始终从左上角开始
注意:因为画布已经被构造成比显示区域大,所以我还需要转换最终结果,使其在显示中居中,我可以使用任何一种方法来实现这一点
canvas.translate(xOffset,yOffset) PRIOR to calling the camera methods
或
两者都正确地将画布居中显示,但我似乎无法将旋转点作为相机的中心。rotateZ(angle)调用尝试使用3D android示例中的方法,但尽管它们似乎适用于X/Y轴,但它们似乎不会影响Z轴
如果您能提供任何帮助,我们将不胜感激,文档并不详尽。解决了这个问题,不确定这是否是最好的方法,但它确实有效。解决办法是 首先平移画布,使较大的画布在显示屏中居中 然后应用摄影机旋转 然后使用矩阵上的前后平移方法更改旋转点,类似于android示例所做的操作 缺少的部分是首先进行画布翻译,我也没有使用较大的画布大小来计算翻译前和翻译后方法的偏移量 这是修改后的代码,如果它能帮助其他人
// 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);
如果有人有更好的方法或看到问题,请留下评论。将此作为动画课程中的转换
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);
}
我喜欢用困难的方式做事,并且“自己动手”。 此外,如果您正在制作动画,累积误差可能会在concat'ing矩阵中爬行
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.
这对我很有用:
@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);
}
我已经使用公认的解决方案(稍微修改)一段时间了,没有任何问题。您好,谢谢您的这篇文章,但我无法理解translateX、translateY和centerScaled变量的值是多少。你能解释一下吗?@Dhaval请检查一下,这似乎是正确的解决方案。由于
Camera#applyToCanvas()
可能不适用于某些ICS设备
@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);
}