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

Revision 9601, 61.8 kB (checked in by robert, 6 years ago)

Fixed size of background of frame stats so that it's the correct width of the window

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