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

Revision 9554, 61.9 kB (checked in by robert, 6 years ago)

Refactored the view stats.

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