diff --git a/include/osgUtil/ConvertVec b/include/osgUtil/ConvertVec new file mode 100644 index 000000000..15f65740b --- /dev/null +++ b/include/osgUtil/ConvertVec @@ -0,0 +1,139 @@ +/* -*-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_CONVERTVEC +#define OSGUTIL_CONVERTVEC 1 + +namespace osgUtil { + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + {} +}; + + + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y())); + } +}; + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y()), + static_cast(0.0)); + } +}; + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y()), + static_cast(0.0), + static_cast(1.0)); + } +}; + + + + + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y())); + } +}; + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y()), + static_cast(in.z())); + } +}; + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y()), + static_cast(in.z()), + static_cast(1.0)); + } +}; + + + + + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()/in.w()), + static_cast(in.y()/in.w())); + } +}; + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()/in.w()), + static_cast(in.y()/in.w()), + static_cast(in.z()/in.w())); + } +}; + +template +struct ConvertVec +{ + static void convert(InType & in, OutType & out) + { + out.set(static_cast(in.x()), + static_cast(in.y()), + static_cast(in.z()), + static_cast(in.w())); + } +}; + +} // end of osg namespace + +#endif // ** OSG_CONVERTVEC ** // diff --git a/include/osgUtil/EdgeCollector b/include/osgUtil/EdgeCollector new file mode 100644 index 000000000..333811306 --- /dev/null +++ b/include/osgUtil/EdgeCollector @@ -0,0 +1,210 @@ +/* -*-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_EDGECOLLECTOR +#define OSGUTIL_EDGECOLLECTOR 1 + + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace osgUtil { + + struct dereference_less + { + template + inline bool operator() (const T& lhs,const U& rhs) const + { + return *lhs < *rhs; + } + }; + + template + bool dereference_check_less(const T& lhs,const T& rhs) + { + if (lhs==rhs) return false; + if (!lhs) return true; + if (!rhs) return false; + return *lhs < *rhs; + } + + struct dereference_clear + { + template + inline void operator() (const T& t) + { + T& non_const_t = const_cast(t); + non_const_t->clear(); + } + }; + +class EdgeCollector +{ +public: + + struct Triangle; + struct Edge; + struct Edgeloop; + struct Point; + + + + typedef std::list > IndexArrayList; + + ~EdgeCollector(); + + void setGeometry(osg::Geometry* geometry); + osg::Geometry* getGeometry() { return _geometry; } + + unsigned int getNumOfTriangles() { return _triangleSet.size(); } + + typedef std::set,dereference_less > EdgeSet; + typedef std::vector > EdgeList; + typedef std::list< osg::ref_ptr > EdgeloopList; + typedef std::set< osg::ref_ptr,dereference_less > PointSet; + typedef std::vector< osg::ref_ptr > PointList; + typedef std::list< osg::ref_ptr > TriangleList; + typedef std::set< osg::ref_ptr > TriangleSet; + typedef std::map< osg::ref_ptr, unsigned int, dereference_less > TriangleMap; + + struct Point : public osg::Referenced + { + Point(): _protected(false), _index(0) {} + + bool _protected; + + unsigned int _index; + + osg::Vec3 _vertex; + TriangleSet _triangles; + + void clear() { _triangles.clear(); } + + bool operator < ( const Point& rhs) const { return _vertex < rhs._vertex; } + + bool isBoundaryPoint() const; + }; + + struct Edge : public osg::Referenced + { + void clear(); + + osg::ref_ptr _p1; + osg::ref_ptr _p2; + + osg::ref_ptr _op1; + osg::ref_ptr _op2; + + TriangleSet _triangles; + + + bool operator < ( const Edge& rhs) const; + + bool operator == ( const Edge& rhs) const; + + bool operator != ( const Edge& rhs) const; + + void setOrderedPoints(Point* p1, Point* p2); + + void addTriangle(Triangle* triangle) { _triangles.insert(triangle); } + + bool isBoundaryEdge() const { return _triangles.size()<=1; } + + bool isAdjacentToBoundary() const { return isBoundaryEdge() || _p1->isBoundaryPoint() || _p2->isBoundaryPoint(); } + + bool endConnected(const Edge& rhs) const { return (_op2 == rhs._op1); } + + bool beginConnected(const Edge& rhs) const { return (_op1 == rhs._op2); } + }; + + struct Triangle : public osg::Referenced + { + Triangle() {} + + void clear(); + + inline bool operator < (const Triangle& rhs) const; + + + void setOrderedPoints(Point* p1, Point* p2, Point* p3); + + float distance(const osg::Vec3& vertex) const { return _plane.distance(vertex); } + + bool isBoundaryTriangle() const + { return (_e1->isBoundaryEdge() || _e2->isBoundaryEdge() || _e3->isBoundaryEdge()); } + + + osg::ref_ptr _p1; + osg::ref_ptr _p2; + osg::ref_ptr _p3; + + osg::ref_ptr _op1; + osg::ref_ptr _op2; + osg::ref_ptr _op3; + + osg::ref_ptr _e1; + osg::ref_ptr _e2; + osg::ref_ptr _e3; + + osg::Plane _plane; + }; + + class Edgeloop : public osg::Referenced + { + public: + typedef std::vector > EdgeList; + + bool isClosed() { return (_edgeList.back()->endConnected(*_edgeList.front().get())); } + + osg::UIntArray * toIndexArray() const; + + EdgeList _edgeList; + }; + + + + Triangle* addTriangle(unsigned int p1, unsigned int p2, unsigned int p3); + Triangle* addTriangle(Point* p1, Point* p2, Point* p3); + + Edge* addEdge(Triangle* triangle, Point* p1, Point* p2); + + Point* addPoint(Triangle* triangle, unsigned int p1) { return addPoint(triangle,_originalPointList[p1].get()); } + Point* addPoint(Triangle* triangle, Point* point); + + void getBoundaryEdgeList(EdgeList & el); + bool extractBoundaryEdgeloop(EdgeList & el, Edgeloop & edgeloop); + bool extractBoundaryEdgeloopList(EdgeList & el, EdgeloopList & edgeloopList); + + void getEdgeloopIndexList(IndexArrayList & ial); + +//protected: + + osg::Geometry* _geometry; + + EdgeSet _edgeSet; + TriangleSet _triangleSet; + PointSet _pointSet; + PointList _originalPointList; + +}; + +} // end of osgUtil namespace + +#endif // ** OSGUTIL_EDGECOLLECTOR ** // diff --git a/include/osgUtil/OperationArrayFunctor b/include/osgUtil/OperationArrayFunctor new file mode 100644 index 000000000..92a1781b0 --- /dev/null +++ b/include/osgUtil/OperationArrayFunctor @@ -0,0 +1,103 @@ +#ifndef OSGUTIL_OPERATIONARRAYFUNCTOR +#define OSGUTIL_OPERATIONARRAYFUNCTOR 1 + + +#include +#include + +// ** template ArrayVisitor to handle all method in one template. +// ** Only use when process done on each array could be templated + +namespace osgUtil { + +template +class OperationArrayFunctor : public osg::ArrayVisitor, public T +{ + public: + + virtual void apply(osg::Array&) {} +// virtual void apply(osg::ByteArray& array) { T::process(array); } +// virtual void apply(osg::ShortArray& array) { T::process(array); } +// virtual void apply(osg::IntArray& array) { T::process(array); } +// virtual void apply(osg::UByteArray& array) { T::process(array); } +// virtual void apply(osg::UShortArray& array) { T::process(array); } +// virtual void apply(osg::UIntArray& array) { T::process(array); } +// virtual void apply(osg::FloatArray& array) { T::process(array); } +// virtual void apply(osg::DoubleArray& array) { T::process(array); } + + virtual void apply(osg::Vec2Array & array) { T::process(array); } + virtual void apply(osg::Vec3Array& array) { T::process(array); } + virtual void apply(osg::Vec4Array& array) { T::process(array); } + + virtual void apply(osg::Vec4ubArray& array) { T::process(array); } + + virtual void apply(osg::Vec2bArray& array) { T::process(array); } + virtual void apply(osg::Vec3bArray& array) { T::process(array); } + virtual void apply(osg::Vec4bArray& array) { T::process(array); } + + virtual void apply(osg::Vec2sArray& array) { T::process(array); } + virtual void apply(osg::Vec3sArray& array) { T::process(array); } + virtual void apply(osg::Vec4sArray& array) { T::process(array); } + + virtual void apply(osg::Vec2dArray& array) { T::process(array); } + virtual void apply(osg::Vec3dArray& array) { T::process(array); } + virtual void apply(osg::Vec4dArray& array) { T::process(array); } +}; + +struct AddRangeOperator +{ + template + void process(ArrayType & array) + { + typedef typename ArrayType::ElementDataType ElementDataType; + + ElementDataType convertedVector; + osgUtil::ConvertVec::convert(_vector, convertedVector); + + typename ArrayType::iterator it = array.begin(); + std::advance(it, _begin); + + typename ArrayType::iterator end = it; + std::advance(end, _count); + + for (; it < end; ++it) + (*it) += convertedVector; + } + + unsigned int _begin; + unsigned int _count; + + osg::Vec3 _vector; +}; +typedef OperationArrayFunctor AddRangeFunctor; + +struct MultiplyRangeOperator +{ + template + void process(ArrayType & array) + { + typedef typename ArrayType::ElementDataType ElementDataType; + + ElementDataType convertedVector; + osgUtil::ConvertVec::convert(_vector, convertedVector); + + typename ArrayType::iterator it = array.begin(); + std::advance(it, _begin); + + typename ArrayType::iterator end = it; + std::advance(end, _count); + + for (; it < end; ++it) + (*it) *= convertedVector; + } + + unsigned int _begin; + unsigned int _count; + + osg::Vec3 _vector; +}; +typedef OperationArrayFunctor MultiplyRangeFunctor; + +} // end osgUtil namespace + +#endif // ** OPERATIONARRAYFUNCTOR ** // diff --git a/include/osgUtil/ReversePrimitiveFunctor b/include/osgUtil/ReversePrimitiveFunctor new file mode 100644 index 000000000..49d72385c --- /dev/null +++ b/include/osgUtil/ReversePrimitiveFunctor @@ -0,0 +1,77 @@ +/* -*-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_REVERSEPRIMITIVEFUNCTOR +#define OSGUTIL_REVERSEPRIMITIVEFUNCTOR 1 + +#include +#include + +namespace osgUtil { + + +class ReversePrimitiveFunctor : public osg::PrimitiveIndexFunctor +{ +public: + + virtual ~ReversePrimitiveFunctor() {} + + osg::PrimitiveSet * getReversedPrimitiveSet() { return _reversedPrimitiveSet.get(); } + + 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; } + + + osg::ref_ptr _reversedPrimitiveSet; + + +}; + +} // end osgUtil namespace + +#endif // ** OSGUTIL_REVERSEFACEVISITOR ** // diff --git a/src/osgUtil/CMakeLists.txt b/src/osgUtil/CMakeLists.txt index 6e7d9acda..ebbbf70fe 100644 --- a/src/osgUtil/CMakeLists.txt +++ b/src/osgUtil/CMakeLists.txt @@ -9,17 +9,20 @@ ENDIF(DYNAMIC_OPENSCENEGRAPH) SET(LIB_NAME osgUtil) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(LIB_PUBLIC_HEADERS + ${HEADER_PATH}/ConvertVec ${HEADER_PATH}/CubeMapGenerator ${HEADER_PATH}/CullVisitor ${HEADER_PATH}/DelaunayTriangulator ${HEADER_PATH}/DisplayRequirementsVisitor + ${HEADER_PATH}/EdgeCollector ${HEADER_PATH}/Export ${HEADER_PATH}/GLObjectsVisitor ${HEADER_PATH}/HalfWayMapGenerator ${HEADER_PATH}/HighlightMapGenerator - ${HEADER_PATH}/IntersectVisitor ${HEADER_PATH}/IntersectionVisitor + ${HEADER_PATH}/IntersectVisitor ${HEADER_PATH}/LineSegmentIntersector + ${HEADER_PATH}/OperationArrayFunctor ${HEADER_PATH}/Optimizer ${HEADER_PATH}/PlaneIntersector ${HEADER_PATH}/PolytopeIntersector @@ -28,6 +31,7 @@ SET(LIB_PUBLIC_HEADERS ${HEADER_PATH}/RenderBin ${HEADER_PATH}/RenderLeaf ${HEADER_PATH}/RenderStage + ${HEADER_PATH}/ReversePrimitiveFunctor ${HEADER_PATH}/SceneView ${HEADER_PATH}/Simplifier ${HEADER_PATH}/SmoothingVisitor @@ -49,11 +53,12 @@ ADD_LIBRARY(${LIB_NAME} CullVisitor.cpp DelaunayTriangulator.cpp DisplayRequirementsVisitor.cpp + EdgeCollector.cpp GLObjectsVisitor.cpp HalfWayMapGenerator.cpp HighlightMapGenerator.cpp - IntersectVisitor.cpp IntersectionVisitor.cpp + IntersectVisitor.cpp LineSegmentIntersector.cpp Optimizer.cpp PlaneIntersector.cpp @@ -62,6 +67,7 @@ ADD_LIBRARY(${LIB_NAME} RenderBin.cpp RenderLeaf.cpp RenderStage.cpp + ReversePrimitiveFunctor.cpp SceneView.cpp Simplifier.cpp SmoothingVisitor.cpp @@ -71,11 +77,11 @@ ADD_LIBRARY(${LIB_NAME} Tessellator.cpp TransformAttributeFunctor.cpp TransformCallback.cpp - TriStripVisitor.cpp TriStrip_graph_array.h TriStrip_heap_array.h TriStrip_tri_stripper.cpp TriStrip_tri_stripper.h + TriStripVisitor.cpp UpdateVisitor.cpp Version.cpp ) diff --git a/src/osgUtil/EdgeCollector.cpp b/src/osgUtil/EdgeCollector.cpp new file mode 100644 index 000000000..2d0cd84ef --- /dev/null +++ b/src/osgUtil/EdgeCollector.cpp @@ -0,0 +1,457 @@ +/* -*-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. +*/ + +#include + +#include + +namespace osgUtil +{ + +bool EdgeCollector::Point::isBoundaryPoint() const +{ + if (_protected) return true; + + for(TriangleSet::const_iterator itr=_triangles.begin(); + itr!=_triangles.end(); + ++itr) + { + const Triangle* triangle = itr->get(); + if ((triangle->_e1->_p1==this || triangle->_e1->_p2==this) && triangle->_e1->isBoundaryEdge()) return true; + if ((triangle->_e2->_p1==this || triangle->_e2->_p2==this) && triangle->_e2->isBoundaryEdge()) return true; + if ((triangle->_e3->_p1==this || triangle->_e3->_p2==this) && triangle->_e3->isBoundaryEdge()) return true; + + //if ((*itr)->isBoundaryTriangle()) return true; + } + return false; +} + +void EdgeCollector::Edge::clear() +{ + _p1 = 0; + _p2 = 0; + _op1 = 0; + _op2 = 0; + _triangles.clear(); +} + + + +bool EdgeCollector::Edge::operator < ( const Edge& rhs) const +{ + if (dereference_check_less(_p1,rhs._p1)) return true; + if (dereference_check_less(rhs._p1,_p1)) return false; + + return dereference_check_less(_p2,rhs._p2); +} + +bool EdgeCollector::Edge::operator == ( const Edge& rhs) const +{ + if (&rhs==this) return true; + if (*this_vertex,_op2->_vertex,_op3->_vertex); +} + + + + +osg::UIntArray * EdgeCollector::Edgeloop::toIndexArray() const +{ + osg::UIntArray * indexArray = new osg::UIntArray; + + EdgeList::const_iterator it = _edgeList.begin(), end = _edgeList.end(); + + for (;it != end; ++it) + indexArray->push_back((*it)->_op1->_index); + + return indexArray; +} + +EdgeCollector::Triangle* EdgeCollector::addTriangle(unsigned int p1, unsigned int p2, unsigned int p3) +{ + //osg::notify(osg::NOTICE)<<"addTriangle("<_vertex == _originalPointList[p2]->_vertex) || + (_originalPointList[p2]->_vertex == _originalPointList[p3]->_vertex) || + (_originalPointList[p3]->_vertex == _originalPointList[p1]->_vertex)) return 0; + + Triangle* triangle = new Triangle; + + triangle->setOrderedPoints(addPoint(triangle, p1), addPoint(triangle, p2), addPoint(triangle, p3)); + + triangle->_e1 = addEdge(triangle, triangle->_op1.get(), triangle->_op2.get()); + triangle->_e2 = addEdge(triangle, triangle->_op2.get(), triangle->_op3.get()); + triangle->_e3 = addEdge(triangle, triangle->_op3.get(), triangle->_op1.get()); + + _triangleSet.insert(triangle); + + return triangle; +} + +EdgeCollector::Triangle* EdgeCollector::addTriangle(Point* p1, Point* p2, Point* p3) +{ + // osg::notify(osg::NOTICE)<<" addTriangle("<_vertex == p2->_vertex) || + (p2->_vertex == p3->_vertex) || + (p3->_vertex == p1->_vertex)) return 0; + + Triangle* triangle = new Triangle; + + triangle->setOrderedPoints(addPoint(triangle, p1), addPoint(triangle, p2), addPoint(triangle, p3)); + + triangle->_e1 = addEdge(triangle, triangle->_op1.get(), triangle->_op2.get()); + triangle->_e2 = addEdge(triangle, triangle->_op2.get(), triangle->_op3.get()); + triangle->_e3 = addEdge(triangle, triangle->_op3.get(), triangle->_op1.get()); + + _triangleSet.insert(triangle); + + return triangle; + } + + +EdgeCollector::Edge* EdgeCollector::addEdge(Triangle* triangle, Point* p1, Point* p2) +{ + // osg::notify(osg::NOTICE)<<" addEdge("< edge = new Edge; + edge->setOrderedPoints(p1,p2); + + EdgeSet::iterator itr = _edgeSet.find(edge); + if (itr==_edgeSet.end()) + { + // osg::notify(osg::NOTICE)<<" addEdge("<_p1="<_p1.get()<<" _p2="<_p2.get()<_p1="<_p1.get()<<" _p2="<_p2.get()<addTriangle(triangle); + + return edge.get(); +} + + + + +EdgeCollector::Point* EdgeCollector::addPoint(Triangle* triangle, Point* point) +{ + + PointSet::iterator itr = _pointSet.find(point); + if (itr==_pointSet.end()) + { + //osg::notify(osg::NOTICE)<<" addPoint("<(itr->get()); + //osg::notify(osg::NOTICE)<<" reusePoint("<_triangles.insert(triangle); + + return point; +} + +void EdgeCollector::getBoundaryEdgeList(EdgeList & el) +{ + for (EdgeSet::iterator it = _edgeSet.begin(), end = _edgeSet.end(); it != end; ++it) + { + if ((*it)->isBoundaryEdge()) el.push_back(*it); + } +} + +bool EdgeCollector::extractBoundaryEdgeloop(EdgeList & el, Edgeloop & edgeloop) +{ + if (el.empty()) return false; + + + osg::ref_ptr current = el.back(); + el.pop_back(); + + // ** init the Edgeloop + edgeloop._edgeList.push_back(current.get()); + + + + bool done = false; + while (!done) + { + bool found = false; + EdgeList::iterator it = el.begin(), end = el.end(); + while (it != end && !found) + { + if (current->endConnected(*(it->get()))) + { + found = true; + } + else + { + ++it; + } + } + + if (!found) + { + osg::notify(osg::WARN) << "extractBoundaryEdgeloop : unable to close edge loop" << std::endl; + return false; + } + else + { + edgeloop._edgeList.push_back(it->get()); + current = it->get(); + el.erase(it); + + if (edgeloop.isClosed()) done = true; + } + } + return true; +} + +bool EdgeCollector::extractBoundaryEdgeloopList(EdgeList & el, EdgeloopList & edgeloopList) +{ + while (!el.empty()) + { + osg::ref_ptr edgeloop(new Edgeloop); + + if (extractBoundaryEdgeloop(el, *edgeloop)) + edgeloopList.push_back(edgeloop); + else + return false; + } + return true; +} + + + + + + + +struct CollectTriangleOperator +{ + + CollectTriangleOperator():_ec(0) {} + + void setEdgeCollector(EdgeCollector* ec) { _ec = ec; } + + EdgeCollector* _ec; + + // for use in the triangle functor. + inline void operator()(unsigned int p1, unsigned int p2, unsigned int p3) + { + _ec->addTriangle(p1,p2,p3); + } + +}; + + +typedef osg::TriangleIndexFunctor CollectTriangleIndexFunctor; + +class CopyVertexArrayToPointsVisitor : public osg::ArrayVisitor +{ + public: + CopyVertexArrayToPointsVisitor(EdgeCollector::PointList& pointList): + _pointList(pointList) {} + + virtual void apply(osg::Vec2Array& 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; + + osg::Vec2& value = array[i]; + osg::Vec3& vertex = _pointList[i]->_vertex; + vertex.set(value.x(),value.y(),0.0f); + } + } + + virtual void apply(osg::Vec3Array& 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::Vec4Array& 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; + + 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()); + } + } + + EdgeCollector::PointList& _pointList; +}; + +EdgeCollector::~EdgeCollector() +{ + std::for_each(_edgeSet.begin(),_edgeSet.end(),dereference_clear()); + + std::for_each(_triangleSet.begin(),_triangleSet.end(),dereference_clear()); + std::for_each(_pointSet.begin(),_pointSet.end(),dereference_clear()); + std::for_each(_originalPointList.begin(),_originalPointList.end(),dereference_clear()); +} + + +void EdgeCollector::setGeometry(osg::Geometry* geometry) +{ + _geometry = geometry; + + // check to see if vertex attributes indices exists, if so expand them to remove them + if (_geometry->suitableForOptimization()) + { + // removing coord indices + osg::notify(osg::INFO)<<"EdgeCollector::setGeometry(..): Removing attribute indices"<copyToAndOptimize(*_geometry); + } + + unsigned int numVertices = geometry->getVertexArray()->getNumElements(); + + _originalPointList.resize(numVertices); + + // copy vertices across to local point list + CopyVertexArrayToPointsVisitor copyVertexArrayToPoints(_originalPointList); + _geometry->getVertexArray()->accept(copyVertexArrayToPoints); + + CollectTriangleIndexFunctor collectTriangles; + collectTriangles.setEdgeCollector(this); + + _geometry->accept(collectTriangles); +} + +// ** search BoundaryEdgeloop in the geometry, extrude this loop +// ** and create primitiveSet to link original loop and extruded loop +void EdgeCollector::getEdgeloopIndexList(IndexArrayList & ial) +{ + // ** collect Boundary Edge + EdgeList edgeList; + getBoundaryEdgeList(edgeList); + + // ** collect Edgeloop + EdgeloopList edgeloopList; + if (extractBoundaryEdgeloopList(edgeList, edgeloopList) == false) + { + osg::notify(osg::WARN) << "EdgeCollector: fail to collect Edgeloop.\n\n\n" << std::endl; + return; + } + + // ** get IndexArray of each Edgeloop + EdgeloopList::iterator elIt, elEnd = edgeloopList.end(); + for (elIt = edgeloopList.begin(); elIt != elEnd; ++elIt) + { + ial.push_back((*elIt)->toIndexArray()); + } +} + +} // end of osgUtil namespace diff --git a/src/osgUtil/ReversePrimitiveFunctor.cpp b/src/osgUtil/ReversePrimitiveFunctor.cpp new file mode 100644 index 000000000..4dbacf009 --- /dev/null +++ b/src/osgUtil/ReversePrimitiveFunctor.cpp @@ -0,0 +1,112 @@ +/* -*-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. +*/ + +#include + + +template +osg::PrimitiveSet * drawElementsTemplate(GLenum mode,GLsizei count, const typename Type::value_type* indices) +{ + if (indices==0 || count==0) return NULL; + + Type * dePtr = new Type(mode); + Type & de = *dePtr; + de.reserve(count); + + typedef const typename Type::value_type* IndexPointer; + + switch(mode) + { + case(GL_TRIANGLES): + { + IndexPointer ilast = &indices[count]; + + for (IndexPointer iptr=indices; iptr(mode, count, indices); +} +void ReversePrimitiveFunctor::drawElements(GLenum mode,GLsizei count,const GLushort* indices) +{ + _reversedPrimitiveSet = drawElementsTemplate(mode, count, indices); +} +void ReversePrimitiveFunctor::drawElements(GLenum mode,GLsizei count,const GLuint* indices) +{ + _reversedPrimitiveSet = drawElementsTemplate(mode, count, indices); +} + +} // end osgUtil namespace