From 09bdb10af51a1d2793a18393d50996c273199d60 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 18 Jul 2002 00:53:03 +0000 Subject: [PATCH] Various fixes to the flt loader, and knock on changes to the osgUtil::Optimizer to better support removal of seperate osg::Geometry instances where they share the same state and bindings. --- doc/install.html | 117 +++++++++-------- include/osg/Array | 10 +- include/osg/Geode | 6 +- include/osg/Geometry | 4 + include/osg/Primitive | 11 ++ include/osgUtil/AppVisitor | 2 +- include/osgUtil/Optimizer | 16 +++ src/Demos/osgcallback/osgcallback.cpp | 2 +- src/osg/Geometry.cpp | 164 ++++++++++++++++++++++- src/osg/Primitive.cpp | 29 +++++ src/osgPlugins/flt/GeoSetBuilder.cpp | 130 ++++++------------- src/osgPlugins/flt/GeoSetBuilder.h | 81 ++++++++---- src/osgPlugins/flt/flt2osg.cpp | 84 ++++++------ src/osgUtil/CullVisitor.cpp | 4 +- src/osgUtil/Optimizer.cpp | 179 +++++++++++++++++++++++++- 15 files changed, 609 insertions(+), 230 deletions(-) diff --git a/doc/install.html b/doc/install.html index 6cd19f6c1..813a923c3 100644 --- a/doc/install.html +++ b/doc/install.html @@ -274,66 +274,73 @@ To get full details of make options, type:

-Compiling under MacOS X (instructions written -by Phil Atkin)

-For anyone who's ever used a Unix box for development it really is so simple -it's insane. -

You need to have installed the Developer tools from the CD that comes +Compiling under MacOS X +For anyone who's ever used a Unix box for development, well, the mac +is a Unix box. It's very simple to get OpenSceneGraph building +and running under Mac OS X. The main requirement is that you need to have +installed the Developer tools from the CD that comes for free with OS X. This gives you compilers, headers, frameworks - stuff -like GLUT and Carbon for developers. -

Everything is done command-line, so you need to get to the underlying -OS rather than the Aqua gloss. The Mac comes with an app in Applications/Utilities +like GLUT and Carbon for developers. Get those here: + +

+ +

Everything is done command-line, so you need to get to a shell before +proceeding. The Mac comes with an app in Applications/Utilities called Terminal - open up any Finder window (e.g double-click on your hard disk icon), click on the Applications icon at the top right of the window, -then click on the Utilities folder to get access to all the grubby apps -which give away the real OS roots underneath the shiny paint work. Anyone -developing will need Terminal so much they should put it in their Dock. -You do that by grabbing the icon of the app in the Utilities folder and -dragging it to the bottom of your screen, at which point the other app -icons in the Dock slide away to leave a gap which when you release the -mouse button leaves Terminal permanently available, just a mouse click -away on your desktop. When you start Terminal it brings you up a csh running -under Darwin (which is the BSD-with-knobs-on that underlies OS X), and -does a cd to ~ (otherwise /Users/username of whoever you are logged in -as, as far as the Finder in OS X is concerned you are in the Users/username -folder of the harddisk the machine booted from). -

Then you are in Unix land, and it's all very familiar. -

You will need a .cshrc file with $OSGHOME (as above), and this is a -filename that the Mac won't let you see from the Finder or in fact generate -from an app, so I used vi to create that. Then I just went -

cd $OSGHOME -

% make clean -
% make macosx
+then click on the Utilities folder to get access to the Terminal. +When you start Terminal it brings you up a csh running from your ~/ directory. +Now, go to your OpenSceneGraph directory, and simply type: +

+

+make -j2 +
-


And it sounds too good to be true but it is that simple. It's worth -doing some editing on the Makefiles in the Plugins and Demos directories -so that it only tries to build a subset, otherwise the developer will have -to dig out the support projects like jpeg etc. I have only built up to -now sgv, hangglide, osgcube, osgreflect, osgviews and in the Plugins have -built osg rgb 3ds and a couple others - will check and get back to you. -

Tricky bit : -

Installing the libdl.a is more trouble, as you have to enable the root -account on the machine, which by default is switched off as the machines -ship for security reasons. Rather than typing in and risking error through -paraphrase, here is a link to a site which tells you how to do this - -

http://www.macos.utah.edu/Documentation/macosx/security/enablerootuser.html
-Or alternately, -
http://www.thinkmacintosh.com/osxfaq.html
+And some time later you'll be rewarded with a lovely set of binaries and +libraries. The Mac OSX build currently only builds a subset of the total +functionality in OpenSceneGraph, but a large subset at that. Some of +the remaining projects are known to build as well, but have external +dependencies on libraries such as libtiff, libjpg, libpng, etc. and +so are not included in the default build. However, if you examine +the file OpenSceneGraph/Make/makedefs you will find which extra +projects build for the mac, provided you have the external libraries +required. Details +on how to install these external libraries are outside the scope of +this document, but for starting points, see one of: + +

Running the examples

+Once you've got OpenSceneGraph built, you're ready to run your examples. +As with other builds on other platforms, OpenSceneGraph requires +you to set a few environment variables which describe your installation. These +environment variables should be full-path, not relative, and a list +of these for a csh-derived environment follow: + +
+ +setenv OSGHOME `pwd`/OpenSceneGraph
+setenv OSGFILEPATH `pwd`/OpenSceneGraph-Data
+setenv OSG_LD_LIBRARY_PATH ${OSGHOME}/lib
+setenv DYLD_LIBRARY_PATH ${OSG_LD_LIBRARY_PATH}
+
+
+ +

Notes

+ + -


One you have a root account enabled, you have to su root you cd -to the directory which the Fink installer generates, and it puts libdl.a -and the associated .h files in sensible system places so the compiler just -finds them. -

