void
TerrainTileModelFactory::addPatchLayers(TerrainTileModel* model,
                                        const Map* map,
                                        const TileKey&    key,
                                        const CreateTileModelFilter& filter,
                                        ProgressCallback* progress)
{
    OE_START_TIMER(fetch_patch_layers);

    PatchLayerVector patchLayers;
    map->getLayers(patchLayers);

    for(PatchLayerVector::const_iterator i = patchLayers.begin();
        i != patchLayers.end();
        ++i )
    {

        PatchLayer* layer = i->get();

        if (!filter.accept(layer))
            continue;

        if (!layer->getEnabled())
            continue;

        if (layer->getAcceptCallback() == 0L || layer->getAcceptCallback()->acceptKey(key))
        {
            PatchLayer::TileData* tileData = layer->createTileData(key);
            if (tileData)
            {
                TerrainTilePatchLayerModel* patchModel = new TerrainTilePatchLayerModel();
                patchModel->setPatchLayer(layer);
                patchModel->setTileData(tileData);

                model->patchLayers().push_back(patchModel);
            }
        }
    }

    if (progress)
        progress->stats()["fetch_patches_time"] += OE_STOP_TIMER(fetch_patch_layers);
}
Esempio n. 2
0
void
TerrainCuller::apply(osg::Node& node)
{
    // push the node's state.
    osg::StateSet* node_state = node.getStateSet();

    TileNode* tileNode = dynamic_cast<TileNode*>(&node);
    if (tileNode)
    {
        _currentTileNode = tileNode;
        _currentTileDrawCommands = 0u;
        
        if (!_terrain.patchLayers().empty())
        {
            // todo: check for patch/virtual
            const RenderBindings&  bindings    = _context->getRenderBindings();
            TileRenderModel& renderModel = _currentTileNode->renderModel();

            bool pushedMatrix = false;
            
            for (PatchLayerVector::const_iterator i = _terrain.patchLayers().begin(); i != _terrain.patchLayers().end(); ++i)
            {
                PatchLayer* layer = i->get();
                if (layer->getAcceptCallback() == 0L ||
                    layer->getAcceptCallback()->acceptKey(_currentTileNode->getKey()))
                {
                    // Push this tile's matrix if we haven't already done so:
                    if (!pushedMatrix)
                    {
                        SurfaceNode* surface = tileNode->getSurfaceNode();

                        // push the surface matrix:
                        osg::Matrix mvm = *getModelViewMatrix();
                        surface->computeLocalToWorldMatrix(mvm, this);
                        pushModelViewMatrix(createOrReuseMatrix(mvm), surface->getReferenceFrame());
                        pushedMatrix = true;
                    }

                    // Add the draw command:
                    DrawTileCommand* cmd = addDrawCommand(layer->getUID(), &renderModel, 0L, tileNode);
                    if (cmd)
                    {
                        cmd->_drawPatch = true;
                        cmd->_drawCallback = layer->getDrawCallback();
                        ++_currentTileDrawCommands;
                    }
                }
            }

            if (pushedMatrix)
            {
                popModelViewMatrix();
            }
        }
    }

    else
    {
        SurfaceNode* surface = dynamic_cast<SurfaceNode*>(&node);
        if (surface)
        {
            TileRenderModel& renderModel = _currentTileNode->renderModel();

            // push the surface matrix:
            osg::Matrix mvm = *getModelViewMatrix();
            surface->computeLocalToWorldMatrix(mvm, this);
            pushModelViewMatrix(createOrReuseMatrix(mvm), surface->getReferenceFrame());
                        
            // First go through any legit rendering pass data in the Tile and
            // and add a DrawCommand for each.
            for (unsigned p = 0; p < renderModel._passes.size(); ++p)
            {
                const RenderingPass& pass = renderModel._passes[p];
                
                if (pass._layer.valid() && pass._layer->getRenderType() == Layer::RENDERTYPE_TILE)
                {
                    if (addDrawCommand(pass._sourceUID, &renderModel, &pass, _currentTileNode))
                    {
                        ++_currentTileDrawCommands;
                    }
                }
            }

            // Next, add a DrawCommand for each tile layer not represented in the TerrainTileModel
            // as a rendering pass.
            for (LayerVector::const_iterator i = _terrain.tileLayers().begin(); i != _terrain.tileLayers().end(); ++i)
            {
                Layer* layer = i->get();
                if (addDrawCommand(layer->getUID(), &renderModel, 0L, _currentTileNode))
                {
                    ++_currentTileDrawCommands;
                }
            }

            // If the culler added no draw commands for this tile... do something!
            if (_currentTileDrawCommands == 0)
            {
                //OE_INFO << LC << "Adding blank render.\n";
                addDrawCommand(-1, &renderModel, 0L, _currentTileNode);
            }

            popModelViewMatrix();

            _terrain._drawState->_bs.expandBy(surface->getBound());
            _terrain._drawState->_box.expandBy(_terrain._drawState->_bs);
        }
    }

    traverse(node);
}
Esempio n. 3
0
void
TerrainCuller::apply(osg::Node& node)
{
    // push the node's state.
    osg::StateSet* node_state = node.getStateSet();

    TileNode* tileNode = dynamic_cast<TileNode*>(&node);
    if (tileNode)
    {
        _currentTileNode = tileNode;

        // reset the pointer to the first DrawTileCommand. We keep track of this so
        // we can set it's "order" member to zero at the end, so the rendering engine
        // knows to blend it with the terrain geometry color.
        _firstTileDrawCommandForTile = 0L;

        //_currentTileDrawCommands = 0u;
        
        if (!_terrain.patchLayers().empty())
        {
            // todo: check for patch/virtual
            const RenderBindings& bindings = _context->getRenderBindings();
            TileRenderModel& renderModel = _currentTileNode->renderModel();

            bool pushedMatrix = false;
            
            for (PatchLayerVector::const_iterator i = _terrain.patchLayers().begin(); i != _terrain.patchLayers().end(); ++i)
            {
                PatchLayer* layer = i->get();
                if (layer->getAcceptCallback() == 0L ||
                    layer->getAcceptCallback()->acceptKey(_currentTileNode->getKey()))
                {
                    // Push this tile's matrix if we haven't already done so:
                    if (!pushedMatrix)
                    {
                        SurfaceNode* surface = tileNode->getSurfaceNode();

                        // push the surface matrix:
                        osg::Matrix mvm = *getModelViewMatrix();
                        surface->computeLocalToWorldMatrix(mvm, this);
                        pushModelViewMatrix(createOrReuseMatrix(mvm), surface->getReferenceFrame());
                        pushedMatrix = true;
                    }

                    // Add the draw command:
                    DrawTileCommand* cmd = addDrawCommand(layer->getUID(), &renderModel, 0L, tileNode);
                    if (cmd)
                    {
                        cmd->_drawPatch = true;
                        cmd->_drawCallback = layer->getDrawCallback();
                    }
                }
            }

            if (pushedMatrix)
            {
                popModelViewMatrix();
            }
        }
    }

    else
    {
        SurfaceNode* surface = dynamic_cast<SurfaceNode*>(&node);
        if (surface)
        {
            TileRenderModel& renderModel = _currentTileNode->renderModel();

            // push the surface matrix:
            osg::Matrix mvm = *getModelViewMatrix();
            surface->computeLocalToWorldMatrix(mvm, this);
            pushModelViewMatrix(createOrReuseMatrix(mvm), surface->getReferenceFrame());

            int order = 0;

            // First go through any legit rendering pass data in the Tile and
            // and add a DrawCommand for each.
            for (unsigned p = 0; p < renderModel._passes.size(); ++p)
            {
                const RenderingPass& pass = renderModel._passes[p];
                DrawTileCommand* cmd = addDrawCommand(pass.sourceUID(), &renderModel, &pass, _currentTileNode);
                if (cmd)
                {
                    if (_firstTileDrawCommandForTile == 0L)
                    {
                        _firstTileDrawCommandForTile = cmd;
                    }
                    else if (cmd->_order < _firstTileDrawCommandForTile->_order)
                    {
                        //_firstTileDrawCommandForTile->_order = 1;
                        _firstTileDrawCommandForTile = cmd;
                    }
                }
            }

            // If the culler added no draw commands for this tile... we still need
            // to draw something or else there will be a hole! So draw a blank tile.
            // UID = -1 is the special UID code for a blank.
            if (_firstTileDrawCommandForTile == 0L)
            {
                //OE_INFO << LC << "Adding blank render for tile " << _currentTileNode->getKey().str() << std::endl;
                DrawTileCommand* cmd = addDrawCommand(-1, &renderModel, 0L, _currentTileNode);
                if (cmd)
                    cmd->_order = 0;
            }

            // Set the layer order of the first draw command for this tile to zero,
            // to support proper terrain blending.
            if (_firstTileDrawCommandForTile)
            {
                _firstTileDrawCommandForTile->_order = 0;
            }
                
            // pop the matrix from the cull stack
            popModelViewMatrix();

            // update our bounds
            _terrain._drawState->_bs.expandBy(surface->getBound());
            _terrain._drawState->_box.expandBy(_terrain._drawState->_bs);
        }
    }

    // Handle any CullCallbacks and traverse.
    osg::Callback* cullCallback = node.getCullCallback();
    if (cullCallback) cullCallback->run(&node, this);
    else traverse(node);
}