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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<float,float> MinMaxPair;
|
||||
typedef std::vector<MinMaxPair> 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<float> RangeList;
|
||||
RangeList _rangeList;
|
||||
RangeList _rangeList2;
|
||||
|
||||
ref_ptr<EvaluateLODCallback> _evaluateLODCallback;
|
||||
|
||||
Vec3 _center;
|
||||
|
||||
RangeList _rangeList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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);}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/LOD>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
@@ -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"<<std::endl;
|
||||
int result = lod->evaluateLODChild(eye_local,bias);
|
||||
std::cout<<"evaluateLODChild callback - post lod->evaluateLODChild"<<std::endl;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct TransformCallback : public osg::Transform::ComputeTransformCallback
|
||||
{
|
||||
/** Get the transformation matrix which moves from local coords to world coords.*/
|
||||
@@ -170,12 +157,6 @@ class InsertCallbacksVisitor : public osg::NodeVisitor
|
||||
node.setComputeTransformCallback(new TransformCallback());
|
||||
apply((osg::Node&)node);
|
||||
}
|
||||
|
||||
virtual void apply(osg::LOD& node)
|
||||
{
|
||||
node.setEvaluateLODCallback(new LODCallback());
|
||||
apply((osg::Node&)node);
|
||||
}
|
||||
};
|
||||
|
||||
int main( int argc, char **argv )
|
||||
|
||||
@@ -99,8 +99,7 @@ int main( int argc, char **argv )
|
||||
|
||||
// standard LOD settings
|
||||
impostor->addChild(model);
|
||||
impostor->setRange(0,0.0f);
|
||||
impostor->setRange(1,1e7f);
|
||||
impostor->setRange(0,0.0f,1e7f);
|
||||
impostor->setCenter(bs.center());
|
||||
|
||||
// impostor specfic settings.
|
||||
|
||||
@@ -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 "<<eval<< std::endl;
|
||||
handle_cull_callbacks_and_accept(node,node.getChild(eval));
|
||||
handle_cull_callbacks_and_traverse(node);
|
||||
|
||||
// pop the culling mode.
|
||||
popCurrentMask();
|
||||
|
||||
@@ -6,9 +6,9 @@ using namespace osg;
|
||||
|
||||
LOD::LOD(const LOD& lod,const CopyOp& copyop):
|
||||
Group(lod,copyop),
|
||||
_rangeList(lod._rangeList),
|
||||
_rangeList2(lod._rangeList2),
|
||||
_center(lod._center)
|
||||
_centerMode(lod._centerMode),
|
||||
_userDefinedCenter(lod._userDefinedCenter),
|
||||
_rangeList(lod._rangeList)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -21,42 +21,51 @@ void LOD::traverse(NodeVisitor& nv)
|
||||
std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
|
||||
break;
|
||||
case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
|
||||
if (_children.size()!=0) _children.front()->accept(nv);
|
||||
break;
|
||||
{
|
||||
float distance = nv.getDistanceToEyePoint(getCenter(),true);
|
||||
unsigned int numChildren = _children.size();
|
||||
if (_rangeList.size()<numChildren) numChildren=_rangeList.size();
|
||||
|
||||
for(unsigned int i=0;i<numChildren;++i)
|
||||
{
|
||||
if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
|
||||
{
|
||||
_children[i]->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<end_marker;++i)
|
||||
if (Group::addChild(child))
|
||||
{
|
||||
if (LODRange<_rangeList2[i+1])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
float maxRange = 0.0f;
|
||||
if (!_rangeList.empty()) maxRange=_rangeList.back().second;
|
||||
if (_children.size()>_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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<const LOD&>(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 "<<lod.getNumRanges()<<" {"<< std::endl;
|
||||
fw.moveIn();
|
||||
|
||||
for(unsigned int i=0; i<lod.getNumRanges();++i)
|
||||
{
|
||||
fw.indent() << lod.getRange(i) << std::endl;
|
||||
fw.indent() << lod.getMinRange(i) << " "<<lod.getMaxRange(i)<<std::endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent() << "}"<< std::endl;
|
||||
|
||||
@@ -16,7 +16,7 @@ RegisterDotOsgWrapperProxy g_SwitchProxy
|
||||
(
|
||||
osgNew osg::Switch,
|
||||
"Switch",
|
||||
"Object Node Group Switch",
|
||||
"Object Node Switch Group",
|
||||
&Switch_readLocalData,
|
||||
&Switch_writeLocalData
|
||||
);
|
||||
@@ -51,7 +51,7 @@ bool Switch_readLocalData(Object& obj, Input& fr)
|
||||
}
|
||||
}
|
||||
|
||||
if (fr.matchSequence("values {"))
|
||||
if (fr.matchSequence("ValueList {"))
|
||||
{
|
||||
int entry = fr[0].getNoNestedBrackets();
|
||||
|
||||
@@ -89,7 +89,7 @@ bool Switch_writeLocalData(const Object& obj, Output& fw)
|
||||
{
|
||||
case(Switch::MULTIPLE_CHILDREN_ON):
|
||||
{
|
||||
fw.indent()<<"values {"<< std::endl;
|
||||
fw.indent()<<"ValueList {"<< std::endl;
|
||||
fw.moveIn();
|
||||
const Switch::ValueList& values = sw.getValueList();
|
||||
for(Switch::ValueList::const_iterator itr=values.begin();
|
||||
|
||||
@@ -202,9 +202,9 @@ osg::Node* ConvertFromPerformer::visitLOD(osg::Group* osgParent,pfLOD* lod)
|
||||
osgLOD->setCenter(osgCenter);
|
||||
|
||||
int i;
|
||||
for(i=0;i<lod->getNumRanges();++i)
|
||||
for(i=0;i<lod->getNumRanges()-1;++i)
|
||||
{
|
||||
osgLOD->setRange(i,lod->getRange(i));
|
||||
osgLOD->setRange(i,lod->getRange(i),lod->getRange(i+1));
|
||||
}
|
||||
|
||||
for(i=0;i<lod->getNumChildren();++i)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "<<eval<< std::endl;
|
||||
handle_cull_callbacks_and_accept(node,node.getChild(eval));
|
||||
handle_cull_callbacks_and_traverse(node);
|
||||
|
||||
// pop the node's state off the render graph stack.
|
||||
if (node_state) popStateSet();
|
||||
@@ -538,9 +549,6 @@ void CullVisitor::apply(Impostor& node)
|
||||
|
||||
osg::Vec3 eyeLocal = getEyeLocal();
|
||||
|
||||
int eval = node.evaluate(eyeLocal,_LODBias);
|
||||
if (eval<0) return;
|
||||
|
||||
// push the culling mode.
|
||||
pushCurrentMask();
|
||||
|
||||
@@ -557,13 +565,13 @@ void CullVisitor::apply(Impostor& node)
|
||||
{
|
||||
// outwith the impostor distance threshold therefore simple
|
||||
// traverse the appropriate child of the LOD.
|
||||
handle_cull_callbacks_and_accept(node,node.getChild(eval));
|
||||
handle_cull_callbacks_and_traverse(node);
|
||||
}
|
||||
else if (_viewportStack.empty())
|
||||
{
|
||||
// need to use impostor but no valid viewport is defined to simply
|
||||
// default to using the LOD child as above.
|
||||
handle_cull_callbacks_and_accept(node,node.getChild(eval));
|
||||
handle_cull_callbacks_and_traverse(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -623,7 +631,7 @@ void CullVisitor::apply(Impostor& node)
|
||||
{
|
||||
// no impostor has been selected or created so default to
|
||||
// traversing the usual LOD selected child.
|
||||
handle_cull_callbacks_and_accept(node,node.getChild(eval));
|
||||
handle_cull_callbacks_and_traverse(node);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -645,7 +653,6 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
|
||||
const Matrix& matrix = getModelViewMatrix();
|
||||
const BoundingSphere& bs = node.getBound();
|
||||
osg::Vec3 eye_local = getEyeLocal();
|
||||
int eval = node.evaluate(eye_local,_LODBias);
|
||||
|
||||
if (!bs.valid())
|
||||
{
|
||||
@@ -777,7 +784,7 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
|
||||
{
|
||||
|
||||
// traversing the usual LOD selected child.
|
||||
handle_cull_callbacks_and_accept(node,node.getChild(eval));
|
||||
handle_cull_callbacks_and_traverse(node);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +96,7 @@ void InsertImpostorsVisitor::insertImpostors()
|
||||
|
||||
// standard LOD settings
|
||||
impostor->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;ci<lod->getNumChildren();++ci)
|
||||
{
|
||||
impostor->addChild(lod->getChild(ci));
|
||||
}
|
||||
|
||||
for(unsigned int ri=0;ri<lod->getNumRanges();++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);
|
||||
|
||||
@@ -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;i<lod->getNumRanges();++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<osg::LOD*>(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 && r<smallestRadius) smallestRadius = r;
|
||||
bb.expandBy((*lod_itr)->getCenter());
|
||||
}
|
||||
if (bb.radius()<1e-2)
|
||||
if (bb.radius()<smallestRadius*0.1f)
|
||||
{
|
||||
typedef std::pair<float,float> RangePair;
|
||||
typedef std::multimap<RangePair,osg::Node*> 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;i<lod->getNumRanges()-1;++i)
|
||||
for(unsigned int i=0;i<lod->getNumRanges();++i)
|
||||
{
|
||||
if (maxRange<lod->getRange(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);
|
||||
|
||||
Reference in New Issue
Block a user