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 + -
显示快捷键?