readerwritertxp.cpp
来自「最新osg包」· C++ 代码 · 共 878 行 · 第 1/2 页
CPP
878 行
#include <osg/Group>#include <osg/Object>#include <osg/Node>#include <osg/Notify>#include <osg/MatrixTransform>#include <osg/BoundingSphere>#include <osgDB/Registry>#include <osgDB/FileUtils>#include <osg/io_utils>#include <iostream>#include <sstream>#include "ReaderWriterTXP.h"#include "TXPNode.h"#include "TXPArchive.h"#include "TXPPagedLOD.h"#include "TXPSeamLOD.h"#include "TileMapper.h"#define ReaderWriterTXPERROR(s) osg::notify(osg::NOTICE) << "txp::ReaderWriterTXP::" << (s) << " error: "namespace{ char gbuf[2048];}using namespace txp;int ReaderWriterTXP::_archiveId = 0;osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::string& file, const osgDB::ReaderWriter::Options* options){ std::string name = osgDB::getSimpleFileName(file); // We load archive.txp if (strncmp(name.c_str(),"archive",7)==0) { std::string fileName = osgDB::findDataFile( file, options ); if ( fileName.empty() ) return ReadResult::FILE_NOT_FOUND; osg::ref_ptr<TXPNode> txpNode = new TXPNode; txpNode->setArchiveName(fileName); if (options) { txpNode->setOptions(options->getOptionString()); } //modified by Brad Anderegg on May-27-08 //calling getArchive will create a new TXPArchive if the specified one does not exist //we will set our osgdb loader options on the archive and set the appropriate archive on //the txpNode. int id = ++_archiveId; TXPArchive* archive = getArchive(id,osgDB::getFilePath(fileName)); if (archive != NULL) { archive->setId(id); if (options && options->getOptionString().find("loadMaterialsToStateSet")!=std::string::npos) { archive->SetMaterialAttributesToStateSetVar(true); } txpNode->loadArchive(archive); return txpNode.get(); } else { return ReadResult::ERROR_IN_READING_FILE; } } // We load tileLOD_XxY_ID.txp else if (strncmp(name.c_str(),"tile",4)==0) { int x,y,lod; unsigned int id; sscanf(name.c_str(),"tile%d_%dx%d_%u",&lod,&x,&y,&id); TXPArchive* archive = getArchive(id,osgDB::getFilePath(file)); // The way this is done a 'tile' should only be created for lod 0 only, // something is wrong if this is no the case if(lod != 0) { ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "paged 'tile' should be at lod 0" << std::endl; return ReadResult::ERROR_IN_READING_FILE; } trpgEndian endian = archive->GetEndian(); archive->ReadSubArchive( 0, 0, endian); archive->ReadSubArchive( y, x, endian);// std::cout << "Attempted " << x << " " << y << std::endl; TXPArchive::TileInfo info; if (!archive->getTileInfo(x,y,lod,info)) return ReadResult::ERROR_IN_READING_FILE; std::vector<TXPArchive::TileLocationInfo> childrenLoc; osg::ref_ptr<osg::Node> tileContent = getTileContent(info,x,y,lod,archive, childrenLoc); tileContent->setName("TileContent"); bool asChildren = false; std::string childrenInfoStr; int numLods = archive->getNumLODs(); int majorVersion, minorVersion; archive->GetVersion(majorVersion, minorVersion); if(majorVersion ==2 && minorVersion >=1) { // Version 2.1 and over // The tile table only contains lod 0 and the children // info are stored in its parent. SO if we do not want // to be forced to reparse the parent we need to save that // info. For now we just add it to the node name if(childrenLoc.size() > 0) { asChildren = true; createChildrenLocationString(childrenLoc, childrenInfoStr); } } else { if (lod < (numLods-1)) asChildren = true; } if (asChildren) { char pagedLODfile[1024]; sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d", archive->getDir(), lod, x, y, archive->getId()); strcat(pagedLODfile, childrenInfoStr.c_str()); strcat(pagedLODfile, ".txp"); // there are tile sets which do not maintain the z extents in // the tile table. This attempt to address the issue by using // the geometry bounding sphere. The downside is that this is // not coupled to the generation and may result in runtime cracks if (info.center.z() == 0) { osg::BoundingSphere bSphere = tileContent->getBound(); info.center.z() = bSphere.center().z(); info.radius = bSphere.radius(); } osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD; // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); pagedLOD->setFileName(1,pagedLODfile); pagedLOD->setRange(1,0,info.minRange); pagedLOD->setCenter(info.center); pagedLOD->setRadius(info.radius); pagedLOD->setPriorityOffset(0,numLods-lod); pagedLOD->setPriorityScale(0,1.0f); pagedLOD->setNumChildrenThatCannotBeExpired(1); pagedLOD->setTileId(x,y,lod); const trpgHeader* header = archive->GetHeader(); trpgHeader::trpgTileType tileType; header->GetTileOriginType(tileType); if(tileType == trpgHeader::TileLocal) { osg::Vec3d sw(info.bbox._min); pagedLOD->setCenter(info.center - sw); } return pagedLOD.get(); } else return tileContent.get(); } // For 2.0 and lower we load subtilesLOD_XxY_ID.txp // For 2.1 and over we load subtilesLOD_XxY_ID_NBCHILD_{X_Y_FID_FOFFSET_ZMIN_ZMAX_X_Y_ADDR ....}.txp else if (strncmp(name.c_str(),"sub",3)==0) { int x,y,lod; unsigned int id; sscanf(name.c_str(),"subtiles%d_%dx%d_%u",&lod,&x,&y,&id); TXPArchive* archive = getArchive(id,osgDB::getFilePath(file)); int majorVersion, minorVersion; archive->GetVersion(majorVersion, minorVersion); std::vector<TXPArchive::TileLocationInfo> childrenLoc; osg::ref_ptr<osg::Group> subtiles = new osg::Group; int numLods = archive->getNumLODs(); if(majorVersion == 2 && minorVersion >= 1) { int nbChild; sscanf(name.c_str(),"subtiles%d_%dx%d_%u_%d",&lod,&x,&y,&id, &nbChild); std::vector<TXPArchive::TileLocationInfo> locs; bool status = true; status = extractChildrenLocations(name, lod, locs, nbChild); if(majorVersion >= TRPG_NOMERGE_VERSION_MAJOR && minorVersion >=TRPG_NOMERGE_VERSION_MINOR && archive->GetHeader()->GetIsMaster()) { for(int idx=0;idx<nbChild;idx++) { //figure out the block row/col int blockx,blocky; unsigned int denom = (1 << locs[idx].lod); // this should work up to lod 31 blockx = locs[idx].x/denom; blocky = locs[idx].y/denom; locs[idx].addr.col = blockx; locs[idx].addr.row = blocky; } } if(!status) { ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "'subtile' filename children parsing failed " << std::endl; return ReadResult::ERROR_IN_READING_FILE; } const trpgHeader* header = archive->GetHeader(); trpgHeader::trpgTileType tileType; header->GetTileOriginType(tileType); TXPArchive::TileLocationInfo plInfo; plInfo.x = x; plInfo.y = y; plInfo.lod = lod; TXPArchive::TileInfo parentInfo; archive->getTileInfo(plInfo,parentInfo); for(int idx = 0; idx < nbChild; ++idx) { std::vector<TXPArchive::TileLocationInfo> childrenChildLoc; TXPArchive::TileLocationInfo& loc = locs[idx]; TXPArchive::TileInfo info; if (!archive->getTileInfo(loc,info)) continue; osg::ref_ptr<osg::Node> tileContent = getTileContent(info, loc, archive, childrenChildLoc); tileContent->setName("TileContent"); if(childrenChildLoc.size() > 0) { std::string childInfoStr; createChildrenLocationString(childrenChildLoc, childInfoStr); char pagedLODfile[1024]; sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d%s.txp", archive->getDir(), loc.lod, loc.x, loc.y, archive->getId(), childInfoStr.c_str()); // there are tile sets which do not maintain the z extents in // the tile table. This attempt to address the issue by using // the geometry bounding sphere. The downside is that this is // not coupled to the generation and may result in runtime cracks if (info.center.z() == 0) { osg::BoundingSphere bSphere = tileContent->getBound(); info.center.z() = bSphere.center().z(); info.radius = bSphere.radius(); } osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD; // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); pagedLOD->setFileName(1,pagedLODfile); pagedLOD->setRange(1,0,info.minRange); pagedLOD->setCenter(info.center); pagedLOD->setRadius(info.radius); pagedLOD->setPriorityOffset(0,numLods - loc.lod); pagedLOD->setPriorityScale(0,1.0f); pagedLOD->setNumChildrenThatCannotBeExpired(1); pagedLOD->setTileId(loc.x, loc.y, loc.lod); if(tileType == trpgHeader::TileLocal) { osg::Vec3d center(info.center - parentInfo.bbox._min); osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); sw[2] = 0.0; pagedLOD->setCenter(center - sw); osg::Matrix offset; offset.setTrans(sw); osg::MatrixTransform *tform = new osg::MatrixTransform(offset); tform->addChild(pagedLOD.get()); subtiles->addChild(tform); } else subtiles->addChild(pagedLOD.get()); subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod)); // is this really needed? } else { subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod)); if(tileType == trpgHeader::TileLocal) { osg::Vec3d center(info.center - parentInfo.bbox._min); osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); sw[2] = 0.0; osg::Matrix offset; offset.setTrans(sw); osg::MatrixTransform *tform = new osg::MatrixTransform(offset); tform->addChild(tileContent.get()); subtiles->addChild(tform); } else subtiles->addChild(tileContent.get()); } } } else { int sizeX, sizeY; archive->getLODSize(lod+1,sizeX,sizeY); const trpgHeader* header = archive->GetHeader(); trpgHeader::trpgTileType tileType; header->GetTileOriginType(tileType); TXPArchive::TileInfo parentInfo; archive->getTileInfo(x,y,lod,parentInfo); for (int ix = 0; ix < 2; ix++) { for (int iy = 0; iy < 2; iy++) { int tileX = x*2+ix; int tileY = y*2+iy; int tileLOD = lod+1; TXPArchive::TileInfo info; if (!archive->getTileInfo(tileX,tileY,tileLOD,info)) continue; osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive, childrenLoc); tileContent->setName("TileContent"); if (tileLOD < (numLods-1)) { char pagedLODfile[1024]; sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp", archive->getDir(), tileLOD, tileX, tileY, archive->getId()); // there are tile sets which do not maintain the z extents in // the tile table. This attempt to address the issue by using // the geometry bounding sphere. The downside is that this is // not coupled to the generation and may result in runtime cracks if (info.center.z() == 0) { osg::BoundingSphere bSphere = tileContent->getBound(); info.center.z() = bSphere.center().z(); info.radius = bSphere.radius(); } osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD; // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); pagedLOD->setFileName(1,pagedLODfile); pagedLOD->setRange(1,0,info.minRange); pagedLOD->setCenter(info.center); pagedLOD->setRadius(info.radius); pagedLOD->setPriorityOffset(0,numLods-lod); pagedLOD->setPriorityScale(0,1.0f); pagedLOD->setNumChildrenThatCannotBeExpired(1); pagedLOD->setTileId(tileX,tileY,tileLOD); if(tileType == trpgHeader::TileLocal) { osg::Vec3d center(info.center - parentInfo.bbox._min); osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); sw[2] = 0.0; pagedLOD->setCenter(center - sw); osg::Matrix offset; offset.setTrans(sw); osg::MatrixTransform *tform = new osg::MatrixTransform(offset); tform->addChild(pagedLOD.get()); subtiles->addChild(tform); } else subtiles->addChild(pagedLOD.get()); } else { subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD)); if(tileType == trpgHeader::TileLocal) { osg::Vec3d center(info.center - parentInfo.bbox._min); osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); sw[2] = 0.0; osg::Matrix offset; offset.setTrans(sw); osg::MatrixTransform *tform = new osg::MatrixTransform(offset); tform->addChild(tileContent.get()); subtiles->addChild(tform); } else subtiles->addChild(tileContent.get()); } } } } //osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl; return subtiles.get(); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?