OpenSceneGraph 中的 osg::Transform详解
osg::Transform
是 OpenSceneGraph 中用于实现空间变换的基类,它提供了一种在场景图中应用各种变换(平移、旋转、缩放等)的机制。
一、Transform 基本概念
1. 核心特性
-
继承关系:继承自
osg::Group
-
主要功能:对子节点应用空间变换
-
两种模式:
-
相对变换 (RELATIVE_RF):相对于父节点的变换(默认)
-
绝对变换 (ABSOLUTE_RF):忽略父节点变换,直接使用世界坐标系
-
2. 派生类
-
osg::MatrixTransform
- 使用矩阵进行变换 -
osg::PositionAttitudeTransform
- 使用位置/姿态进行变换 -
osg::AutoTransform
- 自动面向相机的变换
二、MatrixTransform 详解
1. 基本用法
// 创建MatrixTransform节点
osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
// 设置变换矩阵
mt->setMatrix(osg::Matrix::translate(10.0f, 0.0f, 0.0f)); // 平移
// 添加子节点
mt->addChild(childNode);
2. 组合变换
osg::Matrix m;
m.makeIdentity();
m *= osg::Matrix::translate(5.0f, 0.0f, 0.0f); // 平移
m *= osg::Matrix::rotate(osg::PI_2, osg::Z_AXIS); // 旋转90度
m *= osg::Matrix::scale(2.0f, 1.0f, 1.0f); // 非均匀缩放
mt->setMatrix(m);
3. 获取逆矩阵
osg::Matrix inverse = mt->getInverseMatrix();
三、PositionAttitudeTransform 详解
1. 基本用法
osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
// 设置位置
pat->setPosition(osg::Vec3(5.0f, 3.0f, 0.0f));
// 设置姿态(四元数旋转)
pat->setAttitude(osg::Quat(osg::PI_4, osg::Z_AXIS)); // 绕Z轴旋转45度
// 设置缩放
pat->setScale(osg::Vec3(1.5f, 1.5f, 1.5f)); // 均匀缩放1.5倍
// 设置中心点(缩放/旋转的参考点)
pat->setPivotPoint(osg::Vec3(0.0f, 0.0f, 1.0f));
pat->addChild(childNode);
2. 与MatrixTransform对比
特性 | MatrixTransform | PositionAttitudeTransform |
---|---|---|
易用性 | 需要矩阵运算 | 更直观的参数设置 |
性能 | 稍高 | 稍低(内部转换为矩阵) |
适用场景 | 复杂变换组合 | 简单的位置/旋转/缩放 |
四、Transform 高级应用
1. 变换回调(动画)
class RotationCallback : public osg::NodeCallback {
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);
if (mt) {
static double angle = 0.0;
angle += 0.01;
mt->setMatrix(osg::Matrix::rotate(angle, osg::Z_AXIS));
}
traverse(node, nv);
}
};
// 应用回调
mt->setUpdateCallback(new RotationCallback);
2. 绝对变换示例
// 创建一个不受父节点变换影响的节点
osg::ref_ptr<osg::MatrixTransform> absoluteTransform = new osg::MatrixTransform;
absoluteTransform->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
absoluteTransform->setMatrix(osg::Matrix::translate(0.0f, 0.0f, 10.0f));
3. 层级变换
// 创建变换层级
osg::ref_ptr<osg::MatrixTransform> parentTransform = new osg::MatrixTransform;
parentTransform->setMatrix(osg::Matrix::translate(10.0f, 0.0f, 0.0f));
osg::ref_ptr<osg::MatrixTransform> childTransform = new osg::MatrixTransform;
childTransform->setMatrix(osg::Matrix::rotate(osg::PI_2, osg::Z_AXIS));
parentTransform->addChild(childTransform);
childTransform->addChild(geometryNode); // 实际几何体
五、性能优化技巧
-
静态变换优化:
mt->setDataVariance(osg::Object::STATIC); // 声明为静态不变化
-
合并静态变换:
osgUtil::Optimizer optimizer; optimizer.optimize(rootNode, osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS);
-
避免频繁矩阵计算:
// 预计算复杂矩阵 osg::Matrix complexMatrix = computeComplexMatrix(); mt->setMatrix(complexMatrix);
六、实际应用案例
1. 太阳系模型
// 太阳(中心)
osg::ref_ptr<osg::MatrixTransform> sun = new osg::MatrixTransform;
sun->addChild(createSphere(5.0f));
// 地球绕太阳旋转
osg::ref_ptr<osg::MatrixTransform> earthOrbit = new osg::MatrixTransform;
earthOrbit->setUpdateCallback(new OrbitCallback(10.0f, 2.0)); // 半径10m,周期2秒
osg::ref_ptr<osg::MatrixTransform> earth = new osg::MatrixTransform;
earth->addChild(createSphere(1.0f));
earth->setMatrix(osg::Matrix::translate(10.0f, 0.0f, 0.0f));
earthOrbit->addChild(earth);
sun->addChild(earthOrbit);
// 月球绕地球旋转
osg::ref_ptr<osg::MatrixTransform> moonOrbit = new osg::MatrixTransform;
moonOrbit->setUpdateCallback(new OrbitCallback(3.0f, 0.5)); // 半径3m,周期0.5秒
osg::ref_ptr<osg::MatrixTransform> moon = new osg::MatrixTransform;
moon->addChild(createSphere(0.3f));
moon->setMatrix(osg::Matrix::translate(3.0f, 0.0f, 0.0f));
moonOrbit->addChild(moon);
earth->addChild(moonOrbit);
2. 第一人称相机控制
class CameraUpdateCallback : public osg::NodeCallback {
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);
if (mt) {
osg::Matrix mat;
mat.makeTranslate(_position);
mat.preMultRotate(_orientation);
mt->setMatrix(mat);
}
traverse(node, nv);
}
void moveForward(float distance) {
_position += _orientation * osg::Vec3(0.0f, distance, 0.0f);
}
void rotate(float angleX, float angleY) {
_orientation *= osg::Quat(angleX, osg::X_AXIS);
_orientation *= osg::Quat(angleY, osg::Z_AXIS);
}
private:
osg::Vec3 _position;
osg::Quat _orientation;
};
// 使用
osg::ref_ptr<osg::MatrixTransform> cameraTransform = new osg::MatrixTransform;
cameraTransform->setUpdateCallback(new CameraUpdateCallback);
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
七、常见问题与调试
1. 变换顺序问题
-
问题:矩阵乘法顺序错误导致意外结果
-
解决:记住OSG使用前乘(preMult)顺序
2. 调试变换矩阵
// 打印当前变换矩阵
osg::Matrix mat = mt->getMatrix();
std::cout << "Transform Matrix: " << mat << std::endl;
// 可视化变换轴
osg::ref_ptr<osg::Geode> axis = createAxesGeode(2.0f);
mt->addChild(axis);
3. 性能分析
osgviewer your_scene.osgb --stats
# 查看 "Transform" 相关的统计信息
osg::Transform
及其派生类是OSG场景图的核心组件,合理使用可以实现复杂的场景层次和动画效果,同时保持高效的渲染性能。