bool Terrain::getHeight(osg::Node* patch, const SpatialReference* srs, double x, double y, double* out_hamsl, double* out_hae ) const { if ( !_graph.valid() && !patch ) return 0L; // convert to map coordinates: if ( srs && !srs->isHorizEquivalentTo(getSRS()) ) { srs->transform2D(x, y, getSRS(), x, y); } // trivially reject a point that lies outside the terrain: if ( !getProfile()->getExtent().contains(x, y) ) return 0L; const osg::EllipsoidModel* em = getSRS()->getEllipsoid(); double r = std::min( em->getRadiusEquator(), em->getRadiusPolar() ); // calculate the endpoints for an intersection test: osg::Vec3d start(x, y, r); osg::Vec3d end (x, y, -r); if ( isGeocentric() ) { const SpatialReference* ecef = getSRS()->getECEF(); getSRS()->transform(start, ecef, start); getSRS()->transform(end, ecef, end); } DPLineSegmentIntersector* lsi = new DPLineSegmentIntersector( start, end ); lsi->setIntersectionLimit(osgUtil::Intersector::LIMIT_NEAREST); osgUtil::IntersectionVisitor iv( lsi ); iv.setTraversalMask( ~_terrainOptions.secondaryTraversalMask().value() ); if ( patch ) patch->accept( iv ); else _graph->accept( iv ); osgUtil::LineSegmentIntersector::Intersections& results = lsi->getIntersections(); if ( !results.empty() ) { const osgUtil::LineSegmentIntersector::Intersection& firstHit = *results.begin(); osg::Vec3d hit = firstHit.getWorldIntersectPoint(); getSRS()->transformFromWorld(hit, hit, out_hae); if ( out_hamsl ) *out_hamsl = hit.z(); return true; } return false; }
void LinearLineOfSightNode::compute(osg::Node* node, bool backgroundThread) { if ( !getMapNode() ) return; if (!_start.isValid() || !_end.isValid() ) { return; } if (_start != _end) { const SpatialReference* mapSRS = getMapNode()->getMapSRS(); const Terrain* terrain = getMapNode()->getTerrain(); //Computes the LOS and redraws the scene if (!_start.transform(mapSRS).toWorld( _startWorld, terrain ) || !_end.transform(mapSRS).toWorld( _endWorld, terrain )) { return; } DPLineSegmentIntersector* lsi = new DPLineSegmentIntersector(_startWorld, _endWorld); osgUtil::IntersectionVisitor iv( lsi ); node->accept( iv ); DPLineSegmentIntersector::Intersections& hits = lsi->getIntersections(); if ( hits.size() > 0 ) { _hasLOS = false; _hitWorld = hits.begin()->getWorldIntersectPoint(); _hit.fromWorld( mapSRS, _hitWorld ); } else { _hasLOS = true; } } draw(backgroundThread); for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }
bool MouseCoordsTool::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { if (ea.getEventType() == ea.MOVE || ea.getEventType() == ea.DRAG) { osg::Vec3d world; if ( _mapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), world) ) { GeoPoint map; map.fromWorld( _mapNode->getMapSRS(), world ); for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i ) i->get()->set( map, aa.asView(), _mapNode ); } else { for( Callbacks::iterator i = _callbacks.begin(); i != _callbacks.end(); ++i ) i->get()->reset( aa.asView(), _mapNode ); } #if 1 // testing AGL, Dist to Point osg::Vec3d eye, center, up; aa.asView()->getCamera()->getViewMatrixAsLookAt(eye, center, up); DPLineSegmentIntersector* lsi = new DPLineSegmentIntersector(eye, osg::Vec3d(0,0,0)); osgUtil::IntersectionVisitor iv(lsi); lsi->setIntersectionLimit(lsi->LIMIT_NEAREST); //iv.setUserData( new Map() ); _mapNode->accept(iv); if ( !lsi->getIntersections().empty() ) { double agl = (eye - lsi->getFirstIntersection().getWorldIntersectPoint()).length(); double dtp = (eye - world).length(); //OE_NOTICE << "AGL = " << agl << "m; DPT = " << dtp << "m" << std::endl; Registry::instance()->startActivity("AGL", Stringify() << agl << " m"); Registry::instance()->startActivity("Range", Stringify() << dtp << " m"); } #endif } return false; }
void RadialLineOfSightNode::compute_fill(osg::Node* node) { if ( !getMapNode() ) return; GeoPoint centerMap; _center.transform( getMapNode()->getMapSRS(), centerMap ); centerMap.toWorld( _centerWorld, getMapNode()->getTerrain() ); bool isProjected = getMapNode()->getMapSRS()->isProjected(); osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : osg::Vec3d(_centerWorld); up.normalize(); //Get the "side" vector osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1); //Get the number of spokes double delta = osg::PI * 2.0 / (double)_numSpokes; osg::Geometry* geometry = new osg::Geometry; geometry->setUseVertexBufferObjects(true); osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve(_numSpokes * 2); geometry->setVertexArray( verts ); osg::Vec4Array* colors = new osg::Vec4Array(); colors->reserve( _numSpokes * 2 ); geometry->setColorArray( colors ); geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::ref_ptr<osgUtil::IntersectorGroup> ivGroup = new osgUtil::IntersectorGroup(); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { double angle = delta * (double)i; osg::Quat quat(angle, up ); osg::Vec3d spoke = quat * (side * _radius); osg::Vec3d end = _centerWorld + spoke; osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end ); ivGroup->addIntersector( dplsi.get() ); } osgUtil::IntersectionVisitor iv; iv.setIntersector( ivGroup.get() ); node->accept( iv ); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { //Get the current hit DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get()); DPLineSegmentIntersector::Intersections& hits = los->getIntersections(); osg::Vec3d currEnd = los->getEnd(); bool currHasLOS = hits.empty(); osg::Vec3d currHit = currHasLOS ? osg::Vec3d() : hits.begin()->getWorldIntersectPoint(); //Get the next hit unsigned int nextIndex = i + 1; if (nextIndex == _numSpokes) nextIndex = 0; DPLineSegmentIntersector* losNext = static_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[nextIndex].get()); DPLineSegmentIntersector::Intersections& hitsNext = losNext->getIntersections(); osg::Vec3d nextEnd = losNext->getEnd(); bool nextHasLOS = hitsNext.empty(); osg::Vec3d nextHit = nextHasLOS ? osg::Vec3d() : hitsNext.begin()->getWorldIntersectPoint(); if (currHasLOS && nextHasLOS) { //Both rays have LOS verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _goodColor ); } else if (!currHasLOS && !nextHasLOS) { //Both rays do NOT have LOS //Draw the "good triangle" verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _goodColor ); //Draw the two bad triangles verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } else if (!currHasLOS && nextHasLOS) { //Current does not have LOS but next does //Draw the good portion verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currHit - _centerWorld ); colors->push_back( _goodColor ); //Draw the bad portion verts->push_back( currHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } else if (currHasLOS && !nextHasLOS) { //Current does not have LOS but next does //Draw the good portion verts->push_back( _centerWorld - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( nextHit - _centerWorld ); colors->push_back( _goodColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _goodColor ); //Draw the bad portion verts->push_back( nextHit - _centerWorld ); colors->push_back( _badColor ); verts->push_back( nextEnd - _centerWorld ); colors->push_back( _badColor ); verts->push_back( currEnd - _centerWorld ); colors->push_back( _badColor ); } } geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, verts->size())); osg::Geode* geode = new osg::Geode(); geode->addDrawable( geometry ); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrixd::translate(_centerWorld)); mt->addChild(geode); //Remove all the children removeChildren(0, getNumChildren()); addChild( mt ); for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }
void RadialLineOfSightNode::compute_line(osg::Node* node) { if ( !getMapNode() ) return; GeoPoint centerMap; _center.transform( getMapNode()->getMapSRS(), centerMap ); centerMap.toWorld( _centerWorld, getMapNode()->getTerrain() ); bool isProjected = getMapNode()->getMapSRS()->isProjected(); osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : osg::Vec3d(_centerWorld); up.normalize(); //Get the "side" vector osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1); //Get the number of spokes double delta = osg::PI * 2.0 / (double)_numSpokes; osg::Geometry* geometry = new osg::Geometry; geometry->setUseVertexBufferObjects(true); osg::Vec3Array* verts = new osg::Vec3Array(); verts->reserve(_numSpokes * 5); geometry->setVertexArray( verts ); osg::Vec4Array* colors = new osg::Vec4Array(); colors->reserve( _numSpokes * 5 ); geometry->setColorArray( colors ); geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); osg::Vec3d previousEnd; osg::Vec3d firstEnd; osg::ref_ptr<osgUtil::IntersectorGroup> ivGroup = new osgUtil::IntersectorGroup(); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { double angle = delta * (double)i; osg::Quat quat(angle, up ); osg::Vec3d spoke = quat * (side * _radius); osg::Vec3d end = _centerWorld + spoke; osg::ref_ptr<DPLineSegmentIntersector> dplsi = new DPLineSegmentIntersector( _centerWorld, end ); ivGroup->addIntersector( dplsi.get() ); } osgUtil::IntersectionVisitor iv; iv.setIntersector( ivGroup.get() ); node->accept( iv ); for (unsigned int i = 0; i < (unsigned int)_numSpokes; i++) { DPLineSegmentIntersector* los = dynamic_cast<DPLineSegmentIntersector*>(ivGroup->getIntersectors()[i].get()); DPLineSegmentIntersector::Intersections& hits = los->getIntersections(); osg::Vec3d start = los->getStart(); osg::Vec3d end = los->getEnd(); osg::Vec3d hit; bool hasLOS = hits.empty(); if (!hasLOS) { hit = hits.begin()->getWorldIntersectPoint(); } if (hasLOS) { verts->push_back( start - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _goodColor ); colors->push_back( _goodColor ); } else { if (_displayMode == LineOfSight::MODE_SPLIT) { verts->push_back( start - _centerWorld ); verts->push_back( hit - _centerWorld ); colors->push_back( _goodColor ); colors->push_back( _goodColor ); verts->push_back( hit - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _badColor ); colors->push_back( _badColor ); } else if (_displayMode == LineOfSight::MODE_SINGLE) { verts->push_back( start - _centerWorld ); verts->push_back( end - _centerWorld ); colors->push_back( _badColor ); colors->push_back( _badColor ); } } if (i > 0) { verts->push_back( end - _centerWorld ); verts->push_back( previousEnd - _centerWorld ); colors->push_back( _outlineColor ); colors->push_back( _outlineColor ); } else { firstEnd = end; } previousEnd = end; } //Add the last outside of circle verts->push_back( firstEnd - _centerWorld ); verts->push_back( previousEnd - _centerWorld ); colors->push_back( osg::Vec4(1,1,1,1)); colors->push_back( osg::Vec4(1,1,1,1)); geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, verts->size())); osg::Geode* geode = new osg::Geode(); geode->addDrawable( geometry ); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::MatrixTransform* mt = new osg::MatrixTransform; mt->setMatrix(osg::Matrixd::translate(_centerWorld)); mt->addChild(geode); //Remove all the children removeChildren(0, getNumChildren()); addChild( mt ); for( LOSChangedCallbackList::iterator i = _changedCallbacks.begin(); i != _changedCallbacks.end(); i++ ) { i->get()->onChanged(); } }
void OcclusionCullingCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) { if (nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); static int frameNumber = -1; static double remainingTime = OcclusionCullingCallback::_maxFrameTime; static int numCompleted = 0; static int numSkipped = 0; if (nv->getFrameStamp()->getFrameNumber() != frameNumber) { if (numCompleted > 0 || numSkipped > 0) { OE_DEBUG << "OcclusionCullingCallback frame=" << frameNumber << " completed=" << numCompleted << " skipped=" << numSkipped << std::endl; } frameNumber = nv->getFrameStamp()->getFrameNumber(); numCompleted = 0; numSkipped = 0; remainingTime = OcclusionCullingCallback::_maxFrameTime; } osg::Vec3d eye = cv->getViewPoint(); if (_prevEye != eye || _prevWorld != _world) { if (remainingTime > 0.0) { double alt = 0.0; if ( _srs && !_srs->isProjected() ) { osgEarth::GeoPoint mapPoint; mapPoint.fromWorld( _srs.get(), eye ); alt = mapPoint.z(); } else { alt = eye.z(); } //Only do the intersection if we are close enough for it to matter if (alt <= _maxElevation && _node.valid()) { //Compute the intersection from the eye to the world point osg::Timer_t startTick = osg::Timer::instance()->tick(); osg::Vec3d start = eye; osg::Vec3d end = _world; DPLineSegmentIntersector* i = new DPLineSegmentIntersector( start, end ); i->setIntersectionLimit( osgUtil::Intersector::LIMIT_ONE ); osgUtil::IntersectionVisitor iv; iv.setIntersector( i ); _node->accept( iv ); osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections(); _visible = results.empty(); osg::Timer_t endTick = osg::Timer::instance()->tick(); double elapsed = osg::Timer::instance()->delta_m( startTick, endTick ); remainingTime -= elapsed; } else { _visible = true; } numCompleted++; _prevEye = eye; _prevWorld = _world; } else { numSkipped++; } } if (_visible) { traverse(node, nv ); } } else { traverse( node, nv ); } }
void OcclusionCullingCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) { if (nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); static int frameNumber = -1; static double remainingTime = OcclusionCullingCallback::_maxFrameTime; static int numCompleted = 0; static int numSkipped = 0; if (nv->getFrameStamp()->getFrameNumber() != frameNumber) { if (numCompleted > 0 || numSkipped > 0) { OE_DEBUG << "OcclusionCullingCallback frame=" << frameNumber << " completed=" << numCompleted << " skipped=" << numSkipped << std::endl; } frameNumber = nv->getFrameStamp()->getFrameNumber(); numCompleted = 0; numSkipped = 0; remainingTime = OcclusionCullingCallback::_maxFrameTime; } osg::Vec3d eye = cv->getViewPoint(); if (_prevEye != eye) { if (remainingTime > 0.0) { osg::ref_ptr<GeoTransform> geo; if ( _xform.lock(geo) ) { double alt = 0.0; osg::ref_ptr<Terrain> terrain = geo->getTerrain(); if ( terrain.valid() && !terrain->getSRS()->isProjected() ) { osgEarth::GeoPoint mapPoint; mapPoint.fromWorld( terrain->getSRS(), eye ); alt = mapPoint.z(); } else { alt = eye.z(); } //Only do the intersection if we are close enough for it to matter if (alt <= _maxAltitude && terrain.valid()) { //Compute the intersection from the eye to the world point osg::Timer_t startTick = osg::Timer::instance()->tick(); osg::Vec3d start = eye; osg::Vec3d end = osg::Vec3d(0,0,0) * geo->getMatrix(); // shorten the intersector by 1m to prevent flickering. osg::Vec3d vec = end-start; vec.normalize(); end -= vec*1.0; DPLineSegmentIntersector* i = new DPLineSegmentIntersector( start, end ); i->setIntersectionLimit( osgUtil::Intersector::LIMIT_NEAREST ); osgUtil::IntersectionVisitor iv; iv.setIntersector( i ); terrain->accept( iv ); osgUtil::LineSegmentIntersector::Intersections& results = i->getIntersections(); _visible = results.empty(); osg::Timer_t endTick = osg::Timer::instance()->tick(); double elapsed = osg::Timer::instance()->delta_m( startTick, endTick ); remainingTime -= elapsed; } else { _visible = true; } numCompleted++; _prevEye = eye; } } else { numSkipped++; // if we skipped some we need to request a redraw so the remianing ones get processed on the next frame. if ( cv->getCurrentCamera() && cv->getCurrentCamera()->getView() ) { osgGA::GUIActionAdapter* aa = dynamic_cast<osgGA::GUIActionAdapter*>(cv->getCurrentCamera()->getView()); if ( aa ) { aa->requestRedraw(); } } } } if (_visible) { traverse(node, nv ); } } else { traverse( node, nv ); } }
void intersectWithQuadTree(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable , const osg::Vec3d s, const osg::Vec3d e , const osg::Vec3d _start, const osg::Vec3d _end , QuadTree* quadTree , DPLineSegmentIntersector& intersector) { QuadTree::LineSegmentIntersections intersections; intersections.reserve(4); if (quadTree->intersect(s,e,intersections)) { // OSG_NOTICE<<"Got QuadTree intersections"<<std::endl; for(QuadTree::LineSegmentIntersections::iterator itr = intersections.begin(); itr != intersections.end(); ++itr) { QuadTree::LineSegmentIntersection& lsi = *(itr); // get ratio in s,e range double ratio = lsi.ratio; // remap ratio into _start, _end range double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length(); osgUtil::LineSegmentIntersector::Intersection hit; hit.ratio = remap_ratio; hit.matrix = iv.getModelMatrix(); hit.nodePath = iv.getNodePath(); hit.drawable = drawable; hit.primitiveIndex = lsi.primitiveIndex; hit.localIntersectionPoint = _start*(1.0-remap_ratio) + _end*remap_ratio; // OSG_NOTICE<<"QuadTree: ratio="<<hit.ratio<<" ("<<hit.localIntersectionPoint<<")"<<std::endl; hit.localIntersectionNormal = lsi.intersectionNormal; hit.indexList.reserve(3); hit.ratioList.reserve(3); if (lsi.r0!=0.0f) { hit.indexList.push_back(lsi.p0); hit.ratioList.push_back(lsi.r0); } if (lsi.r1!=0.0f) { hit.indexList.push_back(lsi.p1); hit.ratioList.push_back(lsi.r1); } if (lsi.r2!=0.0f) { hit.indexList.push_back(lsi.p2); hit.ratioList.push_back(lsi.r2); } intersector.insertIntersection(hit); } } }