From cbeeeefdabbeb039c851d2a4e02874027f1c72af Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 25 Jun 2002 20:27:51 +0000 Subject: [PATCH] Added osg::Drawable::PrimitiveFunctor and TriangleFunctor subclass for querrying the primitive data inside Drawables. Moved various support classes over from being osg::GeoSet based to osg::Geometry based. --- include/osg/BoundingBox | 2 +- include/osg/Drawable | 348 +++++++++++++++++++++- include/osg/GeoSet | 2 + include/osg/Geometry | 78 ++--- include/osg/Statistics | 2 +- include/osgUtil/IntersectVisitor | 5 +- include/osgUtil/TriStripVisitor | 4 +- src/Demos/osgcube/osgcube.cpp | 143 ++++----- src/Demos/osggeometry/osggeometry.cpp | 105 ------- src/osg/GeoSet.cpp | 47 +++ src/osg/Geometry.cpp | 18 ++ src/osg/Image.cpp | 44 ++- src/osg/ImpostorSprite.cpp | 2 +- src/osg/ShadowVolumeOccluder.cpp | 91 +----- src/osgGLUT/Viewer.cpp | 4 +- src/osgPlugins/osg/Geometry.cpp | 6 +- src/osgUtil/IntersectVisitor.cpp | 75 ++--- src/osgUtil/Optimizer.cpp | 6 +- src/osgUtil/SmoothingVisitor.cpp | 6 +- src/osgUtil/TriStripVisitor.cpp | 400 ++++++++++---------------- 20 files changed, 737 insertions(+), 651 deletions(-) diff --git a/include/osg/BoundingBox b/include/osg/BoundingBox index 8e35745de..35d433f8e 100644 --- a/include/osg/BoundingBox +++ b/include/osg/BoundingBox @@ -15,7 +15,7 @@ class BoundingSphere; /** General purpose axis-aligned bounding box class for enclosing objects/vertices. Used to bounding the leaf objects in the scene, - i.e. osg::GeoSet's to assist in view frustum culling etc. + i.e. osg::Drawable's to assist in view frustum culling etc. */ class SG_EXPORT BoundingBox { diff --git a/include/osg/Drawable b/include/osg/Drawable index 5daa3c3f7..f01ee00c2 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -33,7 +33,7 @@ class Node; #define USE_SEPERATE_COMPILE_AND_EXECUTE /** Pure virtual base class for drawable Geometry. Contains no drawing primitives - directly, these are provided by subclasses such as GeoSet. State attributes + directly, these are provided by subclasses such as osg::Geometry. State attributes 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. @@ -41,7 +41,7 @@ class Node; 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 GeoSet.cpp: + 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. @@ -261,6 +261,26 @@ class SG_EXPORT Drawable : public Object virtual AttributeBitMask applyAttributeOperation(AttributeFunctor&) { return 0; } + class PrimitiveFunctor + { + public: + + virtual void setVertexArray(unsigned int count,Vec3* vertices) = 0; + + virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0; + virtual void drawElements(GLenum mode,GLsizei count,unsigned char* indices) = 0; + virtual void drawElements(GLenum mode,GLsizei count,unsigned short* indices) = 0; + virtual void drawElements(GLenum mode,GLsizei count,unsigned int* indices) = 0; + + virtual void begin(GLenum mode) = 0; + virtual void vertex(const Vec3& vert) = 0; + virtual void vertex(float x,float y,float z) = 0; + virtual void end() = 0; + + }; + + /** apply the internal geometry as basic primitives to a PrimitiveFunctor.*/ + virtual void applyPrimitiveOperation(PrimitiveFunctor&) {} protected: @@ -354,7 +374,329 @@ inline void Drawable::draw(State& state) else drawImmediateMode(state); } -} +}; + +template +class TriangleFunctor : public Drawable::PrimitiveFunctor, public T +{ +public: + + TriangleFunctor() + { + _vertexArraySize=0; + _vertexArrayPtr=0; + _modeCache=0; + } + + virtual ~TriangleFunctor() {} + + virtual void setVertexArray(unsigned int count,Vec3* vertices) + { + _vertexArraySize = count; + _vertexArrayPtr = vertices; + } + + virtual void drawArrays(GLenum mode,GLint first,GLsizei count) + { + if (_vertexArrayPtr==0 && count==0) return; + + switch(mode) + { + case(GL_TRIANGLES): + { + Vec3* vlast = &_vertexArrayPtr[first+count]; + for(Vec3* vptr=&_vertexArrayPtr[first];vptr _vertexCache; + +}; + } diff --git a/include/osg/GeoSet b/include/osg/GeoSet index c24e04fb9..e62a3b2d8 100644 --- a/include/osg/GeoSet +++ b/include/osg/GeoSet @@ -337,6 +337,8 @@ class SG_EXPORT GeoSet : public Drawable /** return the attributes successully applied in applyAttributeUpdate.*/ virtual AttributeBitMask applyAttributeOperation(AttributeFunctor& auf); + /** apply the internal geometry as basic primitives to a PrimitiveFunctor.*/ + virtual void applyPrimitiveOperation(PrimitiveFunctor& functor); /** convinience function for converting GeoSet's to equivilant Geometry nodes.*/ Geometry* convertToGeometry(); diff --git a/include/osg/Geometry b/include/osg/Geometry index 2842fca1e..abdd3d7c5 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -76,6 +76,10 @@ class TemplateArray : public AttributeArray, public std::vector AttributeArray(ta,copyop), std::vector(ta) {} + TemplateArray(unsigned int no) : + AttributeArray(ARRAYTYPE,DataSize,DataType), + std::vector(no) {} + TemplateArray(unsigned int no,T* ptr) : AttributeArray(ARRAYTYPE,DataSize,DataType), std::vector(ptr,ptr+no) {} @@ -131,10 +135,14 @@ class Primitive : public Object POLYGON = GL_POLYGON }; - Primitive(PrimitiveType primType=PrimitivePrimitiveType):_primitiveType(primType) {} + Primitive(PrimitiveType primType=PrimitivePrimitiveType,GLenum mode=0): + _primitiveType(primType), + _mode(mode) {} Primitive(const Primitive& prim,const CopyOp& copyop=CopyOp::SHALLOW_COPY): - Object(prim,copyop) {} + Object(prim,copyop), + _primitiveType(prim._primitiveType), + _mode(prim._mode) {} virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } @@ -142,9 +150,17 @@ class Primitive : public Object PrimitiveType primitiveType() const { return _primitiveType; } + void setMode(GLenum mode) { _mode = mode; } + GLenum getMode() const { return _mode; } + virtual void draw() const = 0; + virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor&) {} + + protected: + PrimitiveType _primitiveType; + GLenum _mode; }; class DrawArrays : public Primitive @@ -152,18 +168,16 @@ class DrawArrays : public Primitive public: DrawArrays(): - Primitive(DrawArraysPrimitiveType) + Primitive(DrawArraysPrimitiveType,0) {} DrawArrays(GLenum mode, GLint first, GLsizei count): - Primitive(DrawArraysPrimitiveType), - _mode(mode), + Primitive(DrawArraysPrimitiveType,mode), _first(first), _count(count) {} DrawArrays(const DrawArrays& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Primitive(da,copyop), - _mode(da._mode), _first(da._first), _count(da._count) {} @@ -174,30 +188,29 @@ class DrawArrays : public Primitive virtual const char* className() const { return "DrawArrays"; } - void set(GLenum mode, GLint first, GLsizei count) + void set(GLenum mode,GLint first, GLsizei count) { _mode = mode; _first = first; _count = count; } - void setMode(GLenum mode) { _mode = mode; } - GLenum getMode() const { return _mode; } - void setFirst(GLint first) { _first = first; } GLint getFirst() const { return _first; } void setCount(GLsizei count) { _count = count; } GLsizei getCount() const { return _count; } - - virtual void draw() const { glDrawArrays(_mode,_first,_count); } - GLenum _mode; + virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor) + { + functor.drawArrays(_mode,_first,_count); + } + GLint _first; GLsizei _count; }; @@ -208,42 +221,44 @@ class DrawElements : public Primitive, public std::vector public: DrawElements(GLenum mode=0): - Primitive(PRIMTYPE), - _mode(mode), + Primitive(PRIMTYPE,mode), _dataType(DataType) {} DrawElements(const DrawElements& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Primitive(array,copyop), std::vector(array), - _mode(array._mode), _dataType(array._dataType) {} DrawElements(GLenum mode,unsigned int no,T* ptr) : - Primitive(PRIMTYPE), + Primitive(PRIMTYPE,mode), std::vector(ptr,ptr+no), - _mode(mode), + _dataType(DataType) {} + + DrawElements(GLenum mode,unsigned int no) : + Primitive(PRIMTYPE,mode), + std::vector(no), _dataType(DataType) {} DrawElements(GLenum mode, T* first,T* last) : - Primitive(PRIMTYPE), + Primitive(PRIMTYPE,mode), std::vector(first,last), - _mode(mode), _dataType(DataType) {} virtual Object* cloneType() const { return osgNew DrawElements(); } virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawElements(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } - - void setMode(GLenum mode) { _mode = mode; } - GLenum getMode() const { return _mode; } virtual void draw() const { glDrawElements(_mode,size(),_dataType,&front()); } - GLenum _mode; + virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor) + { + if (!empty()) functor.drawElements(_mode,size(),&front()); + } + GLenum _dataType; }; @@ -255,8 +270,6 @@ typedef DrawElements /* ******************************************************************************************************************* */ -/** Experiemntal replacement for GeoSet. -*/ class SG_EXPORT Geometry : public Drawable { public: @@ -280,15 +293,15 @@ class SG_EXPORT Geometry : public Drawable BIND_PER_VERTEX, }; - void setVertexArray(Vec3Array* array) { _vertexArray = array; } + void setVertexArray(Vec3Array* array) { _vertexArray = array; dirtyDisplayList(); } Vec3Array* getVertexArray() { return _vertexArray.get(); } const Vec3Array* getVertexArray() const { return _vertexArray.get(); } - void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; } + void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; dirtyDisplayList(); } AttributeBinding getNormalBinding() const { return _normalBinding; } - void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; } + void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; dirtyDisplayList(); } Vec3Array* getNormalArray() { return _normalArray.get(); } const Vec3Array* getNormalArray() const { return _normalArray.get(); } @@ -296,7 +309,7 @@ class SG_EXPORT Geometry : public Drawable void setColorBinding(AttributeBinding ab) { _colorBinding = ab; } AttributeBinding getColorBinding() const { return _colorBinding; } - void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; } + void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; dirtyDisplayList(); } AttributeArray* getColorArray() { return _colorArray.get(); } const AttributeArray* getColorArray() const { return _colorArray.get(); } @@ -315,11 +328,11 @@ class SG_EXPORT Geometry : public Drawable typedef std::vector< ref_ptr > PrimitiveList; - void setPrimitiveList(const PrimitiveList& primitives) { _primitives = primitives; } + void setPrimitiveList(const PrimitiveList& primitives) { _primitives = primitives; dirtyDisplayList(); } PrimitiveList& getPrimitiveList() { return _primitives; } const PrimitiveList& getPrimitiveList() const { return _primitives; } - void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); } + void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); dirtyDisplayList(); } @@ -340,6 +353,7 @@ class SG_EXPORT Geometry : public Drawable /** return the attributes successully applied in applyAttributeUpdate.*/ virtual AttributeBitMask applyAttributeOperation(AttributeFunctor& auf); + virtual void applyPrimitiveOperation(PrimitiveFunctor&); protected: diff --git a/include/osg/Statistics b/include/osg/Statistics index 5b9bc2ed0..15726e38c 100644 --- a/include/osg/Statistics +++ b/include/osg/Statistics @@ -14,7 +14,7 @@ namespace osg { * Statistics base class. Used to extract primitive information from * the renderBin(s). Add a case of getStats(osgUtil::Statistics *stat) * for any new drawable (or drawable derived class) that you generate - * (eg see GeoSet.cpp). There are 20 types of drawable counted - actually only + * (eg see Geometry.cpp). There are 20 types of drawable counted - actually only * 14 cases can occur in reality. these represent sets of GL_POINTS, GL_LINES * GL_LINESTRIPS, LOOPS, TRIANGLES, TRI-fans, tristrips, quads, quadstrips etc * The number of triangles rendered is inferred: diff --git a/include/osgUtil/IntersectVisitor b/include/osgUtil/IntersectVisitor index 3bd3cf5d3..3392a2b24 100644 --- a/include/osgUtil/IntersectVisitor +++ b/include/osgUtil/IntersectVisitor @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -51,7 +50,7 @@ class OSGUTIL_EXPORT Hit osg::ref_ptr _localLineSegment; osg::NodePath _nodePath; osg::ref_ptr _geode; - osg::ref_ptr _geoset; + osg::ref_ptr _drawable; osg::ref_ptr _matrix; osg::ref_ptr _inverse; @@ -139,7 +138,7 @@ class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor }; - bool intersect(osg::GeoSet& gset); + bool intersect(osg::Drawable& gset); void pushMatrix(const osg::Matrix& matrix); void popMatrix(); diff --git a/include/osgUtil/TriStripVisitor b/include/osgUtil/TriStripVisitor index b00167817..b58beec42 100644 --- a/include/osgUtil/TriStripVisitor +++ b/include/osgUtil/TriStripVisitor @@ -7,7 +7,7 @@ #include #include -#include +#include #include @@ -30,7 +30,7 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor * NvTriStrip. Converts all primitive types except points * and lines, linestrips which it leaves unchanged. */ - static void stripify(osg::GeoSet& gset); + static void stripify(osg::Geometry& drawable); /// apply stripify method to all geode geosets. virtual void apply(osg::Geode& geode); diff --git a/src/Demos/osgcube/osgcube.cpp b/src/Demos/osgcube/osgcube.cpp index aa664ad78..6a9bb0fd9 100644 --- a/src/Demos/osgcube/osgcube.cpp +++ b/src/Demos/osgcube/osgcube.cpp @@ -1,8 +1,5 @@ -// simple animation demo written by Graeme Harkness. - - #include -#include +#include #include #include #include @@ -15,16 +12,10 @@ #include // ---------------------------------------------------------------------- -// Global variables - this is basically the stuff which will be animated +// Global variables - this is basically the stuff wh ich will be animated // ---------------------------------------------------------------------- -osg::Geode* createCube(); //Forward Declaration added by SMW - - - - - class MyTransformCallback : public osg::NodeCallback{ public: @@ -60,22 +51,6 @@ class MyTransformCallback : public osg::NodeCallback{ _previousTraversalNumber = nv->getTraversalNumber(); -// Some memory stress testing added by Steve to reveal crashes under Windows. -// // Start Added by SMW -// osg::Transform* Tnode = (osg::Transform *)node; -// int i; -// osg::Node *n; -// while (Tnode->getNumChildren() > 0) -// { -// n = Tnode->getChild(0); -// Tnode->removeChild(n); -// } -// for (i = 0;i < 500;i++) -// { -// Tnode->addChild( createCube() ); -// } -// // End Added by SMW - } } } @@ -96,76 +71,76 @@ class MyTransformCallback : public osg::NodeCallback{ }; -osg::Geode* createCube() +osg::Geode* createGeometryCube() { osg::Geode* geode = new osg::Geode(); // ------------------------------------------- - // Set up a new GeoSet which will be our cube + // Set up a new Geometry which will be our cube // ------------------------------------------- - osg::GeoSet* cube = new osg::GeoSet(); + osg::Geometry* cube = new osg::Geometry(); // set up the primitives - cube->setPrimType( osg::GeoSet::POLYGON ); - cube->setNumPrims( 6 ); // the six square faces + + cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,0,4)); + cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,4,4)); + cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,8,4)); + cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,12,4)); + cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,16,4)); + cube->addPrimitive(new osg::DrawArrays(osg::Primitive::POLYGON,20,4)); + - // set up the primitive indices - int* cubeLengthList = new int[6]; - cubeLengthList[0] = 4; // each side of the cube has 4 vertices - cubeLengthList[1] = 4; - cubeLengthList[2] = 4; - cubeLengthList[3] = 4; - cubeLengthList[4] = 4; - cubeLengthList[5] = 4; + // set up coords. + osg::Vec3Array* coords = new osg::Vec3Array; + coords->resize(24); + + (*coords)[0].set( -1.0000f, 1.0000f, -1.000f ); + (*coords)[1].set( 1.0000f, 1.0000f, -1.0000f ); + (*coords)[2].set( 1.0000f, -1.0000f, -1.0000f ); + (*coords)[3].set( -1.0000f, -1.0000f, -1.000 ); - cube->setPrimLengths( cubeLengthList ); + (*coords)[4].set( 1.0000f, 1.0000f, -1.0000f ); + (*coords)[5].set( 1.0000f, 1.0000f, 1.0000f ); + (*coords)[6].set( 1.0000f, -1.0000f, 1.0000f ); + (*coords)[7].set( 1.0000f, -1.0000f, -1.0000f ); + + (*coords)[8].set( 1.0000f, 1.0000f, 1.0000f ); + (*coords)[9].set( -1.0000f, 1.0000f, 1.000f ); + (*coords)[10].set( -1.0000f, -1.0000f, 1.000f ); + (*coords)[11].set( 1.0000f, -1.0000f, 1.0000f ); + + (*coords)[12].set( -1.0000f, 1.0000f, 1.000 ); + (*coords)[13].set( -1.0000f, 1.0000f, -1.000 ); + (*coords)[14].set( -1.0000f, -1.0000f, -1.000 ); + (*coords)[15].set( -1.0000f, -1.0000f, 1.000 ); + + (*coords)[16].set( -1.0000f, 1.0000f, 1.000 ); + (*coords)[17].set( 1.0000f, 1.0000f, 1.0000f ); + (*coords)[18].set( 1.0000f, 1.0000f, -1.0000f ); + (*coords)[19].set( -1.0000f, 1.0000f, -1.000f ); + + (*coords)[20].set( -1.0000f, -1.0000f, 1.000f ); + (*coords)[21].set( -1.0000f, -1.0000f, -1.000f ); + (*coords)[22].set( 1.0000f, -1.0000f, -1.0000f ); + (*coords)[23].set( 1.0000f, -1.0000f, 1.0000f ); - // set up the coordinates. - osg::Vec3 *cubeCoords = new osg::Vec3[24]; - cubeCoords[0].set( -1.0000f, 1.0000f, -1.000f ); - cubeCoords[1].set( 1.0000f, 1.0000f, -1.0000f ); - cubeCoords[2].set( 1.0000f, -1.0000f, -1.0000f ); - cubeCoords[3].set( -1.0000f, -1.0000f, -1.000 ); - - cubeCoords[4].set( 1.0000f, 1.0000f, -1.0000f ); - cubeCoords[5].set( 1.0000f, 1.0000f, 1.0000f ); - cubeCoords[6].set( 1.0000f, -1.0000f, 1.0000f ); - cubeCoords[7].set( 1.0000f, -1.0000f, -1.0000f ); - - cubeCoords[8].set( 1.0000f, 1.0000f, 1.0000f ); - cubeCoords[9].set( -1.0000f, 1.0000f, 1.000f ); - cubeCoords[10].set( -1.0000f, -1.0000f, 1.000f ); - cubeCoords[11].set( 1.0000f, -1.0000f, 1.0000f ); - - cubeCoords[12].set( -1.0000f, 1.0000f, 1.000 ); - cubeCoords[13].set( -1.0000f, 1.0000f, -1.000 ); - cubeCoords[14].set( -1.0000f, -1.0000f, -1.000 ); - cubeCoords[15].set( -1.0000f, -1.0000f, 1.000 ); - - cubeCoords[16].set( -1.0000f, 1.0000f, 1.000 ); - cubeCoords[17].set( 1.0000f, 1.0000f, 1.0000f ); - cubeCoords[18].set( 1.0000f, 1.0000f, -1.0000f ); - cubeCoords[19].set( -1.0000f, 1.0000f, -1.000f ); - - cubeCoords[20].set( -1.0000f, -1.0000f, 1.000f ); - cubeCoords[21].set( -1.0000f, -1.0000f, -1.000f ); - cubeCoords[22].set( 1.0000f, -1.0000f, -1.0000f ); - cubeCoords[23].set( 1.0000f, -1.0000f, 1.0000f ); - - cube->setCoords( cubeCoords ); + cube->setVertexArray( coords ); // set up the normals. - osg::Vec3 *cubeNormals = new osg::Vec3[6]; - cubeNormals[0].set(0.0f,0.0f,-1.0f); - cubeNormals[1].set(1.0f,0.0f,0.0f); - cubeNormals[2].set(0.0f,0.0f,1.0f); - cubeNormals[3].set(-1.0f,0.0f,0.0f); - cubeNormals[4].set(0.0f,1.0f,0.0f); - cubeNormals[5].set(0.0f,-1.0f,0.0f); - cube->setNormals( cubeNormals ); - cube->setNormalBinding( osg::GeoSet::BIND_PERPRIM ); + osg::Vec3Array* cubeNormals = new osg::Vec3Array; + cubeNormals->resize(6); + + (*cubeNormals)[0].set(0.0f,0.0f,-1.0f); + (*cubeNormals)[1].set(1.0f,0.0f,0.0f); + (*cubeNormals)[2].set(0.0f,0.0f,1.0f); + (*cubeNormals)[3].set(-1.0f,0.0f,0.0f); + (*cubeNormals)[4].set(0.0f,1.0f,0.0f); + (*cubeNormals)[5].set(0.0f,-1.0f,0.0f); + + cube->setNormalArray( cubeNormals ); + cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE ); // --------------------------------------- // Set up a StateSet to make the cube red @@ -201,7 +176,7 @@ int main( int argc, char **argv ) viewer.readCommandLine(commandLine); osg::Transform* myTransform = new osg::Transform(); - myTransform->addChild( createCube() ); + myTransform->addChild( createGeometryCube() ); // move node in a circle at 90 degrees a sec. myTransform->setAppCallback(new MyTransformCallback(myTransform,osg::inDegrees(90.0f))); diff --git a/src/Demos/osggeometry/osggeometry.cpp b/src/Demos/osggeometry/osggeometry.cpp index fe1548166..6a9bb0fd9 100644 --- a/src/Demos/osggeometry/osggeometry.cpp +++ b/src/Demos/osggeometry/osggeometry.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -52,22 +51,6 @@ class MyTransformCallback : public osg::NodeCallback{ _previousTraversalNumber = nv->getTraversalNumber(); -// Some memory stress testing added by Steve to reveal crashes under Windows. -// // Start Added by SMW -// osg::Transform* Tnode = (osg::Transform *)node; -// int i; -// osg::Node *n; -// while (Tnode->getNumChildren() > 0) -// { -// n = Tnode->getChild(0); -// Tnode->removeChild(n); -// } -// for (i = 0;i < 500;i++) -// { -// Tnode->addChild( createCube() ); -// } -// // End Added by SMW - } } } @@ -88,93 +71,6 @@ class MyTransformCallback : public osg::NodeCallback{ }; -osg::Geode* createCube() -{ - osg::Geode* geode = new osg::Geode(); - - // ------------------------------------------- - // Set up a new GeoSet which will be our cube - // ------------------------------------------- - osg::GeoSet* cube = new osg::GeoSet(); - - // set up the primitives - cube->setPrimType( osg::GeoSet::POLYGON ); - cube->setNumPrims( 6 ); // the six square faces - - // set up the primitive indices - int* cubeLengthList = new int[6]; - cubeLengthList[0] = 4; // each side of the cube has 4 vertices - cubeLengthList[1] = 4; - cubeLengthList[2] = 4; - cubeLengthList[3] = 4; - cubeLengthList[4] = 4; - cubeLengthList[5] = 4; - - cube->setPrimLengths( cubeLengthList ); - - - // set up the coordinates. - osg::Vec3 *cubeCoords = new osg::Vec3[24]; - cubeCoords[0].set( -1.0000f, 1.0000f, -1.000f ); - cubeCoords[1].set( 1.0000f, 1.0000f, -1.0000f ); - cubeCoords[2].set( 1.0000f, -1.0000f, -1.0000f ); - cubeCoords[3].set( -1.0000f, -1.0000f, -1.000 ); - - cubeCoords[4].set( 1.0000f, 1.0000f, -1.0000f ); - cubeCoords[5].set( 1.0000f, 1.0000f, 1.0000f ); - cubeCoords[6].set( 1.0000f, -1.0000f, 1.0000f ); - cubeCoords[7].set( 1.0000f, -1.0000f, -1.0000f ); - - cubeCoords[8].set( 1.0000f, 1.0000f, 1.0000f ); - cubeCoords[9].set( -1.0000f, 1.0000f, 1.000f ); - cubeCoords[10].set( -1.0000f, -1.0000f, 1.000f ); - cubeCoords[11].set( 1.0000f, -1.0000f, 1.0000f ); - - cubeCoords[12].set( -1.0000f, 1.0000f, 1.000 ); - cubeCoords[13].set( -1.0000f, 1.0000f, -1.000 ); - cubeCoords[14].set( -1.0000f, -1.0000f, -1.000 ); - cubeCoords[15].set( -1.0000f, -1.0000f, 1.000 ); - - cubeCoords[16].set( -1.0000f, 1.0000f, 1.000 ); - cubeCoords[17].set( 1.0000f, 1.0000f, 1.0000f ); - cubeCoords[18].set( 1.0000f, 1.0000f, -1.0000f ); - cubeCoords[19].set( -1.0000f, 1.0000f, -1.000f ); - - cubeCoords[20].set( -1.0000f, -1.0000f, 1.000f ); - cubeCoords[21].set( -1.0000f, -1.0000f, -1.000f ); - cubeCoords[22].set( 1.0000f, -1.0000f, -1.0000f ); - cubeCoords[23].set( 1.0000f, -1.0000f, 1.0000f ); - - cube->setCoords( cubeCoords ); - - - // set up the normals. - osg::Vec3 *cubeNormals = new osg::Vec3[6]; - cubeNormals[0].set(0.0f,0.0f,-1.0f); - cubeNormals[1].set(1.0f,0.0f,0.0f); - cubeNormals[2].set(0.0f,0.0f,1.0f); - cubeNormals[3].set(-1.0f,0.0f,0.0f); - cubeNormals[4].set(0.0f,1.0f,0.0f); - cubeNormals[5].set(0.0f,-1.0f,0.0f); - cube->setNormals( cubeNormals ); - cube->setNormalBinding( osg::GeoSet::BIND_PERPRIM ); - - // --------------------------------------- - // Set up a StateSet to make the cube red - // --------------------------------------- - osg::StateSet* cubeState = new osg::StateSet(); - osg::Material* redMaterial = new osg::Material(); - osg::Vec4 red( 1.0f, 0.0f, 0.0f, 1.0f ); - redMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, red ); - cubeState->setAttribute( redMaterial ); - - cube->setStateSet( cubeState ); - - geode->addDrawable( cube ); - - return geode; -} - osg::Geode* createGeometryCube() { osg::Geode* geode = new osg::Geode(); @@ -280,7 +176,6 @@ int main( int argc, char **argv ) viewer.readCommandLine(commandLine); osg::Transform* myTransform = new osg::Transform(); -// myTransform->addChild( createCube() ); myTransform->addChild( createGeometryCube() ); // move node in a circle at 90 degrees a sec. diff --git a/src/osg/GeoSet.cpp b/src/osg/GeoSet.cpp index 0cd0fb020..4f1ea2aa3 100644 --- a/src/osg/GeoSet.cpp +++ b/src/osg/GeoSet.cpp @@ -979,8 +979,55 @@ bool GeoSet::getStats(Statistics &stat) return true; } +void GeoSet::applyPrimitiveOperation(PrimitiveFunctor& functor) +{ + // will easily convert into a Geometry. + + if (!_coords || !_numcoords) return; + + functor.setVertexArray(_numcoords,_coords); + + if( _needprimlen ) + { + // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP, + // TRIANGLE_FAN, QUAD_STRIP, POLYGONS + int index = 0; + if( _primLengths == (int *)0 ) + { + return; + } + for( int i = 0; i < _numprims; i++ ) + { + if( _cindex.valid() ) + { + + if (_cindex._is_ushort) + functor.drawElements( (GLenum)_oglprimtype, _primLengths[i],&_cindex._ptr._ushort[index] ); + else + functor.drawElements( (GLenum)_oglprimtype, _primLengths[i],&_cindex._ptr._ushort[index] ); + } + else + functor.drawArrays( (GLenum)_oglprimtype, index, _primLengths[i] ); + index += _primLengths[i]; + } + } + else // POINTS, LINES, TRIANGLES, QUADS + { + if( _cindex.valid()) + { + if (_cindex._is_ushort) + functor.drawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._ushort ); + else + functor.drawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._uint ); + } + else + functor.drawArrays( (GLenum)_oglprimtype, 0, _numcoords ); + } + + +} Geometry* GeoSet::convertToGeometry() { diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 61eaf8a39..955a5b2fc 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -73,6 +73,8 @@ void Geometry::setTexCoordArray(unsigned int unit,AttributeArray* array) _texCoordList.resize(unit+1,0); _texCoordList[unit] = array; + + dirtyDisplayList(); } AttributeArray* Geometry::getTexCoordArray(unsigned int unit) @@ -245,6 +247,22 @@ Drawable::AttributeBitMask Geometry::applyAttributeOperation(AttributeFunctor& ) return 0; } +void Geometry::applyPrimitiveOperation(PrimitiveFunctor& functor) +{ + if (!_vertexArray.valid() || _vertexArray->empty()) return; + + functor.setVertexArray(_vertexArray->size(),&(_vertexArray->front())); + + for(PrimitiveList::iterator itr=_primitives.begin(); + itr!=_primitives.end(); + ++itr) + { + (*itr)->applyPrimitiveOperation(functor); + } + +} + + const bool Geometry::computeBound() const { _bbox.init(); diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 026b8e86d..c0511b110 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include @@ -491,35 +491,33 @@ Geode* osg::createGeodeForImage(osg::Image* image,const float s,const float t) dstate->setAttributeAndModes(texture,osg::StateAttribute::ON); // set up the geoset. - osg::GeoSet* gset = osgNew osg::GeoSet; - gset->setStateSet(dstate); + Geometry* geom = osgNew Geometry; + geom->setStateSet(dstate); - osg::Vec3* coords = osgNew Vec3[4]; - coords[0].set(-x,0.0f,y); - coords[1].set(-x,0.0f,-y); - coords[2].set(x,0.0f,-y); - coords[3].set(x,0.0f,y); - gset->setCoords(coords); + Vec3Array* coords = osgNew Vec3Array(4); + (*coords)[0].set(-x,0.0f,y); + (*coords)[1].set(-x,0.0f,-y); + (*coords)[2].set(x,0.0f,-y); + (*coords)[3].set(x,0.0f,y); + geom->setVertexArray(coords); - osg::Vec2* tcoords = osgNew Vec2[4]; - tcoords[0].set(0.0f,1.0f); - tcoords[1].set(0.0f,0.0f); - tcoords[2].set(1.0f,0.0f); - tcoords[3].set(1.0f,1.0f); - gset->setTextureCoords(tcoords); - gset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX); + Vec2Array* tcoords = osgNew Vec2Array(4); + (*tcoords)[0].set(0.0f,1.0f); + (*tcoords)[1].set(0.0f,0.0f); + (*tcoords)[2].set(1.0f,0.0f); + (*tcoords)[3].set(1.0f,1.0f); + geom->setTexCoordArray(0,tcoords); - osg::Vec4* colours = osgNew Vec4[1]; - colours->set(1.0f,1.0f,1.0,1.0f); - gset->setColors(colours); - gset->setColorBinding(osg::GeoSet::BIND_OVERALL); + osg::Vec4Array* colours = osgNew osg::Vec4Array(1); + (*colours)[0].set(1.0f,1.0f,1.0,1.0f); + geom->setColorArray(colours); + geom->setColorBinding(Geometry::BIND_OVERALL); - gset->setNumPrims(1); - gset->setPrimType(osg::GeoSet::QUADS); + geom->addPrimitive(osgNew DrawArrays(Primitive::QUADS,0,4)); // set up the geode. osg::Geode* geode = osgNew osg::Geode; - geode->addDrawable(gset); + geode->addDrawable(geom); return geode; diff --git a/src/osg/ImpostorSprite.cpp b/src/osg/ImpostorSprite.cpp index 90ec9aff4..934e7f8b8 100644 --- a/src/osg/ImpostorSprite.cpp +++ b/src/osg/ImpostorSprite.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/osg/ShadowVolumeOccluder.cpp b/src/osg/ShadowVolumeOccluder.cpp index f732f509f..8f962963a 100644 --- a/src/osg/ShadowVolumeOccluder.cpp +++ b/src/osg/ShadowVolumeOccluder.cpp @@ -3,7 +3,6 @@ #include #include -#include using namespace osg; @@ -163,59 +162,7 @@ float computePolytopeVolume(const PointList& front, const PointList& back) return volume; } - -Drawable* createOccluderDrawable(const PointList& front, const PointList& back) -{ - // create a drawable for occluder. - osg::GeoSet* geoset = osgNew osg::GeoSet; - - int totalNumber = front.size()+back.size(); - osg::Vec3* coords = osgNew osg::Vec3[front.size()+back.size()]; - osg::Vec3* cptr = coords; - for(PointList::const_iterator fitr=front.begin(); - fitr!=front.end(); - ++fitr) - { - *cptr = fitr->second; - ++cptr; - } - - for(PointList::const_iterator bitr=back.begin(); - bitr!=back.end(); - ++bitr) - { - *cptr = bitr->second; - ++cptr; - } - - geoset->setCoords(coords); - - osg::Vec4* color = osgNew osg::Vec4[1]; - color[0].set(1.0f,1.0f,1.0f,0.5f); - geoset->setColors(color); - geoset->setColorBinding(osg::GeoSet::BIND_OVERALL); - - geoset->setPrimType(osg::GeoSet::POINTS); - geoset->setNumPrims(totalNumber); - - //cout << "totalNumber = "<addDrawable(geoset); - - osg::StateSet* stateset = osgNew osg::StateSet; - stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); - stateset->setMode(GL_BLEND,osg::StateAttribute::ON); - stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - - geoset->setStateSet(stateset); - - return geoset; -} - - -bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables) +bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool /*createDrawables*/) { @@ -291,24 +238,6 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex _volume = computePolytopeVolume(points,farPoints)/volumeview; - if (createDrawables && !nodePath.empty()) - { - osg::Group* group = dynamic_cast(nodePath.back()); - if (group) - { - - osg::Matrix invMV; - invMV.invert(MV); - - transform(points,invMV); - transform(farPoints,invMV); - - osg::Geode* geode = osgNew osg::Geode; - group->addChild(geode); - geode->addDrawable(createOccluderDrawable(points,farPoints)); - } - } - for(ConvexPlanerOccluder::HoleList::const_iterator hitr=occluder.getHoleList().begin(); hitr!=occluder.getHoleList().end(); @@ -350,24 +279,6 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex // remove the hole's volume from the occluder volume. _volume -= computePolytopeVolume(points,farPoints)/volumeview; - - if (createDrawables && !nodePath.empty()) - { - osg::Group* group = dynamic_cast(nodePath.back()); - if (group) - { - - osg::Matrix invMV; - invMV.invert(MV); - - transform(points,invMV); - transform(farPoints,invMV); - - osg::Geode* geode = osgNew osg::Geode; - group->addChild(geode); - geode->addDrawable(createOccluderDrawable(points,farPoints)); - } - } } } diff --git a/src/osgGLUT/Viewer.cpp b/src/osgGLUT/Viewer.cpp index 41a33f3e5..c32a34779 100644 --- a/src/osgGLUT/Viewer.cpp +++ b/src/osgGLUT/Viewer.cpp @@ -1158,8 +1158,8 @@ void Viewer::keyboard(unsigned char key, int x, int y) if (key=='r' && geode) { // remove geoset.. - osg::GeoSet* gset = hitr->_geoset.get(); - osg::notify(osg::NOTICE) << " geoset ("<removeDrawable(gset)<<")"<< std::endl; + osg::Drawable* drawable = hitr->_drawable.get(); + osg::notify(osg::NOTICE) << " drawable ("<removeDrawable(drawable)<<")"<< std::endl; } } diff --git a/src/osgPlugins/osg/Geometry.cpp b/src/osgPlugins/osg/Geometry.cpp index 59ff0c44e..71109e11c 100644 --- a/src/osgPlugins/osg/Geometry.cpp +++ b/src/osgPlugins/osg/Geometry.cpp @@ -629,7 +629,7 @@ bool Primitve_writeLocalData(const Primitive& prim,Output& fw) case(UByteDrawElementsPrimitiveType): { const UByteDrawElements& cprim = static_cast(prim); - fw<(prim); - fw<(prim); - fw<valid()) { - notify(WARN)<<"Warning: invalid line segment passed to IntersectVisitor::addLineSegment(..), segment ignored.."<< std::endl; + notify(WARN)<<"Warning: invalid line segment passed to IntersectVisitor::addLineSegment(..)"<start()<<" "<end()<<" segment ignored.."<< std::endl; return; } @@ -304,7 +305,16 @@ struct TriangleIntersect typedef std::multimap > TriangleHitList; TriangleHitList _thl; + TriangleIntersect() + { + } + TriangleIntersect(const LineSegment& seg,float ratio=FLT_MAX) + { + set(seg,ratio); + } + + void set(const LineSegment& seg,float ratio=FLT_MAX) { _seg=new LineSegment(seg); _hit=false; @@ -315,7 +325,6 @@ struct TriangleIntersect _d = _seg->end()-_seg->start(); _length = _d.length(); _d /= _length; - } // bool intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r) @@ -408,6 +417,14 @@ struct TriangleIntersect float r = d/_length; + if (!in.valid()) + { + osg::notify(WARN)<<"Warning:: Picked up error in TriangleIntersect"< > (r,std::pair(_index-1,normal))); _hit = true; @@ -415,13 +432,13 @@ struct TriangleIntersect }; -bool IntersectVisitor::intersect(GeoSet& gset) +bool IntersectVisitor::intersect(Drawable& drawable) { bool hitFlag = false; IntersectState* cis = _intersectStateStack.back().get(); - const BoundingBox& bb = gset.getBound(); + const BoundingBox& bb = drawable.getBound(); for(IntersectState::LineSegmentList::iterator sitr=cis->_segList.begin(); sitr!=cis->_segList.end(); @@ -429,8 +446,10 @@ bool IntersectVisitor::intersect(GeoSet& gset) { if (sitr->second->intersect(bb)) { - TriangleIntersect ti(*sitr->second); - for_each_triangle(gset,ti); + + TriangleFunctor ti; + ti.set(*sitr->second); + drawable.applyPrimitiveOperation(ti); if (ti._hit) { @@ -442,7 +461,7 @@ bool IntersectVisitor::intersect(GeoSet& gset) hit._nodePath = _nodePath; hit._matrix = cis->_matrix; hit._inverse = cis->_inverse; - hit._geoset = &gset; + hit._drawable = &drawable; if (_nodePath.empty()) hit._geode = NULL; else hit._geode = dynamic_cast(_nodePath.back()); @@ -470,49 +489,13 @@ bool IntersectVisitor::intersect(GeoSet& gset) } - void IntersectVisitor::apply(Geode& geode) { if (!enterNode(geode)) return; for(int i = 0; i < geode.getNumDrawables(); i++ ) { - osg::GeoSet* gset = dynamic_cast(geode.getDrawable(i)); - if (gset) intersect(*gset); - else - { - IntersectState* cis = _intersectStateStack.back().get(); - - // simply default to intersecting with bounding box. - for(IntersectState::LineSegmentList::iterator sitr=cis->_segList.begin(); - sitr!=cis->_segList.end(); - ++sitr) - { - if (sitr->second->intersect(geode.getDrawable(i)->getBound())) - { - Hit hit; - hit._nodePath = _nodePath; - hit._matrix = cis->_matrix; - hit._inverse = cis->_inverse; - hit._geoset = NULL; - if (_nodePath.empty()) hit._geode = NULL; - else hit._geode = dynamic_cast(_nodePath.back()); - - hit._ratio = 0.0f; - hit._primitiveIndex = -1; - hit._originalLineSegment = sitr->first; - hit._localLineSegment = sitr->second; - - hit._intersectPoint = geode.getDrawable(i)->getBound().center(); - - hit._intersectNormal.set(0.0,0.0,1.0); - - _segHitList[sitr->first.get()].push_back(hit); - std::sort(_segHitList[sitr->first.get()].begin(),_segHitList[sitr->first.get()].end()); - - } - } - } + intersect(*geode.getDrawable(i)); } leaveNode(); diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index cd9db6128..da60fdb5a 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -64,9 +64,9 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) } -// // convert the old style GeoSet to Geometry -// ConvertGeoSetsToGeometryVisitor cgtg; -// node->accept(cgtg); + // convert the old style GeoSet to Geometry +// ConvertGeoSetsToGeometryVisitor cgtg; +// node->accept(cgtg); if (options & SHARE_DUPLICATE_STATE) diff --git a/src/osgUtil/SmoothingVisitor.cpp b/src/osgUtil/SmoothingVisitor.cpp index 41791a958..d86039645 100644 --- a/src/osgUtil/SmoothingVisitor.cpp +++ b/src/osgUtil/SmoothingVisitor.cpp @@ -22,7 +22,7 @@ struct LessPtr }; // triangle functor. -struct TriangleFunctor +struct SmoothTriangleFunctor { osg::Vec3 *_coordBase; @@ -31,7 +31,7 @@ struct TriangleFunctor typedef std::multiset CoordinateSet; CoordinateSet _coordSet; - TriangleFunctor(osg::Vec3 *cb,int noVertices, osg::Vec3 *nb) : _coordBase(cb),_normalBase(nb) + SmoothTriangleFunctor(osg::Vec3 *cb,int noVertices, osg::Vec3 *nb) : _coordBase(cb),_normalBase(nb) { osg::Vec3* vptr = cb; for(int i=0;i - -#include -#include #include #include #include +#include + #include "NvTriStripObjects.h" using namespace osg; @@ -23,7 +18,9 @@ struct TriangleAcumulatorFunctor WordVec in_indices; const Vec3* _vbase; - TriangleAcumulatorFunctor( const Vec3* vbase ) : _vbase(vbase) {} + TriangleAcumulatorFunctor() : _vbase(0) {} + + void setCoords( const Vec3* vbase ) { _vbase = vbase; } inline void operator() ( const Vec3 &v1, const Vec3 &v2, const Vec3 &v3 ) { @@ -37,267 +34,172 @@ struct TriangleAcumulatorFunctor } }; -void createStrips( - NvStripInfoVec& strips, - NvFaceInfoVec& leftoverFaces, - int& noPrims, - int **lens, - osg::ushort **osg_indices) +void TriStripVisitor::stripify(Geometry& geom) { - int nStripCount = strips.size(); - assert(nStripCount > 0); - noPrims = strips.size()+leftoverFaces.size(); - *lens = osgNew int [noPrims]; + unsigned int numSurfacePrimitives = 0; + unsigned int numNonSurfacePrimitives = 0; - int* lensPtr = *lens; - - unsigned int i; - int noIndices = 0; - for (i = 0; i < strips.size(); i++) + Geometry::PrimitiveList& primitives = geom.getPrimitiveList(); + Geometry::PrimitiveList::iterator itr; + for(itr=primitives.begin(); + itr!=primitives.end(); + ++itr) { - noIndices += strips[i]->m_faces.size()+2; - } - - noIndices += leftoverFaces.size()*3; - - *osg_indices = osgNew osg::ushort[noIndices]; - osg::ushort *osg_indicesPtr = *osg_indices; - - for (i = 0; i < strips.size(); i++) - { - NvStripInfo *strip = strips[i]; - int nStripFaceCount = strip->m_faces.size(); - - *(lensPtr++) = nStripFaceCount+2; - - NvFaceInfo tLastFace(0, 0, 0); - - // Handle the first face in the strip + switch((*itr)->getMode()) { - NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2); + case(Primitive::TRIANGLES): + case(Primitive::TRIANGLE_STRIP): + case(Primitive::TRIANGLE_FAN): + case(Primitive::QUADS): + case(Primitive::QUAD_STRIP): + case(Primitive::POLYGON): + ++numSurfacePrimitives; + break; + default: + ++numNonSurfacePrimitives; + break; + + } + } + + if (!numSurfacePrimitives) return; + + TriangleFunctor taf; - // If there is a second face, reorder vertices such that the - // unique vertex is first - if (nStripFaceCount > 1) + Geometry::PrimitiveList new_primitives; + new_primitives.reserve(primitives.size()); + + for(itr=primitives.begin(); + itr!=primitives.end(); + ++itr) + { + switch((*itr)->getMode()) + { + case(Primitive::TRIANGLES): + case(Primitive::TRIANGLE_STRIP): + case(Primitive::TRIANGLE_FAN): + case(Primitive::QUADS): + case(Primitive::QUAD_STRIP): + case(Primitive::POLYGON): + (*itr)->applyPrimitiveOperation(taf); + break; + default: + new_primitives.push_back(*itr); + break; + + } + } + + if (!taf.in_indices.empty()) + { + int in_numVertices = -1; + for(WordVec::iterator itr=taf.in_indices.begin(); + itr!=taf.in_indices.end(); + ++itr) + { + if (*itr>in_numVertices) in_numVertices=*itr; + } + // the largest indice is in_numVertices, but indices start at 0 + // so increment to give to the corrent number of verticies. + ++in_numVertices; + + int in_cacheSize = 16; + int in_minStripLength = 2; + NvStripInfoVec strips; + NvFaceInfoVec leftoverFaces; + + NvStripifier stripifier; + stripifier.Stripify(taf.in_indices, + in_numVertices, + in_cacheSize, + in_minStripLength, + strips, + leftoverFaces); + + unsigned int i; + for (i = 0; i < strips.size(); ++i) + { + + NvStripInfo *strip = strips[i]; + int nStripFaceCount = strip->m_faces.size(); + + osg::UShortDrawElements* elements = osgNew osg::UShortDrawElements(osg::Primitive::TRIANGLE_STRIP); + elements->reserve(nStripFaceCount+2); + new_primitives.push_back(elements); + + NvFaceInfo tLastFace(0, 0, 0); + + // Handle the first face in the strip { - int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace); - if (nUnique == tFirstFace.m_v1) - { - std::swap(tFirstFace.m_v0, tFirstFace.m_v1); - } - else if (nUnique == tFirstFace.m_v2) - { - std::swap(tFirstFace.m_v0, tFirstFace.m_v2); - } + NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2); - // If there is a third face, reorder vertices such that the - // shared vertex is last - if (nStripFaceCount > 2) + // If there is a second face, reorder vertices such that the + // unique vertex is first + if (nStripFaceCount > 1) { - int nShared = NvStripifier::GetSharedVertex(strip->m_faces[2], &tFirstFace); - if (nShared == tFirstFace.m_v1) + int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace); + if (nUnique == tFirstFace.m_v1) { - std::swap(tFirstFace.m_v1, tFirstFace.m_v2); + std::swap(tFirstFace.m_v0, tFirstFace.m_v1); + } + else if (nUnique == tFirstFace.m_v2) + { + std::swap(tFirstFace.m_v0, tFirstFace.m_v2); + } + + // If there is a third face, reorder vertices such that the + // shared vertex is last + if (nStripFaceCount > 2) + { + int nShared = NvStripifier::GetSharedVertex(strip->m_faces[2], &tFirstFace); + if (nShared == tFirstFace.m_v1) + { + std::swap(tFirstFace.m_v1, tFirstFace.m_v2); + } } } - } - *(osg_indicesPtr++) = tFirstFace.m_v0; - *(osg_indicesPtr++) = tFirstFace.m_v1; - *(osg_indicesPtr++) = tFirstFace.m_v2; - - // Update last face info - tLastFace = tFirstFace; - } - - for (int j = 1; j < nStripFaceCount; j++) - { - int nUnique = NvStripifier::GetUniqueVertexInB(&tLastFace, strip->m_faces[j]); - if (nUnique != -1) - { - *(osg_indicesPtr++) = nUnique; + elements->push_back(tFirstFace.m_v0); + elements->push_back(tFirstFace.m_v1); + elements->push_back(tFirstFace.m_v2); // Update last face info - tLastFace.m_v0 = tLastFace.m_v1; - tLastFace.m_v1 = tLastFace.m_v2; - tLastFace.m_v2 = nUnique; + tLastFace = tFirstFace; } + + for (int j = 1; j < nStripFaceCount; j++) + { + int nUnique = NvStripifier::GetUniqueVertexInB(&tLastFace, strip->m_faces[j]); + if (nUnique != -1) + { + elements->push_back(nUnique); + + // Update last face info + tLastFace.m_v0 = tLastFace.m_v1; + tLastFace.m_v1 = tLastFace.m_v2; + tLastFace.m_v2 = nUnique; + } + } + } - } - - for (i = 0; i < leftoverFaces.size(); ++i) - { - - *(lensPtr++) = 3; - - *(osg_indicesPtr++) = leftoverFaces[i]->m_v0; - *(osg_indicesPtr++) = leftoverFaces[i]->m_v1; - *(osg_indicesPtr++) = leftoverFaces[i]->m_v2; - - } - -} - - -void TriStripVisitor::stripify(GeoSet& gset) -{ - GeoSet::PrimitiveType primTypeIn = gset.getPrimType(); - GeoSet::PrimitiveType primTypeOut = gset.getPrimType(); - - // determine whether to do smoothing or not, and if - // the primitive type needs to be modified enable smoothed normals. - bool doStripify; - switch(primTypeIn) - { - case(GeoSet::QUADS): - case(GeoSet::QUAD_STRIP): - case(GeoSet::POLYGON): - case(GeoSet::TRIANGLES): - case(GeoSet::TRIANGLE_STRIP): - case(GeoSet::TRIANGLE_FAN): - primTypeOut = GeoSet::TRIANGLE_STRIP; - doStripify = true; - break; - case(GeoSet::FLAT_TRIANGLE_STRIP): - case(GeoSet::FLAT_TRIANGLE_FAN): -// comment out for time being since per vertex colors and normals need -// to take account of the osg::GeoSet::_flat_shaded_skip -// primTypeOut = GeoSet::FLAT_TRIANGLE_STRIP; -// doStripify = true; -// break; - default: // points and lines etc. - doStripify = false; - break; - } - - if (doStripify) - { - - TriangleAcumulatorFunctor tt(gset.getCoords()); - for_each_triangle( gset, tt ); - - if (!tt.in_indices.empty()) + if (leftoverFaces.size()) { - int in_numVertices = -1; - for(WordVec::iterator itr=tt.in_indices.begin(); - itr!=tt.in_indices.end(); - ++itr) + + osg::UShortDrawElements* triangles = osgNew osg::UShortDrawElements(osg::Primitive::TRIANGLES); + triangles->reserve(leftoverFaces.size()*3); + new_primitives.push_back(triangles); + + for (i = 0; i < leftoverFaces.size(); ++i) { - if (*itr>in_numVertices) in_numVertices=*itr; + + triangles->push_back(leftoverFaces[i]->m_v0); + triangles->push_back(leftoverFaces[i]->m_v1); + triangles->push_back(leftoverFaces[i]->m_v2); } - // the largest indice is in_numVertices, but indices start at 0 - // so increment to give to the corrent number of verticies. - ++in_numVertices; - - int in_cacheSize = 16; - int in_minStripLength = 1; - NvStripInfoVec strips; - NvFaceInfoVec leftoverFaces; - - NvStripifier stripifier; - stripifier.Stripify(tt.in_indices, - in_numVertices, - in_cacheSize, - in_minStripLength, - strips, - leftoverFaces); - - int noPrims; - int *lens; - osg::ushort* osg_indices; - - createStrips(strips,leftoverFaces,noPrims,&lens,&osg_indices); - - if (primTypeIn!=primTypeOut) - gset.setPrimType( primTypeOut ); - - gset.setPrimLengths(lens); - gset.setNumPrims(noPrims); - - gset.setCoords(gset.getCoords(),osg_indices); - - if (gset.getTextureCoords()) - { - switch(gset.getTextureBinding()) - { - case(GeoSet::BIND_OVERALL): - // leave as before - break; - case(GeoSet::BIND_PERPRIM): - // switch off tex coords.. - gset.setTextureBinding(GeoSet::BIND_OFF); - gset.setTextureCoords(NULL); - break; - case(GeoSet::BIND_PERVERTEX): - // set up the indexing. - gset.setTextureCoords(gset.getTextureCoords(),osg_indices); - break; - case(GeoSet::BIND_OFF): - case(GeoSet::BIND_DEFAULT): - // switch off tex coords.. - gset.setTextureCoords(NULL); - break; - } - } - - if (gset.getColors()) - { - switch(gset.getColorBinding()) - { - case(GeoSet::BIND_OVERALL): - // leave as before - break; - case(GeoSet::BIND_PERPRIM): - // switch off colors.. - gset.setColorBinding(GeoSet::BIND_OFF); - gset.setColors(NULL); - break; - case(GeoSet::BIND_PERVERTEX): - // set up the indexing. - gset.setColors(gset.getColors(),osg_indices); - break; - case(GeoSet::BIND_OFF): - case(GeoSet::BIND_DEFAULT): - // switch off colors.. - gset.setColors(NULL); - break; - } - } - - if (gset.getNormals()) - { - switch(gset.getNormalBinding()) - { - case(GeoSet::BIND_OVERALL): - // leave as before - break; - case(GeoSet::BIND_PERPRIM): - // switch off normals.. - gset.setNormalBinding(GeoSet::BIND_OFF); - gset.setNormals(NULL); - break; - case(GeoSet::BIND_PERVERTEX): - // set up the indexing. - gset.setNormals(gset.getNormals(),osg_indices); - break; - case(GeoSet::BIND_OFF): - case(GeoSet::BIND_DEFAULT): - // switch off normals.. - gset.setNormals(NULL); - break; - } - } - gset.computeNumVerts(); - gset.dirtyDisplayList(); - gset.dirtyBound(); } - else - { - notify(INFO) << "No triangles to stripify"<< std::endl; - } - + geom.setPrimitiveList(new_primitives); } } @@ -306,7 +208,7 @@ void TriStripVisitor::apply(Geode& geode) { for(int i = 0; i < geode.getNumDrawables(); ++i ) { - osg::GeoSet* gset = dynamic_cast(geode.getDrawable(i)); - if (gset) stripify(*gset); + osg::Geometry* geom = dynamic_cast(geode.getDrawable(i)); + if (geom) stripify(*geom); } }