There is one oddball problem - if you rely on Path to find the resulting -executables, a weird Core Graphics error occurs - so even though I set -up my path to include $(OSGHOME)/bin, and when I cd to $OSGHOME and type -for example hangglide, the application starts fine (so it is in the path), -but at the point it tries to use GLUT to open a window it falls over with -a CGS error (which is I think Core Graphics System). If you explicitly -go bin/hangglide it works fine. Weird, it may be an OS X 10.04 issue which -is gone in 10.1 or it may be a weirdy in the Mac GLUT implementation, but -forewarned is forearmed.  -


Compiling under Cygwin

To compile, from the OSG root directory, type: make Note, make should automatically diff --git a/include/osg/Array b/include/osg/Array index d90f69776..160305682 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -58,9 +58,10 @@ class SG_EXPORT Array : public Object Type getType() const { return _arrayType; } - GLint dataSize() const { return _dataSize; } - GLenum dataType() const { return _dataType; } - virtual const GLvoid* dataPointer() const = 0; + GLint getDataSize() const { return _dataSize; } + GLenum getDataType() const { return _dataType; } + virtual const GLvoid* getDataPointer() const = 0; + virtual unsigned int getNumElements() const = 0; protected: @@ -101,7 +102,8 @@ class TemplateArray : public Array, public std::vector virtual Object* clone(const CopyOp& copyop) const { return osgNew TemplateArray(*this,copyop); } virtual void accept(ArrayVisitor& av) { av.apply(*this); } - virtual const GLvoid* dataPointer() const { if (!empty()) return &front(); else return 0; } + virtual const GLvoid* getDataPointer() const { if (!empty()) return &front(); else return 0; } + virtual unsigned int getNumElements() const { return size(); } protected: diff --git a/include/osg/Geode b/include/osg/Geode index dead4e21d..728f6ea85 100644 --- a/include/osg/Geode +++ b/include/osg/Geode @@ -54,13 +54,13 @@ class SG_EXPORT Geode : public Node /** return the number of geoset's.*/ - inline const int getNumDrawables() const { return _drawables.size(); } + inline const unsigned int getNumDrawables() const { return _drawables.size(); } /** return geoset at position i.*/ - inline Drawable* getDrawable( const int i ) { return _drawables[i].get(); } + inline Drawable* getDrawable( const unsigned int i ) { return _drawables[i].get(); } /** return geoset at position i.*/ - inline const Drawable* getDrawable( const int i ) const { return _drawables[i].get(); } + inline const Drawable* getDrawable( const unsigned int i ) const { return _drawables[i].get(); } /** return true if geoset is contained within Geode.*/ inline const bool containsDrawable(const Drawable* gset) const diff --git a/include/osg/Geometry b/include/osg/Geometry index 45cad8ca6..c8d4fbd81 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -80,6 +80,10 @@ class SG_EXPORT Geometry : public Drawable void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); dirtyDisplayList(); } + bool verifyBindings() const; + + void computeCorrectBindingsAndArraySizes(); + /** draw Geometry directly ignoring an OpenGL display list which could be attached. * This is the internal draw method which does the drawing itself, diff --git a/include/osg/Primitive b/include/osg/Primitive index ea52e475b..949b172f5 100644 --- a/include/osg/Primitive +++ b/include/osg/Primitive @@ -124,6 +124,8 @@ class Primitive : public Object virtual void draw() const = 0; virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor&) {} + + virtual void offsetIndices(int offset) = 0; protected: @@ -174,6 +176,8 @@ class SG_EXPORT DrawArrays : public Primitive virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor); + virtual void offsetIndices(int offset) { _first += offset; } + protected: GLint _first; @@ -223,6 +227,8 @@ class SG_EXPORT DrawArrayLengths : public Primitive, public VectorSizei virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor); + virtual void offsetIndices(int offset) { _first += offset; } + protected: GLint _first; @@ -261,6 +267,8 @@ class SG_EXPORT DrawElementsUByte : public Primitive, public VectorUByte virtual void draw() const ; virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor); + + virtual void offsetIndices(int offset); }; @@ -297,6 +305,8 @@ class SG_EXPORT DrawElementsUShort : public Primitive, public VectorUShort virtual void draw() const; virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor); + + virtual void offsetIndices(int offset); }; class SG_EXPORT DrawElementsUInt : public Primitive, public VectorUInt @@ -333,6 +343,7 @@ class SG_EXPORT DrawElementsUInt : public Primitive, public VectorUInt virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor); + virtual void offsetIndices(int offset); }; // backwards compatibility with first incarnation of DrawElements nameing convention. diff --git a/include/osgUtil/AppVisitor b/include/osgUtil/AppVisitor index 070f07dc8..88afec889 100644 --- a/include/osgUtil/AppVisitor +++ b/include/osgUtil/AppVisitor @@ -73,7 +73,7 @@ class OSGUTIL_EXPORT AppVisitor : public osg::NodeVisitor else if (node.getNumChildrenRequiringAppTraversal()>0) traverse(node); // call the app callbacks on the drawables. - for(int i=0;igetAppCallback(); if (callback) callback->app(this,node.getDrawable(i)); diff --git a/include/osgUtil/Optimizer b/include/osgUtil/Optimizer index 5e37f5e44..8c342321b 100644 --- a/include/osgUtil/Optimizer +++ b/include/osgUtil/Optimizer @@ -7,6 +7,7 @@ #include #include +#include #include @@ -315,7 +316,22 @@ class OSGUTIL_EXPORT Optimizer StateSetMap _statesets; }; + + + class OSGUTIL_EXPORT MergeGeometryVisitor : public osg::NodeVisitor + { + public: + /// default to traversing all children. + MergeGeometryVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) {} + + virtual void apply(osg::Geode& geode) { mergeGeode(geode); } + virtual void apply(osg::Billboard& billboard) { /* don't do anything*/ } + + static bool mergeGeode(osg::Geode& geode); + static bool mergeGeometry(osg::Geometry& lhs,osg::Geometry& rhs); + + }; }; } diff --git a/src/Demos/osgcallback/osgcallback.cpp b/src/Demos/osgcallback/osgcallback.cpp index 5ffaee7bb..5016bc66d 100644 --- a/src/Demos/osgcallback/osgcallback.cpp +++ b/src/Demos/osgcallback/osgcallback.cpp @@ -170,7 +170,7 @@ class InsertCallbacksVisitor : public osg::NodeVisitor //If you wish to control the culling of drawables //then use a drawable cullback... - for(int i=0;isetAppCallback(new DrawableAppCallback()); geode.getDrawable(i)->setCullCallback(new DrawableCullCallback()); diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index ad4d1025e..e5b446864 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -1,4 +1,5 @@ #include +#include using namespace osg; @@ -40,12 +41,18 @@ Array* Geometry::getTexCoordArray(unsigned int unit) else return 0; } +const Array* Geometry::getTexCoordArray(unsigned int unit) const +{ + if (unit<_texCoordList.size()) return _texCoordList[unit].get(); + else return 0; +} + void Geometry::drawImmediateMode(State& state) { if (!_vertexArray.valid()) return; // set up the vertex arrays. - state.setVertexPointer(3,GL_FLOAT,0,_vertexArray->dataPointer()); + state.setVertexPointer(3,GL_FLOAT,0,_vertexArray->getDataPointer()); // set up texture coordinates. unsigned int i; @@ -53,7 +60,7 @@ void Geometry::drawImmediateMode(State& state) { Array* array = _texCoordList[i].get(); if (array) - state.setTexCoordPointer(i,array->dataSize(),array->dataType(),0,array->dataPointer()); + state.setTexCoordPointer(i,array->getDataSize(),array->getDataType(),0,array->getDataPointer()); else state.disableTexCoordPointer(i); } @@ -96,19 +103,19 @@ void Geometry::drawImmediateMode(State& state) { case(Array::UByte4ArrayType): { - colorPointer = reinterpret_cast(_colorArray->dataPointer()); + colorPointer = reinterpret_cast(_colorArray->getDataPointer()); colorStride = 4; break; } case(Array::Vec3ArrayType): { - colorPointer = reinterpret_cast(_colorArray->dataPointer()); + colorPointer = reinterpret_cast(_colorArray->getDataPointer()); colorStride = 12; break; } case(Array::Vec4ArrayType): { - colorPointer = reinterpret_cast(_colorArray->dataPointer()); + colorPointer = reinterpret_cast(_colorArray->getDataPointer()); colorStride = 16; break; } @@ -146,7 +153,7 @@ void Geometry::drawImmediateMode(State& state) state.disableColorPointer(); break; case(BIND_PER_VERTEX): - if (colorPointer) state.setColorPointer(_colorArray->dataSize(),_colorArray->dataType(),0,colorPointer); + if (colorPointer) state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,colorPointer); else state.disableColorPointer(); } @@ -255,3 +262,148 @@ const bool Geometry::computeBound() const return _bbox.valid(); } +bool Geometry::verifyBindings() const +{ + switch(_normalBinding) + { + case(BIND_OFF): + if (_normalArray.valid() && _normalArray->getNumElements()>0) return false; + break; + case(BIND_OVERALL): + if (!_normalArray.valid()) return false; + if (_normalArray->getNumElements()!=1) return false; + break; + case(BIND_PER_PRIMITIVE): + if (!_normalArray.valid()) return false; + if (_normalArray->getNumElements()!=_primitives.size()) return false; + break; + case(BIND_PER_VERTEX): + if (_vertexArray.valid()) + { + if (!_normalArray.valid()) return false; + if (_normalArray->getNumElements()!=_vertexArray->getNumElements()) return false; + } + else if (_normalArray.valid() && _normalArray->getNumElements()>0) return false; + break; + } + + switch(_colorBinding) + { + case(BIND_OFF): + if (_colorArray.valid() && _colorArray->getNumElements()>0) return false; + break; + case(BIND_OVERALL): + if (!_colorArray.valid()) return false; + if (_colorArray->getNumElements()!=1) return false; + break; + case(BIND_PER_PRIMITIVE): + if (!_colorArray.valid()) return false; + if (_colorArray->getNumElements()!=_primitives.size()) return false; + break; + case(BIND_PER_VERTEX): + if (_vertexArray.valid()) + { + if (!_colorArray.valid()) return false; + if (_colorArray->getNumElements()!=_vertexArray->getNumElements()) return false; + } + else if (_colorArray.valid() && _colorArray->getNumElements()>0) return false; + break; + } + + for(TexCoordArrayList::const_iterator itr=_texCoordList.begin(); + itr!=_texCoordList.end(); + ++itr) + { + const Array* array = itr->get(); + if (_vertexArray.valid()) + { + if (array && array->getNumElements()!=_vertexArray->getNumElements()) return false; + } + else if (array && array->getNumElements()>0) return false; + } + + return true; +} + +void Geometry::computeCorrectBindingsAndArraySizes() +{ + if (verifyBindings()) return; + + if (!_vertexArray.valid() || _vertexArray->empty()) + { + // no vertex array so switch everything off. + + _vertexArray = 0; + + _colorArray = 0; + _colorBinding = BIND_OFF; + + _normalArray = 0; + _normalBinding = BIND_OFF; + + _texCoordList.clear(); + + notify(INFO)<<"Info: remove redundent attribute arrays from empty osg::Geometry"<getNumElements()==0) + { + _normalArray = 0; + _normalBinding = BIND_OFF; + } + else if (_normalArray->getNumElements()>1) + { + // trim the array down to 1 element long. + _normalArray->erase(_normalArray->begin()+1,_normalArray->end()); + } + break; + case(BIND_PER_PRIMITIVE): + if (!_normalArray.valid()) + { + _normalBinding = BIND_OFF; + } + else if (_normalArray->getNumElements()<_primitives.size()) + { + _normalArray = 0; + _normalBinding = BIND_OFF; + } + else if (_normalArray->getNumElements()>_primitives.size()) + { + // trim the array down to size of the number of primitives. + _normalArray->erase(_normalArray->begin()+_primitives.size(),_normalArray->end()); + } + break; + case(BIND_PER_VERTEX): + if (!_normalArray.valid()) + { + _normalBinding = BIND_OFF; + } + else if (_normalArray->getNumElements()<_vertexArray->getNumElements()) + { + _normalArray = 0; + _normalBinding = BIND_OFF; + } + else if (_normalArray->getNumElements()>_vertexArray->getNumElements()) + { + // trim the array down to size of the number of primitives. + _normalArray->erase(_normalArray->begin()+_vertexArray->getNumElements(),_normalArray->end()); + } + break; + } + + // TODO colours and tex coords. + +} diff --git a/src/osg/Primitive.cpp b/src/osg/Primitive.cpp index fb5f99dca..2ae37fca6 100644 --- a/src/osg/Primitive.cpp +++ b/src/osg/Primitive.cpp @@ -48,6 +48,16 @@ void DrawElementsUByte::applyPrimitiveOperation(Drawable::PrimitiveFunctor& func if (!empty()) functor.drawElements(_mode,size(),&front()); } +void DrawElementsUByte::offsetIndices(int offset) +{ + for(iterator itr=begin(); + itr!=end(); + ++itr) + { + *itr += offset; + } +} + void DrawElementsUShort::draw() const { @@ -59,6 +69,15 @@ void DrawElementsUShort::applyPrimitiveOperation(Drawable::PrimitiveFunctor& fun if (!empty()) functor.drawElements(_mode,size(),&front()); } +void DrawElementsUShort::offsetIndices(int offset) +{ + for(iterator itr=begin(); + itr!=end(); + ++itr) + { + *itr += offset; + } +} void DrawElementsUInt::draw() const @@ -70,3 +89,13 @@ void DrawElementsUInt::applyPrimitiveOperation(Drawable::PrimitiveFunctor& funct { if (!empty()) functor.drawElements(_mode,size(),&front()); } + +void DrawElementsUInt::offsetIndices(int offset) +{ + for(iterator itr=begin(); + itr!=end(); + ++itr) + { + *itr += offset; + } +} diff --git a/src/osgPlugins/flt/GeoSetBuilder.cpp b/src/osgPlugins/flt/GeoSetBuilder.cpp index 03e94533b..12181dd35 100644 --- a/src/osgPlugins/flt/GeoSetBuilder.cpp +++ b/src/osgPlugins/flt/GeoSetBuilder.cpp @@ -49,39 +49,39 @@ void DynGeoSet::append(DynGeoSet* source) { APPEND_DynGeoSet_List(_primLenList) APPEND_DynGeoSet_List(_coordList) - APPEND_DynGeoSet_List(_normalList) - APPEND_DynGeoSet_List(_colorList) - APPEND_DynGeoSet_List(_tcoordList) + if (_normal_binding==osg::Geometry::BIND_PER_VERTEX || _normal_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_normalList) + if (_color_binding==osg::Geometry::BIND_PER_VERTEX || _color_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_colorList) + if (_texture_binding==osg::Geometry::BIND_PER_VERTEX || _texture_binding==osg::Geometry::BIND_PER_PRIMITIVE) APPEND_DynGeoSet_List(_tcoordList) } #define VERIFY_DynGeoSet_Binding(binding,list) \ switch (binding) \ { \ - case osg::GeoSet::BIND_PERVERTEX: \ + case osg::Geometry::BIND_PER_VERTEX: \ if (list.size() < _coordList.size()) { \ - binding = osg::GeoSet::BIND_OFF; \ + binding = osg::Geometry::BIND_OFF; \ list.clear(); } \ break; \ - case osg::GeoSet::BIND_PERPRIM: \ + case osg::Geometry::BIND_PER_PRIMITIVE: \ if (list.size() < _primLenList.size()) { \ - binding = osg::GeoSet::BIND_OFF; \ + binding = osg::Geometry::BIND_OFF; \ list.clear(); } \ break; \ - case osg::GeoSet::BIND_OVERALL: \ + case osg::Geometry::BIND_OVERALL: \ if (list.size() < 1) { \ - binding = osg::GeoSet::BIND_OFF; \ + binding = osg::Geometry::BIND_OFF; \ list.clear(); } \ break; \ default: \ break; \ } -DynGeoSet::DynGeoSet():osg::GeoSet() +const osg::Primitive::Mode NO_PRIMITIVE_TYPE = (osg::Primitive::Mode)0xffff; + +DynGeoSet::DynGeoSet() { - // disable the attribute delete functor since the vectors contained in DynGeoSet - // will delete the memory for us. - _adf = NULL; + _primtype=NO_PRIMITIVE_TYPE; } void DynGeoSet::setBinding() @@ -98,38 +98,13 @@ void DynGeoSet::setBinding() osg::StateSet* stateset = getStateSet(); if (stateset) { - if (_normal_binding == osg::GeoSet::BIND_OFF) + if (_normal_binding == osg::Geometry::BIND_OFF) stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); } } -bool DynGeoSet::setLists() -{ - if ((_primLenList.size() > 0) && (_coordList.size() > 0)) - { - setPrimLengths(&_primLenList.front()); - setCoords(&_coordList.front()); - - if ((_normalList.size() > 0) - && (getNormalBinding() != osg::GeoSet::BIND_OFF)) - setNormals(&_normalList.front()); - - if ((_colorList.size() > 0) - && (getColorBinding() != osg::GeoSet::BIND_OFF)) - setColors(&_colorList.front()); - - if ((_tcoordList.size() > 0) - && (getTextureBinding() != osg::GeoSet::BIND_OFF)) - setTextureCoords(&_tcoordList.front()); - - return true; - } - - return false; -} - void DynGeoSet::addToGeometry(osg::Geometry* geom) { int indexBase = 0; @@ -153,7 +128,7 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom) osg::Vec3Array* normals = geom->getNormalArray(); if (normals) { - if (_normal_binding==osg::GeoSet::BIND_PERVERTEX || _normal_binding==osg::GeoSet::BIND_PERPRIM) + if (_normal_binding==osg::Geometry::BIND_PER_VERTEX || _normal_binding==osg::Geometry::BIND_PER_PRIMITIVE) normals->insert(normals->end(),_normalList.begin(),_normalList.end()); } else @@ -163,9 +138,9 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom) switch(_normal_binding) { - case(osg::GeoSet::BIND_OVERALL):geom->setNormalBinding(osg::Geometry::BIND_OVERALL);break; - case(osg::GeoSet::BIND_PERVERTEX):geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);break; - case(osg::GeoSet::BIND_PERPRIM):geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);break; + case(osg::Geometry::BIND_OVERALL):geom->setNormalBinding(osg::Geometry::BIND_OVERALL);break; + case(osg::Geometry::BIND_PER_VERTEX):geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);break; + case(osg::Geometry::BIND_PER_PRIMITIVE):geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);break; default:geom->setNormalBinding(osg::Geometry::BIND_OFF); break; } } @@ -190,7 +165,7 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom) osg::Vec4Array* colors = dynamic_cast(geom->getColorArray()); if (colors) { - if (_color_binding==osg::GeoSet::BIND_PERVERTEX || _color_binding==osg::GeoSet::BIND_PERPRIM) + if (_color_binding==osg::Geometry::BIND_PER_VERTEX || _color_binding==osg::Geometry::BIND_PER_PRIMITIVE) colors->insert(colors->end(),_colorList.begin(),_colorList.end()); } else @@ -200,29 +175,17 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom) switch(_color_binding) { - case(osg::GeoSet::BIND_OVERALL):geom->setColorBinding(osg::Geometry::BIND_OVERALL);break; - case(osg::GeoSet::BIND_PERVERTEX):geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);break; - case(osg::GeoSet::BIND_PERPRIM):geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);break; + case(osg::Geometry::BIND_OVERALL):geom->setColorBinding(osg::Geometry::BIND_OVERALL);break; + case(osg::Geometry::BIND_PER_VERTEX):geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);break; + case(osg::Geometry::BIND_PER_PRIMITIVE):geom->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);break; default:geom->setColorBinding(osg::Geometry::BIND_OFF); break; } } - } - - osg::Primitive::Mode mode = osg::Primitive::POLYGON; - switch(_primtype) - { - case(osg::GeoSet::POINTS):mode = osg::Primitive::POINTS; break; - case(osg::GeoSet::LINES):mode = osg::Primitive::LINES; break; - case(osg::GeoSet::TRIANGLES):mode = osg::Primitive::TRIANGLES; break; - case(osg::GeoSet::QUADS):mode = osg::Primitive::QUADS; break; - case(osg::GeoSet::POLYGON):mode = osg::Primitive::POLYGON; break; - default: mode = osg::Primitive::POLYGON; - } + } - - if (mode!=osg::Primitive::POLYGON) + if (_primtype!=osg::Primitive::POLYGON) { - geom->addPrimitive(new osg::DrawArrays(mode,indexBase,_coordList.size())); + geom->addPrimitive(new osg::DrawArrays(_primtype,indexBase,_coordList.size())); } else { @@ -230,7 +193,7 @@ void DynGeoSet::addToGeometry(osg::Geometry* geom) itr!=_primLenList.end(); ++itr) { - geom->addPrimitive(new osg::DrawArrays(mode,indexBase,*itr)); + geom->addPrimitive(new osg::DrawArrays(_primtype,indexBase,*itr)); indexBase += *itr; } } @@ -314,30 +277,12 @@ osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode) } osgUtil::Tesselator tesselator; - for(int i=0;igetNumDrawables();++i) + for(unsigned int i=0;igetNumDrawables();++i) { osg::Geometry* geom = dynamic_cast(geode->getDrawable(i)); if (geom) tesselator.retesselatePolygons(*geom); } -//Old GeoSet code. -// for(itr=_dynGeoSetList.begin(); -// itr!=_dynGeoSetList.end(); -// ++itr) -// { -// DynGeoSet* dgset = itr->get(); -// if (dgset) -// { -// int prims = dgset->primLenListSize(); -// if (prims > 0) -// { -// dgset->setLists(); -// dgset->setNumPrims(prims); -// geode->addDrawable(dgset); -// } -// } -// } - return geode; } @@ -346,11 +291,13 @@ bool GeoSetBuilder::addPrimitive(bool dontMerge) { DynGeoSet* dgset = getDynGeoSet(); // This is the new geoset we want to add - if (dgset->getPrimType() == osg::GeoSet::NO_TYPE) + if (dgset->getPrimType()==NO_PRIMITIVE_TYPE) + { dgset->setPrimType(findPrimType(dgset->coordListSize())); + } // Still no primitive type? - if (dgset->getPrimType() == osg::GeoSet::NO_TYPE) + if (dgset->getPrimType()==NO_PRIMITIVE_TYPE) return false; dgset->setBinding(); @@ -389,18 +336,19 @@ DynGeoSet* GeoSetBuilder::findMatchingGeoSet() } -osg::GeoSet::PrimitiveType GeoSetBuilder::findPrimType(const int nVertices) +osg::Primitive::Mode GeoSetBuilder::findPrimType(const int nVertices) { switch (nVertices) { - case 1: return osg::GeoSet::POINTS; - case 2: return osg::GeoSet::LINES; - case 3: return osg::GeoSet::TRIANGLES; - case 4: return osg::GeoSet::QUADS; + case 1: return osg::Primitive::POINTS; + case 2: return osg::Primitive::LINES; + case 3: return osg::Primitive::TRIANGLES; + case 4: return osg::Primitive::QUADS; } - if (nVertices >= 5) return osg::GeoSet::POLYGON; - return osg::GeoSet::NO_TYPE; + if (nVertices>=5) return osg::Primitive::POLYGON; + + return NO_PRIMITIVE_TYPE; } diff --git a/src/osgPlugins/flt/GeoSetBuilder.h b/src/osgPlugins/flt/GeoSetBuilder.h index 4307e1b3b..0d490c4ff 100644 --- a/src/osgPlugins/flt/GeoSetBuilder.h +++ b/src/osgPlugins/flt/GeoSetBuilder.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -27,7 +26,7 @@ class TmpGeoSet; // DynGeoSet // //////////////////////////////////////////////////////////////////// -#if 0 +#if 1 # define COMPARE_DynGeoSet_Parameter(parameter) \ if (parameter= 1) && (rhs._colorList.size() >= 1) - && (_colorList[0] != rhs._colorList[0])) - return -1; - + if (_color_binding == osg::Geometry::BIND_OVERALL) + { + if ((_colorList.size() >= 1) && (rhs._colorList.size() >= 1)) + { + if (_colorList[0]compare(*rhs.getStateSet(), true); if (result!=0) return result; @@ -66,18 +67,26 @@ class DynGeoSet : public osg::GeoSet int compatible(const DynGeoSet& rhs) const { + COMPARE_DynGeoSet_Parameter(_color_binding) - COMPARE_DynGeoSet_Parameter(_normal_binding) COMPARE_DynGeoSet_Parameter(_texture_binding) - int result=getStateSet()->compare(*rhs.getStateSet(), true); if (result!=0) return result; - if ((_color_binding == osg::GeoSet::BIND_OVERALL) - && (_colorList.size() >= 1) && (rhs._colorList.size() >= 1) - && (_colorList[0] != rhs._colorList[0])) - return -1; + COMPARE_DynGeoSet_Parameter(_normal_binding) + + return 0; + + + if (_color_binding == osg::Geometry::BIND_OVERALL) + { + if ((_colorList.size() >= 1) && (rhs._colorList.size() >= 1)) + { + if (_colorList[0] ColorList; typedef std::vector TcoordList; - PrimLenList _primLenList; - CoordList _coordList; - NormalList _normalList; - ColorList _colorList; - TcoordList _tcoordList; + + osg::ref_ptr _stateset; + + + osg::Primitive::Mode _primtype; + PrimLenList _primLenList; + + CoordList _coordList; + + osg::Geometry::AttributeBinding _normal_binding; + NormalList _normalList; + + osg::Geometry::AttributeBinding _color_binding; + ColorList _colorList; + + osg::Geometry::AttributeBinding _texture_binding; + TcoordList _tcoordList; }; @@ -149,7 +184,7 @@ class GeoSetBuilder void initPrimData(); DynGeoSet* findMatchingGeoSet(); - osg::GeoSet::PrimitiveType findPrimType(const int nVertices); + osg::Primitive::Mode findPrimType(const int nVertices); private: diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 48ed8bf9c..110532d97 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -672,16 +671,27 @@ osg::Group* ConvertFromFLT::visitSwitch(osg::Group& osgParent, SwitchRecord* rec visitAncillary(osgParent, *group, rec)->addChild( group ); visitPrimaryNode(*group, (PrimNodeRecord*)rec); - for(int nChild=0; nChildgetNumChildren(); nChild++) + for(unsigned int nChild=0; nChild<(unsigned int)rec->getNumChildren(); nChild++) { - int nMaskBit = nChild % 32; - int nMaskWord = pSSwitch->nCurrentMask * pSSwitch->nWordsInMask + nChild / 32; + unsigned int nMaskBit = nChild % 32; + unsigned int nMaskWord = pSSwitch->nCurrentMask * pSSwitch->nWordsInMask + nChild / 32; if (!(pSSwitch->aMask[nMaskWord] & (uint32(1) << nMaskBit))) { - osg::Node* node = group->getChild(nChild); - if (node) - node->setNodeMask(0); + if (nChildgetNumChildren()) + { + osg::Node* node = group->getChild(nChild); + if (node) + node->setNodeMask(0); + } + else + { + osg::notify(osg::WARN)<<"Warning::OpenFlight loader has come across an incorrectly handled switch."<getNumChildren()<<") "<getNumChildren()<<")"<setPrimType(osg::GeoSet::LINE_STRIP); + dgset->setPrimType(osg::Primitive::LINE_STRIP); break; case FaceRecord::WIREFRAME_CLOSED: - dgset->setPrimType(osg::GeoSet::LINE_LOOP); + dgset->setPrimType(osg::Primitive::LINE_LOOP); break; } @@ -776,39 +786,39 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec) case FaceRecord::FACE_COLOR: // Use face color, not illuminated osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); - dgset->setColorBinding( osg::GeoSet::BIND_OVERALL /*BIND_PERPRIM*/ ); + dgset->setColorBinding( osg::Geometry::BIND_OVERALL /*BIND_PERPRIM*/ ); break; case FaceRecord::VERTEX_COLOR: // Use vertex colors, not illuminated osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); - dgset->setColorBinding( osg::GeoSet::BIND_PERVERTEX ); + dgset->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); break; case FaceRecord::FACE_COLOR_LIGHTING: // Use face color and vertex normal osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON ); - dgset->setColorBinding( osg::GeoSet::BIND_OVERALL ); - dgset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX); + dgset->setColorBinding( osg::Geometry::BIND_OVERALL ); + dgset->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); break; case FaceRecord::VERTEX_COLOR_LIGHTING: // Use vertex color and vertex normal osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::ON ); - dgset->setColorBinding( osg::GeoSet::BIND_PERVERTEX ); - dgset->setNormalBinding(osg::GeoSet::BIND_PERVERTEX); + dgset->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); + dgset->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); break; default : osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); - dgset->setColorBinding( osg::GeoSet::BIND_OVERALL ); + dgset->setColorBinding( osg::Geometry::BIND_OVERALL ); break; } } else // Version 11, 12 & 13 { osgStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); - dgset->setColorBinding( osg::GeoSet::BIND_OVERALL /*BIND_PERPRIM*/ ); + dgset->setColorBinding( osg::Geometry::BIND_OVERALL /*BIND_PERPRIM*/ ); } @@ -857,8 +867,8 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec) _faceColor[3] = 1.0f - ((float)pSFace->wTransparency / 65535.0f); if (pSFace->wTransparency > 0) bBlend = true; - if ((dgset->getColorBinding() == osg::GeoSet::BIND_OVERALL) - || (dgset->getColorBinding() == osg::GeoSet::BIND_PERPRIM)) + if ((dgset->getColorBinding() == osg::Geometry::BIND_OVERALL) + || (dgset->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE)) dgset->addColor(_faceColor); // @@ -974,7 +984,7 @@ void ConvertFromFLT::visitFace(GeoSetBuilder* pBuilder, FaceRecord* rec) } #endif - dgset->setTextureBinding(osg::GeoSet::BIND_PERVERTEX); + dgset->setTextureBinding(osg::Geometry::BIND_PER_VERTEX); } } } @@ -1050,7 +1060,7 @@ int ConvertFromFLT::addVertices(GeoSetBuilder* pBuilder, PrimNodeRecord* primRec if (vertices > 0) { - if (dgset->getPrimType() == osg::GeoSet::POINTS) + if (dgset->getPrimType() == osg::Primitive::POINTS) { for (i=0; i < vertices; i++) dgset->addPrimLen(1); @@ -1095,7 +1105,7 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); - if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) } @@ -1107,9 +1117,9 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); - if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_NORMAL(dgset, pVert) - if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) } break; @@ -1120,11 +1130,11 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); - if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_NORMAL(dgset, pVert) - if (dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_TCOORD(dgset, pVert) - if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) } break; @@ -1135,9 +1145,9 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->Coord.x(), pVert->Coord.y(), pVert->Coord.z()); coord *= (float)_unitScale; dgset->addCoord(coord); - if (dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_TCOORD(dgset, pVert) - if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_VERTEX_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) } break; @@ -1148,7 +1158,7 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]); coord *= (float)_unitScale; dgset->addCoord(coord); - if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX) + if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) && (rec->getSize() >= sizeof(SOldVertex))) ADD_OLD_TCOORD(dgset, pVert) } @@ -1160,9 +1170,9 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]); coord *= (float)_unitScale; dgset->addCoord(coord); - if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) - if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX) + if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) && (rec->getSize() >= sizeof(SOldVertexColor))) ADD_OLD_TCOORD(dgset, pVert) } @@ -1174,15 +1184,15 @@ int ConvertFromFLT::addVertex(DynGeoSet* dgset, Record* rec) osg::Vec3 coord(pVert->v[0], pVert->v[1], pVert->v[2]); coord *= (float)_unitScale; dgset->addCoord(coord); - if (dgset->getNormalBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) { osg::Vec3 normal(pVert->n[0], pVert->n[1], pVert->n[2]); normal /= (float)(1L<<30); dgset->addNormal(normal); } - if (dgset->getColorBinding() == osg::GeoSet::BIND_PERVERTEX) + if (dgset->getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ADD_OLD_COLOR(dgset, pVert, rec->getFltFile()->getColorPool()) - if ((dgset->getTextureBinding() == osg::GeoSet::BIND_PERVERTEX) + if ((dgset->getTextureBinding() == osg::Geometry::BIND_PER_VERTEX) && (rec->getSize() >= sizeof(SOldVertexColorNormal))) ADD_OLD_TCOORD(dgset, pVert) } @@ -1249,10 +1259,10 @@ void ConvertFromFLT::visitLightPoint(GeoSetBuilder* pBuilder, LightPointRecord* osg::StateSet* stateSet = dgset->getStateSet(); SLightPoint *pSLightPoint = (SLightPoint*)rec->getData(); - dgset->setPrimType(osg::GeoSet::POINTS); + dgset->setPrimType(osg::Primitive::POINTS); stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON); - dgset->setColorBinding(osg::GeoSet::BIND_PERVERTEX); + dgset->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::Point* point = new osg::Point; if (point) diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index e21e69e93..054dc095b 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -250,7 +250,7 @@ void CullVisitor::apply(Geode& node) if (node_state) pushStateSet(node_state); Matrix& matrix = getModelViewMatrix(); - for(int i=0;igetBound(); @@ -316,7 +316,7 @@ void CullVisitor::apply(Billboard& node) const Vec3& eye_local = getEyeLocal(); const Matrix& modelview = getModelViewMatrix(); - for(int i=0;iaccept(osv); osv.optimize(); + + MergeGeometryVisitor mgv; + node->accept(mgv); #endif } - @@ -138,7 +140,7 @@ class TransformFunctor : public osg::Drawable::AttributeFunctor void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode) { - for(int i=0;i(geode.getDrawable(i)); if (geoset) @@ -204,7 +206,7 @@ void Optimizer::StateVisitor::apply(osg::Geode& geode) { osg::StateSet* ss = geode.getStateSet(); if (ss && ss->getDataVariance()==osg::Object::STATIC) addStateSet(ss,&geode); - for(int i=0;isetAxis(axis); - for(int i=0;igetNumDrawables();++i) + for(unsigned int i=0;igetNumDrawables();++i) { billboard->setPos(i,billboard->getPos(i)*matrix); billboard->getDrawable(i)->applyAttributeOperation(tf); @@ -650,7 +652,7 @@ void Optimizer::RemoveLowestStaticTransformsVisitor::apply(osg::Geode& geode) osg::Matrix matrix; if (!_matrixStack.empty()) matrix = _matrixStack.back(); - for(int i=0;isetAxis(axis); - for(int i=0;igetNumDrawables();++i) + for(unsigned int i=0;igetNumDrawables();++i) { billboard->setPos(i,billboard->getPos(i)*matrix); billboard->getDrawable(i)->applyAttributeOperation(tf); @@ -1162,3 +1164,166 @@ void Optimizer::CombineLODsVisitor::combineLODs() _groupList.clear(); } +//////////////////////////////////////////////////////////////////////////// +// code to merge geometry object which share, state, and attribute bindings. +//////////////////////////////////////////////////////////////////////////// + +struct LessGeometry +{ + bool operator() (const osg::Geometry* lhs,const osg::Geometry* rhs) + { + if (lhs->getStateSet()getStateSet()) return true; + if (rhs->getStateSet()getStateSet()) return false; + + if (lhs->getColorBinding()getColorBinding()) return true; + if (rhs->getColorBinding()getColorBinding()) return false; + + if (lhs->getNormalBinding()getNormalBinding()) return true; + if (rhs->getNormalBinding()getNormalBinding()) return false; + + if (lhs->getNumTexCoordArrays()getNumTexCoordArrays()) return true; + if (rhs->getNumTexCoordArrays()getNumTexCoordArrays()) return false; + + // therefore lhs->getNumTexCoordArrays()==rhs->getNumTexCoordArrays() + + for(unsigned int i=0;igetNumTexCoordArrays();++i) + { + if (rhs->getTexCoordArray(i)) + { + if (!lhs->getTexCoordArray(i)) return true; + } + else if (lhs->getTexCoordArray(i)) return false; + } + + if (lhs->getNormalBinding()==osg::Geometry::BIND_OVERALL) + { + // assumes that the bindings and arrays are set up correctly, this + // should be the case after running computeCorrectBindingsAndArraySizes(); + const osg::Vec3& lhs_normal = (*(lhs->getNormalArray()))[0]; + const osg::Vec3& rhs_normal = (*(rhs->getNormalArray()))[0]; + if (lhs_normalgetColorBinding()==osg::Geometry::BIND_OVERALL) + { + if (lhs->getColorArray()->getType()getColorArray()->getType()) return true; + if (rhs->getColorArray()->getType()getColorArray()->getType()) return false; + } + + return false; + + } +}; + +bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode) +{ + if (geode.getNumDrawables()<2) return false; + + typedef std::vector DuplicateList; + typedef std::map GeometryDuplicateMap; + + GeometryDuplicateMap geometryDuplicateMap; + + for(unsigned int i=0;i(geode.getDrawable(i)); + if (geom) + { + geom->computeCorrectBindingsAndArraySizes(); + + geometryDuplicateMap[geom].push_back(geom); + } + } + + for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin(); + itr!=geometryDuplicateMap.end(); + ++itr) + { + if (itr->second.size()>1) + { + osg::Geometry* lhs = itr->second[0]; + for(DuplicateList::iterator dupItr=itr->second.begin()+1; + dupItr!=itr->second.end(); + ++dupItr) + { + osg::Geometry* rhs = *dupItr; + if (mergeGeometry(*lhs,*rhs)) + { + geode.removeDrawable(rhs); + + static int co = 0; + osg::notify(osg::INFO)<<"merged and removed Geometry "<<++co<size(); + lhs.getVertexArray()->insert(lhs.getVertexArray()->end(),rhs.getVertexArray()->begin(),rhs.getVertexArray()->end()); + } + else if (rhs.getVertexArray()) + { + lhs.setVertexArray(rhs.getVertexArray()); + } + + if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalBinding()!=osg::Geometry::BIND_OVERALL) + { + lhs.getNormalArray()->insert(lhs.getNormalArray()->end(),rhs.getNormalArray()->begin(),rhs.getNormalArray()->end()); + } + else if (rhs.getNormalArray()) + { + lhs.setNormalArray(rhs.getNormalArray()); + } + + if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL) + { + // we need to add the handling of the other array types... + osg::Vec4Array* col_lhs = dynamic_cast(lhs.getColorArray()); + osg::Vec4Array* col_rhs = dynamic_cast(rhs.getColorArray()); + + if (col_lhs && col_rhs) + { + col_lhs->insert(col_lhs->end(),col_rhs->begin(),col_rhs->end()); + } + } + else if (rhs.getColorArray()) + { + lhs.setColorArray(rhs.getColorArray()); + } + + for(unsigned int unit=0;unit(lhs.getTexCoordArray(unit)); + osg::Vec2Array* tex_rhs = dynamic_cast(rhs.getTexCoordArray(unit)); + + if (tex_lhs && tex_rhs) + { + tex_lhs->insert(tex_lhs->end(),tex_rhs->begin(),tex_rhs->end()); + } + } + + // shift the indices of the incomming primitives to account for the pre exisiting geometry. + for(osg::Geometry::PrimitiveList::iterator primItr=rhs.getPrimitiveList().begin(); + primItr!=rhs.getPrimitiveList().end(); + ++primItr) + { + osg::Primitive* primitive = primItr->get(); + primitive->offsetIndices(base); + } + + lhs.getPrimitiveList().insert(lhs.getPrimitiveList().end(),rhs.getPrimitiveList().begin(),rhs.getPrimitiveList().end()); + + + return true; +}