Changeset 850
- Timestamp:
- 01/21/08 21:22:04
- Files:
-
- trunk/include/vpb/ExtrudeVisitor (modified) (4 diffs)
- trunk/src/vpb/ExtrudeVisitor.cpp (modified) (4 diffs)
- trunk/src/vpb/HeightFieldMapper.cpp (modified) (7 diffs)
- trunk/src/vpb/ShapeFilePlacer.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/vpb/ExtrudeVisitor
r811 r850 26 26 public: 27 27 28 enum Mode28 enum OutputMode 29 29 { 30 30 Replace, … … 32 32 }; 33 33 34 enum Type34 enum Mode 35 35 { 36 36 PER_VERTEX, … … 38 38 }; 39 39 40 ExtrudeVisitor() : _mode(Merge) {} 41 ExtrudeVisitor(Mode mode) : _mode(mode) {} 42 ExtrudeVisitor(Mode mode, osg::Vec3d & extrudeVector) : _mode(mode), _extrudeVector(extrudeVector) {} 40 ExtrudeVisitor() : _mode(PER_GEOMETRY), _outputMode(Merge) {} 41 ExtrudeVisitor(Mode mode) : _mode(mode), _outputMode(Merge) {} 42 ExtrudeVisitor(Mode mode, osg::Vec3d & extrudeVector) : _mode(mode), _outputMode(Merge), _extrudeVector(extrudeVector) {} 43 ExtrudeVisitor(Mode mode, OutputMode outputMode, osg::Vec3d & extrudeVector) : _mode(mode), _outputMode(outputMode), _extrudeVector(extrudeVector) {} 44 45 OutputMode getOutputMode() { return _outputMode; } 46 void setOutputMode(OutputMode outputMode) { _outputMode = outputMode; } 43 47 44 48 Mode getMode() { return _mode; } 45 49 void setMode(Mode mode) { _mode = mode; } 46 50 47 51 osg::Vec3d & getExtrudeVector() { return _extrudeVector; } 48 52 const osg::Vec3d & getExtrudeVector() const { return _extrudeVector; } 49 53 void setExtrudeVector(osg::Vec3d extrudeVector) { _extrudeVector = extrudeVector; } 50 54 51 void extrude(osg::Geometry& geometry , osg::Vec3d & extrudeVector);55 void extrude(osg::Geometry& geometry); 52 56 53 57 virtual void apply(osg::Geode& node); … … 58 62 osg::UIntArray & extrudeIndexArray); 59 63 Mode _mode; 64 OutputMode _outputMode; 65 60 66 osg::Vec3d _extrudeVector; 61 67 }; trunk/src/vpb/ExtrudeVisitor.cpp
r810 r850 48 48 typedef osgUtil::OperationArrayFunctor<DuplicateIndexOperator> DuplicateIndexFunctor; 49 49 50 struct DuplicateAndInterlaceOperator 51 { 52 template <typename ArrayType> 53 void process(ArrayType & array) 54 { 55 unsigned int size = array.size(); 56 osg::ref_ptr<ArrayType> newArray(new ArrayType(size * 2)); 57 ArrayType & refNewArray = *newArray.get(); 58 59 for (unsigned int i=0; i<size; ++i) 60 refNewArray[2*i] = refNewArray[2*i+1] = array[i]; 61 62 array = refNewArray; 63 } 64 }; 65 typedef osgUtil::OperationArrayFunctor<DuplicateAndInterlaceOperator> DuplicateAndInterlaceFunctor; 66 67 struct AddOddOperator 68 { 69 template <typename ArrayType> 70 void process(ArrayType & array) 71 { 72 typedef typename ArrayType::ElementDataType ElementDataType; 73 74 ElementDataType convertedVector; 75 osgUtil::ConvertVec<osg::Vec3d, ElementDataType>::convert(_vector, convertedVector); 76 77 78 std::size_t size = array.size(); 79 for (unsigned int i = 1; i<size; i+=2) 80 array[i] += convertedVector; 81 } 82 83 osg::Vec3d _vector; 84 }; 85 typedef osgUtil::OperationArrayFunctor<AddOddOperator> AddOddFunctor; 50 86 51 87 … … 64 100 // ** search BoundaryEdgeloop in the geometry, extrude this loop 65 101 // ** and create primitiveSet to link original loop and extruded loop 66 void ExtrudeVisitor::extrude(osg::Geometry& geometry , osg::Vec3d & extrudeVector)102 void ExtrudeVisitor::extrude(osg::Geometry& geometry) 67 103 { 68 104 // osg::notify(osg::INFO)<<"****************Extruder : Start ************"<<std::endl; … … 70 106 unsigned int originalVertexArraySize = geometry.getVertexArray()->getNumElements(); 71 107 72 73 74 // ** collect Edge 75 // osg::notify(osg::INFO)<<"****************Extruder : collect Points, Edges, Triangles"<<std::endl; 76 osgUtil::EdgeCollector ec; 77 ec.setGeometry(&geometry); 78 if (ec._triangleSet.size() == 0) return; 79 // osg::notify(osg::INFO)<<"****************Extruder : found " << ec._pointSet.size() << " Points"<<std::endl; 80 // osg::notify(osg::INFO)<<"****************Extruder : found " << ec._edgeSet.size() << " Edges"<<std::endl; 81 // osg::notify(osg::INFO)<<"****************Extruder : found " << ec._triangleSet.size() << " Triangles"<<std::endl; 82 83 84 // ** get IndexArray of each Edgeloop 85 86 osgUtil::EdgeCollector::IndexArrayList originalIndexArrayList; 87 osgUtil::EdgeCollector::IndexArrayList extrudedIndexArrayList; 88 89 ec.getEdgeloopIndexList(originalIndexArrayList); 90 osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 91 for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 108 109 if (_mode == PER_VERTEX) 92 110 { 93 extrudedIndexArrayList.push_back(new osg::UIntArray(*iaIt->get())); 94 } 95 96 _mode = Replace; 97 98 // ** replace geometry by extruded geometry 99 if (_mode == Replace) 111 // ** duplicate vertex 112 DuplicateAndInterlaceFunctor daif; 113 geometry.getVertexArray()->accept(daif); 114 115 // ** extrude vertex with odd index 116 AddOddFunctor aof; 117 aof._vector = _extrudeVector; 118 geometry.getVertexArray()->accept(aof); 119 120 geometry.getPrimitiveSetList().clear(); 121 geometry.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, geometry.getVertexArray()->getNumElements())); 122 123 } 124 else // if (_mode == PER_GEOMETRY) 100 125 { 101 // ** extrude vertexArray 102 // osg::notify(osg::INFO)<<"****************Extruder : Duplicate Edgeloop and Extrude VertexArray ************"<<std::endl; 103 104 105 unsigned int currentVertexArraySize = originalVertexArraySize; 106 107 DuplicateIndexFunctor dif; 126 // ** collect Edge 127 osgUtil::EdgeCollector ec; 128 ec.setGeometry(&geometry); 129 if (ec._triangleSet.size() == 0) return; 130 131 132 // ** get IndexArray of each Edgeloop 133 osgUtil::EdgeCollector::IndexArrayList originalIndexArrayList; 134 osgUtil::EdgeCollector::IndexArrayList extrudedIndexArrayList; 135 136 ec.getEdgeloopIndexList(originalIndexArrayList); 108 137 osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 109 138 for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 110 139 { 111 osg::UIntArray & indexArray = *(iaIt->get()); 112 113 // ** duplicate vertex indexed by indexArray 114 dif._indexArray = &indexArray; 115 geometry.getVertexArray()->accept(dif); 116 117 // ** remap indexArray 118 unsigned int size = indexArray.size(); 119 for (unsigned int i=0; i<size; ++i) 120 indexArray[i] = currentVertexArraySize + i; 121 122 currentVertexArraySize += size; 123 } 124 125 // ** extrude original vertex and keep original value in duplicate vertex 126 osgUtil::AddRangeFunctor erf; 127 erf._vector = extrudeVector; 128 erf._begin = 0; 129 erf._count = originalVertexArraySize; 130 131 geometry.getVertexArray()->accept(erf); 132 } 133 else //if (_mode == Merge) 134 { 135 // ** duplicate vertexArray 136 // osg::notify(osg::INFO)<<"****************Extruder : Duplicate and extrude VertexArray ************"<<std::endl; 137 138 // ** duplicate all vertex 139 DuplicateFunctor df; 140 geometry.getVertexArray()->accept(df); 141 142 // ** duplicate edgeloop index 143 osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 144 for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 145 { 146 osg::UIntArray & indexArray = *(iaIt->get()); 147 148 // ** remap indexArray 149 unsigned int size = indexArray.size(); 150 for (unsigned int i=0; i<size; ++i) 151 indexArray[i] += originalVertexArraySize; 152 } 153 154 // ** extrude original vertex and keep original value in duplicate vertex 155 osgUtil::AddRangeFunctor erf; 156 erf._vector = extrudeVector; 157 erf._begin = 0; 158 erf._count = originalVertexArraySize; 159 geometry.getVertexArray()->accept(erf); 160 161 // ** offset primitive's indices to draw duplicated vertex 162 osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 163 std::for_each(psl.begin(), psl.end(), OffsetIndices(originalVertexArraySize)); 164 165 } 166 167 168 169 170 171 172 bool reverseTopShape = true;//needReverseTopShape(extrudeVector, ); TODO 173 174 // osg::notify(osg::INFO)<<"****************Extruder : Make top primitiveSet List ************"<<std::endl; 175 { 176 osg::Geometry::PrimitiveSetList newPsl; 177 178 // ** for each primitive in geometry, we duplicate this primitive and reverse it if need 179 osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 180 osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); 181 for (it = psl.begin(); it != end; ++it) 182 { 183 osg::ref_ptr<osg::PrimitiveSet> newPs; 184 185 // ** duplicate 186 if (reverseTopShape) 140 extrudedIndexArrayList.push_back(new osg::UIntArray(*iaIt->get())); 141 } 142 143 // _outputMode = Replace; 144 145 // ** replace geometry by extruded geometry 146 if (_outputMode == Replace) 147 { 148 // ** extrude vertexArray 149 unsigned int currentVertexArraySize = originalVertexArraySize; 150 151 DuplicateIndexFunctor dif; 152 osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 153 for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 154 { 155 osg::UIntArray & indexArray = *(iaIt->get()); 156 157 // ** duplicate vertex indexed by indexArray 158 dif._indexArray = &indexArray; 159 geometry.getVertexArray()->accept(dif); 160 161 // ** remap indexArray 162 unsigned int size = indexArray.size(); 163 for (unsigned int i=0; i<size; ++i) 164 indexArray[i] = currentVertexArraySize + i; 165 166 currentVertexArraySize += size; 167 } 168 169 // ** extrude original vertex and keep original value in duplicate vertex 170 osgUtil::AddRangeFunctor erf; 171 erf._vector = _extrudeVector; 172 erf._begin = 0; 173 erf._count = originalVertexArraySize; 174 175 geometry.getVertexArray()->accept(erf); 176 } 177 else //if (_outputMode == Merge) 178 { 179 // ** duplicate all vertex 180 DuplicateFunctor df; 181 geometry.getVertexArray()->accept(df); 182 183 // ** duplicate edgeloop index 184 osgUtil::EdgeCollector::IndexArrayList::iterator iaIt, iaEnd = originalIndexArrayList.end(); 185 for (iaIt = originalIndexArrayList.begin(); iaIt != iaEnd; ++iaIt) 186 { 187 osg::UIntArray & indexArray = *(iaIt->get()); 188 189 // ** remap indexArray 190 unsigned int size = indexArray.size(); 191 for (unsigned int i=0; i<size; ++i) 192 indexArray[i] += originalVertexArraySize; 193 } 194 195 // ** extrude original vertex and keep original value in duplicate vertex 196 osgUtil::AddRangeFunctor erf; 197 erf._vector = _extrudeVector; 198 erf._begin = 0; 199 erf._count = originalVertexArraySize; 200 geometry.getVertexArray()->accept(erf); 201 202 // ** offset primitive's indices to draw duplicated vertex 203 osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 204 std::for_each(psl.begin(), psl.end(), OffsetIndices(originalVertexArraySize)); 205 206 } 207 208 209 210 211 212 // Make top primitiveSet List 213 bool reverseTopShape = false;//needReverseTopShape(extrudeVector, ); TODO 214 { 215 osg::Geometry::PrimitiveSetList newPsl; 216 217 // ** for each primitive in geometry, we duplicate this primitive and reverse it if need 218 osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); 219 osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); 220 for (it = psl.begin(); it != end; ++it) 221 { 222 osg::ref_ptr<osg::PrimitiveSet> newPs; 223 224 // ** duplicate 225 if (reverseTopShape) 226 { 227 osgUtil::ReversePrimitiveFunctor rpf; 228 (*it)->accept(rpf); 229 230 newPs = rpf.getReversedPrimitiveSet(); 231 } 232 else 233 { 234 newPs = static_cast<osg::PrimitiveSet*>((*it)->clone(osg::CopyOp::SHALLOW_COPY)); 235 } 236 237 if (newPs.valid()) 238 { 239 newPsl.push_back(newPs); 240 } 241 } 242 243 // ** Replace by or Merge new Primitives 244 if (_outputMode == Replace) 245 { 246 psl = newPsl; 247 } 248 else //if (_outputMode == Merge) 249 { 250 psl.insert(psl.end(), newPsl.begin(), newPsl.end()); 251 } 252 } 253 254 255 256 // ** link original and extruded Boundary Edgeloops 257 osgUtil::EdgeCollector::IndexArrayList::iterator oit, oend = originalIndexArrayList.end(); 258 osgUtil::EdgeCollector::IndexArrayList::iterator eit = extrudedIndexArrayList.begin(); 259 for (oit = originalIndexArrayList.begin(); oit != oend; ++oit, ++eit) 260 { 261 262 osg::ref_ptr<osg::DrawElementsUInt> de = linkAsTriangleStrip(*(*oit), *(*eit)); 263 264 // ** if bottom shape have up normal, we need to reverse the extruded face 265 if (reverseTopShape == false) 187 266 { 188 267 osgUtil::ReversePrimitiveFunctor rpf; 189 (*it)->accept(rpf);190 191 newPs = rpf.getReversedPrimitiveSet();268 de->accept(rpf); 269 270 geometry.addPrimitiveSet(rpf._reversedPrimitiveSet.get()); 192 271 } 193 272 else 194 273 { 195 newPs = static_cast<osg::PrimitiveSet*>((*it)->clone(osg::CopyOp::SHALLOW_COPY)); 196 } 197 198 if (newPs.valid()) 199 { 200 newPsl.push_back(newPs); 201 } 202 } 203 204 // ** Replace by or Merge new Primitives 205 if (_mode == Replace) 206 { 207 psl = newPsl; 208 } 209 else //if (_mode == Merge) 210 { 211 psl.insert(psl.end(), newPsl.begin(), newPsl.end()); 212 } 213 } 214 215 216 217 218 219 220 // osg::notify(osg::INFO)<<"****************Extruder : link original and extruded Boundary Edgeloops ************"<<std::endl; 221 // ** link original and extruded Boundary Edgeloops 222 223 osgUtil::EdgeCollector::IndexArrayList::iterator oit, oend = originalIndexArrayList.end(); 224 osgUtil::EdgeCollector::IndexArrayList::iterator eit = extrudedIndexArrayList.begin(); 225 for (oit = originalIndexArrayList.begin(); oit != oend; ++oit, ++eit) 226 { 227 228 osg::ref_ptr<osg::DrawElementsUInt> de = linkAsTriangleStrip(*(*oit), *(*eit)); 229 230 // ** if bottom shape have up normal, we need to reverse the extruded face 231 if (reverseTopShape == false) 232 { 233 osgUtil::ReversePrimitiveFunctor rpf; 234 de->accept(rpf); 235 236 geometry.addPrimitiveSet(rpf._reversedPrimitiveSet.get()); 237 } 238 else 239 { 240 // ** add the extruded face 241 geometry.addPrimitiveSet(de.get()); 242 } 243 } 244 245 246 osgUtil::SmoothingVisitor::smooth(geometry); 247 // osg::notify(osg::INFO)<<"****************Extruder : finish ************"<<std::endl; 274 // ** add the extruded face 275 geometry.addPrimitiveSet(de.get()); 276 } 277 } 278 279 280 osgUtil::SmoothingVisitor::smooth(geometry); 281 } 248 282 } 249 283 … … 281 315 if (geo) 282 316 { 283 extrude(*geo , _extrudeVector);317 extrude(*geo); 284 318 } 285 319 } trunk/src/vpb/HeightFieldMapper.cpp
r812 r850 23 23 #include <osgUtil/EdgeCollector> 24 24 #include <osgUtil/ConvertVec> 25 #include <osgUtil/Tessellator> 25 26 26 27 namespace vpb { … … 51 52 52 53 53 54 class ComputeCentroidVisitor : public osg::ArrayVisitor 54 class SetZeroToZVisitor : public osg::ArrayVisitor 55 55 { 56 56 public: 57 58 ComputeCentroidVisitor(osg::UIntArray & ia) : _ia(ia) {}59 60 57 61 58 void apply(osg::Vec3Array& array) { computeCentroid<osg::Vec3Array>(array); } … … 65 62 void apply(osg::Vec4dArray& array) { computeCentroid<osg::Vec4dArray>(array); } 66 63 67 #if 0 64 68 65 template <typename ArrayType> 69 66 void computeCentroid(ArrayType & array) 70 67 { 71 double area = 0.0; 72 double centroidTmp = 0.0; 73 double centroidX = 0.0; 74 double centroidY = 0.0; 75 76 osg::UIntArray::iterator it, end = _ia.end() - 1; 77 for (it = _ia.begin(); it != end; ++it) 78 { 79 typename ArrayType::ElementDataType & vec0 = array[*it]; 80 typename ArrayType::ElementDataType & vec1 = array[*(it + 1)]; 81 82 area += vec0.x() * vec1.y(); 83 area -= vec0.y() * vec1.x(); 84 85 centroidTmp = (vec0.x() * vec1.y() - vec1.x() * vec0.y()); 86 centroidX += (vec0.x() + vec1.x()) * centroidTmp; 87 centroidY += (vec0.y() + vec1.y()) * centroidTmp; 88 } 89 90 typename ArrayType::ElementDataType & vec0 = array[_ia.back()]; 91 typename ArrayType::ElementDataType & vec1 = array[_ia.front()]; 92 93 area += vec0.x() * vec1.y(); 94 area -= vec0.y() * vec1.x(); 95 96 centroidTmp = (vec0.x() * vec1.y() - vec1.x() * vec0.y()); 97 centroidX += (vec0.x() + vec1.x()) * centroidTmp; 98 centroidY += (vec0.y() + vec1.y()) * centroidTmp; 99 100 area *= 0.5; 101 area = 1 / (6 * area); 102 _centroid.set(area * centroidX, area * centroidY, vec0.z()); 103 } 104 #else 68 unsigned int size = array.size(); 69 70 for (unsigned int i=0; i<size; ++i) 71 array[i].z() = 0.0; 72 } 73 }; 74 75 class ComputeCentroidVisitor : public osg::ArrayVisitor 76 { 77 public: 78 79 void apply(osg::Vec3Array& array) { computeCentroid<osg::Vec3Array>(array); } 80 void apply(osg::Vec4Array& array) { computeCentroid<osg::Vec4Array>(array); } 81 82 void apply(osg::Vec3dArray& array) { computeCentroid<osg::Vec3dArray>(array); } 83 void apply(osg::Vec4dArray& array) { computeCentroid<osg::Vec4dArray>(array); } 84 105 85 106 86 template <typename ArrayType> 107 87 void computeCentroid(ArrayType & array) 108 88 { 109 if (_ia.empty()) return; 110 89 unsigned int size = array.size(); 111 90 osg::Vec3d total(0.0,0.0,0.0); 112 91 113 for ( osg::UIntArray::iterator it = _ia.begin(); it != _ia.end(); ++it)114 { 115 typename ArrayType::ElementDataType & vec = array[ *it];92 for (unsigned int i=0; i<size; ++i) 93 { 94 typename ArrayType::ElementDataType & vec = array[i]; 116 95 total.x() += vec.x(); 117 96 total.y() += vec.y(); … … 119 98 } 120 99 121 _centroid = total / double(_ia.size()) ; 122 } 123 124 125 #endif 126 127 osg::UIntArray & _ia; 100 _centroid = total / double(size) ; 101 } 102 128 103 osg::Vec3d _centroid; 129 104 }; 130 105 106 struct CopyIndexedOperator 107 { 108 template <typename ArrayType> 109 void process(ArrayType & array) 110 { 111 ArrayType * va = new ArrayType(); 112 113 osg::UIntArray::iterator it, end = _indexArray->end(); 114 for (it = _indexArray->begin(); it < end; ++it) 115 va->push_back(array[*it]); 116 117 _copyArray = va; 118 } 119 120 osg::ref_ptr<osg::UIntArray> _indexArray; 121 osg::ref_ptr<osg::Array> _copyArray; 122 }; 123 typedef osgUtil::OperationArrayFunctor<CopyIndexedOperator> CopyIndexedFunctor; 124 125 struct IsConvexPolygonVisitor : public osg::ArrayVisitor 126 { 127 virtual void apply(osg::Vec3Array& array) { process<osg::Vec3Array>(array); } 128 virtual void apply(osg::Vec4Array& array) { process<osg::Vec4Array>(array); } 129 130 131 virtual void apply(osg::Vec3dArray& array) { process<osg::Vec3dArray>(array); } 132 virtual void apply(osg::Vec4dArray& array) { process<osg::Vec4dArray>(array); } 133 134 template <typename ArrayType> 135 void process(ArrayType & array) 136 { 137 typedef typename ArrayType::ElementDataType VecType; 138 139 bool positif; 140 141 { 142 const VecType & v1 = array[0]; 143 const VecType & v2 = array[1]; 144 const VecType & v3 = array[2]; 145 146 positif = (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0); 147 } 148 149 150 unsigned int size = array.size() - 2; 151 unsigned int i; 152 for (i=1; i<size; ++i) 153 { 154 const VecType & v1 = array[i]; 155 const VecType & v2 = array[i+1]; 156 const VecType & v3 = array[i+2]; 157 158 if (positif != (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0)) 159 { 160 _isConvex = false; 161 return; 162 } 163 } 164 165 { 166 const VecType & v1 = array[i]; 167 const VecType & v2 = array[i+1]; 168 const VecType & v3 = array[0]; 169 170 if (positif != (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0)) 171 { 172 _isConvex = false; 173 return; 174 } 175 } 176 177 { 178 const VecType & v1 = array[i+1]; 179 const VecType & v2 = array[0]; 180 const VecType & v3 = array[1]; 181 182 if (positif != (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) >= 0.0)) 183 { 184 _isConvex = false; 185 return; 186 } 187 } 188 189 _isConvex = true; 190 } 191 192 bool _isConvex; 193 }; 194 195 196 // ** This operator map each vertex and add them only if they overlap the HeightField 131 197 class HeightFieldMapperArrayVisitor : public osg::ArrayVisitor 132 198 { 199 public: 200 201 HeightFieldMapperArrayVisitor(const HeightFieldMapper & hfm) : _hfm(hfm) {} 202 203 virtual void apply(osg::Vec3Array& array) { process<osg::Vec3Array>(array); } 204 virtual void apply(osg::Vec4Array& array) { process<osg::Vec4Array>(array); } 205 206 207 virtual void apply(osg::Vec3dArray& array) { process<osg::Vec3dArray>(array); } 208 virtual void apply(osg::Vec4dArray& array) { process<osg::Vec4dArray>(array); } 209 210 template <typename ArrayType> 211 void process(ArrayType & array) 212 { 213 unsigned int size = array.size(); 214 osg::ref_ptr<ArrayType> newArray(new ArrayType); 215 newArray->reserve(size); 216 217 ArrayType & refNewArray = *newArray.get(); 218 219 220 for (unsigned int i=0; i<size; ++i) 221 { 222 typename ArrayType::ElementDataType & vec = array[i]; 223 vec.z() = _hfm.getZfromXY(vec.x(), vec.y()); 224 225 if (vec.z() != DBL_MAX) refNewArray.push_back(vec); 226 } 227 228 array = refNewArray; 229 } 230 231 const HeightFieldMapper & _hfm; 232 }; 233 234 235 // ** This operator reverse the array if its normal is not (0,0,1) 236 class AssertUpNormalVisitor : public osg::ArrayVisitor 237 { 133 238 public: 134 135 template <class T> 136 struct HeightFieldMapperOperator 137 { 138 HeightFieldMapperOperator(const HeightFieldMapper & hfm) : _hfm(hfm) {} 139 void operator ()(T & vec) { vec.z() = _hfm.getZfromXY(vec.x(), vec.y()); } 140 141 private: 142 143 const HeightFieldMapper _hfm; 239 240 virtual void apply(osg::Vec3Array& array) { process<osg::Vec3Array>(array); } 241 virtual void apply(osg::Vec4Array& array) { process<osg::Vec4Array>(array); } 242 243 virtual void apply(osg::Vec3dArray& array) { process<osg::Vec3dArray>(array); } 244 virtual void apply(osg::Vec4dArray& array) { process<osg::Vec4dArray>(array); } 245 246 template <typename ArrayType> 247 void process(ArrayType & array) const 248 { 249 typedef typename ArrayType::ElementDataType VecType; 250 251 const VecType & v1 = array[0]; 252 const VecType & v2 = array[1]; 253 const VecType & v3 = array[2]; 254 255 if (((v1.x() - v2.x()) * (v3.y() - v2.y()) - (v1.y() - v2.y()) * (v3.x() - v2.x())) > 0.0) 256 { 257 std::reverse(array.begin(), array.end()); 258 } 259 } 260 }; 261 262 263 264 // ** This visitor cut the geometry to overlap exactly the HeightField 265 template <typename ArrayType, typename CreatePolicy> 266 class CutGeometryToOverlapHeightField 267 { 268 public: 269 270 typedef typename ArrayType::ElementDataType VecType; 271 272 273 CutGeometryToOverlapHeightField(double xMin, double yMin, double xMax, double yMax) 274 : _xMin(xMin), _yMin(yMin), _xMax(xMax), _yMax(yMax) 275 {} 276 277 bool overlapHeightField(double x, double y) const 278 { 279 return !((x > _xMax) || (x < _xMin) || (y > _yMax) || (y < _yMin)); 280 } 281 282 void process(ArrayType & array) 283 { 284 285 unsigned int size = array.size(); 286 _cuttenVertexArray = new ArrayType; 287 288 ArrayType & refNewArray = *static_cast<ArrayType*>(_cuttenVertexArray.get()); 289 refNewArray.reserve(size); 290 291 // ** find the first vertex overlaping the HeightField 292 unsigned int i=0; 293 bool notFound = true; 294 while (notFound && (i<size)) 295 { 296 VecType & vec = array[i]; 297 if (overlapHeightField(vec.x(), vec.y())) 298 notFound = false; 299 else 300 ++i; 301 } 302 303 if (i == size) return; 304 305 // ** move vertex at the end of the array. Now, the first vertex in the array overlap the HeightField 306 if (i) 307 { 308 std::rotate(array.begin(), array.begin() + i, array.end()); 309 } 310 311 312 313 314 VecType inToOutVec, outToInVec; 315 316 refNewArray.push_back(array[0]); 317 i=1; 318 while (i<size) 319 { 320 VecType & vec = array[i]; 321 322 // ** if the vertex not overlap the HeightField 323 if (overlapHeightField(vec.x(), vec.y()) == false) 324 { 325 computeIntersection(array[i-1], array[i], inToOutVec); 326 ++i; 327 328 bool notOverlap = true; 329 while (notOverlap && (i<size)) 330 { 331 VecType & v = array[i]; 332 if (overlapHeightField(v.x(), v.y())) 333 notOverlap = false; 334 else 335 ++i; 336 } 337 338 if (notOverlap == false) 339 computeIntersection(array[i], array[i-1], outToInVec); 340 else 341 computeIntersection(array[0], array[i-1], outToInVec); 342 343 344 insertIntersectedVertex(refNewArray, inToOutVec, outToInVec); 345 346 347 if (notOverlap == false) 348 refNewArray.push_back(array[i]); 349 } 350 else 351 { 352 refNewArray.push_back(vec); 353 } 354 355 ++i; 356 } 357 } 358 359 enum Corner 360 { 361 NotACorner = 0, 362 C00, // corner(_xMin, _yMin) 363 C10, // corner(_xMax, _yMin) 364 C11, // corner(_xMax, _yMax) 365 C01 // corner(_xMin, _yMax) 144 366 }; 145 367 146 147 HeightFieldMapperArrayVisitor(const HeightFieldMapper & hfm) : _hfm(hfm) {} 148 149 virtual void apply(osg::Vec3Array & array) 150 { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec3>(_hfm)); } 151 virtual void apply(osg::Vec4Array & array) 152 { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec4>(_hfm)); } 153 virtual void apply(osg::Vec3dArray & array) 154 { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec3d>(_hfm)); } 155 virtual void apply(osg::Vec4dArray & array) 156 { std::for_each(array.begin(), array.end(), HeightFieldMapperOperator<osg::Vec4d>(_hfm)); } 368 Corner isCorner(const VecType & v) 369 { 370 if (v.x() == _xMin) 371 { 372 if (v.y() == _yMin) return C00; 373 if (v.y() == _yMax) return C01; 374 } 375 if (v.x() == _xMax) 376 { 377 if (v.y() == _yMin) return C10; 378 if (v.y() == _yMax) return C11; 379 } 380 return (NotACorner); 381 } 382 383 void insertIntersectedVertex(ArrayType & array, const VecType & v1, const VecType & v2) 384 { 385 array.push_back(v1); 386 387 if (v1.x() == _xMin) 388 { 389 if (v2.y() == _yMin) 390 { 391 if ((isCorner(v1) != C00) && (isCorner(v2) != C00)) array.push_back(CreatePolicy::create(_xMin, _yMin)); 392 } 393 else if (v2.x() == _xMax) 394 { 395 if (isCorner(v1) != C00) array.push_back(CreatePolicy::create(_xMin, _yMin)); 396 array.push_back(CreatePolicy::create(_xMax, _yMin)); 397 } 398 else if (v2.y() == _yMax) 399 { 400 if (isCorner(v1) != C00) array.push_back(CreatePolicy::create(_xMin, _yMin)); 401 array.push_back(CreatePolicy::create(_xMax, _yMin)); 402 array.push_back(CreatePolicy::create(_xMax, _yMax)); 403 } 404 else if (v2.x() == _xMin) 405 { 406 if (v1.y() < v2.y()) 407 { 408 if (isCorner(v1) != C00) array.push_back(CreatePolicy::create(_xMin, _yMin)); 409 array.push_back(CreatePolicy::create(_xMax, _yMin)); 410 array.push_back(CreatePolicy::create(_xMax, _yMax)); 411 array.push_back(CreatePolicy::create(_xMin, _yMax)); 412 } 413 } 414 } 415 416 else if (v1.y() == _yMin) 417 { 418 if (v2.x() == _xMax) 419 { 420 if ((isCorner(v1) != C10) && (isCorner(v2) != C10)) array.push_back(CreatePolicy::create(_xMax, _yMin)); 421 } 422 else if (v2.y() == _yMax) 423 { 424 if (isCorner(v1) != C10) array.push_back(CreatePolicy::create(_xMax, _yMin)); 425 array.push_back(CreatePolicy::create(_xMax, _yMax)); 426 } 427 else if (v2.x() == _xMin) 428 { 429 if (isCorner(v1) != C10) array.push_back(CreatePolicy::create(_xMax, _yMin)); 430 array.push_back(CreatePolicy::create(_xMax, _yMax)); 431 array.push_back(CreatePolicy::create(_xMin, _yMax)); 432 } 433 else if (v2.y() == _yMin) 434 { 435 if (v1.x() > v2.x()) 436 { 437 if (isCorner(v1) != C10) array.push_back(CreatePolicy::create(_xMax, _yMin)); 438 array.push_back(CreatePolicy::create(_xMax, _yMax)); 439 array.push_back(CreatePolicy::create(_xMin, _yMax)); 440 array.push_back(CreatePolicy::create(_xMin, _yMin)); 441 } 442 } 443 } 444 445 else if (v1.x() == _xMax) 446 { 447 if (v2.y() == _yMax) 448 { 449 if ((isCorner(v1) != C11) && (isCorner(v2) != C11)) array.push_back(CreatePolicy::create(_xMax, _yMax)); 450 } 451 else if (v2.x() == _xMin) 452 { 453 if (isCorner(v1) != C11) array.push_back(CreatePolicy::create(_xMax, _yMax)); 454 array.push_back(CreatePolicy::create(_xMax, _yMin)); 455 } 456 else if (v2.y() == _yMin) 457 { 458 if (isCorner(v1) != C11) array.push_back(CreatePolicy::create(_xMax, _yMax)); 459 array.push_back(CreatePolicy::create(_xMin, _yMax)); 460 array.push_back(CreatePolicy::create(_xMin, _yMin)); 461 } 462 else if (v2.x() == _xMax) 463 { 464 if (v1.y() > v2.y()) 465 { 466 if (isCorner(v1) != C11) array.push_back(CreatePolicy::create(_xMax, _yMax)); 467 array.push_back(CreatePolicy::create(_xMin, _yMax)); 468 array.push_back(CreatePolicy::create(_xMin, _yMin)); 469 array.push_back(CreatePolicy::create(_xMax, _yMin)); 470 } 471 } 472 } 473 474 else if (v1.y() == _yMax) 475 { 476 if (v2.x() == _xMin) 477 { 478 if ((isCorner(v1) != C01) && (isCorner(v2) != C01)) array.push_back(CreatePolicy::create(_xMin, _yMax)); 479 } 480 else if (v2.y() == _yMin) 481 { 482<
