2011-07-07 9 views
6

Estoy tratando de usar la cámara (android.graphics.Camera no la cámara de hardware) para rotar un lienzo de vistas alrededor de un punto específico , en este caso, el medio del lienzo.Cómo rotar un lienzo en un punto específico usando android.graphics.Camera.rotateX (ángulo)

En dispatchDraw (Canvas canvas) - por brevedad, omito todas las partes no importantes.

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

canvas.concat(cameraMatrix); 

El lienzo gira, pero siempre desde la esquina superior izquierda.

NOTA: Debido a que el lienzo se ha construido para ser más grande que el área de visualización También tengo que traducir el resultado final de manera que quede centrado en la pantalla, no puedo hacer esto con cualquiera

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

O

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

Tanto centrar correctamente la lona en la pantalla, pero me parece que no puede conseguir el punto de rotación para ser el centro de la llamada camera.rotateZ (ángulo), intentado usar los métodos de la muestra androide 3D, pero mientras parecen trabajar para el eje X/Y, no parecen afectar el eje Z

Cualquier ayuda sería apreciada, los documentos no son exactamente detallados.

Respuesta

8

Resuelto esto, no estoy seguro si es la mejor manera, pero funciona. La solución fue

Traducir el lienzo primero para centrar el lienzo más grande en la pantalla

A continuación, aplicar las rotaciones de la cámara

entonces para usar el pre y post traducir métodos en la matriz para cambiar el punto de rotación similar a lo que hizo la muestra de Android.

Los bits que faltaban eran primero la traducción del lienzo y tampoco usaba el tamaño de lienzo más grande para calcular los desplazamientos para los métodos de traducción previa y posterior.

Aquí está el código modificado si ayuda a alguien más.

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

Si alguien tiene una mejor manera o ve un problema, por favor deje un comentario.

+2

Hola gracias por este post, pero no soy capaz de entender el cuál va a ser el valor de translateX, translateY y centerScaled variables. ¿Puedes por favor explicarme? – Dhaval

+0

@Dhaval por favor revise http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html – Ankit

+0

En realidad, esta parece ser la solución correcta.Dado que 'Camera # applyToCanvas()' puede no funcionar para algunos dispositivos ICS –

0

utilizar esto como la transformación en su clase de animación

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

He estado utilizando la solución aceptada (ligeramente modificada) durante un tiempo y no he tenido problemas con ella. – Idistic

1

me gusta hacer las cosas de la manera difícil y "rodar mi propia". Además, si estás haciendo animaciones, los errores acumulativos pueden aparecer en la mezcla de Matrix.

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

Esto funcionó para mí:

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