使用osg时我们首先需要做的第一件事就是创建一个渲染窗口,当我们配置好一个osg的开发环境,一般会编写以下一段测试程序:
#include <osg/Node> #include <osgDB/ReadFile> #include <osgViewer/Viewer> int main() { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; //配置OSG_FILE_PATH环境变量指向glider.osg文件所在的目录 osg::ref_ptr<osg::Node> gliderNode = osgDB::readNodeFile("glider.osg"); viewer->setSceneData(gliderNode); viewer->run(); }
osg的窗口创建过程是在viewer->run() 中实现的,下面我们就对该过程做一个完整的剖析。
void ViewerBase::frame(double simulationTime) { if (_done) return; if (_firstFrame) { viewerInit(); if (!isRealized()) { realize(); } _firstFrame = false; } advance(simulationTime); eventTraversal(); updateTraversal(); renderingTraversals(); }
void viewerInit() { init(); }viewerInit直接调用了osgViewer::Viewer中的init方法,但是查看osgViewer::viewer的源码发现它的实现文件中并没有init函数,说明在父类中有实现,osgViewer::Viewer只是直接调用了父类的实现,查看代码发现确实如此,在osgViewer::View中实现了init方法,它的实现代码如下:
void View::init() { OSG_INFO<<"View::init()"<<std::endl; osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent(); initEvent->setEventType(osgGA::GUIEventAdapter::FRAME); if (_cameraManipulator.valid()) { _cameraManipulator->init(*initEvent, *this); } }
bool Viewer::isRealized() const { Contexts contexts; const_cast<Viewer*>(this)->getContexts(contexts); unsigned int numRealizedWindows = 0; // clear out all the previously assigned operations for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { if ((*citr)->isRealized()) ++numRealizedWindows; } return numRealizedWindows > 0; }
typedef std::vector<osg::GraphicsContext*> Contexts;
typedef std::set<osg::GraphicsContext*> ContextSet; ContextSet contextSet; contexts.clear(); if (_camera.valid() && _camera->getGraphicsContext() && (_camera->getGraphicsContext()->valid() || !onlyValid)) { contextSet.insert(_camera->getGraphicsContext()); contexts.push_back(_camera->getGraphicsContext()); } for(unsigned int i=0; i<getNumSlaves(); ++i) { Slave& slave = getSlave(i); osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0; if (sgc && (sgc->valid() || !onlyValid)) { if (contextSet.count(sgc)==0) { contextSet.insert(sgc); contexts.push_back(sgc); } } }代码还是比较清晰的,osg会搜集 Viewer视景器中相机(一个视景器Viewer类包含一个主相机和多个从相机(Slave))的所有渲染上下文,并将这些渲染上下文添加到数组中。
for(Contexts::iterator citr = contexts.begin(); citr != contexts.end(); ++citr) { if ((*citr)->isRealized()) ++numRealizedWindows; }
inline bool isRealized() const { return isRealizedImplementation(); }接着追溯下去可以看到 isRealziedImplementation的实现就有很多了,它在GraphicsContext类中是一个纯虚函数,实现需要追溯到平台相关的实现中,包括了前面所绘制的类的继承关系图中的 GraphicsWindowQt 、GraphicsWindowWin32、GraphicsWindowCocoa、GraphcisWindowCarbon、GraphicsWindowIOS、GraphicsWindowX11,分别对应Qt、Win32、MacOS X、IOS、以及Linux的实现,