看array大神的CookBook后一些感想,在代码上添加了一些注释,也对源码做了一些研读,记录下学习的过程。

CookBook中第一个例子就是observer_ptr指针,这个指针和它的名字一样,就是用来观察指针的,可以把它想象成一个观察者,它只观察一个你给他指点的对象,但是不会影响这个对象的创建和销毁,它只是一个旁观者,但是它观察的这个对象要是被销毁了它也会知道并且自己也会被销毁。和osg::ref_ptr不同,osg::ref_ptr是用来管理指针的创建和删除的。如下图:

下面是代码,代码中添加了注释,因为CookBook中的例子很多,所以定义了一个common.h和common.cpp,记录一些通用型的类和函数。common.h:

#pragma  once
#ifdef _DEBUG #pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgDBd.lib")
#pragma comment(lib,"osgViewerd.lib")
#pragma comment(lib,"osgGAd.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,"osgViewer.lib")
#pragma comment(lib,"osgGA.lib")
#pragma comment(lib,"osgUtil.lib")
#pragma comment(lib,"osgText.lib") #endif #include <osg/Camera>
#include <osg/Geode>
#include <osg/Node>
#include <osg/ShapeDrawable> #include <osgText/Text>
#include <osgUtil/LineSegmentIntersector> #include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIEventHandler> #include <osgViewer/Viewer> namespace osgCookBook{ extern osg::Camera* createHUDCamera(double left,double right,double bottom,double top); extern osgText::Text* createText(const osg::Vec3 &pos,const std::string &content,float size); class PickHandler : public osgGA::GUIEventHandler
{
public:
/** .h中的成往事 */
virtual void doUserOperation(osgUtil::LineSegmentIntersector::Intersection& )=0;
virtual bool handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter & aa);
};
}

common.cpp:

#include "common.h"

namespace osgCookBook{

	/** 创建HUD相机 */
osg::Camera* createHUDCamera(double left,double right,double bottom,double top){ osg::ref_ptr<osg::Camera> camera=new osg::Camera;
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::POST_RENDER);
camera->setAllowEventFocus(false);
camera->setProjectionMatrix(osg::Matrix::ortho2D(left,right,bottom,top));
camera->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
return camera.release();
} osg::ref_ptr<osgText::Font> g_font=osgText::readFontFile("fonts/arial.ttf"); /** 创建文字节点 */
osgText::Text* createText(const osg::Vec3 &pos,const std::string &content,float size){ osg::ref_ptr<osgText::Text> text=new osgText::Text;
text->setDataVariance(osg::Object::DYNAMIC);
text->setFont(g_font.get());
text->setCharacterSize(size);
text->setAxisAlignment(osgText::TextBase::XY_PLANE);
text->setText(content);
return text.release();
} /** 实现处理器中的handle方法*/
bool PickHandler::handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter & aa){
if (ea.getEventType()!=osgGA::GUIEventAdapter::RELEASE
||ea.getButton()!=osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON
||!(ea.getModKeyMask()&osgGA::GUIEventAdapter::MODKEY_CTRL))
return false; osgViewer::View *viewer=dynamic_cast<osgViewer::View *>(&aa);
if (viewer)
{
//定义射线求交类,它的定义方式有3种
//在窗口坐标系osgUtil::Intersector::WINDOW中会创建一个一个起点(x,y,0)到终点(x,y,1)的线段
//在投影坐标系osgUtil::Intersector::PROJECTION中会创建一个一个起点(x,y,-1)到终点(x,y,1)的线段
//在模型视图坐标系osgUtil::Intersector::VIEW或osgUtil::Intersector::MODEL中会创建一个一个起点(x,y,0)到终点(x,y,1)的线段
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector=new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW,ea.getX(),ea.getY()); //创建求交访问器
osgUtil::IntersectionVisitor iv(intersector.get());
viewer->getCamera()->accept(iv); //判断射线求交是否有交点
if (intersector->containsIntersections())
{
//射线求交的交点是经过深度排序的
//intersector->getIntersections()的返回结果是Intersections
//这是Intersections的定义:typedef std::multiset<Intersection> Intersections
//就是说Intersections是一个multiset,multiset是一个有序的容器,里面的元素都是经过排序的
//它排序的标准是里面元素的<操作符的定义,在这里就是Intersection中<操作符的定义
//而在Intersection类中有如下操作符重载: bool operator < (const Intersection& rhs) const { return ratio < rhs.ratio; }
//也就是说ratio是反应交点与射线起点距离的一个成员变量,array也说了ratio是交点与线段起点的距离和线段总长度的比例
osgUtil::LineSegmentIntersector::Intersection &result=*(intersector->getIntersections().begin());
doUserOperation(result);
}
} return false;
} }

