来看看Transform类。
AutoTransform、MatrixTransform、PositionAttitudeTransform、DOFTransform、Camera
等都是
Transform的子类,用于进行变换操作。
Transform继承自Group,所有子节点可以通过一个矩阵变换,产生操作器和动画等效果。特别强调了如
果进行缩放,应该重新计算法向量,
stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
在OpenGL中有两个计算法向量的模式:GL_NORMALIZE and GL_RESCALE_NORMAL,GL_RESCALE_NORMAL是
xyz都乘同一个因子,GL_NORMALIZE各个方向乘不同的因子,因此效果好,但计算量大。
Transform中RELATIVE_RF,ABSOLUTE_RF很重要,RELATIVE_RF是参考父节点的相对矩阵,ABSOLUTE_RF是
相对于绝对坐标的。因此,在调用
computeLocalToWorldMatrix
和
computeWorldToLocalMatrix
时候会根
据ReferenceFrame的值是否乘上父节点的矩阵。
Transform中只提供了一个接口,真正的实现都在其子类,我们看一下MatrixTransform,MatrixTransform中保存了一个节点的变换矩阵_matrix,
看这两个函数:
bool MatrixTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
if
(_referenceFrame==RELATIVE_RF)
{
matrix.preMult(_matrix);
}
else //
absolute
{
matrix = _matrix;
}
return true;
}
bool
MatrixTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const
{
const
Matrix& inverse = getInverseMatrix();
if (_referenceFrame==RELATIVE_RF)
{
matrix.postMult(inverse);
}
else // absolute
{
matrix = inverse;
}
return true;
}
如果当前的模式是相对的,matrix就需要乘上_matrix,否则matrix就等于_matrix,这样能够保证变换
矩阵的层级的变换,把没一级别的Transform的变换累计,则就是最终的变换。
AutoTransform中的computeLocalToWorldMatrix和computeWorldToLocalMatrix和上面一样,可以累乘,
AutoTransform中几种模式:
enum AutoRotateMode
{
NO_ROTATION,
ROTATE_TO_SCREEN,
ROTATE_TO_CAMERA,
ROTATE_TO_AXIS
};
没有旋转、旋转到屏幕、旋转到相机、旋转到坐标轴。
回到例子中:
看看createLabel创建了一个文字叶节点,这里对于文字先不做研究,Text继承自TextBase,TextBase又
继承自Drawable,因此可以添加到Geode中,这样创建了一个文字节点。
在createAxis函数中,把上面的文字叶节点添加到AutoTransform中,并设置AutoTransform的不同模式
。这里文字叶节点只是作为一个演示,在Text中同样可以设置SCREEN_COORDS,
text->setAutoRotateToScreen(true);
实现文字一直向着屏幕的效果。
最后看看AutoTransform中的这两个属性:
double _minimumScale;
double _maximumScale;
最小范围和最大范围,_minimumScale默认是0,_maximumScale默认是DBL_MAX,即在0到DBL_MAX之间是
会进行自动节点的缩放的,相机距离AutoTransform的距离小于_minimumScale,Autotransform节点不会
再进行自动缩放,节点会“变大”。相机距离AutoTransform的距离大于_minimumScale,AutoTransform
节点会“变小”。
通过这个节点可以实现一些地名显示等效果。