diff --git a/include/osg/Drawable b/include/osg/Drawable index a10026af8..cddd4fdf6 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -17,7 +17,6 @@ namespace osg { -class Statistics; class Vec2; class Vec3; class Vec4; @@ -36,19 +35,6 @@ class Node; for a Drawable are maintained in StateSet which the Drawable maintains a referenced counted pointer to. Both Drawable's and StateSet's can be shared for optimal memory usage and graphics performance. - - Subclasses should provide an instance of getStats(Statistics *st) if the subclass - contains drawing primitives. This member function should add the primitives it - draws into the Statistics class; for example add the number of quads, triangles etc - created. For an example see Geometry.cpp: - getStats(osgUtil::Statistics *stat). - Failure to implement this routine will only result in the stats displayed for - your drawable being wrong. - Another example is in the InfinitePlane class- this draws a normal geoset AND - its own special set of quads, so this case of getPrims calls: - the normal geoset stats gs->getStats(..), and then adds the number of quads - rendered directly (it is rendered in a display list, but we do know how many - quads are in the display list). */ class SG_EXPORT Drawable : public Object { @@ -231,11 +217,6 @@ class SG_EXPORT Drawable : public Object /** flush all the cached display list which need to be deleted * in the OpenGL context related to contextID.*/ static void flushDeletedDisplayLists(uint contextID); - - - /** Collect Stistics count from Drawable.*/ - virtual bool getStats(Statistics&) { return false; } - typedef uint AttributeBitMask; diff --git a/include/osg/GeoSet b/include/osg/GeoSet index 40464ffeb..015c191d3 100644 --- a/include/osg/GeoSet +++ b/include/osg/GeoSet @@ -328,12 +328,6 @@ class SG_EXPORT GeoSet : public Drawable /** get the current AttributeDeleteFunction to handle attribute arrays attached to this Geoset.*/ const AttributeDeleteFunctor* getAttributeDeleteFunctor() const { return _adf.get(); } - - - /** Statistics collection for each drawable- 26.09.01 - */ - bool getStats(Statistics &); - /** return the attributes supported by applyAttrbuteUpdate() as an AttributeBitMask.*/ virtual AttributeBitMask suppportsAttributeOperation() const; diff --git a/include/osg/Geometry b/include/osg/Geometry index c8d4fbd81..f28649f6a 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -91,10 +91,6 @@ class SG_EXPORT Geometry : public Drawable */ virtual void drawImmediateMode(State& state); - /** Statistics collection for each drawable- 26.09.01 - */ - bool getStats(Statistics &); - /** return the attributes supported by applyAttrbuteUpdate() as an AttributeBitMask.*/ virtual AttributeBitMask suppportsAttributeOperation() const; diff --git a/include/osg/ImpostorSprite b/include/osg/ImpostorSprite index c8c3593e2..d1ce91c04 100644 --- a/include/osg/ImpostorSprite +++ b/include/osg/ImpostorSprite @@ -113,11 +113,8 @@ class SG_EXPORT ImpostorSprite : public Drawable const int s() const { return _s; } const int t() const { return _t; } - /** draw ImpostorSprite directly. */ virtual void drawImmediateMode(State& state); - - bool getStats(Statistics &stat); protected: diff --git a/include/osg/Statistics b/include/osg/Statistics index 2484bfe7e..0a4553588 100644 --- a/include/osg/Statistics +++ b/include/osg/Statistics @@ -8,6 +8,8 @@ #include #include +#include + namespace osg { /** @@ -23,84 +25,60 @@ namespace osg { * each trifan or tristrip = (length-2) triangles and so on. */ -class Statistics : public osg::Referenced, public osg::Drawable::AttributeFunctor -{ +class Statistics : public osg::Referenced, public osg::Drawable::PrimitiveFunctor{ public: - - Statistics(): - osg::Drawable::AttributeFunctor(osg::Drawable::COORDS) + + typedef std::pair PrimitivePair; + typedef std::map PrimtiveValueMap; + + + Statistics() { reset(); }; - - enum PrimitiveType - { - NO_TYPE, - POINTS, - LINES, - LINE_STRIP, - FLAT_LINE_STRIP, - LINE_LOOP, - TRIANGLES, - TRIANGLE_STRIP, - FLAT_TRIANGLE_STRIP, - TRIANGLE_FAN, - FLAT_TRIANGLE_FAN, - QUADS, - QUAD_STRIP, - POLYGON, - IMPOSTOR - }; - ~Statistics() {}; // no dynamic allocations, so no need to free enum statsType { STAT_NONE, // default - STAT_FRAMERATE, STAT_GRAPHS, - STAT_VIEWPARMS, // descrbe the view parameters (FOV, near/far...) - STAT_PRIMS, STAT_PRIMSPERVIEW, STAT_PRIMSPERBIN, + STAT_FRAMERATE, + STAT_GRAPHS, + STAT_PRIMS, + STAT_PRIMSPERVIEW, + STAT_PRIMSPERBIN, STAT_DC, STAT_RESTART // hint to restart the stats }; + void reset() { numOpaque=0, nummat=0; depth=0; stattype=STAT_NONE; - nprims=0, nlights=0; nbins=0; nimpostor=0; - for (int i=0; i<=POLYGON; i++) primverts[i]=numprimtypes[i]=primlens[i]=primtypes[i]=0; + nlights=0; nbins=0; nimpostor=0; + + _vertexCount=0; + _primitiveCount.clear(); + + _currentPrimtiveFunctorMode=0; } void setType(statsType t) {stattype=t;} + + virtual void setVertexArray(unsigned int count,Vec3*) { _vertexCount += count; } - virtual bool apply(osg::Drawable::AttributeBitMask abm,osg::Vec3* begin,osg::Vec3* end) - { - if (abm == osg::Drawable::COORDS) - { - primverts[0] += (end-begin); - return true; - } - return false; - } + virtual void drawArrays(GLenum mode,GLint,GLsizei count) { PrimitivePair& prim = _primitiveCount[mode]; ++prim.first; prim.second+=count; } + virtual void drawElements(GLenum mode,GLsizei count,GLubyte*) { PrimitivePair& prim = _primitiveCount[mode]; ++prim.first; prim.second+=count; } + virtual void drawElements(GLenum mode,GLsizei count,GLushort*) { PrimitivePair& prim = _primitiveCount[mode]; ++prim.first; prim.second+=count; } + virtual void drawElements(GLenum mode,GLsizei count,GLuint*) { PrimitivePair& prim = _primitiveCount[mode]; ++prim.first; prim.second+=count; } - void addNumPrims(const int typ, const int nprimlen, const int numprimtype, const int primvert) - { - if (typ>NO_TYPE && typ<=POLYGON) { - primtypes[0]++; - primtypes[typ]++; - numprimtypes[0]+=numprimtype; - numprimtypes[typ]+=numprimtype; - primlens[0]+=nprimlen; - primlens[typ]+=nprimlen; - //primverts[0]+=primvert; - primverts[typ]+=primvert; - } - } + virtual void begin(GLenum mode) { _currentPrimtiveFunctorMode=mode; PrimitivePair& prim = _primitiveCount[mode]; ++prim.first; } + virtual void vertex(const Vec3&) { PrimitivePair& prim = _primitiveCount[_currentPrimtiveFunctorMode]; ++prim.second; } + virtual void vertex(float,float,float) { PrimitivePair& prim = _primitiveCount[_currentPrimtiveFunctorMode]; ++prim.second; } + virtual void end() {} void addOpaque() { numOpaque++;} void addMatrix() { nummat++;} void addLight(const int np) { nlights+=np;} - void addNumPrims(const int np) { nprims += np; } void addImpostor(const int np) { nimpostor+= np; } inline const int getBins() { return nbins;} void setDepth(const int d) { depth=d; } @@ -111,15 +89,15 @@ class Statistics : public osg::Referenced, public osg::Drawable::AttributeFuncto public: int numOpaque, nummat, nbins; - int nprims, nlights; + int nlights; int depth; // depth into bins - eg 1.1,1.2,1.3 etc int _binNo; statsType stattype; int nimpostor; // number of impostors rendered - int numprimtypes[16]; // histogram of number of each type of prim - int primtypes[16]; // histogram of number of each type of prim - int primlens[16]; // histogram of lengths of each type of prim - int primverts[16]; // histogram of number of vertices to be transformed + + unsigned int _vertexCount; + PrimtiveValueMap _primitiveCount; + GLenum _currentPrimtiveFunctorMode; }; diff --git a/include/osgParticle/ParticleSystem b/include/osgParticle/ParticleSystem index 943a9d770..20428ba63 100644 --- a/include/osgParticle/ParticleSystem +++ b/include/osgParticle/ParticleSystem @@ -19,7 +19,6 @@ #include #include #include -#include #include namespace osgParticle @@ -117,9 +116,8 @@ namespace osgParticle /// Update the particles. Don't call this directly, use a ParticleSystemUpdater instead. virtual void update(double dt); - inline virtual bool getStats(osg::Statistics &stats); - protected: + virtual ~ParticleSystem(); ParticleSystem &operator=(const ParticleSystem &) { return *this; } @@ -231,12 +229,6 @@ namespace osgParticle return true; } - inline bool ParticleSystem::getStats(osg::Statistics &stats) - { - stats.addNumPrims(draw_count_); - return true; - } - inline void ParticleSystem::update_bounds(const osg::Vec3 &p, float r) { if (reset_bounds_flag_) { diff --git a/include/osgUtil/RenderBin b/include/osgUtil/RenderBin index a57d24b14..f96c53297 100644 --- a/include/osgUtil/RenderBin +++ b/include/osgUtil/RenderBin @@ -6,12 +6,14 @@ #define OSGUTIL_RENDERBIN 1 #include -#include #include #include #include +// forward declare Statistics to remove link dependancy. +namespace osg { class Statistics; } + namespace osgUtil { class RenderStage; diff --git a/src/osg/GeoSet.cpp b/src/osg/GeoSet.cpp index 2f589629d..2cbd9c1c9 100644 --- a/src/osg/GeoSet.cpp +++ b/src/osg/GeoSet.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -887,98 +886,6 @@ Drawable::AttributeBitMask GeoSet::applyAttributeOperation(AttributeFunctor& auf return ramb; } -bool GeoSet::getStats(Statistics &stat) -{ // analyse the drawable GeoSet - const int np=getNumPrims(); // number of primitives in this geoset - stat.addNumPrims(np); - const int type=getPrimType(); - int nprimlens=0, numprimtypes=0, primverts=0; - switch (type) { - case osg::GeoSet::POINTS: - case osg::GeoSet::LINES: - case osg::GeoSet::LINE_STRIP: - case osg::GeoSet::FLAT_LINE_STRIP: - case osg::GeoSet::LINE_LOOP: - case osg::GeoSet::TRIANGLE_STRIP: - case osg::GeoSet::FLAT_TRIANGLE_STRIP: - case osg::GeoSet::TRIANGLE_FAN: - case osg::GeoSet::FLAT_TRIANGLE_FAN: - case osg::GeoSet::QUAD_STRIP: - case osg::GeoSet::POLYGON: - break; - case osg::GeoSet::TRIANGLES: // should not have any lengths for tris & quads - nprimlens=np; - numprimtypes=np; - primverts=3*np; - break; - case osg::GeoSet::QUADS: - nprimlens=np*2; - primverts=4*np; - numprimtypes=np; - break; - case osg::GeoSet::NO_TYPE: - default: - break; - } - // now count the lengths, ie efficiency of triangulation - const int *lens=getPrimLengths(); // primitive lengths - if (lens) { // then count for each length - for (int i=0; i #include #include -#include using namespace osg; @@ -268,12 +267,3 @@ ImpostorSprite* ImpostorSpriteManager::createOrReuseImpostorSprite(int s,int t,i return is; } - - -bool ImpostorSprite::getStats(Statistics &stat) -{ // analyse the drawable Impostor Sprite - stat.addNumPrims(1); // use new member functions of Statistics class to update - stat.addNumPrims(Statistics::QUADS, 2, 1, 4); - stat.addImpostor(1); - return true; -} diff --git a/src/osgGLUT/Viewer.cpp b/src/osgGLUT/Viewer.cpp index 27099b9c6..be876d309 100644 --- a/src/osgGLUT/Viewer.cpp +++ b/src/osgGLUT/Viewer.cpp @@ -11,7 +11,9 @@ #include #endif #include + #include +#include #include @@ -535,7 +537,7 @@ void Viewer::showStats(const unsigned int /*viewport*/) glEnd(); glLineWidth(1.0f); } - if (_printStats==Statistics::STAT_PRIMS) { // yet more stats - add triangles, number of strips... + if (_printStats==osg::Statistics::STAT_PRIMS) { // yet more stats - add triangles, number of strips... /* * Use the new renderStage. Required mods to RenderBin.cpp, and RenderStage.cpp (add getPrims) * also needed to define a new class called Statistic (see osgUtil/Statistic). @@ -1503,128 +1505,84 @@ void displaytext(int x, int y, char *s) glListBase(0); // glPopAttrib (); } -/* -void writePrims( const int ypos, osg::Statistics& stats) -{ - char clin[100]; // buffer to print - char ctmp[12]; - int i; // a counter - static char *prtypes[]={"Total", - " Pt", " Ln", " Lstr", " LSTf", " Llop", // 1- 5 - " Tris", " TStr", " TSfl", " TFan", " TFnf", // 6-10 - " Quad", " QStr", " Pols", "", "", // 11-15 - "", "", "", "", ""}; - glColor3f(.9f,.9f,0.0f); - sprintf(clin,"%d Prims %d Matxs %d Gsets %d nlts %d bins %d imps", - stats.nprims, stats.nummat, stats.numOpaque, stats.nlights, stats.nbins, stats.nimpostor); - displaytext(0,ypos,clin); - strcpy(clin," "); - for (i=0; i<15; i++) { - if (i==0 || stats.primtypes[i]) { - strcat(clin, prtypes[i]); - } - } - displaytext(0,ypos-12,clin); - strcpy(clin,"GSet type: "); - for (i=0; i<15; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.primtypes[i]); - strcat(clin, ctmp); - } - } - displaytext(0,ypos-24,clin); - strcpy(clin,"Prims: "); - for (i=0; i<15; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.numprimtypes[i]); - strcat(clin, ctmp); - } - } - displaytext(0,ypos-36,clin); - strcpy(clin,"Triangles: "); - for (i=0; i<15; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.primlens[i]); - strcat(clin, ctmp); - } - } - displaytext(0,ypos-48,clin); - strcpy(clin,"Vertices: "); - for (i=0; i<15; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.primverts[i]); - strcat(clin, ctmp); - } - } - displaytext(0,ypos-60,clin); -} -*/ + int writePrims( const int ypos, osg::Statistics& stats) { char clin[100]; // buffer to print char ctmp[12]; - int i; // a counter int npix=0; // offset from ypos char intro[12]; // start of first line - static char *prtypes[]={"Total", - " Pt", " Ln", " Lstr", " LSTf", " Llop", // 1- 5 - " Tris", " TStr", " TSfl", " TFan", " TFnf", // 6-10 - " Quad", " QStr", " Pols", "", "", // 11-15 - "", "", "", "", ""}; + static char *prtypes[]= + { + " Point", // GL_POINTS 0x0000 + " Lines", // GL_LINES 0x0001 + " LnLoop", // GL_LINE_LOOP 0x0002 + " LnStr", // GL_LINE_SRIP 0x0002 + " Tris", // GL_TRIANGLES 0x0004 + " TriStr", // GL_TRIANGLE_STRIP 0x0005 + " TriFan", // GL_TRIANGLE_FAN 0x0006 + " Quads", // GL_QUADS 0x0007 + " QudStr", // GL_QUAD_STRIP 0x0008 + " Poly" // GL_POLYGON 0x0009 + }; + glColor3f(.9f,.9f,0.0f); if (stats.depth==1) sprintf(intro,"==> Bin %2d", stats._binNo); - else sprintf(intro," "); - sprintf(clin,"%s %d Prims %d Matxs %d Gsets %d nlts %d bins %d imps", - intro ,stats.nprims, stats.nummat, stats.numOpaque, stats.nlights, stats.nbins, stats.nimpostor); + else sprintf(intro,"General Stats: "); + sprintf(clin,"%s %d Opaque Drawables %d Lights %d Bins %d Impostors", + intro ,stats.numOpaque, stats.nlights, stats.nbins, stats.nimpostor); displaytext(0,ypos-npix,clin); - npix+=12; - strcpy(clin," "); - for (i=0; i<=osg::Statistics::POLYGON; i++) { - if (i==0 || stats.primtypes[i]) { - strcat(clin, prtypes[i]); - } + npix+=24; + + strcpy(clin," Total"); + + unsigned int totalNumPrimives = 0; + unsigned int totalNumIndices = 0; + osg::Statistics::PrimtiveValueMap::iterator pItr; + for(pItr=stats._primitiveCount.begin(); + pItr!=stats._primitiveCount.end(); + ++pItr) + { + totalNumPrimives += (pItr->second.first); + totalNumIndices += (pItr->second.second); + strcat(clin, prtypes[pItr->first]); } displaytext(0,ypos-npix,clin); npix+=12; - strcpy(clin,"GSet type: "); - for (i=0; i<=osg::Statistics::POLYGON; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.primtypes[i]); - strcat(clin, ctmp); - } + + strcpy(clin,"Primitives: "); + sprintf(ctmp,"%7d", totalNumPrimives); + strcat(clin, ctmp); + for(pItr=stats._primitiveCount.begin(); + pItr!=stats._primitiveCount.end(); + ++pItr) + { + sprintf(ctmp,"%7d", pItr->second.first); + strcat(clin, ctmp); } displaytext(0,ypos-npix,clin); npix+=12; - strcpy(clin,"Prims: "); - for (i=0; i<=osg::Statistics::POLYGON; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.numprimtypes[i]); - strcat(clin, ctmp); - } + + strcpy(clin,"Indices: "); + sprintf(ctmp,"%7d", totalNumIndices); + strcat(clin, ctmp); + for(pItr=stats._primitiveCount.begin(); + pItr!=stats._primitiveCount.end(); + ++pItr) + { + sprintf(ctmp,"%7d", pItr->second.second); + strcat(clin, ctmp); } displaytext(0,ypos-npix,clin); npix+=12; - strcpy(clin,"Triangles: "); - for (i=0; i<=osg::Statistics::POLYGON; i++) { - if (stats.primtypes[i]) { - sprintf(ctmp,"%5d", stats.primlens[i]); - strcat(clin, ctmp); - } - } + + strcpy(clin,"Vertices: "); + sprintf(ctmp,"%7d", stats._vertexCount); + strcat(clin, ctmp); displaytext(0,ypos-npix,clin); npix+=12; - strcpy(clin,"Vertices: "); - for (i=0; i<=osg::Statistics::POLYGON; i++) { - if (stats.primverts[i]) { - sprintf(ctmp,"%5d", stats.primverts[i]); - strcat(clin, ctmp); - } - } - displaytext(0,ypos-npix,clin); - npix+=12; - if (stats.stattype!=osg::Statistics::STAT_PRIMSPERBIN) { - } + return npix; } diff --git a/src/osgUtil/IntersectVisitor.cpp b/src/osgUtil/IntersectVisitor.cpp index 7fdd51e46..923f8eed7 100644 --- a/src/osgUtil/IntersectVisitor.cpp +++ b/src/osgUtil/IntersectVisitor.cpp @@ -493,7 +493,7 @@ void IntersectVisitor::apply(Geode& geode) { if (!enterNode(geode)) return; - for(int i = 0; i < geode.getNumDrawables(); i++ ) + for(unsigned int i = 0; i < geode.getNumDrawables(); i++ ) { intersect(*geode.getDrawable(i)); } diff --git a/src/osgUtil/RenderBin.cpp b/src/osgUtil/RenderBin.cpp index ca41eced8..a01c3ecd7 100644 --- a/src/osgUtil/RenderBin.cpp +++ b/src/osgUtil/RenderBin.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include using namespace osg; @@ -186,13 +188,10 @@ bool RenderBin::getStats(osg::Statistics* primStats) Drawable* dw= rl->_drawable; primStats->addOpaque(); // number of geosets if (rl->_modelview.get()) primStats->addMatrix(); // number of matrices - if (dw) { // then tot up the types 1-14 - // commenting out as having intrusive stats in base classes is - // undersirable. - dw->getStats(*primStats); // use sub-class to find the stats for each drawable - - // use an AttributeOption to get the stats we require. - dw->applyAttributeOperation(*primStats); + if (dw) + { + // then tot up the primtive types and no vertices. + dw->applyPrimitiveOperation(*primStats); // use sub-class to find the stats for each drawable } } somestats=true; diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index b9111d743..dc74dfc9c 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -1,8 +1,10 @@ #include #include +#include #include + using namespace osg; using namespace osgUtil;