コード例 #1
0
osg::Node* renderHeightField(const GeoHeightField& geoHF)
{
    osg::MatrixTransform* mt = new osg::MatrixTransform;

    GeoPoint centroid;
    geoHF.getExtent().getCentroid(centroid);

    osg::Matrix world2local, local2world;
    centroid.createWorldToLocal( world2local );
    local2world.invert( world2local );

    mt->setMatrix( local2world );

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

    osg::Vec3Array* verts = new osg::Vec3Array;
    geometry->setVertexArray( verts );

    for (unsigned int c = 0; c < geoHF.getHeightField()->getNumColumns() - 1; c++)
    {
        for (unsigned int r = 0; r < geoHF.getHeightField()->getNumRows() - 1; r++)
        {
            // Add two triangles 
            verts->push_back( getWorld( geoHF, c,     r    ) * world2local );
            verts->push_back( getWorld( geoHF, c + 1, r    ) * world2local );
            verts->push_back( getWorld( geoHF, c + 1, r + 1) * world2local );

            verts->push_back( getWorld( geoHF, c,     r    ) * world2local );
            verts->push_back( getWorld( geoHF, c + 1, r + 1) * world2local );
            verts->push_back( getWorld( geoHF, c,     r + 1) * world2local );
        }
    }
    geode->setCullingActive(false);
    mt->setCullingActive(false);

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

    osg::Vec4ubArray* colors = new osg::Vec4ubArray();
    colors->push_back(osg::Vec4ub(255,0,0,255));
    geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
    mt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    mt->getOrCreateStateSet()->setRenderBinDetails(99, "RenderBin");        

    return mt;
}
コード例 #2
0
ファイル: GLSkyNode.cpp プロジェクト: JD31/osgearth
void
GLSkyNode::onSetDateTime()
{
    if ( !getSunLight() )
        return;

    CelestialBody sun = getEphemeris()->getSunPosition(getDateTime());   

    // If the user set a projected-map reference point, assume we are using
    // a projected map and set the sun position acordingly.
    if (getReferencePoint().isValid())
    {
        // pull the ref point:
        GeoPoint refpoint = getReferencePoint();

        // convert to lat/long:
        GeoPoint refLatLong;
        osg::ref_ptr<const SpatialReference> wgs84 = SpatialReference::get("wgs84");
        refpoint.transform(wgs84.get(), refLatLong);

        // Matrix to convert the ECEF sun position to the local tangent plane
        // centered on our reference point:
        osg::Matrixd world2local;
        refLatLong.createWorldToLocal(world2local);

        // convert the sun position:
        osg::Vec3d sunPosLocal = sun.geocentric * world2local;
        sunPosLocal.normalize();

        getSunLight()->setPosition( osg::Vec4(sunPosLocal, 0.0) );
    }

    else if (_options.coordinateSystem() == SkyOptions::COORDSYS_ECEF)
    {
        osg::Vec3d pos = sun.geocentric;
        pos.normalize();
        _light->setPosition(osg::Vec4(pos, 0.0)); // directional light
    }

    else if (_options.coordinateSystem() == SkyOptions::COORDSYS_ECI)
    {
        osg::Vec3d pos = sun.eci;
        pos.normalize();
        _light->setPosition(osg::Vec4(pos, 0.0)); // directional light
    }
}
コード例 #3
0
ファイル: GLSkyNode.cpp プロジェクト: 2php/osgearth
void
GLSkyNode::onSetDateTime()
{
    if ( !getSunLight() || !_profile.valid() )
        return;

    const DateTime& dt = getDateTime();
    osg::Vec3d sunPosECEF = getEphemeris()->getSunPositionECEF( dt );

    if ( _profile->getSRS()->isGeographic() )
    {
        sunPosECEF.normalize();
        getSunLight()->setPosition( osg::Vec4(sunPosECEF, 0.0) );
    }
    else
    {
        // pull the ref point:
        GeoPoint refpoint = getReferencePoint();
        if ( !refpoint.isValid() )
        {
            // not found; use the center of the profile:
            _profile->getExtent().getCentroid(refpoint);
        }

        // convert to lat/long:
        GeoPoint refLatLong;
        refpoint.transform(_profile->getSRS()->getGeographicSRS(), refLatLong);

        // Matrix to convert the ECEF sun position to the local tangent plane
        // centered on our reference point:
        osg::Matrixd world2local;
        refLatLong.createWorldToLocal(world2local);

        // convert the sun position:
        osg::Vec3d sunPosLocal = sunPosECEF * world2local;
        sunPosLocal.normalize();

        getSunLight()->setPosition( osg::Vec4(sunPosLocal, 0.0) );
    }
}
コード例 #4
0
ファイル: GeometryPool.cpp プロジェクト: rhabacker/osgearth
osg::Geometry*
GeometryPool::createGeometry(const TileKey& tileKey,
                             const MapInfo& mapInfo,
                             MaskGenerator* maskSet) const
{    
    // Establish a local reference frame for the tile:
    osg::Vec3d centerWorld;
    GeoPoint centroid;
    tileKey.getExtent().getCentroid( centroid );
    centroid.toWorld( centerWorld );

    osg::Matrix world2local, local2world;
    centroid.createWorldToLocal( world2local );
    local2world.invert( world2local );

    // Attempt to calculate the number of verts in the surface geometry.
    bool createSkirt = _options.heightFieldSkirtRatio() > 0.0f;

    unsigned numVertsInSurface    = (_tileSize*_tileSize);
    unsigned numVertsInSkirt      = createSkirt ? _tileSize*4u - 4u : 0;
    unsigned numVerts             = numVertsInSurface + numVertsInSkirt;    
    unsigned numIndiciesInSurface = (_tileSize-1) * (_tileSize-1) * 6;
    unsigned numIncidesInSkirt    = getNumSkirtElements();
    
    GLenum mode = (_options.gpuTessellation() == true) ? GL_PATCHES : GL_TRIANGLES;

    // Pre-allocate enough space for all triangles.
    osg::DrawElements* primSet = new osg::DrawElementsUShort(mode);

    primSet->reserveElements(numIndiciesInSurface + numIncidesInSkirt);

    osg::BoundingSphere tileBound;

    // the geometry:
    osg::Geometry* geom = new osg::Geometry();
    geom->setUseVertexBufferObjects(true);
    geom->setUseDisplayList(false);

    geom->addPrimitiveSet( primSet );

    // the vertex locations:
    osg::Vec3Array* verts = new osg::Vec3Array();
    verts->reserve( numVerts );
    geom->setVertexArray( verts );

    // the surface normals (i.e. extrusion vectors)
    osg::Vec3Array* normals = new osg::Vec3Array();
    normals->reserve( numVerts );
    geom->setNormalArray( normals );
    geom->setNormalBinding( geom->BIND_PER_VERTEX );

    osg::Vec3Array* neighbors = 0L;
    if ( _options.morphTerrain() == true )
    {
        // neighbor positions (for morphing)
        neighbors = new osg::Vec3Array();
        neighbors->reserve( numVerts );
        geom->setTexCoordArray( 1, neighbors );
    }

    // tex coord is [0..1] across the tile. The 3rd dimension tracks whether the
    // vert is masked: 0=yes, 1=no
#ifdef SHARE_TEX_COORDS
    bool populateTexCoords = false;
    if ( !_sharedTexCoords.valid() )
    {
        _sharedTexCoords = new osg::Vec3Array();
        _sharedTexCoords->reserve( numVerts );
        populateTexCoords = true;
    }    
    osg::Vec3Array* texCoords = _sharedTexCoords.get();
#else
    bool populateTexCoords = true;
    osg::Vec3Array* texCoords = new osg::Vec3Array();
    texCoords->reserve( numVerts );
#endif

    geom->setTexCoordArray( 0, texCoords );
    
    float delta = 1.0/(_tileSize-1);
    osg::Vec3d tdelta(delta,0,0);
    tdelta.normalize();
    osg::Vec3d vZero(0,0,0);

    osg::ref_ptr<GeoLocator> locator = GeoLocator::createForKey( tileKey, mapInfo );

    for(unsigned row=0; row<_tileSize; ++row)
    {
        float ny = (float)row/(float)(_tileSize-1);
        for(unsigned col=0; col<_tileSize; ++col)
        {
            float nx = (float)col/(float)(_tileSize-1);

            osg::Vec3d model;
            locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model);
            osg::Vec3d modelLTP = model*world2local;
            verts->push_back( modelLTP );
            tileBound.expandBy( verts->back() );

            if ( populateTexCoords )
            {
                // if masked then set textCoord z-value to 0.0
                float marker = maskSet ? maskSet->getMarker(nx, ny) : MASK_MARKER_NORMAL;
                texCoords->push_back( osg::Vec3f(nx, ny, marker) );
            }

            osg::Vec3d modelPlusOne;
            locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne);
            osg::Vec3d normal = (modelPlusOne*world2local)-modelLTP;                
            normal.normalize();
            normals->push_back( normal );

            // neighbor:
            if ( neighbors )
            {
                osg::Vec3d modelNeighborLTP = (*verts)[verts->size() - getMorphNeighborIndexOffset(col, row, _tileSize)];
                neighbors->push_back(modelNeighborLTP);
            }
        }
    }

    // Now tessellate the surface.
    
    // TODO: do we really need this??
    bool swapOrientation = !locator->orientationOpenGL();

    for(unsigned j=0; j<_tileSize-1; ++j)
    {
        for(unsigned i=0; i<_tileSize-1; ++i)
        {
            int i00;
            int i01;
            if (swapOrientation)
            {
                i01 = j*_tileSize + i;
                i00 = i01+_tileSize;
            }
            else
            {
                i00 = j*_tileSize + i;
                i01 = i00+_tileSize;
            }

            int i10 = i00+1;
            int i11 = i01+1;

            // skip any triangles that have a discarded vertex:
            bool discard = maskSet && (
                maskSet->isMasked( (*texCoords)[i00] ) ||
                maskSet->isMasked( (*texCoords)[i11] )
            );

            if ( !discard )
            {
                discard = maskSet && maskSet->isMasked( (*texCoords)[i01] );
                if ( !discard )
                {
                    primSet->addElement(i01);
                    primSet->addElement(i00);
                    primSet->addElement(i11);
                }
            
                discard = maskSet && maskSet->isMasked( (*texCoords)[i10] );
                if ( !discard )
                {
                    primSet->addElement(i00);
                    primSet->addElement(i10);
                    primSet->addElement(i11);
                }
            }
        }
    }

    if ( createSkirt )
    {
        // SKIRTS:
        // calculate the skirt extrusion height
        double height = tileBound.radius() * _options.heightFieldSkirtRatio().get();
        
        unsigned skirtIndex = verts->size();

        // first, create all the skirt verts, normals, and texcoords.
        for(int c=0; c<(int)_tileSize-1; ++c)
            addSkirtDataForIndex( c, height ); //top

        for(int r=0; r<(int)_tileSize-1; ++r)
            addSkirtDataForIndex( r*_tileSize+(_tileSize-1), height ); //right
    
        for(int c=_tileSize-1; c>=0; --c)
            addSkirtDataForIndex( (_tileSize-1)*_tileSize+c, height ); //bottom

        for(int r=_tileSize-1; r>=0; --r)
            addSkirtDataForIndex( r*_tileSize, height ); //left
    
        // then create the elements indices:
        int i;
        for(i=skirtIndex; i<(int)verts->size()-2; i+=2)
            addSkirtTriangles( i, i+2 );

        addSkirtTriangles( i, skirtIndex );
    }

    // create mask geometry
    if (maskSet)
    {
        osg::ref_ptr<osg::DrawElementsUInt> maskPrim = maskSet->createMaskPrimitives(mapInfo, verts, texCoords, normals, neighbors);
        if (maskPrim)
            geom->addPrimitiveSet( maskPrim );
    }

    return geom;
}
コード例 #5
0
ファイル: GeometryPool.cpp プロジェクト: 0x6e/osgearth
osg::Geometry*
GeometryPool::createGeometry(const TileKey& tileKey,
                             const MapInfo& mapInfo,
                             MaskGenerator* maskSet) const
{    
    // Establish a local reference frame for the tile:
    osg::Vec3d centerWorld;
    GeoPoint centroid;
    tileKey.getExtent().getCentroid( centroid );
    centroid.toWorld( centerWorld );

    osg::Matrix world2local, local2world;
    centroid.createWorldToLocal( world2local );
    local2world.invert( world2local );

    // Attempt to calculate the number of verts in the surface geometry.
    bool createSkirt = _options.heightFieldSkirtRatio() > 0.0f;

    unsigned numVertsInSurface    = (_tileSize*_tileSize);
    unsigned numVertsInSkirt      = createSkirt ? _tileSize*4u - 4u : 0;
    unsigned numVerts             = numVertsInSurface + numVertsInSkirt;    
    unsigned numIndiciesInSurface = (_tileSize-1) * (_tileSize-1) * 6;
    unsigned numIncidesInSkirt    = createSkirt ? (_tileSize-1) * 4 * 6 : 0;
    
    GLenum mode = (_options.gpuTessellation() == true) ? GL_PATCHES : GL_TRIANGLES;

    // Pre-allocate enough space for all triangles.
    osg::DrawElements* primSet = new osg::DrawElementsUShort(mode);

    primSet->reserveElements(numIndiciesInSurface + numIncidesInSkirt);

    osg::BoundingSphere tileBound;

    // the geometry:
    osg::Geometry* geom = new osg::Geometry();
    geom->setUseVertexBufferObjects(true);
    geom->setUseDisplayList(false);

    geom->addPrimitiveSet( primSet );

    // the vertex locations:
    osg::Vec3Array* verts = new osg::Vec3Array();
    verts->reserve( numVerts );
    geom->setVertexArray( verts );

    // the surface normals (i.e. extrusion vectors)
    osg::Vec3Array* normals = new osg::Vec3Array();
    normals->reserve( numVerts );
    geom->setNormalArray( normals );
    geom->setNormalBinding( geom->BIND_PER_VERTEX );

    // neighbor positions (for morphing)
    osg::Vec3Array* neighbors = new osg::Vec3Array();
    neighbors->reserve( numVerts );
    geom->setTexCoordArray( 1, neighbors );

    // tex coord is [0..1] across the tile. The 3rd dimension tracks whether the
    // vert is masked: 0=yes, 1=no
#ifdef SHARE_TEX_COORDS
    bool populateTexCoords = false;
    if ( !_sharedTexCoords.valid() )
    {
        _sharedTexCoords = new osg::Vec3Array();
        _sharedTexCoords->reserve( numVerts );
        populateTexCoords = true;
    }    
    osg::Vec3Array* texCoords = _sharedTexCoords.get();
#else
    bool populateTexCoords = true;
    osg::Vec3Array* texCoords = new osg::Vec3Array();
    texCoords->reserve( numVerts );
#endif

    geom->setTexCoordArray( 0, texCoords );
    
    float delta = 1.0/(_tileSize-1);
    osg::Vec3d tdelta(delta,0,0);
    tdelta.normalize();
    osg::Vec3d vZero(0,0,0);

    osg::ref_ptr<GeoLocator> locator = GeoLocator::createForKey( tileKey, mapInfo );

    for(unsigned row=0; row<_tileSize; ++row)
    {
        float ny = (float)row/(float)(_tileSize-1);
        for(unsigned col=0; col<_tileSize; ++col)
        {
            float nx = (float)col/(float)(_tileSize-1);

            osg::Vec3d model;
            locator->unitToModel(osg::Vec3d(nx, ny, 0.0f), model);
            osg::Vec3d modelLTP = model*world2local;
            verts->push_back( modelLTP );
            tileBound.expandBy( verts->back() );

            // no masking in the geometry pool, so always write a z=1.0 -gw
            //bool masked = _maskSet.contains(nx, ny);     
            if ( populateTexCoords )
            {
                texCoords->push_back( osg::Vec3f(nx, ny, 1.0f) );
            }

            osg::Vec3d modelPlusOne;
            locator->unitToModel(osg::Vec3d(nx, ny, 1.0f), modelPlusOne);
            osg::Vec3d normal = (modelPlusOne*world2local)-modelLTP;                
            normal.normalize();
            normals->push_back( normal );

            // neighbor:
            osg::Vec3d modelNeighborLTP = (*verts)[verts->size() - getMorphNeighborIndexOffset(col, row, _tileSize)];
            neighbors->push_back(modelNeighborLTP);
        }
    }

    // Now tessellate the surface.
    
    // TODO: do we really need this??
    bool swapOrientation = !locator->orientationOpenGL();

    for(unsigned j=0; j<_tileSize-1; ++j)
    {
        for(unsigned i=0; i<_tileSize-1; ++i)
        {
            int i00;
            int i01;
            if (swapOrientation)
            {
                i01 = j*_tileSize + i;
                i00 = i01+_tileSize;
            }
            else
            {
                i00 = j*_tileSize + i;
                i01 = i00+_tileSize;
            }

            int i10 = i00+1;
            int i11 = i01+1;

            // If the quad does not intersect a mask, tessellate it; otherwise skip it
            // since the mask generator will take care of it.
            bool addTris = true;
            if ( maskSet )
            {
                addTris =
                    !maskSet->isMasked( (*texCoords)[i00] ) &&
                    !maskSet->isMasked( (*texCoords)[i01] ) &&
                    !maskSet->isMasked( (*texCoords)[i10] ) &&
                    !maskSet->isMasked( (*texCoords)[i11] ) &&
                    !maskSet->containedByQuadAtColRow( i, j, _tileSize );
            }

            if ( addTris )
            {
                primSet->addElement(i01);
                primSet->addElement(i00);
                primSet->addElement(i11);

                primSet->addElement(i00);
                primSet->addElement(i10);
                primSet->addElement(i11);
            }
        }
    }

    if ( createSkirt )
    {
        // SKIRTS:
        // calculate the skirt extrusion height
        double height = tileBound.radius() * _options.heightFieldSkirtRatio().get();
        
        unsigned skirtIndex = verts->size();

        // first, create all the skirt verts, normals, and texcoords.
        for(int c=0; c<(int)_tileSize-1; ++c)
            addSkirtDataForIndex( c, height ); //top

        for(int r=0; r<(int)_tileSize-1; ++r)
            addSkirtDataForIndex( r*_tileSize+(_tileSize-1), height ); //right
    
        for(int c=_tileSize-1; c>=0; --c)
            addSkirtDataForIndex( (_tileSize-1)*_tileSize+c, height ); //bottom

        for(int r=_tileSize-1; r>=0; --r)
            addSkirtDataForIndex( r*_tileSize, height ); //left
    
        // then create the elements indices:
        int i;
        for(i=skirtIndex; i<(int)verts->size()-2; i+=2)
            addSkirtTriangles( i, i+2 );

        addSkirtTriangles( i, skirtIndex );
    }

#if 0
    // if we're using patches, we must create a "proxy" primitive set that supports
    // PrimitiveFunctor et al (for intersections, bounds testing, etc.)
    if ( mode == GL_PATCHES )
    {
        osg::PrimitiveSet* patchesAsTriangles = osg::clone( primSet, osg::CopyOp::SHALLOW_COPY );
        patchesAsTriangles->setMode( GL_TRIANGLES );
        geom->setPatchTriangles( patchesAsTriangles );
    }
#endif

    return geom;
}
コード例 #6
0
ファイル: ModelSplatter.cpp プロジェクト: KNeal/osgearth
void
ModelSplatter::operator()(const TileKey& key, osg::Node* node)
{
    TerrainTileNode* tile = osgEarth::findTopMostNodeOfType<TerrainTileNode>(node);
    if ( !tile )
        return;

    if ( key.getLOD() >= _minLOD && _model.valid() )
    {
        // make sure the correct model is loaded
        establish();

        // elevation texture and matrix are required
        osg::Texture* elevationTex = tile->getElevationTexture();
        if ( !elevationTex )
        {
            //OE_WARN << LC << "No elevation texture for key " << key.str() << "\n";
            return;
        }

        osg::RefMatrix* elevationTexMat = tile->getElevationTextureMatrix();
        if ( !elevationTexMat )
        {
            //OE_WARN << LC << "No elevation texture matrix for key " << key.str() << "\n";
            return;
        }
        
        tile->addChild( _model.get() );

        osg::StateSet* ss = tile->getOrCreateStateSet();

        // first, a rotation vector to make trees point up.
        GeoPoint p;
        key.getExtent().getCentroid(p);
        osg::Vec3d up;
        p.createWorldUpVector(up);
        osg::Quat q;
        q.makeRotate(osg::Vec3d(0,0,1), up);
        osg::Matrixd zup = osg::Matrixd::rotate(q);

        // matrices to resolve the weird terrain localization into a usable LTP.
        osg::Matrix tile2world = tile->getMatrix();
        osg::Matrix world2ltp;
        p.createWorldToLocal(world2ltp);
        osg::Matrix local2ltp = tile2world * world2ltp;
        osg::Matrix ltp2local;
        ltp2local.invert(local2ltp);

        // after inverting the matrix, combine the ZUP (optimization)
        local2ltp.preMult( zup );

        ss->addUniform( new osg::Uniform("oe_trees_local2ltp", osg::Matrixf(local2ltp)) );
        ss->addUniform( new osg::Uniform("oe_trees_ltp2local", osg::Matrixf(ltp2local)) );

        // calculate the scatter area:
        float h = key.getExtent().height() * 111320.0f;
        float w = key.getExtent().width() * 111320.0f * cos(fabs(osg::DegreesToRadians(p.y())));
        ss->addUniform( new osg::Uniform("oe_trees_span", osg::Vec2f(w,h)) );
        
        ss->setTextureAttributeAndModes(2, tile->getElevationTexture(), 1);
        ss->addUniform( new osg::Uniform("oe_terrain_tex_matrix", osg::Matrixf(*elevationTexMat)) );        
    }
}