*********************************************************前言
我们要说点什么:1.matrix
2.canvas的matrix
3.三类影响bitmap绘制的方式
4.使用camera来完成三维旋转
*********************************************************正文
matrix
一般的坐标变换transform,包含了:平移translate,缩放scale,旋转rotate等坐标变换改变的是什么:坐标系
坐标系影响了什么:点的坐标值是不会改变的(除非你主动去改变它),但是点是在坐标系上进行绘制的。坐标系的改变,将使得点的绘制发生改变
在Android中,由Matrix这个类来表示坐标变换矩阵,matrix并不是android的概念,他是3d中的概念
且,标准的4*4矩阵,变成了3*3矩阵
Matrix中的post...和pre...有什么样的区别呢?
设Matrix本身的坐标变换为TR1,post...中的东东的坐标变换为TR2,则新的坐标变换TR3=TR2*TR1,它对坐标系的影响是:先执行TR2变换,再执行TR1变换
设Matrix本身的坐标变换为TR1,pre...中的东东的坐标变换为TR2,则新的坐标变换TR3=TR1*TR2,它对坐标系的影响是:先执行TR1变换,再执行TR2变换
即是:
TR1 post TR2:TR1在TR2的后面,在坐标系变换的执行过程中,先执行TR2,再执行TR1
TR1 pre TR2:TR1在TR2的前面,在坐标系变换的执行过程中,先执行TR1,再执行TR2
此外,学生时代,设E是单位矩阵,M*E=E*M=M,还记得吧
进一步的参考:http://blog.csdn.net/kuku20092009/article/details/6740865
canvas的matrix
Canvas.getmatrix返回了一个canvas的matrix的一个拷贝注意:该matrix并不是一个E矩阵:
view经过measure,确定了mwidth和mheight后,经由父亲group,被layout到某个区域
该区域左上角的坐标,便是canvas的坐标系的原点
则,canvas的matrix是一个translate,相对于屏幕的(0,0)
matrix是如何影响view的绘制的:
view是在canvas中绘制的,一旦改变canvas的坐标系,那么绘制便有所不同
再次强调:
坐标变换,改变的是坐标系,而不是点的坐标
你要绘制的东东都是具有坐标的,无论是点,线,bitmap还是其他,
这些东东的绘制:会参照(0,0)原点,并在x/y轴上进行延伸
当坐标轴经过坐标变换后,变的奇形怪状,那么你的图形才因此变得奇形怪状。或者,你的图形本来就是奇形怪状的,而坐标系是很正统的那种
三类影响bitmap绘制的方式
1.使用matrix,构建一个新的bitmap,在绘制时,使用e矩阵
使用
bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
,来创建一个奇形怪状的bitmap
2.在绘制时,使用一个新的matrix,来绘制原始的bitmap
使用
方式2和方式3,可以达到相同的效果:
设方式2的matrix为m2,方式3中canvas的最终的matrix为m3
则 m3 = m_canvas_original * m2
当做了一个实验,你发现结果是:绕z轴旋转
实际上,绕某个轴某个角度进行旋转的矩阵,都是有固定的格式
我的意思是:比如绕y轴旋转,你会看到一个参数矩阵,这个矩阵有0/1,也有sinx/cosx/..等,你确定sin/cos的值,这个matrix就确定了
但是,查阅matrix这个类,你发现,没有一个构造方法/方法提供了:根据一个float[]来构建一个matrix对象,所以,上述的思路在这里行不通
-----
另外一种方式:有没有现成的矩阵来让我使用
有,使用graphics.camera(而不是hardware.camera)
在这个类中,你将发现,它提供了rotatex/y/z方法
你可以通过camera.getmatrix来获得你想要的旋转矩阵
注意:如果你要想获得绕K轴旋转a角度的矩阵,那么请使用camera.rotateK(-a),注意到a和-a了吗,别奇怪
在android中,xyz轴的正方向是什么:x向右,y向下,z向外(拿着手机,屏幕对着你,它拿了z的正方向指向了你)
canvas.drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
,来将该bitmap绘制的奇形怪状(canvas的坐标系并没有改变)
3.改变canvas的坐标系,来绘制原始的bitmap
canvas.setmatrix(...)
canvas.drawbitmap(...)
方式2 vs 方式3
方式2和方式3,可以达到相同的效果:
设方式2的matrix为m2,方式3中canvas的最终的matrix为m3
则 m3 = m_canvas_original * m2
使用camera来完成三维旋转
matrix中有旋转方法,但是,你会发现,你除了指定旋转角度(或者,旋转点)以外,你并没有指定绕哪个轴旋转当做了一个实验,你发现结果是:绕z轴旋转
如何才能绕z轴之外的其他轴旋转,你需要构造一个matrix(绕某个轴旋转某个角度):
实际上,绕某个轴某个角度进行旋转的矩阵,都是有固定的格式
我的意思是:比如绕y轴旋转,你会看到一个参数矩阵,这个矩阵有0/1,也有sinx/cosx/..等,你确定sin/cos的值,这个matrix就确定了
但是,查阅matrix这个类,你发现,没有一个构造方法/方法提供了:根据一个float[]来构建一个matrix对象,所以,上述的思路在这里行不通
-----
另外一种方式:有没有现成的矩阵来让我使用
有,使用graphics.camera(而不是hardware.camera)
在这个类中,你将发现,它提供了rotatex/y/z方法
你可以通过camera.getmatrix来获得你想要的旋转矩阵
注意:如果你要想获得绕K轴旋转a角度的矩阵,那么请使用camera.rotateK(-a),注意到a和-a了吗,别奇怪
上述只是拿了旋转来当例子,你可以动手试试translate,scale等
在android中,xyz轴的正方向是什么:x向右,y向下,z向外(拿着手机,屏幕对着你,它拿了z的正方向指向了你)
之下展示了获取 一个以某点为原点,绕k轴旋转的 旋转矩阵 的方法:
/**
* 将原点平移到指定点后,绕axis旋转
*
* @param angle
* 绕axis轴旋转的角度
* @param whichAxis
* 哪一个轴
* @param centerX
* 原点坐标x
* @param centerY
* 原点坐标y
* @param cm
* canvas的原始matrix
* @return
*/
private Matrix getRotateMatrix(float angle, String whichAxis,
float centerX, float centerY, Matrix cm) {
Matrix matrix = null;
Camera c = new Camera();
// 保存当前的camera的状态,如:坐标系等
// 注意:与restore的对应
c.save();
if (whichAxis.toLowerCase().equals("x")) {
c.rotateX(-angle);
} else if (whichAxis.toLowerCase().equals("y")) {
c.rotateY(-angle);
} else if (whichAxis.toLowerCase().equals("z")) {
c.rotateZ(-angle);
}
matrix = new Matrix();
// R
c.getMatrix(matrix);
// 恢复camera到“其在save时刻的状态”
c.restore();
// T1
matrix.preTranslate(-centerX, -centerY);
// T2
matrix.postTranslate(centerX, centerY);
if (whichAxis.toLowerCase().equals("x")) {
// 最后的执行的变换操作是: CTR, T2, R, T1
matrix.postConcat(cm);
} else if (whichAxis.toLowerCase().equals("y")) {
// 最后的执行的变换操作是: T2, R, T1, CTR
matrix.preConcat(cm);
}
return matrix;
}