コード例 #1
0
SurfaceNode::SurfaceNode(const TileKey&        tilekey,
                         const MapInfo&        mapinfo,
                         const RenderBindings& bindings,
                         TileDrawable*         drawable)
{
    _tileKey = tilekey;

    _drawable = drawable;

    _surfaceGeode = new osg::Geode();
    _surfaceGeode->addDrawable( drawable );

    // Create the final node.
    addChild( _surfaceGeode.get() );

    // Establish a local reference frame for the tile:
    GeoPoint centroid;
    tilekey.getExtent().getCentroid(centroid);

    osg::Matrix local2world;
    centroid.createLocalToWorld( local2world );
    setMatrix( local2world );

    _matrix = new osg::RefMatrix( local2world );

    // Initialize the cached bounding box.
    setElevationRaster( 0L, osg::Matrixf::identity() );
}
コード例 #2
0
void
PolyhedralLineOfSightNode::recalculateExtent()
{
    // get a local2world matrix for the map position:
    GeoPoint absMapPos = _mapPosition;
    absMapPos.makeAbsolute( getMapNode()->getTerrain() );
    osg::Matrix local2world;
    absMapPos.createLocalToWorld( local2world );

    // local offsets (east and north)
    osg::Vec3d x( _distance.as(Units::METERS), 0.0, 0.0 );
    osg::Vec3d y( 0.0, _distance.as(Units::METERS), 0.0 );

    // convert these to map coords:
    GeoPoint easting, northing;
    easting.fromWorld( getMapNode()->getMapSRS(), x * local2world );
    northing.fromWorld( getMapNode()->getMapSRS(), y * local2world );

    // calculate the offsets:
    double d_easting = easting.x() - absMapPos.x();
    double d_northing = northing.y() - absMapPos.y();

    // update the extent.
    _extent = GeoExtent(
        getMapNode()->getMapSRS(),
        absMapPos.x() - d_easting, absMapPos.y() - d_northing,
        absMapPos.x() + d_easting, absMapPos.y() + d_northing );

    OE_INFO << LC << "Cached extent = " << _extent.toString() << std::endl;
}
コード例 #3
0
SurfaceNode::SurfaceNode(const TileKey&        tilekey,
                         const MapInfo&        mapinfo,
                         const RenderBindings& bindings,
                         TileDrawable*         drawable)
