root/OpenSceneGraph/trunk/src/osgPlugins/txp/trpage_rarchive.cpp @ 9124

Revision 9124, 21.8 kB (checked in by robert, 6 years ago)

From Michael Platings, Converted std::fstream/ifstream/ofstream to osgDB::fstream/ifstream/ofstream and
fopen to osgDB::fopen to facilitate support for wide character filenames using UT8 encoding.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* ************************
2   Copyright Terrain Experts Inc.
3   Terrain Experts Inc (TERREX) reserves all rights to this source code
4   unless otherwise specified in writing by the President of TERREX.
5   This copyright may be updated in the future, in which case that version
6   supercedes this one.
7   -------------------
8   Terrex Experts Inc.
9   4400 East Broadway #314
10   Tucson, AZ  85711
11   info@terrex.com
12   Tel: (520) 323-7990
13   ************************
14   */
15
16#include <osgDB/FileUtils>
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21
22/* trpage_rarchive.cpp
23   This source file implements the methods for a trpgr_Archive.
24   The Read Archive is used to read a paging archive from disk.
25*/
26
27#include <trpage_read.h>
28#include <trpage_compat.h>
29
30// Constructor
31trpgr_Archive::trpgr_Archive()
32{
33    fp = NULL;
34    ness = LittleEndian;
35    strcpy(dir,".");
36    tileCache = NULL;
37}
38
39// Destructor
40trpgr_Archive::~trpgr_Archive()
41{
42    if (fp)
43        fclose(fp);
44    fp = NULL;
45    if (tileCache)
46        delete tileCache;
47}
48
49int32 trpgr_Archive::GetHeaderData(char *dataPtr, int length, FILE *filehandle)
50{
51    return fread(dataPtr,1,length,filehandle);
52}
53
54// Set the directory where the archive is
55void trpgr_Archive::SetDirectory(const char *in_dir)
56{
57    strncpy(dir,in_dir,1024);
58}
59
60// Open File
61// Open the given file and look for the file specific info
62bool trpgr_Archive::OpenFile(const char *name)
63{
64    char file[1024];
65    sprintf(file,"%s" PATHSEPERATOR "%s",dir,name);
66
67    CloseFile();
68
69    if (!(fp = osgDB::fopen(file,"rb")))
70        return false;
71
72    // Look for a magic # and endianness
73    int32 magic;
74    if (fread(&magic,sizeof(int32),1,fp) != 1)
75        return false;
76
77    headerRead = false;
78
79    // Figure out the endianness from the magic number
80    trpgEndian cpuNess = trpg_cpu_byte_order();
81    if (magic == GetMagicNumber()) {
82        ness = cpuNess;
83        return true;
84    }
85    if (trpg_byteswap_int(magic) == GetMagicNumber()) {
86        if (cpuNess == LittleEndian)
87            ness = BigEndian;
88        else
89            ness = LittleEndian;
90        return true;
91    }
92    if (magic != GetMagicNumber())
93        return false;
94
95    // Not one of our files
96    return false;
97}
98
99// Get new reading app file cache
100trpgrAppFileCache* trpgr_Archive::GetNewRAppFileCache(const char *fullBase, const char *ext)
101{
102    return new trpgrAppFileCache(fullBase,ext);
103}
104
105trpgrImageHelper* trpgr_Archive::GetNewRImageHelper(trpgEndian ness,char *dir,const trpgMatTable &matTable,const trpgTexTable &texTable)
106{
107    bool separateGeo = false;
108    int majorVer,minorVer;
109    GetHeader()->GetVersion(majorVer,minorVer);
110    if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) {
111        separateGeo = true;
112    }
113    return new trpgrImageHelper(ness,dir,matTable,texTable,separateGeo);
114}
115
116// Close File
117// Close the currently open file
118void trpgr_Archive::CloseFile()
119{
120    if (fp)
121        fclose(fp);
122    fp = NULL;
123    if (tileCache)
124        delete tileCache;
125    tileCache = NULL;
126}
127
128/**
129 * Read a sub block from a 2.2 TXP database. This can be called any time after ReadHeader is called
130 * if ReadHeader is called with the false parameter to specify not to read all the sub-archives.
131 * This can make a huge improvement in startup time for loading a very large archive with many blocks.
132 **/
133bool trpgr_Archive::ReadSubArchive(int row, int col, trpgEndian cpuNess)
134{
135    int ret;
136    trpgHeader blockHeader;
137    trpgr_Parser bparser;
138   
139    char blockpath[1024];
140    //open the block archive
141    // the block archive will be in the base dir + \\cols\\row\\archive.txp
142    sprintf(blockpath,"%s%s%d%s%d%sarchive.txp",dir,PATHSEPERATOR,col,PATHSEPERATOR,row,PATHSEPERATOR);
143    FILE *bfp = osgDB::fopen(blockpath,"rb");
144    if(!bfp) {
145        return false;
146    }
147    // Look for a magic # and endianness
148    int32 bmagic;
149    if (fread(&bmagic,sizeof(int32),1,bfp) != 1)
150        return false;
151    // The block archive will always be the same endianness as the master
152    if ( (bmagic != GetMagicNumber()) && (trpg_byteswap_int(bmagic) != GetMagicNumber()) )
153        return false;
154   
155    int32 bheaderSize=0;
156    if (fread(&bheaderSize,sizeof(int32),1,bfp) != 1)
157        return false;
158    if (ness != cpuNess)
159        bheaderSize = trpg_byteswap_int(bheaderSize);
160    int bheadLen = bheaderSize;
161    if (bheadLen < 0) 
162        return false;
163
164    // Read in the header whole
165    trpgMemReadBuffer bbuf(ness);
166    bbuf.SetLength(bheadLen);
167    char *bdata = bbuf.GetDataPtr();
168    if ((ret = GetHeaderData(bdata,bheadLen,bfp)) != bheadLen) 
169        return false;
170    //keep track of where this came from in the master table.       
171    tileTable.SetCurrentBlock(row,col,true);
172    texTable.SetCurrentBlock(row,col);
173   
174    bparser.AddCallback(TRPGHEADER,&blockHeader);
175    bparser.AddCallback(TRPGMATTABLE,&materialTable);    // Went back to oldest style for 2.0
176    //if(!headerHasTexTable) {
177    bparser.AddCallback(TRPGTEXTABLE2,&texTable);            // Added for 2.0
178    //}
179    bparser.AddCallback(TRPGMODELTABLE,&modelTable);
180    bparser.AddCallback(TRPGLIGHTTABLE,&lightTable);                // Added for 2.0
181    bparser.AddCallback(TRPGRANGETABLE,&rangeTable);                // Added for 2.0
182    bparser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable);                // Added for 2.1
183    bparser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable);       
184    bparser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable);       
185    // Don't read the tile table for v1.0 archives
186    // It's only really used for 2.0 archives
187    bparser.AddCallback(TRPGTILETABLE2,&tileTable);
188
189    // Parse the buffer
190    if (!bparser.Parse(bbuf))
191        return false;
192    //close the block archive
193    fclose(bfp);
194
195    tileTable.SetCurrentBlock(-1,-1,false);
196
197    return true;
198}
199
200bool trpgr_Archive::ReadHeader()
201{
202    return ReadHeader(true);
203}
204
205// Read Header
206// Run through the rest of the header information
207bool trpgr_Archive::ReadHeader(bool readAllBlocks)
208{
209    int ret;
210
211    if (!fp || headerRead)
212        return false;
213
214    headerRead = true;
215
216    // Next int64 should be the header size
217    trpgEndian cpuNess = trpg_cpu_byte_order();
218    int32 headerSize;
219    if (fread(&headerSize,sizeof(int32),1,fp) != 1)
220        return false;
221    if (ness != cpuNess)
222        headerSize = trpg_byteswap_int(headerSize);
223    int headLen = headerSize;
224    if (headLen < 0) 
225        return false;
226
227    // Read in the header whole
228    trpgMemReadBuffer buf(ness);
229    buf.SetLength(headLen);
230    char *data = buf.GetDataPtr();
231    if ((ret = GetHeaderData(data,headLen,fp)) != headLen) 
232        return false;
233
234    // Set up a parser
235    // Catch the tables we need for the archive
236    trpgMatTable1_0 oldMatTable;
237    trpgTexTable1_0 oldTexTable;
238    trpgr_Parser parser;
239    parser.AddCallback(TRPGHEADER,&header);
240    parser.AddCallback(TRPGMATTABLE,&materialTable);    // Went back to oldest style for 2.0
241    parser.AddCallback(TRPGMATTABLE2,&oldMatTable);     // Added 11-14-98 (1.0 material table)
242    parser.AddCallback(TRPGTEXTABLE,&oldTexTable);
243    parser.AddCallback(TRPGTEXTABLE2,&texTable);            // Added for 2.0
244    parser.AddCallback(TRPGMODELTABLE,&modelTable);
245    parser.AddCallback(TRPGLIGHTTABLE,&lightTable);                // Added for 2.0
246    parser.AddCallback(TRPGRANGETABLE,&rangeTable);                // Added for 2.0
247    parser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable);                // Added for 2.1
248    parser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable);       
249    parser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable);       
250    // Don't read the tile table for v1.0 archives
251    // It's only really used for 2.0 archives
252    parser.AddCallback(TRPGTILETABLE2,&tileTable);
253
254    // Parse the buffer
255    if (!parser.Parse(buf))
256        return false;
257
258    if(header.GetIsMaster())
259    {
260        // bool firstBlock = true;
261        bool headerHasTexTable = false;
262        //if the master has textures, we want to use them instead of the tables in the
263        //block archives
264        int numTex = 0;
265        texTable.GetNumTextures(numTex);
266        if(numTex)
267            headerHasTexTable = true;
268        // int numTiles = 0;
269        //tileTable.
270        int totalrows,totalcols;
271        trpg2dPoint mhdr_swExtents;
272        trpg2dPoint mhdr_neExtents;
273        trpg3dPoint mhdr_Origin;
274        // integrate header information from the block header.
275        header.GetExtents(mhdr_swExtents,mhdr_neExtents);
276        header.GetOrigin(mhdr_Origin);
277        header.GetBlocks(totalrows,totalcols);
278        if(readAllBlocks) {
279            for(int row=0;row<totalrows;row++) {
280                for(int col=0;col<totalcols;col++) {
281                    // Read each block -- Warning, this can take a while!!!
282                    ReadSubArchive( row, col, cpuNess);
283                }
284            }
285        }
286        else {
287            ReadSubArchive( 0, 0, cpuNess);//Get the first archive!
288        }
289
290    }
291    tileTable.SetCurrentBlock(-1,-1,false);
292
293    // 1.0 Compatibility
294    // If we see an older style material table, convert it to the new style
295    // This isn't terribly memory efficient, but it does work
296    if (oldMatTable.isValid())
297        materialTable = oldMatTable;
298    if (oldTexTable.isValid())
299        texTable = oldTexTable;
300
301    // Set up a tile cache, if needed
302    trpgTileTable::TileMode tileMode;
303    tileTable.GetMode(tileMode);
304    if (tileMode == trpgTileTable::Local) {
305        if (tileCache)  delete tileCache;
306        char fullBase[1024];
307        sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir);
308        tileCache = GetNewRAppFileCache(fullBase,"tpf");
309    }
310
311    valid = true;
312
313    return true;
314}
315
316// Read Tile
317// Read a tile into a read buffer
318// For version 2.1 only  tile with lod=0 are stored in the tile table, so an
319// error will be returned if you try to use the table with a differrent lod.
320bool trpgr_Archive::ReadTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
321{
322    if (!isValid())
323        return false;
324
325    // Reality check the address
326    int32 numLods;
327    header.GetNumLods(numLods);
328    if (static_cast<int>(lod) >= numLods)
329        return false;
330    trpg2iPoint lodSize;
331    header.GetLodSize(lod,lodSize);
332    if (static_cast<int>(x) >= lodSize.x || static_cast<int>(y) >= lodSize.y)
333        return false;
334
335    trpgTileTable::TileMode tileMode;
336    tileTable.GetMode(tileMode);
337
338    bool status = true;
339    if (tileMode == trpgTileTable::External || tileMode == trpgTileTable::ExternalSaved) {
340        status = ReadExternalTile(x, y, lod, buf);
341       
342    } else {
343        // Local tile.  Figure out where it is (which file)
344        int majorVersion, minorVersion;
345        header.GetVersion(majorVersion, minorVersion);
346        if(majorVersion == 2 && minorVersion >=1)
347        {
348            // Version 2.1
349            // Tile table contains only lod 0 tiles
350            if(lod != 0)
351                status = false;
352        }
353
354        if(status)
355        {
356            trpgwAppAddress addr;
357            float zmin,zmax;
358            status = tileTable.GetTile(x,y,lod,addr,zmin,zmax);
359
360            if(status)
361                status = ReadTile(addr, buf);
362        }
363    }
364
365    return status;
366}
367
368bool trpgr_Archive::ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
369{
370    // Figure out the file name
371    char filename[1024];
372    int majorVer,minorVer;
373    header.GetVersion(majorVer,minorVer);
374    if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer >= TRPG_NOMERGE_VERSION_MINOR)) {
375        int blockx,blocky;
376        unsigned int denom = (1 << lod); // this should work up to lod 31
377        blockx = x/denom;
378        blocky = y/denom;
379        sprintf(filename,"%s" PATHSEPERATOR "%d" PATHSEPERATOR "%d" PATHSEPERATOR "tile_%d_%d_%d.tpt",
380                dir,blockx,blocky,x,y,lod);
381    }
382    else {
383        sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod);
384    }
385    // Open the file and read the contents
386    FILE *fp= 0;
387    try {
388        if (!(fp = osgDB::fopen(filename,"rb")))  {
389
390            throw 1;
391        }
392        // Find the file end
393        if (fseek(fp,0,SEEK_END)) 
394            throw 1;
395        // Note: This means tile is capped at 2 gigs
396        long pos = ftell(fp);
397        if (fseek(fp,0,SEEK_SET))
398            throw 1;
399        // Now we know the size.  Read the whole file
400        buf.SetLength(pos);
401        char *data = buf.GetDataPtr();
402        if (fread(data,pos,1,fp) != 1)
403            throw 1;
404        fclose(fp);
405        fp = NULL;
406    }
407    catch (...) {
408        if (fp)
409            fclose(fp);
410        return false;
411    }
412
413    return true;
414}
415bool trpgr_Archive::ReadTile(const trpgwAppAddress& addr, trpgMemReadBuffer &buf)
416{
417    // Fetch the appendable file from the cache
418    trpgrAppFile *tf = tileCache->GetFile(ness,addr.file,addr.col,addr.row);
419    if (!tf) 
420        return false;
421
422    // Fetch the tile
423    if (!tf->Read(&buf,addr.offset))
424        return false;
425    else
426        return true;
427}
428
429// Get methods
430const trpgHeader *trpgr_Archive::GetHeader() const
431{
432    return &header;
433}
434const trpgMatTable *trpgr_Archive::GetMaterialTable() const
435{
436    return &materialTable;
437}
438trpgTexTable *trpgr_Archive::GetTexTable()
439{
440    return &texTable;
441}
442const trpgModelTable *trpgr_Archive::GetModelTable() const
443{
444    return &modelTable;
445}
446const trpgTileTable *trpgr_Archive::GetTileTable() const
447{
448    return &tileTable;
449}
450const trpgLightTable *trpgr_Archive::GetLightTable() const
451{
452    return &lightTable;
453}
454const trpgRangeTable *trpgr_Archive::GetRangeTable() const
455{
456    return &rangeTable;
457}
458const trpgTextStyleTable *trpgr_Archive::GetTextStyleTable() const
459{
460    return &textStyleTable;
461}
462const trpgSupportStyleTable *trpgr_Archive::GetSupportStyleTable() const
463{
464    return &supportStyleTable;
465}
466const trpgLabelPropertyTable *trpgr_Archive::GetLabelPropertyTable() const
467{
468    return &labelPropertyTable;
469}
470trpgEndian trpgr_Archive::GetEndian() const
471{
472    return ness;
473}
474
475// Utility MBR routine
476bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,trpg3dPoint &ur) const
477{
478    if (!header.isValid())
479        return false;
480    int32 numLod;
481    header.GetNumLods(numLod);
482    trpg2iPoint maxXY;
483    header.GetLodSize(lod,maxXY);
484    if (static_cast<int>(x) >= maxXY.x || static_cast<int>(y)>= maxXY.y)
485        return false;
486
487    trpg3dPoint origin;
488    header.GetOrigin(origin);
489    trpg2dPoint size;
490    header.GetTileSize(lod,size);
491
492    ll.x = origin.x + size.x*x;
493    ll.y = origin.y + size.y*y;
494    ur.x = origin.x + size.x*(x+1);
495    ur.y = origin.y + size.y*(y+1);
496
497    // If the tiles are local, we should have Z information
498    trpgwAppAddress addr;
499    float elev_min=0.0,elev_max=0.0;
500    tileTable.GetTile(x,y,lod,addr,elev_min,elev_max);
501    ll.z = elev_min;  ur.z = elev_max;
502
503    return true;
504}
505
506/* *****************
507   Read Image Helper
508   *****************
509   */
510
511trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir,
512                                   const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp)
513{
514    Init(inNess,inDir,inMatTable,inTexTable,separateGeoTyp);
515}
516
517void trpgrImageHelper::Init(trpgEndian inNess,char *inDir,
518                            const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp)
519{
520    ness = inNess;
521    strcpy(dir,inDir);
522    this->separateGeoTyp = separateGeoTyp;
523    matTable = &inMatTable;
524    texTable = &inTexTable;
525
526    // Set up the texture cache
527    // It doesn't do anything until it's called anyway
528    char fullBase[1024];
529    sprintf(fullBase,"%s" PATHSEPERATOR "texFile",dir);
530    texCache = GetNewRAppFileCache(fullBase,"txf");
531    if(separateGeoTyp) {
532        sprintf(fullBase,"%s" PATHSEPERATOR "geotypFile",dir);
533        geotypCache = GetNewRAppFileCache(fullBase,"txf");
534    }
535    else {
536        geotypCache = texCache;
537    }
538       
539}
540
541trpgrImageHelper::~trpgrImageHelper()
542{
543    if (texCache) {
544        delete texCache;
545        texCache = NULL;
546    }
547    if(separateGeoTyp && geotypCache) {
548        delete geotypCache;
549        geotypCache = NULL;
550    }
551}
552
553trpgrAppFileCache* trpgrImageHelper::GetNewRAppFileCache(const char *fullBase,const char* /*ext*/)
554{
555    return new trpgrAppFileCache(fullBase,"txf");
556}
557
558bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
559{
560    // Make sure the texture is Local
561    trpgTexture::ImageMode mode;
562    tex->GetImageMode(mode);
563    if (mode != trpgTexture::Local)
564        return false;
565
566    // Fetch data data
567    trpgwAppAddress addr;
568    tex->GetImageAddr(addr);
569    trpgrAppFile *af = geotypCache->GetFile(ness,addr.file,addr.col,addr.row);
570    if (!af)
571        return false;
572    if (!af->Read(data,addr.offset,0,size))
573        return false;
574
575    return true;
576}
577
578bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,char *data,int32 dataSize)
579{
580    if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
581        return false;
582
583    // Make sure the texture is Local
584    trpgTexture::ImageMode mode;
585    tex->GetImageMode(mode);
586    if (mode != trpgTexture::Local)
587        return false;
588
589    // Fetch data data
590    trpgwAppAddress addr;
591    tex->GetImageAddr(addr);
592    trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
593    if (!af)
594        return false;
595
596    int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
597    if (!af->Read(data,addr.offset,level_offset,dataSize))
598        return false;
599
600    return true;
601}
602
603
604bool trpgrImageHelper::GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
605                                               const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
606{
607    return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize);
608}
609
610bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
611                                                  const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
612{
613    // Get the base material for the Local Material
614    int32 matSubTable,matID;
615    locMat->GetBaseMaterial(matSubTable,matID);
616    // For right now, force the subtable number to match the index.
617    // Eventually, either store multiple base materials for each local material,
618    // or overhaul this in some other fashion.
619    int numTables;
620    if (!matTable->GetNumTable(numTables))
621        return false;
622    if (index>=numTables)
623        return false;
624    if (index>0) matSubTable=index; // otherwise, leave it alone - could be nonzero
625    const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID);
626    if (!mat) 
627        return false;
628
629    // Now get the texture (always the first one)
630    trpgTextureEnv texEnv;
631    int32 texID;
632    if (!mat->GetTexture(0,texID,texEnv))
633        return false;
634    const trpgTexture *tex = texTable->GetTextureRef(texID);
635    if (!tex) 
636        return false;
637
638    totSize = tex->CalcTotalSize();
639
640    *retTex = tex;
641    *retMat = mat;
642    return true;
643}
644
645bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize)
646{
647    return GetNthImageForLocalMat(locMat, 0, data, dataSize);
648}
649
650bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,int index, char *data,int dataSize)
651{
652    if (!locMat->isValid())
653        return false;
654
655    const trpgMaterial *mat;
656    const trpgTexture *tex;
657    int totSize;
658    if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
659        return false;
660
661    // Determine the type
662    trpgTexture::ImageMode imageMode;
663    tex->GetImageMode(imageMode);
664    switch (imageMode) {
665    case trpgTexture::Template:
666    {
667        // Read the image data out of the Local image (in an archive somewhere)
668        trpgwAppAddress addr;
669        if (!locMat->GetNthAddr(index,addr)) return false;
670        trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
671        if (!af) 
672            return false;
673        if (!af->Read(data,addr.offset,0,dataSize))
674            return false;
675    }
676    break;
677    case trpgTexture::Global:
678        // Note: Not dealing with Global textures yet
679        return false;
680        break;
681    default:
682        // This is not a valid Local Material
683        return false;
684    };
685
686    return true;
687}
688
689bool trpgrImageHelper::GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize)
690{
691    return GetNthImageMipLevelForLocalMat(miplevel, locMat, 0, data, dataSize);
692}
693
694bool trpgrImageHelper::GetNthImageMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat, int index, char *data,int dataSize)
695{
696    if (index>0) return false; // not yet, folks, if ever.  index>1 means sensors for now.
697    if (!locMat->isValid()) return false;
698
699    const trpgMaterial *mat;
700    const trpgTexture *tex;
701    int totSize;
702    if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
703        return false;
704
705    if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
706        return false;
707
708    // Determine the type
709    trpgTexture::ImageMode imageMode;
710    tex->GetImageMode(imageMode);
711    switch (imageMode) {
712    case trpgTexture::Template:
713    {
714        // Read the image data out of the Local image (in an archive somewhere)
715        trpgwAppAddress addr;
716        if (!locMat->GetNthAddr(index,addr)) return false;
717        trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
718        if (!af)  return false;
719
720        int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
721        if (!af->Read(data,addr.offset,level_offset,dataSize))
722            return false;
723    }
724    break;
725    case trpgTexture::Global:
726        // Note: Not dealing with Global textures yet
727        return false;
728        break;
729    default:
730        // This is not a valid Local Material
731        return false;
732    };
733
734    return true;
735}
736
737bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pathLen)
738{
739    char name[1024];
740    int nameLen=1024;
741    tex->GetName(name,nameLen);
742    nameLen = strlen(name);
743
744    if (static_cast<int>(strlen(dir)) + nameLen + 2 > pathLen)
745        return false;
746
747    sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);
748
749    return true;
750}
Note: See TracBrowser for help on using the browser.