然后就是observer_ptr指针的例子:observe_ptr.cpp

#include "../common/common.cpp"

/**
* 事件处理器类
继承自PickHandler,只需要重写用户自定义方法doUserOperation即可
*/
class RemoveShapeHandle : public osgCookBook::PickHandler
{ virtual void doUserOperation(osgUtil::LineSegmentIntersector::Intersection& result){ //射线求交得到的结果
if (result.nodePath.size()>0)
{
//得到该路径中最后一个节点
osg::Geode* geode=dynamic_cast<osg::Geode *>(result.nodePath.back());
if (geode)
geode->removeDrawable(result.drawable);
}
} int test;
}; /**
* 节点回调类,每一帧都会执行
*/
class ObserveShapeCallback : public osg::NodeCallback{
public: virtual void operator()(osg::Node * node,osg::NodeVisitor *nv){
std::string content;
if(_drawable1.valid()) content+="Drawable 1 ;";
if(_drawable2.valid()) content+="Drawable 2 ;";
if(_text.valid()) _text->setText(content);
} osg::ref_ptr<osgText::Text> _text;
osg::observer_ptr<osg::Drawable> _drawable1; //这里如果用ref_ptr那么当这个Drawable被移除后,文字依然存在
osg::observer_ptr<osg::Drawable> _drawable2;
}; int main()
{
osgText::Text * text=osgCookBook::createText(osg::Vec3(70.0,70.0,0.0f),"",10.0f);
osg::ref_ptr<osg::Geode> textGeode=new osg::Geode;
textGeode->addDrawable(text); osg::ref_ptr<osg::Camera> hudCamera=osgCookBook::createHUDCamera(0,800,0,600);
hudCamera->addChild(textGeode); osg::ref_ptr<osg::Geode> geode=new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(-2.0f,0.0,0.0),1.0)));
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(2.0,0.0,0.0),1.0))); osg::ref_ptr<osg::Group> root=new osg::Group;
root->addChild(hudCamera);
root->addChild(geode); osg::ref_ptr<ObserveShapeCallback> ob=new ObserveShapeCallback;
ob->_text=text;
ob->_drawable1=geode->getDrawable(0);
ob->_drawable2=geode->getDrawable(1);
root->addUpdateCallback(ob); osgViewer::Viewer viewer;
viewer.addEventHandler(new RemoveShapeHandle);
viewer.setSceneData(root);
return viewer.run(); }

