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

Revision 9563, 61.5 kB (checked in by robert, 6 years ago)

From Paul Melis, removed redundent spacing.

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