osg状态信息统计的实现原理_hankern的博客-程序员宝宝_osg::statshandler

技术标签: osg  

osgViewer::Viewer首先添加osgView::StatsHandler负责统计信息的处理

osgView::StatsHandle中的handle函数具体负责s键的响应和切换。

osgViewer/StatsHandler.cpp
bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
    switch(ea.getEventType())
    {
        case(osgGA::GUIEventAdapter::KEYDOWN):
        {
            if (ea.getKey()==_keyEventTogglesOnScreenStats)
            {
                    switch(_statsType)
                    {
                        case(NO_STATS):
                        case(FRAME_RATE):
                        case(VIEWER_STATS):
                        case(CAMERA_SCENE_STATS):
                        case(VIEWER_SCENE_STATS):
                    }
            }
        }
    }
}

统计信息的切换显示是通过osg::Switch实现的,每一个统计信息为其中的一个osg::Group。动态信息的绘制是通过绘制回调函数来实现的(在osgViewer::StatsHandler::setUpSecne中实现):


frameRateValue->setDrawCallback(new AveragedValueTextDrawCallback(viewer->getViewerStats(),"Frame rate",-1, true, 1.0));

frameMarkers->setDrawCallback(new FrameMarkerDrawCallback(this, _startBlocks, viewer->getViewerStats(), 0, _numBlocks + 1));

camStatsText->setDrawCallback(new CameraSceneStatsTextDrawCallback(*citr, cameraCounter));

text->setDrawCallback(new ViewSceneStatsTextDrawCallback(*it, viewCounter));

统计信息的获取是在如下位置:

1、获取帧速率的信息

osgViewer/Vierwer.cpp
void Viewer::advance(double 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());
    }
}

2、获取视图的统计信息

2.1、获取事件遍历的统计信息

osgViewer/Vierwer.cpp
void Viewer::eventTraversal()
{
    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);
    }
}

2.2、获取更新遍历的统计信息

osgViewer/Vierwer.cpp
void Viewer::updateTraversal()
{
    if (getViewerStats() && getViewerStats()->collectStats("update"))
    {
        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());

        // update current frames stats
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
    }
}

2.3、获取裁剪遍历的统计信息

osgViewer/Renderer.cpp
void Renderer::cull()
{
        if (stats && stats->collectStats("rendering"))
        {
            DEBUG_MESSAGE<<"Collecting rendering stats"<<std::endl;

            stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
            stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
            stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
        }
}

2.4、获取绘制的统计信息

osgViewer/Renderer.cpp
void Renderer::draw()
{
        if (stats && stats->collectStats("rendering"))
        {
            stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
            stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
            stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick));
        }
}

2.5、获取GPU绘制的统计信息

osgViewer/Renderer.cpp
void ARBQuerySupport::checkQuery(osg::Stats* stats, osg::State* state,
                                 osg::Timer_t /*startTick*/)
{
    for(QueryFrameList::iterator itr = _queryFrameList.begin();
        itr != _queryFrameList.end();
        )
    {
        GLint available = 0;
        // If the end query is available, the begin query must be too.
        _extensions->glGetQueryObjectiv(itr->queries.second,
                                        GL_QUERY_RESULT_AVAILABLE, &available);
        if (available)
        {
            QueryPair queries = itr->queries;
            GLuint64 beginTimestamp = 0;
            GLuint64 endTimestamp = 0;
            _extensions->glGetQueryObjectui64v(queries.first, GL_QUERY_RESULT,
                                               &beginTimestamp);
            _extensions->glGetQueryObjectui64v(queries.second, GL_QUERY_RESULT,
                                               &endTimestamp);
            GLuint64 gpuTimestamp = state->getGpuTimestamp();
            // Have any of the timestamps wrapped around?
            int tbits = state->getTimestampBits();
            if (tbits < 64)
            {
                // If the high bits on any of the timestamp bits are
                // different then the counters may have wrapped.
                const int hiShift = (tbits - 1);
                const GLuint64 one = 1;
                const GLuint64 hiMask = one << hiShift;
                const GLuint64 sum = (beginTimestamp >> hiShift)
                    + (endTimestamp >> hiShift) + (gpuTimestamp >> hiShift);
                if (sum == 1 || sum == 2) {
                    const GLuint64 wrapAdd = one << tbits;
                    // Counter wrapped between begin and end?
                    if (beginTimestamp > endTimestamp)
                    {
                        endTimestamp += wrapAdd;
                    }
                    else if (gpuTimestamp < beginTimestamp
                             && beginTimestamp - gpuTimestamp > (hiMask >> 1))
                    {
                        gpuTimestamp += wrapAdd;
                    }
                    else if (endTimestamp < gpuTimestamp
                             && gpuTimestamp - endTimestamp > (hiMask >> 1))
                    {
                        beginTimestamp += wrapAdd;
                        endTimestamp += wrapAdd;
                    }
                }
            }
            GLuint64 timeElapsed = endTimestamp - beginTimestamp;
            double timeElapsedSeconds = double(timeElapsed)*1e-9;
            double gpuTick = state->getGpuTime();
                     double beginTime = 0.0;
            double endTime = 0.0;
            if (beginTimestamp > gpuTimestamp)
                beginTime = gpuTick
                    + double(beginTimestamp - gpuTimestamp) * 1e-9;
            else
                beginTime = gpuTick
                    - double(gpuTimestamp - beginTimestamp) * 1e-9;
            if (endTimestamp > gpuTimestamp)
                endTime = gpuTick
                    + double(endTimestamp - gpuTimestamp) * 1e-9;
            else
                endTime = gpuTick
                    - double(gpuTimestamp - endTimestamp) * 1e-9;
            stats->setAttribute(itr->frameNumber, "GPU draw begin time",
                                beginTime);
            stats->setAttribute(itr->frameNumber, "GPU draw end time", endTime);
            stats->setAttribute(itr->frameNumber, "GPU draw time taken",
                                timeElapsedSeconds);
            itr = _queryFrameList.erase(itr);
            _availableQueryObjects.push_back(queries);
        }
        else
        {
            ++itr;
        }
    }
}

