我需要碰撞在osg中实现EventCallback,但是事件处理中没有响应,请问我这样写错误了吗?还是少了什么代码?

1339人阅读
osgWidget是通过HUD来实现的一个嵌入OSG中的响应界面,和功能更加强大的CEGUI类似。
WindowManager 是osgWidget管理类,继承自Switch,可以识别事件的响应,添加各种窗体,例如button
、label等。WindowManager还可以支持Lua、Python等脚本文件,通过ScriptEngine进行脚本解析。
Event定义事件,EventInterface定义响应事件的接口。
通过StyleManager来定义窗体的样式。
接下来在main中通过osgWidget::Box定义了一个容器,加载了ColorLabelMenu
osgWidget可能是参考Qt进行设计的,设计的方法类似Qt,widget是基类,label等从widget继承,,之
前说过osgWidget是通过HUD加入到OSG场景中的,那么这个HUD在什么地方呢?
找到osgWidget::Util中的createOrthoCamera 很熟悉,创建了一个平行投影的相机,
camera-&getOrCreateStateSet()-&setMode(
&&&&&&& GL_LIGHTING,
osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF
&&& camera-
&setProjectionMatrix(osg::Matrix::ortho2D(0.0, width, 0.0f, height));
&&& camera-
&setReferenceFrame(osg::Transform::ABSOLUTE_RF);
&&& camera-&setViewMatrix
(osg::Matrix::identity());
&&& camera-&setClearMask(GL_DEPTH_BUFFER_BIT);
&&& camera-
&setRenderOrder(osg::Camera::POST_RENDER);
来看看非常熟悉的这几句,这几句代码经常会用到,
创建HUD首先关闭光照,做一个平行投影,设置转换为绝对坐标,这个ABSOLUTE_RF说明了当前的相机节
点是相对于世界坐标的,设置相机矩阵为单位矩阵,清空深度缓存(因为这个HUD是要显示在显示器上,
因此不需要和场景中其他物体进行深度计算,干脆就清空,这样这个相机节点不进行深度测试,完全绘
制),POST_RENDER设置相机最后渲染。
当相机作为一个HUD节点使用的时候,我们就可以理解它是一个可以变换自身的普通节点,与相机的其它
功能区分开。
走的有些远了,来看看Label,继承Widget,可以设置样式、位置、文字等,ColorLabel继承Label
主要为了重新mousePush mouseEnter mouseLeave事件。
ColorLabelMenu继承了ColorLabel添加了更多的ColorLabel,addWidget的几个参数就是加入的窗体,在
table中的位置。ColorLabelMenu中的其它方法设计了简单的交互,显隐等,不多说了。
这里一直涉及到EaseMotionSampler,来看看EaseMotionSampler是什么:
createEaseMotionGeometry函数中根据传进来的Motion绘制了一条曲线。EaseMotionSampler继承了
NodeCallback,重写了operator()函数,在这个函数中对Callback的节点进行了setMatrix操作,也就是
根据motion进行运动,再来看main函数
&geode-&addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 4.0f)));
EASE_MOTION_SAMPLER = new EaseMotionSampler(osg::Vec3(50.0f, 0.0f, 0.0f));
EASE_MOTION_GEODE&& = new osg::Geode();
&&& mt-&addChild(geode);
&&& mt-&setUpdateCallback
(EASE_MOTION_SAMPLER);
&&& mt-&setNodeMask(MASK_3D);
这几行代码,把一个球,一条曲线加入到mt中,mt设置了callback,没一帧都调用operator方法更新自
身的位置,实现根据motion进行移动。
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
viewer.getCameraManipulator()-&setHomePosition(
&&&&&&& osg::Vec3d(0.0f, 0.0f, 200.0f),
& osg::Vec3d(20.0f, 0.0f, 0.0f),
&&&&&&& osg::Vec3d(0.0f, 1.0f, 0.0f)
&&&&&&& );
viewer.home();
设置了操作器,设置了操作器的初始位置,设置view的初始位置,执行createExample,createExample
中就是设置了窗体大小位置,根节点加入场景,eventhandler等。
createExample中的代码可以拿出来修改来实现自己的场景。
到目前唯一还有一点没有进行解析,那就是osgAnimation::Motion
来看看他是什么吧,在easeMotion(缓和的移动)类中,EaseMotion中定义了好多的移动方式,
TimeBehaviour执行一次还是循环,
Motion中三个重要的变量float _startV
&&&&&&& float _changeV
&&&&&&& float _
开始值,改变值,持续时间。
MathMotionTemplate继承了Motion重写了getValueInNormalizedRange,MathMotionTemplate是一个模板
类,通过不同的模板实现不同的效果,看看getValueInNormalizedRange中干了什么,没错,调用了模板
的getValueAt方法,这样不同的模板就产生了不同的效果,而EaseMotion中实现了很多的数学方法。各
种曲线函数,如果想实现自己的算法可以重写getValueAt方法,想参考不同的曲线算法都可以参考
EaseMotion中的实现。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:76338次
积分:1321
积分:1321
排名:千里之外
原创:58篇
评论:19条
(1)(2)(11)(17)(1)(23)(3)请问下我运行MATLAB GUI界面,出现如下错误,有谁能告诉我是什么意思么?不胜感激!!!_百度知道
请问下我运行MATLAB GUI界面,出现如下错误,有谁能告诉我是什么意思么?不胜感激!!!
??; untitled3 at 42
gui_mainfcn(gui_State?怎么修改; untitled3&gt:});cell'Error in ==&pushbutton2_Callback at 311m=eval(k)?;,guidata(hObject)) ,eventdata)untitled3('Error in ==& @(hObject, varargin{,eventdata,是什么意思;eval&#39,hO for input arguments of type 'Error in ==&gt.Error in ==&gt? Error while evaluating uicontrol Callback总共我有5个GUI设计界面; gui_mainfcn at 96
feval(varargin{:});pushbutton2_Callback&#39?,但每次运行其中两个的时候就会出现这些错误? Undefined function or method &#39
就能避免上述问题:a{0},即第一个成员的内容,访问其内容为:数据类型不对答。很可能是你输入的数据是元胞类型。建议你在函数中直接对元胞的内容进行访问,但是在程序中采用了中不支持元胞类型的函数。如a是元胞
其他类似问题
为您推荐:
matlab的相关知识
其他2条回答
你应该修改程序或者编写完成后点击保存,但是不要运行,从GUI面板中的运行开始,这样就可以了
pushbutton2_Callback at 311这行可能有错误,'pushbutton2_Callback'这个调用写的可能也有错误
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁osg笔记三&&
11:41:02|&&分类:&|字号&订阅
在用户程序中使用osg
Osg开放了所有的功能模块。因此用户程序完全可以使用最底层的osg功能来执行渲染操作。假设用户希望能够完全自主的控制场景图形的渲染,那么也可以按照下面的步骤编写应用程序的代码:
设计自己的视角管理代码:以改变OpenGL的模型视图矩阵。
创建用户窗口和OpenGL上下文,并将他们激活。如果有需要的话,用户也可以自行编写管理多窗口和多个设备上下文的代码。
如果应用程序需要使用分页数据库,那么可以使用osgDB::DatabasePager类
可以将osgUtil::UpdateVisitor,osgUtil::CullVisitor,osgUtil::RenderStage对象实例化,以实现场景的更新,挑选和绘制遍历。如果用户希望获得更多的控制权,则可以自己编写类来实现以上遍历的特性。
编写主循环代码来处理操作系统返回的事件。并且调用自己的视角观察代码来更新模型视图矩阵。
在渲染一帧之前先要调用glClear()。渲染时要依次执行场景更新,挑选和绘制遍历,最后交换缓存数据。
如果用户程序或者运行改程序的软﹑硬件平台需要立体化渲染(stereo rendering)或者多通道渲染(multipipe
rendering)功能的支持,则可以自行编写额外的代码。
最后请依照平台无关性的要求来编写所有的代码,这样你的代码才可以在所有的目标平台上运行通过。
用户使用osg时,往往可以利用以下这些工具和库来简化开发的过程:
osgUtil::SceneView:这个类封装了更新,挑选,和绘制遍历,但是并不启用DatabasePager。有一部分应用程序会使用SceneView作为osg渲染的主接口。
Producer和osgProducer—Producer是一个外部的摄像机库,可以支持多通道渲染。osgProducer是一个集成了Producer和osg的应用库。Producer有相当多的用户,目前有一部分的osg程序是基于osgProducer和Producer开发的。
Osg2.0版本核心添加了一个新的库成员—osgViewer。osgViewer包含了一系列的用于控制视口显示的相关的类,并封装了大量用户常用的功能函数,例如显示管理,事件响应,场景渲染等。这个库使用osg::Camera类来管理OpenGL的模型视图矩阵。与SceneView类不同,osgViewer的视口类提供了对DatabasePager的全部支持。osgViewer还可以针对同一个场景图形,提供并通过多个独立的视口显示该场景。
&& 3.1.1 Viewer类
&& 改变视口:
Viewer在其内部创建了一个osg::Camera摄像机对象来管理osg的模型—视图矩阵。用户可以通过以下的两个方法来控制Camera对象。
①将一个摄像机控制器对象关联到Viewer中。如果你的程序不需要这么做,那么Viewer.run()将自动创建一个osgGA::TrackballManipulator对象来控制摄像机的工作。osgGA库定义了一些常用的控制器类。用户可以调用Viewer::setCameraManipulator来指定一个期望的控制器。
②设置Camera对象的投影矩阵和观察矩阵为自定义的矩阵值。这样也可以保证用户程序能够完全控制视口的浏览动作。
osgViewer::setViewMatrix()方法来设置视口矩阵。参数是一个osg::Matrix矩阵,
osgViewer::setViewMatrixAsLookat():参数和gluLookAt类似,三个向量:eye,center,up。
设置清屏颜色:
Camera::setClearColor()用来设置清屏颜色,缺省情况下会清除深度和颜色缓存,可以使用Camera::setClearMask(GL_CLOLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)来设置清除属性。
3.1.2&&&&&&&&&
SimpleViewer 和 CompositeViewer
osgViewer::SimpleViewer类不会主动的创建窗口或者设备上下文,它需要依赖用户程序来创建窗口、上下文,并将其激活为当前设备,如果操作正确的话,SimpleViewer::frame()将会在用户给定的窗口中渲染。
osgViewer::CompositeViewer:Viewer类只能在一个场景中添加一个视口,而CompositeViewer类可以支持一个或多个场景的多个视口显示,并允许用户程序指定其渲染顺序。CompositeViewer还支持渲染到纹理(RTT)的操作,即,允许用户程序将一个视口中渲染的图像作为另一个视口的纹理贴图。
二.动态更改
Osg允许用户动态的修改场景图形并因而改变每一帧的显示。用户可以更改几何数据,渲染状态参数,Switch节点设置,以及任何场景图形的结构。OsgViewer库支持多线程模式,每一个线程均独立的运行挑选及绘制遍历,但osg并没有为了线程的安全性增设内存锁,而是要求用户程序只可在挑选及绘制遍历的时域之外修改场景图形。
确保用户的修改不会与挑选及绘制线程发生冲突,一个简单的方案是,在Viewer::frame()的调用之外进行场景图形的修改,这需要在主渲染循环中添加额外的代码。但如果用户希望自己的程序更加整洁及规范的话,可以选择在更新遍历中进行场景的修改操作。
一些与场景图形动态更改相关的基本技术:
处于性能优化和线程安全性的考虑,用户需要通知osg,场景图形的哪些部分是可能要进行修改的。用户可以通过设置Object对象(Node,Drawable,StateSet等)的数据变度(data
variance)属性来完成这一工作。
osh允许用户为Node和Drawable设置回调(callback)。Osg将在特定遍历中执行这些回调,
用户程序有时不能预知场景图形的哪一部分需要修改。这是需要搜索整个场景图形来查找特定的节点,或者由用户使用鼠标等输入设备来选择一个节点。
3.2.1&&&&&&&
OsgViewer支持的多线程模型允许主循环不必等到绘制遍历结束就可以继续运行,也就是Viewer::frame()方法在绘制遍历仍未结束的时候就可以返回。换句话说,上一帧的绘制遍历可以与下一帧的更新遍历产生重叠。Osg提供了osg::object::DataVariance()方法解决绘制遍历与多线程的更新操作的冲突。(Frame():Render
a complete new frame)。用于处理绘制遍历与其他遍历的同步性。
3.2.2&&&&&&&&&
Osg允许用户设置Node和Drawable对象的回调类。Node可以在执行更新和挑选时进行回调,Drawable可以在挑选和绘制遍历时进行回调。
使用NodeCallback,用户程序所需要执行的步骤:
从NodeCallback继承一个新的类。
重载NodeCallback::operator()方法,实现场景图形的动态更改。
实例化继承而来的类,然后使用Node::setUpdateCallback()方法关联到将要修改的Node。
NodeCallback::operator()两参数:第一个是回调类所关联的Node节点地址,第二个参数是osg::NodeVisitor对象的地址。
NodeVisitor::traverse():这个方法允许osg访问其他的节点并执行其回调。
3.2.3&&&&&&&&&
NodeVisitor类
这是osg对于访问器(visitor)设计思想的实现。从本质上说,NodeVisitor类遍历了一个场景图形并为每一个被访问节点调用特定的函数。这一简单的技术却是许多osg操作的基类,如osgUtil::Optimizer,osgUtil的几何体处理类。Osg使用osgUtil::UpdateVisitor类(继承自NodeVisitor)来实现更新遍历。
NodeVisitor是一个基类,用户程序无法直接将其实例化。但用户程序可以使用osg提供的任何NodeVisitor派生类,也可以自己编写继承自NodeVisitor类的代码。NodeVisitor包含了一些经过重载的apply()方法,其输入参数涵盖了大部分osg的节点类型。当一个NodeVisitor对象遍历整个场景图形时,它将会为每个被访问的节点调用其相应的apply()方法。
使用特定的名称来搜索节点也是一种简单而实用的操作。
允许NodeVisitor遍历:
缺省情况下,NodeVisitor类禁止执行遍历。因此在你的派生类中,需要使用枚举量NodeVisitor::TRAVERSE_ALL_CHILDREN来初始化基类,以允许执行遍历,否则osg将不会调用apply()方法。
如果要使用NodeVisitor来遍历整个场景图形,可以将NodeVisitor作为Node::accept()的输入参数传递。你可以在任何一个节点上调用accept(),NodeVisitor将从那个节点开始遍历整个场景图形,如果要搜索整个场景图形的话,可以从根节点开始调用accept()。
3.2.4&&&&&&&&&
从本质上讲,osg程序通过两个步骤来实现用户选择:
接受鼠标事件osgGA提供了允许程序接受鼠标事件的事件类,它具备设备平台无关特性。
判断场景图形的哪个部分被鼠标光标覆盖。osgUtil提供了一种相交集类(Intersection),可以在鼠标xy坐标的周围创建包围盒,并判段包围盒与场景图形的相交情况,osgUtil将按照由前至后的顺序返回与包围盒相交的节点列表。
捕捉鼠标事件
osgGA::TrackballManipulator将鼠标事件作为输入,并修改用于控制用户视口的osg::Camera视口矩阵。
TrackballManipulator派生自osgGA::GUIEventHandler类,是虚基类,无法实例化,但用户可以从GUIEventHandler派生自己的类,以实现各种基于GUI事件的操作。要实现鼠标控制的选择操作,可以从GUIEventHandler派生新的类,并重载
GUIEventHandler::Handle()方法,以接收鼠标事件。然后用户可以创建新类的实例并将其关联到应用程序的观察视口。
Virtual bool GUIEventHandler::Handle(const osgGA::GUIEventAdapter
& ea,osgGA::GUIActionAdapter &
aa);用户实现的Handle()方法可以接收来自GUIEventAdapter的各种GUI事件,包括鼠标事件。GUIEventAdapter类的头文件中定义了枚举类型EventType,用户程序可以从中选择自己需要的GUI事件。使用GUIEventAdapter.getEventType()方法可以得到当前的事件类型。GUIActionAdapter是用户返回给GUI系统的程序接口。当遇到鼠标选择的操作时,用户将用于选择事件的GUIEventHandler关联到视口类,则视口类就是一个GUIActionAdapter。用户需要使用他来实现当前视口与场景之间的交互。
在渲染视口之前,用户往往会创建一个GUIEventHandler派生类的实例,并使用Viewer::addEventHandler()将其关联到视口。一个视口可以有多个事件处理器,Viewer将事件处理对象添加到一个事件处理列表中。运行时Viewer将调用每个GUI事件的handle()函数,直到其中一个的handle()函数返回true为止。
要实现接收鼠标事件并实现用户选择的功能,需要经过以下几个步骤:
从GUIEventHandler继承新的类,重载handler()方法。
在handler()方法中检查GUIEventAdapter参数传递的事件类型,并针对需要的事件类型执行相应的操纵。方法返回true时将阻止其他事件处理器继续接受事件消息。
在渲染之前,创建事件处理器的实例,并使用addEventHandler()方法添加到视口中。Osg将会把视口作为GUIActionAdapter参数传递给handler()方法。
Osg使用一种多胞体(polytope)的金字塔形包围盒代替射线。这种金字塔的顶峰位于视点,其中心轴直接穿过鼠标(光标)的位置。它距离视点的宽度是由视场和程序控制的宽度参数决定的。
osgUtil::IntersectionVisitor类继承自NodeVisitor,它可以监测每个定点的包围盒与交集包围盒的关系,并允许在某个子图形不可能存在有交集的子节点时,跳过该子图形的遍历。
用户可以设置IntersectionVisitor类并使用几种不同的几何结构进行交集检测。其构造函数使用osgUtil::Intersector作为输入参数,Intersector定义了选择操作的几何体并执行实际的交集操作。Intersector是一个纯虚基类,osgUtil库从中派生了许多代表不同几何结构的新类。
有些程序需要拾取单独的顶点和多边形,而有些程序只需要简单的获取那些包含了被选节点的Group或Transform父节点。IntersectionVisitor返回osg::NodePath对象来满足这些要求。NodePath是一个std::vector向量,它表示沿着根节点到叶节点﹑呈现出一定排列层次的节点路线。如果用户程序需要获取中的父节点,只需要从后到钱搜索满足要求的节点即可。
要实现osg中的鼠标选择操作,需要按照如下的步骤编写代码:
创建并设置PolytopeIntersector,其中的鼠标位置应当使用GUIEventAdapter中经过归一化的数据。
创建IntersectionVisitor对象,并将PolytopeIntersector作为其构造函数的输入参数。
由场景图形的根节点加载IntersectionVisitor,一般来说是通过Viewer中的Camera对象,
如下面的代码:
iv是一个IntersectionVisitor对象
viewer.getCamera()-&accept(iv);
如果PolytopeIntersector的返回值包含了交集,那么可以获取返回的NodePath并搜索符合要求的节点。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。由于需要自动抓取OSG中的场景截图,对OSG掌握不好,花费了一些时间才算搞定。
首先,OSG在类osgViewer::ScreenCaptureHandler中默认情况下按下c(小写c)可以截取单张图片,而且实现得比较全面,在按下C(大写c)时可以连续截图;经过继承osgViewer::ScreenCaptureHandler类和osgViewer::ScreenCaptureHandler::CaptureOperation类,由于需要自动在某个时刻保存,所以些了一个自定义的事件,并将事件压入OSG的事件队列。
ScreenCapture.h文件 &
#pragma once
#ifndef SCREENCAPTURE_H
#define SCREENCAPTURE_H
#include &string&
#include &osgDB/WriteFile&
#include &osgViewer/ViewerEventHandlers&
class CScreenCapture : public osgViewer::ScreenCaptureHandler
class &WriteToImageFile : public osgViewer::ScreenCaptureHandler::CaptureOperation
enum SavePolicy
OVERWRITE,
SEQUENTIAL_NUMBER
// ... any others?
WriteToImageFile(const std::string& filename, const std::string& extension, SavePolicy savePolicy = SEQUENTIAL_NUMBER);
virtual void operator()(const osg::Image& image, const unsigned int context_id);
void setFileName(const std::string &filename){ _filename = }
void setSavePolicy(SavePolicy savePolicy) { _savePolicy = saveP }
SavePolicy getSavePolicy() const { return _saveP }
protected:
WriteToImageFile& operator = (const WriteToImageFile&) { return * }
std::string _
std::string _
SavePolicy _saveP
std::vector&unsigned int& _contextSaveC
CScreenCapture(CaptureOperation* defaultOperation = 0, int numFrames = 1);
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
void setFileName(const std::string& filename );
#endif // SCREENCAPTURE_H
ScreenCapture.cpp文件 &
/****************************************************************************
****************************************************************************/
#include &stdafx.h&
#include &ScreenCapture.h&
CScreenCapture::CScreenCapture(CaptureOperation* defaultOperation /*= 0*/, int numFrames/* = 1*/):
ScreenCaptureHandler( defaultOperation, numFrames )
bool CScreenCapture::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
osgViewer::ViewerBase* viewer = dynamic_cast&osgViewer::View*&(&aa)-&getViewerBase();
if (!viewer)
switch(ea.getEventType())
case (osgGA::GUIEventAdapter::FRAME):
// Booleans aren't the best way of doing this, but I want to do
// the actual adding here because I don't want to require
// startCapture() take a viewer as argument, which could not be
// the right one.
if (_startCapture)
// Start capturing with the currently set number of frames.
// If set to -1 it will capture continuously, if set to &0
// it will capture that number of frames.
_startCapture =
addCallbackToViewer(*viewer);
else if (_stopCapture)
_stopCapture =
removeCallbackFromViewer(*viewer);
case ( osgGA::GUIEventAdapter::USER )://自定义的事件,需要进入OSG的事件队列
const OwnDefineEventAdpater* adpater= dynamic_cast& const MyEventAdpater *&(ea.getUserData());
switch(adpater-&m_eventType)
case SAVE_IMAGE:// 保存图片的事件
if (getFramesToCapture() == 0)
setFramesToCapture(1);
addCallbackToViewer(*viewer);
//if (adpater-&m_eventType == SaveImage )
// // Check that we will capture at least one frame.
// // Just check for ==0, because &0 is means we're already
// // capturing and &0 means it will capture all frames.
// if (getFramesToCapture() == 0)
// setFramesToCapture(1);
// addCallbackToViewer(*viewer);
void CScreenCapture::setFileName( const std::string& filename )
CScreenCapture::WriteToImageFile* wtf = &dynamic_cast&CScreenCapture::WriteToImageFile*&(getCaptureOperation());
wtf-&setFileName( filename );
void CScreenCapture::WriteToImageFile::operator()( const osg::Image& image, const unsigned int context_id )//仿函数实现图片保存
if ( !_filename.empty() )
osgDB::writeImageFile( image, _filename );
CScreenCapture::WriteToImageFile::WriteToImageFile( const std::string& filename, const std::string& extension, SavePolicy savePolicy /*= SEQUENTIAL_NUMBER*/ )
: _filename( filename ),
_extension( extension ),
_savePolicy( savePolicy )
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:21123次
排名:千里之外
原创:20篇
转载:113篇
(3)(7)(5)(4)(2)(2)(9)(3)(6)(2)(7)(4)(8)(4)(11)(2)(2)(7)(1)(2)(13)(9)(1)(3)(3)(8)(5)&该示例程序主要展示了osg回调的用法,osg提供的回调功能主要使节点能够完成用户临时定义的功能,这些功能由回调函数完成,在每帧更新时(不同回调类型执行回调函数的时机不一样)执行回调函数完成用户定义的功能。
能执行回调函数的对象包括:节点、叶结点、相机、几何体(Drawable),osg提供的回调类型包括:
更新回调(UpdateCallback)每帧遍历时执行,自动执行回调函数。
事件回调(EventCallback):由事件触发回调函数的执行。
拣选回调(CullCallback):在拣选遍历时执行回调函数。
绘制回调(DrawCallback):几何体(Drawable)对象绘制时,执行回调函数,只能(Drawable)对象使用。
在示例程序中分别演示了这些回调类型的用法,执行回调首先要从osg::NodeCallback派生子类,在派生类中重载operator()方法,在该方法中加入自己定义的功能,然后让派生的类和相关的对象关联,执行回调。
示例程序主要使用InsertCallbacksVisitor类对根节点进行遍历,对于遍历到的节点执行相应的回调,示例代码如下:
class InsertCallbacksVisitor : public osg::NodeVisitor
&InsertCallbacksVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
//当遍历到节点时,执行更新和拣选回调&
virtual void apply(osg::Node& node)
&&&&&& node.setUpdateCallback(new UpdateCallback());
&&&&&& node.setCullCallback(new CullCallback());
&&&& &traverse(node);
//遍历到叶结点时,执行更新回调,对于叶结点执行拣选回调是无意义的。&
virtual void apply(osg::Geode& geode)
&&&&&&//执行更新回调
&&&&& geode.setUpdateCallback(new UpdateCallback());
&&&&&&//得到叶结点包含的几何体,对每个几何体执行更新、拣选、绘制回调&
&&&&& for(unsigned int i=0;i&geode.getNumDrawables();++i)
&&&&&&&&&& geode.getDrawable(i)-&setUpdateCallback(new DrawableUpdateCallback());
&&&&&&&&&& geode.getDrawable(i)-&setCullCallback(new DrawableCullCallback());
&&&&&&&& &geode.getDrawable(i)-&setDrawCallback(new DrawableDrawCallback());
&virtual void apply(osg::Transform& node)
&&&&& apply((osg::Node&)node);
对于每种回调类的定义,在此不再重复,请参看相关的代码。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:6226次
排名:千里之外
原创:14篇
转载:22篇
(8)(1)(1)(13)(13)}

我要回帖

更多关于 osg callback 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信