From 2aca19a4e649d1a0b534dbf323388ee669ae9286 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 26 Dec 2007 21:39:29 +0000 Subject: [PATCH] From David Callu, further work in support of shapefile support in VirtualPlanetBuilder --- include/osgUtil/DrawElementTypeSimplifier | 38 +++++++ include/osgUtil/EdgeCollector | 8 +- include/osgUtil/OperationArrayFunctor | 8 +- include/osgUtil/ReversePrimitiveFunctor | 68 +++++------- src/osgUtil/CMakeLists.txt | 2 + src/osgUtil/DrawElementTypeSimplifier.cpp | 83 ++++++++++++++ src/osgUtil/EdgeCollector.cpp | 48 +++++++- src/osgUtil/ReversePrimitiveFunctor.cpp | 105 ++++++++++++++++++ src/osgWrappers/osgUtil/EdgeCollector.cpp | 2 +- .../osgUtil/ReversePrimitiveFunctor.cpp | 4 +- 10 files changed, 308 insertions(+), 58 deletions(-) create mode 100644 include/osgUtil/DrawElementTypeSimplifier create mode 100644 src/osgUtil/DrawElementTypeSimplifier.cpp diff --git a/include/osgUtil/DrawElementTypeSimplifier b/include/osgUtil/DrawElementTypeSimplifier new file mode 100644 index 000000000..3af8cf94a --- /dev/null +++ b/include/osgUtil/DrawElementTypeSimplifier @@ -0,0 +1,38 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ +#ifndef OSGUTIL_DRAWELEMENTTYPESIMPLIFIER +#define OSGUTIL_DRAWELEMENTTYPESIMPLIFIER + + +#include +#include + +namespace osgUtil +{ + +class DrawElementTypeSimplifier +{ + public: + void simplify(osg::Geometry & geometry) const; +}; + +class DrawElementTypeSimplifierVisitor : public osg::NodeVisitor +{ + public: + + void apply(osg::Geode& node); +}; + +} + +#endif // ** OSGUTIL_DRAWELEMENTTYPESIMPLIFIER ** // diff --git a/include/osgUtil/EdgeCollector b/include/osgUtil/EdgeCollector index 4113d9ba6..d4242d6ee 100644 --- a/include/osgUtil/EdgeCollector +++ b/include/osgUtil/EdgeCollector @@ -25,6 +25,9 @@ #include #include +#include + + namespace osgUtil { struct dereference_less @@ -55,7 +58,8 @@ namespace osgUtil { } }; -class EdgeCollector + +class OSGUTIL_EXPORT EdgeCollector { public: @@ -92,7 +96,7 @@ public: unsigned int _index; - osg::Vec3 _vertex; + osg::Vec3d _vertex; TriangleSet _triangles; void clear() { _triangles.clear(); } diff --git a/include/osgUtil/OperationArrayFunctor b/include/osgUtil/OperationArrayFunctor index b95960781..740c1bf8e 100644 --- a/include/osgUtil/OperationArrayFunctor +++ b/include/osgUtil/OperationArrayFunctor @@ -65,7 +65,7 @@ struct AddRangeOperator typedef typename ArrayType::ElementDataType ElementDataType; ElementDataType convertedVector; - osgUtil::ConvertVec::convert(_vector, convertedVector); + osgUtil::ConvertVec::convert(_vector, convertedVector); typename ArrayType::iterator it = array.begin(); std::advance(it, _begin); @@ -80,7 +80,7 @@ struct AddRangeOperator unsigned int _begin; unsigned int _count; - osg::Vec3 _vector; + osg::Vec3d _vector; }; typedef OperationArrayFunctor AddRangeFunctor; @@ -92,7 +92,7 @@ struct MultiplyRangeOperator typedef typename ArrayType::ElementDataType ElementDataType; ElementDataType convertedVector; - osgUtil::ConvertVec::convert(_vector, convertedVector); + osgUtil::ConvertVec::convert(_vector, convertedVector); typename ArrayType::iterator it = array.begin(); std::advance(it, _begin); @@ -107,7 +107,7 @@ struct MultiplyRangeOperator unsigned int _begin; unsigned int _count; - osg::Vec3 _vector; + osg::Vec3d _vector; }; typedef OperationArrayFunctor MultiplyRangeFunctor; diff --git a/include/osgUtil/ReversePrimitiveFunctor b/include/osgUtil/ReversePrimitiveFunctor index 49d72385c..b441af269 100644 --- a/include/osgUtil/ReversePrimitiveFunctor +++ b/include/osgUtil/ReversePrimitiveFunctor @@ -22,54 +22,36 @@ namespace osgUtil { class ReversePrimitiveFunctor : public osg::PrimitiveIndexFunctor { -public: - - virtual ~ReversePrimitiveFunctor() {} - - osg::PrimitiveSet * getReversedPrimitiveSet() { return _reversedPrimitiveSet.get(); } + public: - virtual void setVertexArray(unsigned int /*count*/,const osg::Vec2* /*vertices*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void setVertexArray(unsigned int /*count*/,const osg::Vec3* /*vertices*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void setVertexArray(unsigned int /*count*/,const osg::Vec4* /*vertices*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void setVertexArray(unsigned int /*count*/,const osg::Vec2d* /*vertices*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void setVertexArray(unsigned int /*count*/,const osg::Vec3d* /*vertices*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void setVertexArray(unsigned int /*count*/,const osg::Vec4d* /*vertices*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void drawArrays(GLenum /*mode*/,GLint /*first*/,GLsizei /*count*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices); - - virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices); - - virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices); - - - /// Mimics the OpenGL \c glBegin() function. - virtual void begin(GLenum /*mode*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void vertex(unsigned int /*pos*/) - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } - - virtual void end() - { osg::notify(osg::WARN) << "ReversePrimitiveFunctor : not implemented " << std::endl; } + virtual ~ReversePrimitiveFunctor() {} + osg::PrimitiveSet * getReversedPrimitiveSet() { return _reversedPrimitiveSet.get(); } + + virtual void setVertexArray(unsigned int , const osg::Vec2* ) {} + virtual void setVertexArray(unsigned int , const osg::Vec3* ) {} + virtual void setVertexArray(unsigned int , const osg::Vec4* ) {} + virtual void setVertexArray(unsigned int , const osg::Vec2d* ) {} + virtual void setVertexArray(unsigned int , const osg::Vec3d* ) {} + virtual void setVertexArray(unsigned int , const osg::Vec4d* ) {} - osg::ref_ptr _reversedPrimitiveSet; + virtual void drawArrays(GLenum mode,GLint first,GLsizei count); + virtual void drawElements(GLenum mode,GLsizei count, const GLubyte* indices); + virtual void drawElements(GLenum mode,GLsizei count, const GLushort* indices); + virtual void drawElements(GLenum mode,GLsizei count, const GLuint* indices); + + /// Mimics the OpenGL \c glBegin() function. + virtual void begin(GLenum mode); + virtual void vertex(unsigned int /*pos*/); + virtual void end(); + + + osg::ref_ptr _reversedPrimitiveSet; + private: + + bool _running; }; } // end osgUtil namespace diff --git a/src/osgUtil/CMakeLists.txt b/src/osgUtil/CMakeLists.txt index ebbbf70fe..c84daea9c 100644 --- a/src/osgUtil/CMakeLists.txt +++ b/src/osgUtil/CMakeLists.txt @@ -14,6 +14,7 @@ SET(LIB_PUBLIC_HEADERS ${HEADER_PATH}/CullVisitor ${HEADER_PATH}/DelaunayTriangulator ${HEADER_PATH}/DisplayRequirementsVisitor + ${HEADER_PATH}/DrawElementTypeSimplifier ${HEADER_PATH}/EdgeCollector ${HEADER_PATH}/Export ${HEADER_PATH}/GLObjectsVisitor @@ -53,6 +54,7 @@ ADD_LIBRARY(${LIB_NAME} CullVisitor.cpp DelaunayTriangulator.cpp DisplayRequirementsVisitor.cpp + DrawElementTypeSimplifier.cpp EdgeCollector.cpp GLObjectsVisitor.cpp HalfWayMapGenerator.cpp diff --git a/src/osgUtil/DrawElementTypeSimplifier.cpp b/src/osgUtil/DrawElementTypeSimplifier.cpp new file mode 100644 index 000000000..8ac8c45a3 --- /dev/null +++ b/src/osgUtil/DrawElementTypeSimplifier.cpp @@ -0,0 +1,83 @@ +#include + +#include + +template +OutType * copy(InType& array) +{ + unsigned int size = array.size(); + OutType * newArray = new OutType(array.getMode(), size); + OutType & na = *newArray; + + for (unsigned int i = 0; i < size; ++i) na[i] = array[i]; + + return newArray; +} + +template +unsigned int getMax(InType& array) +{ + unsigned int max = 0; + unsigned int size = array.size(); + + for (unsigned int i = 0; i < size; ++i) + { + if (array[i] > max) max = array[i]; + } + return (max); +} + +namespace osgUtil +{ + + +void DrawElementTypeSimplifier::simplify(osg::Geometry & geometry) const +{ + osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); + osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); + + unsigned int max = 0; + + for (it = psl.begin(); it!=end; ++it) + { + switch ((*it)->getType()) + { + case osg::PrimitiveSet::DrawElementsUShortPrimitiveType: + { + osg::DrawElementsUShort & de = *static_cast(it->get()); + + max = getMax(de); + if (max < 255) *it = copy(de); + + break; + } + case osg::PrimitiveSet::DrawElementsUIntPrimitiveType: + { + osg::DrawElementsUInt & de = *static_cast(it->get()); + + max = getMax(de); + if (max < 256) *it = copy(de); + else if (max < 65536) *it = copy(de); + + break; + } + default: break; + } + } +} + +void DrawElementTypeSimplifierVisitor::apply(osg::Geode& node) +{ + DrawElementTypeSimplifier dets; + + unsigned int numDrawables = node.getNumDrawables(); + for (unsigned int i = 0; i != numDrawables; ++i) + { + osg::Geometry * geom = dynamic_cast(node.getDrawable(i)); + if (geom) dets.simplify(*geom); + } + + osg::NodeVisitor::apply((osg::Node&)node); +} + +} diff --git a/src/osgUtil/EdgeCollector.cpp b/src/osgUtil/EdgeCollector.cpp index 2d0cd84ef..72f04c021 100644 --- a/src/osgUtil/EdgeCollector.cpp +++ b/src/osgUtil/EdgeCollector.cpp @@ -12,6 +12,7 @@ */ #include +#include #include @@ -357,9 +358,7 @@ class CopyVertexArrayToPointsVisitor : public osg::ArrayVisitor _pointList[i] = new EdgeCollector::Point; _pointList[i]->_index = i; - osg::Vec2& value = array[i]; - osg::Vec3& vertex = _pointList[i]->_vertex; - vertex.set(value.x(),value.y(),0.0f); + osgUtil::ConvertVec::convert(array[i], _pointList[i]->_vertex); } } @@ -385,9 +384,46 @@ class CopyVertexArrayToPointsVisitor : public osg::ArrayVisitor _pointList[i] = new EdgeCollector::Point; _pointList[i]->_index = i; - osg::Vec4& value = array[i]; - osg::Vec3& vertex = _pointList[i]->_vertex; - vertex.set(value.x()/value.w(),value.y()/value.w(),value.z()/value.w()); + osgUtil::ConvertVec::convert(array[i], _pointList[i]->_vertex); + } + } + + virtual void apply(osg::Vec2dArray& array) + { + if (_pointList.size()!=array.size()) return; + + for(unsigned int i=0;i<_pointList.size();++i) + { + _pointList[i] = new EdgeCollector::Point; + _pointList[i]->_index = i; + + osgUtil::ConvertVec::convert(array[i], _pointList[i]->_vertex); + } + } + + virtual void apply(osg::Vec3dArray& array) + { + if (_pointList.size()!=array.size()) return; + + for(unsigned int i=0;i<_pointList.size();++i) + { + _pointList[i] = new EdgeCollector::Point; + _pointList[i]->_index = i; + + _pointList[i]->_vertex = array[i]; + } + } + + virtual void apply(osg::Vec4dArray& array) + { + if (_pointList.size()!=array.size()) return; + + for(unsigned int i=0;i<_pointList.size();++i) + { + _pointList[i] = new EdgeCollector::Point; + _pointList[i]->_index = i; + + osgUtil::ConvertVec::convert(array[i], _pointList[i]->_vertex); } } diff --git a/src/osgUtil/ReversePrimitiveFunctor.cpp b/src/osgUtil/ReversePrimitiveFunctor.cpp index e4709f03d..0526fd209 100644 --- a/src/osgUtil/ReversePrimitiveFunctor.cpp +++ b/src/osgUtil/ReversePrimitiveFunctor.cpp @@ -97,6 +97,76 @@ osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typena namespace osgUtil { +void ReversePrimitiveFunctor::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + if (count==0) return ; + + osg::DrawElementsUInt * dePtr = new osg::DrawElementsUInt(mode); + osg::DrawElementsUInt & de = *dePtr; + de.reserve(count); + + GLint end = first + count; + + switch (mode) + { + case (GL_TRIANGLES): + { + for (GLint i=first; ifirst; i--) + de.push_back(i); + + break; + } + case (GL_POLYGON): + case (GL_POINTS): + case (GL_LINES): + case (GL_LINE_STRIP): + case (GL_LINE_LOOP): + { + for (GLint i=end-1; i>=first; i--) + de.push_back(i); + + break; + } + default: + break; + } + + _reversedPrimitiveSet = &de; +} + void ReversePrimitiveFunctor::drawElements(GLenum mode,GLsizei count,const GLubyte* indices) { _reversedPrimitiveSet = drawElementsTemplate(mode, count, indices); @@ -110,4 +180,39 @@ void ReversePrimitiveFunctor::drawElements(GLenum mode,GLsizei count,const GLuin _reversedPrimitiveSet = drawElementsTemplate(mode, count, indices); } +void ReversePrimitiveFunctor::begin(GLenum mode) +{ + if (_running) + osg::notify(osg::WARN) << "ReversePrimitiveFunctor : call \"begin\" without call \"end\"." << std::endl; + else + { + _running = true; + + _reversedPrimitiveSet = new osg::DrawElementsUInt(mode); + } +} + +void ReversePrimitiveFunctor::vertex(unsigned int pos) +{ + if (_running == false) + osg::notify(osg::WARN) << "ReversePrimitiveFunctor : call \"vertex(" << pos << ")\" without call \"begin\"." << std::endl; + else + { + static_cast(_reversedPrimitiveSet.get())->push_back(pos); + } +} + +void ReversePrimitiveFunctor::end() +{ + if (_running == false) + osg::notify(osg::WARN) << "ReversePrimitiveFunctor : call \"end\" without call \"begin\"." << std::endl; + else + { + _running = false; + + osg::ref_ptr tmpDe(static_cast(_reversedPrimitiveSet.get())); + + _reversedPrimitiveSet = drawElementsTemplate(tmpDe->getMode(), tmpDe->size(), &(tmpDe->front())); + } +} } // end osgUtil namespace diff --git a/src/osgWrappers/osgUtil/EdgeCollector.cpp b/src/osgWrappers/osgUtil/EdgeCollector.cpp index 7fd6ccfe0..bd89e0cfe 100644 --- a/src/osgWrappers/osgUtil/EdgeCollector.cpp +++ b/src/osgWrappers/osgUtil/EdgeCollector.cpp @@ -217,7 +217,7 @@ BEGIN_OBJECT_REFLECTOR(osgUtil::EdgeCollector::Point) ""); I_PublicMemberProperty(bool, _protected); I_PublicMemberProperty(unsigned int, _index); - I_PublicMemberProperty(osg::Vec3, _vertex); + I_PublicMemberProperty(osg::Vec3d, _vertex); I_PublicMemberProperty(osgUtil::EdgeCollector::TriangleSet, _triangles); END_REFLECTOR diff --git a/src/osgWrappers/osgUtil/ReversePrimitiveFunctor.cpp b/src/osgWrappers/osgUtil/ReversePrimitiveFunctor.cpp index e3320c2b5..19ab0743e 100644 --- a/src/osgWrappers/osgUtil/ReversePrimitiveFunctor.cpp +++ b/src/osgWrappers/osgUtil/ReversePrimitiveFunctor.cpp @@ -68,7 +68,7 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osgUtil::ReversePrimitiveFunctor) __void__setVertexArray__unsigned__C5_osg_Vec4d_P1, "", ""); - I_Method3(void, drawArrays, IN, GLenum, x, IN, GLint, x, IN, GLsizei, x, + I_Method3(void, drawArrays, IN, GLenum, mode, IN, GLint, first, IN, GLsizei, count, Properties::VIRTUAL, __void__drawArrays__GLenum__GLint__GLsizei, "", @@ -88,7 +88,7 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osgUtil::ReversePrimitiveFunctor) __void__drawElements__GLenum__GLsizei__C5_GLuint_P1, "", ""); - I_Method1(void, begin, IN, GLenum, x, + I_Method1(void, begin, IN, GLenum, mode, Properties::VIRTUAL, __void__begin__GLenum, "Mimics the OpenGL glBegin() function. ",