From 01992a779090f5e12deca522edd26f598977eca9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 27 Jun 2002 20:29:32 +0000 Subject: [PATCH] Ported the flt plugin across to use osg::Geometry, it still uses a GeoSet internally, and I will remove this after some futher work. --- src/osg/CollectOccludersVisitor.cpp | 8 +- src/osg/Geometry.cpp | 22 +++- src/osgPlugins/flt/GeoSetBuilder.cpp | 173 +++++++++++++++++++++++++-- src/osgPlugins/flt/GeoSetBuilder.h | 29 ++++- 4 files changed, 215 insertions(+), 17 deletions(-) diff --git a/src/osg/CollectOccludersVisitor.cpp b/src/osg/CollectOccludersVisitor.cpp index 214556456..6fcdb1ed0 100644 --- a/src/osg/CollectOccludersVisitor.cpp +++ b/src/osg/CollectOccludersVisitor.cpp @@ -199,11 +199,15 @@ void CollectOccludersVisitor::removeOccludedOccluders() // do so in reverse order so that the iterators remain valid. for(ShadowVolumeOccluder::HoleList::reverse_iterator holeItr=holeList.rbegin(); holeItr!=holeList.rend(); - ++holeItr) + ) { if (occluder->contains(holeItr->getReferenceVertexList())) { - holeList.erase(holeItr.base()); + holeList.erase((++holeItr).base()); + } + else + { + ++holeItr; } } diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index f60b0ac1f..969af0d42 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -194,14 +194,30 @@ bool Geometry::getStats(Statistics &) Drawable::AttributeBitMask Geometry::suppportsAttributeOperation() const { - return 0; + // we do support coords,normals,texcoords and colors so return true. + return COORDS | NORMALS | COLORS | TEXTURE_COORDS; } /** return the attributes successully applied in applyAttributeUpdate.*/ -Drawable::AttributeBitMask Geometry::applyAttributeOperation(AttributeFunctor& ) +Drawable::AttributeBitMask Geometry::applyAttributeOperation(AttributeFunctor& auf) { - return 0; + AttributeBitMask amb = auf.getAttributeBitMask(); + AttributeBitMask ramb = 0; + + if ((amb & COORDS) && _vertexArray.valid() && !_vertexArray->empty()) + { + if (auf.apply(COORDS,&(*(_vertexArray->begin())),&(*(_vertexArray->end())))) ramb = COORDS; + } + + if ((amb & NORMALS) && _normalArray.valid() && !_normalArray->empty()) + { + if (auf.apply(NORMALS,&(*(_normalArray->begin())),&(*(_normalArray->end())))) ramb = NORMALS; + } + + // colors and texture coords to implement... + + return ramb; } void Geometry::applyPrimitiveOperation(PrimitiveFunctor& functor) diff --git a/src/osgPlugins/flt/GeoSetBuilder.cpp b/src/osgPlugins/flt/GeoSetBuilder.cpp index c4b775963..ccc7827f8 100644 --- a/src/osgPlugins/flt/GeoSetBuilder.cpp +++ b/src/osgPlugins/flt/GeoSetBuilder.cpp @@ -126,6 +126,113 @@ bool DynGeoSet::setLists() return false; } +void DynGeoSet::addToGeometry(osg::Geometry* geom) +{ + int indexBase = 0; + + geom->setStateSet(getStateSet()); + + osg::Vec3Array* vertices = geom->getVertexArray(); + if (vertices) + { + indexBase = vertices->size(); + vertices->insert(vertices->end(),_coordList.begin(),_coordList.end()); + } + else + { + vertices = new osg::Vec3Array(_coordList.begin(),_coordList.end()); + geom->setVertexArray(vertices); + } + + if (!_normalList.empty()) + { + osg::Vec3Array* normals = geom->getNormalArray(); + if (normals) + { + if (_normal_binding==osg::GeoSet::BIND_PERVERTEX || _normal_binding==osg::GeoSet::BIND_PERPRIM) + normals->insert(normals->end(),_normalList.begin(),_normalList.end()); + } + else + { + normals = new osg::Vec3Array(_normalList.begin(),_normalList.end()); + geom->setNormalArray(normals); + + 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; + default:geom->setNormalBinding(osg::Geometry::BIND_OFF); break; + } + } + } + + if (!_tcoordList.empty()) + { + osg::Vec2Array* texcoords = dynamic_cast(geom->getTexCoordArray(0)); + if (texcoords) + { + texcoords->insert(texcoords->end(),_tcoordList.begin(),_tcoordList.end()); + } + else + { + texcoords = new osg::Vec2Array(_tcoordList.begin(),_tcoordList.end()); + geom->setTexCoordArray(0,texcoords); + } + } + + if (!_colorList.empty()) + { + osg::Vec4Array* colors = dynamic_cast(geom->getColorArray()); + if (colors) + { + if (_color_binding==osg::GeoSet::BIND_PERVERTEX || _color_binding==osg::GeoSet::BIND_PERPRIM) + colors->insert(colors->end(),_colorList.begin(),_colorList.end()); + } + else + { + colors = new osg::Vec4Array(_colorList.begin(),_colorList.end()); + geom->setColorArray(colors); + + 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; + 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; + } + + + if (mode!=osg::Primitive::POLYGON) + { + geom->addPrimitive(new osg::DrawArrays(mode,indexBase,_coordList.size())); + } + else + { + for(PrimLenList::iterator itr=_primLenList.begin(); + itr!=_primLenList.end(); + ++itr) + { + geom->addPrimitive(new osg::DrawArrays(mode,indexBase,*itr)); + indexBase += *itr; + } + } + +} + + //////////////////////////////////////////////////////////////////// // // GeoSetBuilder @@ -149,6 +256,13 @@ void GeoSetBuilder::initPrimData() _dynGeoSet->setStateSet(new osg::StateSet); } +struct SortDynGeoSet +{ + bool operator () (const osg::ref_ptr& lhs,const osg::ref_ptr& rhs) + { + return *lhs<*rhs; + } +}; osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode) { @@ -156,23 +270,62 @@ osg::Geode* GeoSetBuilder::createOsgGeoSets(osg::Geode* geode) if( geode == NULL) return geode; - for(DynGeoSetList::iterator itr=_dynGeoSetList.begin(); - itr!=_dynGeoSetList.end(); - ++itr) + DynGeoSetList::iterator itr; + + if (_dynGeoSetList.size()==1) { - DynGeoSet* dgset = itr->get(); - if (dgset) + osg::Geometry* geom = new osg::Geometry; + geode->addDrawable(geom); + + _dynGeoSetList.front()->addToGeometry(geom); + } + else if (_dynGeoSetList.size()>1) + { + std::sort(_dynGeoSetList.begin(),_dynGeoSetList.end(),SortDynGeoSet()); + + osg::Geometry* geom = new osg::Geometry; + geode->addDrawable(geom); + _dynGeoSetList.front()->addToGeometry(geom); + + + static int counter=0; + itr = _dynGeoSetList.begin(); + DynGeoSetList::iterator prev = itr++; + for(; + itr!=_dynGeoSetList.end(); + ++itr) { - int prims = dgset->primLenListSize(); - if (prims > 0) + if ((*itr)->compatible(*(*prev))==0) { - dgset->setLists(); - dgset->setNumPrims(prims); - geode->addDrawable(dgset); + (*itr)->addToGeometry(geom); + counter++; + } else + { + geom = new osg::Geometry; + geode->addDrawable(geom); + (*itr)->addToGeometry(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; } diff --git a/src/osgPlugins/flt/GeoSetBuilder.h b/src/osgPlugins/flt/GeoSetBuilder.h index c35ac03a1..4307e1b3b 100644 --- a/src/osgPlugins/flt/GeoSetBuilder.h +++ b/src/osgPlugins/flt/GeoSetBuilder.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,6 @@ class DynGeoSet : public osg::GeoSet int compare(const DynGeoSet& rhs) const { - COMPARE_DynGeoSet_Parameter(_primtype) COMPARE_DynGeoSet_Parameter(_color_binding) COMPARE_DynGeoSet_Parameter(_normal_binding) COMPARE_DynGeoSet_Parameter(_texture_binding) @@ -57,7 +57,30 @@ class DynGeoSet : public osg::GeoSet && (_colorList[0] != rhs._colorList[0])) return -1; - return getStateSet()->compare(*rhs.getStateSet(), true); + int result=getStateSet()->compare(*rhs.getStateSet(), true); + if (result!=0) return result; + + COMPARE_DynGeoSet_Parameter(_primtype); + return 0; + } + + 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; + + return 0; + } bool operator < (const DynGeoSet& rhs) const { return compare(rhs)<0; } @@ -73,6 +96,8 @@ class DynGeoSet : public osg::GeoSet void append(DynGeoSet* source); void setBinding(); bool setLists(); + + void addToGeometry(osg::Geometry* geom); inline const int primLenListSize() const { return _primLenList.size(); } inline const int coordListSize() const { return _coordList.size(); }