From f2e215bf44f98dcb89757ce8d7189fbb60196192 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 23 Jun 2002 21:43:46 +0000 Subject: [PATCH] Added conversion to osg::GeoSet::converToGeometry() utility to help the migration to and testing of the new osg::Geometry class. --- include/osg/GeoSet | 7 + include/osg/Geometry | 74 ++-- include/osg/Texture | 2 +- include/osg/ref_ptr | 6 + include/osgUtil/Optimizer | 124 ++++++- src/Demos/osggeometry/osggeometry.cpp | 16 +- src/osg/GeoSet.cpp | 367 ++++++++++++++++++++ src/osg/Geometry.cpp | 28 +- src/osgUtil/Optimizer.cpp | 474 ++++++++++++++++++++++++-- src/osgUtil/Tesselator.cpp | 12 +- 10 files changed, 1022 insertions(+), 88 deletions(-) diff --git a/include/osg/GeoSet b/include/osg/GeoSet index 5a21a9258..c24e04fb9 100644 --- a/include/osg/GeoSet +++ b/include/osg/GeoSet @@ -12,6 +12,10 @@ namespace osg { + +// forward declare so that we don't need to include the header. +class Geometry; + /** Encapsulates OpenGL drawing primitives, geometry and optional binding of normal, color and texture coordinates. Used for representing the visible objects in the scene. State attributes @@ -334,6 +338,9 @@ class SG_EXPORT GeoSet : public Drawable virtual AttributeBitMask applyAttributeOperation(AttributeFunctor& auf); + /** convinience function for converting GeoSet's to equivilant Geometry nodes.*/ + Geometry* convertToGeometry(); + protected: diff --git a/include/osg/Geometry b/include/osg/Geometry index c60b2768a..81c8fdaec 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -88,8 +88,18 @@ class TemplateArray : public AttributeArray, public std::vector TemplateArray() : AttributeArray(ARRAYTYPE,DataSize,DataType) {} - TemplateArray(const TemplateArray& ta,const CopyOp& copyop=CopyOp::SHALLOW_COPY) : AttributeArray(ta,copyop), std::vector(ta) {} + TemplateArray(const TemplateArray& ta,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + AttributeArray(ta,copyop), + std::vector(ta) {} + TemplateArray(unsigned int no,T* ptr) : + AttributeArray(ARRAYTYPE,DataSize,DataType), + std::vector(ptr,ptr+no) {} + + TemplateArray(T* first,T* last) : + AttributeArray(ARRAYTYPE,DataSize,DataType), + std::vector(first,last) {} + virtual Object* cloneType() const { return osgNew TemplateArray(); } virtual Object* clone(const CopyOp& copyop) const { return osgNew TemplateArray(*this,copyop); } virtual const char* libraryName() const { return "osg"; } @@ -115,7 +125,7 @@ typedef TemplateArray Vec4Ar enum PrimitiveType { PrimitivePrimitiveType = 0, - DrawArrayPrimitiveType = 1, + DrawArraysPrimitiveType = 1, UByteDrawElementsPrimitiveType = 2, UShortDrawElementsPrimitiveType = 3, UIntDrawElementsPrimitiveType = 4, @@ -124,7 +134,7 @@ enum PrimitiveType static char* s_PrimitiveNames[] = { "Primitive", // 0 - "DrawArray", // 1 + "DrawArrays", // 1 "UByteDrawElements", // 2 "UShortDrawElements", // 3 "UIntDrawElements" // 4 @@ -164,31 +174,31 @@ class Primitive : public Object PrimitiveType _primitiveType; }; -class DrawArray : public Primitive +class DrawArrays : public Primitive { public: - DrawArray(): - Primitive(DrawArrayPrimitiveType) + DrawArrays(): + Primitive(DrawArraysPrimitiveType) {} - DrawArray(GLenum mode, GLint first, GLsizei count): - Primitive(DrawArrayPrimitiveType), + DrawArrays(GLenum mode, GLint first, GLsizei count): + Primitive(DrawArraysPrimitiveType), _mode(mode), _first(first), _count(count) {} - DrawArray(const DrawArray& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + DrawArrays(const DrawArrays& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Primitive(da,copyop), _mode(da._mode), _first(da._first), _count(da._count) {} - virtual Object* cloneType() const { return osgNew DrawArray(); } - virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawArray(*this,copyop); } - virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } + virtual Object* cloneType() const { return osgNew DrawArrays(); } + virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawArrays(*this,copyop); } + virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } - virtual const char* className() const { return "DrawArray"; } + virtual const char* className() const { return "DrawArrays"; } virtual void draw() const { @@ -200,15 +210,33 @@ class DrawArray : public Primitive GLsizei _count; }; -template +template class DrawElements : public Primitive, public std::vector { public: - DrawElements():Primitive(PRIMTYPE),_dataType(_dataType) {} + DrawElements(GLenum mode=0): + Primitive(PRIMTYPE), + _mode(mode), + _dataType(DataType) {} DrawElements(const DrawElements& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): - Primitive(array,copyop) {} + Primitive(array,copyop), + std::vector(array), + _mode(array._mode), + _dataType(array._dataType) {} + + DrawElements(GLenum mode,unsigned int no,T* ptr) : + Primitive(PRIMTYPE), + std::vector(ptr,ptr+no), + _mode(mode), + _dataType(DataType) {} + + DrawElements(GLenum mode, T* first,T* last) : + Primitive(PRIMTYPE), + 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); } @@ -252,10 +280,10 @@ class SG_EXPORT Geometry : public Drawable enum AttributeBinding { - OFF=0, - OVERALL, - PER_PRIMITIVE, - PER_VERTEX, + BIND_OFF=0, + BIND_OVERALL, + BIND_PER_PRIMITIVE, + BIND_PER_VERTEX, }; void setVertexArray(Vec3Array* array) { _vertexArray = array; } @@ -266,7 +294,7 @@ class SG_EXPORT Geometry : public Drawable void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; } AttributeBinding getNormalBinding() const { return _normalBinding; } - void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=OFF; } + void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; } Vec3Array* getNormalArray() { return _normalArray.get(); } const Vec3Array* getNormalArray() const { return _normalArray.get(); } @@ -274,7 +302,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=OFF; } + void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; } AttributeArray* getColorArray() { return _colorArray.get(); } const AttributeArray* getColorArray() const { return _colorArray.get(); } @@ -292,7 +320,7 @@ class SG_EXPORT Geometry : public Drawable PrimitiveList& getPrimitiveList() { return _primitives; } const PrimitiveList& getPrimitiveList() const { return _primitives; } - void addPrimtive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); } + void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); } diff --git a/include/osg/Texture b/include/osg/Texture index 3377ae131..39b79a7a0 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -274,7 +274,7 @@ class SG_EXPORT Texture : public StateAttribute { // pad out handle list if required. if (_handleList.size()<=contextID) - _handleList.resize(contextID,0); + _handleList.resize(contextID+1,0); // get the globj for the current contextID. return _handleList[contextID]; diff --git a/include/osg/ref_ptr b/include/osg/ref_ptr index 6b8d62ab0..b0aabb2ec 100644 --- a/include/osg/ref_ptr +++ b/include/osg/ref_ptr @@ -95,6 +95,12 @@ class ref_ptr inline const T* get() const { return _ptr; } + /** take control over the object pointed to by ref_ptr, unreference but do not delete even if ref count goes to 0, + * return the pointer to the object. + * Note, do not use this unless you are 100% sure your code handles the deletion of the object correctly, and + * only use when absolutely required.*/ + inline T* take() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp;} + private: T* _ptr; }; diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index 0777e572a..86bcb632d 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -42,7 +42,19 @@ class OSGUTIL_EXPORT Optimizer virtual void optimize(osg::Node* node, unsigned int options = ALL_OPTIMIZATIONS); - + /** ConvertGeoSetsToGeometryVisitor all the old GeoSet Drawables to the new Geometry Drawables.*/ + class OSGUTIL_EXPORT ConvertGeoSetsToGeometryVisitor : public osg::NodeVisitor + { + public: + + ConvertGeoSetsToGeometryVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Geode& geode); + virtual void apply(osg::Node& node) { traverse(node); } + + }; + + /** Flatten Static Trasform nodes by applying their transform to the * geometry on the leaves of the scene graph, then removing the * now redundent transforms.*/ @@ -133,6 +145,113 @@ class OSGUTIL_EXPORT Optimizer }; + /** Remove the lowest static transforms in the scene.*/ + class OSGUTIL_EXPORT RemoveLowestStaticTransformsVisitor : public osg::NodeVisitor + { + public: + + + + RemoveLowestStaticTransformsVisitor(bool ignoreDynamicTransforms=true): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _ignoreDynamicTransforms(ignoreDynamicTransforms) {} + + virtual void apply(osg::Geode& geode); + virtual void apply(osg::Billboard& billboard); + virtual void apply(osg::LOD& lod); + virtual void apply(osg::Transform& transform); + + bool removeTransforms(); + + + typedef std::vector TransformStack; + typedef std::vector MatrixStack; + + protected: + + struct TransformStruct + { + typedef std::set ObjectSet; + + TransformStruct():_containsTransform(false),_canBeApplied(true) {} + + void add(osg::Object* obj) { _objectSet.insert(obj); } + + bool _containsTransform; + bool _canBeApplied; + ObjectSet _objectSet; + }; + + struct ObjectStruct + { + typedef std::set TransformSet; + + ObjectStruct():_canBeApplied(true),_matrixSet(false),_moreThanOneMatrixRequired(false) {} + + void add(osg::Transform* transform,osg::Matrix& matrix) + { + _transformSet.insert(transform); + if (!_matrixSet) + { + _matrixSet = true; + _moreThanOneMatrixRequired = false; + _matrix = matrix; + } + else if (_matrix!=matrix) + { + _moreThanOneMatrixRequired = true; + } + + } + + bool _canBeApplied; + bool _matrixSet; + bool _moreThanOneMatrixRequired; + osg::Matrix _matrix; + TransformSet _transformSet; + + }; + + typedef std::map TransformMap; + typedef std::map ObjectMap; + + void disableObject(osg::Object* object) + { + disableObject(_objectMap.find(object)); + } + + void disableObject(ObjectMap::iterator itr); + void disableTransform(osg::Transform* transform); + void doTransform(osg::Object* obj,osg::Matrix& matrix); + + bool _ignoreDynamicTransforms; + MatrixStack _matrixStack; + TransformStack _transformStack; + + TransformMap _transformMap; + ObjectMap _objectMap; + + + }; + + /** Remove rendundent nodes, such as groups with one single child.*/ + class OSGUTIL_EXPORT RemoveEmptyNodesVisitor : public osg::NodeVisitor + { + public: + + + typedef std::set NodeList; + NodeList _redundentNodeList; + + RemoveEmptyNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Geode& geode); + virtual void apply(osg::Group& group); + + void removeEmptyNodes(); + + }; + /** Remove rendundent nodes, such as groups with one single child.*/ class OSGUTIL_EXPORT RemoveRedundentNodesVisitor : public osg::NodeVisitor { @@ -142,8 +261,9 @@ class OSGUTIL_EXPORT Optimizer NodeList _redundentNodeList; RemoveRedundentNodesVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} - + virtual void apply(osg::Group& group); + virtual void apply(osg::Transform& transform); void removeRedundentNodes(); diff --git a/src/Demos/osggeometry/osggeometry.cpp b/src/Demos/osggeometry/osggeometry.cpp index 67cbdec62..fe1548166 100644 --- a/src/Demos/osggeometry/osggeometry.cpp +++ b/src/Demos/osggeometry/osggeometry.cpp @@ -13,7 +13,7 @@ #include // ---------------------------------------------------------------------- -// Global variables - this is basically the stuff which will be animated +// Global variables - this is basically the stuff wh ich will be animated // ---------------------------------------------------------------------- @@ -186,12 +186,12 @@ osg::Geode* createGeometryCube() // set up the primitives - cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,0,4)); - cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,4,4)); - cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,8,4)); - cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,12,4)); - cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,16,4)); - cube->addPrimtive(new osg::DrawArray(osg::Primitive::POLYGON,20,4)); + 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 coords. @@ -244,7 +244,7 @@ osg::Geode* createGeometryCube() (*cubeNormals)[5].set(0.0f,-1.0f,0.0f); cube->setNormalArray( cubeNormals ); - cube->setNormalBinding( osg::Geometry::PER_PRIMITIVE ); + cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE ); // --------------------------------------- // Set up a StateSet to make the cube red diff --git a/src/osg/GeoSet.cpp b/src/osg/GeoSet.cpp index e8e1335a4..0cd0fb020 100644 --- a/src/osg/GeoSet.cpp +++ b/src/osg/GeoSet.cpp @@ -9,6 +9,9 @@ #include #include +#include +#include + //#include using namespace osg; @@ -975,3 +978,367 @@ bool GeoSet::getStats(Statistics &stat) stat.addNumPrims(type, nprimlens, numprimtypes, primverts); return true; } + + + + +Geometry* GeoSet::convertToGeometry() +{ + set_fast_path(); + computeNumVerts(); + + ref_ptr geom = osgNew Geometry; + geom->setStateSet(getStateSet()); + + if (_flat_shaded_skip) + { + // will need to add flat shading to primitive. + + StateSet* stateset = geom->getStateSet(); + if (!stateset) + { + stateset = osgNew StateSet; + geom->setStateSet(stateset); + } + ShadeModel* shademodel = dynamic_cast(stateset->getAttribute(StateAttribute::SHADEMODEL)); + if (!shademodel) + { + shademodel = osgNew osg::ShadeModel; + stateset->setAttribute(shademodel,StateAttribute::OVERRIDE); + } + + shademodel->setMode( ShadeModel::FLAT ); + } + + switch(_normal_binding) + { + case(BIND_OFF): + geom->setNormalBinding(Geometry::BIND_OFF); + break; + case(BIND_OVERALL): + geom->setNormalBinding(Geometry::BIND_OVERALL); + break; + case(BIND_PERPRIM): + geom->setNormalBinding(Geometry::BIND_PER_PRIMITIVE); + break; + case(BIND_PERVERTEX): + geom->setNormalBinding(Geometry::BIND_PER_VERTEX); + break; + default: + geom->setNormalBinding(Geometry::BIND_OFF); + break; + } + + switch(_color_binding) + { + case(BIND_OFF): + geom->setColorBinding(Geometry::BIND_OFF); + break; + case(BIND_OVERALL): + geom->setColorBinding(Geometry::BIND_OVERALL); + break; + case(BIND_PERPRIM): + geom->setColorBinding(Geometry::BIND_PER_PRIMITIVE); + break; + case(BIND_PERVERTEX): + geom->setColorBinding(Geometry::BIND_PER_VERTEX); + break; + default: + geom->setColorBinding(Geometry::BIND_OFF); + break; + } + + + if (_fast_path) + { + // will easily convert into a Geometry. + + if (_coords) geom->setVertexArray(osgNew Vec3Array(_numcoords,_coords)); + + if (_normals) geom->setNormalArray(osgNew Vec3Array(_numnormals,_normals)); + + if (_colors) geom->setColorArray(osgNew Vec4Array(_numcolors,_colors)); + + if (_tcoords) geom->setTexCoordArray(0,osgNew Vec2Array(_numtcoords,_tcoords)); + + if( _needprimlen ) // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP, + // TRIANGLE_FAN, QUAD_STRIP, POLYGONS + { + int index = 0; + if( _primLengths == (int *)0 ) + { + return 0; + } + + for( int i = 0; i < _numprims; i++ ) + { + if( _cindex.valid() ) + { + UShortDrawElements* n = new UShortDrawElements; + geom->addPrimitive(n); + + if (_cindex._is_ushort) + geom->addPrimitive(osgNew UShortDrawElements( (GLenum)_oglprimtype, _primLengths[i],&_cindex._ptr._ushort[index] )); + else + geom->addPrimitive(osgNew UIntDrawElements( (GLenum)_oglprimtype, _primLengths[i], &_cindex._ptr._uint[index] )); + } + else + geom->addPrimitive(osgNew DrawArrays( (GLenum)_oglprimtype, index, _primLengths[i] )); + + index += _primLengths[i]; + } + } + else // POINTS, LINES, TRIANGLES, QUADS + { + if( _cindex.valid()) + { + if (_cindex._is_ushort) + geom->addPrimitive(osgNew UShortDrawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._ushort )); + else + geom->addPrimitive(osgNew UIntDrawElements( (GLenum)_oglprimtype, _cindex._size, _cindex._ptr._uint )); + } + else + geom->addPrimitive(new DrawArrays( (GLenum)_oglprimtype, 0, _numcoords )); + } + + + } + else if( _needprimlen ) + { + // slow path, and needing handling of primlen array. + // + // LINE_STRIP, LINE_LOOP, TRIANGLE_STRIP, + // TRIANGLE_FAN, QUAD_STRIP, POLYGONS + // FLAT_LINE_STRIP, FLAT_TRIANGLE_STRIP, FLAT_TRIANGLE_FAN + + int i, j; + int index = 0; + int ai = 0; + int ci = 0; + int ni = 0; + int ti = 0; + + if( _primLengths == (int *)0 ) + { + return 0; + } + + + Vec3Array* coords = osgNew Vec3Array; + Vec3Array* normals = 0; + Vec4Array* colors = 0; + Vec2Array* texcoords = 0; + + if (_colors) colors = osgNew Vec4Array; + if (_normals) normals = osgNew Vec3Array; + if (_tcoords) texcoords = osgNew Vec2Array; + + geom->setVertexArray(coords); + geom->setColorArray(colors); + geom->setNormalArray(normals); + geom->setTexCoordArray(0,texcoords); + + if (_color_binding == BIND_OVERALL) + { + if( _colindex.valid() ) + colors->push_back( _colors[_colindex[0]] ); + else + colors->push_back( _colors[0] ); + } + + if (_normal_binding == BIND_OVERALL) + { + if( _nindex.valid() ) + normals->push_back( _normals[0] ); + else + normals->push_back( _normals[0] ); + } + + for( i = 0; i < _numprims; i++ ) + { + if (_color_binding == BIND_PERPRIM && colors) + { + if( _colindex.valid() ) + colors->push_back( _colors[_colindex[ci++]] ); + else + colors->push_back( _colors[ci++] ); + } + + if (_normal_binding == BIND_PERPRIM && normals) + { + if( _nindex.valid() ) + normals->push_back( _normals[_nindex[ni++]] ); + else + normals->push_back( _normals[ni++] ); + } + + unsigned int first = coords->size(); + unsigned int count = 0; + + + for( j = 0; j < _primLengths[i]; j++ ) + { + if( j >= _flat_shaded_skip ) + { + if( _color_binding == BIND_PERVERTEX && colors) + { + if( (_colindex.valid()) ) + colors->push_back( _colors[_colindex[ci++]] ); + else + colors->push_back( _colors[ci++] ); + } + + if( _normal_binding == BIND_PERVERTEX && normals) + { + if(_nindex.valid()) + normals->push_back( _normals[_nindex[ni++]] ); + else + normals->push_back( _normals[ni++] ); + } + } + else + { + // note don't increment ci & ni as we want to make multiple copies it when in _flat_shaded_skip + if( _color_binding == BIND_PERVERTEX && colors) + { + if( (_colindex.valid()) ) + colors->push_back( _colors[_colindex[ci]] ); + else + colors->push_back( _colors[ci] ); + } + + if( _normal_binding == BIND_PERVERTEX && normals ) + { + if(_nindex.valid()) + normals->push_back( _normals[_nindex[ni]] ); + else + normals->push_back( _normals[ni] ); + } + } + + if( _texture_binding == BIND_PERVERTEX && texcoords) + { + if( _tindex.valid() ) + texcoords->push_back( _tcoords[_tindex[ti++]] ); + else + texcoords->push_back( _tcoords[ti++] ); + } + + if( _cindex.valid() ) + coords->push_back( _coords[_cindex[ai++]] ); + else + coords->push_back( _coords[ai++] ); + + ++count; + + } + + geom->addPrimitive(osgNew DrawArrays(_oglprimtype,first,count)); + + index += _primLengths[i]; + } + + } + else + { + + Vec3Array* coords = osgNew Vec3Array; + Vec3Array* normals = 0; + Vec4Array* colors = 0; + Vec2Array* texcoords = 0; + + if (_colors) colors = osgNew Vec4Array; + if (_normals) normals = osgNew Vec3Array; + if (_tcoords) texcoords = osgNew Vec2Array; + + geom->setVertexArray(coords); + geom->setColorArray(colors); + geom->setNormalArray(normals); + geom->setTexCoordArray(0,texcoords); + + if (_color_binding == BIND_OVERALL) + { + if( _colindex.valid() ) + colors->push_back( _colors[_colindex[0]] ); + else + colors->push_back( _colors[0] ); + } + + if (_normal_binding == BIND_OVERALL) + { + if( _nindex.valid() ) + normals->push_back( _normals[_nindex[0]] ); + else + normals->push_back( _normals[0] ); + } + + for(int i = 0; i < _numprims; i++ ) + { + if (_color_binding == BIND_PERPRIM && colors) + { + if( _colindex.valid() ) + colors->push_back( _colors[_colindex[i]] ); + else + colors->push_back( _colors[i] ); + } + + if (_normal_binding == BIND_PERPRIM && normals) + { + if( _nindex.valid() ) + normals->push_back( _normals[_nindex[i]] ); + else + normals->push_back( _normals[i] ); + } + + unsigned int first = coords->size(); + unsigned int count = 0; + + for(int j = 0; j < _primlength; j++ ) + { + if( _color_binding == BIND_PERVERTEX && colors) + { + if( (_colindex.valid()) ) + colors->push_back( _colors[_colindex[i*_primlength+j]] ); + else + colors->push_back( _colors[i*_primlength+j] ); + } + + if( _normal_binding == BIND_PERVERTEX && normals ) + { + if(_nindex.valid()) + normals->push_back( _normals[_nindex[i*_primlength+j]] ); + else + normals->push_back( _normals[i*_primlength+j] ); + } + + if( _texture_binding == BIND_PERVERTEX && texcoords) + { + if( _tindex.valid() ) + texcoords->push_back( _tcoords[_tindex[i*_primlength+j]] ); + else + texcoords->push_back( _tcoords[i*_primlength+j] ); + } + + if( _cindex.valid() ) + coords->push_back( _coords[_cindex[i*_primlength+j]] ); + else + coords->push_back( _coords[i*_primlength+j] ); + + ++count; + } + + geom->addPrimitive(osgNew DrawArrays(_oglprimtype,first,count)); + + } + + } + + + return geom.take(); + + +} + + + + diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index fefbff593..8d13b1271 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -4,8 +4,8 @@ using namespace osg; Geometry::Geometry() { - _normalBinding = OFF; - _colorBinding = OFF; + _normalBinding = BIND_OFF; + _colorBinding = BIND_OFF; } Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop): @@ -70,17 +70,17 @@ void Geometry::drawImmediateMode(State& /*state*/) switch (_normalBinding) { - case(OFF): + case(BIND_OFF): glDisableClientState( GL_NORMAL_ARRAY ); break; - case(OVERALL): + case(BIND_OVERALL): + glDisableClientState( GL_NORMAL_ARRAY ); if (normalPointer) glNormal3fv(reinterpret_cast(normalPointer)); + break; + case(BIND_PER_PRIMITIVE): glDisableClientState( GL_NORMAL_ARRAY ); break; - case(PER_PRIMITIVE): - glDisableClientState( GL_NORMAL_ARRAY ); - break; - case(PER_VERTEX): + case(BIND_PER_VERTEX): glEnableClientState( GL_NORMAL_ARRAY ); if (normalPointer) glNormalPointer(GL_FLOAT,0,normalPointer); break; @@ -121,10 +121,10 @@ void Geometry::drawImmediateMode(State& /*state*/) switch (_colorBinding) { - case(OFF): + case(BIND_OFF): glDisableClientState( GL_COLOR_ARRAY ); break; - case(OVERALL): + case(BIND_OVERALL): glDisableClientState( GL_COLOR_ARRAY ); if (colorPointer) { @@ -142,10 +142,10 @@ void Geometry::drawImmediateMode(State& /*state*/) } } break; - case(PER_PRIMITIVE): + case(BIND_PER_PRIMITIVE): glDisableClientState( GL_COLOR_ARRAY ); break; - case(PER_VERTEX): + case(BIND_PER_VERTEX): glEnableClientState( GL_COLOR_ARRAY ); if (colorPointer) glColorPointer(_colorArray->dataSize(),_colorArray->dataType(),0,colorPointer); } @@ -156,12 +156,12 @@ void Geometry::drawImmediateMode(State& /*state*/) itr!=_primitives.end(); ++itr) { - if (_normalBinding==PER_PRIMITIVE) + if (_normalBinding==BIND_PER_PRIMITIVE) { glNormal3fv((const GLfloat *)normalPointer++); } - if (_colorBinding==PER_PRIMITIVE) + if (_colorBinding==BIND_PER_PRIMITIVE) { switch(colorType) { diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 399b29c33..76473958e 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -18,6 +20,7 @@ using namespace osgUtil; void Optimizer::optimize(osg::Node* node, unsigned int options) { + if (options & COMBINE_ADJACENT_LODS) { CombineLODsVisitor clv; @@ -30,15 +33,42 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) FlattenStaticTransformsVisitor fstv; node->accept(fstv); fstv.removeTransforms(); + +// the following RemoveLowestStaticTransformVisitor doesn't yet work +// properly, will need further work.... Robert Osfield, June 2002. +// int i=0; +// bool result = false; +// do +// { +// cout << "************ RemoveLowestStaticTransformsVisitor "<accept(fstv); +// result = fstv.removeTransforms(); +// ++i; +// } while (result); + + + } if (options & REMOVE_REDUNDENT_NODES) { + + RemoveEmptyNodesVisitor renv; + node->accept(renv); + renv.removeEmptyNodes(); + RemoveRedundentNodesVisitor rrnv; node->accept(rrnv); rrnv.removeRedundentNodes(); + } +// // convert the old style GeoSet to Geometry +// ConvertGeoSetsToGeometryVisitor cgtg; +// node->accept(cgtg); + + if (options & SHARE_DUPLICATE_STATE) { #if (defined(_MSC_VER) && _MSC_VER<1300 && !defined(_STLPORT_VERSION)) @@ -50,6 +80,9 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) #endif } + + + } class TransformFunctor : public osg::Drawable::AttributeFunctor @@ -94,6 +127,34 @@ class TransformFunctor : public osg::Drawable::AttributeFunctor }; +//////////////////////////////////////////////////////////////////////////// +// Convert GeoSet To Geometry Visitor. +//////////////////////////////////////////////////////////////////////////// + +void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode) +{ + for(int i=0;i(geode.getDrawable(i)); + if (geoset) + { + osg::Geometry* geom = geoset->convertToGeometry(); + if (geom) + { + std::cout<<"Successfully converted GeoSet to Geometry"<second._canBeApplied) + { + // we havn't been disabled yet so we need to disable, + itr->second._canBeApplied = false; + + // and then inform everybody we have been disabled. + for(ObjectStruct::TransformSet::iterator titr = itr->second._transformSet.begin(); + titr != itr->second._transformSet.end(); + ++titr) + { + disableTransform(*titr); + } + } +} + +void Optimizer::RemoveLowestStaticTransformsVisitor::disableTransform(osg::Transform* transform) +{ + TransformMap::iterator itr=_transformMap.find(transform); + if (itr==_transformMap.end()) + { + // Euston we have a problem.. + osg::notify(osg::WARN)<<"Warning: internal error Optimizer::RemoveLowestStaticTransformsVisitor::disableTransform()"<second._canBeApplied) + { + + // we havn't been disabled yet so we need to disable, + itr->second._canBeApplied = false; + // and then inform everybody we have been disabled. + for(TransformStruct::ObjectSet::iterator oitr = itr->second._objectSet.begin(); + oitr != itr->second._objectSet.end(); + ++oitr) + { + disableObject(*oitr); + } + } +} + +bool Optimizer::RemoveLowestStaticTransformsVisitor::removeTransforms() +{ + + // create the TransformMap from the ObjectMap + ObjectMap::iterator oitr; + for(oitr=_objectMap.begin(); + oitr!=_objectMap.end(); + ++oitr) + { + osg::Object* object = oitr->first; + ObjectStruct& os = oitr->second; + + for(ObjectStruct::TransformSet::iterator titr = os._transformSet.begin(); + titr != os._transformSet.end(); + ++titr) + { + _transformMap[*titr].add(object); + } + } + + + for(TransformMap::iterator titr=_transformMap.begin(); + titr!=_transformMap.end(); + ++titr) + { + TransformStruct& ts = titr->second; + if (ts._containsTransform) + { + disableTransform(titr->first); + } + } + + // disable all the objects which have more than one matrix associated + // with them, and then disable all transforms which have an object associated + // them that can't be applied, and then disable all objects which have + // disabled transforms associated, recursing until all disabled + // associativity. + for(oitr=_objectMap.begin(); + oitr!=_objectMap.end(); + ++oitr) + { + ObjectStruct& os = oitr->second; + if (os._canBeApplied) + { + if (os._moreThanOneMatrixRequired) + { + disableObject(oitr); + } + } + } + + + // transform the objects that can be applied. + for(oitr=_objectMap.begin(); + oitr!=_objectMap.end(); + ++oitr) + { + osg::Object* object = oitr->first; + ObjectStruct& os = oitr->second; + if (os._canBeApplied) + { + doTransform(object,os._matrix); + } + } + + + bool transformsRemoved = false; + + // clean up the transforms. + for(TransformMap::iterator titr=_transformMap.begin(); + titr!=_transformMap.end(); + ++titr) + { + if (titr->second._canBeApplied && titr->first) + { + osg::ref_ptr transform = titr->first; + osg::ref_ptr group = osgNew osg::Group; + group->setDataVariance(osg::Object::STATIC); + for(unsigned int i=0;igetNumChildren();++i) + { + for(unsigned int j=0;jgetNumParents();++j) + { + group->addChild(transform->getChild(i)); + } + } + + for(int i2=transform->getNumParents()-1;i2>=0;--i2) + { + transform->getParent(i2)->replaceChild(transform.get(),group.get()); + } + transformsRemoved = true; + } + } + _objectMap.clear(); + _transformMap.clear(); + _transformStack.clear(); + _matrixStack.clear(); + + return transformsRemoved; +} + + +//////////////////////////////////////////////////////////////////////////// +// RemoveEmptyNodes. +//////////////////////////////////////////////////////////////////////////// + +void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Geode& geode) +{ + if (geode.getNumParents()>0) + { + if (geode.getNumDrawables()==0) _redundentNodeList.insert(&geode); + } +} + +void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group) +{ + if (group.getNumParents()>0) + { + if (group.getNumChildren()==0) + { + _redundentNodeList.insert(&group); + } + } + traverse(group); +} + +void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes() +{ + + NodeList newEmptyGroups; + + // keep iterator through until scene graph is cleaned of empty nodes. + while (!_redundentNodeList.empty()) + { + for(NodeList::iterator itr=_redundentNodeList.begin(); + itr!=_redundentNodeList.end(); + ++itr) + { + + osg::Node* nodeToRemove = (*itr); + + // take a copy of parents list since subsequent removes will modify the original one. + osg::Node::ParentList parents = nodeToRemove->getParents(); + + for(osg::Node::ParentList::iterator pitr=parents.begin(); + pitr!=parents.end(); + ++pitr) + { + (*pitr)->removeChild(nodeToRemove); + if ((*pitr)->getNumChildren()==0) newEmptyGroups.insert(*pitr); + } + } + + _redundentNodeList.clear(); + _redundentNodeList.swap(newEmptyGroups); + } +} + //////////////////////////////////////////////////////////////////////////// // RemoveRedundentNodes. @@ -555,24 +954,42 @@ void Optimizer::FlattenStaticTransformsVisitor::removeTransforms() void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Group& group) { - if (typeid(group)==typeid(osg::Group)) + if (group.getNumParents()>0) { - if (group.getNumParents()>0 && group.getNumChildren()<=1) + if (group.getNumChildren()==1 && typeid(group)==typeid(osg::Group)) { - if (!group.getUserData() && - !group.getAppCallback() && - !group.getStateSet() && - group.getNodeMask()==0xffffffff) + if (group.getNumParents()>0 && group.getNumChildren()<=1) { - _redundentNodeList.insert(&group); + if (!group.getUserData() && + !group.getAppCallback() && + !group.getStateSet() && + group.getNodeMask()==0xffffffff) + { + _redundentNodeList.insert(&group); + } } } } traverse(group); } +void Optimizer::RemoveRedundentNodesVisitor::apply(osg::Transform& transform) +{ + if (transform.getNumParents()>0) + { + static osg::Matrix identity; + if (transform.getMatrix()==identity && transform.getDataVariance()==osg::Object::STATIC) + { + _redundentNodeList.insert(&transform); + } + } + traverse(transform); +} + + void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes() { + for(NodeList::iterator itr=_redundentNodeList.begin(); itr!=_redundentNodeList.end(); ++itr) @@ -582,17 +999,8 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes() { // take a copy of parents list since subsequent removes will modify the original one. osg::Node::ParentList parents = group->getParents(); - - if (group->getNumChildren()==0) - { - for(osg::Node::ParentList::iterator pitr=parents.begin(); - pitr!=parents.end(); - ++pitr) - { - (*pitr)->removeChild(group.get()); - } - } - else if (group->getNumChildren()==1) + + if (group->getNumChildren()==1) { osg::Node* child = group->getChild(0); for(osg::Node::ParentList::iterator pitr=parents.begin(); @@ -601,14 +1009,13 @@ void Optimizer::RemoveRedundentNodesVisitor::removeRedundentNodes() { (*pitr)->replaceChild(group.get(),child); } - + } - else // (group->getNumChildren()>1) - { - osg::notify(osg::WARN)<<"Warning: Optimizer::RemoveRedundentNodesVisitor has incorrectly assigned Group to remove."<=0;--i) { - for(int i=numIndices-1;i>=0;--i) - { _coordVec.push_back(VertexIndexSet(this,coords[indices[i]],indices[i])); } - } + } do_it(); }