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
trpgr_Archive()31 trpgr_Archive::trpgr_Archive()
32 {
33 fp = NULL;
34 ness = LittleEndian;
35 strcpy(dir,".");
36 tileCache = NULL;
37 }
38
39 // Destructor
~trpgr_Archive()40 trpgr_Archive::~trpgr_Archive()
41 {
42 if (fp)
43 fclose(fp);
44 fp = NULL;
45 if (tileCache)
46 delete tileCache;
47 }
48
GetHeaderData(char * dataPtr,int length,FILE * filehandle)49 int32 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
SetDirectory(const char * in_dir)55 void 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
OpenFile(const char * name)62 bool 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
GetNewRAppFileCache(const char * fullBase,const char * ext)100 trpgrAppFileCache* trpgr_Archive::GetNewRAppFileCache(const char *fullBase, const char *ext)
101 {
102 return new trpgrAppFileCache(fullBase,ext);
103 }
104
GetNewRImageHelper(trpgEndian ness,char * dir,const trpgMatTable & matTable,const trpgTexTable & texTable)105 trpgrImageHelper* 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
CloseFile()118 void 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 **/
ReadSubArchive(int row,int col,trpgEndian cpuNess)133 bool 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
ReadHeader()200 bool trpgr_Archive::ReadHeader()
201 {
202 return ReadHeader(true);
203 }
204
205 // Read Header
206 // Run through the rest of the header information
ReadHeader(bool readAllBlocks)207 bool 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 //if the master has textures, we want to use them instead of the tables in the
262 //block archives
263
264 // int numTiles = 0;
265 //tileTable.
266 int totalrows,totalcols;
267 trpg2dPoint mhdr_swExtents;
268 trpg2dPoint mhdr_neExtents;
269 trpg3dPoint mhdr_Origin;
270 // integrate header information from the block header.
271 header.GetExtents(mhdr_swExtents,mhdr_neExtents);
272 header.GetOrigin(mhdr_Origin);
273 header.GetBlocks(totalrows,totalcols);
274 if(readAllBlocks) {
275 for(int row=0;row<totalrows;row++) {
276 for(int col=0;col<totalcols;col++) {
277 // Read each block -- Warning, this can take a while!!!
278 ReadSubArchive( row, col, cpuNess);
279 }
280 }
281 }
282 else {
283 ReadSubArchive( 0, 0, cpuNess);//Get the first archive!
284 }
285
286 }
287 tileTable.SetCurrentBlock(-1,-1,false);
288
289 // 1.0 Compatibility
290 // If we see an older style material table, convert it to the new style
291 // This isn't terribly memory efficient, but it does work
292 if (oldMatTable.isValid())
293 materialTable = oldMatTable;
294 if (oldTexTable.isValid())
295 texTable = oldTexTable;
296
297 // Set up a tile cache, if needed
298 trpgTileTable::TileMode tileMode;
299 tileTable.GetMode(tileMode);
300 if (tileMode == trpgTileTable::Local) {
301 if (tileCache) delete tileCache;
302 char fullBase[1024];
303 sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir);
304 tileCache = GetNewRAppFileCache(fullBase,"tpf");
305 }
306
307 valid = true;
308
309 return true;
310 }
311
312 // Read Tile
313 // Read a tile into a read buffer
314 // For version 2.1 only tile with lod=0 are stored in the tile table, so an
315 // error will be returned if you try to use the table with a differrent lod.
ReadTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer & buf)316 bool trpgr_Archive::ReadTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
317 {
318 if (!isValid())
319 return false;
320
321 // Reality check the address
322 int32 numLods;
323 header.GetNumLods(numLods);
324 if (static_cast<int>(lod) >= numLods)
325 return false;
326 trpg2iPoint lodSize;
327 header.GetLodSize(lod,lodSize);
328 if (static_cast<int>(x) >= lodSize.x || static_cast<int>(y) >= lodSize.y)
329 return false;
330
331 trpgTileTable::TileMode tileMode;
332 tileTable.GetMode(tileMode);
333
334 bool status = true;
335 if (tileMode == trpgTileTable::External || tileMode == trpgTileTable::ExternalSaved) {
336 status = ReadExternalTile(x, y, lod, buf);
337
338 } else {
339 // Local tile. Figure out where it is (which file)
340 int majorVersion, minorVersion;
341 header.GetVersion(majorVersion, minorVersion);
342 if(majorVersion == 2 && minorVersion >=1)
343 {
344 // Version 2.1
345 // Tile table contains only lod 0 tiles
346 if(lod != 0)
347 status = false;
348 }
349
350 if(status)
351 {
352 trpgwAppAddress addr;
353 float zmin,zmax;
354 status = tileTable.GetTile(x,y,lod,addr,zmin,zmax);
355
356 if(status)
357 status = ReadTile(addr, buf);
358 }
359 }
360
361 return status;
362 }
363
ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer & buf)364 bool trpgr_Archive::ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
365 {
366 // Figure out the file name
367 char filename[1024];
368 int majorVer,minorVer;
369 header.GetVersion(majorVer,minorVer);
370 if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer >= TRPG_NOMERGE_VERSION_MINOR)) {
371 int blockx,blocky;
372 unsigned int denom = (1 << lod); // this should work up to lod 31
373 blockx = x/denom;
374 blocky = y/denom;
375 sprintf(filename,"%s" PATHSEPERATOR "%d" PATHSEPERATOR "%d" PATHSEPERATOR "tile_%d_%d_%d.tpt",
376 dir,blockx,blocky,x,y,lod);
377 }
378 else {
379 sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod);
380 }
381 // Open the file and read the contents
382 FILE *fp= 0;
383 try {
384 if (!(fp = osgDB::fopen(filename,"rb"))) {
385
386 throw 1;
387 }
388 // Find the file end
389 if (fseek(fp,0,SEEK_END))
390 throw 1;
391 // Note: This means tile is capped at 2 gigs
392 long pos = ftell(fp);
393 if (fseek(fp,0,SEEK_SET))
394 throw 1;
395 // Now we know the size. Read the whole file
396 buf.SetLength(pos);
397 char *data = buf.GetDataPtr();
398 if (fread(data,pos,1,fp) != 1)
399 throw 1;
400 fclose(fp);
401 fp = NULL;
402 }
403 catch (...) {
404 if (fp)
405 fclose(fp);
406 return false;
407 }
408
409 return true;
410 }
ReadTile(const trpgwAppAddress & addr,trpgMemReadBuffer & buf)411 bool trpgr_Archive::ReadTile(const trpgwAppAddress& addr, trpgMemReadBuffer &buf)
412 {
413 // Fetch the appendable file from the cache
414 trpgrAppFile *tf = tileCache->GetFile(ness,addr.file,addr.col,addr.row);
415 if (!tf)
416 return false;
417
418 // Fetch the tile
419 if (!tf->Read(&buf,addr.offset))
420 return false;
421 else
422 return true;
423 }
424
425 // Get methods
GetHeader() const426 const trpgHeader *trpgr_Archive::GetHeader() const
427 {
428 return &header;
429 }
GetMaterialTable() const430 const trpgMatTable *trpgr_Archive::GetMaterialTable() const
431 {
432 return &materialTable;
433 }
GetTexTable()434 trpgTexTable *trpgr_Archive::GetTexTable()
435 {
436 return &texTable;
437 }
GetModelTable() const438 const trpgModelTable *trpgr_Archive::GetModelTable() const
439 {
440 return &modelTable;
441 }
GetTileTable() const442 const trpgTileTable *trpgr_Archive::GetTileTable() const
443 {
444 return &tileTable;
445 }
GetLightTable() const446 const trpgLightTable *trpgr_Archive::GetLightTable() const
447 {
448 return &lightTable;
449 }
GetRangeTable() const450 const trpgRangeTable *trpgr_Archive::GetRangeTable() const
451 {
452 return &rangeTable;
453 }
GetTextStyleTable() const454 const trpgTextStyleTable *trpgr_Archive::GetTextStyleTable() const
455 {
456 return &textStyleTable;
457 }
GetSupportStyleTable() const458 const trpgSupportStyleTable *trpgr_Archive::GetSupportStyleTable() const
459 {
460 return &supportStyleTable;
461 }
GetLabelPropertyTable() const462 const trpgLabelPropertyTable *trpgr_Archive::GetLabelPropertyTable() const
463 {
464 return &labelPropertyTable;
465 }
GetEndian() const466 trpgEndian trpgr_Archive::GetEndian() const
467 {
468 return ness;
469 }
470
471 // Utility MBR routine
trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint & ll,trpg3dPoint & ur) const472 bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,trpg3dPoint &ur) const
473 {
474 if (!header.isValid())
475 return false;
476 int32 numLod;
477 header.GetNumLods(numLod);
478 trpg2iPoint maxXY;
479 header.GetLodSize(lod,maxXY);
480 if (static_cast<int>(x) >= maxXY.x || static_cast<int>(y)>= maxXY.y)
481 return false;
482
483 trpg3dPoint origin;
484 header.GetOrigin(origin);
485 trpg2dPoint size;
486 header.GetTileSize(lod,size);
487
488 ll.x = origin.x + size.x*x;
489 ll.y = origin.y + size.y*y;
490 ur.x = origin.x + size.x*(x+1);
491 ur.y = origin.y + size.y*(y+1);
492
493 // If the tiles are local, we should have Z information
494 trpgwAppAddress addr;
495 float elev_min=0.0,elev_max=0.0;
496 tileTable.GetTile(x,y,lod,addr,elev_min,elev_max);
497 ll.z = elev_min; ur.z = elev_max;
498
499 return true;
500 }
501
502 /* *****************
503 Read Image Helper
504 *****************
505 */
506
trpgrImageHelper(trpgEndian inNess,char * inDir,const trpgMatTable & inMatTable,const trpgTexTable & inTexTable,bool separateGeoTyp)507 trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir,
508 const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp)
509 {
510 Init(inNess,inDir,inMatTable,inTexTable,separateGeoTyp);
511 }
512
Init(trpgEndian inNess,char * inDir,const trpgMatTable & inMatTable,const trpgTexTable & inTexTable,bool separateGeoTyp)513 void trpgrImageHelper::Init(trpgEndian inNess,char *inDir,
514 const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp)
515 {
516 ness = inNess;
517 strcpy(dir,inDir);
518 this->separateGeoTyp = separateGeoTyp;
519 matTable = &inMatTable;
520 texTable = &inTexTable;
521
522 // Set up the texture cache
523 // It doesn't do anything until it's called anyway
524 char fullBase[1024];
525 sprintf(fullBase,"%s" PATHSEPERATOR "texFile",dir);
526 texCache = GetNewRAppFileCache(fullBase,"txf");
527 if(separateGeoTyp) {
528 sprintf(fullBase,"%s" PATHSEPERATOR "geotypFile",dir);
529 geotypCache = GetNewRAppFileCache(fullBase,"txf");
530 }
531 else {
532 geotypCache = texCache;
533 }
534
535 }
536
~trpgrImageHelper()537 trpgrImageHelper::~trpgrImageHelper()
538 {
539 if (texCache) {
540 delete texCache;
541 texCache = NULL;
542 }
543 if(separateGeoTyp && geotypCache) {
544 delete geotypCache;
545 geotypCache = NULL;
546 }
547 }
548
GetNewRAppFileCache(const char * fullBase,const char *)549 trpgrAppFileCache* trpgrImageHelper::GetNewRAppFileCache(const char *fullBase,const char* /*ext*/)
550 {
551 return new trpgrAppFileCache(fullBase,"txf");
552 }
553
GetLocalGL(const trpgTexture * tex,char * data,int32 size)554 bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
555 {
556 // Make sure the texture is Local
557 trpgTexture::ImageMode mode;
558 tex->GetImageMode(mode);
559 if (mode != trpgTexture::Local)
560 return false;
561
562 // Fetch data data
563 trpgwAppAddress addr;
564 tex->GetImageAddr(addr);
565 trpgrAppFile *af = geotypCache->GetFile(ness,addr.file,addr.col,addr.row);
566 if (!af)
567 return false;
568 if (!af->Read(data,addr.offset,0,size))
569 return false;
570
571 return true;
572 }
573
GetMipLevelLocalGL(int miplevel,const trpgTexture * tex,char * data,int32 dataSize)574 bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,char *data,int32 dataSize)
575 {
576 if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
577 return false;
578
579 // Make sure the texture is Local
580 trpgTexture::ImageMode mode;
581 tex->GetImageMode(mode);
582 if (mode != trpgTexture::Local)
583 return false;
584
585 // Fetch data data
586 trpgwAppAddress addr;
587 tex->GetImageAddr(addr);
588 trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
589 if (!af)
590 return false;
591
592 int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
593 if (!af->Read(data,addr.offset,level_offset,dataSize))
594 return false;
595
596 return true;
597 }
598
599
GetImageInfoForLocalMat(const trpgLocalMaterial * locMat,const trpgMaterial ** retMat,const trpgTexture ** retTex,int & totSize)600 bool trpgrImageHelper::GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
601 const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
602 {
603 return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize);
604 }
605
GetNthImageInfoForLocalMat(const trpgLocalMaterial * locMat,int index,const trpgMaterial ** retMat,const trpgTexture ** retTex,int & totSize)606 bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
607 const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
608 {
609 // Get the base material for the Local Material
610 int32 matSubTable,matID;
611 locMat->GetBaseMaterial(matSubTable,matID);
612 // For right now, force the subtable number to match the index.
613 // Eventually, either store multiple base materials for each local material,
614 // or overhaul this in some other fashion.
615 int numTables;
616 if (!matTable->GetNumTable(numTables))
617 return false;
618 if (index>=numTables)
619 return false;
620 if (index>0) matSubTable=index; // otherwise, leave it alone - could be nonzero
621 const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID);
622 if (!mat)
623 return false;
624
625 // Now get the texture (always the first one)
626 trpgTextureEnv texEnv;
627 int32 texID;
628 if (!mat->GetTexture(0,texID,texEnv))
629 return false;
630 const trpgTexture *tex = texTable->GetTextureRef(texID);
631 if (!tex)
632 return false;
633
634 totSize = tex->CalcTotalSize();
635
636 *retTex = tex;
637 *retMat = mat;
638 return true;
639 }
640
GetImageForLocalMat(const trpgLocalMaterial * locMat,char * data,int dataSize)641 bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize)
642 {
643 return GetNthImageForLocalMat(locMat, 0, data, dataSize);
644 }
645
GetNthImageForLocalMat(const trpgLocalMaterial * locMat,int index,char * data,int dataSize)646 bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,int index, char *data,int dataSize)
647 {
648 if (!locMat->isValid())
649 return false;
650
651 const trpgMaterial *mat;
652 const trpgTexture *tex;
653 int totSize;
654 if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
655 return false;
656
657 // Determine the type
658 trpgTexture::ImageMode imageMode;
659 tex->GetImageMode(imageMode);
660 switch (imageMode) {
661 case trpgTexture::Template:
662 {
663 // Read the image data out of the Local image (in an archive somewhere)
664 trpgwAppAddress addr;
665 if (!locMat->GetNthAddr(index,addr)) return false;
666 trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
667 if (!af)
668 return false;
669 if (!af->Read(data,addr.offset,0,dataSize))
670 return false;
671 }
672 break;
673 case trpgTexture::Global:
674 // Note: Not dealing with Global textures yet
675 return false;
676 break;
677 default:
678 // This is not a valid Local Material
679 return false;
680 };
681
682 return true;
683 }
684
GetMipLevelForLocalMat(int miplevel,const trpgLocalMaterial * locMat,char * data,int dataSize)685 bool trpgrImageHelper::GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize)
686 {
687 return GetNthImageMipLevelForLocalMat(miplevel, locMat, 0, data, dataSize);
688 }
689
GetNthImageMipLevelForLocalMat(int miplevel,const trpgLocalMaterial * locMat,int index,char * data,int dataSize)690 bool trpgrImageHelper::GetNthImageMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat, int index, char *data,int dataSize)
691 {
692 if (index>0) return false; // not yet, folks, if ever. index>1 means sensors for now.
693 if (!locMat->isValid()) return false;
694
695 const trpgMaterial *mat;
696 const trpgTexture *tex;
697 int totSize;
698 if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
699 return false;
700
701 if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
702 return false;
703
704 // Determine the type
705 trpgTexture::ImageMode imageMode;
706 tex->GetImageMode(imageMode);
707 switch (imageMode) {
708 case trpgTexture::Template:
709 {
710 // Read the image data out of the Local image (in an archive somewhere)
711 trpgwAppAddress addr;
712 if (!locMat->GetNthAddr(index,addr)) return false;
713 trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
714 if (!af) return false;
715
716 int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
717 if (!af->Read(data,addr.offset,level_offset,dataSize))
718 return false;
719 }
720 break;
721 case trpgTexture::Global:
722 // Note: Not dealing with Global textures yet
723 return false;
724 break;
725 default:
726 // This is not a valid Local Material
727 return false;
728 };
729
730 return true;
731 }
732
GetImagePath(const trpgTexture * tex,char * fullPath,int pathLen)733 bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pathLen)
734 {
735 char name[1024];
736 int nameLen=1024;
737 tex->GetName(name,nameLen);
738 nameLen = strlen(name);
739
740 if (static_cast<int>(strlen(dir)) + nameLen + 2 > pathLen)
741 return false;
742
743 sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);
744
745 return true;
746 }
747