| 55 | | osg::Node* createMovingModel(const osg::Vec3& center, float radius) |
| | 55 | |
| | 56 | |
| | 57 | class IntersectionUpdateCallback : public osg::NodeCallback |
| | 58 | { |
| | 59 | virtual void operator()(osg::Node* /*node*/, osg::NodeVisitor* nv) |
| | 60 | { |
| | 61 | if (!root_ || !terrain_ || !ss_ || !intersectionGroup_) |
| | 62 | { |
| | 63 | osg::notify(osg::NOTICE)<<"IntersectionUpdateCallback not set up correctly."<<std::endl; |
| | 64 | return; |
| | 65 | } |
| | 66 | |
| | 67 | //traverse(node,nv); |
| | 68 | frameCount_++; |
| | 69 | if (frameCount_ > 200) |
| | 70 | { |
| | 71 | // first we need find the transformation matrix that takes |
| | 72 | // the terrain into the coordinate frame of the sphere segment. |
| | 73 | osg::Matrixd terrainLocalToWorld; |
| | 74 | osg::MatrixList terrain_worldMatrices = terrain_->getWorldMatrices(root_.get()); |
| | 75 | if (terrain_worldMatrices.empty()) terrainLocalToWorld.makeIdentity(); |
| | 76 | else if (terrain_worldMatrices.size()==1) terrainLocalToWorld = terrain_worldMatrices.front(); |
| | 77 | else |
| | 78 | { |
| | 79 | osg::notify(osg::NOTICE)<<"IntersectionUpdateCallback: warning cannot interestect with multiple terrain instances, just uses first one."<<std::endl; |
| | 80 | terrainLocalToWorld = terrain_worldMatrices.front(); |
| | 81 | } |
| | 82 | |
| | 83 | // sphere segment is easier as this callback is attached to the node, so the node visitor has the unique path to it already. |
| | 84 | osg::Matrixd ssWorldToLocal = osg::computeWorldToLocal(nv->getNodePath()); |
| | 85 | |
| | 86 | // now we can compute the terrain to ss transform |
| | 87 | osg::Matrixd possie = terrainLocalToWorld*ssWorldToLocal; |
| | 88 | |
| | 89 | osgSim::SphereSegment::LineList lines = ss_->computeIntersection(possie, terrain_.get()); |
| | 90 | if (!lines.empty()) |
| | 91 | { |
| | 92 | osg::notify(osg::NOTICE)<<"We've found intersections!!!!"<<std::endl; |
| | 93 | |
| | 94 | if (intersectionGroup_.valid()) |
| | 95 | { |
| | 96 | // now we need to place the intersections which are in the SphereSegmenet's coordinate frame into |
| | 97 | // to the final position. |
| | 98 | osg::MatrixTransform* mt = new osg::MatrixTransform; |
| | 99 | mt->setMatrix(osg::computeLocalToWorld(nv->getNodePath())); |
| | 100 | intersectionGroup_->addChild(mt); |
| | 101 | |
| | 102 | osg::Geode* geode = new osg::Geode; |
| | 103 | mt->addChild(geode); |
| | 104 | |
| | 105 | geode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF); |
| | 106 | |
| | 107 | for(osgSim::SphereSegment::LineList::iterator itr=lines.begin(); |
| | 108 | itr!=lines.end(); |
| | 109 | ++itr) |
| | 110 | { |
| | 111 | osg::Geometry* geom = new osg::Geometry; |
| | 112 | geode->addDrawable(geom); |
| | 113 | |
| | 114 | osg::Vec3Array* vertices = itr->get(); |
| | 115 | geom->setVertexArray(vertices); |
| | 116 | geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, vertices->getNumElements())); |
| | 117 | } |
| | 118 | } |
| | 119 | } |
| | 120 | else |
| | 121 | { |
| | 122 | osg::notify(osg::NOTICE)<<"No intersections found"<<std::endl; |
| | 123 | } |
| | 124 | |
| | 125 | |
| | 126 | frameCount_ = 0; |
| | 127 | } |
| | 128 | } |
| | 129 | public: |
| | 130 | osg::observer_ptr<osg::Group> root_; |
| | 131 | osg::observer_ptr<osg::Geode> terrain_; |
| | 132 | osg::observer_ptr<osgSim::SphereSegment> ss_; |
| | 133 | osg::observer_ptr<osg::Group> intersectionGroup_; |
| | 134 | unsigned frameCount_; |
| | 135 | }; |
| | 136 | |
| | 137 | |
| | 138 | osg::Node* createMovingModel(const osg::Vec3& center, float radius, osg::Geode * terrainGeode, osg::Group * root) |
| 81 | | |
| | 164 | model->addChild(xform); |
| | 165 | } |
| | 166 | if (1) |
| | 167 | { |
| | 168 | // The IntersectionUpdateCallback has to have a safe place to put all its generated geometry into, |
| | 169 | // and this group can't be in the parental chain of the callback otherwise we will end up invalidating |
| | 170 | // traversal iterators. |
| | 171 | osg::Group* intersectionGroup = new osg::Group; |
| | 172 | root->addChild(intersectionGroup); |
| | 173 | |
| | 174 | osg::PositionAttitudeTransform* xform = new osg::PositionAttitudeTransform; |
| | 175 | xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0,1.0)); |
| | 176 | |
| | 177 | osgSim::SphereSegment * ss = new osgSim::SphereSegment(osg::Vec3d(0.0,0.0,0.0), |
| | 178 | 700.0f, // radius |
| | 179 | osg::DegreesToRadians(135.0f), |
| | 180 | osg::DegreesToRadians(240.0f), |
| | 181 | osg::DegreesToRadians(-90.0f), |
| | 182 | osg::DegreesToRadians(-70.0f), |
| | 183 | 60); |
| | 184 | |
| | 185 | IntersectionUpdateCallback * iuc = new IntersectionUpdateCallback; |
| | 186 | iuc->frameCount_ = 0; |
| | 187 | iuc->root_ = root; |
| | 188 | iuc->terrain_ = terrainGeode; |
| | 189 | iuc->ss_ = ss; |
| | 190 | iuc->intersectionGroup_ = intersectionGroup; |
| | 191 | ss->setUpdateCallback(iuc); |
| | 192 | ss->setAllColors(osg::Vec4(1.0f,1.0f,1.0f,0.5f)); |
| | 193 | ss->setSideColor(osg::Vec4(0.5f,1.0f,1.0f,0.1f)); |
| | 194 | xform->addChild(ss); |
| 122 | | |
| 123 | | // add particle effects to cessna. |
| 124 | | { |
| 125 | | osg::PositionAttitudeTransform* positionEffects = new osg::PositionAttitudeTransform; |
| 126 | | positionEffects->setPosition(osg::Vec3(0.0f,0.0f,0.0f)); |
| 127 | | xform->addChild(positionEffects); |
| 128 | | |
| 129 | | osgParticle::ExplosionEffect* explosion = new osgParticle::ExplosionEffect; |
| 130 | | osgParticle::SmokeEffect* smoke = new osgParticle::SmokeEffect; |
| 131 | | osgParticle::FireEffect* fire = new osgParticle::FireEffect; |
| 132 | | |
| 133 | | positionEffects->addChild(explosion); |
| 134 | | positionEffects->addChild(smoke); |
| 135 | | positionEffects->addChild(fire); |
| 136 | | } |