: _debugNodeVisible(false)
{
    _tileKey = tilekey;

    _drawable = drawable;

    _surfaceGeode = new osg::Geode();
    _surfaceGeode->addDrawable( drawable );
    
    // Create the final node.
    addChild( _surfaceGeode.get() );
        
    // Establish a local reference frame for the tile:
    osg::Vec3d centerWorld;
    GeoPoint centroid;
    tilekey.getExtent().getCentroid(centroid);
    centroid.toWorld(centerWorld);
    osg::Matrix local2world;
    centroid.createLocalToWorld( local2world );
    setMatrix( local2world );

    _worldCorners.resize(8);
    _childrenCorners.resize(4);
    for(size_t i = 0; i < _childrenCorners.size(); ++i)
    {
        _childrenCorners[i].resize(8);
    }
    // Initialize the cached bounding box.
    setElevationExtrema(osg::Vec2f(0, 0));
}
コード例 #4
0
osg::BoundingSphere
LocalGeometryNode::computeBound() const
{
    osg::BoundingSphere bs = AnnotationNode::computeBound();
    
    // NOTE: this is the same code found in Feature.cpp. Consolidate?

    _boundingPT.clear();

    // add planes for the four sides of the BS. Normals point inwards.
    _boundingPT.add( osg::Plane(osg::Vec3d( 1, 0,0), osg::Vec3d(-bs.radius(),0,0)) );
    _boundingPT.add( osg::Plane(osg::Vec3d(-1, 0,0), osg::Vec3d( bs.radius(),0,0)) );
    _boundingPT.add( osg::Plane(osg::Vec3d( 0, 1,0), osg::Vec3d(0, -bs.radius(),0)) );
    _boundingPT.add( osg::Plane(osg::Vec3d( 0,-1,0), osg::Vec3d(0,  bs.radius(),0)) );

    const SpatialReference* srs = getPosition().getSRS();
    if ( srs )
    {
        // for a projected feature, we're done. For a geocentric one, transform the polytope
        // into world (ECEF) space.
        if ( srs->isGeographic() && !srs->isPlateCarre() )
        {
            const osg::EllipsoidModel* e = srs->getEllipsoid();

            // add a bottom cap, unless the bounds are sufficiently large.
            double minRad = std::min(e->getRadiusPolar(), e->getRadiusEquator());
            double maxRad = std::max(e->getRadiusPolar(), e->getRadiusEquator());
            double zeroOffset = bs.center().length();
            if ( zeroOffset > minRad * 0.1 )
            {
                _boundingPT.add( osg::Plane(osg::Vec3d(0,0,1), osg::Vec3d(0,0,-maxRad+zeroOffset)) );
            }
        }

        // transform the clipping planes ito ECEF space
        GeoPoint refPoint;
        refPoint.fromWorld( srs, bs.center() );

        osg::Matrix local2world;
        refPoint.createLocalToWorld( local2world );

        _boundingPT.transform( local2world );
    }

    return bs;
}
コード例 #5
0
ファイル: Draggers.cpp プロジェクト: chuckshaw/osgearth
void Dragger::updateTransform(osg::Node* patch)
{
    osg::Matrixd matrix;
    GeoPoint mapPoint;
    _mapNode->getMap()->toMapPoint( _position, mapPoint );
    //Get the height
    if (_position.altitudeMode() == ALTMODE_RELATIVE)
    {
        double hamsl;
        if (_mapNode->getTerrain()->getHeight(mapPoint.x(), mapPoint.y(), &hamsl, 0L, patch))
        {
            mapPoint.z() += hamsl;
        }
        mapPoint.altitudeMode() = ALTMODE_ABSOLUTE;
    }            
    mapPoint.createLocalToWorld( matrix );
    setMatrix( matrix );
}
コード例 #6
0
ファイル: Feature.cpp プロジェクト: DavidLeehome/osgearth
bool
Feature::getWorldBoundingPolytope(const SpatialReference* srs,
                                  osg::Polytope&          out_polytope) const
{
    osg::BoundingSphered bs;
    if ( getWorldBound(srs, bs) && bs.valid() )
    {
        out_polytope.clear();

        // add planes for the four sides of the BS. Normals point inwards.
        out_polytope.add( osg::Plane(osg::Vec3d( 1, 0,0), osg::Vec3d(-bs.radius(),0,0)) );
        out_polytope.add( osg::Plane(osg::Vec3d(-1, 0,0), osg::Vec3d( bs.radius(),0,0)) );
        out_polytope.add( osg::Plane(osg::Vec3d( 0, 1,0), osg::Vec3d(0, -bs.radius(),0)) );
        out_polytope.add( osg::Plane(osg::Vec3d( 0,-1,0), osg::Vec3d(0,  bs.radius(),0)) );

        // for a projected feature, we're done. For a geocentric one, transform the polytope
        // into world (ECEF) space.
        if ( srs->isGeographic() && !srs->isPlateCarre() )
        {
            const osg::EllipsoidModel* e = srs->getEllipsoid();

            // add a bottom cap, unless the bounds are sufficiently large.
            double minRad = std::min(e->getRadiusPolar(), e->getRadiusEquator());
            double maxRad = std::max(e->getRadiusPolar(), e->getRadiusEquator());
            double zeroOffset = bs.center().length();
            if ( zeroOffset > minRad * 0.1 )
            {
                out_polytope.add( osg::Plane(osg::Vec3d(0,0,1), osg::Vec3d(0,0,-maxRad+zeroOffset)) );
            }
        }

        // transform the clipping planes ito ECEF space
        GeoPoint refPoint;
        refPoint.fromWorld( srs, bs.center() );

        osg::Matrix local2world;
        refPoint.createLocalToWorld( local2world );

        out_polytope.transform( local2world );

        return true;
    }
    return false;
}
コード例 #7
0
void
PolyhedralLineOfSightNode::updateSamples()
{
    if ( _geode->getNumDrawables() == 0 )
        rebuildGeometry();

    osg::Geometry* geom  = _geode->getDrawable(0)->asGeometry();
    osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() );

    double distance = _distance.as(Units::METERS);

    // get the world coords and a l2w transform for the origin:
    osg::Vec3d  originWorld;
    osg::Matrix local2world, world2local;

    Terrain* t = getMapNode()->getTerrain();
    GeoPoint origin = getPosition();
    origin.makeAbsolute( t );
    origin.toWorld( originWorld, t );
    origin.createLocalToWorld( local2world );
    world2local.invert( local2world );

    // set up an intersector:
    osgUtil::LineSegmentIntersector* lsi = new osgUtil::LineSegmentIntersector( originWorld, originWorld );
    osgUtil::IntersectionVisitor iv( lsi );

    // intersect the verts (skip the origin point) with the map node.
    for( osg::Vec3Array::iterator v = verts->begin()+1; v != verts->end(); ++v )
    {
        osg::Vec3d unit = *v;
        unit.normalize();
        unit *= distance;

        osg::Vec3d world = unit * local2world;

        if ( osg::equivalent(unit.length(), 0.0) )
        {
            OE_WARN << "problem." << std::endl;
        }

        lsi->reset();
        lsi->setStart( originWorld );
        lsi->setEnd( world );

        OE_DEBUG << LC << "Ray: " <<
            originWorld.x() << "," << originWorld.y() << "," << originWorld.z() << " => "
            << world.x() << "," << world.y() << "," << world.z()
            << std::endl;


        getMapNode()->getTerrain()->accept( iv );

        osgUtil::LineSegmentIntersector::Intersections& hits = lsi->getIntersections();
        if ( !hits.empty() )
        {
            const osgUtil::LineSegmentIntersector::Intersection& hit = *hits.begin();
            osg::Vec3d newV = hit.getWorldIntersectPoint() * world2local;
            if ( newV.length() > 1.0 )
                *v = newV;
            else
                *v = unit;
        }
        else
        {
            *v = unit;
        }

        //OE_NOTICE << "Radial point = " << v->x() << ", " << v->y() << ", " << v->z() << std::endl;
    }

    verts->dirty();
    geom->dirtyBound();
}
コード例 #8
0
bool
BillboardExtension::connect(MapNode* mapNode)
{
    if ( !mapNode )
    {
        OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl;
        return false;
    }

    OE_INFO << LC << "Connecting to MapNode.\n";

    if ( !_options.imageURI().isSet() )
    {
        OE_WARN << LC << "Illegal: image URI is required" << std::endl;
        return false;
    }

    if ( !_options.featureOptions().isSet() )
    {
        OE_WARN << LC << "Illegal: feature source is required" << std::endl;
        return false;
    }
    
    _features = FeatureSourceFactory::create( _options.featureOptions().value() );
    if ( !_features.valid() )
    {
        OE_WARN << LC << "Illegal: no valid feature source provided" << std::endl;
        return false;
    }

    //if ( _features->getGeometryType() != osgEarth::Symbology::Geometry::TYPE_POINTSET )
    //{
    //    OE_WARN << LC << "Illegal: only points currently supported" << std::endl;
    //    return false;
    //}

    _features->initialize( _dbOptions );

    osg::Vec3dArray* verts;
    if ( _features->getFeatureProfile() )
    {
        verts = new osg::Vec3dArray();
        
        OE_NOTICE << "Reading features...\n";
        osg::ref_ptr<FeatureCursor> cursor = _features->createFeatureCursor();
        while ( cursor.valid() && cursor->hasMore() )
        {
            Feature* f = cursor->nextFeature();
            if ( f && f->getGeometry() )
            {
                if ( f->getGeometry()->getComponentType() == Geometry::TYPE_POLYGON )
                {
                    FilterContext cx;
                    cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) );

                    ScatterFilter scatter;
                    scatter.setDensity( _options.density().get() );
                    scatter.setRandom( true );
                    FeatureList featureList;
                    featureList.push_back(f);
                    scatter.push( featureList, cx );
                }

                // Init a filter to tranform feature in desired SRS 
                if (!mapNode->getMapSRS()->isEquivalentTo(_features->getFeatureProfile()->getSRS()))
                {
                    FilterContext cx;
                    cx.setProfile( new FeatureProfile(_features->getFeatureProfile()->getExtent()) );

                    TransformFilter xform( mapNode->getMapSRS() );
                    FeatureList featureList;
                    featureList.push_back(f);
                    cx = xform.push(featureList, cx);
                }

                GeometryIterator iter(f->getGeometry());
                while(iter.hasMore()) {
                    const Geometry* geom = iter.next();
                    osg::ref_ptr<osg::Vec3dArray> fVerts = geom->createVec3dArray();
                    verts->insert(verts->end(), fVerts->begin(), fVerts->end());
                }
            }
        }
    }
    else
    {
        OE_WARN << LC << "Illegal: feature source has no SRS" << std::endl;
        return false;
    }


    if ( verts && verts->size() > 0 )
    {
        OE_NOTICE << LC << "Read " << verts->size() << " points.\n";

        //localize all the verts
        GeoPoint centroid;
        _features->getFeatureProfile()->getExtent().getCentroid(centroid);
        centroid = centroid.transform(mapNode->getMapSRS());

        OE_NOTICE << "Centroid = " << centroid.x() << ", " << centroid.y() << "\n";

        osg::Matrixd l2w, w2l;
        centroid.createLocalToWorld(l2w);
        w2l.invert(l2w);

        osg::MatrixTransform* mt = new osg::MatrixTransform;
        mt->setMatrix(l2w);

        OE_NOTICE << "Clamping elevations...\n";
        osgEarth::ElevationQuery eq(mapNode->getMap());
        eq.setFallBackOnNoData( true );
        eq.getElevations(verts->asVector(), mapNode->getMapSRS(), true, 0.005);
        
        OE_NOTICE << "Building geometry...\n";
        osg::Vec3Array* normals = new osg::Vec3Array(verts->size());

        osg::Vec4Array* colors = new osg::Vec4Array(verts->size());
        Random rng;

        for (int i=0; i < verts->size(); i++)
        {
            GeoPoint vert(mapNode->getMapSRS(), (*verts)[i], osgEarth::ALTMODE_ABSOLUTE);

            osg::Vec3d world;
            vert.toWorld(world);
            (*verts)[i] = world * w2l;

            osg::Vec3 normal = world;
            normal.normalize();
            (*normals)[i] = osg::Matrix::transform3x3(normal, w2l);

            double n = rng.next();
            (*colors)[i].set( n, n, n, 1 );
        }

        //create geom and primitive sets
        osg::Geometry* geometry = new osg::Geometry();
        geometry->setVertexArray( verts );
        geometry->setNormalArray( normals );
        geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
        geometry->setColorArray(colors);
        geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );

        geometry->addPrimitiveSet( new osg::DrawArrays( GL_POINTS, 0, verts->size() ) );

        //create image and texture to render to
        osg::Texture2D* tex = new osg::Texture2D(_options.imageURI()->getImage(_dbOptions));
        tex->setResizeNonPowerOfTwoHint(false);
        tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
        tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
        tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
        tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);

        geometry->setName("BillboardPoints");

        osg::Geode* geode = new osg::Geode;
        geode->addDrawable(geometry);

        //osg::ref_ptr<StateSetCache> cache = new StateSetCache();
        //Registry::shaderGenerator().run(geode, cache.get());

        //set the texture related uniforms
        osg::StateSet* geode_ss = geode->getOrCreateStateSet();
        geode_ss->setTextureAttributeAndModes( 2, tex, 1 );
        geode_ss->getOrCreateUniform("billboard_tex", osg::Uniform::SAMPLER_2D)->set( 2 );

        float bbWidth = (float)tex->getImage()->s() / 2.0f;
        float bbHeight = (float)tex->getImage()->t();
        float aspect = (float)tex->getImage()->s() / (float)tex->getImage()->t();
        if (_options.height().isSet())
        {
            bbHeight = _options.height().get();
            if (!_options.width().isSet())
            {
                bbWidth = bbHeight * aspect / 2.0f;
            }
        }
        if (_options.width().isSet())
        {
            bbWidth = _options.width().get() / 2.0f;
            if (!_options.height().isSet())
            {
                bbHeight = _options.width().get() / aspect;
            }
        }

        geode_ss->getOrCreateUniform("billboard_width", osg::Uniform::FLOAT)->set( bbWidth );
        geode_ss->getOrCreateUniform("billboard_height", osg::Uniform::FLOAT)->set( bbHeight );
        geode_ss->setMode(GL_BLEND, osg::StateAttribute::ON);

        //for now just using an osg::Program
        //TODO: need to add GeometryShader support to the shader comp setup
        VirtualProgram* vp = VirtualProgram::getOrCreate(geode_ss);
        vp->setName( "osgEarth Billboard Extension" );

        ShaderPackage shaders;
        shaders.add( "Billboard geometry shader", billboardGeomShader );
        shaders.add( "Billboard fragment shader", billboardFragShader );
        shaders.loadAll( vp );

        geode_ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
        geode->setCullingActive(false);

        mt->addChild(geode);
        mapNode->getModelLayerGroup()->addChild(mt);

        return true;
    }

    return false;
}
コード例 #9
0
ファイル: GeoTransform.cpp プロジェクト: 469447793/osgearth
bool
GeoTransform::setPosition(const GeoPoint& position)
{
    if ( !position.isValid() )
        return false;

    _position = position;

    // relative Z or reprojection require a terrain:
    osg::ref_ptr<Terrain> terrain;
    _terrain.lock(terrain);

    // relative Z requires a terrain:
    if (position.altitudeMode() == ALTMODE_RELATIVE && !terrain.valid())
    {
        OE_TEST << LC << "setPosition failed condition 1\n";
        return false;
    }

    GeoPoint p;

    // transform into terrain SRS if neccesary:
    if (terrain.valid() && !terrain->getSRS()->isEquivalentTo(position.getSRS()))
        p = position.transform(terrain->getSRS());
    else
        p = position;

    // bail if the transformation failed:
    if ( !p.isValid() )
    {
        OE_TEST << LC << "setPosition failed condition 2\n";
        return false;
    }

    // convert to absolute height:
    if ( !p.makeAbsolute(_terrain.get()) )
    {
        OE_TEST << LC << "setPosition failed condition 3\n";
        return false;
    }

    // assemble the matrix:
    osg::Matrixd local2world;
    p.createLocalToWorld( local2world );
    this->setMatrix( local2world );

    // install auto-recompute?
    if (_autoRecompute &&
        _position.altitudeMode() == ALTMODE_RELATIVE &&
        !_autoRecomputeReady)
    {
        // by using the adapter, there's no need to remove
        // the callback then this object destructs.
        terrain->addTerrainCallback(
           new TerrainCallbackAdapter<GeoTransform>(this) );

        _autoRecomputeReady = true;
    }

    return true;
}