📄 trpage_rarchive.cpp
字号:
/* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. 4400 East Broadway #314 Tucson, AZ 85711 info@terrex.com Tel: (520) 323-7990 ************************ */#include <osgDB/FileUtils>#include <stdlib.h>#include <stdio.h>#include <string.h>/* trpage_rarchive.cpp This source file implements the methods for a trpgr_Archive. The Read Archive is used to read a paging archive from disk.*/#include <trpage_read.h>#include <trpage_compat.h>// Constructortrpgr_Archive::trpgr_Archive(){ fp = NULL; ness = LittleEndian; strcpy(dir,"."); tileCache = NULL;}// Destructortrpgr_Archive::~trpgr_Archive(){ if (fp) fclose(fp); fp = NULL; if (tileCache) delete tileCache;}int32 trpgr_Archive::GetHeaderData(char *dataPtr, int length, FILE *filehandle){ return fread(dataPtr,1,length,filehandle);}// Set the directory where the archive isvoid trpgr_Archive::SetDirectory(const char *in_dir){ strncpy(dir,in_dir,1024);}// Open File// Open the given file and look for the file specific infobool trpgr_Archive::OpenFile(const char *name){ char file[1024]; sprintf(file,"%s" PATHSEPERATOR "%s",dir,name); CloseFile(); if (!(fp = osgDB::fopen(file,"rb"))) return false; // Look for a magic # and endianness int32 magic; if (fread(&magic,sizeof(int32),1,fp) != 1) return false; headerRead = false; // Figure out the endianness from the magic number trpgEndian cpuNess = trpg_cpu_byte_order(); if (magic == GetMagicNumber()) { ness = cpuNess; return true; } if (trpg_byteswap_int(magic) == GetMagicNumber()) { if (cpuNess == LittleEndian) ness = BigEndian; else ness = LittleEndian; return true; } if (magic != GetMagicNumber()) return false; // Not one of our files return false;}// Get new reading app file cachetrpgrAppFileCache* trpgr_Archive::GetNewRAppFileCache(const char *fullBase, const char *ext){ return new trpgrAppFileCache(fullBase,ext);}trpgrImageHelper* trpgr_Archive::GetNewRImageHelper(trpgEndian ness,char *dir,const trpgMatTable &matTable,const trpgTexTable &texTable){ bool separateGeo = false; int majorVer,minorVer; GetHeader()->GetVersion(majorVer,minorVer); if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) { separateGeo = true; } return new trpgrImageHelper(ness,dir,matTable,texTable,separateGeo);}// Close File// Close the currently open filevoid trpgr_Archive::CloseFile(){ if (fp) fclose(fp); fp = NULL; if (tileCache) delete tileCache; tileCache = NULL;}/** * Read a sub block from a 2.2 TXP database. This can be called any time after ReadHeader is called * if ReadHeader is called with the false parameter to specify not to read all the sub-archives. * This can make a huge improvement in startup time for loading a very large archive with many blocks. **/bool trpgr_Archive::ReadSubArchive(int row, int col, trpgEndian cpuNess){ int ret; trpgHeader blockHeader; trpgr_Parser bparser; char blockpath[1024]; //open the block archive // the block archive will be in the base dir + \\cols\\row\\archive.txp sprintf(blockpath,"%s%s%d%s%d%sarchive.txp",dir,PATHSEPERATOR,col,PATHSEPERATOR,row,PATHSEPERATOR); FILE *bfp = osgDB::fopen(blockpath,"rb"); if(!bfp) { return false; } // Look for a magic # and endianness int32 bmagic; if (fread(&bmagic,sizeof(int32),1,bfp) != 1) return false; // The block archive will always be the same endianness as the master if ( (bmagic != GetMagicNumber()) && (trpg_byteswap_int(bmagic) != GetMagicNumber()) ) return false; int32 bheaderSize=0; if (fread(&bheaderSize,sizeof(int32),1,bfp) != 1) return false; if (ness != cpuNess) bheaderSize = trpg_byteswap_int(bheaderSize); int bheadLen = bheaderSize; if (bheadLen < 0) return false; // Read in the header whole trpgMemReadBuffer bbuf(ness); bbuf.SetLength(bheadLen); char *bdata = bbuf.GetDataPtr(); if ((ret = GetHeaderData(bdata,bheadLen,bfp)) != bheadLen) return false; //keep track of where this came from in the master table. tileTable.SetCurrentBlock(row,col,true); texTable.SetCurrentBlock(row,col); bparser.AddCallback(TRPGHEADER,&blockHeader); bparser.AddCallback(TRPGMATTABLE,&materialTable); // Went back to oldest style for 2.0 //if(!headerHasTexTable) { bparser.AddCallback(TRPGTEXTABLE2,&texTable); // Added for 2.0 //} bparser.AddCallback(TRPGMODELTABLE,&modelTable); bparser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0 bparser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0 bparser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1 bparser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable); bparser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable); // Don't read the tile table for v1.0 archives // It's only really used for 2.0 archives bparser.AddCallback(TRPGTILETABLE2,&tileTable); // Parse the buffer if (!bparser.Parse(bbuf)) return false; //close the block archive fclose(bfp); tileTable.SetCurrentBlock(-1,-1,false); return true;}bool trpgr_Archive::ReadHeader(){ return ReadHeader(true);}// Read Header// Run through the rest of the header informationbool trpgr_Archive::ReadHeader(bool readAllBlocks){ int ret; if (!fp || headerRead) return false; headerRead = true; // Next int64 should be the header size trpgEndian cpuNess = trpg_cpu_byte_order(); int32 headerSize; if (fread(&headerSize,sizeof(int32),1,fp) != 1) return false; if (ness != cpuNess) headerSize = trpg_byteswap_int(headerSize); int headLen = headerSize; if (headLen < 0) return false; // Read in the header whole trpgMemReadBuffer buf(ness); buf.SetLength(headLen); char *data = buf.GetDataPtr(); if ((ret = GetHeaderData(data,headLen,fp)) != headLen) return false; // Set up a parser // Catch the tables we need for the archive trpgMatTable1_0 oldMatTable; trpgTexTable1_0 oldTexTable; trpgr_Parser parser; parser.AddCallback(TRPGHEADER,&header); parser.AddCallback(TRPGMATTABLE,&materialTable); // Went back to oldest style for 2.0 parser.AddCallback(TRPGMATTABLE2,&oldMatTable); // Added 11-14-98 (1.0 material table) parser.AddCallback(TRPGTEXTABLE,&oldTexTable); parser.AddCallback(TRPGTEXTABLE2,&texTable); // Added for 2.0 parser.AddCallback(TRPGMODELTABLE,&modelTable); parser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0 parser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0 parser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1 parser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable); parser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable); // Don't read the tile table for v1.0 archives // It's only really used for 2.0 archives parser.AddCallback(TRPGTILETABLE2,&tileTable); // Parse the buffer if (!parser.Parse(buf)) return false; if(header.GetIsMaster()) { // bool firstBlock = true; bool headerHasTexTable = false; //if the master has textures, we want to use them instead of the tables in the //block archives int numTex = 0; texTable.GetNumTextures(numTex); if(numTex) headerHasTexTable = true; // int numTiles = 0; //tileTable. int totalrows,totalcols; trpg2dPoint mhdr_swExtents; trpg2dPoint mhdr_neExtents; trpg3dPoint mhdr_Origin; // integrate header information from the block header. header.GetExtents(mhdr_swExtents,mhdr_neExtents); header.GetOrigin(mhdr_Origin); header.GetBlocks(totalrows,totalcols); if(readAllBlocks) { for(int row=0;row<totalrows;row++) { for(int col=0;col<totalcols;col++) { // Read each block -- Warning, this can take a while!!! ReadSubArchive( row, col, cpuNess); } } } else { ReadSubArchive( 0, 0, cpuNess);//Get the first archive! } } tileTable.SetCurrentBlock(-1,-1,false); // 1.0 Compatibility // If we see an older style material table, convert it to the new style // This isn't terribly memory efficient, but it does work if (oldMatTable.isValid()) materialTable = oldMatTable; if (oldTexTable.isValid()) texTable = oldTexTable; // Set up a tile cache, if needed trpgTileTable::TileMode tileMode; tileTable.GetMode(tileMode); if (tileMode == trpgTileTable::Local) { if (tileCache) delete tileCache; char fullBase[1024]; sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir); tileCache = GetNewRAppFileCache(fullBase,"tpf"); } valid = true; return true;}// Read Tile// Read a tile into a read buffer// For version 2.1 only tile with lod=0 are stored in the tile table, so an// error will be returned if you try to use the table with a differrent lod.bool trpgr_Archive::ReadTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf){ if (!isValid()) return false; // Reality check the address int32 numLods; header.GetNumLods(numLods); if (static_cast<int>(lod) >= numLods) return false; trpg2iPoint lodSize; header.GetLodSize(lod,lodSize); if (static_cast<int>(x) >= lodSize.x || static_cast<int>(y) >= lodSize.y) return false; trpgTileTable::TileMode tileMode; tileTable.GetMode(tileMode); bool status = true; if (tileMode == trpgTileTable::External || tileMode == trpgTileTable::ExternalSaved) { status = ReadExternalTile(x, y, lod, buf); } else { // Local tile. Figure out where it is (which file) int majorVersion, minorVersion; header.GetVersion(majorVersion, minorVersion); if(majorVersion == 2 && minorVersion >=1) { // Version 2.1 // Tile table contains only lod 0 tiles if(lod != 0) status = false; } if(status) { trpgwAppAddress addr; float zmin,zmax; status = tileTable.GetTile(x,y,lod,addr,zmin,zmax); if(status) status = ReadTile(addr, buf); } } return status;}bool trpgr_Archive::ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf){ // Figure out the file name char filename[1024]; int majorVer,minorVer; header.GetVersion(majorVer,minorVer); if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer >= TRPG_NOMERGE_VERSION_MINOR)) { int blockx,blocky; unsigned int denom = (1 << lod); // this should work up to lod 31
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -