From 8a14aa29cdd14e04cb438cc0b2efbb3e6dfb5b4d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 Jul 2002 22:23:57 +0000 Subject: [PATCH] Added support to osgUtil::Tesselator to insert extra vertices and other attributes into an osg::Geometry node. Uses the new osg::ArrayVisitor. Converted the osg plugin Geometry support to use the new UByte4 class. --- include/osgUtil/Tesselator | 54 ++++++++++- src/osgPlugins/osg/Geometry.cpp | 9 +- src/osgUtil/Tesselator.cpp | 158 +++++++++++++++++++++++++++----- 3 files changed, 193 insertions(+), 28 deletions(-) diff --git a/include/osgUtil/Tesselator b/include/osgUtil/Tesselator index 221a57781..a0120117d 100644 --- a/include/osgUtil/Tesselator +++ b/include/osgUtil/Tesselator @@ -70,7 +70,7 @@ class OSGUTIL_EXPORT Tesselator void begin(GLenum mode); void vertex(osg::Vec3* vertex); - void combine(osg::Vec3* vertex); + void combine(osg::Vec3* vertex,void* vertex_data[4],GLfloat weight[4]); void end(); void error(GLenum errorCode); @@ -90,11 +90,63 @@ class OSGUTIL_EXPORT Tesselator }; + struct NewVertex + { + + NewVertex(): + _f1(0), + _v1(0), + _f2(0), + _v2(0), + _f3(0), + _v3(0), + _f4(0), + _v4(0) {} + + NewVertex(const NewVertex& nv): + _f1(nv._f1), + _v1(nv._v1), + _f2(nv._f2), + _v2(nv._v2), + _f3(nv._f3), + _v3(nv._v3), + _f4(nv._f4), + _v4(nv._v4) {} + + NewVertex(float f1,osg::Vec3* v1, + float f2,osg::Vec3* v2, + float f3,osg::Vec3* v3, + float f4,osg::Vec3* v4): + _f1(f1), + _v1(v1), + _f2(f2), + _v2(v2), + _f3(f3), + _v3(v3), + _f4(f4), + _v4(v4) {} + + float _f1; + osg::Vec3* _v1; + + float _f2; + osg::Vec3* _v2; + + float _f3; + osg::Vec3* _v3; + + float _f4; + osg::Vec3* _v4; + + }; + + typedef std::map NewVertexList; typedef std::vector Vec3dList; GLUtesselator* _tobj; PrimList _primList; Vec3dList _coordData; + NewVertexList _newVertexList; GLenum _errorCode; }; diff --git a/src/osgPlugins/osg/Geometry.cpp b/src/osgPlugins/osg/Geometry.cpp index 4fc34a285..57cca7784 100644 --- a/src/osgPlugins/osg/Geometry.cpp +++ b/src/osgPlugins/osg/Geometry.cpp @@ -296,11 +296,14 @@ Array* Array_readLocalData(Input& fr) array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { - unsigned int uint_value; - if (fr[0].getUInt(uint_value)) + unsigned int r,g,b,a; + if (fr[0].getUInt(r) && + fr[1].getUInt(g) && + fr[2].getUInt(b) && + fr[3].getUInt(a)) { ++fr; - array->push_back(uint_value); + array->push_back(osg::UByte4(r,g,b,a)); } else ++fr; } diff --git a/src/osgUtil/Tesselator.cpp b/src/osgUtil/Tesselator.cpp index 023fe19af..a0df8aba4 100644 --- a/src/osgUtil/Tesselator.cpp +++ b/src/osgUtil/Tesselator.cpp @@ -93,9 +93,51 @@ void Tesselator::reset() } _primList.clear(); _coordData.clear(); + _newVertexList.clear(); _errorCode = 0; } +class InsertNewVertices : public osg::ArrayVisitor +{ + public: + + float _f1,_f2,_f3,_f4; + unsigned int _i1,_i2,_i3,_i4; + + InsertNewVertices(float f1,unsigned int i1, + float f2,unsigned int i2, + float f3,unsigned int i3, + float f4,unsigned int i4): + _f1(f1),_f2(f2),_f3(f3),_f4(f4), + _i1(i1),_i2(i2),_i3(i3),_i4(i4){} + + template + void apply_imp(A& array) + { + Type val; + if (_f1) val += static_cast(array[_i1] * _f1); + if (_f2) val += static_cast(array[_i2] * _f2); + if (_f3) val += static_cast(array[_i3] * _f3); + if (_f4) val += static_cast(array[_i4] * _f4); + + array.push_back(val); + } + + virtual void apply(osg::ByteArray& ba) { apply_imp(ba); } + virtual void apply(osg::ShortArray& ba) { apply_imp(ba); } + virtual void apply(osg::IntArray& ba) { apply_imp(ba); } + virtual void apply(osg::UByteArray& ba) { apply_imp(ba); } + virtual void apply(osg::UShortArray& ba) { apply_imp(ba); } + virtual void apply(osg::UIntArray& ba) { apply_imp(ba); } + virtual void apply(osg::UByte4Array& ba) { apply_imp(ba); } + virtual void apply(osg::FloatArray& ba) { apply_imp(ba); } + virtual void apply(osg::Vec2Array& ba) { apply_imp(ba); } + virtual void apply(osg::Vec3Array& ba) { apply_imp(ba); } + virtual void apply(osg::Vec4Array& ba) { apply_imp(ba); } + +}; + + void Tesselator::retesselatePolygons(osg::Geometry& geom) { Vec3Array* vertices = geom.getVertexArray(); @@ -163,8 +205,86 @@ void Tesselator::retesselatePolygons(osg::Geometry& geom) endContour(); endTesselation(); - Vec3* vbase = &(vertices->front()); - Vec3* vtop = &(vertices->back()); + typedef std::map VertexPtrToIndexMap; + VertexPtrToIndexMap vertexPtrToIndexMap; + + // populate the VertexPtrToIndexMap. + for(unsigned int vi=0;visize();++vi) + { + vertexPtrToIndexMap[&((*vertices)[vi])] = vi; + } + + if (!_newVertexList.empty()) + { + + osg::Vec3Array* normals = NULL; + if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX) + { + normals = geom.getNormalArray(); + } + + typedef std::vector ArrayList; + ArrayList arrays; + + if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX) + { + arrays.push_back(geom.getColorArray()); + } + + osg::Geometry::TexCoordArrayList& tcal = geom.getTexCoordArrayList(); + for(osg::Geometry::TexCoordArrayList::iterator tcalItr=tcal.begin(); + tcalItr!=tcal.end(); + ++tcalItr) + { + if (tcalItr->valid()) + { + arrays.push_back(tcalItr->get()); + } + } + + // now add any new vertices that are required. + for(NewVertexList::iterator itr=_newVertexList.begin(); + itr!=_newVertexList.end(); + ++itr) + { + osg::Vec3* vertex = itr->first; + NewVertex& newVertex = itr->second; + + // assign vertex. + vertexPtrToIndexMap[vertex]=vertices->size(); + vertices->push_back(*vertex); + + // assign normals + if (normals) + { + osg::Vec3 norm(0.0f,0.0f,0.0f); + if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1; + if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2; + if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3; + if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4; + norm.normalize(); + normals->push_back(norm); + } + + if (!arrays.empty()) + { + InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1], + newVertex._f2,vertexPtrToIndexMap[newVertex._v2], + newVertex._f3,vertexPtrToIndexMap[newVertex._v3], + newVertex._f4,vertexPtrToIndexMap[newVertex._v4]); + + // assign the rest of the attributes. + for(ArrayList::iterator aItr=arrays.begin(); + aItr!=arrays.end(); + ++aItr) + { + (*aItr)->accept(inv); + } + } + } + + } + for(PrimList::iterator primItr=_primList.begin(); primItr!=_primList.end(); @@ -177,17 +297,7 @@ void Tesselator::retesselatePolygons(osg::Geometry& geom) vitr!=prim->_vertices.end(); ++vitr) { - if (*vitrvtop) - { - // new vertex. - std::cout<<"Ooohhh we're getting funky, extra vertices need to be inserted"<push_back(i); - } + elements->push_back(vertexPtrToIndexMap[*vitr]); } if (primItr==_primList.begin()) @@ -218,16 +328,16 @@ void Tesselator::vertex(osg::Vec3* vertex) { Prim* prim = _primList.back().get(); prim->_vertices.push_back(vertex); + } } -void Tesselator::combine(osg::Vec3* vertex) +void Tesselator::combine(osg::Vec3* vertex,void* vertex_data[4],GLfloat weight[4]) { - if (!_primList.empty()) - { - Prim* prim = _primList.back().get(); - prim->_vertices.push_back(vertex); - } + _newVertexList[vertex]=NewVertex(weight[0],(Vec3*)vertex_data[0], + weight[1],(Vec3*)vertex_data[1], + weight[2],(Vec3*)vertex_data[2], + weight[3],(Vec3*)vertex_data[3]); } void Tesselator::end() @@ -255,14 +365,14 @@ void CALLBACK Tesselator::vertexCallback(GLvoid *data, void* userData) ((Tesselator*)userData)->vertex((Vec3*)data); } -void CALLBACK Tesselator::combineCallback(GLdouble coords[3], void* /*vertex_data*/[4], - GLfloat /*weight*/[4], void** outData, - void* userData) +void CALLBACK Tesselator::combineCallback(GLdouble coords[3], void* vertex_data[4], + GLfloat weight[4], void** outData, + void* /*userData*/) { - Vec3* newData = new osg::Vec3(coords[0],coords[2],coords[3]); + Vec3* newData = new osg::Vec3(coords[0],coords[1],coords[2]); *outData = newData; //((Tesselator*)userData)->combine(newData); - s_currentTesselator->combine(newData); + s_currentTesselator->combine(newData,vertex_data,weight); } void CALLBACK Tesselator::errorCallback(GLenum errorCode, void* userData)