From 70861ef70e374d63e88b91ba65799a2cb27085ae Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 6 Oct 2002 20:33:13 +0000 Subject: [PATCH] Converted osg::LOD from used n+1 successive ranges to n min/max ranges, one min/max pair per child. Converted the rest of the OSG to use the new osg::LOD node. --- include/osg/CollectOccludersVisitor | 3 + include/osg/CullStack | 6 +- include/osg/Group | 12 +++ include/osg/LOD | 86 +++++++++------------ include/osg/NodeVisitor | 13 +++- include/osgUtil/CullVisitor | 3 + src/Demos/osgcallback/osgcallback.cpp | 19 ----- src/Demos/osgimpostor/osgimpostor.cpp | 3 +- src/osg/CollectOccludersVisitor.cpp | 21 +++-- src/osg/LOD.cpp | 73 +++++++++-------- src/osg/Switch.cpp | 18 +---- src/osgPlugins/flt/flt2osg.cpp | 14 +++- src/osgPlugins/osg/LOD.cpp | 60 +++++++++++--- src/osgPlugins/osg/Switch.cpp | 6 +- src/osgPlugins/pfb/ConvertFromPerformer.cpp | 4 +- src/osgPlugins/txp/TrPageParser.cpp | 3 +- src/osgUtil/CullVisitor.cpp | 41 ++++++---- src/osgUtil/InsertImpostorsVisitor.cpp | 11 +-- src/osgUtil/Optimizer.cpp | 39 ++++------ 19 files changed, 240 insertions(+), 195 deletions(-) diff --git a/include/osg/CollectOccludersVisitor b/include/osg/CollectOccludersVisitor index 8846ec3f9..6f8ea134c 100644 --- a/include/osg/CollectOccludersVisitor +++ b/include/osg/CollectOccludersVisitor @@ -26,6 +26,9 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C virtual void reset(); + virtual float getDistanceToEyePoint(const Vec3& pos, bool withLODBias) const; + virtual float getDistanceFromEyePoint(const Vec3& pos, bool withLODBias) const; + virtual void apply(osg::Node&); virtual void apply(osg::Transform& node); virtual void apply(osg::Projection& node); diff --git a/include/osg/CullStack b/include/osg/CullStack index 6bf2ba2c6..4b25f6b8d 100644 --- a/include/osg/CullStack +++ b/include/osg/CullStack @@ -140,7 +140,7 @@ class SG_EXPORT CullStack inline osg::Viewport* getViewport(); inline osg::Matrix& getModelViewMatrix(); inline osg::Matrix& getProjectionMatrix(); - inline const osg::Matrix getWindowMatrix(); + inline osg::Matrix getWindowMatrix(); inline const osg::Matrix& getMVPW(); inline const osg::Vec3& getEyeLocal() const { return _eyePointStack.back(); } @@ -156,7 +156,7 @@ class SG_EXPORT CullStack const osg::Matrix& matrix = *_modelviewStack.back(); return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2)); } - + protected: void pushCullingSet(); @@ -239,7 +239,7 @@ inline osg::Matrix& CullStack::getProjectionMatrix() } } -inline const osg::Matrix CullStack::getWindowMatrix() +inline osg::Matrix CullStack::getWindowMatrix() { if (!_viewportStack.empty()) { diff --git a/include/osg/Group b/include/osg/Group index 567654168..4fd44a4df 100644 --- a/include/osg/Group +++ b/include/osg/Group @@ -110,6 +110,18 @@ class SG_EXPORT Group : public Node return _children.end(); } + /** Find the index number of child, return a value between + * 0 and _children.size()-1 if found, if not found then + * return _children.size().*/ + inline unsigned int findChildNo( const Node* node ) const + { + for (unsigned int childNo=0;childNo<_children.size();++childNo) + { + if (_children[childNo]==node) return childNo; + } + return _children.size(); // node not found. + } + protected: virtual ~Group(); diff --git a/include/osg/LOD b/include/osg/LOD index c780d901d..fc1c84c11 100644 --- a/include/osg/LOD +++ b/include/osg/LOD @@ -36,68 +36,58 @@ class SG_EXPORT LOD : public Group virtual void traverse(NodeVisitor& nv); - /** Sets the value of range list element index to range which - is a floating point distance specified in world coordinates. - Range list automatically expands to accommodate values beyond - the current getNumRanges().*/ - void setRange(unsigned int index, float range); - - /** returns the range for specified index.*/ - inline float getRange(unsigned int index) const { return _rangeList[index]; } - - /** returns the number of ranges currently set.*/ - inline unsigned int getNumRanges() const { return _rangeList.size(); } + virtual bool addChild( Node *child ); + + virtual bool removeChild( Node *child ); + + + typedef std::pair MinMaxPair; + typedef std::vector RangeList; + + enum CenterMode + { + USE_BOUNDING_SPHERE_CENTER, + USER_DEFINED_CENTER + }; + + void setCenterMode(CenterMode mode) { _centerMode=mode; } + + CenterMode getCenterMode() const { return _centerMode; } /** Sets the object-space point which defines the center of the osg::LOD. center is affected by any transforms in the hierarchy above the osg::LOD.*/ - inline void setCenter(const Vec3& center) { _center = center; } + inline void setCenter(const Vec3& center) { _centerMode=USER_DEFINED_CENTER; _userDefinedCenter = center; } /** return the LOD center point. */ - inline const Vec3& getCenter() const { return _center; } + inline const Vec3& getCenter() const { if (_centerMode==USER_DEFINED_CENTER) return _userDefinedCenter; else return getBound().center(); } - - /** Callback attached to an LOD which allows the users to customize the selection of LOD children.*/ - struct EvaluateLODCallback : public osg::Referenced - { - /** Compute the child to select.*/ - virtual int evaluateLODChild(const osg::LOD* lod, const Vec3& eye_local, float bias) const = 0; - }; - - /** Set the EvaluateLODCallback which allows users to attach customize computation of the the selection of LOD children.*/ - void setEvaluateLODCallback(EvaluateLODCallback* cbc) { _evaluateLODCallback=cbc; } + /** Sets the min and max visible ranges of range of specifiec child. + Values are floating point distance specified in local objects coordinates.*/ + void setRange(unsigned int childNo, float min,float max); - /** Get the non const ComputeBillboardCallback.*/ - EvaluateLODCallback* getEvaluateLODCallback() { return _evaluateLODCallback.get(); } + /** returns the min visible range for specified child.*/ + inline float getMinRange(unsigned int childNo) const { return _rangeList[childNo].first; } + + /** returns the max visible range for specified child.*/ + inline float getMaxRange(unsigned int childNo) const { return _rangeList[childNo].second; } - /** Get the const ComputeBillboardCallback.*/ - const EvaluateLODCallback* getEvaluateLODCallback() const { return _evaluateLODCallback.get(); } + /** returns the number of ranges currently set. + * An LOD which has been fully set up will have getNumChildren()==getNumRanges(). */ + inline unsigned int getNumRanges() const { return _rangeList.size(); } - /** return the child to traverse. - Selected by the distance between the eye point in local - coordinates and the LOD center, multiplied by the bias.*/ - inline int evaluate(const Vec3& eye_local,float bias=1.0f) const - { - if (_evaluateLODCallback.valid()) - return _evaluateLODCallback->evaluateLODChild(this,eye_local,bias); - else - return evaluateLODChild(eye_local,bias); - } - - - virtual int evaluateLODChild(const Vec3& eye_local,float bias) const; + /** return the list of MinMax ranges for each child.*/ + inline RangeList& getRangeList() { return _rangeList; } + + /** return the list of MinMax ranges for each child.*/ + inline const RangeList& getRangeList() const { return _rangeList; } protected : virtual ~LOD() {} + CenterMode _centerMode; + Vec3 _userDefinedCenter; - typedef std::vector RangeList; - RangeList _rangeList; - RangeList _rangeList2; - - ref_ptr _evaluateLODCallback; - - Vec3 _center; - + RangeList _rangeList; }; diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index 46f4ed1ed..5c732dd7c 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -184,11 +184,20 @@ class SG_EXPORT NodeVisitor : public Referenced const NodePath& getNodePath() const { return _nodePath; } /** Get the Local To World Matrix from the NodePath for specified Transform::Mode, and u.*/ - bool getLocalToWorldMatrix(Matrix& matrix, Node* node); + virtual bool getLocalToWorldMatrix(Matrix& matrix, Node* node); /** Get the World To Local Matrix from the NodePath for specified Transform::Mode.*/ - bool getWorldToLocalMatrix(Matrix& matrix, Node* node); + virtual bool getWorldToLocalMatrix(Matrix& matrix, Node* node); + /** Get the distance from a point to the eye point, distance value in local coordinate system. + * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement. + * If the getDistianceFromEyePoint(pos) is not implmented than a default value of 0.0 is returned.*/ + virtual float getDistanceToEyePoint(const Vec3& /*pos*/, bool /*useLODBias*/) const { return 0.0f; } + + /** Get the distance of a point from the eye point, distance value in the eye coordinate system. + * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement. + * If the getDistianceFromEyePoint(pos) is not implmented than a default value of 0.0 is returned.*/ + virtual float getDistanceFromEyePoint(const Vec3& /*pos*/, bool /*useLODBias*/) const { return 0.0f; } virtual void apply(Node& node) { traverse(node);} diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index efdb8454a..b27cb294c 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -47,6 +47,9 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac virtual CullVisitor* cloneType() const { return osgNew CullVisitor(); } virtual void reset(); + + virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODBias) const; + virtual float getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODBias) const; virtual void apply(osg::Node&); virtual void apply(osg::Geode& node); diff --git a/src/Demos/osgcallback/osgcallback.cpp b/src/Demos/osgcallback/osgcallback.cpp index 568f69a5b..45fece80f 100644 --- a/src/Demos/osgcallback/osgcallback.cpp +++ b/src/Demos/osgcallback/osgcallback.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -80,18 +79,6 @@ class DrawableDrawCallback : public osg::Drawable::DrawCallback } }; -struct LODCallback : public osg::LOD::EvaluateLODCallback -{ - /** Compute the child to select.*/ - virtual int evaluateLODChild(const osg::LOD* lod, const osg::Vec3& eye_local, float bias) const - { - std::cout<<"evaluateLODChild callback - pre lod->evaluateLODChild"<evaluateLODChild(eye_local,bias); - std::cout<<"evaluateLODChild callback - post lod->evaluateLODChild"<addChild(model); - impostor->setRange(0,0.0f); - impostor->setRange(1,1e7f); + impostor->setRange(0,0.0f,1e7f); impostor->setCenter(bs.center()); // impostor specfic settings. diff --git a/src/osg/CollectOccludersVisitor.cpp b/src/osg/CollectOccludersVisitor.cpp index be503f494..29e7b58f1 100644 --- a/src/osg/CollectOccludersVisitor.cpp +++ b/src/osg/CollectOccludersVisitor.cpp @@ -32,6 +32,21 @@ void CollectOccludersVisitor::reset() CullStack::reset(); } +float CollectOccludersVisitor::getDistanceToEyePoint(const Vec3& pos, bool withLODBias) const +{ + if (withLODBias) return (pos-getEyeLocal()).length()*getLODBias(); + else return (pos-getEyeLocal()).length(); +} + +float CollectOccludersVisitor::getDistanceFromEyePoint(const Vec3& pos, bool withLODBias) const +{ + const Matrix& matrix = *_modelviewStack.back(); + float dist = -(pos[0]*matrix(0,2)+pos[1]*matrix(1,2)+pos[2]*matrix(2,2)+matrix(3,2)); + + if (withLODBias) return dist*getLODBias(); + else return dist*getLODBias(); +} + void CollectOccludersVisitor::apply(osg::Node& node) { if (isCulled(node)) return; @@ -91,14 +106,10 @@ void CollectOccludersVisitor::apply(osg::LOD& node) { if (isCulled(node)) return; - int eval = node.evaluate(getEyeLocal(),_LODBias); - if (eval<0) return; - // push the culling mode. pushCurrentMask(); - //notify(INFO) << "selecting child "<accept(nv); - break; + { + float distance = nv.getDistanceToEyePoint(getCenter(),true); + unsigned int numChildren = _children.size(); + if (_rangeList.size()accept(nv); + } + } + break; + } default: break; } } - -void LOD::setRange(unsigned int index, float range) +bool LOD::addChild( Node *child ) { - if (index<_rangeList.size()) _rangeList[index] = range; - else while (index>=_rangeList.size()) _rangeList.push_back(range); - - if (index<_rangeList2.size()) _rangeList2[index] = range*range; - else while (index>=_rangeList2.size()) _rangeList2.push_back(range*range); -} - - -int LOD::evaluateLODChild(const Vec3& eye_local, float bias) const -{ - // For cache coherency, use _rangeList2 exclusively - if (_rangeList2.empty()) return -1; - - // Test distance-squared against the stored array of squared ranges - float LODRange = (eye_local-_center).length2()*bias; - if (LODRange<_rangeList2[0]) return -1; - - unsigned int end_marker = _rangeList2.size()-1; - if (end_marker>_children.size()) end_marker=_children.size(); - for(unsigned int i=0;i_rangeList.size()) _rangeList.resize(_children.size(),MinMaxPair(maxRange,maxRange)); + return true; } - return -1; + return false; } +bool LOD::removeChild( Node *child ) +{ + // find the child's position. + unsigned int pos=findChildNo(child); + if (pos==_children.size()) return false; + + _rangeList.erase(_rangeList.begin()+pos); + + return Group::removeChild(child); +} + +void LOD::setRange(unsigned int childNo, float min,float max) +{ + if (childNo>=_rangeList.size()) _rangeList.resize(childNo+1,MinMaxPair(min,min)); + _rangeList[childNo].first=min; + _rangeList[childNo].second=max; +} diff --git a/src/osg/Switch.cpp b/src/osg/Switch.cpp index 82de3ff76..f5cabe44c 100644 --- a/src/osg/Switch.cpp +++ b/src/osg/Switch.cpp @@ -53,11 +53,7 @@ bool Switch::addChild( Node *child ) bool Switch::removeChild( Node *child ) { // find the child's position. - unsigned int pos=0; - for (;pos<_children.size();++pos) - { - if (_children[pos]==child) break; - } + unsigned int pos=findChildNo(child); if (pos==_children.size()) return false; _values.erase(_values.begin()+pos); @@ -74,11 +70,7 @@ void Switch::setValue(unsigned int pos,bool value) void Switch::setValue(const Node* child,bool value) { // find the child's position. - unsigned int pos=0; - for (;pos<_children.size();++pos) - { - if (_children[pos]==child) break; - } + unsigned int pos=findChildNo(child); if (pos==_children.size()) return; _values[pos]=value; @@ -93,11 +85,7 @@ bool Switch::getValue(unsigned int pos) const bool Switch::getValue(const Node* child) const { // find the child's position. - unsigned int pos=0; - for (;pos<_children.size();++pos) - { - if (_children[pos]==child) break; - } + unsigned int pos=findChildNo(child); if (pos==_children.size()) return false; return _values[pos]; diff --git a/src/osgPlugins/flt/flt2osg.cpp b/src/osgPlugins/flt/flt2osg.cpp index 99f0e8fc1..c9b593295 100644 --- a/src/osgPlugins/flt/flt2osg.cpp +++ b/src/osgPlugins/flt/flt2osg.cpp @@ -646,9 +646,12 @@ osg::Group* ConvertFromFLT::visitLOD(osg::Group& osgParent, LodRecord* rec) float64x3* pCenter = &pSLOD->Center; lod->setCenter(osg::Vec3(pCenter->x(), pCenter->y(), pCenter->z())*_unitScale); - lod->setRange(0, pSLOD->dfSwitchOutDist*_unitScale); - lod->setRange(1, pSLOD->dfSwitchInDist*_unitScale); + + lod->setRange(0, pSLOD->dfSwitchOutDist*_unitScale, + pSLOD->dfSwitchInDist*_unitScale); + lod->setName(pSLOD->szIdent); + visitAncillary(osgParent, *lod, rec)->addChild( lod ); osg::Group* group = new osg::Group; @@ -668,9 +671,12 @@ osg::Group* ConvertFromFLT::visitOldLOD(osg::Group& osgParent, OldLodRecord* rec (float)pSLOD->Center[0], (float)pSLOD->Center[1], (float)pSLOD->Center[2])*_unitScale); - lod->setRange(0, ((float)pSLOD->dwSwitchOutDist)*_unitScale); - lod->setRange(1, ((float)pSLOD->dwSwitchInDist)*_unitScale); + + lod->setRange(0, ((float)pSLOD->dwSwitchOutDist)*_unitScale, + ((float)pSLOD->dwSwitchInDist)*_unitScale); + lod->setName(pSLOD->szIdent); + visitAncillary(osgParent, *lod, rec)->addChild( lod ); osg::Group* group = new osg::Group; diff --git a/src/osgPlugins/osg/LOD.cpp b/src/osgPlugins/osg/LOD.cpp index 4b9a3b69a..1fdcd1484 100644 --- a/src/osgPlugins/osg/LOD.cpp +++ b/src/osgPlugins/osg/LOD.cpp @@ -39,32 +39,36 @@ bool LOD_readLocalData(Object& obj, Input& fr) fr+=4; } + // For backwards compatibility with old style LOD's (pre October 2002). bool matchFirst = false; if ((matchFirst=fr.matchSequence("Ranges {")) || fr.matchSequence("Ranges %i {")) { // set up coordinates. int entry = fr[0].getNoNestedBrackets(); + int capacity; if (matchFirst) { fr += 2; } - else + else if (fr[1].getInt(capacity)) { - //_rangeList.(capacity); + lod.getRangeList().reserve(capacity); fr += 3; } - float range; - int i=0; + float minRange=0.0; + float maxRange=0.0; + unsigned int i=0; while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { - if (fr[0].getFloat(range)) + if (fr[0].getFloat(maxRange)) { - lod.setRange(i,range); + if (i>0) lod.setRange(i-1,minRange,maxRange); ++fr; ++i; + minRange = maxRange; } else { @@ -77,6 +81,44 @@ bool LOD_readLocalData(Object& obj, Input& fr) } + if ((matchFirst=fr.matchSequence("RangeList {")) || fr.matchSequence("RangeList %i {")) + { + + // set up coordinates. + int entry = fr[0].getNoNestedBrackets(); + int capacity; + + if (matchFirst) + { + fr += 2; + } + else if (fr[1].getInt(capacity)) + { + lod.getRangeList().reserve(capacity); + fr += 3; + } + + float minRange=0.0; + float maxRange=0.0; + unsigned int i=0; + while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) + { + if (fr[0].getFloat(minRange) && fr[1].getFloat(maxRange) ) + { + lod.setRange(i,minRange,maxRange); + fr+=2; + ++i; + } + else + { + ++fr; + } + } + + iteratorAdvanced = true; + ++fr; + + } return iteratorAdvanced; } @@ -85,14 +127,14 @@ bool LOD_writeLocalData(const Object& obj, Output& fw) { const LOD& lod = static_cast(obj); - fw.indent() << "Center "<< lod.getCenter() << std::endl; + if (lod.getCenterMode()==osg::LOD::USER_DEFINED_CENTER) fw.indent() << "Center "<< lod.getCenter() << std::endl; - fw.indent() << "Ranges {"<< std::endl; + fw.indent() << "RangeList "<setCenter(osgCenter); int i; - for(i=0;igetNumRanges();++i) + for(i=0;igetNumRanges()-1;++i) { - osgLOD->setRange(i,lod->getRange(i)); + osgLOD->setRange(i,lod->getRange(i),lod->getRange(i+1)); } for(i=0;igetNumChildren();++i) diff --git a/src/osgPlugins/txp/TrPageParser.cpp b/src/osgPlugins/txp/TrPageParser.cpp index a8411ef41..a43abfebb 100644 --- a/src/osgPlugins/txp/TrPageParser.cpp +++ b/src/osgPlugins/txp/TrPageParser.cpp @@ -489,8 +489,7 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) Vec3 osg_Center; osg_Center[0] = center.x; osg_Center[1] = center.y; osg_Center[2] = center.z; osg_Lod->setCenter(osg_Center); - osg_Lod->setRange(0,minRange); - osg_Lod->setRange(1,maxRange); + osg_Lod->setRange(0,minRange,maxRange); // Our LODs are binary so we need to add a group under this LOD and attach stuff // to that instead of the LOD diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 7a51dd875..5055ce694 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -132,6 +132,25 @@ void CullVisitor::reset() } +float CullVisitor::getDistanceToEyePoint(const Vec3& pos, bool withLODBias) const +{ + if (withLODBias) return (pos-getEyeLocal()).length()*getLODBias(); + else return (pos-getEyeLocal()).length(); +} + +inline float distance(const osg::Vec3& coord,const osg::Matrix& matrix) +{ + return -(coord[0]*matrix(0,2)+coord[1]*matrix(1,2)+coord[2]*matrix(2,2)+matrix(3,2)); +} + +float CullVisitor::getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODBias) const +{ + const Matrix& matrix = *_modelviewStack.back(); + float dist = distance(pos,matrix); + + if (withLODBias) return dist*getLODBias(); + else return dist*getLODBias(); +} void CullVisitor::popProjectionMatrix() { @@ -168,10 +187,6 @@ void CullVisitor::popProjectionMatrix() CullStack::popProjectionMatrix(); } -inline float distance(const osg::Vec3& coord,const osg::Matrix& matrix) -{ - return -(coord[0]*matrix(0,2)+coord[1]*matrix(1,2)+coord[2]*matrix(2,2)+matrix(3,2)); -} void CullVisitor::updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb) @@ -459,9 +474,6 @@ void CullVisitor::apply(LOD& node) { if (isCulled(node)) return; - int eval = node.evaluate(getEyeLocal(),_LODBias); - if (eval<0) return; - // push the culling mode. pushCurrentMask(); @@ -469,8 +481,7 @@ void CullVisitor::apply(LOD& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - //notify(INFO) << "selecting child "<addChild(group); - impostor->setRange(0,0.0f); - impostor->setRange(1,1e7f); - impostor->setCenter(bs.center()); + impostor->setRange(0,0.0f,1e7f); // impostor specfic settings. impostor->setImpostorThresholdToBound(_impostorThresholdRatio); @@ -147,14 +145,11 @@ void InsertImpostorsVisitor::insertImpostors() for(unsigned int ci=0;cigetNumChildren();++ci) { impostor->addChild(lod->getChild(ci)); - } - - for(unsigned int ri=0;rigetNumRanges();++ri) - { - impostor->setRange(ri,lod->getRange(ri)); + impostor->setRange(ci,lod->getMinRange(ci),lod->getMaxRange(ci)); } impostor->setCenter(lod->getCenter()); + impostor->setCenterMode(lod->getCenterMode()); // impostor specfic settings. impostor->setImpostorThresholdToBound(_impostorThresholdRatio); diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index f32bf1bcf..b9b45deb5 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -24,13 +24,12 @@ using namespace osgUtil; void Optimizer::optimize(osg::Node* node, unsigned int options) { -// temporarily commented out to prevent problems with combining FLT lod's inapporpriately, -// if (options & COMBINE_ADJACENT_LODS) -// { -// CombineLODsVisitor clv; -// node->accept(clv); -// clv.combineLODs(); -// } + if (options & COMBINE_ADJACENT_LODS) + { + CombineLODsVisitor clv; + node->accept(clv); + clv.combineLODs(); + } if (options & FLATTEN_STATIC_TRANSFORMS) { @@ -560,7 +559,7 @@ void CollectLowestTransformsVisitor::doTransform(osg::Object* obj,osg::Matrix& m // adjust ranges to new scale. for(unsigned int i=0;igetNumRanges();++i) { - lod->setRange(i,lod->getRange(i)*ratio); + lod->setRange(i,lod->getMinRange(i)*ratio,lod->getMaxRange(i)*ratio); } lod->dirtyBound(); @@ -968,14 +967,7 @@ void Optimizer::CombineLODsVisitor::combineLODs() osg::LOD* lod = dynamic_cast(child); if (lod) { - if (lod->getNumRanges()-1==lod->getNumChildren()) - { - lodChildren.insert(lod); - } - else - { - // wonky LOD, numRanges should = numChildren+1 - } + lodChildren.insert(lod); } } @@ -983,29 +975,29 @@ void Optimizer::CombineLODsVisitor::combineLODs() { osg::BoundingBox bb; LODSet::iterator lod_itr; + float smallestRadius=FLT_MAX; for(lod_itr=lodChildren.begin(); lod_itr!=lodChildren.end(); ++lod_itr) { - + float r = (*lod_itr)->getBound().radius(); + if (r>=0 && rgetCenter()); } - if (bb.radius()<1e-2) + if (bb.radius() RangePair; typedef std::multimap RangeMap; RangeMap rangeMap; - float maxRange = 0.0f; for(lod_itr=lodChildren.begin(); lod_itr!=lodChildren.end(); ++lod_itr) { osg::LOD* lod = *lod_itr; - for(unsigned int i=0;igetNumRanges()-1;++i) + for(unsigned int i=0;igetNumRanges();++i) { - if (maxRangegetRange(i+1)) maxRange = lod->getRange(i+1); - rangeMap.insert(RangeMap::value_type(RangePair(lod->getRange(i),lod->getRange(i+1)),lod->getChild(i))); + rangeMap.insert(RangeMap::value_type(RangePair(lod->getMinRange(i),lod->getMaxRange(i)),lod->getChild(i))); } } @@ -1020,10 +1012,9 @@ void Optimizer::CombineLODsVisitor::combineLODs() c_itr!=rangeMap.end(); ++c_itr,++i) { - newLOD->setRange(i,c_itr->first.first); + newLOD->setRange(i,c_itr->first.first,c_itr->first.second); newLOD->addChild(c_itr->second); } - newLOD->setRange(i,maxRange); // add LOD into parent. group->addChild(newLOD);