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

Revision 9385, 62.6 kB (checked in by robert, 6 years ago)

Fixed warnings

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