如何使用android.graphics.Camera.rotateX(角度)在特定点旋转画布

时间:2011-07-07 00:16:28

标签: android canvas 3d camera rotation

我正在尝试使用Camera(android.graphics.Camera而不是硬件相机)围绕特定点旋转视图画布,在这个实例中是画布的中间。

在dispatchDraw(Canvas画布)中 - 为简洁起见,我将所有非重要部分都遗漏掉。

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

OR

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

两者都正确地将画布置于显示中心,但我似乎无法将旋转点作为camera.rotateZ(角度)调用的中心,尝试使用3D android示例中的方法但是它们似乎为X / Y轴工作它们似乎不影响Z轴

任何帮助都会受到赞赏,文档并不完全详细。

4 个答案:

答案 0 :(得分:8)

解决了这个问题,不确定它是否是最好的方式,但它有效。解决方案是

首先翻译画布,使较大的画布居中显示

然后应用相机旋转

然后在矩阵上使用pre和post translate方法来改变旋转点,类似于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);

如果有人有更好的方法或发现问题,请发表评论。

答案 1 :(得分:3)

这对我有用:

@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);
}

答案 2 :(得分:1)

我喜欢以困难的方式做事并“自己动手”。 此外,如果你正在制作动画,累积的错误可能会在连续的矩阵中蔓延。

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.

答案 3 :(得分:0)

将此作为动画类中的变换

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);

}