OSG中测试旋转与平移

其实,无需关心osg矩阵是如何实现的.但是要记住的是osg中采用的左乘操作,我们平时里讨论的操作如旋转平移等。

      OpenGL的:    newpos = R* T * oldpos    //先执行平移 后执行 旋转 (全局坐标系)

      osg当中:  newpos  =oldpos * T *R    //先执行平移 后执行旋转    (全局坐标系)

因为在osg当中矩阵执行的操作则是行矩阵操作.因此为了跟OpenGL的列矩阵做同步 而不在定义的时候就相当于做了一个转置操作.即

 OSG中测试旋转与平移 - 蝴蝶小兵 - 蝴蝶小兵的博客

 

你只需牢记 在OSG当中变换的步骤则是左乘操作(全局坐标系)..即左边的是先执行变换的.

谈完如上的那些之后.我们现在来看MatrixTransform 和PositionAttitudeTransform.

参考坐标系有三种
            RELATIVE_RF,    //全局 相对 ()
            ABSOLUTE_RF,  //局部  绝对 ()
            ABSOLUTE_RF_INHERIT_VIEWPOINT   //基于视点一个局部坐标系.很少用到.

MatrixTransform 故名 矩阵变换节点.在位于它的节点之下的节点都将按照这它的矩阵变换来进行模型变换操作.因此 MatrixTransform的主要功能之一就是提供模型变换操作..你只要根据你所需要的设置其模型矩阵就行.
即执行 setMatrix() 因此.查看计算当前World矩阵的方法就可以很清晰的明白其最后结果就是:

如果是相对的.那么 先执行自身的变换,在执行父节点的变换操作.这类似OpenGL中后写的变换是先执行的一样(全局坐标系考虑)
否则是绝对的,那么当前矩阵就是自身矩阵

#include <osg/NodeCallback>
#include <osg/PositionAttitudeTransform>
#include <osgViewer/Viewer>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>

//旋转控制
/*
int main()
{
 //创建XYZ坐标节点
 osg::Node* axesNode = NULL;
 //根节点
    osg::Group* root = new osg::Group();
    osgViewer::Viewer viewer;
 //读入axes.osg
    axesNode = osgDB::readNodeFile("axes.osg");
    //旋转度到弧度
    float iRadians = osg::DegreesToRadians(-45.0);
    //旋转弧度到度
    float iDegress = osg::RadiansToDegrees(1.2);
    //创建一个四元数来控制旋转弧度
    osg::Quat quat(iRadians, osg::Vec3(1,0,0));
    //创建位置变换节点
    osg::MatrixTransform* axesXform;  
    axesXform = new osg::MatrixTransform();
    //创建变换实例
    osg::Matrixd mat;
    //旋转45度
    mat.makeRotate(quat);
    axesXform->setMatrix(mat);
    axesXform->addChild(axesNode);
    root->addChild(axesXform);  
    viewer.setSceneData(root);
    viewer.realize();
    return viewer.run();
}
*/


osg::Group* createTrans()
{
  
    osg::Group* root = new osg::Group;
    //创建姿态节点
    osg::PositionAttitudeTransform* posCow = new osg::PositionAttitudeTransform;
    root->addChild(posCow);
    //创建变换节点
    osg::MatrixTransform* matrixCow  = new osg::MatrixTransform;
    root->addChild(matrixCow);
    //牛
    osg::Node* cow = osgDB::readNodeFile("cow.osg");
    posCow->addChild(cow);
    osg::Quat quat;
 //旋转
 quat.makeRotate(osg::PI_2,osg::Vec3(0.0,0.0,1.0));
    posCow->setAttitude(quat);
 //设置位置
    posCow->setPosition(osg::Vec3(-10,0.0,0.0));
   
    matrixCow->addChild(cow);
    //旋转
 quat.makeRotate(osg::DegreesToRadians(60.0),osg::Vec3(0.0,0.0,1.0));
    //设置位置
 matrixCow->setMatrix(osg::Matrixd::translate(osg::Vec3(10.0,0.0,0.0))*osg::Matrixd::rotate(quat));
    return root;
}

int main()
{
 //根节点
    osg::Group* root = new osg::Group();
 root = createTrans();
    osgViewer::Viewer viewer;
    //创建节点到场景中
    viewer.setSceneData(root);
    viewer.realize();
    return viewer.run();
}

在 OpenSceneGraph (OSG) ,您可以使用 `NodeVisitor` 类来遍历场景图的节点,并对每个子节点进行旋转平移操作。下面是一个示例代码片段,展示了如何使用 `NodeVisitor` 来对子节点进行旋转平移: ```cpp #include <osg/NodeVisitor> #include <osg/MatrixTransform> #include <osg/Geode> #include <osgDB/ReadFile> // 自定义的 NodeVisitor 子类 class MyVisitor : public osg::NodeVisitor { public: MyVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} // 重写 apply 方法,在遍历每个节点时执行操作 virtual void apply(osg::Node& node) { // 在这里添加旋转平移的代码 osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(&node); if (transform) { // 旋转节点 osg::Matrix rotationMatrix; rotationMatrix.makeRotate(osg::Quat(osg::PI / 4, osg::Vec3(0, 0, 1))); // 绕 Z 轴旋转 45 度 transform->setMatrix(transform->getMatrix() * rotationMatrix); // 平移节点 osg::Matrix translationMatrix; translationMatrix.makeTranslate(osg::Vec3(1, 0, 0)); // 沿 X 轴平移 1 单位 transform->setMatrix(transform->getMatrix() * translationMatrix); } // 继续遍历子节点 traverse(node); } }; int main() { // 加载场景文件 osg::ref_ptr<osg::Node> scene = osgDB::readNodeFile("path/to/your/scene.osg"); // 创建 MyVisitor 对象并应用于场景节点 MyVisitor visitor; scene->accept(visitor); // 运行场景图的渲染循环... return 0; } ``` 在上面的示例,我们首先定义了一个名为 `MyVisitor` 的自定义 `NodeVisitor` 子类。在 `apply` 方法,我们使用 `dynamic_cast` 操作将节点转换为 `osg::MatrixTransform` 类型,然后对其进行旋转平移操作。然后,我们调用 `traverse` 方法继续遍历子节点。 在 `main` 函数,我们加载场景文件并创建了 `MyVisitor` 对象,并将其应用于场景节点。然后,您可以根据需要执行场景图的渲染循环。 请注意,上述示例旋转平移操作仅作为演示。您可以根据实际需求修改旋转平移的参数。同时,您可能需要添加其他条件来筛选出特定的节点进行操作。 希望对您有所帮助!如果您有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值