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 trpgMemWriteBuffer::trpgMemWriteBuffer(trpgEndian in_ness) { ness = in_ness; cpuNess = trpg_cpu_byte_order(); data = NULL; curLen = totLen = 0; }
/* ************************* Memory Read Buffer ************************* */ trpgMemReadBuffer::trpgMemReadBuffer(trpgEndian in_ness) { data = NULL; len = totLen = pos = 0; ness = in_ness; cpuNess = trpg_cpu_byte_order(); }
void trpgrAppFile::Init(trpgEndian inNess,const char *fileName) { valid = false; ness = inNess; cpuNess = trpg_cpu_byte_order(); if (!(fp = osgDB::fopen(fileName,"rb"))) return; valid = true; }
void trpgwAppFile::Init(trpgEndian inNess,const char *fileName,bool reuse) { valid = false; ness = inNess; cpuNess = trpg_cpu_byte_order(); if (reuse==false) { if (!(fp = osgDB::fopen(fileName,"wb"))) return; lengthSoFar = 0; valid = true; } else { if (!(fp = osgDB::fopen(fileName,"ab"))) return; // ftell is still zero, dammit. Arg. fseek(fp,0,SEEK_END); lengthSoFar = ftell(fp); valid = true; } }
// Collect the current vertex data and add a new whole vertex // Note: Deal with color void trpgwGeomHelper::AddVertex(trpg3dPoint &pt) { polyTex.insert(polyTex.end(),tmpTex.begin(),tmpTex.end()); polyNorm.push_back(tmpNorm); // Note: Turn this back on. It's not right currently, though #if 0 if (buf->GetEndian() != trpg_cpu_byte_order()) { trpg3dPoint tmpVert; tmpVert.x = trpg_byteswap_8bytes_to_double ((char *)&pt.x); tmpVert.y = trpg_byteswap_8bytes_to_double ((char *)&pt.y); tmpVert.z = trpg_byteswap_8bytes_to_double ((char *)&pt.z); polyVert.push_back(tmpVert); } else #endif polyVert.push_back(pt); // Update min/max zmin = MIN(pt.z,zmin); zmax = MAX(pt.z,zmax); }
// Open File // Open the given file and look for the file specific info bool trpgr_Archive::OpenFile(const char *name) { char file[1025]; 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; }
// Read Header // Run through the rest of the header information bool 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; //if the master has textures, we want to use them instead of the tables in the //block archives // 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[1060]; sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir); tileCache = GetNewRAppFileCache(fullBase,"tpf"); } valid = true; return true; }
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; }