补充

当然细心的你会发现,_scene->updateSceneGraph(*_updateVisitor)中还有一个imagePager::UpdateSceneGraph()还没有进行讲解,这是因为imagePager和DatabasePager是可以对比这理解的,这里imagePager的主要功能就是加载纹理图片文件。但是imagePager只是负责在另一个线程中加载图片,而没有databasePager的分页功能以及去掉过期数据。这样我们就真的可以重新回到Viewer::updateTraversal()中,继续向下进行了。

Viewer::updateTraversal()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// if we have a shared state manager prune any unused entries
    if (osgDB::Registry::instance()->getSharedStateManager())
        osgDB::Registry::instance()->getSharedStateManager()->prune();
 
    // update the Registry object cache.
    osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp());
    osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp());
 
 
    if (_updateOperations.valid())
    {
        _updateOperations->runOperations(this);
    }
 
    if (_incrementalCompileOperation.valid())
    {
        // merge subgraphs that have been compiled by the incremental compiler operation.
        _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp());
    }
 
    {
        // Do UpdateTraversal for slaves with their own subgraph
        for(unsigned int i=0; i<getNumSlaves(); ++i)
        {
            osg::View::Slave& slave = getSlave(i);
            osg::Camera* camera = slave._camera.get();
            if(camera && !slave._useMastersSceneData)
            {
                camera->accept(*_updateVisitor);
            }
        }
    }
 
    {
        // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
        // leave that to the scene update traversal.
        osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
        _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
 
        if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*_updateVisitor);
 
        for(unsigned int i=0; i<getNumSlaves(); ++i)
        {
            osg::View::Slave& slave = getSlave(i);
            osg::Camera* camera = slave._camera.get();
            if (camera && slave._useMastersSceneData && camera->getUpdateCallback())
            {
                camera->accept(*_updateVisitor);
            }
        }
 
        _updateVisitor->setTraversalMode(tm);
    }
 
    if (_cameraManipulator.valid())
    {
        setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
                            getCameraManipulator()->getFusionDistanceValue() );
 
        _cameraManipulator->updateCamera(*_camera);
    }
 
    updateSlaves();
 
    if (getViewerStats() && getViewerStats()->collectStats("update"))
    {
        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
 
        // update current frames stats
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
    }
      • 1、大家应该还记得前面提到的SharedStateManager,用于node间储存共享的属性或状态。我们将要遇到的下一个if就是要遍历这个SharedStateManager所有储存的共享状态,删除其中不再被引用到的。
      • 2、更新又一次被外部引用的在缓存中的对象的时间戳,以保证他不会被清除掉。然后就是清除掉已经过期的在缓存中的对象
      • 3、_updateOperations代表更新任务的队列,然后取得任务队列(OperationQueue),注意这里要使用 Mutex 互斥锁,避免用户追加任务时与线程的执行产生冲突。获取任务队列中的一个任务(OperationQueue::getNextOperation)。这个函数看似简单,只要从 std::list 列表中取出一个 osg::Operation 对象就可以了。但是其中还是有诸多的注意事项:首先,如果任务列表是空的,渲染线程将选择暂时阻塞自己(使用 block 函数),直到有新的 Operation 操作加入到队列中为止。其次,我们有一个任务列表迭代器_currentOperationIterator,如果这个迭代器已经到达列表的末尾,则自动将其转至列表首部,这样就可以在线程中循环执行任务列表中的内容。如果迭代器取得了一个 Operation 操作任务,那么我们需要判断这个任务是否将被反复执行,即,迭代器转至任务列表首部之后,是否还可以取得这个任务。判断所用的函数是Operation::getKeep,这个函数返回 true 时,任务将允许反复执行(例如场景筛选和绘制的任务),否则任务将被随即从列表中移除,我们也不会再取得这个 Operation 对象(除非再次将其加入列表)
      • 4、把已经编译好的子图进行合并。然后更新所有从相机自己的子图。调用任何相机更新回调,但只遍历那个回调,不要遍历其子图,将其留给场景更新遍历。
      • 5、使用相机操作器更新相机的位置。然后就是调用所有从相机的更新回调函数。并记录更新循环中的所有的信息。

现在我们总有算是完成了漫长的 updateTraversal 函数之旅。我们明天开始更艰巨的任务osgViewer:: ViewerBase::renderingTraversals()。

原文链接 http://www.3wwang.cn/blog/article.ftl?id=32

