void TileNode::merge(const TerrainTileModel* model, const RenderBindings& bindings) { bool newElevationData = false; const SamplerBinding& color = bindings[SamplerBinding::COLOR]; if (color.isActive()) { for(TerrainTileColorLayerModelVector::const_iterator i = model->colorLayers().begin(); i != model->colorLayers().end(); ++i) { TerrainTileImageLayerModel* model = dynamic_cast<TerrainTileImageLayerModel*>(i->get()); if (model) { if (model->getTexture()) { RenderingPass* pass = _renderModel.getPass(model->getImageLayer()->getUID()); if (!pass) { pass = &_renderModel.addPass(); pass->setLayer(model->getLayer()); // This is a new pass that just showed up at this LOD // Since it just arrived at this LOD, make the parent the same as the color. if (bindings[SamplerBinding::COLOR_PARENT].isActive()) { pass->samplers()[SamplerBinding::COLOR_PARENT]._texture = model->getTexture(); pass->samplers()[SamplerBinding::COLOR_PARENT]._matrix.makeIdentity(); } } pass->samplers()[SamplerBinding::COLOR]._texture = model->getTexture(); pass->samplers()[SamplerBinding::COLOR]._matrix = *model->getMatrix(); // Handle an RTT image layer: if (model->getImageLayer() && model->getImageLayer()->createTextureSupported()) { // Check the texture's userdata for a Node. If there is one there, // render it to the texture using the Tile Rasterizer service. // TODO: consider hanging on to this texture and not applying it to // the live tile until the RTT is complete. (Prevents unsightly flashing) GeoNode* rttNode = dynamic_cast<GeoNode*>(model->getTexture()->getUserData()); if (rttNode) { _context->getTileRasterizer()->push(rttNode->_node.get(), model->getTexture(), rttNode->_extent); } } } } else // non-image color layer (like splatting, e.g.) { TerrainTileColorLayerModel* model = i->get(); if (model && model->getLayer()) { RenderingPass* pass = _renderModel.getPass(model->getLayer()->getUID()); if (!pass) { pass = &_renderModel.addPass(); pass->setLayer(model->getLayer()); } } } } } // Elevation: const SamplerBinding& elevation = bindings[SamplerBinding::ELEVATION]; if (elevation.isActive() && model->elevationModel().valid() && model->elevationModel()->getTexture()) { osg::Texture* tex = model->elevationModel()->getTexture(); // always keep the elevation image around because we use it for bounding box computation: tex->setUnRefImageDataAfterApply(false); _renderModel._sharedSamplers[SamplerBinding::ELEVATION]._texture = tex; _renderModel._sharedSamplers[SamplerBinding::ELEVATION]._matrix.makeIdentity(); setElevationRaster(tex->getImage(0), osg::Matrixf::identity()); newElevationData = true; } // Normals: const SamplerBinding& normals = bindings[SamplerBinding::NORMAL]; if (normals.isActive() && model->normalModel().valid() && model->normalModel()->getTexture()) { osg::Texture* tex = model->normalModel()->getTexture(); // keep the normal map around because we might update it later in "ping" tex->setUnRefImageDataAfterApply(false); _renderModel._sharedSamplers[SamplerBinding::NORMAL]._texture = tex; _renderModel._sharedSamplers[SamplerBinding::NORMAL]._matrix.makeIdentity(); updateNormalMap(); } // Other Shared Layers: for (unsigned i = 0; i < model->sharedLayers().size(); ++i) { TerrainTileImageLayerModel* layerModel = model->sharedLayers()[i].get(); if (layerModel->getTexture()) { // locate the shared binding corresponding to this layer: UID uid = layerModel->getImageLayer()->getUID(); unsigned bindingIndex = INT_MAX; for(unsigned i=SamplerBinding::SHARED; i<bindings.size() && bindingIndex==INT_MAX; ++i) { if (bindings[i].isActive() && bindings[i].sourceUID().isSetTo(uid)) { bindingIndex = i; } } if (bindingIndex < INT_MAX) { osg::Texture* tex = layerModel->getTexture(); _renderModel._sharedSamplers[bindingIndex]._texture = tex; _renderModel._sharedSamplers[bindingIndex]._matrix.makeIdentity(); } } } // Patch Layers for (unsigned i = 0; i < model->patchLayers().size(); ++i) { TerrainTilePatchLayerModel* layerModel = model->patchLayers()[i].get(); } if (_childrenReady) { getSubTile(0)->refreshInheritedData(this, bindings); getSubTile(1)->refreshInheritedData(this, bindings); getSubTile(2)->refreshInheritedData(this, bindings); getSubTile(3)->refreshInheritedData(this, bindings); } if (newElevationData) { _context->getEngine()->getTerrain()->notifyTileAdded(getKey(), this); } }
// invoke runs in the background pager thread. void LoadTileData::invoke() { osg::ref_ptr<TileNode> tilenode; if ( _tilenode.lock(tilenode) ) { // Assemble all the components necessary to display this tile _model = _context->getEngine()->createTileModel( _context->getMapFrame(), tilenode->getTileKey(), 0L ); // progress // Prep the stateset for merging (and for GL pre-compile). if ( _model.valid() ) { const RenderBindings& bindings = _context->getRenderBindings(); osg::StateSet* stateSet = getStateSet(); // Insert all the color layers into a new MPTexture state attribute, // which exists to facilitate GL pre-compilation. if ( _model->colorLayers().size() > 0 ) { const SamplerBinding* colorBinding = SamplerBinding::findUsage(bindings, SamplerBinding::COLOR); if ( colorBinding ) { osg::ref_ptr<MPTexture> mptex = new MPTexture(); for(TerrainTileImageLayerModelVector::iterator i = _model->colorLayers().begin(); i != _model->colorLayers().end(); ++i) { TerrainTileImageLayerModel* layerModel = i->get(); if ( layerModel && layerModel->getTexture() ) { mptex->setLayer( layerModel->getImageLayer(), layerModel->getTexture(), layerModel->getOrder() ); } } if ( !mptex->getPasses().empty() ) { stateSet->setTextureAttribute( colorBinding->unit(), mptex ); } } } // Insert the elevation texture and an identity matrix: if ( _model->elevationModel().valid() && _model->elevationModel()->getTexture()) { const SamplerBinding* binding = SamplerBinding::findUsage(bindings, SamplerBinding::ELEVATION); if ( binding ) { stateSet->setTextureAttribute( binding->unit(), _model->elevationModel()->getTexture() ); stateSet->removeUniform(binding->matrixName()); stateSet->addUniform( _context->getOrCreateMatrixUniform( binding->matrixName(), osg::Matrixf::identity() ) ); } } // Insert the normal texture and an identity matrix: if ( _model->normalModel().valid() && _model->normalModel()->getTexture() ) { const SamplerBinding* binding = SamplerBinding::findUsage(bindings, SamplerBinding::NORMAL); if ( binding ) { stateSet->setTextureAttribute( binding->unit(), _model->normalModel()->getTexture() ); stateSet->removeUniform(binding->matrixName()); stateSet->addUniform( _context->getOrCreateMatrixUniform( binding->matrixName(), osg::Matrixf::identity() ) ); } } // Process any shared image layers, each of which should have its // own sampler binding point for(TerrainTileImageLayerModelVector::iterator i = _model->sharedLayers().begin(); i != _model->sharedLayers().end(); ++i) { TerrainTileImageLayerModel* layerModel = i->get(); if ( layerModel->getTexture() ) { const SamplerBinding* binding = SamplerBinding::findUID(bindings, layerModel->getImageLayer()->getUID()); if ( binding ) { stateSet->setTextureAttribute( binding->unit(), layerModel->getTexture() ); stateSet->removeUniform(binding->matrixName()); stateSet->addUniform( _context->getOrCreateMatrixUniform( binding->matrixName(), osg::Matrixf::identity() ) ); } } } } } }