tilemapper.cpp

来自「最新osg包」· C++ 代码 · 共 485 行

CPP
485
字号
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield  * * This library is open source and may be redistributed and/or modified under   * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or  * (at your option) any later version.  The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * OpenSceneGraph Public License for more details.*/#include "TileMapper.h"//#include "TXPTileNode.h"#include "TXPPagedLOD.h"#include <osg/Material>using namespace txp;float TileMapper::getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const{    if (withLODScale)	return (pos-getEyeLocal()).length()*getLODScale();    else	return (pos-getEyeLocal()).length();}inline TileMapper::value_type distance(const osg::Vec3& coord,const osg::Matrix& matrix){    //std::cout << "distance("<<coord<<", "<<matrix<<")"<<std::endl;    return -((TileMapper::value_type)coord[0]*(TileMapper::value_type)matrix(0,2)+	     (TileMapper::value_type)coord[1]*(TileMapper::value_type)matrix(1,2)+	     (TileMapper::value_type)coord[2]*(TileMapper::value_type)matrix(2,2)+	     matrix(3,2));}float TileMapper::getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScale) const{    const osg::Matrix& matrix = *_modelviewStack.back();    float dist = distance(pos,matrix);        if (withLODScale)	return dist*getLODScale();    else	return dist;}void TileMapper::apply(osg::Node& node){    if (node.getName()=="TileContent")     {        _containsGeode = true;        return;    }    if (isCulled(node))	return;    // push the culling mode.    pushCurrentMask();    traverse(node);    // pop the culling mode.    popCurrentMask();}void TileMapper::apply(osg::Group& node){    if (node.getName()=="TileContent")     {        _containsGeode = true;        return;    }    if (isCulled(node))	return;    // push the culling mode.    pushCurrentMask();    TileIdentifier* tid = dynamic_cast<TileIdentifier*>(node.getUserData());        if (tid)    {        _tileStack.push_back(TileStack::value_type(*tid,&node));        _containsGeode = false;    }    traverse(node);    if (tid)    {        if (_containsGeode)        {            insertTile(*tid);            _containsGeode = false;#if 0            std::cout<<"found Group="<<tid->lod		     <<"  X="<<tid->x		     <<"  Y="<<tid->y		     <<"  ptr="<<&node<<std::endl;              std::cout<<"      inheritance list "<<_tileStack.size()<<std::endl;            for(TileStack::iterator itr=_tileStack.begin();                itr!=_tileStack.end();                ++itr)            {                std::cout<<"      LOD="<<itr->first.lod                         <<" X="<<itr->first.x                         <<" Y="<<itr->first.y                         <<" className="<<itr->second->className()                         <<" ptr="<<itr->second<<std::endl;                  }                        osg::StateSet* stateset = node.getOrCreateStateSet();            osg::Material* material = new osg::Material;            material->setColorMode(osg::Material::OFF);            stateset->setAttribute(material);                        switch(tid->lod)            {            case(0): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); break;            case(1): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,0.0f,1.0f)); break;            case(2): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,1.0f,0.0f,1.0f)); break;            case(3): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,1.0f,1.0f)); break;            case(4): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,1.0f,1.0f)); break;            }            #endif                    }            _tileStack.pop_back();    }    // pop the culling mode.    popCurrentMask();}void TileMapper::apply(osg::Geode&){    _containsGeode = true;}void TileMapper::apply(osg::PagedLOD& node){    if (isCulled(node))	return;    // push the culling mode.    pushCurrentMask();    TXPPagedLOD* txpPagedLOD = dynamic_cast<TXPPagedLOD*>(&node);    if (txpPagedLOD)    {                                           _tileStack.push_back(TileStack::value_type(txpPagedLOD->_tileIdentifier,&node));        _containsGeode = false;    }    traverse(node);    if (txpPagedLOD)    {        if (_containsGeode)        {            insertTile(txpPagedLOD->_tileIdentifier);            _containsGeode = false;#if 0            std::cout<<"found txpPagedLOD LOD="<<txpPagedLOD->_tileIdentifier.lod		     <<"  X="<<txpPagedLOD->_tileIdentifier.x		     <<"  Y="<<txpPagedLOD->_tileIdentifier.y		     <<"  ptr="<<txpPagedLOD<<std::endl;              std::cout<<"      inheritance list "<<_tileStack.size()<<std::endl;            for(TileStack::iterator itr=_tileStack.begin();                itr!=_tileStack.end();                ++itr)            {                std::cout<<"      LOD="<<itr->first.lod                         <<" X="<<itr->first.x                         <<" Y="<<itr->first.y                         <<" className="<<itr->second->className()                         <<" ptr="<<itr->second<<std::endl;                  }            osg::StateSet* stateset = txpPagedLOD->getOrCreateStateSet();            osg::Material* material = new osg::Material;            material->setColorMode(osg::Material::OFF);            stateset->setAttribute(material);            switch(txpPagedLOD->_tileIdentifier.lod)            {            case(0): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); break;            case(1): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,0.0f,1.0f)); break;            case(2): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,1.0f,0.0f,1.0f)); break;            case(3): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,1.0f,1.0f)); break;            case(4): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,1.0f,1.0f)); break;            }#endif                    }        _tileStack.pop_back();    }    // pop the culling mode.    popCurrentMask();}void TileMapper::insertTile(const TileIdentifier& tid){    _tileMap.insert(TileMap::value_type(tid,_tileStack));}bool TileMapper::canParentBeTraversed(const TileIdentifier& tid) const{    // find the tiles parents.    TileMap::const_iterator itr = _tileMap.find(tid);    if (itr==_tileMap.end())    {#if 0        // not found tile in _tileMap, what should we do??        // return true as a fallback right now.        std::cout<<"TileMapper::canDescend() Not found tile in map"<<std::endl;#endif        return true;    }    const TileStack& ts = itr->second;        // note tile here, is tid's parent.    const TileStack::value_type* tile = (ts.size()>=2) ? &ts[ts.size()-2] : 0;    // note parent here, is tid's parents parent.    const TileStack::value_type* parent = (ts.size()>=3) ? &ts[ts.size()-3] : 0;        if (!tile)    {        // no self!!! so we can descend safely?!! shouldn't ever get here.        //std::cout<<"TileMapper::canDescend() tile==0"<<std::endl;        return true;    }    if (!parent)    {        // no parent so we can descend safely.        return true;    }        bool tileHasNorthNeighour = _tileMap.count(TileIdentifier(tid.x,tid.y+1,tid.lod))!=0;    bool tileHasEastNeighour = _tileMap.count(TileIdentifier(tid.x+1,tid.y,tid.lod))!=0;    bool tileHasSouthNeighour = _tileMap.count(TileIdentifier(tid.x,tid.y-1,tid.lod))!=0;    bool tileHasWestNeighour = _tileMap.count(TileIdentifier(tid.x-1,tid.y,tid.lod))!=0;        if (tileHasNorthNeighour && tileHasEastNeighour && tileHasSouthNeighour && tileHasWestNeighour)    {        // tile has neigbours on all sides at the same lod level, so its safe to descend.        //std::cout<<"TileMapper::canDescend() has neightbours on all sides"<<std::endl;        return true;    }    const TileIdentifier& parent_tid = parent->first;        bool parentHasNorthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y+1,parent_tid.lod))!=0;    bool parentHasEastNeighour = _tileMap.count(TileIdentifier(parent_tid.x+1,parent_tid.y,parent_tid.lod))!=0;    bool parentHasSouthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y-1,parent_tid.lod))!=0;    bool parentHasWestNeighour = _tileMap.count(TileIdentifier(parent_tid.x-1,parent_tid.y,parent_tid.lod))!=0;        // identify whether the tile is a NE/SE/SW/NW tile relative to its parent.    osg::Vec3 delta = tile->second->getBound().center() - parent->second->getBound().center();        if (delta.y()>=0.0f) // noth side    {                if (delta.x()>=0.0f)        {            // NE, only traverse if our parent doesn't have any neighbours to the north or east.            return (!parentHasNorthNeighour && !parentHasEastNeighour);        }        else         {            // NW, only traverse if our parent doesn't have any neighbours to the north or west.            return (!parentHasNorthNeighour && !parentHasWestNeighour);        }    }    else // south side    {        if (delta.x()>=0.0f)        {            // SE, only traverse if our parent doesn't have any neighbours to the south or east.            return (!parentHasSouthNeighour && !parentHasEastNeighour);        }        else         {            // SW, only traverse if our parent doesn't have any neighbours to the south or west.            return (!parentHasSouthNeighour && !parentHasWestNeighour);        }    }    // we shouldn't get here...        return true;}void TileMapper::checkValidityOfAllVisibleTiles(){    typedef std::vector<TileIdentifier> ToRemoveList;    typedef std::vector<TileStack> ToAddList;    ToRemoveList toRemoveList;    ToAddList toAddList;    do    {//        std::cout<<"doing checkAllVisibleTiles() loop with "<<_tileMap.size()<<std::endl;            toRemoveList.clear();        toAddList.clear();        for(TileMap::iterator itr=_tileMap.begin();            itr!=_tileMap.end();            ++itr)        {            if (!canParentBeTraversed(itr->first))            {                // need to remove.                toRemoveList.push_back(itr->first);                // trim the end of itr's TileStack and add into toAddList                toAddList.push_back(itr->second);//                 std::cout<<"Tile failed"//                          <<" LOD="<<itr->first.lod//                          <<" X="<<itr->first.x//                          <<" Y="<<itr->first.y<<std::endl;            }        }        for(ToRemoveList::iterator ritr=toRemoveList.begin();            ritr!=toRemoveList.end();            ++ritr)        {            //std::cout<<"Removing Tile"<<std::endl;            _tileMap.erase(*ritr);        }        for(ToAddList::iterator aitr=toAddList.begin();            aitr!=toAddList.end();            ++aitr)        {            //std::cout<<"Adding Parents Tile back in"<<std::endl;            aitr->pop_back();            _blackListedNodeSet.insert(aitr->back().second);            _tileMap.insert(TileMap::value_type(aitr->back().first,*aitr));        }            }    while (!toRemoveList.empty());    #if 0	if ( !_blackListedNodeSet.empty() )		std::cout << "********** We have blacked list " << _blackListedNodeSet.size() << std::endl;    std::cout<<"TileMap contains "<<_tileMap.size()<<std::endl;    for(TileMap::iterator itr=_tileMap.begin();        itr!=_tileMap.end();        ++itr)    {	std::cout<<"    tile="<<itr->first.lod		 <<"  X="<<itr->first.x		 <<"  Y="<<itr->first.y<<std::endl;              }#endif    }bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx, int dy) const{    if (_tileMap.count(TileIdentifier(tid.x+dx,tid.y+dy,tid.lod))!=0)    {        // we have a neightbour at the same lod level.        return false;    }    // find the tiles parents.    TileMap::const_iterator itr = _tileMap.find(tid);    if (itr==_tileMap.end())    {        // not found tile in _tileMap, what should we do??        // return true as a fallback right now.#if 0	std::cout << "TileMapper::isTileNeighbourALowerLODLevel() Not found tile in map," << std::endl;	std::cout << "    LOD=" << tid.lod << "  X=" << tid.x << "  Y=" << tid.y << std::endl;#endif         return true;    }    const TileStack& ts = itr->second;        // note tile here, is tid's parent.    const TileStack::value_type* tile = (ts.size()>=1) ? &ts[ts.size()-1] : 0;    if (!tile)    {        // no tile, so must assume that neighbor is now at a lower level        return false;    }    // note parent here, is tid's parents parent.    const TileStack::value_type* parent = (ts.size()>=2) ? &ts[ts.size()-2] : 0;        if (!parent)    {        // no parent so we must assume that is not at a lower level        return false;    }        const TileIdentifier& parent_tid = parent->first;        bool parentHasNorthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,  parent_tid.y+1,parent_tid.lod))!=0;    bool parentHasEastNeighour  = _tileMap.count(TileIdentifier(parent_tid.x+1,parent_tid.y,  parent_tid.lod))!=0;    bool parentHasSouthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,  parent_tid.y-1,parent_tid.lod))!=0;    bool parentHasWestNeighour  = _tileMap.count(TileIdentifier(parent_tid.x-1,parent_tid.y,  parent_tid.lod))!=0;        // identify whether the tile is a NE/SE/SW/NW tile relative to its parent.    osg::Vec3 delta = tile->second->getBound().center() - parent->second->getBound().center();        if (delta.y()>=0.0f) // noth side    {                if (delta.x()>=0.0f)        {            // NE            if (dy==1)		return parentHasNorthNeighour;            else if (dx==1)		return parentHasEastNeighour;        }        else         {            // NW            if (dy==1)		return parentHasNorthNeighour;            else if (dx==-1)		return parentHasWestNeighour;        }    }    else // south side    {        if (delta.x()>=0.0f)        {            // SE            if (dy==-1)		return parentHasSouthNeighour;            else if (dx==1)		return parentHasEastNeighour;        }        else         {            // SW            if (dy==-1)		return parentHasSouthNeighour;            else if (dx==-1)		return parentHasWestNeighour;        }    }        return false;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?