【OSG源码阅读】Day 1: 从Viewer的run函数开始
Viewer的run函数
几乎每一个OSG代码都是从这个函数开始了运行。
我们来看下这个函数都干了什么?
我这里下载的是OpenSceneGraph-3.2.3版本。
首先找到源码的Viewer
(OsgViewer/osgViewer.cpp)类:
int Viewer::run()
{if (!getCameraManipulator() && getCamera()->getAllowEventFocus()){setCameraManipulator(new osgGA::TrackballManipulator());}setReleaseContextAtEndOfFrameHint(false);return ViewerBase::run();
}
这里实现和简单就是跳转了ViewerBase::run()
.
继续跟踪分析:
int ViewerBase::run()
{
......while(!done() && (run_frame_count_str==0 || getViewerFrameStamp()->getFrameNumber()<runTillFrameNumber)){.......frame();.......}return 0;
}
最后就执行到了ViewerBase::frame()
函数。
进入这个函数我们看下它主要干了啥。
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();
}
我们一个一个来分析:
第一步:初始化
if (_firstFrame){viewerInit();if (!isRealized()){realize();}_firstFrame = false;}
viewerInit():
初始化相机、场景等核心组件。
realize():
创建原生窗口并绑定 OpenGL 上下文(若未就绪)。
如果这是仿真系统启动后的第一帧,则执行viewerInit()
;此时如果还没有执行realize()
函数,则执行它。
第二步:推进场景状态
advance(simulationTime);
作用:调用场景中所有节点的 advance() 方法。
参数:simulationTime 通常表示逻辑时间(用于动画/物理模拟)。
第三步:事件处理
eventTraversal();
从窗口系统获取输入事件(键盘、鼠标等)。
通过 osgGA::EventQueue 分发事件。
触发事件处理器(osgGA::EventHandler)的回调。
第四步:场景更新
updateTraversal();
调用所有节点的 update() 回调。
更新场景图状态(位置变化、LOD切换等)。
执行 osg::NodeCallback 自定义更新逻辑。
第五步: 渲染遍历
renderingTraversals();
核心步骤:
裁剪(Cull):确定可见对象,生成渲染列表。
绘制(Draw):提交 OpenGL 命令到 GPU。
交换缓冲区:显示渲染结果(swapBuffers())。
嗯~,今天的学习需要消化消化,下课,明天见。_
参考文献
《最长的一帧》王锐(array)
Ps: 学习果然是一件很幸福的事情,充实每一天。_