From 5fd86440b33a738e192940ef7990914c5440147c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 30 Sep 2002 13:30:46 +0000 Subject: [PATCH] Added support for per primitive bindings in osg::IndexedGeometry. Added a convertToIndexedGeometry() method to GeoSet to allow datasets with per primitive bindings to be be mapped to across to osg::IndexedGeometry for testing purposes. --- include/osg/GeoSet | 3 + include/osg/IndexedGeometry | 6 +- src/osg/GeoSet.cpp | 232 ++++++++++++++++++++++++++++++++ src/osg/IndexedGeometry.cpp | 261 +++++++++++++++++++++++++----------- src/osgUtil/Optimizer.cpp | 47 +++++-- 5 files changed, 454 insertions(+), 95 deletions(-) diff --git a/include/osg/GeoSet b/include/osg/GeoSet index 638d21ddd..b680a8e9a 100644 --- a/include/osg/GeoSet +++ b/include/osg/GeoSet @@ -15,6 +15,7 @@ namespace osg { // forward declare so that we don't need to include the header. class Geometry; +class IndexedGeometry; /** Note, osg::GeoSet is now deprecated, please use osg::Geometry instead. osg::GeoSet will be kept through to the beta release for @@ -338,6 +339,8 @@ class SG_EXPORT GeoSet : public Drawable /** convinience function for converting GeoSet's to equivilant Geometry nodes.*/ Geometry* convertToGeometry(); + /** convinience function for converting GeoSet's to equivilant IndexedGeometry nodes.*/ + IndexedGeometry* convertToIndexedGeometry(); protected: diff --git a/include/osg/IndexedGeometry b/include/osg/IndexedGeometry index 3e3c8cd3d..366605df8 100644 --- a/include/osg/IndexedGeometry +++ b/include/osg/IndexedGeometry @@ -2,8 +2,8 @@ //Distributed under the terms of the GNU Library General Public License (LGPL) //as published by the Free Software Foundation. -#ifndef OSG_GEOMETRY -#define OSG_GEOMETRY 1 +#ifndef OSG_INDEXEDGEOMETRY +#define OSG_INDEXEDGEOMETRY 1 #include #include @@ -109,7 +109,7 @@ class SG_EXPORT IndexedGeometry : public Drawable Array* getTexCoordArray(unsigned int unit); const Array* getTexCoordArray(unsigned int unit) const; - void setTexCoordIndices(unsigned int unit,Array*); + void setTexCoordIndices(unsigned int unit,IndexArray*); IndexArray* getTexCoordIndices(unsigned int unit); const IndexArray* getTexCoordIndices(unsigned int unit) const; diff --git a/src/osg/GeoSet.cpp b/src/osg/GeoSet.cpp index c2408382b..115a909be 100644 --- a/src/osg/GeoSet.cpp +++ b/src/osg/GeoSet.cpp @@ -9,6 +9,7 @@ #include #include +#include #include //#include @@ -1310,6 +1311,237 @@ Geometry* GeoSet::convertToGeometry() } +IndexedGeometry* GeoSet::convertToIndexedGeometry() +{ + set_fast_path(); + computeNumVerts(); + + ref_ptr geom = osgNew IndexedGeometry; + geom->setStateSet(getStateSet()); + + if (_flat_shaded_skip) + { + // will need to add flat shading to primitive. + + StateSet* stateset = geom->getOrCreateStateSet(); + ShadeModel* shademodel = dynamic_cast(stateset->getAttribute(StateAttribute::SHADEMODEL)); + if (!shademodel) + { + shademodel = osgNew osg::ShadeModel; + stateset->setAttribute(shademodel); + } + shademodel->setMode( ShadeModel::FLAT ); + } + + switch(_normal_binding) + { + case(BIND_OFF): + geom->setNormalBinding(IndexedGeometry::BIND_OFF); + break; + case(BIND_OVERALL): + geom->setNormalBinding(IndexedGeometry::BIND_OVERALL); + break; + case(BIND_PERPRIM): + geom->setNormalBinding(IndexedGeometry::BIND_PER_PRIMITIVE); + break; + case(BIND_PERVERTEX): + geom->setNormalBinding(IndexedGeometry::BIND_PER_VERTEX); + break; + default: + geom->setNormalBinding(IndexedGeometry::BIND_OFF); + break; + } + + switch(_color_binding) + { + case(BIND_OFF): + geom->setColorBinding(IndexedGeometry::BIND_OFF); + break; + case(BIND_OVERALL): + geom->setColorBinding(IndexedGeometry::BIND_OVERALL); + break; + case(BIND_PERPRIM): + geom->setColorBinding(IndexedGeometry::BIND_PER_PRIMITIVE); + break; + case(BIND_PERVERTEX): + geom->setColorBinding(IndexedGeometry::BIND_PER_VERTEX); + break; + default: + geom->setColorBinding(IndexedGeometry::BIND_OFF); + break; + } + + if (_coords) + { + geom->setVertexArray(osgNew Vec3Array(_numcoords,_coords)); + if (_cindex.valid()) + { + if (_cindex._is_ushort) geom->setVertexIndices(osgNew UShortArray(_cindex._size,_cindex._ptr._ushort)); + else /* _nindex._is_uint*/ geom->setVertexIndices(osgNew UIntArray(_cindex._size,_cindex._ptr._uint)); + } + } + + if (_normals) + { + if (_flat_shaded_skip && _needprimlen && _normal_binding==BIND_PERVERTEX) + { + if (_nindex.valid()) + { + geom->setNormalArray(osgNew Vec3Array(_numnormals,_normals)); + if (_nindex._is_ushort) + { + UShortArray* indices = osgNew UShortArray; + int index=0; + for(int primNo = 0; primNo<_numprims; ++primNo) + { + for (int i=0;i<_primLengths[primNo];++i) + { + indices->push_back(_nindex._ptr._ushort[index]); + if (i>=_flat_shaded_skip) ++index; + } + } + geom->setNormalIndices(indices); + } + else + { + UIntArray* indices = osgNew UIntArray; + int index=0; + for(int primNo = 0; primNo<_numprims; ++primNo) + { + for (int i=0;i<_primLengths[primNo];++i) + { + indices->push_back(_nindex._ptr._uint[index]); + if (i>=_flat_shaded_skip) ++index; + } + } + geom->setNormalIndices(indices); + } + } + else + { + Vec3Array* normals = osgNew Vec3Array; + int index=0; + for(int primNo = 0; primNo<_numprims; ++primNo) + { + for (int i=0;i<_primLengths[primNo];++i) + { + normals->push_back(_normals[index]); + if (i>=_flat_shaded_skip) ++index; + } + } + geom->setNormalArray(normals); + } + } + else + { + // usual path. + geom->setNormalArray(osgNew Vec3Array(_numnormals,_normals)); + if (_nindex.valid()) + { + if (_nindex==_cindex) geom->setNormalIndices(geom->getVertexIndices()); + else if (_nindex._is_ushort) geom->setNormalIndices(osgNew UShortArray(_nindex._size,_nindex._ptr._ushort)); + else /* _nindex._is_uint*/ geom->setNormalIndices(osgNew UIntArray(_nindex._size,_nindex._ptr._uint)); + } + } + } + + if (_colors) + { + if (_flat_shaded_skip && _needprimlen && _color_binding==BIND_PERVERTEX) + { + if (_colindex.valid()) + { + geom->setColorArray(osgNew Vec4Array(_numcolors,_colors)); + if (_colindex==_nindex && _normal_binding==BIND_PERVERTEX) + { + geom->setColorIndices(geom->getNormalIndices()); + } + else if (_colindex._is_ushort) + { + UShortArray* indices = osgNew UShortArray; + int index=0; + for(int primNo = 0; primNo<_numprims; ++primNo) + { + for (int i=0;i<_primLengths[primNo];++i) + { + indices->push_back(_colindex._ptr._ushort[index]); + if (i>=_flat_shaded_skip) ++index; + } + } + geom->setColorIndices(indices); + } + else + { + UIntArray* indices = osgNew UIntArray; + int index=0; + for(int primNo = 0; primNo<_numprims; ++primNo) + { + for (int i=0;i<_primLengths[primNo];++i) + { + indices->push_back(_colindex._ptr._uint[index]); + if (i>=_flat_shaded_skip) ++index; + } + } + geom->setColorIndices(indices); + } + } + else + { + Vec4Array* colors = osgNew Vec4Array; + int index=0; + for(int primNo = 0; primNo<_numprims; ++primNo) + { + for (int i=0;i<_primLengths[primNo];++i) + { + colors->push_back(_colors[index]); + if (i>=_flat_shaded_skip) ++index; + } + } + geom->setColorArray(colors); + } + + } + else + { + // usual path. + geom->setColorArray(osgNew Vec4Array(_numcolors,_colors)); + if (_colindex.valid()) + { + if (_colindex==_cindex) geom->setColorIndices(geom->getVertexIndices()); + else if (_colindex==_nindex) geom->setColorIndices(geom->getNormalIndices()); + else if (_colindex._is_ushort) geom->setColorIndices(osgNew UShortArray(_colindex._size,_colindex._ptr._ushort)); + else /* _colindex._is_uint*/ geom->setColorIndices(osgNew UIntArray(_colindex._size,_colindex._ptr._uint)); + } + } + } + + if (_tcoords) + { + geom->setTexCoordArray(0,osgNew Vec2Array(_numtcoords,_tcoords)); + if (_tindex.valid()) + { + if (_tindex==_cindex) geom->setTexCoordIndices(0,geom->getVertexIndices()); + else if (_tindex==_nindex) geom->setTexCoordIndices(0,geom->getNormalIndices()); + else if (_tindex==_colindex) geom->setTexCoordIndices(0,geom->getColorIndices()); + else if (_tindex._is_ushort) geom->setTexCoordIndices(0,osgNew UShortArray(_tindex._size,_tindex._ptr._ushort)); + else /* _tindex._is_uint*/ geom->setTexCoordIndices(0,osgNew UIntArray(_tindex._size,_tindex._ptr._uint)); + } + } + + + if (_needprimlen) + { + geom->addPrimitiveSet(osgNew DrawArrayLengths((GLenum)_oglprimtype,0, _primLengths, _primLengths+_numprims )); + } + else + { + geom->addPrimitiveSet(osgNew DrawArrays((GLenum)_oglprimtype,0, _numcoords)); + } + + return geom.take(); + + +} diff --git a/src/osg/IndexedGeometry.cpp b/src/osg/IndexedGeometry.cpp index c908dc851..11af1d75b 100644 --- a/src/osg/IndexedGeometry.cpp +++ b/src/osg/IndexedGeometry.cpp @@ -236,9 +236,25 @@ Array* IndexedGeometry::getTexCoordArray(unsigned int unit) else return 0; } -const Array* IndexedGeometry::getTexCoordArray(unsigned int unit) const +void IndexedGeometry::setTexCoordIndices(unsigned int unit,IndexArray* array) { - if (unit<_texCoordList.size()) return _texCoordList[unit].first.get(); + if (_texCoordList.size()<=unit) + _texCoordList.resize(unit+1); + + _texCoordList[unit].second = array; + + dirtyDisplayList(); +} + +IndexArray* IndexedGeometry::getTexCoordIndices(unsigned int unit) +{ + if (unit<_texCoordList.size()) return _texCoordList[unit].second.get(); + else return 0; +} + +const IndexArray* IndexedGeometry::getTexCoordIndices(unsigned int unit) const +{ + if (unit<_texCoordList.size()) return _texCoordList[unit].second.get(); else return 0; } @@ -496,56 +512,47 @@ void IndexedGeometry::drawImmediateMode(State& state) } else { + PrimitiveSet* primitiveset = itr->get(); + GLenum mode=primitiveset->getMode(); + + unsigned int primLength; + switch(mode) + { + case(GL_POINTS): primLength=1; break; + case(GL_LINES): primLength=2; break; + case(GL_TRIANGLES): primLength=3; break; + case(GL_QUADS): primLength=4; break; + default: primLength=0; break; // compute later when =0. + } + + // draw primtives by the more flexible "slow" path, // sending OpenGL glBegin/glVertex.../glEnd(). - PrimitiveSet* primitiveset = itr->get(); switch(primitiveset->getType()) { case(PrimitiveSet::DrawArraysPrimitiveType): { + if (primLength==0) primLength=primitiveset->getNumIndices(); + const DrawArrays* drawArray = static_cast(primitiveset); - glBegin(primitiveset->getMode()); + glBegin(mode); unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount(); - for(unsigned int vindex=drawArray->getFirst(); - vindex!=indexEnd; - ++vindex) + for(unsigned int vindex=drawArray->getFirst();vindex(primitiveset); - GLenum mode = primitiveset->getMode(); - unsigned int vindex=drawArrayLengths->getFirst(); - for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin(); - primItr!=drawArrayLengths->end(); - ++primItr) - { - glBegin(mode); - - for(GLsizei count=0; - count<*primItr; - ++count,++vindex) - { if (normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); @@ -560,8 +567,59 @@ void IndexedGeometry::drawImmediateMode(State& state) if (drawTextCoord.valid()) (*drawTextCoord)(vindex); drawVertex(vindex); + ++vindex; } + } + + glEnd(); + break; + } + case(PrimitiveSet::DrawArrayLengthsPrimitiveType): + { + const DrawArrayLengths* drawArrayLengths = static_cast(primitiveset); + unsigned int vindex=drawArrayLengths->getFirst(); + for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin(); + primItr!=drawArrayLengths->end(); + ++primItr) + { + unsigned int localPrimLength; + if (primLength==0) localPrimLength=*primItr; + else localPrimLength=primLength; + + glBegin(mode); + + for(GLsizei count=0;count<*primItr;) + { + if (normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); + if (colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); + if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); + if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); + + for(unsigned int primCount=0; + primCountgetNumIndices(); + const DrawElementsUByte* drawElements = static_cast(primitiveset); - glBegin(primitiveset->getMode()); + glBegin(mode); for(DrawElementsUByte::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); - ++primItr) + ) { - unsigned int vindex=*primItr; + if (normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); + if (colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); + if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); + if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if (normalBinding==BIND_PER_VERTEX) drawNormal(vindex); - if (colorBinding==BIND_PER_VERTEX) drawColor(vindex); - if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); - if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); - - for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); - texItr!=drawTexCoordList.end(); - ++texItr) + for(unsigned int primCount=0; + primCountgetNumIndices(); + const DrawElementsUShort* drawElements = static_cast(primitiveset); - glBegin(primitiveset->getMode()); + glBegin(mode); for(DrawElementsUShort::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primItr) { - unsigned int vindex=*primItr; + if (normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); + if (colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); + if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); + if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if (normalBinding==BIND_PER_VERTEX) drawNormal(vindex); - if (colorBinding==BIND_PER_VERTEX) drawColor(vindex); - if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); - if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); - - for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); - texItr!=drawTexCoordList.end(); - ++texItr) + for(unsigned int primCount=0; + primCountgetNumIndices(); + const DrawElementsUInt* drawElements = static_cast(primitiveset); - glBegin(primitiveset->getMode()); + glBegin(mode); for(DrawElementsUInt::const_iterator primItr=drawElements->begin(); primItr!=drawElements->end(); ++primItr) { - unsigned int vindex=*primItr; + if (normalBinding==BIND_PER_PRIMITIVE) drawNormal(normalIndex++); + if (colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); + if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); + if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if (normalBinding==BIND_PER_VERTEX) drawNormal(vindex); - if (colorBinding==BIND_PER_VERTEX) drawColor(vindex); - if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); - if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); - - for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); - texItr!=drawTexCoordList.end(); - ++texItr) + for(unsigned int primCount=0; + primCount #include #include +#include #include #include #include @@ -15,6 +16,9 @@ using namespace osgUtil; +//#define CONVERT_GEOSET_TO_GEOMETRY +//#define CONVERT_GEOSET_TO_INDEXEDGEOMETRY + //////////////////////////////////////////////////////////////////////////// // Overall Optimizetion function. //////////////////////////////////////////////////////////////////////////// @@ -59,9 +63,11 @@ void Optimizer::optimize(osg::Node* node, unsigned int options) } +#if defined(CONVERT_GEOSET_TO_GEOMETRY) || defined(CONVERT_GEOSET_TO_INDEXEDGEOMETRY) // convert the old style GeoSet to Geometry -// ConvertGeoSetsToGeometryVisitor cgtg; -// node->accept(cgtg); + ConvertGeoSetsToGeometryVisitor cgtg; + node->accept(cgtg); +#endif if (options & SHARE_DUPLICATE_STATE) { @@ -127,16 +133,33 @@ void Optimizer::ConvertGeoSetsToGeometryVisitor::apply(osg::Geode& geode) osg::GeoSet* geoset = dynamic_cast(geode.getDrawable(i)); if (geoset) { - osg::Geometry* geom = geoset->convertToGeometry(); - if (geom) - { - std::cout<<"Successfully converted GeoSet to Geometry"<convertToGeometry(); + if (geom) + { + std::cout<<"Successfully converted GeoSet to Geometry"<convertToIndexedGeometry(); + if (geom) + { + std::cout<<"Successfully converted GeoSet to IndexedGeometry"<