[osg]osgcallback各种回调使用的例子介绍

观察MyReadFileCallback结构体的内容,可以发现它继承自osgDB::Registry::ReadFileCallback,并重载了一个函数readNode,分析源代码可知,该函数在osgDB::readNodeFile函数中被调用,即,在加载模型文件时,即会调用 MyReadFileCallback结构体所重载的readNode函数并执行相应的内容。示例程序中该函数的内容如下:
class MyReadFileCallback : public osgDB::Registry::ReadFileCallback
{
public:
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options)
{
std::cout<<"before readNode"<<std::endl;
// note when calling the Registry to do the read you have to call readNodeImplementation NOT readNode, as this will
// cause on infinite recusive loop.
osgDB::ReaderWriter::ReadResult result = osgDB::Registry::instance()->readNodeImplementation(fileName,options);
std::cout<<"after readNode"<<std::endl;
return result;
}
};
其中较为重要的是readNodeImplementation一行,这是模型文件读取的实际执行函数,如果在回调中对于这一语句的使用有错,那么模型无论怎样都不能被加载。

InsertCallbacksVisitor的内容比较复杂,它继承自osg::NodeVisitor,属于用户自定义的节点访问器。换句话说,当执行到:
InsertCallbacksVisitor icv;
rootnode->accept(icv);
节点访问器将从根节点rootnode开始,遍历所有的子节点并执行相应的操作。
节点访问器InsertCallbacksVisitor的构造函数中,可以传递一个遍历方式的枚举量TraversalMode ,它的取值意义如下:
TRAVERSE_NONE:仅仅传递到当前节点,然后停止传递; 
TRAVERSE_PARENTS:传递给当前节点及其父节点,注意,如果当前节点有不止一个父节点,那么访问器将列举出所有的传递路线,其中可能有多个重复出现的节点; 
TRAVERSE_ALL_CHILDREN:传递给当前节点及其所有子节点,同样,对于多个子节点的情况,访问器将列举所有的传递路线; 
TRAVERSE_ACTIVE_CHILDREN:传递给当前节点及所有被激活的子节点,例如遇到LOD节点和Switch节点时,将不会传递给当前无法显示的子节点。

在节点访问器中,使用apply函数来实现对各种类型的节点的访问。当遍历过程中遇到与某个重载的apply的输入参数相符合的节点时,将执行这一 apply函数的内容。示例代码中重载了Node,Geode和Transform节点的访问函数。在Geode节点的访问函数中,实现了对场景图形结构中每个节点的回调指定:
// 指定Geode节点的更新回调。
geode.setUpdateCallback(new UpdateCallback());

// 指定Geode节点中所有关联几何体(Drawables)的绘制回调,拣选回调和更新回调。
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());
}

在Geode之外的其它节点的apply函数中,往往包含有下面的语句:
traverse(node);
这表示对场景图形节点的遍历将继续进行。换句话说,如果某种类型的节点的apply函数中不包含这一语句,那么场景图形遍历到这一类型的节点时,当前遍历的路线将自动结束,以下的子节点均被忽略。而对Geode节点来说,因为不存在子节点,因此也不必添加这一语句。

使用节点访问器为场景图形节点或几何体添加的回调主要有以下几种:
几何体绘制遍历(DrawableDrawCallback):重载函数drawImplementation,当几何体进行绘制时,函数的内容被调用,注意需要添加Drawable::drawImplementation函数以实现几何体的实际绘制,否则将无法画出当前的几何形状。可以参阅 include/osg/Drawable,draw函数中的调用过程。
几何体拣选遍历(DrawableCullCallback):重载函数cull,当几何体进行拣选优化时,函数的内容被调用。可以参阅src/osgUtil/CullVisitor,apply(Geode&)函数中的调用过程。
几何体更新遍历(DrawableUpdateCallback):重载函数update,当几何体更新时,函数的内容被调用。可以参阅include/osgUtil/UpdateVisitor,handle_geode_callbacks函数中的调用过程。
拣选遍历(CullCallBack):重载操作符operator(),当场景执行拣选优化时,operator()的内容被调用,注意需要添加 traverse函数以实现节点的继续遍历。可以参阅include/osgUtil /CullVisitor,handle_cull_callbacks_and_traverse函数中的调用过程。
更新遍历(UpdateCallBack):重载操作符operator(),当场景更新时,operator()的内容被调用,注意需要添加 traverse函数以实现节点的继续遍历。可以参阅src/osg/StateSet.cpp,runUpdateCallbacks函数中的调用过程。

