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