OSG-OSG中的observer_ptr指针的更多相关文章

  1. OSG中的智能指针

    在OpenSceneGraph中,智能指针(Smart pointer)的概念指的是一种类的模板,它针对某一特定类型的对象(即Referenced类及其派生类)构建,提供了自己的管理模式,以避免因为用 ...

  2. [osg]OSG使用更新回调来更改模型

    使用回调类实现对场景图形节点的更新.本节将讲解如何使用回调来实现在每帧的更新遍历(update traversal)中进行节点的更新.        回调概览       用户可以使用回调来实现与场景 ...

  3. QT中使用函数指针

    想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...

  4. C++中引用与指针的区别(详细介绍)

    C++中引用与指针的区别(详细介绍) C++中的引用与指针的区别   指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一 ...

  5. Delphi中的函数指针判断是否为空

    delphi函数指针 只有@@p才代表了函数指针本身的地址   assigned(p) 判断是否为空 或者用 @p=nil 来判断函数指针是不是为空 Delphi中的函数指针实际上就是指针,只是在使用 ...

  6. js中的this指针(三)

    当一个函数并非一个对象的忏悔时,它会被当作一个函数来调用. 此时,函数中的 this 指针被绑定到了全局对象. 后果:方法不能利用内部函数来帮助工作,由于 this 被绑定了错误的值,将无法共享该方法 ...

  7. 由javascript中的this指针所想到的

    初次结识 this 指针,是在学 <<C++ Primer Plus>>这本书的时候(这本书勉强读了一二遍,之后转学 html+css+js了,不过这是后话). 依稀记得书中举 ...

  8. [BS-21] 关于OC中对象与指针的思考

    关于OC中对象与指针的思考 1. 创建对象: OC中可通过代码Person *p = [[Person alloc] init];创建了一个对象p.该过程中内存情况为: 在当前线程的栈(默认1M)中, ...

  9. PHP中使用数组指针函数操作数组示例

    数组的内部指针是数组内部的组织机制,指向一个数组中的某个元素.默认是指向数组中第一个元素通过移动或改变指针的位置,可以访问数组中的任意元素.对于数组指针的控制PHP提供了以下几个内建函数可以利用. ★ ...

随机推荐

  1. [LuoguP2900] [USACO08MAR]土地征用(Land Acquisition)

    土地征用 (Link) 约翰准备扩大他的农场,眼前他正在考虑购买N块长方形的土地.如果约翰单买一块土 地,价格就是土地的面积.但他可以选择并购一组土地,并购的价格为这些土地中最大的长 乘以最大的宽.比 ...

  2. [转]SQL Server 安全性概論與無法刪除資料庫使用者的解決辦法

    經常有人來問我特定 SQL Server 資料庫裡的使用者無法刪除的問題,這問題其實跟 SQL Server 的安全性架構有很大關係,解決這個問題當然還是瞭解觀念的重要性大於知道如何解決問題.除了講解 ...

  3. selenium处理table表格

    在UI自动化测试中经常会遇到表格的处理,下面是一点心得. 假设网页页面有一个表格,如何获取这个table的指定cell的值?你会说我们可以根据xpath定位到这个cell的行列,然后getText() ...

  4. 【Node.js】Jade视图模板的使用

    跟MVC里面的Rezor做差不多的事儿,但是比Rezor弱了一些,比较不喜欢CoffeeScript.Jade这种靠缩进来维系层级结构的做法,就好比接受不了c#中if下面只有一句很长的代码,但是却不加 ...

  5. asp.net mvc5 step by step(一)——CURD增删查改Demo

    1.  新建一个项目:

  6. Zabbix——使用邮件报警

    前提条件: 1. Zabbix版本4.0 zabbix-server 命令配置: yum install mailx -y #下载邮件功能 vi /etc/mail.rc set bsdcompat ...

  7. Angular.js进阶

    1.常用指令 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UT ...

  8. git 完善使用中

    GIT 版本库控制: 第一步:Git 的账号注册 url :https://github.com/ 这是git的官网如果第一次打开会这样 中间红色圈内是注册 内容, 第一项是用户名 第二项是邮箱 第三 ...

  9. 解决thinkphp query()执行原生SQL语句成功结果报错的问题

    1.query方法 query方法用于执行SQL查询操作,如果数据非法或者查询错误则返回false,否则返回查询结果数据集(同select方法). 2.execute方法 execute用于更新和写入 ...

  10. day 15 装饰器

    装饰器(重点,难点) 开闭原则:             对功能的扩展开放            对代码的修改是封闭的 在目标函数前和后插入一段新的代码.不改变原来的代码 通用装饰器写法: # 存在的 ...