OSG-OSG中的observer_ptr指针

271人阅读 评论(0) 收藏 举报
分类:
看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::Node *m_node = _modelNode;//设置模型节点 osg::Vec3 start; osg::Vec3 end; osg::ref_ptr iv =...
  • HelloEarth_
  • HelloEarth_
  • 2017-11-20 20:15:39
  • 79

OSG鼠标选择求交

OSG鼠标选择求交 ////求交方法一:(用WINDOW坐标值,在相机下求交)            //osg::ref_ptr picker = new osgUtil::LineSegmen...
  • tmljs1988
  • tmljs1988
  • 2012-07-31 14:25:51
  • 11227

碰撞检测

1.计算交点#ifdef _DEBUG #pragma comment(lib, "osgd.lib") #pragma comment(lib, "osgDBd.lib") #pragma comm...
  • u013447988
  • u013447988
  • 2017-07-26 23:13:25
  • 128

osg中拾取对象和拾取点

使用osgUtil::PolytopeIntersector来拾取对象,使用这个类可与方便与点、直线等对象进行碰撞求交计算 int COSGViewInternal:PickObject(int x,...
  • wang15061955806
  • wang15061955806
  • 2016-06-07 16:10:34
  • 1566

OSG中的observer_ptr指针

看array大神的CookBook后一些感想,在代码上添加了一些注释,也对源码做了
  • u012501459
  • u012501459
  • 2014-07-18 10:46:40
  • 1715

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

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

osg线碰撞检测

简介利用osgUtil::LineSegmentIntersector做的线碰撞检测,原理是把小球当前位置和新位置练成线与盒子做碰撞检测,如果有交点,则不准小球移动,记录于此备忘代码#include ...
  • dancing_night
  • dancing_night
  • 2016-11-24 23:08:36
  • 470

osgkeyboardMouse例子分析

(1)Scribe(2)NodeVisitorclass CreateModelToSaveVisitor : public osg::NodeVisitor{public:    CreateMod...
  • tmljs1988
  • tmljs1988
  • 2011-05-06 17:12:00
  • 1905

MFC应用程序中指针的应用

  • 2011年09月27日 12:12
  • 28KB
  • 下载

c/c++中指针的理解(初学者)

关于指针,大家肯定不陌生,一些初学者,想必会出现思绪混乱的情况,现在我就来帮大家缕一缕吧。(第一次写微博 有点小紧张) 大家应该了解一些计算机对内存的管理方式吧。操作系统会将内存单元进行编号,这些...
  • Allen_ww
  • Allen_ww
  • 2016-01-11 19:41:28
  • 11377
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 26万+
    积分: 4721
    排名: 7703
    个人信息
    QQ:609932088

    邮箱:Dream_Dog@163.com

    博客专栏
    最新评论