void TileNode::create(const TileKey& key, EngineContext* context) { _key = key; // Create mask records osg::ref_ptr<MaskGenerator> masks = context ? new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame()) : 0L; // Get a shared geometry from the pool that corresponds to this tile key: osg::ref_ptr<osg::Geometry> geom; context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get()); // Create the drawable for the terrain surface: TileDrawable* surfaceDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get(), context->getGeometryPool()->getNumSkirtElements() ); surfaceDrawable->setDrawAsPatches(false); // Create the node to house the tile drawable: _surface = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), surfaceDrawable ); //_surface->setNodeMask( OSGEARTH_MASK_TERRAIN_SURFACE ); // Slot it into the proper render bin: //osg::StateSet* surfaceSS = _surface->getOrCreateStateSet(); //surfaceSS->setRenderBinDetails(0, "oe.SurfaceBin"); //surfaceSS->setNestRenderBins(false); // Create a drawable for land cover geometry. // Land cover will be rendered as patch data instead of triangles. TileDrawable* patchDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get(), context->getGeometryPool()->getNumSkirtElements() ); patchDrawable->setDrawAsPatches(true); // And a node to house that as well: _landCover = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), patchDrawable ); //_landCover->setNodeMask( OSGEARTH_MASK_TERRAIN_LAND_COVER ); // PPP: Better way to do this rather than here? // Can't do it at RexTerrainEngineNode level, because the SurfaceNode is not valid yet if (context->getSelectionInfo().initialized()==false) { static Threading::Mutex s_selInfoMutex; Threading::ScopedMutexLock lock(s_selInfoMutex); if ( context->getSelectionInfo().initialized()==false) { SelectionInfo& selectionInfo = const_cast<SelectionInfo&>(context->getSelectionInfo()); unsigned uiFirstLOD = *(context->_options.firstLOD()); unsigned uiMaxLod = std::min( context->_options.maxLOD().get(), 19u ); // beyond LOD 19 or 20, morphing starts to lose precision. unsigned uiTileSize = *(context->_options.tileSize()); selectionInfo.initialize(uiFirstLOD, uiMaxLod, uiTileSize, getVisibilityRangeHint(context)); //uiFirstLOD)); } } // initialize all the per-tile uniforms the shaders will need: createTileUniforms(); updateTileUniforms(context->getSelectionInfo()); // Set up a data container for multipass layer rendering: _mptex = new MPTexture(); surfaceDrawable->setMPTexture( _mptex.get() ); // need to recompute the bounds after adding payload: dirtyBound(); // signal the tile to start loading data: setDirty( true ); // register me. context->liveTiles()->add( this ); }
void TileNode::create(const TileKey& key, TileNode* parent, EngineContext* context) { if (!context) return; _context = context; _key = key; // Mask generator creates geometry from masking boundaries when they exist. osg::ref_ptr<MaskGenerator> masks = new MaskGenerator( key, context->getOptions().tileSize().get(), context->getMap()); MapInfo mapInfo(context->getMap()); // Get a shared geometry from the pool that corresponds to this tile key: osg::ref_ptr<SharedGeometry> geom; context->getGeometryPool()->getPooledGeometry( key, mapInfo, context->getOptions().tileSize().get(), masks.get(), geom); // If we donget an empty, that most likely means the tile was completely // contained by a masking boundary. Mark as empty and we are done. if (geom->empty()) { OE_DEBUG << LC << "Tile " << _key.str() << " is empty.\n"; _empty = true; return; } // Create the drawable for the terrain surface: TileDrawable* surfaceDrawable = new TileDrawable( key, geom.get(), context->getOptions().tileSize().get() ); // Give the tile Drawable access to the render model so it can properly // calculate its bounding box and sphere. surfaceDrawable->setModifyBBoxCallback(context->getModifyBBoxCallback()); // Create the node to house the tile drawable: _surface = new SurfaceNode( key, mapInfo, context->getRenderBindings(), surfaceDrawable ); // create a data load request for this new tile: _loadRequest = new LoadTileData( this, context ); _loadRequest->setName( _key.str() ); _loadRequest->setTileKey( _key ); // whether the stitch together normal maps for adjacent tiles. _stitchNormalMap = context->_options.normalizeEdges() == true; // Encode the tile key in a uniform. Note! The X and Y components are presented // modulo 2^16 form so they don't overrun single-precision space. unsigned tw, th; _key.getProfile()->getNumTiles(_key.getLOD(), tw, th); const double m = 65536; //pow(2.0, 16.0); double x = (double)_key.getTileX(); double y = (double)(th - _key.getTileY()-1); _tileKeyValue.set( (float)fmod(x, m), (float)fmod(y, m), (float)_key.getLOD(), -1.0f); // initialize all the per-tile uniforms the shaders will need: float start = (float)context->getSelectionInfo().visParameters(_key.getLOD())._fMorphStart; float end = (float)context->getSelectionInfo().visParameters(_key.getLOD())._fMorphEnd; float one_by_end_minus_start = end - start; one_by_end_minus_start = 1.0f/one_by_end_minus_start; _morphConstants.set( end * one_by_end_minus_start, one_by_end_minus_start ); // Initialize the data model by copying the parent's rendering data // and scale/biasing the matrices. if (parent) { unsigned quadrant = getKey().getQuadrant(); const RenderBindings& bindings = context->getRenderBindings(); bool setElevation = false; for (unsigned p = 0; p < parent->_renderModel._passes.size(); ++p) { const RenderingPass& parentPass = parent->_renderModel._passes[p]; // Copy the parent pass: _renderModel._passes.push_back(parentPass); RenderingPass& myPass = _renderModel._passes.back(); // Scale/bias each matrix for this key quadrant. Samplers& samplers = myPass.samplers(); for (unsigned s = 0; s < samplers.size(); ++s) { samplers[s]._matrix.preMult(scaleBias[quadrant]); } // Are we using image blending? If so, initialize the color_parent // to the color texture. if (bindings[SamplerBinding::COLOR_PARENT].isActive()) { samplers[SamplerBinding::COLOR_PARENT] = samplers[SamplerBinding::COLOR]; } } // Copy the parent's shared samplers and scale+bias each matrix to the new quadrant: _renderModel._sharedSamplers = parent->_renderModel._sharedSamplers; for (unsigned s = 0; s<_renderModel._sharedSamplers.size(); ++s) { Sampler& sampler = _renderModel._sharedSamplers[s]; sampler._matrix.preMult(scaleBias[quadrant]); } // Use the elevation sampler to initialize the elevation raster // (used for primitive functors, intersection, etc.) if (!setElevation && bindings[SamplerBinding::ELEVATION].isActive()) { const Sampler& elevation = _renderModel._sharedSamplers[SamplerBinding::ELEVATION]; if (elevation._texture.valid()) { setElevationRaster(elevation._texture->getImage(0), elevation._matrix); setElevation = true; } } } // need to recompute the bounds after adding payload: dirtyBound(); // signal the tile to start loading data: setDirty( true ); // register me. context->liveTiles()->add( this ); // tell the world. OE_DEBUG << LC << "notify (create) key " << getKey().str() << std::endl; context->getEngine()->getTerrain()->notifyTileAdded(getKey(), this); }
void TileNode::create(const TileKey& key, EngineContext* context) { if (!context) return; _key = key; // Create mask records osg::ref_ptr<MaskGenerator> masks = new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame()); // Get a shared geometry from the pool that corresponds to this tile key: osg::ref_ptr<osg::Geometry> geom; context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get()); // Create the drawable for the terrain surface: TileDrawable* surfaceDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get(), context->getGeometryPool()->getNumSkirtElements() ); surfaceDrawable->setDrawAsPatches(false); // Create the node to house the tile drawable: _surface = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), surfaceDrawable ); // Create a drawable for "patch" geometry, which is rendered as GL patches, not triangles. // Patch geometry can be used to place land cover or render other tile-specific data. TileDrawable* patchDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get(), context->getGeometryPool()->getNumSkirtElements() ); patchDrawable->setDrawAsPatches(true); // And a node to house that as well: _patch = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), patchDrawable ); // initialize all the per-tile uniforms the shaders will need: createPayloadStateSet(context); updateTileUniforms(context->getSelectionInfo()); // Set up a data container for multipass layer rendering: _mptex = new MPTexture(); surfaceDrawable->setMPTexture( _mptex.get() ); // need to recompute the bounds after adding payload: dirtyBound(); // signal the tile to start loading data: setDirty( true ); // register me. context->liveTiles()->add( this ); }
void TileNode::create(const TileKey& key, EngineContext* context) { _key = key; // Get a shared geometry from the pool that corresponds to this tile key: osg::ref_ptr<osg::Geometry> geom; context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom); // Create the drawable for the terrain surface: TileDrawable* surfaceDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get() ); surfaceDrawable->setDrawAsPatches(false); // Create the node to house the tile drawable: _surface = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), surfaceDrawable ); // Slot it into the proper render bin: osg::StateSet* surfaceSS = _surface->getOrCreateStateSet(); surfaceSS->setRenderBinDetails(0, "oe.SurfaceBin"); surfaceSS->setNestRenderBins(false); // Create a drawable for land cover geometry. // Land cover will be rendered as patch data instead of triangles. TileDrawable* patchDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get() ); patchDrawable->setDrawAsPatches(true); // And a node to house that as well: _landCover = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), patchDrawable ); // PPP: Better way to do this rather than here? // Can't do it at RexTerrainEngineNode level, because the SurfaceNode is not valid yet if (context->getSelectionInfo().initialized()==false) { SelectionInfo& selectionInfo = const_cast<SelectionInfo&>(context->getSelectionInfo()); unsigned uiFirstLOD = *(context->_options.firstLOD()); unsigned uiMaxLod = *(context->_options.maxLOD()); unsigned uiTileSize = *(context->_options.tileSize()); selectionInfo.initialize(uiFirstLOD, uiMaxLod, uiTileSize, getVisibilityRangeHint(uiFirstLOD)); } // initialize all the per-tile uniforms the shaders will need: createTileUniforms(); updateTileUniforms(context->getSelectionInfo()); // Set up a data container for multipass layer rendering: _mptex = new MPTexture(); surfaceDrawable->setMPTexture( _mptex.get() ); // need to recompute the bounds after adding payload: dirtyBound(); // signal the tile to start loading data: setDirty( true ); // register me. context->liveTiles()->add( this ); }
void TileNode::create(const TileKey& key, EngineContext* context) { if (!context) return; _key = key; // Create mask records osg::ref_ptr<MaskGenerator> masks = new MaskGenerator(key, context->getOptions().tileSize().get(), context->getMapFrame()); // Get a shared geometry from the pool that corresponds to this tile key: osg::ref_ptr<osg::Geometry> geom; context->getGeometryPool()->getPooledGeometry(key, context->getMapFrame().getMapInfo(), geom, masks.get()); // Create the drawable for the terrain surface: TileDrawable* surfaceDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get(), context->getGeometryPool()->getNumSkirtElements() ); surfaceDrawable->setDrawAsPatches(false); // Create the node to house the tile drawable: _surface = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), surfaceDrawable ); // Create a drawable for "patch" geometry, which is rendered as GL patches, not triangles. // Patch geometry can be used to place land cover or render other tile-specific data. TileDrawable* patchDrawable = new TileDrawable( key, context->getRenderBindings(), geom.get(), context->getOptions().tileSize().get(), context->getGeometryPool()->getNumSkirtElements() ); patchDrawable->setDrawAsPatches(true); // And a node to house that as well: _patch = new SurfaceNode( key, context->getMapFrame().getMapInfo(), context->getRenderBindings(), patchDrawable ); // PPP: Better way to do this rather than here? // Can't do it at RexTerrainEngineNode level, because the SurfaceNode is not valid yet if (context->getSelectionInfo().initialized()==false) { static Threading::Mutex s_selInfoMutex; Threading::ScopedMutexLock lock(s_selInfoMutex); if ( context->getSelectionInfo().initialized()==false) { SelectionInfo& selectionInfo = const_cast<SelectionInfo&>(context->getSelectionInfo()); unsigned uiFirstLOD = *(context->_options.firstLOD()); unsigned uiMaxLod = std::min( context->_options.maxLOD().get(), 19u ); // beyond LOD 19 or 20, morphing starts to lose precision. unsigned uiTileSize = *(context->_options.tileSize()); selectionInfo.initialize(uiFirstLOD, uiMaxLod, uiTileSize, getVisibilityRangeHint(context)); } } // initialize all the per-tile uniforms the shaders will need: createPayloadStateSet(context); updateTileUniforms(context->getSelectionInfo()); // Set up a data container for multipass layer rendering: _mptex = new MPTexture(); surfaceDrawable->setMPTexture( _mptex.get() ); // need to recompute the bounds after adding payload: dirtyBound(); // signal the tile to start loading data: setDirty( true ); // register me. context->liveTiles()->add( this ); }