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

Revision 10601, 61.8 kB (checked in by robert, 5 years ago)

Introduced new GLBufferObject pool for managing the memory footprint taken up by VertexBufferObejct?, ElementBufferObject? and PixelBufferObject?.

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