290 lines
7.9 KiB
C++
290 lines
7.9 KiB
C++
/* ************************
|
|
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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
/* trpage_pparse.cpp
|
|
This file contains classes that can parse a TerraPage
|
|
archive for the purpose of printing it out.
|
|
*/
|
|
|
|
#include <trpage_print.h>
|
|
#include <trpage_scene.h>
|
|
|
|
/* Set up the callbacks for the scene graph parser.
|
|
In our case this is just one read helper with
|
|
a switch statement.
|
|
*/
|
|
trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelper *inImg,trpgPrintBuffer *inBuf)
|
|
{
|
|
printBuf = inBuf;
|
|
archive = inArch;
|
|
imageHelp = inImg;
|
|
|
|
// Register the readers
|
|
AddCallback(TRPG_GEOMETRY,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_GROUP,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_ATTACH,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_BILLBOARD,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_LOD,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_TRANSFORM,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_MODELREF,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_LAYER,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_LIGHT,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPG_LABEL,new ReadHelper(this,printBuf));
|
|
AddCallback(TRPGTILEHEADER,new ReadHelper(this,printBuf));
|
|
}
|
|
|
|
/* Start Children is called when the parser hits a Push
|
|
in the read buffer. We just want to indent further when
|
|
that happens.
|
|
*/
|
|
bool trpgPrintGraphParser::StartChildren(void *)
|
|
{
|
|
printBuf->IncreaseIndent();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/* End Children is called when the parser hits a Pop
|
|
in the read buffer. We just want to reduce the indent
|
|
when that happens.
|
|
*/
|
|
bool trpgPrintGraphParser::EndChildren(void *)
|
|
{
|
|
printBuf->DecreaseIndent();
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Read Helper parse method sets up the correct class depending
|
|
on the token and asks it to read and print itself.
|
|
*/
|
|
void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf)
|
|
{
|
|
trpgReadWriteable *obj = NULL;
|
|
trpgTileHeader *tileHead = NULL;
|
|
|
|
switch (tok) {
|
|
case TRPG_GEOMETRY:
|
|
obj = new trpgGeometry();
|
|
break;
|
|
case TRPG_GROUP:
|
|
obj = new trpgGroup();
|
|
break;
|
|
case TRPG_ATTACH:
|
|
obj = new trpgAttach();
|
|
break;
|
|
case TRPG_BILLBOARD:
|
|
obj = new trpgBillboard();
|
|
break;
|
|
case TRPG_LOD:
|
|
obj = new trpgLod();
|
|
break;
|
|
case TRPG_TRANSFORM:
|
|
obj = new trpgTransform();
|
|
break;
|
|
case TRPG_MODELREF:
|
|
obj = new trpgModelRef();
|
|
break;
|
|
case TRPG_LAYER:
|
|
obj = new trpgLayer();
|
|
break;
|
|
case TRPG_LIGHT:
|
|
obj = new trpgLight();
|
|
break;
|
|
case TRPG_LABEL:
|
|
obj = new trpgLabel();
|
|
break;
|
|
|
|
case TRPGTILEHEADER:
|
|
obj = tileHead = new trpgTileHeader();
|
|
break;
|
|
};
|
|
|
|
if (obj) {
|
|
if (obj->Read(buf))
|
|
obj->Print(*pBuf);
|
|
// For the tile header, do a little more work
|
|
if (tok == TRPGTILEHEADER) {
|
|
int numMat;
|
|
tileHead->GetNumLocalMaterial(numMat);
|
|
for (int i=0;i<numMat;i++) {
|
|
trpgLocalMaterial locMat;
|
|
tileHead->GetLocalMaterial(i,locMat);
|
|
const trpgMaterial *baseMat;
|
|
const trpgTexture *baseTex;
|
|
int totSize;
|
|
trpgrImageHelper *imageHelp = parse->GetImageHelp();
|
|
int numImages=1;
|
|
locMat.GetNumLocals(numImages);
|
|
for (int imgN=0;imgN<numImages;imgN++) {
|
|
// read all the images for each local material
|
|
imageHelp->GetNthImageInfoForLocalMat(&locMat,imgN,&baseMat,&baseTex,totSize);
|
|
|
|
// Fetch the whole image
|
|
{
|
|
char *pixels = new char[totSize];
|
|
bool failed = false;
|
|
try {
|
|
failed = !imageHelp->GetNthImageForLocalMat(&locMat,imgN,pixels,totSize);
|
|
}
|
|
catch (...) {
|
|
failed = true;
|
|
}
|
|
if (failed) {
|
|
fprintf(stderr,"Failed to read local image %d from local material %d.\n",imgN,i);
|
|
} else
|
|
fprintf(stderr,"Read local image %d from local material %d successfully.\n",imgN,i);
|
|
delete [] pixels;
|
|
}
|
|
|
|
// Fetch the individual mipmap levels
|
|
{
|
|
int numMipmap;
|
|
bool hasMipmap;
|
|
baseTex->GetIsMipmap(hasMipmap);
|
|
numMipmap = hasMipmap ? baseTex->CalcNumMipmaps() : 0;
|
|
for (int j=1;j<numMipmap;j++) {
|
|
//int mipOffset = (const_cast<trpgTexture *>(baseTex))->MipLevelOffset(j);
|
|
int mipSize = (const_cast<trpgTexture *>(baseTex))->MipLevelSize(j);
|
|
if (mipSize) {
|
|
char *pixels = new char[mipSize];
|
|
bool failed = false;
|
|
try {
|
|
failed = !imageHelp->GetNthImageMipLevelForLocalMat(j,&locMat,imgN,pixels,mipSize);
|
|
}
|
|
catch (...) {
|
|
failed = true;
|
|
}
|
|
if (failed)
|
|
fprintf(stderr,"Failed to read mipmap level %d for local image %d from local material %d.\n",j,imgN,i);
|
|
else
|
|
fprintf(stderr,"Read mipmap level %d for local image %d from local material %d.\n",j,imgN,i);
|
|
delete [] pixels;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
delete obj;
|
|
}
|
|
|
|
// Need to return non-zero. Otherwise it's interpreted as an error
|
|
return (void *)1;
|
|
}
|
|
|
|
// The following routine is not compiled if there's no _splitpath
|
|
#ifdef _splitpath
|
|
/* This is a convenience function to print out the contents
|
|
of an entire TerraPage archive.
|
|
|
|
There are two versions of this function. The first takes
|
|
a file name and the second an opened archive where the header
|
|
has already been read.
|
|
*/
|
|
bool trpgPrintArchive(char *filename,trpgPrintBuffer &pBuf,int flags)
|
|
{
|
|
trpgr_Archive archive;
|
|
|
|
// Break path apart so we can find the directory
|
|
char drive[100],dir[1024],fname[1024],ext[1024];
|
|
_splitpath(filename,drive,dir,fname,ext);
|
|
|
|
char rname[1024],baseDir[1024];
|
|
sprintf(baseDir,"%s%s",drive,dir);
|
|
sprintf(rname,"%s%s",fname,ext);
|
|
|
|
if (!*baseDir) strcpy(baseDir,".");
|
|
archive.SetDirectory(baseDir);
|
|
if (!archive.OpenFile(rname)) {
|
|
fprintf(stdout,"Failed to open archive.\n");
|
|
return false;
|
|
}
|
|
if (!archive.ReadHeader()) {
|
|
fprintf(stdout,"Failed to read header.\n");
|
|
return false;
|
|
}
|
|
|
|
bool status = trpgPrintArchive(&archive,pBuff,flags);
|
|
return status;
|
|
}
|
|
#endif
|
|
|
|
bool trpgPrintArchive(trpgr_Archive *archive,trpgPrintBuffer &pBuf,int flags)
|
|
{
|
|
char ls[1024];
|
|
|
|
if (!archive->isValid()) return false;
|
|
|
|
pBuf.prnLine("====Header Structures====");
|
|
|
|
// Print out the header portion
|
|
archive->GetHeader()->Print(pBuf);
|
|
archive->GetMaterialTable()->Print(pBuf);
|
|
archive->GetTexTable()->Print(pBuf);
|
|
archive->GetModelTable()->Print(pBuf);
|
|
archive->GetTileTable()->Print(pBuf);
|
|
archive->GetLightTable()->Print(pBuf);
|
|
archive->GetRangeTable()->Print(pBuf);
|
|
archive->GetTextStyleTable()->Print(pBuf);
|
|
archive->GetSupportStyleTable()->Print(pBuf);
|
|
archive->GetLabelPropertyTable()->Print(pBuf);
|
|
pBuf.prnLine();
|
|
|
|
// Read the local images and do the math for the templates
|
|
|
|
// Now do the tiles
|
|
if (!archive->isValid()) return false;
|
|
|
|
// Parser that prints out a tile scene graph
|
|
trpgrImageHelper imageHelp(archive->GetEndian(),archive->getDir(),*archive->GetMaterialTable(),
|
|
*archive->GetTexTable());
|
|
trpgPrintGraphParser parser(archive,&imageHelp,&pBuf);
|
|
|
|
pBuf.prnLine("====Tile Data====");
|
|
int nl,x,y;
|
|
trpgMemReadBuffer buf(archive->GetEndian());
|
|
// Iterate over the terrain lods
|
|
int numLod;
|
|
archive->GetHeader()->GetNumLods(numLod);
|
|
trpg2iPoint tileSize;
|
|
for (nl=0;nl<numLod;nl++) {
|
|
archive->GetHeader()->GetLodSize(nl,tileSize);
|
|
// Iterate over the tiles
|
|
for (x=tileSize.x-1;x>=0;x--)
|
|
for (y=0;y<tileSize.y;y++) {
|
|
sprintf(ls,"Tile (lod) (x,y) = (%d) (%d,%d)",nl,x,y);
|
|
pBuf.prnLine(ls);
|
|
if (archive->ReadTile(x,y,nl,buf)) {
|
|
if (flags & TRPGPRN_BODY) {
|
|
pBuf.IncreaseIndent();
|
|
// Parse it (also prints it
|
|
parser.Parse(buf);
|
|
pBuf.DecreaseIndent();
|
|
}
|
|
} else
|
|
pBuf.prnLine(" Couldn't read tile.");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|