readerwritertxp.cpp

来自「最新osg包」· C++ 代码 · 共 878 行 · 第 1/2 页

CPP
878
字号
    return ReadResult::ERROR_IN_READING_FILE;}// If you change this then you have to change extractChildrenLocation()void ReaderWriterTXP::createChildrenLocationString(const std::vector<TXPArchive::TileLocationInfo>& locs, std::string& locString) const{    std::stringstream theLoc;    if(locs.size() == 0)    {        theLoc << "_" << locs.size();    }    else    {           theLoc << "_" << locs.size() << "_" << "{" ;        for(unsigned int idx = 0; idx < locs.size(); ++idx)        {            const TXPArchive::TileLocationInfo& loc = locs[idx];            theLoc << loc.x                    << "_"                    << loc.y                    << "_"                    << loc.addr.file                    << "_"                    << loc.addr.offset                   << "_"                   << loc.zmin                   << "_"                   << loc.zmax;            if(idx != locs.size() -1)                theLoc << "_";        }    }    theLoc << "}" << std::ends;    locString = theLoc.str();}bool ReaderWriterTXP::extractChildrenLocations(const std::string& name, int parentLod, std::vector<TXPArchive::TileLocationInfo>& locs, int nbChild) const{    locs.clear();    if(nbChild == 0)        return true;    locs.resize(nbChild);    // We look for '{', which should be the start of the list of {x,y,addr} children data    // '}' should end the list.    // We expect: X,Y,FID,FOFFSET,ZMIN,ZMAX    std::string::size_type startOfList = name.find_last_of('{');    if(startOfList == std::string::npos)        return false;    std::string::size_type endOfList = name.find_last_of('}');    if(endOfList == std::string::npos)        return false;    // Extract the data    strcpy(gbuf, name.substr(startOfList + 1, endOfList - startOfList - 1).c_str());    char *token = strtok( gbuf, "_" );    int nbTokenRead = 0;    for(int idx = 0; idx < nbChild; idx++)    {        // X        if(!token)            break;        locs[idx].x = atoi(token);        nbTokenRead++;        // Y        token = strtok(0, "_");        if(!token)            break;        locs[idx].y = atoi(token);        nbTokenRead++;        // FID        token = strtok(0, "_");        if(!token)            break;        locs[idx].addr.file = atoi(token);        nbTokenRead++;        // OFFSET        token = strtok(0, "_");        if(!token)            break;        locs[idx].addr.offset = atoi(token);        nbTokenRead++;        // ZMIN        token = strtok(0, "_");        if(!token)            break;        locs[idx].zmin = (float)atof(token);        nbTokenRead++;        // ZMAX        token = strtok(0, "_");        if(!token)            break;        locs[idx].zmax= (float)atof(token);        nbTokenRead++;        locs[idx].lod = parentLod+1;              token = strtok(0, "_");    }    if(nbTokenRead != nbChild*6)        return false;    else        return true;}TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir){    TXPArchive* archive = NULL;    std::map< int,osg::ref_ptr<TXPArchive> >::iterator iter = _archives.find(id);        if (iter != _archives.end())    {        archive = iter->second.get();    }    if (archive == NULL)    {#ifdef _WIN32        const char _PATHD = '\\';#elif defined(macintosh)        const char _PATHD = ':';#else        const char _PATHD = '/';#endif        std::string archiveName = dir+_PATHD+"archive.txp";        archive = new TXPArchive;        if (archive->openFile(archiveName) == false)        {            ReaderWriterTXPERROR("getArchive()") << "failed to load archive: \"" << archiveName << "\"" << std::endl;            return NULL;        }        if (archive->loadMaterials() == false)        {            ReaderWriterTXPERROR("getArchive()") << "failed to load materials from archive: \"" << archiveName << "\"" << std::endl;            return NULL;        }        if (archive->loadModels() == false)        {            ReaderWriterTXPERROR("getArchive()") << "failed to load models from archive: \"" << archiveName << "\"" << std::endl;            return NULL;        }        if (archive->loadLightAttributes() == false)        {            ReaderWriterTXPERROR("getArchive()") << "failed to load light attributes from archive: \"" << archiveName << "\"" << std::endl;            return NULL;        }        if (archive->loadTextStyles() == false)        {            ReaderWriterTXPERROR("getArchive()") << "failed to load text styles from archive: \"" << archiveName << "\"" << std::endl;            return NULL;        }        archive->setId(id);        _archives[id] = archive;    }    return archive;}class SeamFinder: public osg::NodeVisitor{public:    SeamFinder(int x, int y, int lod, const TXPArchive::TileInfo& info, TXPArchive *archive ):    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),    _x(x), _y(y), _lod(lod), _info(info), _archive(archive)     {}    virtual void apply(osg::Group& group)    {        for (unsigned int i = 0; i < group.getNumChildren(); i++)        {        osg::Node* child = group.getChild(i);        osg::Node* seam = seamReplacement(child);        if (child != seam)        {            group.replaceChild(child,seam);        }        else        {            child->accept(*this);        }        }    }protected:    osg::Node* seamReplacement(osg::Node* node);    int _x, _y, _lod;    const TXPArchive::TileInfo& _info;    TXPArchive *_archive;};osg::Node* SeamFinder::seamReplacement(osg::Node* node){    osg::Group* group = node->asGroup();    if ( group == 0 )        return node;    std::vector<osg::Node*> nonSeamChildren;    osg::LOD* hiRes = 0;    osg::LOD* loRes = 0;    const trpgHeader* header = _archive->GetHeader();    trpgHeader::trpgTileType tileType;    header->GetTileOriginType(tileType);    for (unsigned int i = 0; i < group->getNumChildren(); i++)    {        osg::LOD* lod = dynamic_cast<osg::LOD*>(group->getChild(i));        if (lod == 0)        {            nonSeamChildren.push_back(group->getChild(i));            continue;        }        bool nonSeamChild = true;    // looks like the problem is in here - likely due to seamLOD info    // not being adjusted properly in tiled databases        // seam center is outside the bounding box of the tile    osg::Vec3 lodCenter = lod->getCenter();        if(tileType == trpgHeader::TileLocal)        {            trpg2dPoint tileExtents;            header->GetTileSize(0, tileExtents);            osg::BoundingBox bbox;            _archive->getExtents(bbox);            osg::Vec3 offset(0.0, 0.0, 0.0);            int divider = (0x1 << _lod);            // calculate which tile model is located in            tileExtents.x /= divider;            tileExtents.y /= divider;            offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5;            offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5;        lodCenter += offset;        }        if (!_info.bbox.contains(lodCenter))        {            // seams have center as the neighbour tile            osg::Vec3 d = _info.center - lodCenter;            if (((fabs(d.x())-_info.size.x()) > 0.0001) && ((fabs(d.y())-_info.size.y()) > 0.0001))            {                nonSeamChildren.push_back(lod);                continue;            }            // low res seam has min/max ranges of lod+1 range/lod 0 range            if ((fabs((float)_info.minRange-lod->getMinRange(0))<0.001)&&(fabs((float)_info.lod0Range-lod->getMaxRange(0))<0.001))            {                if (loRes==0)                {                    loRes = lod;                    nonSeamChild = false;                }            }            // hi res seam has min/max ranges of 0 range/lod+1 range            if ((lod->getMinRange(0)==0.0f)&&(fabs(_info.minRange-lod->getMaxRange(0))<0.001))            {                if (hiRes==0)                {                    hiRes = lod;                    nonSeamChild = false;                }            }        }        if (nonSeamChild)        {            nonSeamChildren.push_back(lod);        }    }    if (loRes)    {        int dx = 0;        int dy = 0;        int lod = _lod;    osg::Vec3 lodCenter = loRes->getCenter();        if(tileType == trpgHeader::TileLocal)        {            trpg2dPoint tileExtents;            header->GetTileSize(0, tileExtents);            osg::BoundingBox bbox;            _archive->getExtents(bbox);            osg::Vec3 offset(0.0, 0.0, 0.0);            int divider = (0x1 << _lod);            // calculate which tile model is located in            tileExtents.x /= divider;            tileExtents.y /= divider;            offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5;            offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5;        lodCenter += offset;        }        osg::Vec3 delta = lodCenter-_info.center;        if (fabs(delta.x())>fabs(delta.y()))        {            if ( delta.x() < 0.0 )                --dx;    // west            else                dx++;                  // east        }        else        {            if ( delta.y() < 0.0 )                --dy;    // south            else                ++dy;                  // north        }        TXPSeamLOD* seam = new TXPSeamLOD(_x, _y, lod, dx, dy);    seam->setCenter(loRes->getCenter());        seam->addChild(loRes->getChild(0));        // low res        if (hiRes)         {            seam->addChild(hiRes->getChild(0));    // high res        }          if (nonSeamChildren.empty())        {            return seam;        }        else        {            osg::Group* newGroup = new osg::Group;            newGroup->addChild(seam);                        for (unsigned int i = 0; i < nonSeamChildren.size(); i++)                newGroup->addChild(nonSeamChildren[i]);                            return newGroup;        }    }    return node;}osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive,  std::vector<TXPArchive::TileLocationInfo>& childrenLoc){    if ( archive == 0 )        return false;    int majorVersion, minorVersion;    archive->GetVersion(majorVersion, minorVersion);    double realMinRange = info.minRange;    double realMaxRange = info.maxRange;    double  usedMaxRange = osg::maximum(info.maxRange,1e7);    osg::Vec3 tileCenter;    osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc);    // if group has only one child, then simply use its child.        while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())    {        tileGroup = tileGroup->getChild(0)->asGroup();    }            bool doSeam = false;    if(majorVersion == 2 && minorVersion >= 1)        doSeam = (childrenLoc.size() > 0);    else        doSeam = (lod < (archive->getNumLODs() - 1));    // Handle seams    if (doSeam)    {        SeamFinder sfv(x,y,lod,info,archive);        tileGroup->accept(sfv);    }    return tileGroup;}// this version only gets called if the TXP version is >= than 2.1osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, const TXPArchive::TileLocationInfo& loc, TXPArchive* archive,  std::vector<TXPArchive::TileLocationInfo>& childrenLoc){    if ( archive == 0 )        return false;    // int numLods = archive->getNumLODs();    double realMinRange = info.minRange;    double realMaxRange = info.maxRange;    double usedMaxRange = osg::maximum(info.maxRange,1e7);    osg::Vec3 tileCenter;    osg::Group* tileGroup = archive->getTileContent(loc,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc);    // if group has only one child, then simply use its child.        while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())    {        tileGroup = tileGroup->getChild(0)->asGroup();    }            // Handle seams    if (childrenLoc.size() > 0)    {        SeamFinder sfv(loc.x, loc.y, loc.lod, info, archive);        tileGroup->accept(sfv);    }    return tileGroup;}REGISTER_OSGPLUGIN(txp, ReaderWriterTXP)

⌨️ 快捷键说明

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