变换矩阵乘法的意义
glemon (2010-05-28 17:14:58)
一个问题纠緾了我足足一个星期,为了不忘记,特意写下这篇东西,希望对大家都有用。先说明一下,我用的是pv3d,总觉得pv3d的变换矩阵用得很郁闷,用起来相当麻烦,资料也少,想找E文资料,又大多被墙了,唯有自己多作尝试。
问题是这样的:我要做一个立方体,用2d的上,下,左,右四个方向控制旋转,当然,旋转过程要有动画。看似简单的问题,做起来却不简单,对于立方体的旋转,不能简单地设置rotationX,rotationY,rotationZ,因为当立方体经过旋转后,它自身的旋转轴方向也会随之变化,那该怎么办呢?
首先,我想到一种土方法,建立一个空物体(我命名为rotXDP3d),把立方体放进去,作向水平方向的旋转,再建立一个空物体(我命名为rotYDP3d),把rotDP3d放进去,作垂直方向的旋转,这下问题解决了。但是这样一来,我要多建两个空物体,到底有没有更简便的方法呢?于是我想到了利用变换矩阵作运算。
正如我之前所说,关于变换矩阵的资料凤毛麟角,我查看过仅有的国内外资料,只了解到叠加变换用矩阵乘法。于是我开始尝试:
var box:Cube = scene.getChildByName("box") as Cube;
var mat:Matrix3D = Matrix3D.clone(box.transform);
var rotMat = Matrix3D.rotationX(Math.PI / 2);
mat.calculateMultiply(mat, rotMat);
box.transform = mat;
这个第一次执行,结果正确,可是当我执行第二次时,就出现问题,经过研究,发现这种变换跟直接设置rotationX的效果是一样的。
于是我找各方面的原因,也看了一些资料,也试了多种方法,还是达不到我的目的。后来我终于想到,这种变换其实想当于对立方体的全局矩阵进行变换,于是我马上查看DisplayObject3d类里关于全局矩阵的变换,最终发现了以下代码:
this.world.calculateMultiply( parent.world, this.transform );
正是这行代码,解决了我足足纠緾了一个星期的问题。首先要知道,矩阵乘法是不满足交换律的,也就是说,A矩阵乘B矩阵的结果不等于B矩阵乘A矩阵的结果。于是我作以下尝试:
var box:Cube = scene.getChildByName("box") as Cube;
var mat:Matrix3D = Matrix3D.clone(box.transform);
var rotMat = Matrix3D.rotationX(Math.PI / 2);
rotMat.calculateMultiply(rotMat, mat);
box.transform = rotMat;
经过测试,运作良好。
通过这个事例,我发现了变换矩阵乘法的意义:用实例的矩阵去乘另一矩阵时,相当于实例自身作变换;相反,用一个矩阵去乘实例的矩阵,则相当于实例作全局变换。
值得注意的是,对实例的变换矩阵作旋转变换,会改变rotationX,rotationY,rotationZ的值,但是这个改变不会马上显示出来,要马上查看它们值,可以使用yaw(0);让其执行一次updateRotation()(一个私有方法)。同样,用非矩阵的方式改为实例的属性,要马上获取正确的矩阵,要先执行一次updateTransform()(一个公共方法)。