模型简单控制
来源:互联网 发布:清华北大抢人 知乎 编辑:程序博客网 时间:2024/05/16 12:55
1.读取模型
1.1 基本操作
添加模型
在 OSG 当中模型是使用 osg::Group 和 osg::Node 来装载在一起的,比如同时需要加入两个模型,模型 A 和模型 B, AB 各自是一个 NODE, 那么可以使用以下语句来做到, 首先使用一个 Group,然后 Group ->addChild(A),同样,之后要 Group->addChild(B)。然后再把 Group 添加到 viewer 当中就可以了。如图 3.1 所示 AB 之间的关系。在这里要申明的是 NODE 是 Group 的父类,在类中都有相应的方法可以转到对方,故 Node 与 Group是通用的,Node 也可以被当作 Group 来用。
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;osg::ref_ptr<osg::Group> root = new osg::Group;root ->addChild(osgDB::readNodeFile("glider.osg")) ;root ->addChild(osgDB::readNodeFile("osgcool.osg")) ;viewer->setSceneData(root);viewer->realize();viewer->run();
如果想要添加别的模型,还可以 root ->addChild,但是,如果想在飞机上面添加一些什么,就需要把飞机当成组结点,然后再飞机结点上再添加一些东西。可以这样。
osg::Group* root = new osg::Group() ;osg::Node *glider = osgDB::ReadNodeFile(“glider.osg”) ;glider ->asGroup() ->addChild(osgDB::ReadNodeFile(“xxx.osg””)) ;root ->addChild(glider) ;root ->addChild(osgDB::readNodeFile(“osgcool.osg”)) ;
删除结点
如果我们不需要某个结点了,我们想把它从场景中删除掉。不知道出于某种目的,反正现在要删除掉,可能是开始想看见它现在不想看见它了。可以通过 removeChild 方法,删除多个孩子也可以通过 removeChildren 方法,里面的参数有些需要索引值,有些需要结点本身的指针,读者可以自己尝试。
这里要提醒大家的是,如果要删除一个结点,那么该结点下的所有结点都会被删除。如果一个结点被加入到一个组中两次,那么这两次是分别存在的,删除一次还有另一次。
隐藏模型
隐藏模型其实模型仍在渲染当中,因此损耗并未减少,node ->setNodeMask 可以设置隐藏与显示。osgcool ->setNodeMask(0x0) ;代表隐藏。 osgcool ->setNodeMask(1)代表显示。
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;osg::ref_ptr<osg::Group> root = new osg::Group;osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");root ->addChild(osgDB::readNodeFile("glider.osg")) ;root ->addChild(node) ;node->setNodeMask(0x0);viewer->setSceneData(root);viewer->realize();viewer->run();
结点开关
开关能够隐掉一个结点,它还在内存当中消失,而且想要的时候它才能出来。
在 OSG 当中,专门有一个类来负责打开与关闭结点,该类名为 osg::Switch,里面有相应的方法来控制它所管理的结点的打开与关闭。
#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Switch>void main(){ osgViewer::Viewer viewer; osg::Group * root = new osg::Group() ; osg::Switch *sw = new osg::Switch() ; osg::Node* cow = osgDB::readNodeFile("cow.osg") ; //往开关中添加 cow 但是关掉它,第二个参数为 false sw ->addChild(cow, false) ; sw ->addChild(osgDB::readNodeFile("glider.osg")) ; root ->addChild(sw) ; viewer.setSceneData(root); viewer.realize(); viewer.run();}
将父节点下的子节点替换
group->replaceChild(oldChild, newChild);
1.2 超级指针
超级指针,其实就是引用一个计数器,这个计数器会计算这个箱子被引用的次数,被
别人引用一次这个计数器增加一,别人不用一次,即:释放一次,则计数器减一。当减至 0 时,内存放掉不用。
使用一个 Node 的三种方法,对比一下:
方法一,最好的方法,十分安全,也是OSG中最常用的方法,多少版本它都没变
osg::ref_ptr aNode (new osg::Node());
group->addChild (aNode.get());
方法一:在 new::Node()时申请了一个 Node 的资源,这时在堆内引用该 Node 的计算器会被置 1。在 group->addChild(aNode.get())时又引用了一次,会再加 1。在这两次引用都结束时,Node 的资源就会被释放。
方法二,也是非常好的方法,有时候不适用,但也十分安全
group->addChild (new osg:: Node ());
方法二:这个方法也是很实用的,但是无法引出 Node 的指针,也许在别处可以用到,事实上会经常用到。如果已经这样做了,得到 Node 指针也不是不可以的,可以使用 NodeVisitor 来得到 Node 的指针,也可以使用 findChild 方法来做这件事。
方法三,非常危险,但是令许多人无故铤而走险的方法
osg:: Node* anotherNode = new osg:: Node ();
group->addChild (anotherNode);
方法三:这个应该是最常用,但是最烂的方法了,原因在于如果在 osg::Node*antherode = new osg::Node()之后发生了错误,抛出了异常,谁来释放 Node 所占用的资源呢。而这个异常在后面被捕获,程序正常的走下去,而内存却没有被正常的放掉。
2. 移动/旋转/缩放模型
移动/旋转/缩放其实都是对矩阵进行操作,在 OSG 当中,矩阵可以当作一个特殊的结点加入到 root 当中,而矩阵下也可以另入结点,而加入的结点就会被这个矩阵处理过,比如移动过/旋转过/缩放过。在 OSG 中控制矩阵的类可以为 osg::MatrixTransform。
2.1 直接使用osg::MatrixTransform
功能:移动/旋转/缩放模型,这里加入了四个 glider,一个是默认加入在最中间,一个向上移 2 单位,一个是向下移 2 单位且缩放 0.5 倍,另一个是向右 4 单位,缩放 0.5 且平躺 45 度。
#ifdef _DEBUG#pragma comment(lib,"osgd.lib")#pragma comment(lib,"osgDBd.lib")#pragma comment(lib,"osgViewerd.lib")#pragma comment(lib,"OpenThreadsd.lib")#pragma comment(lib,"osgGAd.lib")#else#pragma comment(lib,"osg.lib")#pragma comment(lib,"osgDB.lib")#pragma comment(lib,"osgViewer.lib")#pragma comment(lib,"OpenThreads.lib")#pragma comment(lib,"osgGA.lib")#endif#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>#include <osg/MatrixTransform>void main(){ osgViewer::Viewer viewer; osg::ref_ptr < osg::Group> root = new osg::Group() ; osg::ref_ptr < osg::Node> osgcool = osgDB::readNodeFile("glider.osg") ; osg::ref_ptr < osg::MatrixTransform> trans = new osg::MatrixTransform ; trans ->setMatrix(osg::Matrix::translate(0, 0, 2)) ; trans ->addChild(osgcool.get()) ; osg::ref_ptr < osg::MatrixTransform> scale = new osg::MatrixTransform ; scale ->setMatrix(osg::Matrix::scale(0.5, 0.5, 0.5)*osg::Matrix::translate(0, 0, -2)) ; scale ->addChild(osgcool.get()) ; osg::ref_ptr < osg::MatrixTransform > rot = new osg::MatrixTransform ; rot ->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(45.0), 1, 0, 0)*osg::Matrix::scale(0.5, 0.5, 0.5)*osg::Matrix::translate(4, 0, -2)) ; rot ->addChild(osgcool.get()) ; root ->addChild(osgcool.get()) ; root ->addChild(trans.get()) ; root ->addChild(scale.get()) ; root ->addChild(rot.get()) ; viewer.setSceneData(root.get()); viewer.realize(); viewer.run();}
2.2 模型控制类实现模型的平移、旋转、缩放等操作
创建NodeMatrix.h文件
#ifdef _DEBUG#pragma comment(lib, "osgd.lib")#pragma comment(lib, "osgDBd.lib")#pragma comment(lib, "osgGAd.lib")#pragma comment(lib, "osgViewerd.lib")#pragma comment(lib, "OpenThreadsd.lib")#pragma comment(lib, "osgUtild.lib")#pragma comment(lib, "osgTextd.lib")#else#pragma comment(lib, "osg.lib")#pragma comment(lib, "osgDB.lib")#pragma comment(lib, "osgGA.lib")#pragma comment(lib, "osgViewer.lib")#pragma comment(lib, "OpenThreads.lib")#pragma comment(lib, "osgUtil.lib")#pragma comment(lib, "osgText.lib")#endif#include <osgViewer/Viewer>#include <osgDB/ReadFile>#include <osgGA/GUIEventAdapter>#include <osgViewer/ViewerEventHandlers>#include <osg/AnimationPath>#include <iostream>#include <osg/MatrixTransform>#include <osg/PositionAttitudeTransform>#include <osg/Matrixd>class NodeMatrix : public osg::MatrixTransform{public: NodeMatrix(void); ~NodeMatrix(void);public: /**设置当前模型转动方式,pivot绕哪个点旋转,axis绕着那个轴转动,angularVelocity旋转速度*/ void rotating(const osg::Vec3d &pivot, const osg::Vec3d &axis, float angularVelocity); /**旋转模型*/ void toRotate(const osg::Matrix &mat); /**旋转模型*/ void toRotate(float angle, const osg::Vec3f &axis); /**缩放模型*/ void toScale(const osg::Matrix &mat); /**缩放模型*/ void toScale(double lel); /**addsChild方法*/ void addsChild(osg::Node *node); /**将模型移到目的点*/ void toPosition(osg::Vec3d &pos); /**得到模型当前的位置*/ osg::Vec3d getPosition(); /**限制模型大小*/ void adapt(osg::BoundingSphere &sps); /**限制模型大小*/ void adapt(osg::Node *node);private: osg::ref_ptr<osg::MatrixTransform> pat; osg::BoundingSphere ps; osg::Node * pnode; float level; osg::Vec3d position;};
创建NodeMatrix.cpp
#define NODE_MATRIX __declspec(dllexport)#include "NodeMatrix.h"NodeMatrix::NodeMatrix(void){ pat = new osg::MatrixTransform; addChild(pat.get()); level = 1.0; position = osg::Vec3d(0, 0, 0);}NodeMatrix::~NodeMatrix(void){}/**设置当前模型转动方式*/void NodeMatrix::rotating(const osg::Vec3d &pivot, const osg::Vec3d &axis, float angularVelocity){ setUpdateCallback(new osg::AnimationPathCallback(pivot, axis, angularVelocity));}/**旋转模型*/void NodeMatrix::toRotate(const osg::Matrix &mat){ pat->setMatrix(mat);}/**旋转模型*/void NodeMatrix::toRotate(float angle, const osg::Vec3f &axis){ pat->setMatrix(osg::Matrix::rotate(angle, axis));}/**缩放模型*/void NodeMatrix::toScale(const osg::Matrix &mat){ pat->setMatrix(mat);}/**缩放模型*/void NodeMatrix::toScale(double lel){ pat->setMatrix(osg::Matrix::scale(lel, lel, lel));}/**addsChild方法*/void NodeMatrix::addsChild(osg::Node *node){ pat->addChild(node); pnode = node; ps = node->getBound(); osg::notify(osg::NOTICE)<<ps.center().x() << " " <<ps.center().y() << " " <<ps.center().z() << std::endl;}/**将模型移到目的点*/void NodeMatrix::toPosition(osg::Vec3d &pos){ osg::Vec3d cps; cps.set(-ps.center().x()*level, -ps.center().y()*level, -ps.center().z()*level); pat->setMatrix(osg::Matrix::translate(cps)*osg::Matrix::translate(pos)); position = pos;}/**限制模型大小*/void NodeMatrix::adapt(osg::BoundingSphere &sps){ float level = sps.radius()/ps.radius(); pat->setMatrix(osg::Matrix::scale(level, level, level));}/**限制模型大小*/void NodeMatrix::adapt(osg::Node * node){ osg::BoundingSphere sps = node->getBound(); level = sps.radius()/ps.radius(); pat->setMatrix(osg::Matrix::scale(level, level, level));}/**得到当前的位置*/osg::Vec3d NodeMatrix::getPosition(){ return position;}
创建main.cpp文件
#include "NodeMatrix.h"int main(){ osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; osg::ref_ptr<NodeMatrix> nm = new NodeMatrix; osg::ref_ptr<osg::Group> group = new osg::Group; osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("glider.osg"); nm->addsChild(osgDB::readNodeFile("Cow.osg")); //nm->rotating(osg::Vec3d(10.0, 0.0, 0.0), osg::Z_AXIS, 1.0); //nm->toRotate(1, osg::Y_AXIS); nm->toPosition(osg::Vec3d(50.0, 0.0, 0.0)); //nm->adapt(node.get()); group->addChild(node.get()); group->addChild(nm.get()); viewer->setSceneData(group.get()); return viewer->run();}
参考书:FreeSouth的《QpenSceneGraph程序设计》
- OSG模型简单控制
- 模型简单控制
- OSG-简单模型控制
- 一个简单的库存控制模型
- unity3d模型运动转向移动简单控制
- Unity3D 加载fbx模型,实现简单的方向控制
- 微程序控制型简单CPU模型Verilog HDL实现
- 模型控制
- 控制模型
- 手机控制urdf小车模型运动(二)-创建简单的机器人模型
- [POSIX线程模型]_[使用pthread对工作线程进行简单控制-暂停-继续-停止]
- 利用unity3d自带的CharacterController包制作第一人称控制模型的简单Demo
- <Shader>简单的纹理坐标滚动(水波模型:脚本控制)
- Struts1.1控制模型
- 访问控制模型
- windows 访问控制模型
- 访问控制模型综述
- iOS蓝牙控制模型
- 待补充
- springcloud(二)
- Using System Calls
- solr-架构
- ありがとう
- 模型简单控制
- 如何在Linux上安装ftp组件
- C#中Math.Round()实现中国式四舍五入
- 符号常量
- Bluetooth MESH探究 --- (2) 协议栈架构
- java——内部类
- hdu2030 汉字统计(C语言)
- 【C语言】文件打开方式
- 矩阵找数--一个m*n的矩阵,从左到右从上到下都是递增的,给一个数x,判断x是否在矩阵中。要求效率尽可能的高。