class TestLOD : public Group
{
public :
TestLOD();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
TestLOD(const TestLOD&,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
META_Node(osg, TestLOD);
typedef osg::BoundingSphere::vec_type vec_type;
typedef osg::BoundingSphere::value_type value_type;
virtual void traverse(NodeVisitor& nv);
virtual bool addChild(Node *child);
virtual bool addChild(Node *child, float min, float max);
virtual bool removeChildren(unsigned int pos,unsigned int numChildrenToRemove=1);
typedef std::pair<float,float> MinMaxPair;
typedef std::vector<MinMaxPair> RangeList;
/** Modes which control how the center of object should be determined when computing which child is active.*/
enum CenterMode
{
USE_BOUNDING_SPHERE_CENTER,
USER_DEFINED_CENTER
};
/** Set how the center of object should be determined when computing which child is active.*/
void setCenterMode(CenterMode mode) { _centerMode=mode; }
/** Get how the center of object should be determined when computing which child is active.*/
CenterMode getCenterMode() const { return _centerMode; }
/** Sets the object-space point which defines the center of the osg::TestTestLOD.
center is affected by any transforms in the hierarchy above the osg::TestTestLOD.*/
inline void setCenter(const vec_type& center) { _centerMode=USER_DEFINED_CENTER; _userDefinedCenter = center; }
/** return the TestTestLOD center point. */
inline const vec_type& getCenter() const { if (_centerMode==USER_DEFINED_CENTER) return _userDefinedCenter; else return getBound().center(); }
/** Set the object-space reference radius of the volume enclosed by the TestTestLOD.
* Used to determine the bounding sphere of the TestTestLOD in the absence of any children.*/
inline void setRadius(value_type radius) { _radius = radius; }
/** Get the object-space radius of the volume enclosed by the TestTestLOD.*/
inline value_type getRadius() const { return _radius; }
/** Modes that control how the range values should be interpreted when computing which child is active.*/
enum RangeMode
{
DISTANCE_FROM_EYE_POINT,
PIXEL_SIZE_ON_SCREEN
};
/** Set how the range values should be interpreted when computing which child is active.*/
void setRangeMode(RangeMode mode) { _rangeMode = mode; }
/** Get how the range values should be interpreted when computing which child is active.*/
RangeMode getRangeMode() const { return _rangeMode; }
/** Sets the min and max visible ranges of range of specific child.
Values are floating point distance specified in local objects coordinates.*/
void setRange(unsigned int childNo, float min,float max);
/** 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; }
/** returns the number of ranges currently set.
* An TestTestLOD which has been fully set up will have getNumChildren()==getNumRanges(). */
inline unsigned int getNumRanges() const { return _rangeList.size(); }
/** set the list of MinMax ranges for each child.*/
inline void setRangeList(const RangeList& rangeList) { _rangeList=rangeList; }
/** return the list of MinMax ranges for each child.*/
inline const RangeList& getRangeList() const { return _rangeList; }
virtual BoundingSphere computeBound() const;
protected :
virtual ~TestLOD() {}
CenterMode _centerMode;
vec_type _userDefinedCenter;
value_type _radius;
RangeMode _rangeMode;
RangeList _rangeList;
};
//--------------------------------------------------------------------
TestLOD::TestLOD():
_centerMode(USE_BOUNDING_SPHERE_CENTER),
_radius(-1.0f),
_rangeMode(DISTANCE_FROM_EYE_POINT)
{
}
TestLOD::TestLOD(const TestLOD& TestLOD,const CopyOp& copyop):
Group(TestLOD,copyop),
_centerMode(TestLOD._centerMode),
_userDefinedCenter(TestLOD._userDefinedCenter),
_radius(TestLOD._radius),
_rangeMode(TestLOD._rangeMode),
_rangeList(TestLOD._rangeList)
{
}
void TestLOD::traverse(NodeVisitor& nv)
{
float required_range = 0;
if (_rangeMode==DISTANCE_FROM_EYE_POINT)
{
required_range = nv.getDistanceToViewPoint(getCenter(),true);//getCenter()得到包围盒的节点或者自定义节点
}
unsigned int numChildren = _children.size();
if (_rangeList.size()<numChildren) numChildren=_rangeList.size();
for(unsigned int i=0;i<numChildren;++i)
{
if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second)
{
_children[i]->accept(nv);//使用访问者渲染节点
}
}
}
BoundingSphere TestLOD::computeBound() const
{
if (_centerMode==USER_DEFINED_CENTER && _radius>=0.0f)
{
return BoundingSphere(_userDefinedCenter,_radius);
}
else
{
return Group::computeBound();
}
}
bool TestLOD::addChild( Node *child )
{
if (Group::addChild(child))
{
if (_children.size()>_rangeList.size())
{
float maxRange = !_rangeList.empty() ? _rangeList.back().second : 0.0f;
_rangeList.resize(_children.size(),MinMaxPair(maxRange,maxRange));
}
return true;
}
return false;
}
bool TestLOD::addChild(Node *child, float min, float max)
{
if (Group::addChild(child))
{
if (_children.size()>_rangeList.size()) _rangeList.resize(_children.size(),MinMaxPair(min,min));
_rangeList[_children.size()-1].first = min;
_rangeList[_children.size()-1].second = max;//把某个节点的最大值和最小值存入
return true;
}
return false;
}
bool TestLOD::removeChildren( unsigned int pos,unsigned int numChildrenToRemove)
{
if (pos<_rangeList.size()) _rangeList.erase(_rangeList.begin()+pos, osg::minimum(_rangeList.begin()+(pos+numChildrenToRemove), _rangeList.end()) );
return Group::removeChildren(pos,numChildrenToRemove);
}
void TestLOD::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;
}