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 ...
随机推荐
- CQRS项目
CQRS+ES项目解析-Diary.CQRS 在<当我们在讨论CQRS时,我们在讨论些神马>中,我们讨论了当使用CQRS的过程中,需要关心的一些问题.其中与CQRS关联最为紧密的模式莫 ...
- Maven配置环境变量
Windows: 1:新建系统M2_HOME变量,并把安装maven路径拷贝上去 2:配置path变量,并把maven路径拷贝上去,这次的maven路径到bin 3:测试maven环境是否配置 ...
- JavaScript003,用法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 【转载】浅谈HTTPS以及Fiddler抓取HTTPS协议
最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...
- 前端学习笔记--html入门
1.什么是html 2.标签和元素: 标签可嵌套,要注意缩进 html文档中的元素分为:内容文本.标签 3.标签和属性: 4.html的文件结构: 5.标签 a标签: 还不知道跳转到哪里,可以使用虚拟 ...
- JavaScript 隐式原型(_proto_)与显示原型(prototype)
作者:苏墨橘链接:https://www.zhihu.com/question/34183746/answer/59043879来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- Python通过yagmail和smtplib模块发送简单邮件
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件.HTML邮件以及带附件的邮件.python发邮件需要掌握两个模块的用法,smtplib和email,这俩模块是pytho ...
- go语言-变量与常量
变量 一.变量注意事项 变量名首字母大写,可以被其他包访问调用(公有),变量名首字母小写,其他包不能访问和调用(私有) 在同一个域里一个变量只能定义一次,不可重复定义 二.变量的声明的种方式 1.先声 ...
- php面向对象之$this->用法简述
在成员方法中,调用成员方法的方法是对象名加方法名,格式就是“对象名->方法名”.但是在定义类的时候,我们往往不知道对象名是什么,所以就没法用对象名,这时,我们就要用到伪变量$this. 什么是$ ...
- postgrepSQL psql基础操作
1.登录postgrepSQL psql 2.退出postgrepSQL \q 3.查看postgrepSQL里面的数据库 1)psql -l 2)\ l 4.切换DB \c db_name 5.查看 ...