zoukankan      html  css  js  c++  java
  • 探索未知种族之osg类生物---呼吸分解之事件循环三

    eventTraval

    那我们就开始处理这些事件中得到的所有的交互事件,首先我们要判断这些事件是否包含osg的退出事件,那什么情况下会触发这个退出事件呢?如果您运行过osg中example中的小例子的,聪明的你一定就会发现当按下esc时就会退出osg。所以osg中默认的退出事件就是由esc触发的。当然我们也可以通过ViewerBase::setQuitEventSetsDone 设置是否允许按下某个键之后直接退出这种做法, 同时还可以使用另一个函数 ViewerBase::setKeyEventSetsDone 来设置自定义的退出键。

    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
    _eventVisitor->setFrameStamp(getFrameStamp());
            _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
     
            for(osgGA::EventQueue::Events::iterator itr = events.begin();
                itr != events.end();
                ++itr)
            {
                osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
                if (!event) continue;
     
                _eventVisitor->reset();
                _eventVisitor->addEvent( event );
     
                getSceneData()->accept(*_eventVisitor);
     
                // Do EventTraversal 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(*_eventVisitor);
                    }
                }
     
     
                // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph
                // leave that to the scene update traversal.
                osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
                _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
     
                if (_camera.valid() && _camera->getEventCallback()) _camera->accept(*_eventVisitor);
     
                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->getEventCallback())
                    {
                        camera->accept(*_eventVisitor);
                    }
                }
     
                _eventVisitor->setTraversalMode(tm);
     
            }

    我们还是先来看一下其中一些新认识的成员。_eventVisitor:, 为了正确地遍历场景的节点和几何体对象,并执行所有可能的事件回调和更新回调, OSG 使用访问器(Visitor)机制来处理场景图形的访问工作。这其中,_eventVisitor 就是负 责管理事件回调的遍历工作的。在事件循环中主要是的访问器主要是通过setEventCallback来设置Drawable对象中的事件回调的。在事件回调的处理函数中(operator()或者 event),我们可以通过读取第二个传入参数, 并调用 EventVisitor::getEvents 函数来获取当前发生的事件。所有的交互和系统事件都会一次 又一次地触发事件回调,因此编写这个回调的内容时请一定要慎重,不然会大幅度地降低系 统的性能。

    那我们回到osgViewer::eventTraversal函数中,首先我们需要设置当前的处于那一帧中,并进行统计,下一步就是我们要遍历所有事件队列中的事件,并放到eventVisitor中。,OSG 还要转至主摄像机_camera 和从摄像机组 _slaves,再次执行它们的事件回调对象,依然使用访问器,但是设置访问器不要向下遍历节点(因为 Camera 同样可以作为场景 的一个中间节点),在访问过所有摄像机之后再恢复访问器的原有值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    for(osgGA::EventQueue::Events::iterator itr = events.begin();
            itr != events.end();
            ++itr)
        {
            osgGA::Event* event = itr->get();
            for(EventHandlers::iterator hitr = _eventHandlers.begin();
                hitr != _eventHandlers.end();
                ++hitr)
            {
                (*hitr)->handle( event, 0, _eventVisitor.get());
            }
     
        }
     
        for(osgGA::EventQueue::Events::iterator itr = events.begin();
            itr != events.end();
            ++itr)
        {
            osgGA::Event* event = itr->get();
            if (event && _cameraManipulator.valid())
            {
                _cameraManipulator->handle( event, 0, _eventVisitor.get());
            }
        }

    然后在遍历场景节点并执行其事件回调之后,在遍历所有的相机操作中的handler函数。这样就基本完成了事件循环的遍历。最后,计算事件遍历的结束时间,将相关的时刻信息保存到记录器中。

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

  • 相关阅读:
    SSH框架的简单上传功能的实现
    笔记:《C++ Primer》第3章
    笔记:《C++ Primer》第1章和第2章
    tcl脚本学习十三:列表命令集
    tcl脚本学习十二: upvar的学习
    tcl脚本学习十一:proc应用 (带默认参数)
    tcl脚本学习十:proc 子函数的使用
    tcl脚本学习八:while循环的使用
    tcl脚本学习九:for循环的学习
    tcl脚本学习七:if的学习
  • 原文地址:https://www.cnblogs.com/wang985850293/p/10463446.html
Copyright © 2011-2022 走看看