osg 关于LOD

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;
}

原文地址:https://www.cnblogs.com/lizhengjin/p/1673055.html