1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSGUTIL_STATISTICS
15#define OSGUTIL_STATISTICS 1
16
17#include <osgUtil/Export>
18
19#include <osg/PrimitiveSet>
20#include <osg/Drawable>
21#include <osg/NodeVisitor>
22#include <osg/Geode>
23#include <osg/LOD>
24#include <osg/Switch>
25#include <osg/Geometry>
26#include <osg/Transform>
27
28#include <map>
29#include <set>
30#include <ostream>
31
32namespace osgUtil {
33
34/**
35 * Statistics base class. Used to extract primitive information from
36 * the renderBin(s).  Add a case of getStats(osgUtil::Statistics *stat)
37 * for any new drawable (or drawable derived class) that you generate
38 * (eg see Geometry.cpp).  There are 20 types of drawable counted - actually only
39 * 14 cases can occur in reality.  these represent sets of GL_POINTS, GL_LINES
40 * GL_LINESTRIPS, LOOPS, TRIANGLES, TRI-fans, tristrips, quads, quadstrips etc
41 * The number of triangles rendered is inferred:
42 * each triangle = 1 triangle (number of vertices/3)
43 * each quad = 2 triangles (nverts/2)
44 * each trifan or tristrip = (length-2) triangles and so on.
45*/
46
47class OSGUTIL_EXPORT Statistics : public osg::PrimitiveFunctor
48{
49    public:
50
51        typedef std::pair<unsigned int,unsigned int>    PrimitivePair;
52        typedef std::map<GLenum,PrimitivePair>          PrimitiveValueMap;
53        typedef std::map<GLenum, unsigned int>          PrimitiveCountMap;
54
55
56        Statistics();
57
58        enum StatsType
59        {
60            STAT_NONE, // default
61            STAT_FRAMERATE,
62            STAT_GRAPHS,
63            STAT_PRIMS,
64            STAT_PRIMSPERVIEW,
65            STAT_PRIMSPERBIN,
66            STAT_DC,
67            STAT_RESTART // hint to restart the stats
68        };
69
70        void reset();
71
72        void setType(StatsType t) { stattype=t; }
73
74        virtual void setVertexArray(unsigned int count,const osg::Vec3*) { _vertexCount += count; }
75        virtual void setVertexArray(unsigned int count,const osg::Vec2*) { _vertexCount += count; }
76        virtual void setVertexArray(unsigned int count,const osg::Vec4*) { _vertexCount += count; }
77        virtual void setVertexArray(unsigned int count,const osg::Vec3d*) { _vertexCount += count; }
78        virtual void setVertexArray(unsigned int count,const osg::Vec2d*) { _vertexCount += count; }
79        virtual void setVertexArray(unsigned int count,const osg::Vec4d*) { _vertexCount += count; }
80
81        virtual void drawArrays(GLenum mode,GLint,GLsizei count);
82        virtual void drawElements(GLenum mode,GLsizei count,const GLubyte*);
83        virtual void drawElements(GLenum mode,GLsizei count,const GLushort*);
84        virtual void drawElements(GLenum mode,GLsizei count,const GLuint*);
85
86        virtual void begin(GLenum mode);
87
88        inline void vertex()
89        {
90            PrimitivePair& prim = _primitiveCount[_currentPrimitiveFunctorMode];
91            ++prim.second;
92           _number_of_vertexes++;
93        }
94
95        virtual void vertex(float,float,float) { vertex(); }
96        virtual void vertex(const osg::Vec3&)  { vertex(); }
97        virtual void vertex(const osg::Vec2&)  { vertex(); }
98        virtual void vertex(const osg::Vec4&)  { vertex(); }
99        virtual void vertex(float,float)   { vertex(); }
100        virtual void vertex(float,float,float,float)  { vertex(); }
101
102        virtual void end();
103
104        void addDrawable() { numDrawables++;}
105        void addFastDrawable() { numFastDrawables++;}
106        void addMatrix() { nummat++;}
107        void addLight(int np) { nlights+=np;}
108        void addImpostor(int np) { nimpostor+= np; }
109        inline int getBins() { return nbins;}
110        void setDepth(int d) { depth=d; }
111        void addBins(int np) { nbins+= np; }
112
113        void setBinNo(int n) { _binNo=n;}
114        void addStateGraphs(int n) { numStateGraphs += n; }
115        void addOrderedLeaves(int n) { numOrderedLeaves += n; }
116
117        void add(const Statistics& stats);
118
119    public:
120
121        PrimitiveCountMap& getPrimitiveCountMap() { return _primitives_count; }
122        const PrimitiveCountMap& getPrimitiveCountMap() const { return _primitives_count; }
123
124        PrimitiveValueMap& getPrimitiveValueMap() { return _primitiveCount; }
125        const PrimitiveValueMap& getPrimitiveValueMap() const { return _primitiveCount; }
126
127
128        /// deprecated
129        PrimitiveCountMap::iterator GetPrimitivesBegin() { return _primitives_count.begin(); }
130        /// deprecated
131        PrimitiveCountMap::iterator GetPrimitivesEnd() { return _primitives_count.end(); }
132
133        int numDrawables, nummat, nbins, numStateGraphs;
134        int numFastDrawables;
135        int nlights;
136        int depth; // depth into bins - eg 1.1,1.2,1.3 etc
137        int _binNo;
138        StatsType stattype;
139        int nimpostor; // number of impostors rendered
140        int numOrderedLeaves;   // leaves from RenderBin fine grain ordering
141
142        unsigned int        _vertexCount;
143        PrimitiveValueMap    _primitiveCount;
144        GLenum              _currentPrimitiveFunctorMode;
145
146    private:
147        PrimitiveCountMap                     _primitives_count;
148
149        unsigned int                         _total_primitives_count;
150        unsigned int                         _number_of_vertexes;
151
152        inline unsigned int _calculate_primitives_number_by_mode(GLenum, GLsizei);
153};
154
155inline unsigned int Statistics::_calculate_primitives_number_by_mode(GLenum mode, GLsizei count)
156{
157    switch (mode)
158    {
159        case GL_POINTS:
160        case GL_LINE_LOOP:
161        case GL_POLYGON:  return count;
162        case GL_LINES: return count / 2;
163        case GL_LINE_STRIP: return count - 1;
164        case GL_TRIANGLES: return count / 3;
165        case GL_TRIANGLE_STRIP:
166        case GL_TRIANGLE_FAN: return count - 2;
167        case GL_QUADS: return count / 4;
168        case GL_QUAD_STRIP: return count / 2 - 1;
169        default: return 0;
170    }
171}
172
173/** StatsVisitor for collecting statistics about scene graph.*/
174class OSGUTIL_EXPORT StatsVisitor : public osg::NodeVisitor
175{
176public:
177
178    typedef std::set<osg::Node*> NodeSet;
179    typedef std::set<osg::Drawable*> DrawableSet;
180    typedef std::set<osg::StateSet*> StateSetSet;
181
182    StatsVisitor();
183
184    META_NodeVisitor(osgUtil, StatsVisitor)
185
186    virtual void reset();
187
188    virtual void apply(osg::Node& node);
189    virtual void apply(osg::Group& node);
190    virtual void apply(osg::Transform& node);
191    virtual void apply(osg::LOD& node);
192    virtual void apply(osg::Switch& node);
193    virtual void apply(osg::Geode& node);
194    virtual void apply(osg::Drawable& drawable);
195    virtual void apply(osg::StateSet& ss);
196
197    virtual void totalUpStats();
198
199    virtual void print(std::ostream& out);
200
201    unsigned int _numInstancedGroup;
202    unsigned int _numInstancedSwitch;
203    unsigned int _numInstancedLOD;
204    unsigned int _numInstancedTransform;
205    unsigned int _numInstancedGeode;
206    unsigned int _numInstancedDrawable;
207    unsigned int _numInstancedGeometry;
208    unsigned int _numInstancedFastGeometry;
209    unsigned int _numInstancedStateSet;
210
211    NodeSet _groupSet;
212    NodeSet _transformSet;
213    NodeSet _lodSet;
214    NodeSet _switchSet;
215    NodeSet _geodeSet;
216    DrawableSet _drawableSet;
217    DrawableSet _geometrySet;
218    DrawableSet _fastGeometrySet;
219    StateSetSet _statesetSet;
220
221    osgUtil::Statistics _uniqueStats;
222    osgUtil::Statistics _instancedStats;
223};
224
225}
226
227#endif
228