想要深入学习Papervision3D,就要对DisplayObject3D(简称do3d)类非常熟悉。这个类是所有3D显示对象的基类,是Papervision3D系统的核心部分。本文分享一些do3d在变换操作方面的知识。

首先要了解一点:3D系统通常都用一个矩阵来表示自身的变换属性。对比Maya系统来看。一个几何体具有对应的变换节点和形状节点。do3d.transform属性就是pv3d中表现变换的节点。这是一个4X4的矩阵,要想了解矩阵是如何作用于物体的变换,可以看看pv3d.org给出的Matrix3D演示

矩阵用于内部计算非常方便,但是对一般用户而言非常不直观。所以一般3D系统还要提供x,y,z,rotationX,scaleZ等等我们所熟知的变换属性。这些变换属性仅仅是提供了直观的属性接口,但是它们不参与内部计算,在系统内部的机制实现都是直接计算矩阵的。

(一)如果我们改变了某个变换属性,那么系统就需要更新矩阵。出于算法的优化考虑,这种更新不是马上就计算的。而是用do3d._transformDirty属性做一个标记,到需要的时候才进行计算。

那么什么时候才进行真正的计算呢?最通常的情况是在一个渲染流程开始的时候,场景中所有do3d的变换矩阵都会被更新(参看project()函数)。另外还有一些方法会触发矩阵的更新,如:translate(),copyTransform()等,请参看下面的图。

papervision

如果需要在一个渲染流程开始以前更新矩阵,可以调用do3d的公开方法updateTransform()。

(二)相反的,如果我们改动了矩阵,那么就需要保证变换值被更新。do3d类提供了一些很实用的方法如yaw(),pitch(),lookAt()等。它们的共性就是直接操作矩阵。执行过这些方法后,do3d._rotationDirty就被设置了标记,表示着旋转值和缩放值需要更新。

与上一情况不同的是,除非我们直接访问这些属性,否则这些更新都不会被计算。而且更新这些变换值的操作:updateRotation()是一个私有方法,不允许我们直接调用。这里就必须特别注意,如果我们使用Matrix3D或Quaternion之类的方法直接更改矩阵,是无法让变换值得到更新的。不正确的rotation值在渲染流程中不会引起问题,但是必须小心,不要让别的程序访问这些错误的值。对此,我想过一个解决办法:就是在矩阵操作以后,调用一次yaw(0)产生一次空旋转。这样就可以触发do3d._rotationDirty的更改,从而可以计算正确的变换值。但这仅是一种变通的办法,最佳的做法应该是避免程序同时依赖于矩阵和变换属性。

最后还要注意一点。updateRotation()方法执行了一个变换矩阵转欧拉角的算法。这种操作在数学中是建议尽量避免的。原因是会产生万向节死锁的问题,计算出的一个轴的旋转角不是我们所希望的0~360连续范围。所以如果调用过上图中标识为“直接改矩阵”的方法后,再使用do3d的旋转值的时候,要特别的注意。

« »