Changeset 13041 for OpenSceneGraph/trunk/src/osgUtil/Simplifier.cpp
- Timestamp:
- 03/21/12 18:36:20 (14 months ago)
- Files:
-
- 1 modified
-
OpenSceneGraph/trunk/src/osgUtil/Simplifier.cpp (modified) (93 diffs)
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgUtil/Simplifier.cpp
r12374 r13041 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 2 * 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 5 5 * (at your option) any later version. The full license is in LICENSE file 6 6 * included with this distribution, and on the openscenegraph.org website. 7 * 7 * 8 8 * This library is distributed in the hope that it will be useful, 9 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 11 * OpenSceneGraph Public License for more details. 12 12 */ … … 74 74 _geometry(0), 75 75 _computeErrorMetricUsingLength(false) {} 76 76 77 77 ~EdgeCollapse(); 78 78 … … 92 92 Point* p1 = edge->_p1.get(); 93 93 Point* p2 = edge->_p2.get(); 94 94 95 95 if (p1==0 || p2==0) 96 96 { 97 97 OSG_NOTICE<<"Error computeInterpolatedPoint("<<edge<<",r) p1 and/or p2==0"<<std::endl; 98 98 return 0; 99 } 100 99 } 100 101 101 point->_vertex = p1->_vertex * r1 + p2->_vertex * r2; 102 102 unsigned int s = osg::minimum(p1->_attributes.size(),p2->_attributes.size()); 103 103 for(unsigned int i=0;i<s;++i) 104 104 { 105 point->_attributes.push_back(p1->_attributes[i]*r1 + p2->_attributes[i]*r2); 105 point->_attributes.push_back(p1->_attributes[i]*r1 + p2->_attributes[i]*r2); 106 106 } 107 107 return point; … … 112 112 return computeInterpolatedPoint(edge,0.5f); 113 113 } 114 114 115 115 error_type computeErrorMetric(Edge* edge,Point* point) const 116 116 { … … 140 140 error += fabs( (*itr)->distance(vertex) ); 141 141 } 142 142 143 143 // use average of error 144 144 error /= error_type(triangles.size()); … … 151 151 } 152 152 } 153 153 154 154 void updateErrorMetricForEdge(Edge* edge) 155 155 { … … 162 162 163 163 osg::ref_ptr<Edge> keep_local_reference_to_edge(edge); 164 164 165 165 if (_edgeSet.count(keep_local_reference_to_edge)!=0) 166 166 { … … 169 169 170 170 edge->_proposedPoint = computeOptimalPoint(edge); 171 171 172 172 if (_computeErrorMetricUsingLength) 173 173 { … … 183 183 edge->setErrorMetric( FLT_MAX ); 184 184 } 185 185 186 186 _edgeSet.insert(keep_local_reference_to_edge); 187 187 } 188 188 189 189 void updateErrorMetricForAllEdges() 190 190 { … … 192 192 LocalEdgeList edges; 193 193 std::copy( _edgeSet.begin(), _edgeSet.end(), std::back_inserter(edges)); 194 194 195 195 _edgeSet.clear(); 196 196 197 197 for(LocalEdgeList::iterator itr=edges.begin(); 198 198 itr!=edges.end(); … … 272 272 { 273 273 Point(): _protected(false), _index(0) {} 274 274 275 275 bool _protected; 276 276 … … 291 291 if (_vertex < rhs._vertex) return true; 292 292 if (rhs._vertex < _vertex) return false; 293 293 294 294 return _attributes < rhs._attributes; 295 295 } 296 296 297 297 bool isBoundaryPoint() const 298 298 { 299 299 if (_protected) return true; 300 300 301 301 for(TriangleSet::const_iterator itr=_triangles.begin(); 302 302 itr!=_triangles.end(); … … 307 307 if ((triangle->_e2->_p1==this || triangle->_e2->_p2==this) && triangle->_e2->isBoundaryEdge()) return true; 308 308 if ((triangle->_e3->_p1==this || triangle->_e3->_p2==this) && triangle->_e3->isBoundaryEdge()) return true; 309 309 310 310 //if ((*itr)->isBoundaryTriangle()) return true; 311 311 } … … 318 318 { 319 319 Edge(): _errorMetric(0.0), _maximumDeviation(1.0) {} 320 320 321 321 void clear() 322 322 { … … 328 328 osg::ref_ptr<Point> _p1; 329 329 osg::ref_ptr<Point> _p2; 330 330 331 331 TriangleSet _triangles; 332 332 … … 338 338 void setErrorMetric(error_type errorMetric) { _errorMetric = errorMetric; } 339 339 error_type getErrorMetric() const { return _errorMetric; } 340 340 341 341 bool operator < ( const Edge& rhs) const 342 342 { … … 347 347 if (dereference_check_less(_p1,rhs._p1)) return true; 348 348 if (dereference_check_less(rhs._p1,_p1)) return false; 349 349 350 350 return dereference_check_less(_p2,rhs._p2); 351 351 } 352 352 353 353 bool operator == ( const Edge& rhs) const 354 354 { … … 366 366 return false; 367 367 } 368 368 369 369 void addTriangle(Triangle* triangle) 370 370 { … … 372 372 // if (_triangles.size()>2) OSG_NOTICE<<"Warning too many triangles ("<<_triangles.size()<<") sharing edge "<<std::endl; 373 373 } 374 374 375 375 bool isBoundaryEdge() const 376 376 { 377 377 return _triangles.size()<=1; 378 378 } 379 379 380 380 bool isAdjacentToBoundary() const 381 381 { 382 return isBoundaryEdge() || _p1->isBoundaryPoint() || _p2->isBoundaryPoint(); 383 } 384 382 return isBoundaryEdge() || _p1->isBoundaryPoint() || _p2->isBoundaryPoint(); 383 } 384 385 385 386 386 void updateMaxNormalDeviationOnEdgeCollapse() … … 407 407 } 408 408 } 409 410 error_type getMaxNormalDeviationOnEdgeCollapse() const { return _maximumDeviation; } 409 410 error_type getMaxNormalDeviationOnEdgeCollapse() const { return _maximumDeviation; } 411 411 412 412 }; … … 415 415 { 416 416 Triangle() {} 417 417 418 418 void clear() 419 419 { … … 421 421 _p2 = 0; 422 422 _p3 = 0; 423 423 424 424 _e1 = 0; 425 425 _e2 = 0; … … 433 433 434 434 435 const Point* lhs_lower = dereference_check_less(_p2,_p3) ? _p2.get() : _p3.get(); 436 const Point* rhs_lower = dereference_check_less(rhs._p2,rhs._p3) ? rhs._p2.get() : rhs._p3.get(); 435 const Point* lhs_lower = dereference_check_less(_p2,_p3) ? _p2.get() : _p3.get(); 436 const Point* rhs_lower = dereference_check_less(rhs._p2,rhs._p3) ? rhs._p2.get() : rhs._p3.get(); 437 437 438 438 if (dereference_check_less(lhs_lower,rhs_lower)) return true; 439 439 if (dereference_check_less(rhs_lower,lhs_lower)) return false; 440 440 441 const Point* lhs_upper = dereference_check_less(_p2,_p3) ? _p3.get() : _p2.get(); 442 const Point* rhs_upper = dereference_check_less(rhs._p2,rhs._p3) ? rhs._p3.get() : rhs._p2.get(); 441 const Point* lhs_upper = dereference_check_less(_p2,_p3) ? _p3.get() : _p2.get(); 442 const Point* rhs_upper = dereference_check_less(rhs._p2,rhs._p3) ? rhs._p3.get() : rhs._p2.get(); 443 443 444 444 return dereference_check_less(lhs_upper,rhs_upper); … … 462 462 _p3 = points[(lowest+2)%3]; 463 463 } 464 464 465 465 void update() 466 466 { 467 467 _plane.set(_p1->_vertex,_p2->_vertex,_p3->_vertex); 468 469 } 470 468 469 } 470 471 471 osg::Plane computeNewPlaneOnEdgeCollapse(Edge* edge,Point* pNew) const 472 472 { 473 const Point* p1 = (_p1==edge->_p1 || _p1==edge->_p2) ? pNew : _p1.get(); 474 const Point* p2 = (_p2==edge->_p1 || _p2==edge->_p2) ? pNew : _p2.get(); 473 const Point* p1 = (_p1==edge->_p1 || _p1==edge->_p2) ? pNew : _p1.get(); 474 const Point* p2 = (_p2==edge->_p1 || _p2==edge->_p2) ? pNew : _p2.get(); 475 475 const Point* p3 = (_p3==edge->_p1 || _p3==edge->_p2) ? pNew : _p3.get(); 476 476 477 477 return osg::Plane(p1->_vertex,p2->_vertex,p3->_vertex); 478 478 } 479 479 480 480 // note return 1 - dotproduct, so that deviation is in the range of 0.0 to 2.0, where 0 is coincident, 1.0 is 90 degrees, and 2.0 is 180 degrees. 481 481 error_type computeNormalDeviationOnEdgeCollapse(Edge* edge,Point* pNew) const 482 482 { 483 const Point* p1 = (_p1==edge->_p1 || _p1==edge->_p2) ? pNew : _p1.get(); 484 const Point* p2 = (_p2==edge->_p1 || _p2==edge->_p2) ? pNew : _p2.get(); 483 const Point* p1 = (_p1==edge->_p1 || _p1==edge->_p2) ? pNew : _p1.get(); 484 const Point* p2 = (_p2==edge->_p1 || _p2==edge->_p2) ? pNew : _p2.get(); 485 485 const Point* p3 = (_p3==edge->_p1 || _p3==edge->_p2) ? pNew : _p3.get(); 486 486 487 487 osg::Vec3 new_normal = (p2->_vertex - p1->_vertex) ^ (p3->_vertex - p2->_vertex); 488 488 new_normal.normalize(); … … 499 499 error_type(_plane[3]); 500 500 } 501 501 502 502 bool isBoundaryTriangle() const 503 503 { … … 505 505 } 506 506 507 507 508 508 osg::ref_ptr<Point> _p1; 509 509 osg::ref_ptr<Point> _p2; 510 510 osg::ref_ptr<Point> _p3; 511 511 512 512 osg::ref_ptr<Edge> _e1; 513 513 osg::ref_ptr<Edge> _e2; 514 514 osg::ref_ptr<Edge> _e3; 515 515 516 516 osg::Plane _plane; 517 517 … … 525 525 // detect if triangle is degenerate. 526 526 if (p1==p2 || p2==p3 || p1==p3) return 0; 527 527 528 528 Triangle* triangle = new Triangle; 529 529 … … 532 532 points[1] = addPoint(triangle, p2); 533 533 points[2] = addPoint(triangle, p3); 534 534 535 535 // find the lowest value point in the list. 536 536 unsigned int lowest = 0; … … 545 545 triangle->_e2 = addEdge(triangle, triangle->_p2.get(), triangle->_p3.get()); 546 546 triangle->_e3 = addEdge(triangle, triangle->_p3.get(), triangle->_p1.get()); 547 547 548 548 triangle->update(); 549 549 550 550 _triangleSet.insert(triangle); 551 551 552 552 return triangle; 553 553 } 554 554 555 555 Triangle* addTriangle(Point* p1, Point* p2, Point* p3) 556 556 { … … 558 558 559 559 // detect if triangle is degenerate. 560 if (p1==p2 || p2==p3 || p1==p3) 560 if (p1==p2 || p2==p3 || p1==p3) 561 561 { 562 562 // OSG_NOTICE<<" **** addTriangle failed - p1==p2 || p2==p3 || p1==p3"<<std::endl; 563 563 return 0; 564 564 } 565 565 566 566 Triangle* triangle = new Triangle; 567 567 … … 570 570 points[1] = addPoint(triangle, p2); 571 571 points[2] = addPoint(triangle, p3); 572 572 573 573 // find the lowest value point in the list. 574 unsigned int lowest = 0; 574 unsigned int lowest = 0; 575 575 if (dereference_check_less(points[1],points[lowest])) lowest = 1; 576 576 if (dereference_check_less(points[2],points[lowest])) lowest = 2; … … 583 583 triangle->_e2 = addEdge(triangle, triangle->_p2.get(), triangle->_p3.get()); 584 584 triangle->_e3 = addEdge(triangle, triangle->_p3.get(), triangle->_p1.get()); 585 585 586 586 triangle->update(); 587 587 … … 596 596 if (triangle->_p2.valid()) removePoint(triangle,triangle->_p2.get()); 597 597 if (triangle->_p3.valid()) removePoint(triangle,triangle->_p3.get()); 598 598 599 599 if (triangle->_e1.valid()) removeEdge(triangle,triangle->_e1.get()); 600 600 if (triangle->_e2.valid()) removeEdge(triangle,triangle->_e2.get()); … … 612 612 if (triangle->_p2==pOriginal) triangle->_p2=pNew; 613 613 if (triangle->_p3==pOriginal) triangle->_p3=pNew; 614 614 615 615 // fixes the edges so they point to use the new point 616 616 triangle->_e1 = replaceEdgePoint(triangle->_e1.get(),pOriginal,pNew); 617 617 triangle->_e2 = replaceEdgePoint(triangle->_e2.get(),pOriginal,pNew); 618 618 triangle->_e3 = replaceEdgePoint(triangle->_e3.get(),pOriginal,pNew); 619 619 620 620 // remove the triangle form the original point, and possibly the point if its the last triangle to use it 621 621 removePoint(triangle, pOriginal); 622 622 623 623 // add the triangle to that point 624 624 addPoint(triangle,pNew); 625 625 } 626 627 } 628 626 627 } 628 629 629 unsigned int testTriangle(Triangle* triangle) 630 630 { … … 635 635 ++result; 636 636 } 637 else if (triangle->_p1->_triangles.count(triangle)==0) 637 else if (triangle->_p1->_triangles.count(triangle)==0) 638 638 { 639 639 OSG_NOTICE<<"testTriangle("<<triangle<<") _p1->_triangles does not contain triangle"<<std::endl; … … 646 646 ++result; 647 647 } 648 else if (triangle->_p2->_triangles.count(triangle)==0) 648 else if (triangle->_p2->_triangles.count(triangle)==0) 649 649 { 650 650 OSG_NOTICE<<"testTriangle("<<triangle<<") _p2->_triangles does not contain triangle"<<std::endl; … … 657 657 ++result; 658 658 } 659 else if (triangle->_p3->_triangles.count(triangle)==0) 659 else if (triangle->_p3->_triangles.count(triangle)==0) 660 660 { 661 661 OSG_NOTICE<<"testTriangle("<<triangle<<") _p3->_triangles does not contain triangle"<<std::endl; 662 662 ++result; 663 663 } 664 664 665 665 if (testEdge(triangle->_e1.get())) 666 666 { … … 668 668 OSG_NOTICE<<"testTriangle("<<triangle<<") _e1 test failed"<<std::endl; 669 669 } 670 670 671 671 if (testEdge(triangle->_e2.get())) 672 672 { … … 710 710 edge->_p2 = p1; 711 711 } 712 712 713 713 edge->setErrorMetric( computeErrorMetric( edge.get(), edge->_proposedPoint.get())); 714 714 715 715 EdgeSet::iterator itr = _edgeSet.find(edge); 716 716 if (itr==_edgeSet.end()) … … 724 724 edge = *itr; 725 725 } 726 726 727 727 edge->addTriangle(triangle); 728 728 729 729 return edge.get(); 730 730 } … … 755 755 { 756 756 // remove the edge from the list, as its positoin in the list 757 // may need to change once its values have been ammended 757 // may need to change once its values have been ammended 758 758 _edgeSet.erase(itr); 759 759 } 760 760 761 761 // modify its values 762 762 if (edge->_p1==pOriginal) edge->_p1=pNew; … … 785 785 return edge; 786 786 } 787 787 788 788 } 789 789 … … 812 812 osg::ref_ptr<Point> edge_p1 = edge->_p1; 813 813 osg::ref_ptr<Point> edge_p2 = edge->_p2; 814 814 815 815 TriangleMap triangleMap; 816 816 TriangleList triangles_p1; 817 817 TriangleList triangles_p2; 818 818 LocalEdgeList oldEdges; 819 820 819 820 821 821 if (edge_p1 != pNew) 822 822 { … … 834 834 } 835 835 } 836 836 837 837 //triangles_p1 = edge_p1->_triangles; 838 838 } 839 839 840 840 if (edge_p2 != pNew) 841 841 { … … 861 861 { 862 862 _edgeSet.erase(*oeitr); 863 863 864 864 const_cast<Edge*>(oeitr->get())->setErrorMetric(0.0f); 865 865 866 866 _edgeSet.insert(*oeitr); 867 867 } 868 868 869 869 TriangleList::iterator titr_p1, titr_p2; 870 870 871 871 for(titr_p1 = triangles_p1.begin(); 872 872 titr_p1 != triangles_p1.end(); … … 884 884 885 885 //OSG_NOTICE<<" pNew="<<pNew<<"\tedge_p1"<<edge_p1.get()<<"\tedge_p2"<<edge_p2.get()<<std::endl; 886 886 887 887 // we copy the edge's _triangles and interate the copy of the triangle set to avoid invalidating iterators. 888 888 TriangleSet trianglesToRemove = edge->_triangles; … … 897 897 LocalEdgeList newEdges; 898 898 899 899 900 900 for(titr_p1 = triangles_p1.begin(); 901 901 titr_p1 != triangles_p1.end(); … … 998 998 999 999 typedef std::set< osg::ref_ptr<Edge> > LocalEdgeList; 1000 LocalEdgeList edges2UpdateErrorMetric; 1000 LocalEdgeList edges2UpdateErrorMetric; 1001 1001 TriangleSet::iterator titr; 1002 1002 1003 1003 1004 1004 // for each deleted triangle insert two new triangles … … 1024 1024 else if (edge->_p2 == tri->_p2.get()) edgeToReplace = 2; // edge p2, p3 1025 1025 } 1026 1026 1027 1027 Triangle* newTri1 = 0; 1028 1028 Triangle* newTri2 = 0; … … 1054 1054 break; 1055 1055 } 1056 1056 1057 1057 if (newTri1) 1058 1058 { … … 1068 1068 } 1069 1069 } 1070 1070 1071 1071 // unsigned int numTriangles2 = _triangleSet.size(); 1072 1072 // unsigned int numEdges2 = _edgeSet.size(); … … 1118 1118 } 1119 1119 } 1120 1120 1121 1121 if (edge->_triangles.empty()) 1122 1122 { … … 1159 1159 Point* addPoint(Triangle* triangle, Point* point) 1160 1160 { 1161 1161 1162 1162 PointSet::iterator itr = _pointSet.find(point); 1163 1163 if (itr==_pointSet.end()) … … 1173 1173 1174 1174 point->_triangles.insert(triangle); 1175 1175 1176 1176 return point; 1177 1177 } … … 1183 1183 { 1184 1184 point->_triangles.erase(triangle); 1185 1185 1186 1186 if (point->_triangles.empty()) 1187 1187 { … … 1190 1190 } 1191 1191 } 1192 1193 } 1194 1192 1193 } 1194 1195 1195 unsigned int testPoint(Point* point) 1196 1196 { 1197 1197 unsigned int numErrors = 0; 1198 1198 1199 1199 for(TriangleSet::iterator itr=point->_triangles.begin(); 1200 1200 itr!=point->_triangles.end(); … … 1211 1211 } 1212 1212 } 1213 1213 1214 1214 return numErrors; 1215 1215 } 1216 1216 1217 1217 unsigned int testAllPoints() 1218 1218 { … … 1226 1226 return numErrors; 1227 1227 } 1228 1228 1229 1229 //protected: 1230 1230 … … 1232 1232 1233 1233 osg::Geometry* _geometry; 1234 1234 1235 1235 bool _computeErrorMetricUsingLength; 1236 1236 EdgeSet _edgeSet; … … 1238 1238 PointSet _pointSet; 1239 1239 PointList _originalPointList; 1240 1240 1241 1241 }; 1242 1242 … … 1247 1247 1248 1248 void setEdgeCollapse(EdgeCollapse* ec) { _ec = ec; } 1249 1250 EdgeCollapse* _ec; 1249 1250 EdgeCollapse* _ec; 1251 1251 1252 1252 // for use in the triangle functor. … … 1275 1275 CopyArrayToPointsVisitor(EdgeCollapse::PointList& pointList): 1276 1276 _pointList(pointList) {} 1277 1277 1278 1278 template<class T> 1279 1279 void copy(T& array) 1280 1280 { 1281 1281 if (_pointList.size()!=array.size()) return; 1282 1283 for(unsigned int i=0;i<_pointList.size();++i) 1284 _pointList[i]->_attributes.push_back((float)array[i]); 1285 } 1286 1282 1283 for(unsigned int i=0;i<_pointList.size();++i) 1284 _pointList[i]->_attributes.push_back((float)array[i]); 1285 } 1286 1287 1287 virtual void apply(osg::Array&) {} 1288 1288 virtual void apply(osg::ByteArray& array) { copy(array); } … … 1297 1297 { 1298 1298 if (_pointList.size()!=array.size()) return; 1299 1300 for(unsigned int i=0;i<_pointList.size();++i) 1299 1300 for(unsigned int i=0;i<_pointList.size();++i) 1301 1301 { 1302 1302 osg::Vec4ub& value = array[i]; 1303 1303 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; 1304 attributes.push_back((float)value.r()); 1305 attributes.push_back((float)value.g()); 1306 attributes.push_back((float)value.b()); 1307 attributes.push_back((float)value.a()); 1304 attributes.push_back((float)value.r()); 1305 attributes.push_back((float)value.g()); 1306 attributes.push_back((float)value.b()); 1307 attributes.push_back((float)value.a()); 1308 1308 } 1309 1309 } … … 1312 1312 { 1313 1313 if (_pointList.size()!=array.size()) return; 1314 1315 for(unsigned int i=0;i<_pointList.size();++i) 1314 1315 for(unsigned int i=0;i<_pointList.size();++i) 1316 1316 { 1317 1317 osg::Vec2& value = array[i]; 1318 1318 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; 1319 attributes.push_back(value.x()); 1320 attributes.push_back(value.y()); 1319 attributes.push_back(value.x()); 1320 attributes.push_back(value.y()); 1321 1321 } 1322 1322 } … … 1325 1325 { 1326 1326 if (_pointList.size()!=array.size()) return; 1327 1328 for(unsigned int i=0;i<_pointList.size();++i) 1327 1328 for(unsigned int i=0;i<_pointList.size();++i) 1329 1329 { 1330 1330 osg::Vec3& value = array[i]; 1331 1331 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; 1332 attributes.push_back(value.x()); 1333 attributes.push_back(value.y()); 1334 attributes.push_back(value.z()); 1335 } 1336 } 1337 1332 attributes.push_back(value.x()); 1333 attributes.push_back(value.y()); 1334 attributes.push_back(value.z()); 1335 } 1336 } 1337 1338 1338 virtual void apply(osg::Vec4Array& array) 1339 1339 { 1340 1340 if (_pointList.size()!=array.size()) return; 1341 1342 for(unsigned int i=0;i<_pointList.size();++i) 1341 1342 for(unsigned int i=0;i<_pointList.size();++i) 1343 1343 { 1344 1344 osg::Vec4& value = array[i]; 1345 1345 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; 1346 attributes.push_back(value.x()); 1347 attributes.push_back(value.y()); 1348 attributes.push_back(value.z()); 1349 attributes.push_back(value.w()); 1350 } 1351 } 1352 1346 attributes.push_back(value.x()); 1347 attributes.push_back(value.y()); 1348 attributes.push_back(value.z()); 1349 attributes.push_back(value.w()); 1350 } 1351 } 1352 1353 1353 EdgeCollapse::PointList& _pointList; 1354 1355 1354 1355 1356 1356 protected: 1357 1357 1358 1358 CopyArrayToPointsVisitor& operator = (const CopyArrayToPointsVisitor&) { return *this; } 1359 1359 }; … … 1364 1364 CopyVertexArrayToPointsVisitor(EdgeCollapse::PointList& pointList): 1365 1365 _pointList(pointList) {} 1366 1366 1367 1367 virtual void apply(osg::Vec2Array& array) 1368 1368 { 1369 1369 if (_pointList.size()!=array.size()) return; 1370 1371 for(unsigned int i=0;i<_pointList.size();++i) 1370 1371 for(unsigned int i=0;i<_pointList.size();++i) 1372 1372 { 1373 1373 _pointList[i] = new EdgeCollapse::Point; 1374 1374 _pointList[i]->_index = i; 1375 1375 1376 1376 osg::Vec2& value = array[i]; 1377 1377 osg::Vec3& vertex = _pointList[i]->_vertex; 1378 vertex.set(value.x(),value.y(),0.0f); 1378 vertex.set(value.x(),value.y(),0.0f); 1379 1379 } 1380 1380 } … … 1383 1383 { 1384 1384 if (_pointList.size()!=array.size()) return; 1385 1386 for(unsigned int i=0;i<_pointList.size();++i) 1385 1386 for(unsigned int i=0;i<_pointList.size();++i) 1387 1387 { 1388 1388 _pointList[i] = new EdgeCollapse::Point; 1389 1389 _pointList[i]->_index = i; 1390 1390 1391 1391 _pointList[i]->_vertex = array[i]; 1392 1392 } 1393 1393 } 1394 1394 1395 1395 virtual void apply(osg::Vec4Array& array) 1396 1396 { 1397 1397 if (_pointList.size()!=array.size()) return; 1398 1399 for(unsigned int i=0;i<_pointList.size();++i) 1398 1399 for(unsigned int i=0;i<_pointList.size();++i) 1400 1400 { 1401 1401 _pointList[i] = new EdgeCollapse::Point; 1402 1402 _pointList[i]->_index = i; 1403 1403 1404 1404 osg::Vec4& value = array[i]; 1405 1405 osg::Vec3& vertex = _pointList[i]->_vertex; 1406 vertex.set(value.x()/value.w(),value.y()/value.w(),value.z()/value.w()); 1407 } 1408 } 1409 1406 vertex.set(value.x()/value.w(),value.y()/value.w(),value.z()/value.w()); 1407 } 1408 } 1409 1410 1410 EdgeCollapse::PointList& _pointList; 1411 1411 1412 1412 protected: 1413 1413 1414 1414 CopyVertexArrayToPointsVisitor& operator = (const CopyVertexArrayToPointsVisitor&) { return *this; } 1415 1415 … … 1419 1419 { 1420 1420 _geometry = geometry; 1421 1421 1422 1422 // check to see if vertex attributes indices exists, if so expand them to remove them 1423 1423 if (_geometry->suitableForOptimization()) … … 1427 1427 _geometry->copyToAndOptimize(*_geometry); 1428 1428 } 1429 1429 1430 1430 // check to see if vertex attributes indices exists, if so expand them to remove them 1431 1431 if (_geometry->containsSharedArrays()) … … 1437 1437 1438 1438 unsigned int numVertices = geometry->getVertexArray()->getNumElements(); 1439 1439 1440 1440 _originalPointList.resize(numVertices); 1441 1441 1442 1442 // copy vertices across to local point list 1443 1443 CopyVertexArrayToPointsVisitor copyVertexArrayToPoints(_originalPointList); 1444 1444 _geometry->getVertexArray()->accept(copyVertexArrayToPoints); 1445 1445 1446 1446 // copy other per vertex attributes across to local point list. 1447 1447 CopyArrayToPointsVisitor copyArrayToPoints(_originalPointList); … … 1455 1455 if (_geometry->getNormalArray() && _geometry->getNormalBinding()==osg::Geometry::BIND_PER_VERTEX) 1456 1456 geometry->getNormalArray()->accept(copyArrayToPoints); 1457 1457 1458 1458 if (_geometry->getColorArray() && _geometry->getColorBinding()==osg::Geometry::BIND_PER_VERTEX) 1459 1459 geometry->getColorArray()->accept(copyArrayToPoints); 1460 1460 1461 1461 if (_geometry->getSecondaryColorArray() && _geometry->getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX) 1462 1462 geometry->getSecondaryColorArray()->accept(copyArrayToPoints); … … 1482 1482 CollectTriangleIndexFunctor collectTriangles; 1483 1483 collectTriangles.setEdgeCollapse(this); 1484 1484 1485 1485 _geometry->accept(collectTriangles); 1486 1486 1487 1487 } 1488 1488 1489 1489 1490 1490 … … 1501 1501 { 1502 1502 array.resize(_pointList.size()); 1503 1504 for(unsigned int i=0;i<_pointList.size();++i) 1505 { 1506 if (_index<_pointList[i]->_attributes.size()) 1503 1504 for(unsigned int i=0;i<_pointList.size();++i) 1505 { 1506 if (_index<_pointList[i]->_attributes.size()) 1507 1507 { 1508 1508 float val = (_pointList[i]->_attributes[_index]); … … 1510 1510 } 1511 1511 } 1512 1512 1513 1513 ++_index; 1514 1514 } 1515 1515 1516 1516 // use local typedefs if usinged char,short and int to get round gcc 3.3.1 problem with defining unsigned short() 1517 1517 typedef unsigned char dummy_uchar; 1518 1518 typedef unsigned short dummy_ushort; 1519 1519 typedef unsigned int dummy_uint; 1520 1520 1521 1521 virtual void apply(osg::Array&) {} 1522 1522 virtual void apply(osg::ByteArray& array) { copy(array, char());} … … 1531 1531 { 1532 1532 array.resize(_pointList.size()); 1533 1534 for(unsigned int i=0;i<_pointList.size();++i) 1533 1534 for(unsigned int i=0;i<_pointList.size();++i) 1535 1535 { 1536 1536 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; … … 1546 1546 { 1547 1547 array.resize(_pointList.size()); 1548 1549 for(unsigned int i=0;i<_pointList.size();++i) 1548 1549 for(unsigned int i=0;i<_pointList.size();++i) 1550 1550 { 1551 1551 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; … … 1558 1558 { 1559 1559 array.resize(_pointList.size()); 1560 1561 for(unsigned int i=0;i<_pointList.size();++i) 1560 1561 for(unsigned int i=0;i<_pointList.size();++i) 1562 1562 { 1563 1563 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; … … 1566 1566 _index += 3; 1567 1567 } 1568 1568 1569 1569 virtual void apply(osg::Vec4Array& array) 1570 1570 { 1571 1571 array.resize(_pointList.size()); 1572 1573 for(unsigned int i=0;i<_pointList.size();++i) 1572 1573 for(unsigned int i=0;i<_pointList.size();++i) 1574 1574 { 1575 1575 EdgeCollapse::FloatList& attributes = _pointList[i]->_attributes; … … 1578 1578 _index += 4; 1579 1579 } 1580 1580 1581 1581 EdgeCollapse::PointList& _pointList; 1582 1582 unsigned int _index; 1583 1583 1584 1584 protected: 1585 1585 1586 1586 CopyPointsToArrayVisitor& operator = (CopyPointsToArrayVisitor&) { return *this; } 1587 1587 }; … … 1591 1591 public: 1592 1592 NormalizeArrayVisitor() {} 1593 1593 1594 1594 template<typename Itr> 1595 1595 void normalize(Itr begin, Itr end) … … 1602 1602 } 1603 1603 } 1604 1604 1605 1605 virtual void apply(osg::Vec2Array& array) { normalize(array.begin(),array.end()); } 1606 1606 virtual void apply(osg::Vec3Array& array) { normalize(array.begin(),array.end()); } 1607 1607 virtual void apply(osg::Vec4Array& array) { normalize(array.begin(),array.end()); } 1608 1608 1609 1609 }; 1610 1610 … … 1614 1614 CopyPointsToVertexArrayVisitor(EdgeCollapse::PointList& pointList): 1615 1615 _pointList(pointList) {} 1616 1616 1617 1617 virtual void apply(osg::Vec2Array& array) 1618 1618 { 1619 1619 array.resize(_pointList.size()); 1620 1621 for(unsigned int i=0;i<_pointList.size();++i) 1620 1621 for(unsigned int i=0;i<_pointList.size();++i) 1622 1622 { 1623 1623 _pointList[i]->_index = i; … … 1630 1630 { 1631 1631 array.resize(_pointList.size()); 1632 1633 for(unsigned int i=0;i<_pointList.size();++i) 1632 1633 for(unsigned int i=0;i<_pointList.size();++i) 1634 1634 { 1635 1635 _pointList[i]->_index = i; … … 1637 1637 } 1638 1638 } 1639 1639 1640 1640 virtual void apply(osg::Vec4Array& array) 1641 1641 { 1642 1642 array.resize(_pointList.size()); 1643 1644 for(unsigned int i=0;i<_pointList.size();++i) 1643 1644 for(unsigned int i=0;i<_pointList.size();++i) 1645 1645 { 1646 1646 _pointList[i]->_index = i; … … 1649 1649 } 1650 1650 } 1651 1651 1652 1652 EdgeCollapse::PointList& _pointList; 1653 1653 1654 1654 protected: 1655 1655 1656 1656 CopyPointsToVertexArrayVisitor& operator = (const CopyPointsToVertexArrayVisitor&) { return *this; } 1657 1657 }; … … 1668 1668 CopyPointsToVertexArrayVisitor copyVertexArrayToPoints(_originalPointList); 1669 1669 _geometry->getVertexArray()->accept(copyVertexArrayToPoints); 1670 1670 1671 1671 // copy other per vertex attributes across to local point list. 1672 1672 CopyPointsToArrayVisitor copyArrayToPoints(_originalPointList); … … 1686 1686 _geometry->getNormalArray()->accept(nav); 1687 1687 } 1688 1688 1689 1689 if (_geometry->getColorArray() && _geometry->getColorBinding()==osg::Geometry::BIND_PER_VERTEX) 1690 1690 _geometry->getColorArray()->accept(copyArrayToPoints); 1691 1691 1692 1692 if (_geometry->getSecondaryColorArray() && _geometry->getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX) 1693 1693 _geometry->getSecondaryColorArray()->accept(copyArrayToPoints); … … 1722 1722 (*primitives)[pos++] = triangle->_p3->_index; 1723 1723 } 1724 1724 1725 1725 _geometry->getPrimitiveSetList().clear(); 1726 1726 _geometry->addPrimitiveSet(primitives); … … 1736 1736 _triStrip(true), 1737 1737 _smoothing(true) 1738 1738 1739 1739 { 1740 1740 } … … 1759 1759 1760 1760 unsigned int numOriginalPrimitives = ec._triangleSet.size(); 1761 1761 1762 1762 if (getSampleRatio()<1.0) 1763 1763 { 1764 1764 while (!ec._edgeSet.empty() && 1765 continueSimplification((*ec._edgeSet.begin())->getErrorMetric() , numOriginalPrimitives, ec._triangleSet.size()) && 1765 continueSimplification((*ec._edgeSet.begin())->getErrorMetric() , numOriginalPrimitives, ec._triangleSet.size()) && 1766 1766 ec.collapseMinimumErrorEdge()) 1767 1767 { … … 1776 1776 // up sampling... 1777 1777 while (!ec._edgeSet.empty() && 1778 continueSimplification((*ec._edgeSet.rbegin())->getErrorMetric() , numOriginalPrimitives, ec._triangleSet.size()) && 1778 continueSimplification((*ec._edgeSet.rbegin())->getErrorMetric() , numOriginalPrimitives, ec._triangleSet.size()) && 1779 1779 // ec._triangleSet.size() < targetNumTriangles && 1780 1780 ec.divideLongestEdge()) … … 1799 1799 OSG_INFO<< " continueSimplification(,,) = "<<continueSimplification((*ec._edgeSet.begin())->getErrorMetric() , numOriginalPrimitives, ec._triangleSet.size())<<std::endl; 1800 1800 } 1801 1801 1802 1802 ec.copyBackToGeometry(); 1803 1803 … … 1806 1806 osgUtil::SmoothingVisitor::smooth(geometry); 1807 1807 } 1808 1808 1809 1809 if (_triStrip) 1810 1810 {
