osgViewer:: Viewer::advance() osg多线程与智能指针
void ViewerBase::frame(double simulationTime)
{
if (_done) return; // OSG_NOTICE<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl; if (_firstFrame)
{
viewerInit(); if (!isRealized())
{
realize();
} _firstFrame = false;
}
advance(simulationTime); eventTraversal();
updateTraversal();
renderingTraversals();
}
当前位置:osgViewer/Viewer.cpp 第 643行,osgViewer:: Viewer::advance()
好的,现在我们终于正式进入仿真循环当中了,之前的 realize 函数虽然十分重要,但它实际上是循环运行前的准备工作。而从这一日开始介绍的 advance,eventTraversal,updateTraversal 和 renderingTraversals 函数,才是真正的一帧的组成部分。
advance 函数的工作内容如下:
1、获取上一次记录的参考时间(Reference Time);
2、根据当前时刻,重新记录参考时间,并因此得到两次记录之间的差值,即一帧经历的时间;
3、记录已经经过的帧数;
4、有的时候我们需要将帧速率,参考时间等内容予以记录并显示给用户,此时需要通过 ViewerBase::getStats 函数获得 osg::Stats 对象,用以进行帧状态的保存和显示;
5、如果需要的话,使用 Referenced::getDeleteHandler()来处理 osg::Referenced 对象被弃用之后的删除工作。
仿真循环运行的参考时间,总时间和总帧数都是由 osg::FrameStamp 变量_frameStamp来处理的,如果用户程序需要获取这些信息的话,也可以通过读取这个变量的成员函数来实现。当然,使用 Viewer 中的 osg::Stats 变量_stats 也是可以的,缺省情况下,这个变量会忠实地记录当前帧以及之前的 24 帧的每帧用时,事件遍历用时,更新遍历用时,以及渲染遍历用时信息。如果我们想获得更多的历史数据,抑或对于频繁的记录操作感到厌烦,可以在开始仿真循环之前执行 ViewerBase::setStats 函数,重新设置这个记录器的参数,或者简单地将其置为 NULL。
void Viewer::advance(double simulationTime)
{
if (_done) return; double previousReferenceTime = _frameStamp->getReferenceTime();
unsigned int previousFrameNumber = _frameStamp->getFrameNumber(); _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+); _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) ); if (simulationTime==USE_REFERENCE_TIME)
{
_frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
}
else
{
_frameStamp->setSimulationTime(simulationTime);
} if (getViewerStats() && getViewerStats()->collectStats("frame_rate"))
{
// update previous frame stats
double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime;
getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime); // update current frames stats
getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
} //简单说来,它的工作是收集所有已经弃用的 OSG 场景对象,并在需要的时候(例如advance 函数代码的相应部分)执行 osg::DeleteHandler::flush,将它们统一删除。
//这里所说的“弃用”,与我们非常熟悉的 osg::ref_ptr 智能指针是密切相关的。我们已经知道,ref_ptr 采用内存引用计数的方式,当一个场景对象(通常是 Node 节点)链接到根节点或者其他节点时,它的引用计数加一,这一动作是通过 ref_ptr::ref()函数实现的;如果它被剔除出节点,那么它的引用计数减一,执行这一工作的函数是 ref_ptr::unref()。unref 函数的另一个重要任务是检查对象的引用计数值是否到达零,如果已经没有被其它对象所引用,那么称这个对象被“弃用”,它应当被立即删除,以释放相应的内存空间,避免泄露。
if (osg::Referenced::getDeleteHandler())
{
osg::Referenced::getDeleteHandler()->flush();
osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFrameNumber());
} }
DeleteHandler* Referenced::getDeleteHandler()
{
return s_deleteHandler.get();
}
又一次回到初始函数
void ViewerBase::frame(double simulationTime)
{
if (_done) return; // OSG_NOTICE<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl; if (_firstFrame)
{
viewerInit(); if (!isRealized())
{
realize();
} _firstFrame = false;
}
advance(simulationTime); eventTraversal();
updateTraversal();
renderingTraversals();
}
eventTraversal()这个函数有二百多行,在我们实验室的编码标准中是不允许的,这种情况下必须拆分成好几个函数,哈哈哈,言归正传,继续看王锐老师的解读
void Viewer::eventTraversal()
{
if (_done) return; double cutOffTime = _frameStamp->getReferenceTime(); double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // OSG_NOTICE<<"Viewer::frameEventTraversal()."<<std::endl; // need to copy events from the GraphicsWindow's into local EventQueue;
osgGA::EventQueue::Events events; Contexts contexts;
getContexts(contexts); // set done if there are no windows
checkWindowStatus(contexts);
if (_done) return; osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); // get events from user Devices attached to Viewer.
for(Devices::iterator eitr = _eventSources.begin();
eitr != _eventSources.end();
++eitr)
{
osgGA::Device* es = eitr->get();
if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
es->checkEvents(); // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events?
// for now assume now and just get the events directly without any reprojection.
es->getEventQueue()->takeEvents(events, cutOffTime);
} // get events from all windows attached to Viewer.
for(Contexts::iterator citr = contexts.begin();
citr != contexts.end();
++citr)
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
if (gw)
{
gw->checkEvents(); osgGA::EventQueue::Events gw_events;
gw->getEventQueue()->takeEvents(gw_events, cutOffTime); osgGA::EventQueue::Events::iterator itr;
for(itr = gw_events.begin();
itr != gw_events.end();
++itr)
{
osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
if (!event) continue; event->setGraphicsContext(gw); switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::RELEASE):
case(osgGA::GUIEventAdapter::DOUBLECLICK):
case(osgGA::GUIEventAdapter::MOVE):
case(osgGA::GUIEventAdapter::DRAG):
{
if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG ||
eventState->getGraphicsContext()!=event->getGraphicsContext() ||
eventState->getNumPointerData()<)
{
generatePointerData(*event);
}
else
{
reprojectPointerData(*eventState, *event);
} eventState->copyPointerDataFrom(*event); break;
}
default:
event->copyPointerDataFrom(*eventState);
break;
} events.push_back(event);
} for(itr = gw_events.begin();
itr != gw_events.end();
++itr)
{
osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
if (!event) continue;
switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
{
bool wasThreading = areThreadsRunning();
if (wasThreading) stopThreading(); gw->close();
_currentContext = NULL; if (wasThreading) startThreading(); break;
}
default:
break;
}
} }
} // create a frame event for the new frame.
{
osg::ref_ptr<osgGA::GUIEventAdapter> event = _eventQueue->frame( getFrameStamp()->getReferenceTime() ); if (!eventState || eventState->getNumPointerData()<)
{
generatePointerData(*event);
}
else
{
reprojectPointerData(*eventState, *event);
}
} // OSG_NOTICE<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl; _eventQueue->takeEvents(events, cutOffTime); // OSG_NOTICE<<"Events "<<events.size()<<std::endl; if ((_keyEventSetsDone!=) || _quitEventSetsDone)
{
for(osgGA::EventQueue::Events::iterator itr = events.begin();
itr != events.end();
++itr)
{
osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
if (!event) continue; // ignore event if it's already been handled.
if (event->getHandled()) continue; switch(event->getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
break; case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
if (_quitEventSetsDone) _done = true;
break; default:
break;
}
}
} if (_done) return; if (_eventVisitor.valid() && getSceneData())
{
_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=; 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->accept(*_eventVisitor); for(unsigned int i=; i<getNumSlaves(); ++i)
{
osg::View::Slave& slave = getSlave(i);
osg::Camera* camera = slave._camera.get();
if (camera && slave._useMastersSceneData)
{
camera->accept(*_eventVisitor);
}
} _eventVisitor->setTraversalMode(tm); }
} 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, , _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, , _eventVisitor.get());
}
} if (getViewerStats() && getViewerStats()->collectStats("event"))
{
double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); // update current frames stats
getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
} }
osgViewer:: Viewer::advance() osg多线程与智能指针的更多相关文章
- OSG中的智能指针
在OpenSceneGraph中,智能指针(Smart pointer)的概念指的是一种类的模板,它针对某一特定类型的对象(即Referenced类及其派生类)构建,提供了自己的管理模式,以避免因为用 ...
- 不可不表的OSG智能指针之强指针与弱指针 《转载》
不可不表的OSG智能指针之强指针与弱指针 <转载> 使用OSG的人都知道OSG的内存管理方式采用了智能指针,通过智能指针的方式让OSG自己处理对象的销毁工作.在OSG中有两个智能指针类型, ...
- osg(OpenSceneGraph)学习笔记1:智能指针osg::ref_ptr<>
OSG的智能指针,osg::ref_ptr<> osg::Referenced类管理引用计数内存块,osg::ref_ptr需要使用以它为基类的其它类作为模板参数. osg::ref_pt ...
- 【C/C++学院】0904-boost智能指针/boost多线程锁定/哈希库/正則表達式
boost_array_bind_fun_ref Array.cpp #include<boost/array.hpp> #include <iostream> #includ ...
- 引用内部函数绑定机制,R转义字符,C++引用,别名,模板元,宏,断言,C++多线程,C++智能指针
1.引用内部函数绑定机制 #include<iostream> #include<functional> usingnamespacestd; usingnamespac ...
- Qt osg QWidget osgViewer::Viewer
osgViewer::Viewer* _viewer = nullptr; _viewer = new osgViewer::Viewer;osg::ref_ptr<osg::Group> ...
- 根据OSG中的ref_ptr和Reference简化的智能指针
main.cpp测试代码 #include "TestSmartPointer" void fun() { SP<TestSmartPointer> sp1=new T ...
- 《最长的一帧》 osg3.4 osgViewer::View::init() osgViewer::Viewer::getContexts()
开始:osgViewer/ViewerBase.cpp 389行,startThreading()函数,启动线程 void ViewerBase::startThreading() { if ...
- enote笔记法使用范例(2)——指针(1)智能指针
要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...
随机推荐
- lvs+keepalived集群架构服务
一,LVS功能详解 1.1 LVS(Linux Virtual Server)介绍 LVS是Linux Virtual Server 的简写(也叫做IPVS),意即Linux虚拟服务器,是一个虚拟的服 ...
- Vue外卖的学习之路
用Vue打造外卖项目 一.项目前整理思绪 (1)项目所需的技术栈 (2)项目分布 (3)整体项目文件介绍
- Codeforces 348 D - Turtles Lindström–Gessel–Viennot lemma
#include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second ...
- MySQL进阶14--标识列(自增序列/auto_increment)--设置/展示步长--设置/删除标示列
/*进阶14 标识列 又称为自增序列; 含义 : 可以不用手动的插入值, 系统提供默认的序列值(1-->n) 特点 : 1.标识列必须和主键搭配? 不一定,但要求是一个key 2.一个表可以有几 ...
- postgresql sql查询结果添加序号列与每组第一个序号应用
1.postgresql 查询每组第一个 ROW_NUMBER () OVER (partition by 字段 ORDER BY 字段 DESC) 写法:SELECT ROW_NUMBER ( ...
- bzoj3097 hash killer 1——构造题
题意 在 $u64$ 自然溢出下,请输出一串字符串和 $L$,使得对任意 $Base$ 都能找到两个长度为 $L$ 的字串的 $Hash$ 值相同. 分析 $u64$ 自然溢出等价于两个哈希值模 $2 ...
- PHP+下载文件夹
php下载文件我整理了这三种方法,和大家分享一下: 第一种:直接添加文件下载的绝对路径连接 //如:我有一个文件在demo.xx.cn/demo.zip<button> <a ...
- Java 中的 SimpleDateFormat 【 parse 和 format 】【转换时间格式】
在 Java 里面有很多特别方便的函数(尽管术语可能不这么说)可以供我们使用,让一些本来要写好长好多的代码的事情变得仅仅几行就解决了. 在 SimpleDateFormat 中,有以下特定的规则: G ...
- es 修改 mapping 字段类型
一.原索引 PUT my_index { "mappings": { "_doc": { "properties": { "cre ...
- Pyhton3异常处理
例: while True: try: x = int(input("Please enter a number: ")) ...