2.6、获取渲染遍历的统计信息

osgViewer/Viewer.cpp
void ViewerBase::renderingTraversals()
{
        getViewerStats()->setAttribute(frameNumber, "Rendering traversals begin time ", beginRenderingTraversals);
        getViewerStats()->setAttribute(frameNumber, "Rendering traversals end time ", endRenderingTraversals);
        getViewerStats()->setAttribute(frameNumber, "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals);
}

3、获取视图中相机的统计信息

osgViewer/Renderer.cpp
void Renderer::cull()
{
        if (stats && stats->collectStats("scene"))
        {
            collectSceneViewStats(frameNumber, sceneView, stats);
        }
}

static void collectSceneViewStats(unsigned int frameNumber, osgUtil::SceneView* sceneView, osg::Stats* stats)
{
    osgUtil::Statistics sceneStats;
    sceneView->getStats(sceneStats);

    stats->setAttribute(frameNumber, "Visible vertex count", static_cast<double>(sceneStats._vertexCount));
    stats->setAttribute(frameNumber, "Visible number of drawables", static_cast<double>(sceneStats.numDrawables));
    stats->setAttribute(frameNumber, "Visible number of fast drawables", static_cast<double>(sceneStats.numFastDrawables));
    stats->setAttribute(frameNumber, "Visible number of lights", static_cast<double>(sceneStats.nlights));
    stats->setAttribute(frameNumber, "Visible number of render bins", static_cast<double>(sceneStats.nbins));
    stats->setAttribute(frameNumber, "Visible depth", static_cast<double>(sceneStats.depth));
    stats->setAttribute(frameNumber, "Number of StateGraphs", static_cast<double>(sceneStats.numStateGraphs));
    stats->setAttribute(frameNumber, "Visible number of impostors", static_cast<double>(sceneStats.nimpostor));
    stats->setAttribute(frameNumber, "Number of ordered leaves", static_cast<double>(sceneStats.numOrderedLeaves));

    unsigned int totalNumPrimitiveSets = 0;
    const osgUtil::Statistics::PrimitiveValueMap& pvm = sceneStats.getPrimitiveValueMap();
    for(osgUtil::Statistics::PrimitiveValueMap::const_iterator pvm_itr = pvm.begin();
        pvm_itr != pvm.end();
        ++pvm_itr)
    {
        totalNumPrimitiveSets += pvm_itr->second.first;
    }
    stats->setAttribute(frameNumber, "Visible number of PrimitiveSets", static_cast<double>(totalNumPrimitiveSets));

    osgUtil::Statistics::PrimitiveCountMap& pcm = sceneStats.getPrimitiveCountMap();
    stats->setAttribute(frameNumber, "Visible number of GL_POINTS", static_cast<double>(pcm[GL_POINTS]));
    stats->setAttribute(frameNumber, "Visible number of GL_LINES", static_cast<double>(pcm[GL_LINES]));
    stats->setAttribute(frameNumber, "Visible number of GL_LINE_STRIP", static_cast<double>(pcm[GL_LINE_STRIP]));
    stats->setAttribute(frameNumber, "Visible number of GL_LINE_LOOP", static_cast<double>(pcm[GL_LINE_LOOP]));
    stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLES", static_cast<double>(pcm[GL_TRIANGLES]));
    stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLE_STRIP", static_cast<double>(pcm[GL_TRIANGLE_STRIP]));
    stats->setAttribute(frameNumber, "Visible number of GL_TRIANGLE_FAN", static_cast<double>(pcm[GL_TRIANGLE_FAN]));
    stats->setAttribute(frameNumber, "Visible number of GL_QUADS", static_cast<double>(pcm[GL_QUADS]));
    stats->setAttribute(frameNumber, "Visible number of GL_QUAD_STRIP", static_cast<double>(pcm[GL_QUAD_STRIP]));
    stats->setAttribute(frameNumber, "Visible number of GL_POLYGON", static_cast<double>(pcm[GL_POLYGON]));
}

4、获取视图中场景的统计信息

osgViewer/ViewerBase.cpp
void ViewerBase::renderingTraversals()
{    
    if (getViewerStats() && getViewerStats()->collectStats("scene"))
    {

        Views views;
        getViews(views);
        for(Views::iterator vitr = views.begin();
            vitr != views.end();
            ++vitr)
        {
            View* view = *vitr;
            osg::Stats* stats = view->getStats();
            osg::Node* sceneRoot = view->getSceneData();
            if (sceneRoot && stats)
            {
                osgUtil::StatsVisitor statsVisitor;
                sceneRoot->accept(statsVisitor);
                statsVisitor.totalUpStats();

                unsigned int unique_primitives = 0;
                osgUtil::Statistics::PrimitiveCountMap::iterator pcmitr;
                for(pcmitr = statsVisitor._uniqueStats.GetPrimitivesBegin();
                    pcmitr != statsVisitor._uniqueStats.GetPrimitivesEnd();
                    ++pcmitr)
                {
                    unique_primitives += pcmitr->second;
                }

                stats->setAttribute(frameNumber, "Number of unique StateSet", static_cast<double>(statsVisitor._statesetSet.size()));
                stats->setAttribute(frameNumber, "Number of unique Group", static_cast<double>(statsVisitor._groupSet.size()));
                stats->setAttribute(frameNumber, "Number of unique Transform", static_cast<double>(statsVisitor._transformSet.size()));
                stats->setAttribute(frameNumber, "Number of unique LOD", static_cast<double>(statsVisitor._lodSet.size()));
                stats->setAttribute(frameNumber, "Number of unique Switch", static_cast<double>(statsVisitor._switchSet.size()));
                stats->setAttribute(frameNumber, "Number of unique Geode", static_cast<double>(statsVisitor._geodeSet.size()));
                stats->setAttribute(frameNumber, "Number of unique Drawable", static_cast<double>(statsVisitor._drawableSet.size()));
                stats->setAttribute(frameNumber, "Number of unique Geometry", static_cast<double>(statsVisitor._geometrySet.size()));
                stats->setAttribute(frameNumber, "Number of unique Vertices", static_cast<double>(statsVisitor._uniqueStats._vertexCount));
                stats->setAttribute(frameNumber, "Number of unique Primitives", static_cast<double>(unique_primitives));

                unsigned int instanced_primitives = 0;
                for(pcmitr = statsVisitor._instancedStats.GetPrimitivesBegin();
                    pcmitr != statsVisitor._instancedStats.GetPrimitivesEnd();
                    ++pcmitr)
                {
                    instanced_primitives += pcmitr->second;
                }

                stats->setAttribute(frameNumber, "Number of instanced Stateset", static_cast<double>(statsVisitor._numInstancedStateSet));
                stats->setAttribute(frameNumber, "Number of instanced Group", static_cast<double>(statsVisitor._numInstancedGroup));
                stats->setAttribute(frameNumber, "Number of instanced Transform", static_cast<double>(statsVisitor._numInstancedTransform));
                stats->setAttribute(frameNumber, "Number of instanced LOD", static_cast<double>(statsVisitor._numInstancedLOD));
                stats->setAttribute(frameNumber, "Number of instanced Switch", static_cast<double>(statsVisitor._numInstancedSwitch));
                stats->setAttribute(frameNumber, "Number of instanced Geode", static_cast<double>(statsVisitor._numInstancedGeode));
                stats->setAttribute(frameNumber, "Number of instanced Drawable", static_cast<double>(statsVisitor._numInstancedDrawable));
                stats->setAttribute(frameNumber, "Number of instanced Geometry", static_cast<double>(statsVisitor._numInstancedGeometry));
                stats->setAttribute(frameNumber, "Number of instanced Vertices", static_cast<double>(statsVisitor._instancedStats._vertexCount));
                stats->setAttribute(frameNumber, "Number of instanced Primitives", static_cast<double>(instanced_primitives));
           }
        }
    }
}

 

 

 

 

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hankern/article/details/86635675

智能推荐

黑马程序员--面对对象3_捌年的博客-程序员宝宝

------- android培训、java培训、期待与您交流! ----------一、继承定义:  在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可

基础的重要性(程序员之路)_张冰庭的博客-程序员宝宝

学习编程有几年了,感觉走了不少弯路,而不少的学弟学妹又在重蹈我当初的覆辙,不免有些痛心。最近在网上也看了许多前辈们的经验建议,再结合自己的学习经历在这里谈谈基础的重要性,希望帮助大家少走些弯路。    什么是基础呢?就是要把我们大学所学的离散数学,算法与数据结构,操作系统,计算机体系结构,编译原理等课程学好,对计算机的体系,CPU本身,操作系统内核,系统平台,面向对象编程,程序的性能等要有

0003C语言--数据类型及运算符_北冥有鱼zsp的博客-程序员宝宝

本文主要讲解的知识点是进制数,数据类型及其转换,运算符。1.进制数及其转换进制是一种计数机制,它可以使用有限的数字符号代表所有的数值。对于任何一种进制——X 进制, 就表示某一位置上的数运算时逢 X 进一位。对于计算机系统来说,常见的进制数有二进制,八进制,十进制及十六进制。(1)二进制对于绝大多数计算机系统来说,数据都是通过二进制的形式存在的。二进制是一种“逢二进一”的机制, 它...

中兴U880 完美版2.3.7第三弹炫目登场,你还在为刷机而烦恼?来吧!它值得你拥有!!!!_打杂人的博客-程序员宝宝

本帖最后由 销魂的猫 于 2012-1-30 14:10 编辑http://wenku.baidu.com/view/d0e4d9350b4c2e3f572763fb.html下个版本需等本帖达到1000个评分、5000个回复后再发布!免得有那么多的伸手党!   完美版第四弹热点功能抢先报:1、装逼专用4.0.1版本,2、提升软件运行速度3、系统设置背景改为 图

使用Flink Watermark sideOutputLateData的坑_ooobenooo的博客-程序员宝宝

Flink Watermark是用于处理数据乱序问题,网上已经有很多优秀的文章介绍,这里就不重复了。参考:https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/event_timestamps_watermarks.html今天要说的使用Watermark过程中自己挖的坑,使用sideOutputLateData()过程中没有正常输出的问题,在此记录一下:先来看一下源码解析:/** * Send late ar

Protocol Buffers for Object-C_凯哥的世界你不懂的博客-程序员宝宝

一、先点击链接去了解一下,或者 google一下http://code.google.com/intl/zh-CN/apis/protocolbuffers/二、protobuf的使用1、编译Protocol Buffers  A.下载Protocol Buffers将下载解压后的文件存放至Applications目录下,进到ProtocolBuffers-2.2.

随便推点

(原创)咱们公司遇到一个想开发和抖音一样的app的客户?_qq18723817197的博客-程序员宝宝

如果客户说想开发一款和抖音一模一样的app,结果会?——链环科技

我和你们不同--和谐就是和而不同--就是多样性的统一_LLKJDLLKJD的博客-程序员宝宝

     软件开发我从来没有研究过,我是寻求一个帮助偶然来到这个空间,希望哪位朋友能够帮助我编写一个这样简单的软件---将标志某商品的品名、产地生产商、经销商、规格型号、产品编号、特殊字符的信息编写成为另外一组可以自由设定的信息,当输入其中某一段信息后,就可以自动导出这些自由设定的信息,就好象户口管理,输入名字,就可以导出身份证号码一样;用途是:好查找库房放置的商品位置。    我的手机号码是

每个程序员都必须遵守的编程原则_马兆娟的博客-程序员宝宝

恰巧看到这篇文章,学过面向对象语言的人会很容易理解里面涉及的编程原则,这些原则恰恰是面向对象语言中常说的。感觉这篇文章写得不错,共享出来,共同学习……原文地址:http://www.aqee.net/principles-of-good-programming/      ============================分割线,请看下文=====================

数据处理平台架构中的SMACK组合:Spark、Mesos、Akka、Cassandra以及Kafka_似水流年的博客-程序员宝宝

摘要: 在今天的文章中,我们将着重探讨如何利用SMACK(即Spark、Mesos、Akka、Cassandra以及Kafka)堆栈构建可扩展数据处理平台。虽然这套堆栈仅由数个简单部分组成,但其能够实现大量不同系统设计。除了纯粹的批量或者流处理机制之外,我们亦可借此实现复杂的Lambda以及Kappa架构。在今天的文章中,我们将着重探讨如何利用SMACK(即Spark、Mesos、Akka、Cassandra以及Kafka)堆栈构建可扩展数据处理平台。虽然这套堆栈仅由数个简单部分组成,但其能够实现大量不

HashSet和HashMap的区别比较_ccxuxuxu的博客-程序员宝宝

HashSet 实现的Set接口,集合中不允许出现重复的值(如果重复会覆盖):package com.wlf.base;public class Person{ public Person(String name, int age) { this.name = name; this.age = age; }

推荐文章

热门文章

相关标签