root/OpenSceneGraph/trunk/src/osgViewer/StatsHandler.cpp @ 9552

Revision 9552, 62.4 kB (checked in by robert, 6 years ago)

Ported onscreen camera stats across to using thread safe stats collection

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[6028]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
[8970]14#include <sstream>
15#include <iomanip>
[7170]16#include <stdio.h>
17
[8970]18#include <osg/io_utils>
19
[8997]20#include <osg/MatrixTransform>
21
[6862]22#include <osgViewer/ViewerEventHandlers>
[7178]23#include <osgViewer/Renderer>
[6028]24
[6062]25#include <osg/PolygonMode>
[6862]26#include <osg/Geometry>
[8970]27#include <osgUtil/Statistics>
[6062]28
[6028]29namespace osgViewer
30{
31
[8970]32
[6028]33StatsHandler::StatsHandler():
[6029]34    _keyEventTogglesOnScreenStats('s'),
35    _keyEventPrintsOutStats('S'),
[6028]36    _statsType(NO_STATS),
[6511]37    _initialized(false),
[7506]38    _threadingModel(ViewerBase::SingleThreaded),
[6028]39    _frameRateChildNum(0),
40    _viewerChildNum(0),
[8970]41    _cameraSceneChildNum(0),
42    _viewerSceneChildNum(0),
[6028]43    _numBlocks(8),
44    _blockMultiplier(10000.0)
45{
[6511]46    _camera = new osg::Camera;
[7178]47    _camera->setRenderer(new Renderer(_camera.get()));
[7181]48    _camera->setProjectionResizePolicy(osg::Camera::FIXED);
[6028]49}
50
51bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
52{
[7505]53   
[7507]54    osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&aa);
55    if (!myview) return false;
[7505]56   
[7507]57    osgViewer::ViewerBase* viewer = myview->getViewerBase();
[7505]58    if (viewer && _threadingModelText.valid() && viewer->getThreadingModel()!=_threadingModel)
[6122]59    {
60        _threadingModel = viewer->getThreadingModel();
61        updateThreadingModelText();
62    }
[7505]63   
64   
[7064]65    if (ea.getHandled()) return false;
66
[6028]67    switch(ea.getEventType())
68    {
69        case(osgGA::GUIEventAdapter::KEYDOWN):
70        {
[6029]71            if (ea.getKey()==_keyEventTogglesOnScreenStats)
[6028]72            {
[7507]73                if (viewer->getStats())
[6028]74                {
[6511]75                    if (!_initialized)
[6028]76                    {
[7507]77                        setUpHUDCamera(viewer);
78                        setUpScene(viewer);
[6028]79                    }
80
81                    ++_statsType;
82
83                    if (_statsType==LAST) _statsType = NO_STATS;
[6072]84                   
[7506]85                    osgViewer::ViewerBase::Cameras cameras;
86                    viewer->getCameras(cameras);
[6028]87
88                    switch(_statsType)
89                    {
90                        case(NO_STATS):
91                        {
[7507]92                            viewer->getStats()->collectStats("frame_rate",false);
93                            viewer->getStats()->collectStats("event",false);
94                            viewer->getStats()->collectStats("update",false);
[6072]95
[7506]96                            for(osgViewer::ViewerBase::Cameras::iterator itr = cameras.begin();
[6072]97                                itr != cameras.end();
98                                ++itr)
99                            {
[9552]100                                osg::Stats* stats = (*itr)->getStats();
101                                if (stats)
102                                {
103                                    stats->collectStats("rendering",false);
104                                    stats->collectStats("gpu",false);
105                                    stats->collectStats("scene",false);
106                                }
[6072]107                            }
108                           
[9552]109                            viewer->getStats()->collectStats("scene",false);
110
[6028]111                            _camera->setNodeMask(0x0);
112                            _switch->setAllChildrenOff();
113                            break;
114                        }
115                        case(FRAME_RATE):
116                        {
[7507]117                            viewer->getStats()->collectStats("frame_rate",true);
[6072]118                           
[6028]119                            _camera->setNodeMask(0xffffffff);
120                            _switch->setValue(_frameRateChildNum, true);
121                            break;
122                        }
123                        case(VIEWER_STATS):
124                        {
[7507]125                            ViewerBase::Scenes scenes;
126                            viewer->getScenes(scenes);
127                            for(ViewerBase::Scenes::iterator itr = scenes.begin();
128                                itr != scenes.end();
129                                ++itr)
[7286]130                            {
[7507]131                                Scene* scene = *itr;
132                                osgDB::DatabasePager* dp = scene->getDatabasePager();
133                                if (dp && dp->isRunning())
134                                {
135                                    dp->resetStats();
136                                }
[7286]137                            }
138                       
[7507]139                            viewer->getStats()->collectStats("event",true);
140                            viewer->getStats()->collectStats("update",true);
[6072]141
[7506]142                            for(osgViewer::ViewerBase::Cameras::iterator itr = cameras.begin();
[6072]143                                itr != cameras.end();
144                                ++itr)
145                            {
146                                if ((*itr)->getStats()) (*itr)->getStats()->collectStats("rendering",true);
147                                if ((*itr)->getStats()) (*itr)->getStats()->collectStats("gpu",true);
148                            }
149                           
[6028]150                            _camera->setNodeMask(0xffffffff);
151                            _switch->setValue(_viewerChildNum, true);
152                            break;
153                        }
[8970]154                        case(CAMERA_SCENE_STATS):
[6028]155                        {
156                            _camera->setNodeMask(0xffffffff);
[8970]157                            _switch->setValue(_cameraSceneChildNum, true);
[9552]158
159                            for(osgViewer::ViewerBase::Cameras::iterator itr = cameras.begin();
160                                itr != cameras.end();
161                                ++itr)
162                            {
163                                osg::Stats* stats = (*itr)->getStats();
164                                if (stats)
165                                {
166                                    stats->collectStats("scene",true);
167                                }
168                            }
169
[6028]170                            break;
171                        }
[8970]172                        case(VIEWER_SCENE_STATS):
173                        {
174                            _camera->setNodeMask(0xffffffff);
175                            _switch->setValue(_viewerSceneChildNum, true);
[9552]176
177                            viewer->getStats()->collectStats("scene",true);
178
[8970]179                            break;
180                        }
[6028]181                        default:
182                            break;
183                    }
184
185
186                }
187                return true;
188            }
[6029]189            if (ea.getKey()==_keyEventPrintsOutStats)
[6028]190            {
[7507]191                if (viewer->getStats())
[6028]192                {
193                    osg::notify(osg::NOTICE)<<std::endl<<"Stats report:"<<std::endl;
194                    typedef std::vector<osg::Stats*> StatsList;
195                    StatsList statsList;
[7507]196                    statsList.push_back(viewer->getStats());
[6028]197
[7506]198                    osgViewer::ViewerBase::Contexts contexts;
199                    viewer->getContexts(contexts);
200                    for(osgViewer::ViewerBase::Contexts::iterator gcitr = contexts.begin();
[6028]201                        gcitr != contexts.end();
202                        ++gcitr)
203                    {
204                        osg::GraphicsContext::Cameras& cameras = (*gcitr)->getCameras();
205                        for(osg::GraphicsContext::Cameras::iterator itr = cameras.begin();
206                            itr != cameras.end();
207                            ++itr)
208                        {
209                            if ((*itr)->getStats())
210                            {
211                                statsList.push_back((*itr)->getStats());
212                            }
213                        }
214                    }
215
[7507]216                    for(int i = viewer->getStats()->getEarliestFrameNumber(); i<= viewer->getStats()->getLatestFrameNumber()-1; ++i)
[6028]217                    {
218                        for(StatsList::iterator itr = statsList.begin();
219                            itr != statsList.end();
220                            ++itr)
221                        {
222                            if (itr==statsList.begin()) (*itr)->report(osg::notify(osg::NOTICE), i);
223                            else (*itr)->report(osg::notify(osg::NOTICE), i, "    ");
224                        }
225                        osg::notify(osg::NOTICE)<<std::endl;
226                    }
227
228                }
229                return true;
230            }
231        }
232        default: break;
233    }
234
235    return false;
236
237}
238
[6122]239void StatsHandler::updateThreadingModelText()
240{
241    switch(_threadingModel)
242    {
243        case(osgViewer::Viewer::SingleThreaded): _threadingModelText->setText("ThreadingModel: SingleThreaded"); break;
244        case(osgViewer::Viewer::CullDrawThreadPerContext): _threadingModelText->setText("ThreadingModel: CullDrawThreadPerContext"); break;
245        case(osgViewer::Viewer::DrawThreadPerContext): _threadingModelText->setText("ThreadingModel: DrawThreadPerContext"); break;
246        case(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext): _threadingModelText->setText("ThreadingModel: CullThreadPerCameraDrawThreadPerContext"); break;
247        case(osgViewer::Viewer::AutomaticSelection): _threadingModelText->setText("ThreadingModel: AutomaticSelection"); break;
[7505]248        default:
249            _threadingModelText->setText("ThreadingModel: unknown"); break;
[6122]250    }
251}
252
[6511]253void StatsHandler::reset()
254{
255    _initialized = false;
256    _camera->setGraphicsContext(0);
[9066]257    _camera->removeChildren( 0, _camera->getNumChildren() );
[6511]258}
259
[7507]260void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer)
[6028]261{
[6511]262    osgViewer::GraphicsWindow* window = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
[7505]263   
[7507]264    if (!window)
[6511]265    {   
266        osgViewer::Viewer::Windows windows;
267        viewer->getWindows(windows);
[6028]268
[6511]269        if (windows.empty()) return;
[6028]270
[6511]271        window = windows.front();
272    }
[7507]273
[9385]274    _camera->setGraphicsContext(window);
[6511]275
[9385]276    _camera->setViewport(0, 0, window->getTraits()->width, window->getTraits()->height);
[7306]277    _camera->setRenderOrder(osg::Camera::POST_RENDER, 10);
[6028]278
279    _camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
280    _camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
281    _camera->setViewMatrix(osg::Matrix::identity());
282
283    // only clear the depth buffer
284    _camera->setClearMask(0);
285
[7178]286    _camera->setRenderer(new Renderer(_camera.get()));
[6511]287   
288    _initialized = true;
[6028]289}
290
[8970]291// Drawcallback to draw averaged attribute
292struct AveragedValueTextDrawCallback : public virtual osg::Drawable::DrawCallback
[6028]293{
[8970]294    AveragedValueTextDrawCallback(osg::Stats* stats, const std::string& name, int frameDelta, bool averageInInverseSpace, double multiplier):
[6028]295        _stats(stats),
296        _attributeName(name),
297        _frameDelta(frameDelta),
[6075]298        _averageInInverseSpace(averageInInverseSpace),
[6072]299        _multiplier(multiplier),
300        _tickLastUpdated(0)
301    {
302    }
[6028]303
304    /** do customized draw code.*/
305    virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
306    {
307        osgText::Text* text = (osgText::Text*)drawable;
308
[6072]309        osg::Timer_t tick = osg::Timer::instance()->tick();
310        double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick);
[6028]311
[6072]312        if (delta>50) // update every 50ms
[6028]313        {
[6072]314            _tickLastUpdated = tick;
315            double value;
[6075]316            if (_stats->getAveragedAttribute( _attributeName, value, _averageInInverseSpace))
[6072]317            {
318                sprintf(_tmpText,"%4.2f",value * _multiplier);
319                text->setText(_tmpText);
320            }
321            else
322            {
323                text->setText("");
324            }
[6028]325        }
326        text->drawImplementation(renderInfo);
327    }
328
[8970]329    osg::ref_ptr<osg::Stats>    _stats;
[6197]330    std::string                 _attributeName;
331    int                         _frameDelta;
332    bool                        _averageInInverseSpace;
333    double                      _multiplier;
334    mutable char                _tmpText[128];
335    mutable osg::Timer_t        _tickLastUpdated;
[6028]336};
337
[8970]338struct CameraSceneStatsTextDrawCallback : public virtual osg::Drawable::DrawCallback
339{
340    CameraSceneStatsTextDrawCallback(osg::Camera* camera, int cameraNumber):
341        _camera(camera),
342        _tickLastUpdated(0),
343        _cameraNumber(cameraNumber)
344    {
345    }
346
347    /** do customized draw code.*/
348    virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
349    {
[9552]350        if (!_camera) return;
351
[8970]352        osgText::Text* text = (osgText::Text*)drawable;
353
354        osg::Timer_t tick = osg::Timer::instance()->tick();
355        double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick);
356
357        if (delta > 100) // update every 100ms
358        {
359            _tickLastUpdated = tick;
360            std::ostringstream viewStr;
361            viewStr.clear();
362
[9552]363            osg::Stats* stats = _camera->getStats();
[8970]364            osgViewer::Renderer* renderer = dynamic_cast<osgViewer::Renderer*>(_camera->getRenderer());
365           
[9552]366            if (stats && renderer)
[8970]367            {
368                viewStr.setf(std::ios::left,std::ios::adjustfield);
369                viewStr.width(14);
370
371                viewStr << std::setw(1) << _cameraNumber  << ": ";
[9552]372
[8970]373                // Camera name
374                if (_camera->getName().empty())
375                    viewStr << std::endl;
376                else
377                    viewStr << _camera->getName() << std::endl;
[9552]378                   
379                int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
380                if (!(renderer->getGraphicsThreadDoesCull()))
[8970]381                {
[9552]382                    --frameNumber;
[8970]383                }
384               
[9552]385                #define STATS_ATTRIBUTE(str) \
386                    if (stats->getAttribute(frameNumber, str, value)) \
387                        viewStr << std::setw(7) << value << std::endl; \
388                    else \
389                        viewStr << std::setw(7) << "no value" << std::endl; \
[8970]390
[9552]391                double value = 0.0;
392
393                STATS_ATTRIBUTE("Visible vertex count")
394                STATS_ATTRIBUTE("Visible number of drawables")
395                STATS_ATTRIBUTE("Visible number of lights")
396                STATS_ATTRIBUTE("Visible number of render bins")
397                STATS_ATTRIBUTE("Visible depth")
398                STATS_ATTRIBUTE("Visible number of materials")
399                STATS_ATTRIBUTE("Visible number of impostors")
400
401                STATS_ATTRIBUTE("Visible number of GL_POINTS")
402                STATS_ATTRIBUTE("Visible number of GL_LINES")
403                STATS_ATTRIBUTE("Visible number of GL_LINE_STRIP")
404                STATS_ATTRIBUTE("Visible number of GL_LINE_LOOP")
405                STATS_ATTRIBUTE("Visible number of GL_TRIANGLES")
406                STATS_ATTRIBUTE("Visible number of GL_TRIANGLE_STRIP")
407                STATS_ATTRIBUTE("Visible number of GL_TRIANGLE_FAN")
408                STATS_ATTRIBUTE("Visible number of GL_QUADS")
409                STATS_ATTRIBUTE("Visible number of GL_QUAD_STRIP")
410                STATS_ATTRIBUTE("Visible number of GL_POLYGON")
411
412
[8970]413                text->setText(viewStr.str());
414            }
415        }
416        text->drawImplementation(renderInfo);
417    }
418
[9552]419    osg::observer_ptr<osg::Camera>  _camera;
420    mutable osg::Timer_t            _tickLastUpdated;
421    int                             _cameraNumber;
[8970]422};
423
424
425struct ViewSceneStatsTextDrawCallback : public virtual osg::Drawable::DrawCallback
426{
427    ViewSceneStatsTextDrawCallback(osgViewer::View* view, int viewNumber):
428        _view(view),
429        _tickLastUpdated(0),
430        _viewNumber(viewNumber)
431    {
432    }
433
434    /** do customized draw code.*/
435    virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
436    {
[9552]437        if (!_view) return;
438
[8970]439        osgText::Text* text = (osgText::Text*)drawable;
440
441        osg::Timer_t tick = osg::Timer::instance()->tick();
442        double delta = osg::Timer::instance()->delta_m(_tickLastUpdated, tick);
443
444        if (delta > 200) // update every 100ms
445        {
446            _tickLastUpdated = tick;
[9552]447            osg::ref_ptr<osg::Node> sceneRoot = _view.valid() ? _view->getScene()->getSceneData() : 0;
[8970]448
[9194]449            if (sceneRoot.valid())
[8970]450            {
451                osgUtil::StatsVisitor statsVisitor;
452                sceneRoot->accept(statsVisitor);
453
454                std::ostringstream viewStr;
455                viewStr.clear();
456                viewStr.setf(std::ios::left,std::ios::adjustfield);
457                viewStr.width(20);
458               
459                viewStr << std::setw(1) << _viewNumber  << ": ";
460                // View name
461                if (_view->getName().empty())
462                    viewStr << std::endl;
463                else
464                    viewStr << _view->getName() << std::endl;
465
466                viewStr << std::endl;
467
468                unsigned int unique_primitives = 0;
469                osgUtil::Statistics::PrimitiveCountMap::iterator pcmitr;
470                for(pcmitr = statsVisitor._uniqueStats.GetPrimitivesBegin();
471                    pcmitr != statsVisitor._uniqueStats.GetPrimitivesEnd();
472                    ++pcmitr)
473                {
474                    unique_primitives += pcmitr->second;
475                }
476
477                unsigned int instanced_primitives = 0;
478                for(pcmitr = statsVisitor._instancedStats.GetPrimitivesBegin();
479                    pcmitr != statsVisitor._instancedStats.GetPrimitivesEnd();
480                    ++pcmitr)
481                {
482                    instanced_primitives += pcmitr->second;
483                }
484
485                viewStr << std::setw(10) << statsVisitor._statesetSet.size()       << std::setw(10) << statsVisitor._numInstancedStateSet << std::endl;
486                viewStr << std::setw(10) << statsVisitor._groupSet.size()          << std::setw(10) << statsVisitor._numInstancedGroup << std::endl;
487                viewStr << std::setw(10) << statsVisitor._transformSet.size()      << std::setw(10) << statsVisitor._numInstancedTransform << std::endl;
488                viewStr << std::setw(10) << statsVisitor._lodSet.size()            << std::setw(10) << statsVisitor._numInstancedLOD << std::endl;
489                viewStr << std::setw(10) << statsVisitor._switchSet.size()         << std::setw(10) << statsVisitor._numInstancedSwitch << std::endl;
490                viewStr << std::setw(10) << statsVisitor._geodeSet.size()          << std::setw(10) << statsVisitor._numInstancedGeode << std::endl;
491                viewStr << std::setw(10) << statsVisitor._drawableSet.size()       << std::setw(10) << statsVisitor._numInstancedDrawable << std::endl;
492                viewStr << std::setw(10) << statsVisitor._geometrySet.size()       << std::setw(10) << statsVisitor._numInstancedGeometry << std::endl;
493                viewStr << std::setw(10) << statsVisitor._uniqueStats._vertexCount << std::setw(10) << statsVisitor._instancedStats._vertexCount << std::endl;
494                viewStr << std::setw(10) << unique_primitives                        << std::setw(10) << instanced_primitives << std::endl;
495
496                text->setText(viewStr.str());
497            }
498            else 
499            {
500                osg::notify(osg::WARN)<<std::endl<<"No valid view to collect scene stats from"<<std::endl;
501               
502                text->setText("");
503            }
504        }
505        text->drawImplementation(renderInfo);
506    }
507
[9552]508    osg::observer_ptr<osgViewer::View>  _view;
509    mutable osg::Timer_t                _tickLastUpdated;
510    int                                 _viewNumber;
[8970]511};
512
[6028]513struct BlockDrawCallback : public virtual osg::Drawable::DrawCallback
514{
515    BlockDrawCallback(StatsHandler* statsHandler, float xPos, osg::Stats* viewerStats, osg::Stats* stats, const std::string& beginName, const std::string& endName, int frameDelta, int numFrames):
516        _statsHandler(statsHandler),
517        _xPos(xPos),
518        _viewerStats(viewerStats),
519        _stats(stats),
520        _beginName(beginName),
521        _endName(endName),
522        _frameDelta(frameDelta),
523        _numFrames(numFrames) {}
524
525    /** do customized draw code.*/
526    virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
527    {
528        osg::Geometry* geom = (osg::Geometry*)drawable;
529        osg::Vec3Array* vertices = (osg::Vec3Array*)geom->getVertexArray();
530
531        int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();           
532
533        int startFrame = frameNumber + _frameDelta - _numFrames + 1;
534        int endFrame = frameNumber + _frameDelta;
535        double referenceTime;
536        if (!_viewerStats->getAttribute( startFrame, "Reference time", referenceTime))
537        {
538            return;
539        }
540
541        unsigned int vi = 0;
542        double beginValue, endValue;
543        for(int i = startFrame; i <= endFrame; ++i)
544        {           
545            if (_stats->getAttribute( i, _beginName, beginValue) &&
546                _stats->getAttribute( i, _endName, endValue) )
547            {
548                (*vertices)[vi++].x() = _xPos + (beginValue - referenceTime) * _statsHandler->getBlockMultiplier();
549                (*vertices)[vi++].x() = _xPos + (beginValue - referenceTime) * _statsHandler->getBlockMultiplier();
550                (*vertices)[vi++].x() = _xPos + (endValue - referenceTime) * _statsHandler->getBlockMultiplier();
551                (*vertices)[vi++].x() = _xPos + (endValue - referenceTime) * _statsHandler->getBlockMultiplier();
552            }
553        }
554
555        drawable->drawImplementation(renderInfo);
556    }
557
[6197]558    StatsHandler*               _statsHandler;
559    float                       _xPos;
560    osg::ref_ptr<osg::Stats>    _viewerStats;
561    osg::ref_ptr<osg::Stats>    _stats;
562    std::string                 _beginName;
563    std::string                 _endName;
564    int                         _frameDelta;
565    int                         _numFrames;
[6028]566};
567
[8970]568osg::Geometry* StatsHandler::createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color)
569{
570    osg::StateSet *ss = new osg::StateSet;
571 
572    osg::Geometry* geometry = new osg::Geometry;
573 
574    geometry->setUseDisplayList(false);
575    geometry->setStateSet(ss);
576
577    osg::Vec3Array* vertices = new osg::Vec3Array;
578    geometry->setVertexArray(vertices);
579 
580    vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0));
581    vertices->push_back(osg::Vec3(pos.x(), pos.y()-height,0));
582    vertices->push_back(osg::Vec3(pos.x()+width, pos.y()-height,0));
583    vertices->push_back(osg::Vec3(pos.x()+width, pos.y(),0));
584 
585    osg::Vec4Array* colors = new osg::Vec4Array;
586    colors->push_back(color);
587    geometry->setColorArray(colors);
588    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
589 
590    osg::DrawElementsUInt *base =  new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS,0);
591    base->push_back(0);
592    base->push_back(1);
593    base->push_back(2);
594    base->push_back(3);
595
596    geometry->addPrimitiveSet(base);
597
598    return geometry;
599}
600
601
[8997]602struct StatsGraph : public osg::MatrixTransform
603{
604    StatsGraph(osg::Vec3 pos, float width, float height)
605        : _pos(pos), _width(width), _height(height),
606          _statsGraphGeode(new osg::Geode)
607    {
608        _pos -= osg::Vec3(0, height, 0.1);
609        this->setMatrix(osg::Matrix::translate(_pos));
610        this->addChild(_statsGraphGeode.get());
611    }
612
613    void addStatGraph(osg::Stats* viewerStats, osg::Stats* stats, const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "")
614    {
615        _statsGraphGeode->addDrawable(new Graph(_width, _height, viewerStats, stats, color, max, nameBegin, nameEnd));
616    }
617
618    osg::Vec3           _pos;
619    float               _width;
620    float               _height;
621
622    osg::ref_ptr<osg::Geode> _statsGraphGeode;
623
624protected:
625    struct Graph : public osg::Geometry
626    {
627        Graph(float width, float height, osg::Stats* viewerStats, osg::Stats* stats,
628              const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "")
629        {
630            this->setUseDisplayList(false);
631
632            this->setVertexArray(new osg::Vec3Array);
633
634            osg::Vec4Array* colors = new osg::Vec4Array;
635            colors->push_back(color);
636            this->setColorArray(colors);
637            this->setColorBinding(osg::Geometry::BIND_OVERALL);
638
639            this->setDrawCallback(new GraphUpdateCallback(width, height, viewerStats, stats, max, nameBegin, nameEnd));
640        }
641    };
642
643    struct GraphUpdateCallback : public osg::Drawable::DrawCallback
644    {
645        GraphUpdateCallback(float width, float height, osg::Stats* viewerStats, osg::Stats* stats,
646                            float max, const std::string& nameBegin, const std::string& nameEnd = "")
647            : _width((unsigned int)width), _height((unsigned int)height), _curX(0),
648              _viewerStats(viewerStats), _stats(stats), _max(max), _nameBegin(nameBegin), _nameEnd(nameEnd)
649        {
650        }
651
652        virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
653        {
654            osg::Geometry* geometry = const_cast<osg::Geometry*>(drawable->asGeometry());
655            if (!geometry) return;
656            osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
657            if (!vertices) return;
658
659            int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
660
661            // Get stats
662            double value;
663            if (_nameEnd.empty())
664            {
665                if (!_stats->getAveragedAttribute( _nameBegin, value, true ))
666                {
667                    value = 0.0;
668                }
669            }
670            else
671            {
672                double beginValue, endValue;
673                if (_stats->getAttribute( frameNumber, _nameBegin, beginValue) &&
674                    _stats->getAttribute( frameNumber, _nameEnd, endValue) )
675                {
676                    value = endValue - beginValue;
677                }
678                else
679                {
680                    value = 0.0;
681                }
682            }
683
684            // Add new vertex for this frame.
685            value = osg::clampTo(value, 0.0, double(_max));
686            vertices->push_back(osg::Vec3(float(_curX), float(_height) / _max * value, 0));
687
688            // One vertex per pixel in X.
689            if (vertices->size() > _width)
690            {
691                unsigned int excedent = vertices->size() - _width;
692                vertices->erase(vertices->begin(), vertices->begin() + excedent);
693
694                // Make the graph scroll when there is enough data.
695                // Note: We check the frame number so that even if we have
696                // many graphs, the transform is translated only once per
697                // frame.
698                static const float increment = -1.0;
699                if (GraphUpdateCallback::_frameNumber != frameNumber)
700                {
701                    // We know the exact layout of this part of the scene
702                    // graph, so this is OK...
703                    osg::MatrixTransform* transform =
704                        geometry->getParent(0)->getParent(0)->asTransform()->asMatrixTransform();
705                    if (transform)
706                    {
707                        transform->setMatrix(transform->getMatrix() * osg::Matrix::translate(osg::Vec3(increment, 0, 0)));
708                    }
709                }
710            }
711            else
712            {
713                // Create primitive set if none exists.
714                if (geometry->getNumPrimitiveSets() == 0)
715                    geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, 0));
716
717                // Update primitive set.
718                osg::DrawArrays* drawArrays = dynamic_cast<osg::DrawArrays*>(geometry->getPrimitiveSet(0));
719                if (!drawArrays) return;
720                drawArrays->setFirst(0);
721                drawArrays->setCount(vertices->size());
722            }
723
724            _curX++;
725            GraphUpdateCallback::_frameNumber = frameNumber;
726
727            geometry->dirtyBound();
728
729            drawable->drawImplementation(renderInfo);
730        }
731
732        const unsigned int      _width;
733        const unsigned int      _height;
734        mutable unsigned int    _curX;
735        osg::Stats*             _viewerStats;
736        osg::Stats*             _stats;
737        const float             _max;
738        const std::string       _nameBegin;
739        const std::string       _nameEnd;
740        static int              _frameNumber;
741    };
742};
743
744int StatsGraph::GraphUpdateCallback::_frameNumber = 0;
745
746
[6028]747osg::Geometry* StatsHandler::createGeometry(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks)
748{
749    osg::Geometry* geometry = new osg::Geometry;
750
751    geometry->setUseDisplayList(false);
752
753    osg::Vec3Array* vertices = new osg::Vec3Array;
754    geometry->setVertexArray(vertices);
755    vertices->reserve(numBlocks*4);
756
757    for(unsigned int i=0; i<numBlocks; ++i)
758    {
759        vertices->push_back(pos+osg::Vec3(i*20, height, 0.0));
760        vertices->push_back(pos+osg::Vec3(i*20, 0.0, 0.0));
761        vertices->push_back(pos+osg::Vec3(i*20+10.0, 0.0, 0.0));
762        vertices->push_back(pos+osg::Vec3(i*20+10.0, height, 0.0));
763    }
764
765    osg::Vec4Array* colours = new osg::Vec4Array;
766    colours->push_back(colour);
767    geometry->setColorArray(colours);
768    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
769
770    geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, numBlocks*4));
771
772    return geometry;       
773}
774
775
776struct FrameMarkerDrawCallback : public virtual osg::Drawable::DrawCallback
777{
778    FrameMarkerDrawCallback(StatsHandler* statsHandler, float xPos, osg::Stats* viewerStats, int frameDelta, int numFrames):
779        _statsHandler(statsHandler),
780        _xPos(xPos),
781        _viewerStats(viewerStats),
782        _frameDelta(frameDelta),
783        _numFrames(numFrames) {}
784
785    /** do customized draw code.*/
786    virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
787    {
788        osg::Geometry* geom = (osg::Geometry*)drawable;
789        osg::Vec3Array* vertices = (osg::Vec3Array*)geom->getVertexArray();
790
791        int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();           
792
793        int startFrame = frameNumber + _frameDelta - _numFrames + 1;
794        int endFrame = frameNumber + _frameDelta;
795        double referenceTime;
796        if (!_viewerStats->getAttribute( startFrame, "Reference time", referenceTime))
797        {
798            return;
799        }
800
801        unsigned int vi = 0;
802        double currentReferenceTime;
803        for(int i = startFrame; i <= endFrame; ++i)
804        {           
805            if (_viewerStats->getAttribute( i, "Reference time", currentReferenceTime))
806            {
807                (*vertices)[vi++].x() = _xPos + (currentReferenceTime - referenceTime) * _statsHandler->getBlockMultiplier();
808                (*vertices)[vi++].x() = _xPos + (currentReferenceTime - referenceTime) * _statsHandler->getBlockMultiplier();
809            }
810        }
811
812        drawable->drawImplementation(renderInfo);
813    }
814
[6197]815    StatsHandler*               _statsHandler;
816    float                       _xPos;
817    osg::ref_ptr<osg::Stats>    _viewerStats;
818    std::string                 _endName;
819    int                         _frameDelta;
820    int                         _numFrames;
[6028]821};
822
[7286]823struct PagerCallback : public virtual osg::NodeCallback
824{
[6028]825
[8970]826    PagerCallback(    osgDB::DatabasePager* dp,
827                    osgText::Text* minValue,
828                    osgText::Text* maxValue,
829                    osgText::Text* averageValue,
830                    osgText::Text* filerequestlist,
831                    osgText::Text* compilelist,
832                    double multiplier):
[7286]833        _dp(dp),
834        _minValue(minValue),
835        _maxValue(maxValue),
836        _averageValue(averageValue),
[8970]837        _filerequestlist(filerequestlist),
[9385]838        _compilelist(compilelist),
839        _multiplier(multiplier)
[7286]840    {
841    }
842
843    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
844    {
845        if (_dp.valid())
846        {           
847            double value = _dp->getAverageTimeToMergeTiles();
848            if (value>= 0.0 && value <= 1000)
849            {
850                sprintf(_tmpText,"%4.0f",value * _multiplier);
851                _averageValue->setText(_tmpText);
852            }
853            else
854            {
855                _averageValue->setText("");
856            }
857           
858            value = _dp->getMinimumTimeToMergeTile();
859            if (value>= 0.0 && value <= 1000)
860            {
861                sprintf(_tmpText,"%4.0f",value * _multiplier);
862                _minValue->setText(_tmpText);
863            }
864            else
865            {
866                _minValue->setText("");
867            }
868
869            value = _dp->getMaximumTimeToMergeTile();
870            if (value>= 0.0 && value <= 1000)
871            {
872                sprintf(_tmpText,"%4.0f",value * _multiplier);
873                _maxValue->setText(_tmpText);
874            }
875            else
876            {
877                _maxValue->setText("");
878            }
[8970]879
880            sprintf(_tmpText,"%4d", _dp->getFileRequestListSize());
881            _filerequestlist->setText(_tmpText);
882
883            sprintf(_tmpText,"%4d", _dp->getDataToCompileListSize());
884            _compilelist->setText(_tmpText);
[7286]885        }
886
887        traverse(node,nv);
888    }
889
890    osg::observer_ptr<osgDB::DatabasePager> _dp;
891   
892    osg::ref_ptr<osgText::Text> _minValue;
893    osg::ref_ptr<osgText::Text> _maxValue;
894    osg::ref_ptr<osgText::Text> _averageValue;
[8970]895    osg::ref_ptr<osgText::Text> _filerequestlist;
896    osg::ref_ptr<osgText::Text> _compilelist;
[9385]897    double              _multiplier;
[7286]898    char                _tmpText[128];
899    osg::Timer_t        _tickLastUpdated;
900};
901
902
[6028]903osg::Geometry* StatsHandler::createFrameMarkers(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numBlocks)
904{
905    osg::Geometry* geometry = new osg::Geometry;
906
907    geometry->setUseDisplayList(false);
908
909    osg::Vec3Array* vertices = new osg::Vec3Array;
910    geometry->setVertexArray(vertices);
911    vertices->reserve(numBlocks*2);
912
913    for(unsigned int i=0; i<numBlocks; ++i)
914    {
915        vertices->push_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.01, height, 0.0));
916        vertices->push_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.01, 0.0, 0.0));
917    }
918
919    osg::Vec4Array* colours = new osg::Vec4Array;
920    colours->push_back(colour);
921    geometry->setColorArray(colours);
922    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
923
924    geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, numBlocks*2));
925
926    return geometry;       
927}
928
929osg::Geometry* StatsHandler::createTick(const osg::Vec3& pos, float height, const osg::Vec4& colour, unsigned int numTicks)
930{
931    osg::Geometry* geometry = new osg::Geometry;
932
933    geometry->setUseDisplayList(false);
934
935    osg::Vec3Array* vertices = new osg::Vec3Array;
936    geometry->setVertexArray(vertices);
937    vertices->reserve(numTicks*2);
938
939    for(unsigned int i=0; i<numTicks; ++i)
940    {
941        float tickHeight = (i%10) ? height : height * 2.0;
942        vertices->push_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.001, tickHeight , 0.0));
943        vertices->push_back(pos+osg::Vec3(double(i)*_blockMultiplier*0.001, 0.0, 0.0));
944    }
945
946    osg::Vec4Array* colours = new osg::Vec4Array;
947    colours->push_back(colour);
948    geometry->setColorArray(colours);
949    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
950
951    geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, numTicks*2));
952
953    return geometry;       
954}
955
[7507]956void StatsHandler::setUpScene(osgViewer::ViewerBase* viewer)
[6028]957{
958    _switch = new osg::Switch;
959
960    _camera->addChild(_switch.get());
961
962    osg::StateSet* stateset = _switch->getOrCreateStateSet();
963    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
[6032]964    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
[6028]965    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
[6062]966    stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED);
[6028]967
968    std::string font("fonts/arial.ttf");
969
970
[7648]971    // collect all the relevant cameras
[7507]972    ViewerBase::Cameras validCameras;
973    viewer->getCameras(validCameras);
974
975    ViewerBase::Cameras cameras;
976    for(ViewerBase::Cameras::iterator itr = validCameras.begin();
977        itr != validCameras.end();
978        ++itr)
[6028]979    {
[7507]980        if ((*itr)->getStats())
[6028]981        {
[7507]982            cameras.push_back(*itr);
[6028]983        }
984    }
985
[7648]986    // check for query time support
[6028]987    unsigned int numCamrasWithTimerQuerySupport = 0;
[7507]988    for(ViewerBase::Cameras::iterator citr = cameras.begin();
[6028]989        citr != cameras.end();
990        ++citr)
991    {
[7178]992        if ((*citr)->getGraphicsContext())
[6028]993        {
[7178]994            unsigned int contextID = (*citr)->getGraphicsContext()->getState()->getContextID();
995            const osg::Drawable::Extensions* extensions = osg::Drawable::getExtensions(contextID, false);
996            if (extensions && extensions->isTimerQuerySupported())
997            {
998                ++numCamrasWithTimerQuerySupport;
999            }
[6028]1000        }
1001    }
1002
[7648]1003    bool acquireGPUStats = numCamrasWithTimerQuerySupport==cameras.size();
[6028]1004
1005    float leftPos = 10.0f;
[6032]1006    float startBlocks = 150.0f;
[6028]1007    float characterSize = 20.0f;
1008
1009    osg::Vec3 pos(leftPos,1000.0f,0.0f);
1010
1011    osg::Vec4 colorFR(1.0f,1.0f,1.0f,1.0f);
[8997]1012    osg::Vec4 colorFRAlpha(1.0f,1.0f,1.0f,0.5f);
[6028]1013    osg::Vec4 colorUpdate( 0.0f,1.0f,0.0f,1.0f);
[6032]1014    osg::Vec4 colorUpdateAlpha( 0.0f,1.0f,0.0f,0.5f);
[9006]1015    osg::Vec4 colorEvent(0.0f, 1.0f, 0.5f, 1.0f);
[8997]1016    osg::Vec4 colorEventAlpha(0.0f, 1.0f, 0.5f, 0.5f);
[9006]1017    osg::Vec4 colorCull( 0.0f,1.0f,1.0f,1.0f);
[8997]1018    osg::Vec4 colorCullAlpha( 0.0f,1.0f,1.0f,0.5f);
[9006]1019    osg::Vec4 colorDraw( 1.0f,1.0f,0.0f,1.0f);
[8997]1020    osg::Vec4 colorDrawAlpha( 1.0f,1.0f,0.0f,0.5f);
[9006]1021    osg::Vec4 colorGPU( 1.0f,0.5f,0.0f,1.0f);
[8997]1022    osg::Vec4 colorGPUAlpha( 1.0f,0.5f,0.0f,0.5f);
[6028]1023
[7286]1024    osg::Vec4 colorDP( 1.0f,1.0f,0.5f,1.0f);
[6028]1025
[7286]1026
[6028]1027    // frame rate stats
1028    {
1029        osg::Geode* geode = new osg::Geode();
1030        _frameRateChildNum = _switch->getNumChildren();
1031        _switch->addChild(geode, false);
1032
1033        osg::ref_ptr<osgText::Text> frameRateLabel = new osgText::Text;
1034        geode->addDrawable( frameRateLabel.get() );
1035
1036        frameRateLabel->setColor(colorFR);
1037        frameRateLabel->setFont(font);
1038        frameRateLabel->setCharacterSize(characterSize);
1039        frameRateLabel->setPosition(pos);
1040        frameRateLabel->setText("Frame Rate: ");
1041
1042        pos.x() = frameRateLabel->getBound().xMax();
1043
1044        osg::ref_ptr<osgText::Text> frameRateValue = new osgText::Text;
1045        geode->addDrawable( frameRateValue.get() );
1046
1047        frameRateValue->setColor(colorFR);
1048        frameRateValue->setFont(font);
1049        frameRateValue->setCharacterSize(characterSize);
1050        frameRateValue->setPosition(pos);
1051        frameRateValue->setText("0.0");
1052
[8970]1053        frameRateValue->setDrawCallback(new AveragedValueTextDrawCallback(viewer->getStats(),"Frame rate",-1, true, 1.0));
[6028]1054
1055        pos.y() -= characterSize*1.5f;
[8970]1056 
[6028]1057    }
1058
[8970]1059    osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3);
1060    osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0);
1061    osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0);
1062    float backgroundMargin = 5;
1063    float backgroundSpacing = 3;
[6028]1064
[8970]1065
[6028]1066    // viewer stats
1067    {
1068        osg::Group* group = new osg::Group;
1069        _viewerChildNum = _switch->getNumChildren();
1070        _switch->addChild(group, false);
1071
1072        osg::Geode* geode = new osg::Geode();
1073        group->addChild(geode);
1074
[6122]1075       
1076        {
1077            pos.x() = leftPos;
1078
1079            _threadingModelText = new osgText::Text;
1080            geode->addDrawable( _threadingModelText.get() );
1081
1082            _threadingModelText->setColor(colorFR);
1083            _threadingModelText->setFont(font);
1084            _threadingModelText->setCharacterSize(characterSize);
1085            _threadingModelText->setPosition(pos);
1086
1087            updateThreadingModelText();
1088
1089            pos.y() -= characterSize*1.5f;
1090        }
1091       
[6032]1092        float topOfViewerStats = pos.y() + characterSize;
[6028]1093
[8970]1094        geode->addDrawable(createBackgroundRectangle(    pos + osg::Vec3(-backgroundMargin, characterSize + backgroundMargin, 0),
[8997]1095                                                        _camera->getViewport()->width() - 2 * backgroundMargin,
[8970]1096                                                        (3 + 4.5 * cameras.size()) * characterSize + 2 * backgroundMargin,
[8997]1097                                                      backgroundColor) );
[8970]1098
[6028]1099        {
1100            pos.x() = leftPos;
1101
1102            osg::ref_ptr<osgText::Text> eventLabel = new osgText::Text;
1103            geode->addDrawable( eventLabel.get() );
1104
1105            eventLabel->setColor(colorUpdate);
1106            eventLabel->setFont(font);
1107            eventLabel->setCharacterSize(characterSize);
1108            eventLabel->setPosition(pos);
1109            eventLabel->setText("Event: ");
1110
1111            pos.x() = eventLabel->getBound().xMax();
1112
1113            osg::ref_ptr<osgText::Text> eventValue = new osgText::Text;
1114            geode->addDrawable( eventValue.get() );
1115
1116            eventValue->setColor(colorUpdate);
1117            eventValue->setFont(font);
1118            eventValue->setCharacterSize(characterSize);
1119            eventValue->setPosition(pos);
1120            eventValue->setText("0.0");
1121
[8970]1122            eventValue->setDrawCallback(new AveragedValueTextDrawCallback(viewer->getStats(),"Event traversal time taken",-1, false, 1000.0));
[6028]1123
1124            pos.x() = startBlocks;
[6032]1125            osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorUpdateAlpha, _numBlocks);
[7507]1126            geometry->setDrawCallback(new BlockDrawCallback(this, startBlocks, viewer->getStats(), viewer->getStats(), "Event traversal begin time", "Event traversal end time", -1, _numBlocks));
[6028]1127            geode->addDrawable(geometry);
1128
1129            pos.y() -= characterSize*1.5f;
1130        }
1131
1132        {
1133            pos.x() = leftPos;
1134
1135            osg::ref_ptr<osgText::Text> updateLabel = new osgText::Text;
1136            geode->addDrawable( updateLabel.get() );
1137
1138            updateLabel->setColor(colorUpdate);
1139            updateLabel->setFont(font);
1140            updateLabel->setCharacterSize(characterSize);
1141            updateLabel->setPosition(pos);
1142            updateLabel->setText("Update: ");
1143
1144            pos.x() = updateLabel->getBound().xMax();
1145
1146            osg::ref_ptr<osgText::Text> updateValue = new osgText::Text;
1147            geode->addDrawable( updateValue.get() );
1148
1149            updateValue->setColor(colorUpdate);
1150            updateValue->setFont(font);
1151            updateValue->setCharacterSize(characterSize);
1152            updateValue->setPosition(pos);
1153            updateValue->setText("0.0");
1154
[8970]1155            updateValue->setDrawCallback(new AveragedValueTextDrawCallback(viewer->getStats(),"Update traversal time taken",-1, false, 1000.0));
[6028]1156
1157            pos.x() = startBlocks;
[6032]1158            osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorUpdateAlpha, _numBlocks);
[7507]1159            geometry->setDrawCallback(new BlockDrawCallback(this, startBlocks, viewer->getStats(), viewer->getStats(), "Update traversal begin time", "Update traversal end time", -1, _numBlocks));
[6028]1160            geode->addDrawable(geometry);
1161
1162            pos.y() -= characterSize*1.5f;
1163        }
1164
1165        pos.x() = leftPos;
1166
1167        // add camera stats
[7507]1168        for(ViewerBase::Cameras::iterator citr = cameras.begin();
[6028]1169            citr != cameras.end();
1170            ++citr)
1171        {
[8970]1172            group->addChild(createCameraTimeStats(font, pos, startBlocks, acquireGPUStats, characterSize, viewer->getStats(), *citr));
[6028]1173        }
1174
1175        // add frame ticks
1176        {
1177            osg::Geode* geode = new osg::Geode;
1178            group->addChild(geode);
1179
1180            osg::Vec4 colourTicks(1.0f,1.0f,1.0f, 0.5f);
1181
1182            pos.x() = startBlocks;
[6032]1183            pos.y() += characterSize;
[6028]1184            float height = topOfViewerStats - pos.y();
1185
1186            osg::Geometry* ticks = createTick(pos, 5.0f, colourTicks, 100);
1187            geode->addDrawable(ticks);
1188
1189            osg::Geometry* frameMarkers = createFrameMarkers(pos, height, colourTicks, _numBlocks + 1);
[7507]1190            frameMarkers->setDrawCallback(new FrameMarkerDrawCallback(this, startBlocks, viewer->getStats(), 0, _numBlocks + 1));
[6028]1191            geode->addDrawable(frameMarkers);
[8997]1192
1193            pos.x() = leftPos;
[6028]1194        }
1195
[8997]1196        // Stats line graph
1197        {
1198            pos.y() -= (backgroundSpacing + 2 * backgroundMargin);
1199            float width = _camera->getViewport()->width() - 4 * backgroundMargin;
1200            float height = 5 * characterSize;
1201
1202            // Create a stats graph and add any stats we want to track with it.
1203            StatsGraph* statsGraph = new StatsGraph(pos, width, height);
1204            group->addChild(statsGraph);
1205
[9006]1206            statsGraph->addStatGraph(viewer->getStats(), viewer->getStats(), colorFR, 100, "Frame rate");
1207            statsGraph->addStatGraph(viewer->getStats(), viewer->getStats(), colorEvent, 0.016, "Event traversal time taken");
1208            statsGraph->addStatGraph(viewer->getStats(), viewer->getStats(), colorUpdate, 0.016, "Update traversal time taken");
[8997]1209           
1210            for(ViewerBase::Cameras::iterator citr = cameras.begin();
1211                citr != cameras.end();
1212                ++citr)
1213            {
[9006]1214                statsGraph->addStatGraph(viewer->getStats(), (*citr)->getStats(), colorCull, 0.016, "Cull traversal time taken");
1215                statsGraph->addStatGraph(viewer->getStats(), (*citr)->getStats(), colorDraw, 0.016, "Draw traversal time taken");
1216                statsGraph->addStatGraph(viewer->getStats(), (*citr)->getStats(), colorGPU, 0.016, "GPU draw time taken");
[8997]1217            }
1218
1219            geode->addDrawable(createBackgroundRectangle( pos + osg::Vec3(-backgroundMargin, backgroundMargin, 0),
1220                                                          width + 2 * backgroundMargin,
1221                                                          height + 2 * backgroundMargin,
1222                                                          backgroundColor) );
1223
1224            pos.x() = leftPos;
1225            pos.y() -= height + 2 * backgroundMargin;
1226        }
1227
[8970]1228        // Databasepager stats
[7507]1229        ViewerBase::Scenes scenes;
1230        viewer->getScenes(scenes);
1231        for(ViewerBase::Scenes::iterator itr = scenes.begin();
1232            itr != scenes.end();
1233            ++itr)
[7286]1234        {
[7507]1235            Scene* scene = *itr;
1236            osgDB::DatabasePager* dp = scene->getDatabasePager();
1237            if (dp && dp->isRunning())
1238            {
[8997]1239                pos.y() -= (characterSize + backgroundSpacing);
[7286]1240
[8970]1241                geode->addDrawable(createBackgroundRectangle(    pos + osg::Vec3(-backgroundMargin, characterSize + backgroundMargin, 0),
[8997]1242                                                                _camera->getViewport()->width() - 2 * backgroundMargin,
[8970]1243                                                                characterSize + 2 * backgroundMargin,
1244                                                                backgroundColor));
1245
[7507]1246                osg::ref_ptr<osgText::Text> averageLabel = new osgText::Text;
1247                geode->addDrawable( averageLabel.get() );
[7286]1248
[7507]1249                averageLabel->setColor(colorDP);
1250                averageLabel->setFont(font);
1251                averageLabel->setCharacterSize(characterSize);
1252                averageLabel->setPosition(pos);
1253                averageLabel->setText("DatabasePager time to merge new tiles - average: ");
[7286]1254
[7507]1255                pos.x() = averageLabel->getBound().xMax();
[7286]1256
[7507]1257                osg::ref_ptr<osgText::Text> averageValue = new osgText::Text;
1258                geode->addDrawable( averageValue.get() );
[7286]1259
[7507]1260                averageValue->setColor(colorDP);
1261                averageValue->setFont(font);
1262                averageValue->setCharacterSize(characterSize);
1263                averageValue->setPosition(pos);
1264                averageValue->setText("1000");
[7286]1265
[7507]1266                pos.x() = averageValue->getBound().xMax() + 2.0f*characterSize;
[7286]1267
1268
[7507]1269                osg::ref_ptr<osgText::Text> minLabel = new osgText::Text;
1270                geode->addDrawable( minLabel.get() );
[7286]1271
[7507]1272                minLabel->setColor(colorDP);
1273                minLabel->setFont(font);
1274                minLabel->setCharacterSize(characterSize);
1275                minLabel->setPosition(pos);
1276                minLabel->setText("min: ");
[7286]1277
[7507]1278                pos.x() = minLabel->getBound().xMax();
[7286]1279
[7507]1280                osg::ref_ptr<osgText::Text> minValue = new osgText::Text;
1281                geode->addDrawable( minValue.get() );
[7286]1282
[7507]1283                minValue->setColor(colorDP);
1284                minValue->setFont(font);
1285                minValue->setCharacterSize(characterSize);
1286                minValue->setPosition(pos);
1287                minValue->setText("1000");
[7286]1288
[7507]1289                pos.x() = minValue->getBound().xMax() + 2.0f*characterSize;
[7286]1290
[7507]1291                osg::ref_ptr<osgText::Text> maxLabel = new osgText::Text;
1292                geode->addDrawable( maxLabel.get() );
[7286]1293
[7507]1294                maxLabel->setColor(colorDP);
1295                maxLabel->setFont(font);
1296                maxLabel->setCharacterSize(characterSize);
1297                maxLabel->setPosition(pos);
1298                maxLabel->setText("max: ");
[7286]1299
[7507]1300                pos.x() = maxLabel->getBound().xMax();
[7286]1301
[7507]1302                osg::ref_ptr<osgText::Text> maxValue = new osgText::Text;
1303                geode->addDrawable( maxValue.get() );
[7286]1304
[7507]1305                maxValue->setColor(colorDP);
1306                maxValue->setFont(font);
1307                maxValue->setCharacterSize(characterSize);
1308                maxValue->setPosition(pos);
1309                maxValue->setText("1000");
[7286]1310
[8970]1311                pos.x() = maxValue->getBound().xMax();
1312
1313                osg::ref_ptr<osgText::Text> requestsLabel = new osgText::Text;
1314                geode->addDrawable( requestsLabel.get() );
1315
1316                requestsLabel->setColor(colorDP);
1317                requestsLabel->setFont(font);
1318                requestsLabel->setCharacterSize(characterSize);
1319                requestsLabel->setPosition(pos);
1320                requestsLabel->setText("requests: ");
1321
1322                pos.x() = requestsLabel->getBound().xMax();
1323
1324                osg::ref_ptr<osgText::Text> requestList = new osgText::Text;
1325                geode->addDrawable( requestList.get() );
1326
1327                requestList->setColor(colorDP);
1328                requestList->setFont(font);
1329                requestList->setCharacterSize(characterSize);
1330                requestList->setPosition(pos);
1331                requestList->setText("0");
1332
1333                pos.x() = requestList->getBound().xMax() + 2.0f*characterSize;;
1334
1335                osg::ref_ptr<osgText::Text> compileLabel = new osgText::Text;
1336                geode->addDrawable( compileLabel.get() );
1337
1338                compileLabel->setColor(colorDP);
1339                compileLabel->setFont(font);
1340                compileLabel->setCharacterSize(characterSize);
1341                compileLabel->setPosition(pos);
1342                compileLabel->setText("tocompile: ");
1343
1344                pos.x() = compileLabel->getBound().xMax();
1345               
1346                osg::ref_ptr<osgText::Text> compileList = new osgText::Text;
1347                geode->addDrawable( compileList.get() );
1348
1349                compileList->setColor(colorDP);
1350                compileList->setFont(font);
1351                compileList->setCharacterSize(characterSize);
1352                compileList->setPosition(pos);
1353                compileList->setText("0");
1354
[7507]1355                pos.x() = maxLabel->getBound().xMax();
[7286]1356
[8970]1357                geode->setCullCallback(new PagerCallback(dp, minValue.get(), maxValue.get(), averageValue.get(), requestList.get(), compileList.get(), 1000.0));
[7507]1358            }
[7286]1359
[7507]1360            pos.x() = leftPos;
1361        }
[6028]1362    }
[8970]1363
1364    // Camera scene stats
[6028]1365    {
[8970]1366        pos.y() -= (characterSize + backgroundSpacing + 2 * backgroundMargin);
[6028]1367
[8970]1368        osg::Group* group = new osg::Group;
1369        _cameraSceneChildNum = _switch->getNumChildren();
1370        _switch->addChild(group, false);
1371
[6028]1372        osg::Geode* geode = new osg::Geode();
[8970]1373        geode->setCullingActive(false);
1374        group->addChild(geode);
1375        geode->addDrawable(createBackgroundRectangle(    pos + osg::Vec3(-backgroundMargin, characterSize + backgroundMargin, 0),
1376                                                        7 * characterSize + 2 * backgroundMargin,
1377                                                        18 * characterSize + 2 * backgroundMargin,
1378                                                        backgroundColor));
[6028]1379
[8970]1380        // Camera scene & primitive stats static text
1381        osg::ref_ptr<osgText::Text> camStaticText = new osgText::Text;
1382        geode->addDrawable( camStaticText.get() ); 
1383        camStaticText->setColor(staticTextColor);
1384        camStaticText->setFont(font);
1385        camStaticText->setCharacterSize(characterSize);
1386        camStaticText->setPosition(pos);
1387
1388        std::ostringstream viewStr;
1389        viewStr.clear();
1390        viewStr.setf(std::ios::left,std::ios::adjustfield);
1391        viewStr.width(14);
1392        viewStr << "Camera" << std::endl;
1393        viewStr << "Vertices" << std::endl;
1394        viewStr << "Drawables" << std::endl;
1395        viewStr << "Lights" << std::endl;
1396        viewStr << "Bins" << std::endl;
1397        viewStr << "Depth" << std::endl;
1398        viewStr << "Matrices" << std::endl;
1399        viewStr << "Imposters" << std::endl;
1400        viewStr << "Points" << std::endl;
1401        viewStr << "Lines" << std::endl;
1402        viewStr << "Line strips" << std::endl;
1403        viewStr << "Line loops" << std::endl;
1404        viewStr << "Triangles" << std::endl;
[9552]1405        viewStr << "Tri. strips" << std::endl;
1406        viewStr << "Tri. fans" << std::endl;
[8970]1407        viewStr << "Quads" << std::endl;
1408        viewStr << "Quad strips" << std::endl;
1409        viewStr << "Polygons" << std::endl; 
1410        viewStr.setf(std::ios::right,std::ios::adjustfield);
1411        camStaticText->setText(viewStr.str());
1412
1413        // Move camera block to the right
1414        pos.x() += 7 * characterSize + 2 * backgroundMargin + backgroundSpacing;
1415
1416        // add camera scene stats
1417        int cameraCounter = 0;
1418        for(ViewerBase::Cameras::iterator citr = cameras.begin(); citr != cameras.end(); ++citr)
[6028]1419        {
[8970]1420            geode->addDrawable(createBackgroundRectangle(    pos + osg::Vec3(-backgroundMargin, characterSize + backgroundMargin, 0),
1421                                                            5 * characterSize + 2 * backgroundMargin,
1422                                                            18 * characterSize + 2 * backgroundMargin,
1423                                                            backgroundColor));
1424
1425            // Camera scene stats
1426            osg::ref_ptr<osgText::Text> camStatsText = new osgText::Text;
1427            geode->addDrawable( camStatsText.get() ); 
1428           
1429            camStatsText->setColor(dynamicTextColor);
1430            camStatsText->setFont(font);
1431            camStatsText->setCharacterSize(characterSize);
1432            camStatsText->setPosition(pos);
1433            camStatsText->setText("");
1434            camStatsText->setDrawCallback(new CameraSceneStatsTextDrawCallback(*citr, cameraCounter));
1435
1436            // Move camera block to the right
1437            pos.x() +=  5 * characterSize + 2 * backgroundMargin + backgroundSpacing;
1438            cameraCounter++;
1439        }
1440    }
1441
1442    // Viewer scene stats
1443    {
1444        osg::Group* group = new osg::Group;
1445        _viewerSceneChildNum = _switch->getNumChildren();
1446        _switch->addChild(group, false);
1447
1448        osg::Geode* geode = new osg::Geode();
1449        geode->setCullingActive(false);
1450        group->addChild(geode);
1451
1452        geode->addDrawable(createBackgroundRectangle(    pos + osg::Vec3(-backgroundMargin, characterSize + backgroundMargin, 0),
1453                                                        5 * characterSize + 2 * backgroundMargin,
1454                                                        12 * characterSize + 2 * backgroundMargin,
1455                                                        backgroundColor));
1456
1457        // View scene stats static text
1458        osg::ref_ptr<osgText::Text> camStaticText = new osgText::Text;
1459        geode->addDrawable( camStaticText.get() ); 
1460        camStaticText->setColor(staticTextColor);
1461        camStaticText->setFont(font);
1462        camStaticText->setCharacterSize(characterSize);
1463        camStaticText->setPosition(pos);
1464
1465        std::ostringstream viewStr;
1466        viewStr.clear();
1467        viewStr.setf(std::ios::left,std::ios::adjustfield);
1468        viewStr.width(14);
1469        viewStr << "View" << std::endl;
1470        viewStr << std::endl;
1471        viewStr << "Stateset" << std::endl;
1472        viewStr << "Group" << std::endl;
1473        viewStr << "Transform" << std::endl;
1474        viewStr << "LOD" << std::endl;
1475        viewStr << "Switch" << std::endl;
1476        viewStr << "Geode" << std::endl;
1477        viewStr << "Drawable" << std::endl;
1478        viewStr << "Geometry" << std::endl;
1479        viewStr << "Vertices" << std::endl;
1480        viewStr << "Primitives" << std::endl;
1481        viewStr.setf(std::ios::right,std::ios::adjustfield);
1482        camStaticText->setText(viewStr.str());
1483
1484        // Move camera block to the right
1485        pos.x() += 5 * characterSize + 2 * backgroundMargin + backgroundSpacing;
1486
1487        std::vector<osgViewer::View*> views;
1488        viewer->getViews(views);
1489
1490        std::vector<osgViewer::View*>::iterator it;
1491        int viewCounter = 0;
1492        for (it = views.begin(); it != views.end(); ++it)
1493        {
1494            geode->addDrawable(createBackgroundRectangle(    pos + osg::Vec3(-backgroundMargin, characterSize + backgroundMargin, 0),
1495                                                            6 * characterSize + 2 * backgroundMargin,
1496                                                            12 * characterSize + 2 * backgroundMargin,
1497                                                            backgroundColor));
1498
1499            // Text for scene statistics
[6028]1500            osgText::Text* text = new  osgText::Text;
1501            geode->addDrawable( text );
[8970]1502 
1503            text->setColor(dynamicTextColor);
[6028]1504            text->setFont(font);
1505            text->setCharacterSize(characterSize);
1506            text->setPosition(pos);
[8970]1507            text->setDrawCallback(new ViewSceneStatsTextDrawCallback(*it, viewCounter));
[6028]1508
[8970]1509            pos.x() += 6 * characterSize + 2 * backgroundMargin + backgroundSpacing;
1510            viewCounter++;
1511        }
[6028]1512    }
1513}
1514
[8970]1515osg::Node* StatsHandler::createCameraTimeStats(const std::string& font, osg::Vec3& pos, float startBlocks, bool acquireGPUStats, float characterSize, osg::Stats* viewerStats, osg::Camera* camera)
[6028]1516{
1517    osg::Stats* stats = camera->getStats();
1518    if (!stats) return 0;
1519
1520    osg::Group* group = new osg::Group;
1521
1522    osg::Geode* geode = new osg::Geode();
1523    group->addChild(geode);
1524
1525    float leftPos = pos.x();
1526
1527    osg::Vec4 colorCull( 0.0f,1.0f,1.0f,1.0f);
[6032]1528    osg::Vec4 colorCullAlpha( 0.0f,1.0f,1.0f,0.5f);
[6028]1529    osg::Vec4 colorDraw( 1.0f,1.0f,0.0f,1.0f);
[6032]1530    osg::Vec4 colorDrawAlpha( 1.0f,1.0f,0.0f,0.5f);
[6028]1531    osg::Vec4 colorGPU( 1.0f,0.5f,0.0f,1.0f);
[6032]1532    osg::Vec4 colorGPUAlpha( 1.0f,0.5f,0.0f,0.5f);
[6028]1533
1534    {
1535        pos.x() = leftPos;
1536
1537        osg::ref_ptr<osgText::Text> cullLabel = new osgText::Text;
1538        geode->addDrawable( cullLabel.get() );
1539
1540        cullLabel->setColor(colorCull);
1541        cullLabel->setFont(font);
1542        cullLabel->setCharacterSize(characterSize);
1543        cullLabel->setPosition(pos);
1544        cullLabel->setText("Cull: ");
1545
1546        pos.x() = cullLabel->getBound().xMax();
1547
1548        osg::ref_ptr<osgText::Text> cullValue = new osgText::Text;
1549        geode->addDrawable( cullValue.get() );
1550
1551        cullValue->setColor(colorCull);
1552        cullValue->setFont(font);
1553        cullValue->setCharacterSize(characterSize);
1554        cullValue->setPosition(pos);
1555        cullValue->setText("0.0");
1556
[8970]1557        cullValue->setDrawCallback(new AveragedValueTextDrawCallback(stats,"Cull traversal time taken",-1, false, 1000.0));
[6028]1558
1559        pos.x() = startBlocks;
[6032]1560        osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorCullAlpha, _numBlocks);
[6028]1561        geometry->setDrawCallback(new BlockDrawCallback(this, startBlocks, viewerStats, stats, "Cull traversal begin time", "Cull traversal end time", -1, _numBlocks));
1562        geode->addDrawable(geometry);
1563
1564        pos.y() -= characterSize*1.5f;
1565    }
1566
1567    {
1568        pos.x() = leftPos;
1569
1570        osg::ref_ptr<osgText::Text> drawLabel = new osgText::Text;
1571        geode->addDrawable( drawLabel.get() );
1572
1573        drawLabel->setColor(colorDraw);
1574        drawLabel->setFont(font);
1575        drawLabel->setCharacterSize(characterSize);
1576        drawLabel->setPosition(pos);
1577        drawLabel->setText("Draw: ");
1578
1579        pos.x() = drawLabel->getBound().xMax();
1580
1581        osg::ref_ptr<osgText::Text> drawValue = new osgText::Text;
1582        geode->addDrawable( drawValue.get() );
1583
1584        drawValue->setColor(colorDraw);
1585        drawValue->setFont(font);
1586        drawValue->setCharacterSize(characterSize);
1587        drawValue->setPosition(pos);
1588        drawValue->setText("0.0");
1589
[8970]1590        drawValue->setDrawCallback(new AveragedValueTextDrawCallback(stats,"Draw traversal time taken",-1, false, 1000.0));
[6028]1591
1592
1593        pos.x() = startBlocks;
[6032]1594        osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorDrawAlpha, _numBlocks);
[6028]1595        geometry->setDrawCallback(new BlockDrawCallback(this, startBlocks, viewerStats, stats, "Draw traversal begin time", "Draw traversal end time", -1, _numBlocks));
1596        geode->addDrawable(geometry);
1597
1598        pos.y() -= characterSize*1.5f;
1599    }
1600
[7648]1601    if (acquireGPUStats)
[6028]1602    {
1603        pos.x() = leftPos;
1604
1605        osg::ref_ptr<osgText::Text> gpuLabel = new osgText::Text;
1606        geode->addDrawable( gpuLabel.get() );
1607
1608        gpuLabel->setColor(colorGPU);
1609        gpuLabel->setFont(font);
1610        gpuLabel->setCharacterSize(characterSize);
1611        gpuLabel->setPosition(pos);
1612        gpuLabel->setText("GPU: ");
1613
1614        pos.x() = gpuLabel->getBound().xMax();
1615
1616        osg::ref_ptr<osgText::Text> gpuValue = new osgText::Text;
1617        geode->addDrawable( gpuValue.get() );
1618
1619        gpuValue->setColor(colorGPU);
1620        gpuValue->setFont(font);
1621        gpuValue->setCharacterSize(characterSize);
1622        gpuValue->setPosition(pos);
1623        gpuValue->setText("0.0");
1624
[8970]1625        gpuValue->setDrawCallback(new AveragedValueTextDrawCallback(stats,"GPU draw time taken",-1, false, 1000.0));
[6028]1626
1627        pos.x() = startBlocks;
[6032]1628        osg::Geometry* geometry = createGeometry(pos, characterSize *0.8, colorGPUAlpha, _numBlocks);
[6028]1629        geometry->setDrawCallback(new BlockDrawCallback(this, startBlocks, viewerStats, stats, "GPU draw begin time", "GPU draw end time", -1, _numBlocks));
1630        geode->addDrawable(geometry);
1631
1632        pos.y() -= characterSize*1.5f;
1633    }
1634
1635
1636    pos.x() = leftPos;
1637
1638    return group;
1639}
1640
[6151]1641
1642void StatsHandler::getUsage(osg::ApplicationUsage& usage) const
1643{
[7648]1644    usage.addKeyboardMouseBinding("s","On screen stats.");
[6151]1645    usage.addKeyboardMouseBinding("S","Output stats to console.");
[6028]1646}
[6151]1647
1648}
Note: See TracBrowser for help on using the browser.