最后,观察CameraUpdateCallback和CameraEventCallback结构体的内容,可以发现它们均继承自 osg::NodeCallback,并重载了操作符operator(),当执行摄像机更新或者事件回调时,operator()的内容将被调用,添加 traverse函数可以实现节点的继续遍历。

此外,还可以使用Node::setEventCallback来设置节点的事件回调,其输入参数为继承自osg::NodeCallback的用户类,且需要重载操作符operator()以实现回调过程的处理。

综上,可以得出回调的编写方法:
1、编写用户结构体,继承OSG中相应的虚函数结构体,如osg::NodeCallBack;
2、重载回调执行函数,根据回调种类的不同,执行函数的名称也不同,可以参考osgcallback中的设置;
3、注意在回调执行的过程中,有一些必要的系统操作需要交由用户来完成,例如readNodeImplementation,Drawable::drawImplementation,traverse等,否则系统本身的渲染工作可能会不正常。

编译运行osgcallback之后,可以看到控制台不断输出各种回调的执行结果,用户可以根据自己的需要在不同的时间段进入不同的回调来完成所需的工作。

时间: 2024-08-27 06:17:14

[osg]osgcallback各种回调使用的例子介绍的相关文章

ThinkPHP 自动创建数据、自动验证、自动完成详细例子介绍(十九)

原文:ThinkPHP 自动创建数据.自动验证.自动完成详细例子介绍(十九) 1:自动创建数据 //$name=$_POST['name']; //$password=$_POST['password'];  ---这个注册页面传过来的POST值 下面用了自动穿件create方法就可以不用这个,会行动绑定 $user =M('User'); $User->create();   //会将传过来的$_POST数据对应到数据库的字段 $user->add();   //就可以直接写入 2:自动验证

OSG使用更新回调来更改模型

OSG使用更新回调来更改模型 转自:http://blog.sina.com.cn/s/blog_668aae7801017gl7.html 使用回调类实现对场景图形节点的更新.本节将讲解如何使用回调来实现在每帧的更新遍历(update traversal)中进行节点的更新. 回调概览用户可以使用回调来实现与场景图形的交互.回调可以被理解成是一种用户自定义的函数,根据遍历方式的不同(更新update,拣选cull,绘制draw),回调函数将自动地执行.回调可以与个别的节点或者选定类型(及子类型)

转:Delphi 回调函数及例子

http://anony3721.blog.163.com/blog/static/5119742010866050589/ { http://anony3721.blog.163.com/blog/static/5119742010866050589/ 例子出处 } unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,StdCt

js的回调函数 一些例子

这边用bootstrap 3.0的  上传控件做例子 下面是上传控件的一段完整的 js 操作 代码. <!-- 上传缩略图控件配置 --><script> // 定义这四个全局变量是 为了保存4张图片的uuid 在回调函数中每次保存 都覆盖前一张的名字 实现 用户可以重复添加取最终的结果保存入库 window.Picture1=""; //轮播图1的全局变量 window.Picture2=""; //轮播图2的全局变量 window.Pic

java回调函数的例子

1. 定义一个回调接口 public interface CallBack { //执行回调操作的方法 void execute(); } 2. 定义一个类的方法,使上面定义的回调接口接口作为它的参数 . public class Test { /** * 测试函数,通过定义CallBack接口的execute方法 * @param callBack */ public void test(CallBack callBack) { System.out.println("回调前..."

PHP操作MongoDB数据库详细例子介绍(增、删、改、查) (六)

PHP操作mongodb: PHP 要操作mongodb需要打模块 官网可以下载:http://pecl.php.net/package/mongo 下载 mongodb设置成用户授权的启动方式 php手册没有些用户授权方式登陆的方法: conn.php <?php $conn = new Mongo("mongodb://user1:[email protected]:27017/test"); //用户授权链接mongodb test数据库 $db = $conn->t

[转载]一个小例子介绍Obj-C的函数命名方式

原文链接:http://www.cnblogs.com/liufan9/archive/2013/04/02/2995626.html 对于以前做C#或者JAVA开发的朋友而言,初次接触iOS开发,Obj-C的函数命名方式可能会感觉非常不习惯. 尤其是打开AppDelegate.m,映入眼帘的代码竟然是: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)l

基于委托的C#异步编程的一个小例子 带有回调函数的例子

我创建的是一个winform测试项目:界面如下: 设置: 下面是代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; usin

通过两个简单例子介绍avalon

<html> <head> <title>TODO supply a title</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="avalon.js"></s