Example #1
0
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;
}
Example #2
0
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();
    }	
}
Example #3
0
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;
}
Example #4
0
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();
    }	
}
Example #5
0
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();
    }	
}
Example #6
0
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 );
    }
}
Example #7
0
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);
        }
    }
}