Changeset 13041 for OpenSceneGraph/trunk/src/osgUtil/Optimizer.cpp
- Timestamp:
- 03/21/12 18:36:20 (14 months ago)
- Files:
-
- 1 modified
-
OpenSceneGraph/trunk/src/osgUtil/Optimizer.cpp (modified) (183 diffs)
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgUtil/Optimizer.cpp
r13023 r13041 1 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 */ … … 61 61 { 62 62 unsigned int options = 0; 63 64 63 64 65 65 const char* env = getenv("OSG_OPTIMIZER"); 66 66 if (env) … … 117 117 if(str.find("~MAKE_FAST_GEOMETRY")!=std::string::npos) options ^= MAKE_FAST_GEOMETRY; 118 118 else if(str.find("MAKE_FAST_GEOMETRY")!=std::string::npos) options |= MAKE_FAST_GEOMETRY; 119 119 120 120 if(str.find("~FLATTEN_BILLBOARDS")!=std::string::npos) options ^= FLATTEN_BILLBOARDS; 121 121 else if(str.find("FLATTEN_BILLBOARDS")!=std::string::npos) options |= FLATTEN_BILLBOARDS; 122 122 123 123 if(str.find("~TEXTURE_ATLAS_BUILDER")!=std::string::npos) options ^= TEXTURE_ATLAS_BUILDER; 124 124 else if(str.find("TEXTURE_ATLAS_BUILDER")!=std::string::npos) options |= TEXTURE_ATLAS_BUILDER; 125 125 126 126 if(str.find("~STATIC_OBJECT_DETECTION")!=std::string::npos) options ^= STATIC_OBJECT_DETECTION; 127 127 else if(str.find("STATIC_OBJECT_DETECTION")!=std::string::npos) options |= STATIC_OBJECT_DETECTION; … … 149 149 { 150 150 StatsVisitor stats; 151 151 152 152 if (osg::getNotifyLevel()>=osg::INFO) 153 153 { … … 169 169 170 170 TessellateVisitor tsv; 171 node->accept(tsv); 172 } 173 171 node->accept(tsv); 172 } 173 174 174 if (options & REMOVE_LOADED_PROXY_NODES) 175 175 { … … 187 187 188 188 CombineLODsVisitor clv(this); 189 node->accept(clv); 189 node->accept(clv); 190 190 clv.combineLODs(); 191 191 } 192 192 193 193 if (options & OPTIMIZE_TEXTURE_SETTINGS) 194 194 { 195 195 OSG_INFO<<"Optimizer::optimize() doing OPTIMIZE_TEXTURE_SETTINGS"<<std::endl; 196 196 197 TextureVisitor tv(true,true, // unref image 197 TextureVisitor tv(true,true, // unref image 198 198 false,false, // client storage 199 199 false,1.0, // anisotropic filtering … … 214 214 osv.optimize(); 215 215 } 216 216 217 217 if (options & TEXTURE_ATLAS_BUILDER) 218 218 { 219 219 OSG_INFO<<"Optimizer::optimize() doing TEXTURE_ATLAS_BUILDER"<<std::endl; 220 220 221 221 // traverse the scene collecting textures into texture atlas. 222 222 TextureAtlasVisitor tav(this); … … 233 233 osv.optimize(); 234 234 } 235 235 236 236 if (options & COPY_SHARED_NODES) 237 237 { … … 242 242 cssv.copySharedNodes(); 243 243 } 244 244 245 245 if (options & FLATTEN_STATIC_TRANSFORMS) 246 246 { … … 284 284 285 285 osg::Timer_t endTick = osg::Timer::instance()->tick(); 286 286 287 287 OSG_INFO<<"MERGE_GEODES took "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl; 288 288 } … … 318 318 OSG_INFO<<"MERGE_GEOMETRY took "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl; 319 319 } 320 320 321 321 if (options & TRISTRIP_GEOMETRY) 322 322 { … … 341 341 342 342 } 343 343 344 344 if (options & FLATTEN_BILLBOARDS) 345 345 { … … 415 415 416 416 template<typename T> 417 struct LessDerefFunctor 417 struct LessDerefFunctor 418 418 { 419 419 bool operator () (const T* lhs,const T* rhs) const 420 420 { 421 return (*lhs<*rhs); 421 return (*lhs<*rhs); 422 422 } 423 423 }; … … 427 427 bool operator () (const osg::StateSet* lhs,const osg::StateSet* rhs) const 428 428 { 429 return (*lhs<*rhs); 429 return (*lhs<*rhs); 430 430 } 431 431 }; … … 445 445 void Optimizer::StateVisitor::apply(osg::Node& node) 446 446 { 447 447 448 448 osg::StateSet* ss = node.getStateSet(); 449 if (ss && ss->getDataVariance()==osg::Object::STATIC) 449 if (ss && ss->getDataVariance()==osg::Object::STATIC) 450 450 { 451 451 if (isOperationPermissibleForObject(&node) && … … 464 464 465 465 osg::StateSet* ss = geode.getStateSet(); 466 467 466 467 468 468 if (ss && ss->getDataVariance()==osg::Object::STATIC) 469 469 { … … 505 505 typedef std::set<osg::StateSet*> StateSetSet; 506 506 typedef std::map<osg::Uniform*,StateSetSet> UniformToStateSetMap; 507 507 508 508 const unsigned int NON_TEXTURE_ATTRIBUTE = 0xffffffff; 509 509 510 510 UniformToStateSetMap uniformToStateSetMap; 511 511 … … 607 607 } 608 608 } 609 610 609 610 611 611 if (uniformToStateSetMap.size()>=2) 612 612 { … … 637 637 // find the duplicates. 638 638 UniformList::iterator first_unique_uniform = uniformList.begin(); 639 UniformList::iterator current_uniform = first_unique_uniform; 639 UniformList::iterator current_uniform = first_unique_uniform; 640 640 ++current_uniform; 641 641 for(; current_uniform!=uniformList.end();++current_uniform) … … 659 659 660 660 } 661 661 662 662 // duplicate state attributes removed. 663 663 // now need to look at duplicate state sets. … … 700 700 drawable->setStateSet(*first_unique); 701 701 } 702 else 702 else 703 703 { 704 704 osg::Node* node = dynamic_cast<osg::Node*>(obj); … … 713 713 } 714 714 } 715 715 716 716 } 717 717 … … 759 759 registerWithCurrentObjects(&transform); 760 760 } 761 761 762 762 virtual void apply(osg::Geode& geode) 763 763 { 764 764 traverse(geode); 765 765 } 766 766 767 767 virtual void apply(osg::Billboard& geode) 768 768 { 769 769 traverse(geode); 770 770 } 771 771 772 772 773 773 void collectDataFor(osg::Node* node) 774 774 { 775 775 _currentObjectList.push_back(node); 776 776 777 777 node->accept(*this); 778 778 779 779 _currentObjectList.pop_back(); 780 780 } … … 783 783 { 784 784 _currentObjectList.push_back(billboard); 785 785 786 786 billboard->accept(*this); 787 787 788 788 _currentObjectList.pop_back(); 789 789 } 790 790 791 791 void collectDataFor(osg::Drawable* drawable) 792 792 { … … 812 812 const osg::Drawable* drawable = dynamic_cast<const osg::Drawable*>(object); 813 813 if (drawable) return isOperationPermissibleForObject(drawable); 814 814 815 815 const osg::Node* node = dynamic_cast<const osg::Node*>(object); 816 816 if (node) return isOperationPermissibleForObject(node); … … 825 825 return BaseOptimizerVisitor::isOperationPermissibleForObject(drawable); 826 826 } 827 827 828 828 inline bool isOperationPermissibleForObject(const osg::Node* node) const 829 829 { … … 835 835 } 836 836 837 protected: 837 protected: 838 838 839 839 struct TransformStruct … … 877 877 else 878 878 { 879 if (!_transformSet.empty()) 879 if (!_transformSet.empty()) 880 880 { 881 881 if (!_firstMatrix.isIdentity()) _moreThanOneMatrixRequired=true; … … 890 890 osg::Matrix _firstMatrix; 891 891 TransformSet _transformSet; 892 }; 892 }; 893 893 894 894 … … 914 914 void disableObject(ObjectMap::iterator itr); 915 915 void doTransform(osg::Object* obj,osg::Matrix& matrix); 916 916 917 917 osgUtil::TransformAttributeFunctor _transformFunctor; 918 918 TransformMap _transformMap; … … 941 941 osg::Matrix matrix_no_trans = matrix; 942 942 matrix_no_trans.setTrans(0.0f,0.0f,0.0f); 943 943 944 944 osg::Vec3 v111(1.0f,1.0f,1.0f); 945 945 osg::Vec3 new_v111 = v111*matrix_no_trans; … … 948 948 // move center point. 949 949 lod->setCenter(lod->getCenter()*matrix); 950 950 951 951 // adjust ranges to new scale. 952 952 for(unsigned int i=0;i<lod->getNumRanges();++i) … … 954 954 lod->setRange(i,lod->getMinRange(i)*ratio,lod->getMaxRange(i)*ratio); 955 955 } 956 956 957 957 lod->dirtyBound(); 958 958 return; … … 964 964 osg::Matrix matrix_no_trans = matrix; 965 965 matrix_no_trans.setTrans(0.0f,0.0f,0.0f); 966 966 967 967 osgUtil::TransformAttributeFunctor tf(matrix_no_trans); 968 968 … … 982 982 billboard->getDrawable(i)->dirtyBound(); 983 983 } 984 984 985 985 billboard->dirtyBound(); 986 986 … … 994 994 { 995 995 return; 996 } 996 } 997 997 998 998 if (itr->second._canBeApplied) … … 1017 1017 { 1018 1018 return; 1019 } 1019 } 1020 1020 1021 1021 if (itr->second._canBeApplied) 1022 1022 { 1023 1023 1024 1024 // we havn't been disabled yet so we need to disable, 1025 1025 itr->second._canBeApplied = false; … … 1044 1044 osg::Object* object = oitr->first; 1045 1045 ObjectStruct& os = oitr->second; 1046 1046 1047 1047 for(ObjectStruct::TransformSet::iterator titr = os._transformSet.begin(); 1048 1048 titr != os._transformSet.end(); … … 1053 1053 } 1054 1054 1055 // disable all the objects which have more than one matrix associated 1056 // with them, and then disable all transforms which have an object associated 1055 // disable all the objects which have more than one matrix associated 1056 // with them, and then disable all transforms which have an object associated 1057 1057 // them that can't be applied, and then disable all objects which have 1058 // disabled transforms associated, recursing until all disabled 1058 // disabled transforms associated, recursing until all disabled 1059 1059 // associativity. 1060 1060 // and disable all objects that the operation is not permisable for) … … 1143 1143 } 1144 1144 } 1145 1146 } 1145 1146 } 1147 1147 } 1148 1148 } 1149 1149 _objectMap.clear(); 1150 1150 _transformMap.clear(); 1151 1151 1152 1152 return transformRemoved; 1153 1153 } … … 1247 1247 cltv.collectDataFor(*bitr); 1248 1248 } 1249 1249 1250 1250 cltv.setUpMaps(); 1251 1251 1252 1252 for(TransformSet::iterator titr=_transformSet.begin(); 1253 1253 titr!=_transformSet.end(); … … 1256 1256 cltv.disableTransform(*titr); 1257 1257 } 1258 1258 1259 1259 1260 1260 return cltv.removeTransforms(nodeWeCannotRemove); … … 1276 1276 _transformSet.insert(&transform); 1277 1277 } 1278 1278 1279 1279 traverse(transform); 1280 1280 } … … 1288 1288 if (itr!=_transformSet.end()) _transformSet.erase(itr); 1289 1289 } 1290 1290 1291 1291 bool transformRemoved = false; 1292 1292 … … 1296 1296 osg::ref_ptr<osg::MatrixTransform> transform = *_transformSet.begin(); 1297 1297 _transformSet.erase(_transformSet.begin()); 1298 1298 1299 1299 if (transform->getNumChildren()==1 && 1300 1300 transform->getChild(0)->asTransform()!=0 && … … 1304 1304 // now combine with its child. 1305 1305 osg::MatrixTransform* child = transform->getChild(0)->asTransform()->asMatrixTransform(); 1306 1306 1307 1307 osg::Matrix newMatrix = child->getMatrix()*transform->getMatrix(); 1308 1308 child->setMatrix(newMatrix); … … 1312 1312 else child->setStateSet(transform->getStateSet()); 1313 1313 } 1314 1314 1315 1315 transformRemoved = true; 1316 1316 … … 1322 1322 (*pitr)->replaceChild(transform.get(),child); 1323 1323 } 1324 1325 } 1326 1324 1325 } 1326 1327 1327 } 1328 1328 return transformRemoved; … … 1355 1355 { 1356 1356 // only remove empty groups, but not empty occluders. 1357 if (group.getNumChildren()==0 && isOperationPermissibleForObject(&group) && 1357 if (group.getNumChildren()==0 && isOperationPermissibleForObject(&group) && 1358 1358 (typeid(group)==typeid(osg::Group) || (dynamic_cast<osg::Transform*>(&group) && !dynamic_cast<osg::CameraView*>(&group)))) 1359 1359 { … … 1376 1376 ++itr) 1377 1377 { 1378 1378 1379 1379 osg::ref_ptr<osg::Node> nodeToRemove = (*itr); 1380 1380 1381 1381 // take a copy of parents list since subsequent removes will modify the original one. 1382 1382 osg::Node::ParentList parents = nodeToRemove->getParents(); … … 1388 1388 osg::Group* parent = *pitr; 1389 1389 if (!dynamic_cast<osg::Sequence*>(parent) && 1390 !dynamic_cast<osg::Switch*>(parent) && 1390 !dynamic_cast<osg::Switch*>(parent) && 1391 1391 strcmp(parent->className(),"MultiSwitch")!=0) 1392 1392 { … … 1394 1394 if (parent->getNumChildren()==0) newEmptyGroups.insert(*pitr); 1395 1395 } 1396 } 1396 } 1397 1397 } 1398 1398 … … 1416 1416 !node.getUpdateCallback() && 1417 1417 node.getDescriptions().empty() && 1418 isOperationPermissibleForObject(&node); 1418 isOperationPermissibleForObject(&node); 1419 1419 } 1420 1420 1421 1421 void Optimizer::RemoveRedundantNodesVisitor::apply(osg::Group& group) 1422 1422 { 1423 if (group.getNumChildren()==1 && 1423 if (group.getNumChildren()==1 && 1424 1424 typeid(group)==typeid(osg::Group) && 1425 1425 isOperationPermissible(group)) … … 1478 1478 { 1479 1479 OSG_WARN<<"Optimizer::RemoveRedundantNodesVisitor::removeRedundantNodes() - failed dynamic_cast"<<std::endl; 1480 } 1480 } 1481 1481 } 1482 1482 _redundantNodeList.clear(); … … 1510 1510 if (group.valid()) 1511 1511 { 1512 1512 1513 1513 // first check to see if data was attached to the ProxyNode that we need to keep. 1514 1514 bool keepData = false; … … 1524 1524 // create a group to store all proxy's children and data. 1525 1525 osg::ref_ptr<osg::Group> newGroup = new osg::Group(*group,osg::CopyOp::SHALLOW_COPY); 1526 1526 1527 1527 1528 1528 // take a copy of parents list since subsequent removes will modify the original one. … … 1559 1559 { 1560 1560 OSG_WARN<<"Optimizer::RemoveLoadedProxyNodesVisitor::removeRedundantNodes() - failed dynamic_cast"<<std::endl; 1561 } 1561 } 1562 1562 } 1563 1563 _redundantNodeList.clear(); … … 1572 1572 { 1573 1573 if (dynamic_cast<osg::PagedLOD*>(&lod)==0) 1574 { 1574 { 1575 1575 for(unsigned int i=0;i<lod.getNumParents();++i) 1576 1576 { … … 1683 1683 if (lhs->getStateSet()<rhs->getStateSet()) return true; 1684 1684 if (rhs->getStateSet()<lhs->getStateSet()) return false; 1685 1685 1686 1686 if (rhs->getVertexIndices()) { if (!lhs->getVertexIndices()) return true; } 1687 1687 else if (lhs->getVertexIndices()) return false; 1688 1688 1689 1689 if (lhs->getNormalBinding()<rhs->getNormalBinding()) return true; 1690 1690 if (rhs->getNormalBinding()<lhs->getNormalBinding()) return false; … … 1695 1695 if (lhs->getColorBinding()<rhs->getColorBinding()) return true; 1696 1696 if (rhs->getColorBinding()<lhs->getColorBinding()) return false; 1697 1697 1698 1698 if (rhs->getColorIndices()) { if (!lhs->getColorIndices()) return true; } 1699 1699 else if (lhs->getColorIndices()) return false; … … 1713 1713 if (lhs->getNumTexCoordArrays()<rhs->getNumTexCoordArrays()) return true; 1714 1714 if (rhs->getNumTexCoordArrays()<lhs->getNumTexCoordArrays()) return false; 1715 1715 1716 1716 // therefore lhs->getNumTexCoordArrays()==rhs->getNumTexCoordArrays() 1717 1717 1718 1718 unsigned int i; 1719 1719 for(i=0;i<lhs->getNumTexCoordArrays();++i) 1720 1720 { 1721 if (rhs->getTexCoordArray(i)) 1721 if (rhs->getTexCoordArray(i)) 1722 1722 { 1723 1723 if (!lhs->getTexCoordArray(i)) return true; … … 1728 1728 else if (lhs->getTexCoordIndices(i)) return false; 1729 1729 } 1730 1730 1731 1731 for(i=0;i<lhs->getNumVertexAttribArrays();++i) 1732 1732 { 1733 if (rhs->getVertexAttribArray(i)) 1733 if (rhs->getVertexAttribArray(i)) 1734 1734 { 1735 1735 if (!lhs->getVertexAttribArray(i)) return true; … … 1740 1740 else if (lhs->getVertexAttribIndices(i)) return false; 1741 1741 } 1742 1743 1742 1743 1744 1744 if (lhs->getNormalBinding()==osg::Geometry::BIND_OVERALL) 1745 1745 { … … 1768 1768 } 1769 1769 } 1770 1770 1771 1771 if (lhs->getColorBinding()==osg::Geometry::BIND_OVERALL) 1772 1772 { … … 1792 1792 break; 1793 1793 } 1794 1794 1795 1795 } 1796 1796 … … 1901 1901 if (geode.getNumDrawables()>=2) 1902 1902 { 1903 1903 1904 1904 // OSG_NOTICE<<"Before "<<geode.getNumDrawables()<<std::endl; 1905 1905 1906 1906 typedef std::vector<osg::Geometry*> DuplicateList; 1907 1907 typedef std::map<osg::Geometry*,DuplicateList,LessGeometry> GeometryDuplicateMap; … … 1932 1932 } 1933 1933 else 1934 { 1934 { 1935 1935 standardDrawables.push_back(geode.getDrawable(i)); 1936 1936 } … … 2019 2019 unsigned int numVertices(duplicateList.front()->getVertexArray() ? duplicateList.front()->getVertexArray()->getNumElements() : 0); 2020 2020 DuplicateList::iterator eachGeom(duplicateList.begin()+1); 2021 // until all geometries have been checked or _targetMaximumNumberOfVertices is reached 2021 // until all geometries have been checked or _targetMaximumNumberOfVertices is reached 2022 2022 for (;eachGeom!=duplicateList.end(); ++eachGeom) 2023 2023 { … … 2050 2050 } 2051 2051 } 2052 2052 2053 2053 if (needToDoMerge) 2054 2054 { … … 2060 2060 keepDrawables[i] = geode.getDrawable(i); 2061 2061 } 2062 2062 2063 2063 // now clear the drawable list of the Geode so we don't have to remove items one by one (which is slow) 2064 2064 geode.removeDrawables(0, geode.getNumDrawables()); 2065 2065 2066 2066 // add back in the standard drawables which arn't possible to merge. 2067 2067 for(osg::Geode::DrawableList::iterator sitr = standardDrawables.begin(); … … 2071 2071 geode.addDrawable(sitr->get()); 2072 2072 } 2073 2073 2074 2074 // now do the merging of geometries 2075 2075 for(MergeList::iterator mitr = mergeList.begin(); … … 2110 2110 ++dupItr) 2111 2111 { 2112 2112 2113 2113 osg::Geometry* rhs = *dupItr; 2114 2114 2115 2115 if (lhs->getVertexArray() && lhs->getVertexArray()->getNumElements()>=_targetMaximumNumberOfVertices) 2116 2116 { … … 2123 2123 continue; 2124 2124 } 2125 2126 if (lhs->getVertexArray() && rhs->getVertexArray() && 2125 2126 if (lhs->getVertexArray() && rhs->getVertexArray() && 2127 2127 (lhs->getVertexArray()->getNumElements()+rhs->getVertexArray()->getNumElements())>=_targetMaximumNumberOfVertices) 2128 2128 { 2129 2129 continue; 2130 2130 } 2131 2131 2132 2132 if (mergeGeometry(*lhs,*rhs)) 2133 2133 { … … 2187 2187 geom->getFogCoordBinding()!=osg::Geometry::BIND_PER_PRIMITIVE_SET) 2188 2188 { 2189 2189 2190 2190 #if 1 2191 2191 bool doneCombine = false; … … 2198 2198 osg::PrimitiveSet* lhs = primitives[lhsNo].get(); 2199 2199 osg::PrimitiveSet* rhs = primitives[rhsNo].get(); 2200 2200 2201 2201 bool combine = false; 2202 2202 … … 2211 2211 case(osg::PrimitiveSet::TRIANGLES): 2212 2212 case(osg::PrimitiveSet::QUADS): 2213 combine = true; 2213 combine = true; 2214 2214 break; 2215 2215 } 2216 2216 2217 2217 } 2218 2218 2219 2219 if (combine) 2220 2220 { 2221 2221 2222 2222 switch(lhs->getType()) 2223 2223 { … … 2257 2257 } 2258 2258 2259 #if 1 2259 #if 1 2260 2260 if (doneCombine) 2261 2261 { … … 2265 2265 osg::Geometry::PrimitiveSetList oldPrimitives; 2266 2266 primitives.swap(oldPrimitives); 2267 2267 2268 2268 // now add the active primitive sets 2269 2269 for(osg::Geometry::PrimitiveSetList::iterator pitr = oldPrimitives.begin(); … … 2276 2276 #endif 2277 2277 2278 #else 2278 #else 2279 2279 2280 2280 osg::Geometry::PrimitiveSetList& primitives = geom->getPrimitiveSetList(); … … 2284 2284 osg::PrimitiveSet* lhs = primitives[primNo].get(); 2285 2285 osg::PrimitiveSet* rhs = primitives[primNo+1].get(); 2286 2286 2287 2287 bool combine = false; 2288 2288 … … 2297 2297 case(osg::PrimitiveSet::TRIANGLES): 2298 2298 case(osg::PrimitiveSet::QUADS): 2299 combine = true; 2299 combine = true; 2300 2300 break; 2301 2301 } 2302 2302 2303 2303 } 2304 2304 2305 2305 if (combine) 2306 2306 { 2307 2307 2308 2308 switch(lhs->getType()) 2309 2309 { … … 2357 2357 if (geom.getSecondaryColorArray() && geom.getSecondaryColorArray()->referenceCount()>1) return true; 2358 2358 if (geom.getFogCoordArray() && geom.getFogCoordArray()->referenceCount()>1) return true; 2359 2359 2360 2360 2361 2361 for(unsigned int unit=0;unit<geom.getNumTexCoordArrays();++unit) … … 2364 2364 if (tex && tex->referenceCount()>1) return true; 2365 2365 } 2366 2366 2367 2367 // shift the indices of the incoming primitives to account for the pre existing geometry. 2368 2368 for(osg::Geometry::PrimitiveSetList::iterator primItr=geom.getPrimitiveSetList().begin(); … … 2372 2372 if ((*primItr)->referenceCount()>1) return true; 2373 2373 } 2374 2375 2374 2375 2376 2376 return false; 2377 2377 } … … 2387 2387 _lhs(0), 2388 2388 _offset(0) {} 2389 2390 2389 2390 2391 2391 /// try to merge the content of two arrays. 2392 2392 bool merge(osg::Array* lhs,osg::Array* rhs, int offset=0) … … 2394 2394 if (lhs==0 || rhs==0) return true; 2395 2395 if (lhs->getType()!=rhs->getType()) return false; 2396 2396 2397 2397 _lhs = lhs; 2398 2398 _offset = offset; 2399 2399 2400 2400 rhs->accept(*this); 2401 2401 return true; 2402 2402 } 2403 2403 2404 2404 template<typename T> 2405 2405 void _merge(T& rhs) 2406 2406 { 2407 T* lhs = static_cast<T*>(_lhs); 2407 T* lhs = static_cast<T*>(_lhs); 2408 2408 lhs->insert(lhs->end(),rhs.begin(),rhs.end()); 2409 2409 } 2410 2410 2411 2411 template<typename T> 2412 2412 void _mergeAndOffset(T& rhs) 2413 2413 { 2414 T* lhs = static_cast<T*>(_lhs); 2414 T* lhs = static_cast<T*>(_lhs); 2415 2415 2416 2416 typename T::iterator itr; … … 2422 2422 } 2423 2423 } 2424 2424 2425 2425 virtual void apply(osg::Array&) { OSG_WARN << "Warning: Optimizer's MergeArrayVisitor cannot merge Array type." << std::endl; } 2426 2426 … … 2437 2437 virtual void apply(osg::Vec3Array& rhs) { _merge(rhs); } 2438 2438 virtual void apply(osg::Vec4Array& rhs) { _merge(rhs); } 2439 2439 2440 2440 virtual void apply(osg::DoubleArray& rhs) { _merge(rhs); } 2441 2441 virtual void apply(osg::Vec2dArray& rhs) { _merge(rhs); } 2442 2442 virtual void apply(osg::Vec3dArray& rhs) { _merge(rhs); } 2443 2443 virtual void apply(osg::Vec4dArray& rhs) { _merge(rhs); } 2444 2444 2445 2445 virtual void apply(osg::Vec2bArray& rhs) { _merge(rhs); } 2446 2446 virtual void apply(osg::Vec3bArray& rhs) { _merge(rhs); } 2447 virtual void apply(osg::Vec4bArray& rhs) { _merge(rhs); } 2447 virtual void apply(osg::Vec4bArray& rhs) { _merge(rhs); } 2448 2448 virtual void apply(osg::Vec2sArray& rhs) { _merge(rhs); } 2449 2449 virtual void apply(osg::Vec3sArray& rhs) { _merge(rhs); } … … 2455 2455 2456 2456 MergeArrayVisitor merger; 2457 2457 2458 2458 unsigned int base = 0; 2459 unsigned int vbase = lhs.getVertexArray() ? lhs.getVertexArray()->getNumElements() : 0; 2459 unsigned int vbase = lhs.getVertexArray() ? lhs.getVertexArray()->getNumElements() : 0; 2460 2460 if (lhs.getVertexArray() && rhs.getVertexArray()) 2461 2461 { … … 2472 2472 lhs.setVertexArray(rhs.getVertexArray()); 2473 2473 } 2474 2474 2475 2475 if (lhs.getVertexIndices() && rhs.getVertexIndices()) 2476 2476 { … … 2487 2487 lhs.setVertexIndices(rhs.getVertexIndices()); 2488 2488 } 2489 2490 2491 unsigned int nbase = lhs.getNormalArray() ? lhs.getNormalArray()->getNumElements() : 0; 2489 2490 2491 unsigned int nbase = lhs.getNormalArray() ? lhs.getNormalArray()->getNumElements() : 0; 2492 2492 if (lhs.getNormalArray() && rhs.getNormalArray() && lhs.getNormalBinding()!=osg::Geometry::BIND_OVERALL) 2493 2493 { … … 2516 2516 2517 2517 2518 unsigned int cbase = lhs.getColorArray() ? lhs.getColorArray()->getNumElements() : 0; 2518 unsigned int cbase = lhs.getColorArray() ? lhs.getColorArray()->getNumElements() : 0; 2519 2519 if (lhs.getColorArray() && rhs.getColorArray() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL) 2520 2520 { … … 2528 2528 lhs.setColorArray(rhs.getColorArray()); 2529 2529 } 2530 2530 2531 2531 if (lhs.getColorIndices() && rhs.getColorIndices() && lhs.getColorBinding()!=osg::Geometry::BIND_OVERALL) 2532 2532 { … … 2542 2542 } 2543 2543 2544 unsigned int scbase = lhs.getSecondaryColorArray() ? lhs.getSecondaryColorArray()->getNumElements() : 0; 2544 unsigned int scbase = lhs.getSecondaryColorArray() ? lhs.getSecondaryColorArray()->getNumElements() : 0; 2545 2545 if (lhs.getSecondaryColorArray() && rhs.getSecondaryColorArray() && lhs.getSecondaryColorBinding()!=osg::Geometry::BIND_OVERALL) 2546 2546 { … … 2554 2554 lhs.setSecondaryColorArray(rhs.getSecondaryColorArray()); 2555 2555 } 2556 2556 2557 2557 if (lhs.getSecondaryColorIndices() && rhs.getSecondaryColorIndices() && lhs.getSecondaryColorBinding()!=osg::Geometry::BIND_OVERALL) 2558 2558 { … … 2568 2568 } 2569 2569 2570 unsigned int fcbase = lhs.getFogCoordArray() ? lhs.getFogCoordArray()->getNumElements() : 0; 2570 unsigned int fcbase = lhs.getFogCoordArray() ? lhs.getFogCoordArray()->getNumElements() : 0; 2571 2571 if (lhs.getFogCoordArray() && rhs.getFogCoordArray() && lhs.getFogCoordBinding()!=osg::Geometry::BIND_OVERALL) 2572 2572 { … … 2598 2598 for(unit=0;unit<lhs.getNumTexCoordArrays();++unit) 2599 2599 { 2600 unsigned int tcbase = lhs.getTexCoordArray(unit) ? lhs.getTexCoordArray(unit)->getNumElements() : 0; 2600 unsigned int tcbase = lhs.getTexCoordArray(unit) ? lhs.getTexCoordArray(unit)->getNumElements() : 0; 2601 2601 if (!merger.merge(lhs.getTexCoordArray(unit),rhs.getTexCoordArray(unit))) 2602 2602 { … … 2612 2612 } 2613 2613 } 2614 2614 2615 2615 for(unit=0;unit<lhs.getNumVertexAttribArrays();++unit) 2616 2616 { 2617 unsigned int vabase = lhs.getVertexAttribArray(unit) ? lhs.getVertexAttribArray(unit)->getNumElements() : 0; 2617 unsigned int vabase = lhs.getVertexAttribArray(unit) ? lhs.getVertexAttribArray(unit)->getNumElements() : 0; 2618 2618 if (!merger.merge(lhs.getVertexAttribArray(unit),rhs.getVertexAttribArray(unit))) 2619 2619 { 2620 2620 OSG_DEBUG << "MergeGeometry: vertex attrib array not merged. Some data may be lost." <<std::endl; 2621 2621 } 2622 2622 2623 2623 if (lhs.getVertexAttribIndices(unit) && rhs.getVertexAttribIndices(unit)) 2624 2624 { … … 2636 2636 { 2637 2637 osg::PrimitiveSet* primitive = primItr->get(); 2638 2638 2639 2639 switch(primitive->getType()) 2640 2640 { … … 2704 2704 } 2705 2705 } 2706 2706 2707 2707 for(primItr=rhs.getPrimitiveSetList().begin(); primItr!=rhs.getPrimitiveSetList().end(); ++primItr) 2708 2708 { … … 2712 2712 lhs.dirtyBound(); 2713 2713 lhs.dirtyDisplayList(); 2714 2714 2715 2715 return true; 2716 2716 } … … 2795 2795 if (divide(*itr,maxNumTreesPerCell)) divided = true; 2796 2796 } 2797 2797 2798 2798 for(GeodesToDivideList::iterator geode_itr=_geodesToDivideList.begin(); 2799 2799 geode_itr!=_geodesToDivideList.end(); … … 2802 2802 if (divide(*geode_itr,maxNumTreesPerCell)) divided = true; 2803 2803 } 2804 2804 2805 2805 return divided; 2806 2806 } … … 2809 2809 { 2810 2810 if (group->getNumChildren()<=maxNumTreesPerCell) return false; 2811 2811 2812 2812 // create the original box. 2813 2813 osg::BoundingBox bb; … … 2817 2817 bb.expandBy(group->getChild(i)->getBound().center()); 2818 2818 } 2819 2819 2820 2820 float radius = bb.radius(); 2821 2821 float divide_distance = radius*0.7f; … … 2825 2825 2826 2826 OSG_INFO<<"Dividing "<<group->className()<<" num children = "<<group->getNumChildren()<<" xAxis="<<xAxis<<" yAxis="<<yAxis<<" zAxis="<<zAxis<<std::endl; 2827 2827 2828 2828 if (!xAxis && !yAxis && !zAxis) 2829 2829 { … … 2831 2831 return false; 2832 2832 } 2833 2833 2834 2834 unsigned int numChildrenOnEntry = group->getNumChildren(); 2835 2835 2836 2836 typedef std::pair< osg::BoundingBox, osg::ref_ptr<osg::Group> > BoxGroupPair; 2837 2837 typedef std::vector< BoxGroupPair > Boxes; … … 2839 2839 boxes.push_back( BoxGroupPair(bb,new osg::Group) ); 2840 2840 2841 // divide up on each axis 2841 // divide up on each axis 2842 2842 if (xAxis) 2843 2843 { … … 2890 2890 2891 2891 // create the groups to drop the children into 2892 2892 2893 2893 2894 2894 // bin each child into associated bb group … … 2921 2921 // add in the bb groups 2922 2922 // add then the unassigned children. 2923 2924 2923 2924 2925 2925 // first removing from the original group, 2926 2926 group->removeChildren(0,group->getNumChildren()); 2927 2927 2928 2928 // add in the bb groups 2929 2929 typedef std::vector< osg::ref_ptr<osg::Group> > GroupList; … … 2951 2951 } 2952 2952 } 2953 2954 2953 2954 2955 2955 // add then the unassigned children. 2956 2956 for(NodeList::iterator nitr=unassignedList.begin(); … … 2970 2970 2971 2971 return (numChildrenOnEntry<group->getNumChildren()); 2972 2972 2973 2973 } 2974 2974 … … 2977 2977 2978 2978 if (geode->getNumDrawables()<=maxNumTreesPerCell) return false; 2979 2979 2980 2980 // create the original box. 2981 2981 osg::BoundingBox bb; … … 2985 2985 bb.expandBy(geode->getDrawable(i)->getBound().center()); 2986 2986 } 2987 2987 2988 2988 float radius = bb.radius(); 2989 2989 float divide_distance = radius*0.7f; … … 2993 2993 2994 2994 OSG_INFO<<"INFO "<<geode->className()<<" num drawables = "<<geode->getNumDrawables()<<" xAxis="<<xAxis<<" yAxis="<<yAxis<<" zAxis="<<zAxis<<std::endl; 2995 2995 2996 2996 if (!xAxis && !yAxis && !zAxis) 2997 2997 { … … 2999 2999 return false; 3000 3000 } 3001 3001 3002 3002 osg::Node::ParentList parents = geode->getParents(); 3003 if (parents.empty()) 3003 if (parents.empty()) 3004 3004 { 3005 3005 OSG_INFO<<" Cannot perform spatialize on root Geode, add a Group above it to allow subdivision."<<std::endl; … … 3016 3016 group->addChild(newGeode); 3017 3017 } 3018 3018 3019 3019 divide(group.get(), maxNumTreesPerCell); 3020 3020 3021 3021 // keep reference around to prevent it being deleted. 3022 3022 osg::ref_ptr<osg::Geode> keepRefGeode = geode; 3023 3023 3024 3024 for(osg::Node::ParentList::iterator itr = parents.begin(); 3025 3025 itr != parents.end(); … … 3028 3028 (*itr)->replaceChild(geode, group.get()); 3029 3029 } 3030 3030 3031 3031 return true; 3032 3032 } … … 3060 3060 osg::ref_ptr<osg::Object> new_object = node->clone(osg::CopyOp::DEEP_COPY_NODES | 3061 3061 osg::CopyOp::DEEP_COPY_DRAWABLES); 3062 // cast it to node. 3062 // cast it to node. 3063 3063 osg::Node* new_node = dynamic_cast<osg::Node*>(new_object.get()); 3064 3064 3065 // replace the node by new_new 3065 // replace the node by new_new 3066 3066 if (new_node) node->getParent(i)->replaceChild(node,new_node); 3067 3067 } … … 3078 3078 void Optimizer::TextureVisitor::apply(osg::Node& node) 3079 3079 { 3080 3080 3081 3081 osg::StateSet* ss = node.getStateSet(); 3082 if (ss && 3082 if (ss && 3083 3083 isOperationPermissibleForObject(&node) && 3084 3084 isOperationPermissibleForObject(ss)) … … 3095 3095 3096 3096 osg::StateSet* ss = geode.getStateSet(); 3097 3097 3098 3098 if (ss && isOperationPermissibleForObject(ss)) 3099 3099 { … … 3140 3140 if (is) ++numImageStreams; 3141 3141 } 3142 3142 3143 3143 if (numImageStreams==0) 3144 3144 { … … 3146 3146 } 3147 3147 } 3148 3148 3149 3149 if (_changeClientImageStorage) 3150 3150 { 3151 3151 texture.setClientStorageHint(_valueClientImageStorage); 3152 3152 } 3153 3153 3154 3154 if (_changeAnisotropy) 3155 3155 { … … 3196 3196 children[i] = group.getChild(i); 3197 3197 } 3198 3198 3199 3199 // remove all children 3200 3200 group.removeChildren(0,group.getNumChildren()); … … 3205 3205 osg::Node* child = children[i].get(); 3206 3206 3207 if (typeid(*child)==typeid(osg::Geode)) 3207 if (typeid(*child)==typeid(osg::Geode)) 3208 3208 { 3209 3209 osg::Geode* geode = static_cast<osg::Geode*>(child); … … 3219 3219 // if no geodes then just return. 3220 3220 if (geodeDuplicateMap.empty()) return false; 3221 3221 3222 3222 OSG_INFO<<"mergeGeodes in group '"<<group.getName()<<"' "<<geodeDuplicateMap.size()<<std::endl; 3223 3223 3224 3224 // merge 3225 3225 for(GeodeDuplicateMap::iterator itr=geodeDuplicateMap.begin(); … … 3233 3233 // add geode back into group 3234 3234 group.addChild(lhs); 3235 3235 3236 3236 for(DuplicateList::iterator dupItr=itr->second.begin()+1; 3237 3237 dupItr!=itr->second.end(); … … 3285 3285 ++itr) 3286 3286 { 3287 bool mergeAcceptable = true; 3287 bool mergeAcceptable = true; 3288 3288 3289 3289 osg::ref_ptr<osg::Billboard> billboard = itr->first; … … 3292 3292 osg::Group* mainGroup = 0; 3293 3293 if (npl.size()>1) 3294 { 3294 { 3295 3295 for(NodePathList::iterator nitr = npl.begin(); 3296 3296 nitr != npl.end(); … … 3306 3306 3307 3307 if (group == mainGroup && 3308 np[np.size()-1]==billboard.get() && 3308 np[np.size()-1]==billboard.get() && 3309 3309 mt && mt->getDataVariance()==osg::Object::STATIC && 3310 3310 mt->getNumChildren()==1) … … 3338 3338 new_billboard->setAxis(billboard->getAxis()); 3339 3339 new_billboard->setStateSet(billboard->getStateSet()); 3340 new_billboard->setName(billboard->getName()); 3340 new_billboard->setName(billboard->getName()); 3341 3341 3342 3342 mainGroup->addChild(new_billboard); … … 3433 3433 3434 3434 Source * source = sitr3->get(); 3435 if (source->_atlas || atlas->_image->getPixelFormat() != source->_image->getPixelFormat() || 3435 if (source->_atlas || atlas->_image->getPixelFormat() != source->_image->getPixelFormat() || 3436 3436 atlas->_image->getDataType() != source->_image->getDataType()) 3437 3437 { … … 3471 3471 { 3472 3472 Source * source = sitr2->get(); 3473 if (source->_atlas || atlas->_image->getPixelFormat() != source->_image->getPixelFormat() || 3473 if (source->_atlas || atlas->_image->getPixelFormat() != source->_image->getPixelFormat() || 3474 3474 atlas->_image->getDataType() != source->_image->getDataType()) 3475 3475 { … … 3520 3520 ++aitr) 3521 3521 { 3522 if(!(*aitr)->_image || 3522 if(!(*aitr)->_image || 3523 3523 ((*aitr)->_image->getPixelFormat() == (*sitr)->_image->getPixelFormat() && 3524 3524 (*aitr)->_image->getPacking() == (*sitr)->_image->getPacking())) … … 3554 3554 } 3555 3555 } 3556 3556 3557 3557 // build the atlas which are suitable for use, and discard the rest. 3558 3558 AtlasList activeAtlasList; … … 3571 3571 atlas->_sourceList.clear(); 3572 3572 } 3573 3573 3574 3574 if (!(atlas->_sourceList.empty())) 3575 3575 { … … 3672 3672 { 3673 3673 if (!_image) return false; 3674 3674 3675 3675 // size too big? 3676 3676 if (_image->s()+margin*2 > maximumAtlasWidth) return false; 3677 3677 if (_image->t()+margin*2 > maximumAtlasHeight) return false; 3678 3678 3679 3679 switch(_image->getPixelFormat()) 3680 3680 { … … 3695 3695 } 3696 3696 3697 if ((_image->getPixelSizeInBits() % 8) != 0) 3697 if ((_image->getPixelSizeInBits() % 8) != 0) 3698 3698 { 3699 3699 // pixel size not byte aligned so report as not suitable to prevent other atlas code from having problems with byte boundaries. … … 3723 3723 } 3724 3724 } 3725 3725 3726 3726 return true; 3727 3727 } … … 3743 3743 const osg::Image* sourceImage = source->_image.get(); 3744 3744 if (!sourceImage) return DOES_NOT_FIT_IN_ANY_ROW; 3745 3745 3746 3746 // does pixel format match? 3747 3747 if (_image.valid()) … … 3750 3750 if (_image->getDataType() != sourceImage->getDataType()) return DOES_NOT_FIT_IN_ANY_ROW; 3751 3751 } 3752 3752 3753 3753 const osg::Texture2D* sourceTexture = source->_texture.get(); 3754 3754 if (sourceTexture) … … 3777 3777 { 3778 3778 3779 bool sourceUsesBorder = sourceTexture->getWrap(osg::Texture2D::WRAP_S)==osg::Texture2D::CLAMP_TO_BORDER || 3779 bool sourceUsesBorder = sourceTexture->getWrap(osg::Texture2D::WRAP_S)==osg::Texture2D::CLAMP_TO_BORDER || 3780 3780 sourceTexture->getWrap(osg::Texture2D::WRAP_T)==osg::Texture2D::CLAMP_TO_BORDER; 3781 3781 3782 bool atlasUsesBorder = sourceTexture->getWrap(osg::Texture2D::WRAP_S)==osg::Texture2D::CLAMP_TO_BORDER || 3782 bool atlasUsesBorder = sourceTexture->getWrap(osg::Texture2D::WRAP_S)==osg::Texture2D::CLAMP_TO_BORDER || 3783 3783 sourceTexture->getWrap(osg::Texture2D::WRAP_T)==osg::Texture2D::CLAMP_TO_BORDER; 3784 3784 … … 3794 3794 if (_texture->getBorderColor() != sourceTexture->getBorderColor()) return DOES_NOT_FIT_IN_ANY_ROW; 3795 3795 } 3796 3796 3797 3797 if (_texture->getFilter(osg::Texture2D::MIN_FILTER) != sourceTexture->getFilter(osg::Texture2D::MIN_FILTER)) 3798 3798 { … … 3800 3800 return DOES_NOT_FIT_IN_ANY_ROW; 3801 3801 } 3802 3802 3803 3803 if (_texture->getFilter(osg::Texture2D::MAG_FILTER) != sourceTexture->getFilter(osg::Texture2D::MAG_FILTER)) 3804 3804 { … … 3806 3806 return DOES_NOT_FIT_IN_ANY_ROW; 3807 3807 } 3808 3808 3809 3809 if (_texture->getMaxAnisotropy() != sourceTexture->getMaxAnisotropy()) 3810 3810 { … … 3812 3812 return DOES_NOT_FIT_IN_ANY_ROW; 3813 3813 } 3814 3814 3815 3815 if (_texture->getInternalFormat() != sourceTexture->getInternalFormat()) 3816 3816 { … … 3818 3818 return DOES_NOT_FIT_IN_ANY_ROW; 3819 3819 } 3820 3820 3821 3821 if (_texture->getShadowCompareFunc() != sourceTexture->getShadowCompareFunc()) 3822 3822 { … … 3824 3824 return DOES_NOT_FIT_IN_ANY_ROW; 3825 3825 } 3826 3826 3827 3827 if (_texture->getShadowTextureMode() != sourceTexture->getShadowTextureMode()) 3828 3828 { … … 3838 3838 } 3839 3839 } 3840 3840 3841 3841 if (sourceImage->s() + 2*_margin > _maximumAtlasWidth) 3842 3842 { … … 3844 3844 return DOES_NOT_FIT_IN_ANY_ROW; 3845 3845 } 3846 3846 3847 3847 if (sourceImage->t() + 2*_margin > _maximumAtlasHeight) 3848 3848 { … … 3872 3872 return IN_NEXT_ROW; 3873 3873 } 3874 3874 3875 3875 // no space for the texture 3876 3876 return DOES_NOT_FIT_IN_ANY_ROW; … … 3903 3903 _texture->setWrap(osg::Texture2D::WRAP_S, sourceTexture->getWrap(osg::Texture2D::WRAP_S)); 3904 3904 _texture->setWrap(osg::Texture2D::WRAP_T, sourceTexture->getWrap(osg::Texture2D::WRAP_T)); 3905 3905 3906 3906 _texture->setBorderColor(sourceTexture->getBorderColor()); 3907 3907 _texture->setBorderWidth(0); 3908 3908 3909 3909 _texture->setFilter(osg::Texture2D::MIN_FILTER, sourceTexture->getFilter(osg::Texture2D::MIN_FILTER)); 3910 3910 _texture->setFilter(osg::Texture2D::MAG_FILTER, sourceTexture->getFilter(osg::Texture2D::MAG_FILTER)); … … 3932 3932 source->_y = _y + _margin; 3933 3933 source->_atlas = this; 3934 3934 3935 3935 // move the atlas' cursor along to the right 3936 3936 _x += sourceImage->s() + 2*_margin; 3937 3937 3938 3938 if (_x > _width) _width = _x; 3939 3939 3940 3940 int localTop = _y + sourceImage->t() + 2*_margin; 3941 3941 if ( localTop > _height) _height = localTop; … … 3960 3960 source->_y = _y + _margin; 3961 3961 source->_atlas = this; 3962 3962 3963 3963 // move the atlas' cursor along to the right 3964 3964 _x += sourceImage->s() + 2*_margin; … … 3986 3986 int h = 1; 3987 3987 while (h<_height) h *= 2; 3988 3988 3989 3989 OSG_INFO<<"Clamping "<<_width<<", "<<_height<<" to "<<w<<","<<h<<std::endl; 3990 3990 3991 3991 _width = w; 3992 3992 _height = h; … … 4003 4003 pixelFormat, dataType, 4004 4004 packing); 4005 4005 4006 4006 { 4007 4007 // clear memory … … 4009 4009 unsigned char* str = _image->data(); 4010 4010 for(unsigned int i=0; i<size; ++i) *(str++) = 0; 4011 } 4011 } 4012 4012 4013 4013 OSG_INFO<<"Atlas::copySources() "<<std::endl; … … 4052 4052 } 4053 4053 } 4054 4054 4055 4055 // copy top row margin 4056 4056 y = source->_y + sourceImage->t(); … … 4064 4064 *(destPtr++) = *(sourcePtr++); 4065 4065 } 4066 4067 } 4068 4066 4067 } 4068 4069 4069 4070 4070 … … 4079 4079 *(destPtr++) = *(sourcePtr++); 4080 4080 } 4081 4081 4082 4082 } 4083 4083 … … 4096 4096 } 4097 4097 } 4098 } 4098 } 4099 4099 4100 4100 // copy right column margin … … 4112 4112 } 4113 4113 } 4114 } 4114 } 4115 4115 4116 4116 // copy top left corner margin … … 4178 4178 { 4179 4179 osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList(); 4180 4180 4181 4181 // if no textures ignore 4182 4182 if (tal.empty()) return false; 4183 4183 4184 4184 bool pushStateState = false; 4185 4185 4186 4186 // if already in stateset list ignore 4187 if (_statesetMap.count(stateset)>0) 4187 if (_statesetMap.count(stateset)>0) 4188 4188 { 4189 4189 pushStateState = true; … … 4208 4208 } 4209 4209 } 4210 4210 4211 4211 if (pushStateState) 4212 4212 { … … 4214 4214 } 4215 4215 4216 4217 return pushStateState; 4216 4217 return pushStateState; 4218 4218 } 4219 4219 … … 4226 4226 { 4227 4227 bool pushedStateState = false; 4228 4228 4229 4229 osg::StateSet* ss = node.getStateSet(); 4230 if (ss && ss->getDataVariance()==osg::Object::STATIC) 4230 if (ss && ss->getDataVariance()==osg::Object::STATIC) 4231 4231 { 4232 4232 if (isOperationPermissibleForObject(&node) && … … 4238 4238 4239 4239 traverse(node); 4240 4240 4241 4241 if (pushedStateState) popStateSet(); 4242 4242 } … … 4247 4247 4248 4248 osg::StateSet* ss = geode.getStateSet(); 4249 4250 4249 4250 4251 4251 bool pushedGeodeStateState = false; 4252 4252 … … 4275 4275 } 4276 4276 } 4277 4277 4278 4278 if (!_statesetStack.empty()) 4279 4279 { 4280 4280 for(StateSetStack::iterator ssitr = _statesetStack.begin(); 4281 ssitr != _statesetStack.end(); 4281 ssitr != _statesetStack.end(); 4282 4282 ++ssitr) 4283 4283 { … … 4288 4288 if (pushedDrawableStateState) popStateSet(); 4289 4289 } 4290 4291 } 4292 4290 4291 } 4292 4293 4293 if (pushedGeodeStateState) popStateSet(); 4294 4294 } … … 4297 4297 { 4298 4298 _builder.reset(); 4299 4299 4300 4300 if (_textures.size()<2) 4301 4301 { … … 4326 4326 bool t_repeat = texture->getWrap(osg::Texture2D::WRAP_T)==osg::Texture2D::REPEAT || 4327 4327 texture->getWrap(osg::Texture2D::WRAP_T)==osg::Texture2D::MIRROR; 4328 4328 4329 4329 if (s_repeat || t_repeat) 4330 4330 { 4331 4331 texturesThatRepeat.insert(texture); 4332 4332 4333 4333 bool s_outOfRange = false; 4334 4334 bool t_outOfRange = false; 4335 4335 4336 4336 float s_min = -0.001; 4337 4337 float s_max = 1.001; … … 4339 4339 float t_min = -0.001; 4340 4340 float t_max = 1.001; 4341 4341 4342 4342 for(Drawables::iterator ditr = drawables.begin(); 4343 4343 ditr != drawables.end(); … … 4365 4365 s_outOfRange = true; 4366 4366 t_outOfRange = true; 4367 } 4367 } 4368 4368 } 4369 4369 4370 if (s_outOfRange || t_outOfRange) 4371 { 4370 if (s_outOfRange || t_outOfRange) 4371 { 4372 4372 texturesThatRepeatAndAreOutOfRange.insert(texture); 4373 4373 } … … 4378 4378 } 4379 4379 4380 // now change any texture that repeat but all texcoords to them 4380 // now change any texture that repeat but all texcoords to them 4381 4381 // are in 0 to 1 range than converting the to CLAMP mode, to allow them 4382 4382 // to be used in an atlas. … … 4434 4434 } 4435 4435 } 4436 4436 4437 4437 Drawables drawablesThatHaveMultipleTexturesOnOneUnit; 4438 4438 for(DrawableStateSetMap::iterator ditr = dssm.begin(); … … 4475 4475 } 4476 4476 } 4477 4478 // remap the textures in the StateSet's 4477 4478 // remap the textures in the StateSet's 4479 4479 for(sitr = _statesetMap.begin(); 4480 4480 sitr != _statesetMap.end(); … … 4503 4503 4504 4504 stateset->setTextureAttribute(unit, newTexture); 4505 4505 4506 4506 Drawables& drawables = sitr->second; 4507 4507 4508 4508 osg::Matrix matrix = _builder.getTextureMatrix(texture); 4509 4509 4510 4510 // first check to see if all drawables are ok for applying texturematrix to. 4511 4511 bool canTexMatBeFlattenedToAllDrawables = true; … … 4517 4517 osg::Vec2Array* texcoords = geom ? dynamic_cast<osg::Vec2Array*>(geom->getTexCoordArray(unit)) : 0; 4518 4518 4519 if (!texcoords) 4519 if (!texcoords) 4520 4520 { 4521 4521 canTexMatBeFlattenedToAllDrawables = false; 4522 4522 } 4523 4523 4524 4524 if (drawablesThatHaveMultipleTexturesOnOneUnit.count(*ditr)!=0) 4525 4525 { … … 4551 4551 { 4552 4552 OSG_NOTICE<<"Error, Optimizer::TextureAtlasVisitor::optimize() shouldn't ever get here..."<<std::endl; 4553 } 4553 } 4554 4554 } 4555 4555 } … … 4597 4597 4598 4598 void Optimizer::StaticObjectDetectionVisitor::applyDrawable(osg::Drawable& drawable) 4599 { 4600 4599 { 4600 4601 4601 if (drawable.getStateSet()) applyStateSet(*drawable.getStateSet()); 4602 4602 4603 4603 drawable.computeDataVariance(); 4604 4604 } … … 4661 4661 _matrixStack.push_back(matrix); 4662 4662 pushed = true; 4663 4663 4664 4664 // convert this Transform to a Group 4665 4665 osg::ref_ptr<osg::Group> group = new osg::Group(dynamic_cast<osg::Group&>(transform), … … 4736 4736 { 4737 4737 transformGeode(geode); 4738 } 4738 } 4739 4739 else 4740 4740 {
