第二日(二)osgViewer::Viewer::getContexts().

又到了分析一个函数的时候了,

目前的流程如下;
osgViewer::viewBase:: frame()

{

viewerInit();[

                          //创建帧事件,并将漫游器与事件和视口相关联

                            ->   osgViewer::Viewer::ViewerInit()

                           ->  osgViewer::View::Init();

                          ->(1)osgGA::EventQueue::createEvent();

                            (2)osgGA::MatrixManipulator::Init();

                            ->(2.1)各种漫游器::init()

                 ]

isRealized();[

                                    //获取图形上下文数组。再遍历上下文数组,只要有一个准备好就Ok

                                  ->   osgViewer::Viewer::isRealized();

                                 ->(1)osgViewer::Viewer::getContexts().

                                ->(2)osg::GraphicContext::isRealized()

                    ]

realize();

advance(simulationTime);

eventTraversal();

updateTraversal();

renderingTraversals();

}

 该分析osgViewer::Viewer::getContexts().了


void Viewer::getContexts(Contexts& contexts, bool onlyValid)
{
    typedef std::set<osg::GraphicsContext*> ContextSet;
    ContextSet contextSet;

    if (_camera.valid() && 
        _camera->getGraphicsContext() && 
        (_camera->getGraphicsContext()->valid() || !onlyValid))
    {
        contextSet.insert(_camera->getGraphicsContext());
    }
    
    for(unsigned int i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        if (slave._camera.valid() && 
            slave._camera->getGraphicsContext() && 
            (slave._camera->getGraphicsContext()->valid() || !onlyValid))
        {
            contextSet.insert(slave._camera->getGraphicsContext());
        }
    }

    contexts.clear();
    contexts.reserve(contextSet.size());

    for(ContextSet::iterator itr = contextSet.begin();
        itr != contextSet.end();
        ++itr)
    {
        contexts.push_back(const_cast<osg::GraphicsContext*>(*itr));
    }

    if (contexts.size()>=2)
    {
        std::sort(contexts.begin(), contexts.end(), LessGraphicsContext()); 
    }
}

首先用到了一个std::set,基于红黑树的平衡二叉树,主要是用来排序,默认从小到大排序,知道这个了,后面就好理解了。这个函数就是用来获得场景中的主摄像机和各个从摄像机的图形上下文,并放入数组中,进行从小到大的排序。

具体从上到下看,如何得到摄像机上下文的呢,主摄像机和从摄像机都用到了osg::Camera::getGraphicsContext(),毕竟都是摄像机,从这个角度看,没区别.

在osg::Camera类中,

     /** Get the GraphicsContext.*/
        GraphicsContext* getGraphicsContext() { return _graphicsContext.get(); }

成员变量
        ref_ptr<GraphicsContext>            _graphicsContext;

摄像机成员变量是在osg::View中的,隐藏得很深


        osg::ref_ptr<osg::Camera>       _camera;        
        typedef std::vector<Slave>      Slaves;
        Slaves                          _slaves;

这个Slave是个结构体,

成员函数就不写了,它的几个成员变量如下:


            osg::ref_ptr<osg::Camera>   _camera;
            osg::Matrixd                _projectionOffset;
            osg::Matrixd                _viewOffset;
            bool                        _useMastersSceneData;

说明从摄像机首先是个摄像机,有投影坐标系和摄像机坐标系的偏移矩阵,也考虑到是否数据和主摄像机一致。

得到从摄像机的个数,一目了然,不解释

unsigned int getNumSlaves() const { return _slaves.size(); }

遍历数组中的从摄像机
        Slave& getSlave(unsigned int pos) { return _slaves[pos]; }

排序用到了


