OSG-OSG中的observer_ptr指针

转载 2017年10月10日 23:06:10
看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();

}


相关文章推荐

Qt 报错onecoreuap\inetcore\urlmon\zones\zoneidentifier.cxx(359)\urlmon.dll!00007FF9D9FA5B50:

具体报错内容 onecoreuap\inetcore\urlmon\zones\zoneidentifier.cxx(359)\urlmon.dll!00007FF9D9FA5B50: (c...

C++学习011-常用内存分配及释放函数

C++用有多种方法来分配及释放内存,下面是一些经常使用的内存分配及释放函数 现在我还是一个技术小白,一般用到也指示 new+delete 和 malloc和free 其他的也是在学习中看到...

OSG中的observer_ptr指针

看array大神的CookBook后一些感想,在代码上添加了一些注释,也对源码做了

关于OSG智能指针 osg::ref_ptr 的一些测试

接触OSG很久了,但本来编程就比较渣渣,看的书也比较少,所以,对这个新事物的理解总不是那么深刻。近日看到一篇博文《OSG 智能指针陷阱 总结》,发现博文中有很多问题,特在此把自己的测试及感想分享给同是...

OSG中的智能指针

OSG中的智能指针 智能指针对于C++程序员来说并不是一个陌生的东西,它在c++的内存管理中有着很广泛的应用(在最开始的时候,由于对智能指针不了解,还天真的以为智能指针就是osg的独创,想起来还正是...

OSG中的智能指针

OSG中使用了智能指针,对堆内存进行管理。  智能指针,其实就是在原始指针的基础上,加上了一个引用计数,然后通过引用计数的值,来决定什么时候释放内存。其目标就是确保一段内存会被释放,且只被释放一次。 ...

OSG中引用计数与智能指针实现原理

OSG中的智能指针 智能指针对于C++程序员来说并不是一个陌生的东西,它在c++的内存管理中有着很广泛的应用(在最开始的时候,由于对智能指针不了解,还天真的以为智能指针就是osg的独创,想起来还正是...

OSG智能指针

OSG智能指针         ref_ptr规则2:绝对不要返回ref_ptr 它自己规则3:绝对不要用ref()、unref(),(或者release()、unref_nodelete())除非...

不可不表的OSG智能指针之强指针与弱指针

使用OSG的人都知道OSG的内存管理方式采用了智能指针,通过智能指针的方式让OSG自己处理对象的销毁工作。在OSG中有两个智能指针类型,一个就是我们再熟悉不过的ref_ptr,另外一个可能很多人不一定...

[osg]源码分析:OSG中的智能指针osg::ref_ptr

探究一下osg中的智能指针:osg::ref_ptr。 一、首先注意,智能指针是个模板类(不要以为理解了这句话)。比如这样一个定义: osg::ref_ptr pArray = new o...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OSG-OSG中的observer_ptr指针
举报原因:
原因补充:

(最多只允许输入30个字)