diff --git a/examples/osgsimulation/osgsimulation.cpp b/examples/osgsimulation/osgsimulation.cpp index 579df8318..96ae6a286 100644 --- a/examples/osgsimulation/osgsimulation.cpp +++ b/examples/osgsimulation/osgsimulation.cpp @@ -5,9 +5,12 @@ #include #include #include +#include #include +#include + #include #include @@ -18,6 +21,108 @@ // for the grid data.. #include "../osghangglide/terrain_coords.h" +osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime) +{ + // set up the animation path + osg::AnimationPath* animationPath = new osg::AnimationPath; + animationPath->setLoopMode(osg::AnimationPath::LOOP); + + int numSamples = 40; + float yaw = 0.0f; + float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f); + float roll = osg::inDegrees(30.0f); + + double time=0.0f; + double time_delta = looptime/(double)numSamples; + for(int i=0;iinsert(time,osg::AnimationPath::ControlPoint(position,rotation)); + + yaw += yaw_delta; + time += time_delta; + + } + return animationPath; +} + +osg::Node* createMovingModel(const osg::Vec3& center, float radius) +{ + float animationLength = 10.0f; + + osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength); + + osg::Group* model = new osg::Group; + + osg::Node* glider = osgDB::readNodeFile("glider.osg"); + if (glider) + { + const osg::BoundingSphere& bs = glider->getBound(); + + float size = radius/bs.radius()*0.3f; + osg::MatrixTransform* positioned = new osg::MatrixTransform; + positioned->setDataVariance(osg::Object::STATIC); + positioned->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(size,size,size)* + osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f)); + + positioned->addChild(glider); + + osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform; + xform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0)); + xform->addChild(positioned); + + model->addChild(xform); + } + + osg::Node* cessna = osgDB::readNodeFile("cessna.osg"); + if (cessna) + { + const osg::BoundingSphere& bs = cessna->getBound(); + + osgText::Text* text = new osgText::Text; + float size = radius/bs.radius()*0.3f; + + text->setPosition(bs.center()); + text->setText("Cessna"); + text->setAlignment(osgText::Text::CENTER_CENTER); + text->setAxisAlignment(osgText::Text::SCREEN); + text->setCharacterSize(40.0f); + text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(text); + + osg::LOD* lod = new osg::LOD; + lod->setRangeMode(osg::LOD::PIXEL_SIZE_ON_SCREEN); + lod->addChild(geode,0.0f,100.0f); + lod->addChild(cessna,100.0f,10000.0f); + + + osg::MatrixTransform* positioned = new osg::MatrixTransform; + positioned->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + positioned->setDataVariance(osg::Object::STATIC); + positioned->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(size,size,size)* + osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,1.0f)); + + //positioned->addChild(cessna); + positioned->addChild(lod); + + osg::MatrixTransform* xform = new osg::MatrixTransform; + xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0)); + xform->addChild(positioned); + + model->addChild(xform); + } + + return model; +} + + osg::Vec3 computeTerrainIntersection(osg::Node* subgraph,float x,float y) { osgUtil::IntersectVisitor iv; @@ -132,6 +237,12 @@ void build_world(osg::Group *root) // add the updater node to the scene graph root->addChild(psu); } + + + // create the moving models. + { + root->addChild(createMovingModel(osg::Vec3(500.0f,500.0f,500.0f),100.0f)); + } } diff --git a/include/osg/LOD b/include/osg/LOD index 918b4357b..fd86a4df8 100644 --- a/include/osg/LOD +++ b/include/osg/LOD @@ -55,14 +55,17 @@ class SG_EXPORT LOD : public Group typedef std::pair MinMaxPair; typedef std::vector RangeList; + /** Modes which control how the center of object should be determined when computed which child is active.*/ enum CenterMode { USE_BOUNDING_SPHERE_CENTER, USER_DEFINED_CENTER }; + /** Set how the center of object should be determined when computed which child is active.*/ void setCenterMode(CenterMode mode) { _centerMode=mode; } + /** Get how the center of object should be determined when computed which child is active.*/ CenterMode getCenterMode() const { return _centerMode; } /** Sets the object-space point which defines the center of the osg::LOD. @@ -72,6 +75,21 @@ class SG_EXPORT LOD : public Group /** return the LOD center point. */ inline const Vec3& getCenter() const { if (_centerMode==USER_DEFINED_CENTER) return _userDefinedCenter; else return getBound().center(); } + + /** Modes that control how the range values should be intepreted when computing which child is active.*/ + enum RangeMode + { + DISTANCE_FROM_EYE_POINT, + PIXEL_SIZE_ON_SCREEN + }; + + /** Set how the range values should be intepreted when computing which child is active.*/ + void setRangeMode(RangeMode mode) { _rangeMode = mode; } + + /** Get how the range values should be intepreted when computing which child is active.*/ + RangeMode getRangeMode() const { return _rangeMode; } + + /** 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); @@ -101,6 +119,7 @@ class SG_EXPORT LOD : public Group CenterMode _centerMode; Vec3 _userDefinedCenter; + RangeMode _rangeMode; RangeList _rangeList; }; diff --git a/src/osg/LOD.cpp b/src/osg/LOD.cpp index 506514322..0103fc1cc 100644 --- a/src/osg/LOD.cpp +++ b/src/osg/LOD.cpp @@ -11,6 +11,7 @@ * OpenSceneGraph Public License for more details. */ #include +#include #include @@ -39,13 +40,35 @@ void LOD::traverse(NodeVisitor& nv) break; case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): { - float distance = nv.getDistanceToEyePoint(getCenter(),true); + float required_range = 0; + if (_rangeMode==DISTANCE_FROM_EYE_POINT) + { + required_range = nv.getDistanceToEyePoint(getCenter(),true); + } + else + { + osg::CullStack* cullStack = dynamic_cast(&nv); + if (cullStack) + { + required_range = cullStack->pixelSize(getBound()); + } + else + { + // fallback to selecting the highest res tile by + // finding out the max range + for(unsigned int i=0;i<_rangeList.size();++i) + { + required_range = osg::minimum(required_range,_rangeList[i].first); + } + } + } + unsigned int numChildren = _children.size(); if (_rangeList.size()accept(nv); }