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

发布于 2024-11-19 05:08:15 字数 757 浏览 3 评论 0原文

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

在dispatchDraw(Canvas 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

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

两者都正确地将画布在显示中居中,但我可以似乎没有让旋转点成为camera.rotateZ(angle)调用的中心,尝试使用3D android示例中的方法,但虽然它们似乎适用于X / Y轴,但它们似乎不会影响Z 轴

任何帮助将不胜感激,文档并不十分详细。

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.

In dispatchDraw(Canvas canvas) -- for brevity I am leaving out all the non important 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 hand corner.

NOTE: Because the canvas has been constructed to be larger than the display area I also need to translate the final result so that it is centered in the display, I can do this with either

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

OR

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

Both correctly center the canvas in the display but I can't seem to get the rotation point to be the center for the camera.rotateZ(angle) call, tried using the methods in the 3D android sample but while they seem to work for the X / Y axis them don't seem to affect the Z axis

Any help would be appreciated, the doc's are not exactly verbose.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

柠檬色的秋千 2024-11-26 05:08:15

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

首先平移画布,使较大的画布在显示屏中居中

,然后应用相机旋转

,然后使用矩阵上的预平移和后平移方法来更改旋转点,类似于 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);

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

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.

泪意 2024-11-26 05:08:15

这对我有用:

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

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);
}
子栖 2024-11-26 05:08:15

使用它作为动画类中的转换

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

}

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

}
︶ ̄淡然 2024-11-26 05:08:15

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

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.

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文