Как повернуть холст в определенной точке, используя android.graphics.Camera.rotateX (angle) - PullRequest
6 голосов
/ 07 июля 2011

Я пытаюсь использовать камеру (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

OR

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

Оба корректно центрируют холст на дисплее, но я не могу получить точку поворота в качестве центра для вызова camera.rotateZ (угол), попытался использовать методы в примере 3D-андроида, но пока они кажутся работать для оси X / Y они, кажется, не влияют на ось Z

Буду признателен за любую помощь, документы не совсем многословны.

Ответы [ 4 ]

8 голосов
/ 07 июля 2011

Решил это, не уверен, что это лучший способ, но он работает. Решение было

Сначала переведите холст, чтобы центрировать больший холст на дисплее

Затем примените поворот камеры

Затем, чтобы использовать методы 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);

Если у кого-то есть способ лучше или он видит проблему, пожалуйста, оставьте комментарий.

3 голосов
/ 03 июля 2012

Это сработало для меня:

@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);
}
1 голос
/ 20 апреля 2012

Мне нравится делать вещи трудным путем и "кататься самостоятельно". Более того, если вы делаете анимацию, кумулятивные ошибки могут заползти в конкатенацию Матрицы.

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 голосов
/ 17 февраля 2012

Используйте это как преобразование в вашем классе анимации

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

}
...