struct LessGraphicsContext
{
    bool operator () (const osg::GraphicsContext* lhs, const osg::GraphicsContext* rhs) const
    {
        int screenLeft = lhs->getTraits()? lhs->getTraits()->screenNum : 0;
        int screenRight = rhs->getTraits()? rhs->getTraits()->screenNum : 0;
        if (screenLeft < screenRight) return true;
        if (screenLeft > screenRight) return false;

        screenLeft = lhs->getTraits()? lhs->getTraits()->x : 0;
        screenRight = rhs->getTraits()? rhs->getTraits()->x : 0;
        if (screenLeft < screenRight) return true;
        if (screenLeft > screenRight) return false;

        screenLeft = lhs->getTraits()? lhs->getTraits()->y : 0;
        screenRight = rhs->getTraits()? rhs->getTraits()->y : 0;
        if (screenLeft < screenRight) return true;
        if (screenLeft > screenRight) return false;
        
        return lhs < rhs;
    } 
};
其中的函数是

osg::GraphicContext::getTraits(),


        /** Get the traits of the GraphicsContext.*/
        inline const Traits* getTraits() const { return _traits.get(); }

        ref_ptr<Traits>         _traits;        

Traits是什么呢?只列出成员变量

struct Traits : public osg::Referenced, public ScreenIdentifier

{

......

     // graphics context original and size
            int x;
            int y;
            int width;
            int height;
            
            // window decoration and behaviour
            std::string windowName;
            bool        windowDecoration;
            bool        supportsResize;
            
            // buffer depths, 0 equals off.
            unsigned int red;
            unsigned int blue;
            unsigned int green;
            unsigned int alpha;
            unsigned int depth;
            unsigned int stencil;

            // multi sample parameters
            unsigned int sampleBuffers;
            unsigned int samples;

            // buffer configuration
            bool pbuffer;
            bool quadBufferStereo;
            bool doubleBuffer;

            // render to texture
            GLenum          target;
            GLenum          format;
            unsigned int    level;
            unsigned int    face;
            unsigned int    mipMapGeneration;
            
            // V-sync
            bool            vsync;
            
            // use multithreaded OpenGL-engine (OS X only)
            bool            useMultiThreadedOpenGLEngine;
            
            // enable cursor
            bool            useCursor;
            
            // shared context
            GraphicsContext* sharedContext;
            
            osg::ref_ptr<osg::Referenced> inheritedWindowData;
            
            // ask the GraphicsWindow implementation to set the pixel format of an inherited window
            bool setInheritedWindowPixelFormat;
            
            // X11 hint whether to override the window managers window size/position redirection
            bool overrideRedirect;

};

Traits是真真正正的屏幕属性

继承自屏幕结构体

struct OSG_EXPORT ScreenIdentifier

{

.....         

std::string  hostName;
            int displayNum;
            int screenNum;

};

有显示数和屏幕数,主机名扽成员变量。

从这里,再回过头来看哪个排序,从小到大排序,先排屏幕数量,再排xy坐标。so easy。

上边说了,osg::GraphicContext类不只是屏幕的属性,还有管理,所以,我预感一切只是铺垫,只是准备好原材料,精彩的还在后面。具体是啥,我也没看,只能期待下文了。

总结下,目前的流程是

osgViewer::viewBase:: frame()

{

viewerInit();[

                          //创建帧事件,并将漫游器与事件和视口相关联

                            ->   osgViewer::Viewer::ViewerInit()

                           ->  osgViewer::View::Init();

                          ->(1)osgGA::EventQueue::createEvent();

                            (2)osgGA::MatrixManipulator::Init();

                            ->(2.1)各种漫游器::init()

                 ]

isRealized();[

                                    //获取图形上下文数组。再遍历上下文数组,只要有一个准备好就Ok

                                  ->   osgViewer::Viewer::isRealized();

                                 ->(1)osgViewer::Viewer::getContexts().

                                 ->(1.1)osg::camera::getGraphicsContext()

                                 ->(1.2)osg::View::getNumSlaves()

                                ->(1.3)osg::View::getSlave()

                               ->(1.4)LessGraphicsContext()->osg::GraphicContext::getTraits()

                                ->(2)osg::GraphicContext::isRealized()

                    ]

realize();

advance(simulationTime);

eventTraversal();

updateTraversal();

renderingTraversals();

}

发布了673 篇原创文章 · 获赞 18 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/directx3d_beginner/article/details/105110561