2011-07-07 46 views
6

我想使用相機(android.graphics.Camera不是硬件相機)來旋轉視圖畫布周圍的特定點,在這個例子中,畫布的中間。如何在特定點使用android.graphics.Camera.rotateX(角度)旋轉畫布

在dispatchDraw(畫布畫布) - 爲了簡便起見,我忽略了所有非重要的部分。

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軸

任何幫助將不勝感激,文檔的不完全冗長。

回答

8

解決了這個問題,不知道它是否是最好的方法,但它的工作原理。解決的辦法是

第一翻譯畫布居中更大的畫布中顯示

然後應用照相機旋轉

然後使用前置和後置翻譯方法在基質上以改變旋轉點類似於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); 

如果有人有更好的方法或發現問題,請發表評論。

+2

感謝你好這個職位,但我無法理解的會是怎樣平移X,平移Y的值和centerScaled變量。你能解釋我嗎? – Dhaval

+0

@Dhaval請檢查http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html – Ankit

+0

其實,這似乎是正確的解決方案。由於'Camera#applyToCanvas()'可能不適用於某些ICS設備 –

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

} 
+0

我一直在使用已接受的解決方案(稍作修改)並且一直沒有問題。 – Idistic

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

這爲我工作:

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