trpage_warchive.cpp
来自「最新osg包」· C++ 代码 · 共 1,608 行 · 第 1/3 页
CPP
1,608 行
/* ************************ 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_warchive.cpp This source file contains the implementations of trpgwArchive and trpgwGeomHelper. The Write Archive is used to write TerraPage archives. All its important methods are virtual, so you shouldn't need to modify any of this code. Simply subclass and override. The Geometry Helper is a class that's used to sort out polygons and build trpgGeometry objects, containing triangle strips and fans out of them. The one contained here is fairly simple, but all its important methods are virtual. So again, subclass and override if you need to change them.*/#include <trpage_geom.h>#include <trpage_write.h>#include <trpage_compat.h>#include <trpage_read.h>// ConstructortrpgwArchive::trpgwArchive(trpgEndian inNess,trpgwArchive::TileMode inTileMode,int majorVer, int minorVer){ Init(inNess,inTileMode,majorVer, minorVer);}void trpgwArchive::Init(trpgEndian inNess, trpgwArchive::TileMode inTileMode,int majorVer, int minorVer){ minorVersion = minorVer; majorVersion = majorVer; if (majorVersion < 1 || majorVersion > TRPG_VERSION_MAJOR) throw 1; if(majorVersion == TRPG_VERSION_MAJOR) { if(minorVersion < 0 || minorVersion > TRPG_VERSION_MINOR) throw 1; } fp = NULL; strcpy(dir,"."); ness = inNess; tileMode = inTileMode; cpuNess = trpg_cpu_byte_order(); tileFile = NULL; tileFileCount = 0; isRegenerate = false; maxTileFileLen = -1; firstHeaderWrite = true;}// Constructor for regeneratetrpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne, int majorVer, int minorVer){ Init(inDir,inFile,sw,ne, majorVer, minorVer);}void trpgwArchive::Init(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne, int majorVer, int minorVer){ maxTileFileLen = -1; majorVersion = majorVer; minorVersion = minorVer; fp = NULL; strcpy(dir,inDir); cpuNess = trpg_cpu_byte_order(); tileFile = NULL; tileFileCount = 0; isRegenerate = true; errMess[0] = '\0'; // TODO: have a "setup from file" method for trpgwArchive // Open a Read Archive to get the rest of the info we need trpgr_Archive *inArch = this->GetArchiveReader(); inArch->SetDirectory(inDir); if (!inArch->OpenFile(inFile)) { delete inArch; throw 1; } // Get the header (this is what we need) if (!inArch->ReadHeader()) { delete inArch; throw 1; } ness = inArch->GetEndian(); const trpgHeader *inHeader = inArch->GetHeader(); // use the version in the archive instead. inHeader->GetVersion(majorVersion,minorVersion); // Expand the coverage trpg2dPoint newSW,newNE; trpg2dPoint oldSW,oldNE; // Or not. Have to add in something to avoid recalculation // when merging geocentric databases. We don't really support // them, and everything goes to hell. So: hack is: // if sw=ne, don't change anything. // This will also help a little with MMB TXP merge speed. bool extentsUnchanged=false; inHeader->GetExtents(oldSW,oldNE); // just checking for equality right now. Bad? if ((sw==ne) || ((oldSW==sw) && (oldNE==ne))) { extentsUnchanged = true; // set up passed-in SW and NE as well. sw=newSW=oldSW; ne=newNE=oldNE; } else { newSW.x = MIN(sw.x,oldSW.x); newSW.y = MIN(sw.y,oldSW.y); newNE.x = MAX(ne.x,oldNE.x); newNE.y = MAX(ne.y,oldNE.y); } // Decide what the offset should be for new tiles if (!extentsUnchanged) { trpg2dPoint blockSize; inHeader->GetTileSize(0,blockSize); double dx = (oldSW.x - newSW.x)/blockSize.x + 10e-10; double dy = (oldSW.y - newSW.y)/blockSize.y + 10e-10; addOffset.x = (int)dx; addOffset.y = (int)dy; if (dx - addOffset.x > 10e-4 || dy - addOffset.y > 10e-4) { delete inArch; throw 1; } } // Header can mostly stay the same header = *inHeader; header.SetExtents(newSW,newNE); header.GetNumLods(numLod); // Update to the new MBR and tile grid sizes if (!extentsUnchanged) { for (int i=0;i<numLod;i++) { // Figure out the tile grid size trpg2dPoint tileSize; inHeader->GetTileSize(i,tileSize); trpg2iPoint newTileExt; newTileExt.x = int((newNE.x - newSW.x)/tileSize.x + 10e-5); newTileExt.y = int((newNE.y - newSW.y)/tileSize.y + 10e-15); header.SetLodSize(i,newTileExt); } } // These tables we can copy straight over matTable = *inArch->GetMaterialTable(); texTable = *inArch->GetTexTable(); modelTable = *inArch->GetModelTable(); lightTable = *inArch->GetLightTable(); rangeTable = *inArch->GetRangeTable(); textStyleTable = *inArch->GetTextStyleTable(); supportStyleTable = *inArch->GetSupportStyleTable(); labelPropertyTable = *inArch->GetLabelPropertyTable(); // Need to resize the tile table (maybe) // NOTE: Starting with version 2.1, the tile tables will contain only // the lod 0 tiles trpgTileTable::TileMode tileTableMode; if (!extentsUnchanged) { const trpgTileTable *oldTiles = inArch->GetTileTable(); oldTiles->GetMode(tileTableMode); tileTable.SetMode(tileTableMode); if(majorVersion == 2 && minorVersion >=1) { // Version 2.1. we store only lod 0, all other lod tiles are // stored in the parent tile tileTable.SetNumLod(0); // Size the output tile table trpg2iPoint tileSize; header.GetLodSize(0,tileSize); tileTable.SetNumTiles(tileSize.x, tileSize.y, 0); // Copy over individual tiles trpg2iPoint levelOffset; levelOffset.x = addOffset.x; levelOffset.y = addOffset.y; trpg2iPoint oldTileSize; inHeader->GetLodSize(0, oldTileSize); for (int ix=0;ix<oldTileSize.x;ix++) { for (int iy=0;iy<oldTileSize.y;iy++) { trpgwAppAddress addr; float zmin,zmax; oldTiles->GetTile(ix, iy, 0,addr,zmin,zmax); tileTable.SetTile(ix+addOffset.x, iy+addOffset.y ,0, addr, zmin, zmax); } } } else { tileTable.SetNumLod(numLod); for (int lod=0;lod<numLod;lod++) { // Size the output tile table trpg2iPoint tileSize; header.GetLodSize(lod,tileSize); tileTable.SetNumTiles(tileSize.x,tileSize.y,lod); // Copy over individual tiles trpg2iPoint levelOffset; levelOffset.x = addOffset.x*(lod+1); levelOffset.y = addOffset.y*(lod+1); trpg2iPoint oldTileSize; inHeader->GetLodSize(lod,oldTileSize); for (int ix=0;ix<oldTileSize.x;ix++) { for (int iy=0;iy<oldTileSize.y;iy++) { trpgwAppAddress addr; float zmin,zmax; oldTiles->GetTile(ix,iy,lod,addr,zmin,zmax); tileTable.SetTile(ix+addOffset.x,iy+addOffset.y,lod,addr,zmin,zmax); } } } } } else { tileTable = *inArch->GetTileTable(); tileTable.GetMode(tileTableMode); } // Continue to work in the mode the original database is in switch(tileTableMode) { case trpgTileTable::Local: tileMode = TileLocal; break; case trpgTileTable::External: tileMode = TileExternal; break; case trpgTileTable::ExternalSaved: tileMode = TileExternalSaved; break; } // That's it for the read archive delete inArch;}// DestructortrpgwArchive::~trpgwArchive(){ if (fp) fclose(fp); if (tileFile) { delete tileFile; tileFile = NULL; }}// WriteHeaderDataint32 trpgwArchive::WriteHeaderData(const char *dataPtr, int length, FILE* /*filehandle*/){ return fwrite(dataPtr,1,length,fp);}// IsValid()// Verifies that our file is openbool trpgwArchive::isValid() const{ if (!fp) { strcpy(errMess, "File object do not exist"); return false; } return true;}const char *trpgwArchive::getErrMess() const{ if(errMess[0] == '\0') return 0; else return &errMess[0];}// Set the maximum advised size for a tile filevoid trpgwArchive::SetMaxTileFileLength(int max){ maxTileFileLen = max;}/* Set Functions These just copy tables and the header from the input. If these aren't set, then empty ones are written.*/bool trpgwArchive::SetHeader(const trpgHeader &head){ header = head; return true;}bool trpgwArchive::SetMaterialTable(const trpgMatTable &mat){ matTable = mat; return true;}bool trpgwArchive::SetTextureTable(const trpgTexTable &tex){ texTable = tex; return true;}bool trpgwArchive::SetModelTable(const trpgModelTable &models){ modelTable = models; return true;}bool trpgwArchive::SetLightTable(const trpgLightTable &lights){ lightTable = lights; return true;}bool trpgwArchive::SetRangeTable(const trpgRangeTable &ranges){ rangeTable = ranges; return true;}bool trpgwArchive::SetTextStyleTable(const trpgTextStyleTable &styles){ textStyleTable = styles; return true;}bool trpgwArchive::SetLabelPropertyTable(const trpgLabelPropertyTable &properties){ labelPropertyTable = properties; return true;}bool trpgwArchive::SetSupportStyleTable(const trpgSupportStyleTable &styles){ supportStyleTable = styles; return true;}/* Get Methods Used in regenerate.*/trpgHeader *trpgwArchive::GetHeader(){ return &header;}trpgMatTable *trpgwArchive::GetMatTable(){ return &matTable;}trpgTexTable *trpgwArchive::GetTextureTable(){ return &texTable;}trpgModelTable *trpgwArchive::GetModelTable(){ return &modelTable;}trpgLightTable *trpgwArchive::GetLightTable(){ return &lightTable;}trpgRangeTable *trpgwArchive::GetRangeTable(){ return &rangeTable;}trpgTextStyleTable *trpgwArchive::GetTextStyleTable(){ return &textStyleTable;}trpgSupportStyleTable *trpgwArchive::GetSupportStyleTable(){ return &supportStyleTable;}trpgLabelPropertyTable *trpgwArchive::GetLabelPropertyTable(){ return &labelPropertyTable;}// OpenFile// Same as above, only gets a basename as wellbool trpgwArchive::OpenFile(const char *in_dir,const char *name){ char filename[1024]; strncpy(dir,in_dir,1023); sprintf(filename,"%s" PATHSEPERATOR "%s",dir,name); if (!(fp = osgDB::fopen(filename,"wb"))) return false; return true;}// CloseFile// Close the open filevoid trpgwArchive::CloseFile(){ if (fp) fclose(fp); fp = NULL;}/* Write Header Flush out the header (checkpoint) and return.*/bool trpgwArchive::WriteHeader(){ bool ret = CheckpointHeader(); if (tileFile) { delete tileFile; tileFile=NULL; } return ret;}/* CheckpointHeader The header lives in its own file, so we can write it at any point we have a valid archive. This includes all the tables, as well as basic header info.*/bool trpgwArchive::CheckpointHeader(){ trpgMemWriteBuffer buf(ness); if (!isValid()) return false; if (!header.isValid()) { if(header.getErrMess()) strcpy(errMess, header.getErrMess()); return false; } // This will close the appendable files if (tileFile) { tileFile->Flush(); } /* Build a Tile Table We need to build one from scratch here. However, we have all the relevant information collected during the WriteTile calls. */ if(header.GetIsLocal()) { int row = 0; int col = 0; header.GetBlocks(row,col); tileTable.SetCurrentBlock(row,col,true); } if (tileMode == TileExternal) { // External tiles are easy tileTable.SetMode(trpgTileTable::External); } else if( tileMode == TileExternalSaved) { if(!isRegenerate && firstHeaderWrite) { // Set up the sizes tileTable.SetMode(trpgTileTable::ExternalSaved); tileTable.SetNumLod(1); trpg2iPoint lodSize; header.GetLodSize(0,lodSize); tileTable.SetNumTiles(lodSize.x, lodSize.y, 0); firstHeaderWrite = false; } // Now set the individual tile locations for (unsigned int i=0;i<externalTiles.size();i++) { TileFileEntry &te = externalTiles[i]; trpgwAppAddress addr; addr.file = -1; addr.offset = -1; tileTable.SetTile(te.x,te.y,te.lod,addr,te.zmin,te.zmax); } externalTiles.clear(); } else { if (!isRegenerate && firstHeaderWrite) { // Local tiles require more work tileTable.SetMode(trpgTileTable::Local); if(majorVersion == 2 && minorVersion >= 1) { // Version 2.1, we store only lod 0 in the tile table // Set up the sizes tileTable.SetNumLod(1); trpg2iPoint lodSize; header.GetLodSize(0,lodSize); tileTable.SetNumTiles(lodSize.x, lodSize.y, 0); } else { // Set up the sizes int32 numLod; header.GetNumLods(numLod); tileTable.SetNumLod(numLod); for (int i=0;i<numLod;i++) { trpg2iPoint lodSize; header.GetLodSize(i,lodSize);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?