探索未知种族之osg类生物---呼吸分解之更新循环三的更多相关文章

  1. 探索未知种族之osg类生物---呼吸分解之更新循环二

    _scene->updateSceneGraph(*_updateVisitor); 我们用了前面4节才刚刚算是完成对DatabasePager::DatabaseThread::run()函数 ...

  2. 探索未知种族之osg类生物---呼吸分解之更新循环一

    上节总结 前几天我们大体上介绍完成了osg的事件循环的介绍,总结一下osg的时间循环主要就是得到平台(windows)的所有消息,并遍历所有的node的eventCallback,并对他们进行处理.接 ...

  3. 探索未知种族之osg类生物---呼吸分解之事件循环三

    那我们就开始处理这些事件中得到的所有的交互事件,首先我们要判断这些事件是否包含osg的退出事件,那什么情况下会触发这个退出事件呢?如果您运行过osg中example中的小例子的,聪明的你一定就会发现当 ...

  4. 探索未知种族之osg类生物---呼吸分解之事件循环一

    事件循环和更新循环 终于到了我们嘴里经常念叨的事件循环.更新循环以及渲染循环了.首先我们来区分一下事件循环和渲染循环,他们两个首先是两个不同顺序执行的过程,我们有时候会用到任意node的updateC ...

  5. 探索未知种族之osg类生物---呼吸分解之事件循环二

    VPM矩阵 1.V 表示摄像机的观察矩阵(View Matrix),它的作用是把对象从世界坐标系变换到摄像机坐标系.因此,对于世界坐标系下的坐标值 worldCoord(x0, y0, z0),如果希 ...

  6. 探索未知种族之osg类生物---呼吸分解之渲染遍历二

    那么今天我们就正式进入osg整个呼吸动作之中最复杂的一个动作,ViewerBase::renderingTraversals(),我们先介绍renderingTraversals的开头的简单的几步操作 ...

  7. 探索未知种族之osg类生物---呼吸分解之advance

    回顾 我们用了两节的内容才堪堪讲解完ViewerBase::frame()函数中调用的realize()---Viewer:: realize()函数.我们简单的总结就是Viewer:: realiz ...

  8. 探索未知种族之osg类生物---呼吸分解之渲染遍历一

    总结 前面我们基本上已经完成对ViewerBase::frame()函数的探究,只剩下renderingTraversals()渲染遍历的探究,虽然就剩下了一个函数,但是这却是最重要的,不可少的一个步 ...

  9. 《探索未知种族之osg类生物》目录

    精力有限,博客园不在更新<探索未知种族之osg类生物>.在这里列出所有文章目录(持续更新)有兴趣的同学可以看看. 探索未知种族之osg类生物[目录] 前序 探索未知种族之osg类生物--- ...

随机推荐

  1. [蓝桥杯]ALGO-187.算法训练_P0502

    编写一个程序,读入一组整数,这组整数是按照从小到大的顺序排列的,它们的个数N也是由用户输入的,最多不会超过20.然后程序将对这个数组进行统计,把出现次数最多的那个数组元素值打印出来.如果有两个元素值出 ...

  2. Reference.svcmap: Could not load file or assembly

    Reference.svcmap: Could not load file or assembly 在添加服务的时候出现如上错误, 把这个勾去掉就可以了.

  3. WPF Binding Mode,UpdateSourceTrigger

    WPF 绑定模式(mode) 枚举值有5个1:OneWay(源变就更新目标属性)2:TwoWay(源变就更新目标并且目标变就更新源)3:OneTime(只根据源来设置目标,以后都不会变)4:OneWa ...

  4. pt-table-checksum校验与pt-table-sync修复数据

    1:下载工具包 登录网站下载相应的工具包 https://www.percona.com/downloads/percona-toolkit/LATEST/ 2:安装 (1)yum安装: sudo y ...

  5. java.lang.Integer源码浅析

    Integer定义,final不可修改的类 public final class Integer extends Number implements Comparable<Integer> ...

  6. bootstrap的日期选择器

    时间框偏移解决办法 首先导入js和css文件 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js" ...

  7. day32基于tcp协议的远程执行命令

    客户端 from socket import *import structimport json client = socket(AF_INET, SOCK_STREAM)client.connect ...

  8. Windows下文件加固

    今天学到一种Windows下简单的文件加固方法,可以防止文件被(普通)删除. CMD找到要加固的文件. 例:C盘下有个 1516.txt 文本文件需要加固. 然后 copy 该文件.(注意:这里并非普 ...

  9. Laravel常见问题集锦

    1.提示:Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes? ...

  10. Centos nginx安装

    1.下载nginx http://nginx.org/en/download.html 2.上传到服务器上,并解压: rz 后选择上传的文件 tar -zxvf /fish/download/ngin ...