From Terrex and Andrew Sampsom and Don Tidrow and Robert Osfield,

email comments from Andew Sampson,

"I've contacted Terrex, and obtained the 2.2 version
of their trpage library.  The library included a
fork of OSG 0.9.8's txp plugin, modified to load 2.1+
txp DBs.

I've done the work of incorporating the changes made
to OSG's txp plugin since 0.9.8 into Terrex's fork.
The forked version is now up-to-date with the changes
made to OSG 0.9.9 and 1.0.

Terrex made a lot of changes (especially differences
in whitespace), so the diff between the forked version

and OSG 1.0's txp plugin is yucky.  I did my best, but

keep in mind that this is the result of a 4-way merge
(kinda... terrex-0.9.8, stock-0.9.8, stock-0.9.9,
stock-1.0).

I really want to see this forked version merged back
into the main OSG branch.  The new features offered by

this version of the plugin (2.1+ support, variable
LOD support, bug fixes) are worth the trouble."

--

Don Tidrow then took this code and added his work.

--

Robert Osfield then fixed all the warnings that abound in the trpage code base.
This commit is contained in:
Robert Osfield 2006-06-27 10:07:42 +00:00
parent 240fc9ebee
commit 261f4a3b1c
50 changed files with 11399 additions and 8113 deletions

View File

@ -3,9 +3,12 @@
#include <osg/Node>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/BoundingSphere>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osg/io_utils>
#include <iostream>
#include <sstream>
#include "ReaderWriterTXP.h"
#include "TXPNode.h"
@ -16,6 +19,13 @@
#define ReaderWriterTXPERROR(s) osg::notify(osg::NOTICE) << "txp::ReaderWriterTXP::" << (s) << " error: "
namespace
{
char gbuf[2048];
}
using namespace txp;
int ReaderWriterTXP::_archiveId = 0;
@ -29,7 +39,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
if (strncmp(name.c_str(),"archive",7)==0)
{
std::string fileName = osgDB::findDataFile( file, options );
if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
if ( fileName.empty() )
return ReadResult::FILE_NOT_FOUND;
osg::ref_ptr<TXPNode> txpNode = new TXPNode;
txpNode->setArchiveName(fileName);
@ -45,7 +56,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
{
int id = _archiveId++;
archive->setId(id);
txpNode->setArchive(getArchive(id,osgDB::getFilePath(fileName)));
// txpNode->setArchive(getArchive(id,osgDB::getFilePath(fileName)));
getArchive(id,osgDB::getFilePath(fileName));
}
return txpNode.get();
}
@ -56,35 +68,92 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
}
// We load tileLOD_XxY_ID.txp
if (strncmp(name.c_str(),"tile",4)==0)
else if (strncmp(name.c_str(),"tile",4)==0)
{
int x,y,lod;
unsigned int id;
sscanf(name.c_str(),"tile%d_%dx%d_%d",&lod,&x,&y,&id);
TXPArchive* archive = getArchive(id,osgDB::getFilePath(file));
// The way this is done a 'tile' should only be created for lod 0 only,
// something is wrong if this is no the case
if(lod != 0)
{
ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "paged 'tile' should be at lod 0" << std::endl;
return ReadResult::ERROR_IN_READING_FILE;
}
trpgEndian endian = archive->GetEndian();
archive->ReadSubArchive( 0, 0, endian);
archive->ReadSubArchive( y, x, endian);
// std::cout << "Attempted " << x << " " << y << std::endl;
TXPArchive::TileInfo info;
if (!archive->getTileInfo(x,y,lod,info))
return ReadResult::ERROR_IN_READING_FILE;
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,x,y,lod,archive);
std::vector<TXPArchive::TileLocationInfo> childrenLoc;
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,x,y,lod,archive, childrenLoc);
tileContent->setName("TileContent");
bool asChildren = false;
std::string childrenInfoStr;
int numLods = archive->getNumLODs();
int majorVersion, minorVersion;
archive->GetVersion(majorVersion, minorVersion);
if(majorVersion ==2 && minorVersion >=1)
{
// Version 2.1 and over
// The tile table only contains lod 0 and the children
// info are stored in its parent. SO if we do not want
// to be forced to reparse the parent we need to save that
// info. For now we just add it to the node name
if(childrenLoc.size() > 0)
{
asChildren = true;
createChildrenLocationString(childrenLoc, childrenInfoStr);
}
}
else
{
if (lod < (numLods-1))
asChildren = true;
}
if (asChildren)
{
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
archive->getDir(),
lod,
x,
y,
archive->getId()
);
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d",
archive->getDir(),
lod,
x,
y,
archive->getId());
strcat(pagedLODfile, childrenInfoStr.c_str());
strcat(pagedLODfile, ".txp");
// there are tile sets which do not maintain the z extents in
// the tile table. This attempt to address the issue by using
// the geometry bounding sphere. The downside is that this is
// not coupled to the generation and may result in runtime cracks
if (info.center.z() == 0)
{
osg::BoundingSphere bSphere = tileContent->getBound();
info.center.z() = bSphere.center().z();
info.radius = bSphere.radius();
}
osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
// not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
// note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
pagedLOD->setFileName(1,pagedLODfile);
pagedLOD->setRange(1,0,info.minRange);
@ -110,111 +179,379 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
return tileContent.get();
}
// We load subtilesLOD_XxY_ID.txp
if (strncmp(name.c_str(),"sub",3)==0)
// For 2.0 and lower we load subtilesLOD_XxY_ID.txp
// For 2.1 and over we load subtilesLOD_XxY_ID_NBCHILD_{X_Y_FID_FOFFSET_ZMIN_ZMAX_X_Y_ADDR ....}.txp
else if (strncmp(name.c_str(),"sub",3)==0)
{
int x,y,lod;
unsigned int id;
sscanf(name.c_str(),"subtiles%d_%dx%d_%d",&lod,&x,&y,&id);
TXPArchive* archive = getArchive(id,osgDB::getFilePath(file));
int majorVersion, minorVersion;
archive->GetVersion(majorVersion, minorVersion);
std::vector<TXPArchive::TileLocationInfo> childrenLoc;
osg::ref_ptr<osg::Group> subtiles = new osg::Group;
int numLods = archive->getNumLODs();
int sizeX, sizeY;
archive->getLODSize(lod+1,sizeX,sizeY);
const trpgHeader* header = archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
TXPArchive::TileInfo parentInfo;
archive->getTileInfo(x,y,lod,parentInfo);
for (int ix = 0; ix < 2; ix++)
if(majorVersion == 2 && minorVersion >= 1)
{
for (int iy = 0; iy < 2; iy++)
int nbChild;
sscanf(name.c_str(),"subtiles%d_%dx%d_%d_%d",&lod,&x,&y,&id, &nbChild);
std::vector<TXPArchive::TileLocationInfo> locs;
bool status = true;
status = extractChildrenLocations(name, lod, locs, nbChild);
if(majorVersion >= TRPG_NOMERGE_VERSION_MAJOR && minorVersion >=TRPG_NOMERGE_VERSION_MINOR && archive->GetHeader()->GetIsMaster())
{
for(int idx=0;idx<nbChild;idx++)
{
//figure out the block row/col
int blockx,blocky;
unsigned int denom = (1 << locs[idx].lod); // this should work up to lod 31
blockx = locs[idx].x/denom;
blocky = locs[idx].y/denom;
locs[idx].addr.col = blockx;
locs[idx].addr.row = blocky;
}
}
if(!status)
{
int tileX = x*2+ix;
int tileY = y*2+iy;
int tileLOD = lod+1;
ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "'subtile' filename children parsing failed " << std::endl;
return ReadResult::ERROR_IN_READING_FILE;
}
TXPArchive::TileInfo info;
if (!archive->getTileInfo(tileX,tileY,tileLOD,info))
continue;
const trpgHeader* header = archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive);
TXPArchive::TileLocationInfo plInfo;
plInfo.x = x;
plInfo.y = y;
plInfo.lod = lod;
TXPArchive::TileInfo parentInfo;
archive->getTileInfo(plInfo,parentInfo);
tileContent->setName("TileContent");
for(int idx = 0; idx < nbChild; ++idx)
{
std::vector<TXPArchive::TileLocationInfo> childrenChildLoc;
TXPArchive::TileLocationInfo& loc = locs[idx];
TXPArchive::TileInfo info;
if (!archive->getTileInfo(loc,info))
continue;
if (tileLOD < (numLods-1))
{
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
archive->getDir(),
tileLOD,
tileX,
tileY,
archive->getId()
);
osg::ref_ptr<osg::Node> tileContent = getTileContent(info, loc, archive, childrenChildLoc);
osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
tileContent->setName("TileContent");
// not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
pagedLOD->setFileName(1,pagedLODfile);
pagedLOD->setRange(1,0,info.minRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
pagedLOD->setPriorityOffset(0,numLods-lod);
pagedLOD->setPriorityScale(0,1.0f);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
pagedLOD->setTileId(tileX,tileY,tileLOD);
if(childrenChildLoc.size() > 0)
{
std::string childInfoStr;
createChildrenLocationString(childrenChildLoc, childInfoStr);
if(tileType == trpgHeader::TileLocal)
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d%s.txp",
archive->getDir(),
loc.lod,
loc.x,
loc.y,
archive->getId(),
childInfoStr.c_str());
// there are tile sets which do not maintain the z extents in
// the tile table. This attempt to address the issue by using
// the geometry bounding sphere. The downside is that this is
// not coupled to the generation and may result in runtime cracks
if (info.center.z() == 0)
{
osg::Vec3d center(info.center - parentInfo.bbox._min);
osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
sw[2] = 0.0;
pagedLOD->setCenter(center - sw);
osg::Matrix offset;
offset.setTrans(sw);
osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
tform->addChild(pagedLOD.get());
subtiles->addChild(tform);
}
else
subtiles->addChild(pagedLOD.get());
}
else
{
subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD));
if(tileType == trpgHeader::TileLocal)
{
osg::Vec3d center(info.center - parentInfo.bbox._min);
osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
sw[2] = 0.0;
osg::Matrix offset;
offset.setTrans(sw);
osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
tform->addChild(tileContent.get());
subtiles->addChild(tform);
}
else
subtiles->addChild(tileContent.get());
}
osg::BoundingSphere bSphere = tileContent->getBound();
info.center.z() = bSphere.center().z();
info.radius = bSphere.radius();
}
osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
// note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
pagedLOD->setFileName(1,pagedLODfile);
pagedLOD->setRange(1,0,info.minRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
pagedLOD->setPriorityOffset(0,numLods - loc.lod);
pagedLOD->setPriorityScale(0,1.0f);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
pagedLOD->setTileId(loc.x, loc.y, loc.lod);
if(tileType == trpgHeader::TileLocal)
{
osg::Vec3d center(info.center - parentInfo.bbox._min);
osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
sw[2] = 0.0;
pagedLOD->setCenter(center - sw);
osg::Matrix offset;
offset.setTrans(sw);
osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
tform->addChild(pagedLOD.get());
subtiles->addChild(tform);
}
else
subtiles->addChild(pagedLOD.get());
subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod)); // is this really needed?
}
else
{
subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod));
if(tileType == trpgHeader::TileLocal)
{
osg::Vec3d center(info.center - parentInfo.bbox._min);
osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
sw[2] = 0.0;
osg::Matrix offset;
offset.setTrans(sw);
osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
tform->addChild(tileContent.get());
subtiles->addChild(tform);
}
else
subtiles->addChild(tileContent.get());
}
}
}
//osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl;
else
{
int sizeX, sizeY;
archive->getLODSize(lod+1,sizeX,sizeY);
const trpgHeader* header = archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
TXPArchive::TileInfo parentInfo;
archive->getTileInfo(x,y,lod,parentInfo);
for (int ix = 0; ix < 2; ix++)
{
for (int iy = 0; iy < 2; iy++)
{
int tileX = x*2+ix;
int tileY = y*2+iy;
int tileLOD = lod+1;
TXPArchive::TileInfo info;
if (!archive->getTileInfo(tileX,tileY,tileLOD,info))
continue;
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive, childrenLoc);
tileContent->setName("TileContent");
if (tileLOD < (numLods-1))
{
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
archive->getDir(),
tileLOD,
tileX,
tileY,
archive->getId());
// there are tile sets which do not maintain the z extents in
// the tile table. This attempt to address the issue by using
// the geometry bounding sphere. The downside is that this is
// not coupled to the generation and may result in runtime cracks
if (info.center.z() == 0)
{
osg::BoundingSphere bSphere = tileContent->getBound();
info.center.z() = bSphere.center().z();
info.radius = bSphere.radius();
}
osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
// note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
pagedLOD->setFileName(1,pagedLODfile);
pagedLOD->setRange(1,0,info.minRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
pagedLOD->setPriorityOffset(0,numLods-lod);
pagedLOD->setPriorityScale(0,1.0f);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
pagedLOD->setTileId(tileX,tileY,tileLOD);
if(tileType == trpgHeader::TileLocal)
{
osg::Vec3d center(info.center - parentInfo.bbox._min);
osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
sw[2] = 0.0;
pagedLOD->setCenter(center - sw);
osg::Matrix offset;
offset.setTrans(sw);
osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
tform->addChild(pagedLOD.get());
subtiles->addChild(tform);
}
else
subtiles->addChild(pagedLOD.get());
}
else
{
subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD));
if(tileType == trpgHeader::TileLocal)
{
osg::Vec3d center(info.center - parentInfo.bbox._min);
osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
sw[2] = 0.0;
osg::Matrix offset;
offset.setTrans(sw);
osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
tform->addChild(tileContent.get());
subtiles->addChild(tform);
}
else
subtiles->addChild(tileContent.get());
}
}
}
}
//osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl;
return subtiles.get();
}
return ReadResult::ERROR_IN_READING_FILE;
}
// If you change this then you have to change extractChildrenLocation()
void ReaderWriterTXP::createChildrenLocationString(const std::vector<TXPArchive::TileLocationInfo>& locs, std::string& locString) const
{
std::stringstream theLoc;
if(locs.size() == 0)
{
theLoc << "_" << locs.size();
}
else
{
theLoc << "_" << locs.size() << "_" << "{" ;
for(unsigned int idx = 0; idx < locs.size(); ++idx)
{
const TXPArchive::TileLocationInfo& loc = locs[idx];
theLoc << loc.x
<< "_"
<< loc.y
<< "_"
<< loc.addr.file
<< "_"
<< loc.addr.offset
<< "_"
<< loc.zmin
<< "_"
<< loc.zmax;
if(idx != locs.size() -1)
theLoc << "_";
}
}
theLoc << "}" << std::ends;
locString = theLoc.str();
}
bool ReaderWriterTXP::extractChildrenLocations(const std::string& name, int parentLod, std::vector<TXPArchive::TileLocationInfo>& locs, int nbChild) const
{
locs.clear();
if(nbChild == 0)
return true;
locs.resize(nbChild);
// We look for '{', which should be the start of the list of {x,y,addr} children data
// '}' should end the list.
// We expect: X,Y,FID,FOFFSET,ZMIN,ZMAX
std::string::size_type startOfList = name.find_last_of('{');
if(startOfList == std::string::npos)
return false;
std::string::size_type endOfList = name.find_last_of('}');
if(endOfList == std::string::npos)
return false;
// Extract the data
strcpy(gbuf, name.substr(startOfList + 1, endOfList - startOfList - 1).c_str());
char *token = strtok( gbuf, "_" );
int nbTokenRead = 0;
for(int idx = 0; idx < nbChild; idx++)
{
// X
if(!token)
break;
locs[idx].x = atoi(token);
nbTokenRead++;
// Y
token = strtok(0, "_");
if(!token)
break;
locs[idx].y = atoi(token);
nbTokenRead++;
// FID
token = strtok(0, "_");
if(!token)
break;
locs[idx].addr.file = atoi(token);
nbTokenRead++;
// OFFSET
token = strtok(0, "_");
if(!token)
break;
locs[idx].addr.offset = atoi(token);
nbTokenRead++;
// ZMIN
token = strtok(0, "_");
if(!token)
break;
locs[idx].zmin = (float)atof(token);
nbTokenRead++;
// ZMAX
token = strtok(0, "_");
if(!token)
break;
locs[idx].zmax= (float)atof(token);
nbTokenRead++;
locs[idx].lod = parentLod+1;
token = strtok(0, "_");
}
if(nbTokenRead != nbChild*6)
return false;
else
return true;
}
TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir)
{
TXPArchive* archive = NULL;
@ -279,45 +616,50 @@ TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir)
class SeamFinder: public osg::NodeVisitor
{
public:
SeamFinder(int x, int y, int lod, TXPArchive::TileInfo& info, TXPArchive *archive ):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_x(x), _y(y), _lod(lod), _info(info), _archive(archive)
{};
SeamFinder(int x, int y, int lod, const TXPArchive::TileInfo& info, TXPArchive *archive ):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_x(x), _y(y), _lod(lod), _info(info), _archive(archive)
{}
virtual void apply(osg::Group& group)
{
for (unsigned int i = 0; i < group.getNumChildren(); i++)
{
osg::Node* child = group.getChild(i);
osg::Node* seam = seamReplacement(child);
if (child != seam)
{
group.replaceChild(child,seam);
}
else
{
child->accept(*this);
}
}
}
{
for (unsigned int i = 0; i < group.getNumChildren(); i++)
{
osg::Node* child = group.getChild(i);
osg::Node* seam = seamReplacement(child);
if (child != seam)
{
group.replaceChild(child,seam);
}
else
{
child->accept(*this);
}
}
}
protected:
osg::Node* seamReplacement(osg::Node* node);
int _x, _y, _lod;
TXPArchive::TileInfo& _info;
const TXPArchive::TileInfo& _info;
TXPArchive *_archive;
};
osg::Node* SeamFinder::seamReplacement(osg::Node* node)
{
osg::Group* group = node->asGroup();
if (group == 0) return node;
if ( group == 0 )
return node;
std::vector<osg::Node*> nonSeamChildren;
osg::LOD* hiRes = 0;
osg::LOD* loRes = 0;
const trpgHeader* header = _archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
for (unsigned int i = 0; i < group->getNumChildren(); i++)
{
osg::LOD* lod = dynamic_cast<osg::LOD*>(group->getChild(i));
@ -329,11 +671,32 @@ osg::Node* SeamFinder::seamReplacement(osg::Node* node)
bool nonSeamChild = true;
// looks like the problem is in here - likely due to seamLOD info
// not being adjusted properly in tiled databases
// seam center is outside the bounding box of the tile
if (!_info.bbox.contains(lod->getCenter()))
osg::Vec3 lodCenter = lod->getCenter();
if(tileType == trpgHeader::TileLocal)
{
trpg2dPoint tileExtents;
header->GetTileSize(0, tileExtents);
osg::BoundingBox bbox;
_archive->getExtents(bbox);
osg::Vec3 offset(0.0, 0.0, 0.0);
int divider = (0x1 << _lod);
// calculate which tile model is located in
tileExtents.x /= divider;
tileExtents.y /= divider;
offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5;
offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5;
lodCenter += offset;
}
if (!_info.bbox.contains(lodCenter))
{
// seams have center as the neighbour tile
osg::Vec3 d = _info.center - lod->getCenter();
osg::Vec3 d = _info.center - lodCenter;
if (((fabs(d.x())-_info.size.x()) > 0.0001) && ((fabs(d.y())-_info.size.y()) > 0.0001))
{
nonSeamChildren.push_back(lod);
@ -372,19 +735,43 @@ osg::Node* SeamFinder::seamReplacement(osg::Node* node)
int dx = 0;
int dy = 0;
int lod = _lod;
osg::Vec3 delta = loRes->getCenter()-_info.center;
osg::Vec3 lodCenter = loRes->getCenter();
if(tileType == trpgHeader::TileLocal)
{
trpg2dPoint tileExtents;
header->GetTileSize(0, tileExtents);
osg::BoundingBox bbox;
_archive->getExtents(bbox);
osg::Vec3 offset(0.0, 0.0, 0.0);
int divider = (0x1 << _lod);
// calculate which tile model is located in
tileExtents.x /= divider;
tileExtents.y /= divider;
offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5;
offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5;
lodCenter += offset;
}
osg::Vec3 delta = lodCenter-_info.center;
if (fabs(delta.x())>fabs(delta.y()))
{
if (delta.x()<0.0) --dx; // west
else dx++; // east
if ( delta.x() < 0.0 )
--dx; // west
else
dx++; // east
}
else
{
if (delta.y()<0.0) --dy; // south
else ++dy; // north
if ( delta.y() < 0.0 )
--dy; // south
else
++dy; // north
}
TXPSeamLOD* seam = new TXPSeamLOD(_x, _y, lod, dx, dy);
seam->setCenter(loRes->getCenter());
seam->addChild(loRes->getChild(0)); // low res
if (hiRes)
{
@ -411,28 +798,34 @@ osg::Node* SeamFinder::seamReplacement(osg::Node* node)
return node;
}
osg::Node* ReaderWriterTXP::getTileContent(TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive)
osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive, std::vector<TXPArchive::TileLocationInfo>& childrenLoc)
{
if (archive == 0) return false;
if ( archive == 0 )
return false;
int numLods = archive->getNumLODs();
int majorVersion, minorVersion;
archive->GetVersion(majorVersion, minorVersion);
double realMinRange = info.minRange;
double realMaxRange = info.maxRange;
double usedMaxRange = osg::maximum(info.maxRange,1e7);
double usedMaxRange = osg::maximum(info.maxRange,1e7);
osg::Vec3 tileCenter;
osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter);
osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc);
// if group has only one child, then simply use its child.
#if 1
while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())
{
tileGroup = tileGroup->getChild(0)->asGroup();
}
#endif
bool doSeam = false;
if(majorVersion == 2 && minorVersion >= 1)
doSeam = (childrenLoc.size() > 0);
else
doSeam = (lod < (archive->getNumLODs() - 1));
// Handle seams
if (lod < (numLods-1))
if (doSeam)
{
SeamFinder sfv(x,y,lod,info,archive);
tileGroup->accept(sfv);
@ -441,5 +834,35 @@ osg::Node* ReaderWriterTXP::getTileContent(TXPArchive::TileInfo &info, int x, in
return tileGroup;
}
// this version only gets called if the TXP version is >= than 2.1
osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, const TXPArchive::TileLocationInfo& loc, TXPArchive* archive, std::vector<TXPArchive::TileLocationInfo>& childrenLoc)
{
if ( archive == 0 )
return false;
// int numLods = archive->getNumLODs();
double realMinRange = info.minRange;
double realMaxRange = info.maxRange;
double usedMaxRange = osg::maximum(info.maxRange,1e7);
osg::Vec3 tileCenter;
osg::Group* tileGroup = archive->getTileContent(loc,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc);
// if group has only one child, then simply use its child.
while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())
{
tileGroup = tileGroup->getChild(0)->asGroup();
}
// Handle seams
if (childrenLoc.size() > 0)
{
SeamFinder sfv(loc.x, loc.y, loc.lod, info, archive);
tileGroup->accept(sfv);
}
return tileGroup;
}
osgDB::RegisterReaderWriterProxy<ReaderWriterTXP> g_txpReaderWriterProxy;

View File

@ -80,9 +80,13 @@ protected:
TXPArchive *getArchive(int id, const std::string&);
osg::Node* getTileContent(TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive);
osg::Node* getTileContent(const TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive, std::vector<TXPArchive::TileLocationInfo>& childrenLoc);
osg::Node* getTileContent(const TXPArchive::TileInfo &info, const TXPArchive::TileLocationInfo& loc, TXPArchive* archive, std::vector<TXPArchive::TileLocationInfo>& childrenLoc);
void createChildrenLocationString(const std::vector<TXPArchive::TileLocationInfo>& locs, std::string& locString) const;
bool extractChildrenLocations(const std::string& name, int parentLod, std::vector<TXPArchive::TileLocationInfo>& locs, int nbChild) const;
mutable osgDB::ReentrantMutex _serializerMutex;
std::map< int,osg::ref_ptr<TXPArchive> > _archives;
static int _archiveId;
};

View File

@ -25,6 +25,10 @@
#include <iostream>
#include <fstream>
#if defined(linux)
# include <unistd.h>
# define _access access
#endif
#include "TXPArchive.h"
#include "TXPParser.h"
@ -36,12 +40,36 @@ using namespace txp;
#define TXPArchiveERROR(s) osg::notify(osg::NOTICE) << "txp::TXPArchive::" << (s) << " error: "
void TXPArchive::SetTexMap(int key,osg::ref_ptr<osg::Texture2D> ref)
{
_texmap[key] = ref;
}
osg::ref_ptr<osg::Texture2D> TXPArchive::GetTexMapEntry(int key)
{
return _texmap[key];
}
void TXPArchive::SetStatesMap(int key,osg::ref_ptr<osg::StateSet> ref)
{
_statesMap[key] = ref;
}
osg::ref_ptr<osg::StateSet> TXPArchive::GetStatesMapEntry(int key)
{
return _statesMap[key];
}
TXPArchive::TXPArchive():
trpgr_Archive(),
_id(-1),
_numLODs(0),
_swExtents(0.0,0.0),
_neExtents(0.0,0.0)
trpgr_Archive(),
_id(-1),
_numLODs(0),
_swExtents(0.0,0.0),
_neExtents(0.0,0.0),
_majorVersion(-1),
_minorVersion(-1),
_isMaster(false)
{
}
@ -87,7 +115,7 @@ bool TXPArchive::openFile(const std::string& archiveName)
return false;
}
if (!ReadHeader())
if (!ReadHeader(false))
{
TXPArchiveERROR("openFile()") << "couldn't read header for archive: " << archiveName << std::endl;
return false;
@ -98,19 +126,19 @@ bool TXPArchive::openFile(const std::string& archiveName)
{
header->GetNumLods(_numLODs);
header->GetExtents(_swExtents,_neExtents);
header->GetVersion(_majorVersion, _minorVersion);
_isMaster = header->GetIsMaster();
}
int numTextures;
texTable.GetNumTextures(numTextures);
_textures.resize(numTextures);
int numModel;
modelTable.GetNumModels(numModel);
_models.resize(numModel);
_models.clear();
int numMaterials;
materialTable.GetNumMaterial(numMaterials);
_gstates.resize(numMaterials);
return true;
}
@ -119,7 +147,9 @@ bool TXPArchive::loadMaterial(int ix)
{
int i = ix;
if (_gstates[ix].get()) return true;
if (GetStatesMapEntry(ix).get())
return true;
osg::StateSet* osg_state_set = new osg::StateSet;
@ -145,17 +175,17 @@ bool TXPArchive::loadMaterial(int ix)
trpgColor color;
mat->GetAmbient(color);
osg_material->setAmbient( osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
osg::Vec4(color.red, color.green, color.blue, alpha));
mat->GetDiffuse(color);
osg_material->setDiffuse(osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
osg::Vec4(color.red, color.green, color.blue, alpha));
mat->GetSpecular(color);
osg_material->setSpecular(osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
osg::Vec4(color.red, color.green, color.blue, alpha));
mat->GetEmission(color);
osg_material->setEmission(osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
osg::Vec4(color.red, color.green, color.blue, alpha));
float64 shinines;
mat->GetShininess(shinines);
@ -213,7 +243,7 @@ bool TXPArchive::loadMaterial(int ix)
texEnv.GetWrap(wrap_s, wrap_t);
loadTexture(texId);
osg::Texture2D* osg_texture = _textures[texId].get();
osg::Texture2D* osg_texture = GetTexMapEntry(texId).get();
if(osg_texture)
{
@ -299,7 +329,7 @@ bool TXPArchive::loadMaterial(int ix)
osg_state_set->setAttributeAndModes(cull_face, osg::StateAttribute::ON);
}
}
_gstates[i] = osg_state_set;
SetStatesMap(i,osg_state_set);
return true;
}
@ -311,19 +341,29 @@ bool TXPArchive::loadMaterials()
bool TXPArchive::loadTexture(int i)
{
if (_textures[i].get()) return true;
trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable);
if (GetTexMapEntry(i).get())
return true;
bool separateGeo = false;
int majorVer,minorVer;
GetVersion(majorVer,minorVer);
if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR))
{
separateGeo = true;
}
trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable,separateGeo);
const trpgTexture *tex;
tex = texTable.GetTextureRef(i);
if (!tex) return false;
if (!tex)
return false;
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if(mode == trpgTexture::External)
{
char texName[1024]; texName[0] = 0;
char texName[ 1024 ];
texName[ 0 ] = 0;
tex->GetName(texName,1023);
// Create a texture by name.
@ -356,30 +396,32 @@ bool TXPArchive::loadTexture(int i)
else
{
osg::notify(osg::WARN) << "TrPageArchive::LoadMaterials() error: "
<< "couldn't open image: " << filename << std::endl;
<< "couldn't open image: " << filename << std::endl;
}
_textures[i] = osg_texture;
SetTexMap(i,osg_texture);
}
else if( mode == trpgTexture::Local )
{
_textures[i] = getLocalTexture(image_helper,tex);
SetTexMap(i,getLocalTexture(image_helper,tex));
}
else if( mode == trpgTexture::Template )
{
_textures[i] = 0L; //GetTemplateTexture(image_helper,0, tex);
SetTexMap(i,0L);
}
else
{
_textures[i] = 0;
SetTexMap(i,0L);
}
return (_textures[i].get() != 0);
return (GetTexMapEntry(i).get() != 0);
}
bool TXPArchive::loadModel(int ix)
{
trpgModel *mod = modelTable.GetModelRef(ix);
int type;
if(!mod)
return false;
mod->GetType(type);
// Only dealing with external models currently
@ -389,24 +431,24 @@ bool TXPArchive::loadModel(int ix)
mod->GetName(name,1023);
// Load the model. It's probably not TerraPage
osg::Node *osg_model = osgDB::readNodeFile(name);
if (!osg_model)
osg::Node *osg_model = osgDB::readNodeFile( name );
if ( !osg_model )
{
osg::notify(osg::WARN) << "TrPageArchive::LoadModels() error: "
<< "failed to load model: "
<< name << std::endl;
<< "failed to load model: "
<< name << std::endl;
}
// Do this even if it's NULL
_models[ix] = osg_model;
// Do this even if it's NULL
_models[ ix ] = osg_model;
}
/*
else
{
trpgMemReadBuffer buf(GetEndian());
mod->Read(buf);
Group *osg_model = parse->ParseScene(buf, m_gstates , m_models);
m_models.push_back(osg_model);
}
else
{
trpgMemReadBuffer buf(GetEndian());
mod->Read(buf);
Group *osg_model = parse->ParseScene(buf, m_gstates , m_models);
m_models.push_back(osg_model);
}
*/
return true;
}
@ -417,14 +459,14 @@ bool TXPArchive::loadModels()
int numModel;
modelTable.GetNumModels(numModel);
_models.resize(numModel);
// Iterate over the models
for (int i=0; i< numModel; i++)
// use a pointer to the models map to bootstrap our map
trpgModelTable::ModelMapType *mt = modelTable.GetModelMap();
trpgModelTable::ModelMapType::iterator itr = mt->begin();
for ( ; itr != mt->end( ); itr++)
{
loadModel(i);
loadModel(itr->first);
}
osg::notify(osg::NOTICE) << "txp:: ... done." << std::endl;
return true;
}
@ -433,11 +475,11 @@ bool TXPArchive::loadLightAttributes()
{
osg::notify(osg::NOTICE) << "txp:: Loading light attributes ..." << std::endl;
int num;
lightTable.GetNumLightAttrs(num);
for ( int attr_num = 0; attr_num < num; attr_num++ )
trpgLightTable::LightMapType *lm = lightTable.getLightMap();
trpgLightTable::LightMapType::iterator itr = lm->begin();
for ( ; itr != lm->end() ; itr++)
{
trpgLightAttr* ref = const_cast<trpgLightAttr*>(lightTable.GetLightAttrRef(attr_num));
trpgLightAttr* ref = &itr->second;
osgSim::LightPointNode* osgLight = new osgSim::LightPointNode();
@ -523,11 +565,12 @@ bool TXPArchive::loadLightAttributes()
lp._sector = back;
osgLight->addLightPoint(lp);
}
else{
else
{
osgLight->addLightPoint(lp);
}
addLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z));
addLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z),itr->first);
}
osg::notify(osg::NOTICE) << "txp:: ... done." << std::endl;
@ -537,15 +580,17 @@ bool TXPArchive::loadLightAttributes()
void trim(std::string& str)
{
while (!str.empty() && isspace(str[str.length()-1]))
str.erase(str.length()-1);
str.erase(str.length()-1);
while (!str.empty() && isspace(str[0]))
str.erase(0,1);
}
bool TXPArchive::loadTextStyles()
{
const trpgTextStyleTable *textStyleTable = GetTextStyleTable();
if (!textStyleTable) return false;
if (textStyleTable->GetNumStyle() < 1) return true;
if ( !textStyleTable )
return false;
if ( textStyleTable->GetNumStyle() < 1 )
return true;
// try fontmap.txt
std::map< std::string, std::string > fontmap;
@ -556,78 +601,81 @@ bool TXPArchive::loadTextStyles()
if (fmapfile.is_open())
{
osg::notify(osg::NOTICE) << "txp:: Font map file found: " << fmapfname << std::endl;
std::string line;
while (std::getline(fmapfile,line))
{
unsigned int ix = line.find_first_of('=');
if (ix != std::string::npos)
{
std::string fontname = line.substr(0,ix);
std::string fontfilename = line.substr(ix+1,line.length()-ix+1);
osg::notify(osg::NOTICE) << "txp:: Font map file found: " << fmapfname << std::endl;
std::string line;
while (std::getline(fmapfile,line))
{
std::string::size_type ix = line.find_first_of('=');
if (ix != std::string::npos)
{
std::string fontname = line.substr(0,ix);
std::string fontfilename = line.substr(ix+1,line.length()-ix+1);
trim(fontname);
trim(fontfilename);
trim(fontname);
trim(fontfilename);
fontmap[fontname] = fontfilename;
fontmap[fontname] = fontfilename;
}
}
fmapfile.close();
}
}
fmapfile.close();
}
else
{
osg::notify(osg::NOTICE) << "txp:: No font map file found: " << fmapfname << std::endl;
osg::notify(osg::NOTICE) << "txp:: All fonts defaulted to arial.ttf" << std::endl;
osg::notify(osg::NOTICE) << "txp:: No font map file found: " << fmapfname << std::endl;
osg::notify(osg::NOTICE) << "txp:: All fonts defaulted to arial.ttf" << std::endl;
}
_fonts.resize(textStyleTable->GetNumStyle());
_fcolors.resize(textStyleTable->GetNumStyle());
for (int i = 0; i < textStyleTable->GetNumStyle(); i++)
const trpgTextStyleTable::StyleMapType *smap = textStyleTable->getStyleMap();
trpgTextStyleTable::StyleMapType::const_iterator itr = smap->begin();
for ( ; itr != smap->end(); itr++)
{
const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(i);
if (!textStyle) continue;
const trpgTextStyle *textStyle = &itr->second;
if ( !textStyle )
continue;
const std::string *fontName = textStyle->GetFont();
if (!fontName) continue;
const std::string *fontName = textStyle->GetFont();
if ( !fontName )
continue;
std::string fontfilename = fontmap[*fontName];
if (!fontfilename.length()) fontfilename = "arial.ttf";
osg::ref_ptr< osgText::Font > font = osgText::readFontFile(fontfilename);
std::string fontfilename = fontmap[*fontName];
if ( !fontfilename.length() )
fontfilename = "arial.ttf";
osg::ref_ptr< osgText::Font > font = osgText::readFontFile(fontfilename);
_fonts[i] = font;
_fonts[itr->first] = font;
const trpgMatTable* matTable = GetMaterialTable();
if (matTable)
{
int matId = textStyle->GetMaterial();
const trpgMaterial* mat = matTable->GetMaterialRef(0,matId);
if (mat)
{
trpgColor faceColor;
mat->GetColor(faceColor);
const trpgMatTable* matTable = GetMaterialTable();
if (matTable)
{
int matId = textStyle->GetMaterial();
const trpgMaterial* mat = matTable->GetMaterialRef(0,matId);
if (mat)
{
trpgColor faceColor;
mat->GetColor(faceColor);
float64 alpha;
mat->GetAlpha(alpha);
float64 alpha;
mat->GetAlpha(alpha);
_fcolors[i] = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha );
}
}
_fcolors[itr->first] = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha );
}
}
}
return true;
}
void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att)
void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att,int handle)
{
DeferredLightAttribute la;
la.lightPoint = lpn;
la.fallback = fallback;
la.attitude = att;
_lights.push_back(la);
_lights[handle] = la;
}
bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info)
bool TXPArchive::getTileInfo(const TileLocationInfo& loc, TileInfo& info)
{
info.minRange = 0.0;
info.maxRange = 0.0;
@ -637,104 +685,150 @@ bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info)
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
header.GetLodRange(lod,info.maxRange);
header.GetLodRange(lod+1,info.minRange);
header.GetLodRange(loc.lod,info.maxRange);
header.GetLodRange(loc.lod+1,info.minRange);
header.GetLodRange(0,info.lod0Range);
trpg2dPoint sw,ne;
header.GetExtents(sw,ne);
trpg2dPoint size;
header.GetTileSize(lod,size);
header.GetTileSize(loc.lod,size);
info.size.x() = size.x;
info.size.y() = size.y;
info.size.z() = 0.f;
trpgwAppAddress addr;
float minz = 0.f;
float maxz = 0.f;
tileTable.GetTile(x,y,lod,addr,minz,maxz);
info.center.set(
sw.x+(x*size.x)+(size.x/2.f),
sw.y+(y*size.y)+(size.y/2.f),
(minz+maxz)/2.f
);
sw.x+(loc.x*size.x)+(size.x/2.f),
sw.y+(loc.y*size.y)+(size.y/2.f),
(loc.zmin + loc.zmax)/2.f
);
info.bbox.set(
osg::Vec3(
info.center.x()-(size.x/2.f),
info.center.y()-(size.y/2.f),
minz
),
loc.zmin
),
osg::Vec3(
info.center.x()+(size.x/2.f),
info.center.y()+(size.y/2.f),
maxz
)
);
loc.zmax
)
);
info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3;
return true;
}
class ModelVisitor : public osg::NodeVisitor
bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info)
{
TXPArchive* _archive;
int _x;
int _y;
int _lod;
public:
ModelVisitor(TXPArchive* archive, int x, int y, int lod):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_archive(archive), _x(x), _y(y), _lod(lod)
if(_majorVersion == 2 && _minorVersion >=1)
{
// Version 2.1
// Tile table contain only lod 0
if(lod > 0)
return false;
}
virtual void apply(osg::MatrixTransform& xform)
{
const trpgHeader* header = _archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
const osg::Referenced* ref = xform.getUserData();
const TileIdentifier* tileID = dynamic_cast<const txp::TileIdentifier*>(ref);
if(!tileID) return; // bail early - this isn't a loaded model
trpgwAppAddress addr;
float minz = 0.f;
float maxz = 0.f;
tileTable.GetTile(x, y, lod, addr, minz, maxz);
if(tileType == trpgHeader::TileLocal && tileID->lod == 9999)
{
trpg2dPoint tileExtents;
header->GetTileSize(0, tileExtents);
osg::BoundingBox bbox;
_archive->getExtents(bbox);
osg::Vec3 offset(xform.getMatrix().getTrans());
offset[0] -= bbox._min[0];
offset[1] -= bbox._min[1];
trpg2dPoint offsetXY, tileID(_x,_y);
int divider = (0x01 << _lod);
// calculate which tile model is located in
tileExtents.x /= divider;
tileExtents.y /= divider;
offset[0] -= tileID.x*tileExtents.x;
offset[1] -= tileID.y*tileExtents.y;
osg::Matrix mat(xform.getMatrix());
mat.setTrans(offset);
xform.setMatrix(mat);
}
}
};
TileLocationInfo loc(x, y, lod, addr, minz, maxz);
return getTileInfo(loc, info);
}
osg::Group* TXPArchive::getTileContent(
int x, int y, int lod,
double realMinRange,
double realMaxRange,
double usedMaxRange,
osg::Vec3& tileCenter)
osg::Vec3& tileCenter,
std::vector<TXPArchive::TileLocationInfo>& childInfoList)
{
if(_majorVersion == 2 && _minorVersion >= 1)
{
// Version 2.1
// This call is valid only for lod = 0
if(lod != 0)
return new osg::Group;
}
trpgwAppAddress addr;
float minz = 0.f;
float maxz = 0.f;
tileTable.GetTile(x, y, lod, addr, minz, maxz);
TileLocationInfo loc(x,y,lod,addr, minz,maxz);
return getTileContent(loc, realMinRange, realMaxRange, usedMaxRange, tileCenter, childInfoList);
}
class ModelVisitor : public osg::NodeVisitor
{
TXPArchive* _archive;
TXPArchive::TileLocationInfo _tileInfo;
// int _x;
// int _y;
// int _lod;
public:
ModelVisitor(TXPArchive* archive, const TXPArchive::TileLocationInfo& loc):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_archive(archive), _tileInfo(loc)
{
}
virtual void apply(osg::MatrixTransform& xform)
{
const trpgHeader* header = _archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
const osg::Referenced* ref = xform.getUserData();
const TileIdentifier* tileID = dynamic_cast<const txp::TileIdentifier*>(ref);
if(!tileID) return; // bail early - this isn't a loaded model
if(tileType == trpgHeader::TileLocal && tileID->lod == 9999)
{
trpg2dPoint tileExtents;
header->GetTileSize(0, tileExtents);
osg::BoundingBox bbox;
_archive->getExtents(bbox);
osg::Vec3 offset(xform.getMatrix().getTrans());
offset[0] -= bbox._min[0];
offset[1] -= bbox._min[1];
trpg2dPoint offsetXY, tileID(_tileInfo.x,_tileInfo.y);
int divider = (0x01 << _tileInfo.lod);
// calculate which tile model is located in
tileExtents.x /= divider;
tileExtents.y /= divider;
offset[0] -= tileID.x*tileExtents.x;
offset[1] -= tileID.y*tileExtents.y;
osg::Matrix mat(xform.getMatrix());
mat.setTrans(offset);
xform.setMatrix(mat);
}
}
};
osg::Group* TXPArchive::getTileContent(
const TileLocationInfo& loc,
double realMinRange,
double realMaxRange,
double usedMaxRange,
osg::Vec3& tileCenter,
std::vector<TileLocationInfo>& childInfoList)
{
if (_parser.get() == 0)
{
_parser = new TXPParser();
@ -742,28 +836,99 @@ osg::Group* TXPArchive::getTileContent(
}
trpgMemReadBuffer buf(GetEndian());
if (!ReadTile(x,y,lod,buf))
bool readStatus;
trpgTileTable::TileMode tileMode;
tileTable.GetMode(tileMode);
if(tileMode == trpgTileTable::External)
readStatus = ReadExternalTile(loc.x, loc.y, loc.lod, buf);
else
readStatus = ReadTile(loc.addr, buf);
if(!readStatus)
return new osg::Group;
trpgTileHeader *tilehdr = _parser->getTileHeaderRef();
int majVersion,minVersion;
GetVersion(majVersion,minVersion);
// only compute block # if we are a master archive.
if((majVersion >= TRPG_NOMERGE_VERSION_MAJOR) && (minVersion >= TRPG_NOMERGE_VERSION_MINOR) && (_isMaster))
{
return new osg::Group;
if(tilehdr)
{
int x,y;
unsigned int denom = (1 << loc.lod); // this should work up to lod 31
x = loc.x/denom;
y = loc.y/denom;
tilehdr->SetBlockNo(y,x);
}
}
osg::Group *tileGroup = _parser->parseScene(buf,_gstates,_models,realMinRange,realMaxRange,usedMaxRange);
osg::Group *tileGroup = _parser->parseScene(buf,_statesMap,_models,realMinRange,realMaxRange,usedMaxRange);
tileCenter = _parser->getTileCenter();
int nbChild = _parser->GetNbChildrenRef();
childInfoList.clear();
for(int idx = 0; idx < nbChild; idx++)
{
const trpgChildRef *childRef = _parser->GetChildRef(idx);
if(childRef)
{
TileLocationInfo loc;
childRef->GetTileLoc(loc.x, loc.y, loc.lod);
childRef->GetTileZValue(loc.zmin, loc.zmax);
childRef->GetTileAddress(loc.addr);
childInfoList.push_back(loc);
}
}
// Fix up model MatrixTransform
ModelVisitor mv(this, x, y, lod);
ModelVisitor mv(this, loc);
tileGroup->accept(mv);
// Prune
unsigned int i = 0;
for (i = 0; i < _gstates.size(); i++)
OSGStatesMapType::iterator itr = _statesMap.begin();
while( itr != _statesMap.end( ) )
{
if (_gstates[i].valid() && (_gstates[i]->referenceCount()==1)) _gstates[i] = 0;
if(itr->second.valid() &&
(itr->second->referenceCount()==1))
{
// unreference it.
itr->second = NULL;
OSGStatesMapType::iterator toRemove = itr;
++itr;
// remove it from the map
_statesMap.erase( toRemove );
}
else
{
++itr;
}
}
for (i = 0; i < _textures.size(); i++)
OSGTexMapType::iterator mitr = _texmap.begin();
while( mitr != _texmap.end( ) )
{
if (_textures[i].valid() && (_textures[i]->referenceCount()==1)) _textures[i] = 0;
if(mitr->second.valid() &&
(mitr->second->referenceCount()==1))
{
// unreference it.
mitr->second = NULL;
OSGTexMapType::iterator toRemove = mitr;
++mitr;
// remove it from the map
_texmap.erase( toRemove );
}
else
{
++mitr;
}
}
return tileGroup;

View File

@ -50,155 +50,210 @@
namespace txp
{
// this one handles different placement of light direction in osg and terrapage
struct DeferredLightAttribute
{
// light point at (0,0,0) looking in (0,0,0) direction
osg::ref_ptr<osgSim::LightPointNode> lightPoint;
osg::ref_ptr<osg::StateSet> fallback;
osg::Vec3 attitude;
};
class TXPParser;
class TXPArchive : public trpgr_Archive, public osg::Referenced
{
public:
// Constructor
TXPArchive();
// Opens the archive file and reads the header
bool openFile(const std::string& archiveName);
// Load the materials from the archve
bool loadMaterials();
bool loadMaterial(int ix);
bool loadTexture(int i);
// Load the models from the archive
bool loadModels();
bool loadModel(int ix);
// Load the light attribs from the archive
bool loadLightAttributes();
// Load the text styles from the archive
bool loadTextStyles();
inline std::vector< osg::ref_ptr<osgText::Font> >& getStyles() { return _fonts; }
inline std::vector< osg::Vec4 >& getTextColors() { return _fcolors; }
// Add light attrib
void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude);
int getNumLightAttributes() { return _lights.size(); }
// Get light attrib
inline DeferredLightAttribute& getLightAttribute(unsigned int i)
// this one handles different placement of light direction in osg and terrapage
struct DeferredLightAttribute
{
return _lights[i];
// light point at (0,0,0) looking in (0,0,0) direction
osg::ref_ptr<osgSim::LightPointNode> lightPoint;
osg::ref_ptr<osg::StateSet> fallback;
osg::Vec3 attitude;
};
// Gets some informations for a given tile
struct TileInfo
class TXPParser;
class TXPArchive : public trpgr_Archive, public osg::Referenced
{
osg::Vec3 center;
double minRange;
double maxRange;
double lod0Range;
float radius;
osg::Vec3 size;
osg::BoundingBox bbox;
};
bool getTileInfo(int x, int y, int lod, TileInfo& info);
public:
// Constructor
TXPArchive();
// Set/Get the archive id
inline void setId(int id)
{
_id = id;
}
inline const int& getId() const
{
return _id;
}
// Opens the archive file and reads the header
bool openFile(const std::string& archiveName);
// Load the materials from the archve
bool loadMaterials();
bool loadMaterial(int ix);
bool loadTexture(int i);
// Returns the number of LODs for this archive
inline const int& getNumLODs() const
{
return _numLODs;
}
// Load the models from the archive
bool loadModels();
bool loadModel(int ix);
// Returns the extents of the archive
// FIXME - Needs to change for databases that aren't flat-earth
void getExtents(osg::BoundingBox& extents);
// Load the light attribs from the archive
bool loadLightAttributes();
// Load the text styles from the archive
bool loadTextStyles();
inline std::map<int, osg::ref_ptr<osgText::Font> >& getStyles()
{
return _fonts;
}
inline std::map<int, osg::Vec4 >& getTextColors()
{
return _fcolors;
}
// Add light attrib
void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude,int handle);
int getNumLightAttributes()
{
return _lights.size();
}
// Get light attrib
inline DeferredLightAttribute& getLightAttribute(unsigned int i)
{
return _lights[i];
};
// Gets some informations for a given tile
struct TileInfo
{
osg::Vec3 center;
double minRange;
double maxRange;
double lod0Range;
float radius;
osg::Vec3 size;
osg::BoundingBox bbox;
};
struct TileLocationInfo
{
TileLocationInfo() : x( -1 ), y( -1 ), lod( -1 )
{}
TileLocationInfo(int gx, int gy, int glod, const trpgwAppAddress& gaddr, float gzmin = 0.0f, float gzmax = 0.0f):
x( gx ), y( gy ), lod( glod ), addr( gaddr ), zmin( gzmin ), zmax( gzmax )
{}
int x, y, lod;
trpgwAppAddress addr;
float zmin, zmax;
};
bool getTileInfo(int x, int y, int lod, TileInfo& info);
bool getTileInfo(const TileLocationInfo& loc, TileInfo& info);
// Set/Get the archive id
inline void setId(int id)
{
_id = id;
}
inline const int& getId() const
{
return _id;
}
// Returns the number of LODs for this archive
inline const int& getNumLODs() const
{
return _numLODs;
}
// Returns the extents of the archive
// FIXME - Needs to change for databases that aren't flat-earth
void getExtents(osg::BoundingBox& extents);
// {
// extents.set(_swExtents.x,_swExtents.y,0.0f,_neExtents.x,_neExtents.y,0.0f);
// }
// Returns the origin of the archive
inline void getOrigin(double& x, double& y)
{
x=_swExtents.x;
y=_swExtents.y;
}
// Returns the origin of the archive
inline void getOrigin(double& x, double& y)
{
x=_swExtents.x;
y=_swExtents.y;
}
// Returns global texture
inline osg::Texture2D* getGlobalTexture(int id)
{
return _textures[id].get();
}
// Returns global texture
inline osg::Texture2D* getGlobalTexture(int id)
{
return GetTexMapEntry(id).get();
}
// Returns scenegraph representing the Tile
osg::Group* getTileContent(
int x,
int y,
int lod,
double realMinRange,
double realMaxRange,
double usedMaxRange,
osg::Vec3& tileCenter);
// Returns scenegraph representing the Tile.
// For version 2.1 and over this function can only be call
// with lod = 0, since the archive tile table will contain
// only tiles with lod = 0
osg::Group* TXPArchive::getTileContent(
int x,
int y,
int lod,
double realMinRange,
double realMaxRange,
double usedMaxRange,
osg::Vec3& tileCenter,
std::vector<TXPArchive::TileLocationInfo>& childInfoList);
// Get the number of tiles for given LOD
bool getLODSize(int lod, int& x, int& y);
// To be used for Version 2.1 with lod > 0
osg::Group* TXPArchive::getTileContent(
const TileLocationInfo& loc,
double realMinRange,
double realMaxRange,
double usedMaxRange,
osg::Vec3& tileCenter,
std::vector<TXPArchive::TileLocationInfo>& childInfoList);
// Get the number of tiles for given LOD
bool getLODSize(int lod, int& x, int& y);
void GetVersion(int& majorVer, int& minorVer) const
{
majorVer = _majorVersion;
minorVer = _minorVersion;
}
protected:
protected:
// Destructor
virtual ~TXPArchive();
// Destructor
virtual ~TXPArchive();
// Id of the archive
int _id;
// Id of the archive
int _id;
// Number of the LODs
int _numLODs;
// Number of the LODs
int _numLODs;
// Archive extents
trpg2dPoint _swExtents;
trpg2dPoint _neExtents;
// Archive extents
trpg2dPoint _swExtents;
trpg2dPoint _neExtents;
// Terra Page Parser
osg::ref_ptr<TXPParser> _parser;
// Terra Page Parser
osg::ref_ptr<TXPParser> _parser;
// Textures
std::vector< osg::ref_ptr<osg::Texture2D> > _textures;
// States
std::vector< osg::ref_ptr<osg::StateSet> > _gstates;
// Models
std::vector< osg::ref_ptr<osg::Node> > _models;
// Light attributes vector
std::vector<DeferredLightAttribute> _lights;
// Textures
typedef std::map<int,osg::ref_ptr<osg::Texture2D> > OSGTexMapType;
OSGTexMapType _texmap;
// Text styles / Fonts
std::vector< osg::ref_ptr<osgText::Font> > _fonts;
void SetTexMap(int key,osg::ref_ptr<osg::Texture2D> ref);
osg::ref_ptr<osg::Texture2D> GetTexMapEntry(int key);
// Text colors
std::vector< osg::Vec4 > _fcolors;
//
OpenThreads::Mutex _mutex;
};
// States
typedef std::map<int,osg::ref_ptr<osg::StateSet> > OSGStatesMapType;
OSGStatesMapType _statesMap;
void SetStatesMap(int key,osg::ref_ptr<osg::StateSet> ref);
osg::ref_ptr<osg::StateSet> GetStatesMapEntry(int key);
// Models
typedef std::map<int,osg::ref_ptr<osg::Node> > OSGModelsMapType;
OSGModelsMapType _models;
// Light attributes vector
std::map<int, DeferredLightAttribute> _lights;
// Text styles / Fonts
std::map<int, osg::ref_ptr<osgText::Font> > _fonts;
// Text colors
std::map<int, osg::Vec4 > _fcolors;
//
OpenThreads::Mutex _mutex;
// Cache those: TerraPage version
int _majorVersion, _minorVersion;
bool _isMaster;
};
} // namespace

View File

@ -49,7 +49,8 @@ bool TXPNode_readLocalData(osg::Object &obj, osgDB::Input &fr)
class Dump2Osg : public osg::NodeVisitor
{
public:
Dump2Osg(osgDB::Output &fw) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _fw(fw) {};
Dump2Osg( osgDB::Output &fw ) : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), _fw( fw )
{}
virtual void apply(osg::Node& node)
{
@ -64,8 +65,10 @@ bool TXPNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
const txp::TXPNode &txpNode = static_cast<const txp::TXPNode&>(obj);
if (!txpNode.getOptions().empty()) fw.indent() << "databaseOptions \"" << txpNode.getOptions() << "\""<<std::endl;
if (!txpNode.getArchiveName().empty()) fw.indent() << "databaseName \"" << txpNode.getArchiveName() << "\"" << std::endl;
if ( !txpNode.getOptions().empty() )
fw.indent() << "databaseOptions \"" << txpNode.getOptions() << "\"" << std::endl;
if ( !txpNode.getArchiveName().empty() )
fw.indent() << "databaseName \"" << txpNode.getArchiveName() << "\"" << std::endl;
osg::Group* grp = const_cast<osg::Group*>(txpNode.asGroup());

View File

@ -20,6 +20,41 @@ using namespace osg;
class RetestCallback : public osg::NodeCallback
{
public:
RetestCallback()
{
timer = osg::Timer::instance(); // get static timer
prevTime = 0; // should this be instantiated with current time?
}
virtual void operator () ( osg::Node * node, osg::NodeVisitor * nv )
{
osg::Group *pLOD = (osg::Group *) node;
osg::Group *n = NULL;
if ((pLOD->getNumChildren() > 0) &&
(n = (osg::Group *) pLOD->getChild(0)) &&
(n->getNumChildren() == 0))
{
osg::Timer_t curTime = timer->tick();
if ((prevTime + 2.0/timer->getSecondsPerTick() ) < curTime)
{
prevTime = curTime;
pLOD->removeChildren( 0, pLOD->getNumChildren());
}
}
NodeCallback::traverse( node, nv );
}
protected:
const osg::Timer* timer;
osg::Timer_t prevTime;
};
#define TXPNodeERROR(s) osg::notify(osg::NOTICE) << "txp::TXPNode::" << (s) << " error: "
@ -29,6 +64,7 @@ _originX(0.0),
_originY(0.0)
{
setNumChildrenRequiringUpdateTraversal(1);
setCullingActive(false);
}
TXPNode::TXPNode(const TXPNode& txpNode,const osg::CopyOp& copyop):
@ -52,18 +88,18 @@ void TXPNode::traverse(osg::NodeVisitor& nv)
{
switch(nv.getVisitorType())
{
case osg::NodeVisitor::CULL_VISITOR:
{
case osg::NodeVisitor::CULL_VISITOR:
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
if (cv)
{
//#define PRINT_TILEMAPP_TIMEINFO
#ifdef PRINT_TILEMAPP_TIMEINFO
//#define PRINT_TILEMAPP_TIMEINFO
#ifdef PRINT_TILEMAPP_TIMEINFO
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start = timer.tick();
std::cout<<"Doing visible tile search"<<std::endl;
#endif // PRINT_TILEMAPP_TIMEINFO
#endif // PRINT_TILEMAPP_TIMEINFO
osg::ref_ptr<TileMapper> tileMapper = new TileMapper;
tileMapper->setLODScale(cv->getLODScale());
@ -92,11 +128,11 @@ void TXPNode::traverse(osg::NodeVisitor& nv)
updateEye(nv);
break;
}
case osg::NodeVisitor::UPDATE_VISITOR:
}
case osg::NodeVisitor::UPDATE_VISITOR:
updateSceneGraph();
break;
default:
default:
break;
}
Group::traverse(nv);
@ -186,7 +222,10 @@ bool TXPNode::loadArchive()
_archive->GetHeader()->GetLodSize(0,tileSize);
_pageManager = new TXPPageManager;
_pageManager->Init(_archive.get());
// We are going to use _pageManager to manage lod 0 only, all other lod
// are managed by this OSG plugin
_pageManager->Init(_archive.get(), 1);
return true;
}
@ -227,7 +266,7 @@ void TXPNode::updateEye(osg::NodeVisitor& nv)
tile->GetTileLoc(x,y,lod);
if (lod==0)
{
osg::Node* node = addPagedLODTile(x,y,lod);
osg::Node* node = addPagedLODTile(x,y);
tile->SetLocalData(node);
//osg::notify(osg::NOTICE) << "Tile load: " << x << " " << y << " " << lod << std::endl;
}
@ -237,8 +276,12 @@ void TXPNode::updateEye(osg::NodeVisitor& nv)
}
}
osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod)
osg::Node* TXPNode::addPagedLODTile(int x, int y)
{
// For TerraPage 2.1 and over this method must only be use with lod = 0.
// If you look at the code that calls it, it is effectively called only when
// lod = 0. So all is OK
int lod = 0;
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\tile%d_%dx%d_%d.txp",_archive->getDir(),lod,x,y,_archive->getId());
@ -254,6 +297,7 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod)
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
pagedLOD->setUpdateCallback(new RetestCallback);
const trpgHeader* header = _archive->GetHeader();
trpgHeader::trpgTileType tileType;
@ -274,9 +318,10 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod)
}
else
{
_nodesToAdd.push_back(pagedLOD);
return pagedLOD;
}
_nodesToAdd.push_back(pagedLOD);
return pagedLOD;
}
}
void TXPNode::updateSceneGraph()

View File

@ -45,6 +45,7 @@
namespace txp
{
class TXPNode : public osg::Group
{
public:
@ -68,32 +69,35 @@ public:
TXPArchive* getArchive();
void setArchive(TXPArchive* archive) { _archive = archive; }
void setArchive( TXPArchive* archive )
{
_archive = archive;
}
virtual osg::BoundingSphere computeBound() const;
protected:
virtual ~TXPNode();
void updateEye(osg::NodeVisitor& nv);
void updateSceneGraph();
osg::Node* addPagedLODTile(int x, int y, int lod);
// Create a page lod for lod 0 with givin grid location (x,y)
osg::Node* addPagedLODTile(int x, int y);
std::string _archiveName;
std::string _options;
std::string _archiveName;
std::string _options;
osg::ref_ptr<TXPArchive> _archive;
osg::ref_ptr<TXPPageManager> _pageManager;
osg::ref_ptr<TXPArchive> _archive;
osg::ref_ptr<TXPPageManager> _pageManager;
double _originX;
double _originY;
osg::BoundingBox _extents;
double _originX;
double _originY;
osg::BoundingBox _extents;
std::vector<osg::Node*> _nodesToAdd;
std::vector<osg::Node*> _nodesToRemove;
std::vector<osg::Node*> _nodesToAdd;
std::vector<osg::Node*> _nodesToRemove;
};

View File

@ -42,7 +42,8 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
bool needToLoadChild = false;
unsigned maxRangeSize = _rangeList.size();
if (maxRangeSize!=0 && forceUseOfFirstChild) maxRangeSize=1;
if (maxRangeSize!=0 && forceUseOfFirstChild)
maxRangeSize=1;
for(unsigned int i=0;i<maxRangeSize;++i)
{
@ -50,9 +51,9 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
{
if (i<_children.size())
{
if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;
if (updateTimeStamp)
_perRangeDataList[i]._timeStamp=timeStamp;
//std::cout<<"PagedLOD::traverse() - Selecting child "<<i<<std::endl;
_children[i]->accept(nv);
lastChildTraversed = (int)i;
}
@ -72,7 +73,8 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
{
//std::cout<<" to child "<<numChildren-1<<std::endl;
if (updateTimeStamp) _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
if (updateTimeStamp)
_perRangeDataList[numChildren-1]._timeStamp=timeStamp;
_children[numChildren-1]->accept(nv);
}
@ -110,7 +112,7 @@ osg::BoundingSphere TXPPagedLOD::computeBound() const
if (_centerMode==USER_DEFINED_CENTER && _radius>=0.0f)
{
float tempRadius = osg::maximum( _radius, result.radius() );
float tempRadius = osg::maximum( _radius, result.radius() );
result = osg::BoundingSphere(_userDefinedCenter,tempRadius);
}
return result;

View File

@ -1,3 +1,4 @@
// -*-c++-*-
/***************************************************************************
* December 2003
*

File diff suppressed because it is too large Load Diff

View File

@ -79,11 +79,11 @@ class GeodeGroup : public osg::Group
public:
GeodeGroup() : osg::Group(), _geode(NULL)
{};
{}
GeodeGroup(const GeodeGroup& gg,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
osg::Group(gg, copyop), _geode(gg._geode)
{};
{}
META_Node(txp, GeodeGroup);
@ -103,6 +103,7 @@ protected:
class TXPArchive;
class childRefRead;
struct DeferredLightAttribute;
class TXPParser : public trpgSceneParser, public osg::Referenced
@ -116,14 +117,17 @@ public:
_archive = archive;
}
// Gets the archive
inline TXPArchive* getArchive() { return _archive; }
// Gets the archive
inline TXPArchive* getArchive()
{
return _archive;
}
// Scene parser
osg::Group *parseScene(
trpgReadBuffer &buf,
std::vector<osg::ref_ptr<osg::StateSet> > &materials,
std::vector<osg::ref_ptr<osg::Node> > &models,
std::map<int,osg::ref_ptr<osg::StateSet> > &materials,
std::map<int,osg::ref_ptr<osg::Node> > &models,
double realMinRange, double realMaxRange, double usedMaxRange);
// Returns the current Top Group
@ -139,13 +143,16 @@ public:
}
// Return the current material list (passed in to ParseScene())
inline std::vector<osg::ref_ptr<osg::StateSet> >* getMaterials()
inline std::map<int,osg::ref_ptr<osg::StateSet> >* getMaterials()
{
return _materials;
return _materialMap;
}
// Ensure material is loaded
inline void loadMaterial(int ix) { _archive->loadMaterial(ix); }
// Ensure material is loaded
inline void loadMaterial( int ix )
{
_archive->loadMaterial( ix );
}
// New to TerraPage 2.0 - local materials
std::vector<osg::ref_ptr<osg::StateSet> >* getLocalMaterials()
@ -157,7 +164,7 @@ public:
void loadLocalMaterials();
// Return the current model list
std::vector<osg::ref_ptr<osg::Node> >* getModels()
std::map<int,osg::ref_ptr<osg::Node> >* getModels()
{
return _models;
}
@ -260,9 +267,23 @@ public:
}
// gets tile center, from the top lod node
inline const osg::Vec3 getTileCenter() const { return _tileCenter; }
inline const osg::Vec3 getTileCenter() const
{
return _tileCenter;
}
inline void setCurrentNode(osg::Node* node) { _currentNode = node; }
inline void setCurrentNode( osg::Node* node )
{
_currentNode = node;
}
// After parsing this will return the number of trpgChildRef node found.
unsigned int GetNbChildrenRef() const;
// This will return the trpgChildRef node pointer associated with the index.
// Will return 0 if index is out of bound
const trpgChildRef* GetChildRef(unsigned int idx) const;
protected:
@ -300,13 +321,15 @@ protected:
void replaceTileLod(osg::Group*);
// Materials
std::vector<osg::ref_ptr<osg::StateSet> >* _materials;
typedef std::map<int,osg::ref_ptr<osg::StateSet> >* MaterialMapType;
MaterialMapType _materialMap;
// Local materials
std::vector<osg::ref_ptr<osg::StateSet> > _localMaterials;
// Model list
std::vector<osg::ref_ptr<osg::Node> >* _models;
typedef std::map<int,osg::ref_ptr<osg::Node> > OSGModelsMapType;
OSGModelsMapType* _models;
// Tile header
trpgTileHeader _tileHeader;
@ -342,6 +365,11 @@ protected:
// TEMP
osg::Geode* createBoundingBox(int x,int y, int lod);
private:
childRefRead *_childRefCB;
};
@ -353,7 +381,7 @@ class geomRead : public trpgr_Callback
public:
geomRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -365,7 +393,7 @@ class groupRead : public trpgr_Callback
{
public:
groupRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -376,10 +404,48 @@ class attachRead : public trpgr_Callback
{
public:
attachRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class childRefRead : public trpgr_Callback
{
public:
typedef std::vector<trpgChildRef> ChildRefList;
childRefRead(TXPParser *in_parse) : _parse(in_parse)
{}
void Reset();
void *Parse(trpgToken tok,trpgReadBuffer &buf);
// After parsing this will return the number of trpgChildRef node found.
unsigned int GetNbChildrenRef() const
{
return childRefList.size();
}
// This will return the trpgChildRef node associated with the index.
// this will return 0 if idx is out of bound
const trpgChildRef* GetChildRef(unsigned int idx) const
{
if(idx >= childRefList.size())
return 0;
else
return &childRefList[idx];
}
protected:
TXPParser *_parse;
private:
ChildRefList childRefList;
};
//----------------------------------------------------------------------------
@ -387,7 +453,7 @@ class lodRead : public trpgr_Callback
{
public:
lodRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -398,7 +464,7 @@ class tileHeaderRead : public trpgr_Callback
{
public:
tileHeaderRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -410,7 +476,7 @@ class modelRefRead : public trpgr_Callback
{
public:
modelRefRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -421,7 +487,7 @@ class billboardRead : public trpgr_Callback
{
public:
billboardRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -432,7 +498,7 @@ class lightRead: public trpgr_Callback
{
public:
lightRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -443,7 +509,7 @@ class layerRead: public trpgr_Callback
{
public:
layerRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
@ -454,7 +520,7 @@ class labelRead: public trpgr_Callback
{
public:
labelRead(TXPParser *in_parse) : _parse(in_parse)
{};
{}
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;

View File

@ -37,6 +37,7 @@ void TXPSeamLOD::traverse(osg::NodeVisitor& nv)
{
TileMapper* tileMapper = dynamic_cast<TileMapper*>(nv.getUserData());
if (tileMapper && !tileMapper->isTileNeighbourALowerLODLevel(_tid,_dx,_dy))
{
getChild(1)->accept(nv);

View File

@ -1,3 +1,4 @@
// -*-c++-*-
/***************************************************************************
* December 2003
*
@ -58,12 +59,15 @@ public:
virtual void traverse(osg::NodeVisitor& nv);
void setCenter( const osg::Vec3& center ) { _center = center; }
osg::Vec3 getCenter() { return _center; }
protected:
TileIdentifier _tid;
int _dx;
int _dy;
osg::Vec3 _center;
};
}

View File

@ -21,8 +21,10 @@ using namespace txp;
float TileMapper::getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const
{
if (withLODScale) return (pos-getEyeLocal()).length()*getLODScale();
else return (pos-getEyeLocal()).length();
if (withLODScale)
return (pos-getEyeLocal()).length()*getLODScale();
else
return (pos-getEyeLocal()).length();
}
inline TileMapper::value_type distance(const osg::Vec3& coord,const osg::Matrix& matrix)
@ -30,7 +32,10 @@ inline TileMapper::value_type distance(const osg::Vec3& coord,const osg::Matrix&
//std::cout << "distance("<<coord<<", "<<matrix<<")"<<std::endl;
return -((TileMapper::value_type)coord[0]*(TileMapper::value_type)matrix(0,2)+(TileMapper::value_type)coord[1]*(TileMapper::value_type)matrix(1,2)+(TileMapper::value_type)coord[2]*(TileMapper::value_type)matrix(2,2)+matrix(3,2));
return -((TileMapper::value_type)coord[0]*(TileMapper::value_type)matrix(0,2)+
(TileMapper::value_type)coord[1]*(TileMapper::value_type)matrix(1,2)+
(TileMapper::value_type)coord[2]*(TileMapper::value_type)matrix(2,2)+
matrix(3,2));
}
float TileMapper::getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScale) const
@ -38,8 +43,10 @@ float TileMapper::getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScal
const osg::Matrix& matrix = *_modelviewStack.back();
float dist = distance(pos,matrix);
if (withLODScale) return dist*getLODScale();
else return dist;
if (withLODScale)
return dist*getLODScale();
else
return dist;
}
void TileMapper::apply(osg::Node& node)
@ -50,7 +57,8 @@ void TileMapper::apply(osg::Node& node)
return;
}
if (isCulled(node)) return;
if (isCulled(node))
return;
// push the culling mode.
pushCurrentMask();
@ -69,11 +77,12 @@ void TileMapper::apply(osg::Group& node)
return;
}
if (isCulled(node)) return;
if (isCulled(node))
return;
// push the culling mode.
pushCurrentMask();
TileIdentifier* tid = dynamic_cast<TileIdentifier*>(node.getUserData());
if (tid)
@ -95,9 +104,9 @@ void TileMapper::apply(osg::Group& node)
#if 0
std::cout<<"found Group="<<tid->lod
<<" X="<<tid->x
<<" Y="<<tid->y
<<" ptr="<<&node<<std::endl;
<<" X="<<tid->x
<<" Y="<<tid->y
<<" ptr="<<&node<<std::endl;
std::cout<<" inheritance list "<<_tileStack.size()<<std::endl;
for(TileStack::iterator itr=_tileStack.begin();
@ -144,7 +153,8 @@ void TileMapper::apply(osg::Geode&)
void TileMapper::apply(osg::PagedLOD& node)
{
if (isCulled(node)) return;
if (isCulled(node))
return;
// push the culling mode.
pushCurrentMask();
@ -171,9 +181,9 @@ void TileMapper::apply(osg::PagedLOD& node)
#if 0
std::cout<<"found txpPagedLOD LOD="<<txpPagedLOD->_tileIdentifier.lod
<<" X="<<txpPagedLOD->_tileIdentifier.x
<<" Y="<<txpPagedLOD->_tileIdentifier.y
<<" ptr="<<txpPagedLOD<<std::endl;
<<" X="<<txpPagedLOD->_tileIdentifier.x
<<" Y="<<txpPagedLOD->_tileIdentifier.y
<<" ptr="<<txpPagedLOD<<std::endl;
std::cout<<" inheritance list "<<_tileStack.size()<<std::endl;
for(TileStack::iterator itr=_tileStack.begin();
@ -187,12 +197,11 @@ void TileMapper::apply(osg::PagedLOD& node)
<<" ptr="<<itr->second<<std::endl;
}
osg::StateSet* stateset = txpPagedLOD->getOrCreateStateSet();
osg::Material* material = new osg::Material;
material->setColorMode(osg::Material::OFF);
stateset->setAttribute(material);
switch(txpPagedLOD->_tileIdentifier.lod)
{
case(0): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); break;
@ -201,14 +210,11 @@ void TileMapper::apply(osg::PagedLOD& node)
case(3): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,1.0f,1.0f)); break;
case(4): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,1.0f,1.0f)); break;
}
#endif
}
_tileStack.pop_back();
}
// pop the culling mode.
popCurrentMask();
}
@ -360,20 +366,23 @@ void TileMapper::checkValidityOfAllVisibleTiles()
_tileMap.insert(TileMap::value_type(aitr->back().first,*aitr));
}
} while (!toRemoveList.empty());
}
while (!toRemoveList.empty());
#if 0
if (!_blackListedNodeSet.empty()) std::cout<<"********** We have blacked list "<<_blackListedNodeSet.size()<<std::endl;
if ( !_blackListedNodeSet.empty() )
std::cout << "********** We have blacked list " << _blackListedNodeSet.size() << std::endl;
std::cout<<"TileMap contains "<<_tileMap.size()<<std::endl;
for(TileMap::iterator itr=_tileMap.begin();
itr!=_tileMap.end();
++itr)
{
std::cout<<" tile="<<itr->first.lod
<<" X="<<itr->first.x
<<" Y="<<itr->first.y<<std::endl;
std::cout<<" tile="<<itr->first.lod
<<" X="<<itr->first.x
<<" Y="<<itr->first.y<<std::endl;
}
#endif
@ -388,7 +397,6 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
return false;
}
// find the tiles parents.
TileMap::const_iterator itr = _tileMap.find(tid);
if (itr==_tileMap.end())
@ -396,8 +404,8 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
// not found tile in _tileMap, what should we do??
// return true as a fallback right now.
#if 0
std::cout<<"TileMapper::isTileNeighbourALowerLODLevel() Not found tile in map,"<<std::endl;
std::cout<<" LOD="<<tid.lod<<" X="<<tid.x<<" Y="<<tid.y<<std::endl;
std::cout << "TileMapper::isTileNeighbourALowerLODLevel() Not found tile in map," << std::endl;
std::cout << " LOD=" << tid.lod << " X=" << tid.x << " Y=" << tid.y << std::endl;
#endif
return true;
}
@ -409,7 +417,7 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
if (!tile)
{
// no tile, so must assume taht neight is now at a lower level
// no tile, so must assume that neighbor is now at a lower level
return false;
}
@ -424,10 +432,10 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
const TileIdentifier& parent_tid = parent->first;
bool parentHasNorthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y+1,parent_tid.lod))!=0;
bool parentHasEastNeighour = _tileMap.count(TileIdentifier(parent_tid.x+1,parent_tid.y,parent_tid.lod))!=0;
bool parentHasSouthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y-1,parent_tid.lod))!=0;
bool parentHasWestNeighour = _tileMap.count(TileIdentifier(parent_tid.x-1,parent_tid.y,parent_tid.lod))!=0;
bool parentHasNorthNeighour = _tileMap.count(TileIdentifier(parent_tid.x, parent_tid.y+1,parent_tid.lod))!=0;
bool parentHasEastNeighour = _tileMap.count(TileIdentifier(parent_tid.x+1,parent_tid.y, parent_tid.lod))!=0;
bool parentHasSouthNeighour = _tileMap.count(TileIdentifier(parent_tid.x, parent_tid.y-1,parent_tid.lod))!=0;
bool parentHasWestNeighour = _tileMap.count(TileIdentifier(parent_tid.x-1,parent_tid.y, parent_tid.lod))!=0;
// identify whether the tile is a NE/SE/SW/NW tile relative to its parent.
@ -438,14 +446,18 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
if (delta.x()>=0.0f)
{
// NE
if (dy==1) return parentHasNorthNeighour;
else if (dx==1) return parentHasEastNeighour;
if (dy==1)
return parentHasNorthNeighour;
else if (dx==1)
return parentHasEastNeighour;
}
else
{
// NW
if (dy==1) return parentHasNorthNeighour;
else if (dx==-1) return parentHasWestNeighour;
if (dy==1)
return parentHasNorthNeighour;
else if (dx==-1)
return parentHasWestNeighour;
}
}
else // south side
@ -453,14 +465,18 @@ bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx
if (delta.x()>=0.0f)
{
// SE
if (dy==-1) return parentHasSouthNeighour;
else if (dx==1) return parentHasEastNeighour;
if (dy==-1)
return parentHasSouthNeighour;
else if (dx==1)
return parentHasEastNeighour;
}
else
{
// SW
if (dy==-1) return parentHasSouthNeighour;
else if (dx==-1) return parentHasWestNeighour;
if (dy==-1)
return parentHasSouthNeighour;
else if (dx==-1)
return parentHasWestNeighour;
}
}

View File

@ -30,18 +30,21 @@ struct TileIdentifier : public osg::Referenced
TileIdentifier():
x(-1),
y(-1),
lod(-1) {}
lod(-1)
{}
TileIdentifier(int ax, int ay, int alod):
x(ax),
y(ay),
lod(alod) {}
lod(alod)
{}
TileIdentifier(const TileIdentifier& rhs):
osg::Referenced(),
x(rhs.x),
y(rhs.y),
lod(rhs.lod) {}
lod(rhs.lod)
{}
TileIdentifier& operator = (const TileIdentifier& rhs)
{
@ -91,7 +94,10 @@ public:
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
virtual osg::Vec3 getEyePoint() const { return getEyeLocal(); }
virtual osg::Vec3 getEyePoint() const
{
return getEyeLocal();
}
virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const;
virtual float getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScale) const;

View File

@ -14,9 +14,9 @@
*/
/* trdll.h
Windows Only
Windows Only
This header file defines the declaration macros for DLLs.
This header file defines the declaration macros for DLLs.
*/
// Export/import declaration for classes and functions

View File

@ -14,8 +14,8 @@
*/
/* trpage_basic.cpp
Methods for checkable base class.
*/
Methods for checkable base class.
*/
#include <stdlib.h>
#include <stdio.h>
@ -23,20 +23,22 @@
#include <trpage_io.h>
/* Checkable
This is just a class that checks validity.
Starts out invalid.
*/
This is just a class that checks validity.
Starts out invalid.
*/
trpgCheckable::trpgCheckable()
{
valid = false;
valid = false;
handle = -1;
writeHandle = false;
}
trpgCheckable::~trpgCheckable()
{
valid = false;
valid = false;
}
bool trpgCheckable::isValid() const
{
return valid;
return valid;
}

View File

@ -18,19 +18,19 @@
#include <string.h>
/* trpage_compat.cpp
This file and the accompanying trpage_compat.h contain objects and procedures
used to maintain compatibility between versions of TerraPage. In particular, the
ability to read older versions of TerraPage and newer applications.
This file and the accompanying trpage_compat.h contain objects and procedures
used to maintain compatibility between versions of TerraPage. In particular, the
ability to read older versions of TerraPage and newer applications.
*/
*/
#include <trpage_geom.h>
#include <trpage_read.h>
#include <trpage_compat.h>
/* Old short Material definition from 1.0.
{secret}
*/
{secret}
*/
class trpgShortMaterial {
public:
// Full trpgMaterial definition this one is based on
@ -56,64 +56,65 @@ bool trpgMatTable1_0::Read(trpgReadBuffer &buf)
std::vector<trpgMaterial> baseMats;
try {
buf.Get(numTable);
buf.Get(numMat);
if (numTable <= 0 || numMat < 0) throw 1;
buf.Get(numTable);
buf.Get(numMat);
if (numTable <= 0 || numMat < 0) throw 1;
// Short material tables are always full size
shortTable.resize(numTable*numMat);
// Short material tables are always full size
shortTable.resize(numTable*numMat);
// Look for short material table
buf.GetToken(matTok,len);
if (matTok == TRPGSHORTMATTABLE) {
int32 numTex,texId;
buf.PushLimit(len);
// Look for short material table
buf.GetToken(matTok,len);
if (matTok == TRPGSHORTMATTABLE) {
int32 numTex,texId;
buf.PushLimit(len);
for (i=0;i<(unsigned int)numTable;i++)
for (j=0;j<(unsigned int)numMat;j++) {
trpgShortMaterial &smat = shortTable[i*numMat+j];
buf.Get(smat.baseMat);
buf.Get(numTex);
trpgShortMaterial &smat = shortTable[i*numMat+j];
buf.Get(smat.baseMat);
buf.Get(numTex);
for (k=0;k<(unsigned int)numTex;k++) {
buf.Get(texId);
smat.texids.push_back(texId);
}
}
buf.PopLimit();
buf.Get(texId);
smat.texids.push_back(texId);
}
}
buf.PopLimit();
// Now read the base materials
int32 numBaseMat;
buf.Get(numBaseMat);
if (numBaseMat < 0) throw 1;
baseMats.resize(numBaseMat);
// Now read the base materials
int32 numBaseMat;
buf.Get(numBaseMat);
if (numBaseMat < 0) throw 1;
baseMats.resize(numBaseMat);
for (i=0;i<(unsigned int)numBaseMat;i++) {
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
mat.Reset();
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
baseMats[i] = mat;
}
}
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
mat.Reset();
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
baseMats[i] = mat;
}
}
}
catch (...) {
return false;
return false;
}
// Now convert to the new style material table
for (i=0;i<shortTable.size();i++) {
trpgShortMaterial &shortMat = shortTable[i];
trpgMaterial &baseMat = baseMats[shortMat.baseMat];
matTables.push_back(baseMat);
trpgMaterial &newMat = matTables[matTables.size()-1];
newMat.SetNumTexture(shortMat.texids.size());
for (j=0;j<shortMat.texids.size();j++) {
int texId;
trpgTextureEnv texEnv;
baseMat.GetTexture(j,texId,texEnv);
newMat.SetTexture(j,shortMat.texids[j],texEnv);
}
trpgShortMaterial &shortMat = shortTable[i];
trpgMaterial &baseMat = baseMats[shortMat.baseMat];
AddMaterial(baseMat,false);
trpgMaterial newMat = baseMat;
newMat.SetNumTexture(shortMat.texids.size());
for (j=0;j<shortMat.texids.size();j++) {
int texId;
trpgTextureEnv texEnv;
baseMat.GetTexture(j,texId,texEnv);
newMat.SetTexture(j,shortMat.texids[j],texEnv);
}
}
valid = true;
@ -123,28 +124,31 @@ bool trpgMatTable1_0::Read(trpgReadBuffer &buf)
bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
// Create one short material for every material
std::vector<trpgShortMaterial> shortMats;
shortMats.resize(numTable*numMat);
// Iterate over the existing materials
int i;
for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = matTables[i];
// Fill in the short material
trpgShortMaterial &sMat = shortMats[i];
sMat.baseMat = 0;
int numTex;
mat.GetNumTexture(numTex);
for (int j=0;j<numTex;j++) {
int texId;
trpgTextureEnv texEnv;
mat.GetTexture(j,texId,texEnv);
sMat.texids.push_back(texId);
sMat.baseMat = i;
}
int i=0;
MaterialMapType::iterator itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++) {
//for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = itr->second; //matTables[i];
// Fill in the short material
trpgShortMaterial &sMat = shortMats[i];
sMat.baseMat = 0;
int numTex;
mat.GetNumTexture(numTex);
for (int j=0;j<numTex;j++) {
int texId;
trpgTextureEnv texEnv;
mat.GetTexture(j,texId,texEnv);
sMat.texids.push_back(texId);
sMat.baseMat = i;
}
i++;
}
// Write the 1.0 material table
@ -154,23 +158,27 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
// Write the short materials
buf.Begin(TRPGSHORTMATTABLE);
for (i=0;i<(int)shortMats.size();i++) {
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
unsigned int j;
for (j=0;j<sMat.texids.size();j++)
buf.Add(sMat.texids[j]);
for (i=0;i<static_cast<int>(shortMats.size());i++) {
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
unsigned int j;
for (j=0;j<sMat.texids.size();j++)
buf.Add(sMat.texids[j]);
}
buf.End();
// Write the regular materials
buf.Add(numTable*numMat);
for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = matTables[i];
// This will be bigger than the old 1.0 material, but it doesn't matter since
// the new stuff is on the end.
mat.Write(buf);
buf.Add((int)materialMap.size());//numTable*numMat);
//for (i=0;i<numTable*numMat;i++) {
itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++) {
trpgMaterial &mat = itr->second; //matTables[i];
// This will be bigger than the old 1.0 material, but it doesn't matter since
// the new stuff is on the end.
mat.Write(buf);
}
// Close Mat Table
@ -191,13 +199,13 @@ bool trpgTexture1_0::Read(trpgReadBuffer &buf)
mode = External;
try {
char texName[1024];
buf.Get(texName,1023);
SetName(texName);
buf.Get(useCount);
char texName[1024];
buf.Get(texName,1023);
SetName(texName);
buf.Get(useCount);
}
catch (...) {
return false;
return false;
}
return true;
@ -207,7 +215,7 @@ bool trpgTexture1_0::Write(trpgWriteBuffer &buf)
{
// Can only deal with external textures in 1.0
if (mode != External)
return false;
return false;
// Write the name and use count
buf.Add(name);
@ -226,16 +234,17 @@ bool trpgTexTable1_0::Read(trpgReadBuffer &buf)
int32 numTex;
try {
buf.Get(numTex);
texList.resize(numTex);
for (unsigned int i=0;i<(unsigned int)numTex;i++) {
trpgTexture1_0 tex1_0;
tex1_0.Read(buf);
texList[i] = tex1_0;
}
buf.Get(numTex);
//texList.resize(numTex);
for (int i=0;i<numTex;i++) {
trpgTexture1_0 tex1_0;
tex1_0.Read(buf);
AddTexture(tex1_0);
//texList[i] = tex1_0;
}
}
catch (...) {
return false;
return false;
}
valid = true;
@ -247,16 +256,18 @@ bool trpgTexTable1_0::Write(trpgWriteBuffer &buf)
int32 numTex;
if (!isValid())
return false;
return false;
buf.Begin(TRPGTEXTABLE);
numTex = texList.size();
numTex = textureMap.size();
buf.Add(numTex);
for (unsigned int i=0;i<texList.size();i++) {
trpgTexture1_0 tex1_0;
tex1_0 = texList[i];
if (!tex1_0.Write(buf))
return false;
TextureMapType::const_iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++) {
trpgTexture1_0 tex1_0;
tex1_0 = itr->second;
if (!tex1_0.Write(buf))
return false;
}
buf.End();
@ -272,12 +283,12 @@ trpgTileTable1_0::trpgTileTable1_0(const trpgTileTable& /*inTable*/)
bool trpgTileTable1_0::Write(trpgWriteBuffer &buf)
{
try {
buf.Begin(TRPGTILETABLE);
buf.Add("");
buf.End();
buf.Begin(TRPGTILETABLE);
buf.Add("");
buf.End();
}
catch (...) {
return false;
return false;
}
return true;

View File

@ -34,13 +34,13 @@ public:
trpgMatTable1_0(const trpgMatTable &);
/* This read method overrides the one from trpgMatTable and knows
how to read the old school material tables.
how to read the old school material tables.
*/
bool Read(trpgReadBuffer &);
bool Read(trpgReadBuffer &);
/* This write method can write a 2.0 material table as 1.0
style for backward compatibility.
style for backward compatibility.
*/
bool Write(trpgWriteBuffer &);
bool Write(trpgWriteBuffer &);
protected:
};
@ -56,13 +56,13 @@ public:
trpgTexTable1_0(const trpgTexTable &);
/* This read method overrides the one from trpgTexTable and
knows how to read the old style texture table.
knows how to read the old style texture table.
*/
bool Read(trpgReadBuffer &);
bool Read(trpgReadBuffer &);
/* The write method can write a 2.0 texture table as 1.0
style for backward compatibility.
style for backward compatibility.
*/
bool Write(trpgWriteBuffer &);
bool Write(trpgWriteBuffer &);
protected:
};
@ -76,9 +76,9 @@ public:
trpgTexture1_0 operator = (const trpgTexture &);
// Knows how to read old style textures
bool Read(trpgReadBuffer &);
bool Read(trpgReadBuffer &);
// Can write old style textures
bool Write(trpgWriteBuffer &);
bool Write(trpgWriteBuffer &);
protected:
};
@ -90,7 +90,7 @@ class trpgTileTable1_0 : public trpgTileTable {
public:
trpgTileTable1_0(const trpgTileTable &);
// Can write old style tile table
bool Write(trpgWriteBuffer &);
bool Write(trpgWriteBuffer &);
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18,22 +18,22 @@
#include <string.h>
/* trpage_header.cpp
Source for trpgHeader methods.
The only reason to change this is if you want to add something
to the header definition.
*/
Source for trpgHeader methods.
The only reason to change this is if you want to add something
to the header definition.
*/
#include <trpage_geom.h>
#include <trpage_read.h>
/* Write Header class
Fill it in and write it out.
*/
Fill it in and write it out.
*/
// Constructor
trpgHeader::trpgHeader()
{
Reset();
Reset();
}
trpgHeader::~trpgHeader()
{
@ -42,152 +42,181 @@ trpgHeader::~trpgHeader()
// Validity check
bool trpgHeader::isValid() const
{
if (numLods <= 0)
{
strcpy(errMess, "Number of LOD <= 0");
return false;
}
if (sw.x == ne.x && sw.y == ne.y)
{
strcpy(errMess, "Mbr is invalid");
// We also need to check that this is a 'master' archive here.
if((verMajor>=TRPG_NOMERGE_VERSION_MAJOR) && (verMinor>=TRPG_NOMERGE_VERSION_MINOR))
{
return true;
}
else {
if (numLods <= 0)
{
strcpy(errMess, "Number of LOD <= 0");
return false;
}
if (sw.x == ne.x && sw.y == ne.y)
{
strcpy(errMess, "Mbr is invalid");
return false;
}
return false;
}
}
return true;
return true;
}
// Reset contents
void trpgHeader::Reset()
{
// Initialize to a default state
verMinor = TRPG_VERSION_MINOR;
verMajor = TRPG_VERSION_MAJOR;
dbVerMinor = 0;
dbVerMajor = 0;
origin = trpg3dPoint(0,0,0);
sw = ne = trpg2dPoint(0,0);
tileType = DatabaseLocal;
// Initialize to a default state
verMinor = TRPG_VERSION_MINOR;
verMajor = TRPG_VERSION_MAJOR;
dbVerMinor = 0;
dbVerMajor = 0;
origin = trpg3dPoint(0,0,0);
sw = ne = trpg2dPoint(0,0);
tileType = DatabaseLocal;
numLods = 0;
lodSizes.resize(0);
lodRanges.resize(0);
tileSize.resize(0);
maxGroupID = -1;
errMess[0] = '\0';
numLods = 0;
lodSizes.resize(0);
lodRanges.resize(0);
tileSize.resize(0);
maxGroupID = -1;
flags = 0;
errMess[0] = '\0';
cols = -1;
rows = -1;
}
// Set functions
void trpgHeader::SetVersion(int32 vmaj,int32 vmin)
{
verMinor = vmin;
verMajor = vmaj;
verMinor = vmin;
verMajor = vmaj;
}
void trpgHeader::SetDbVersion(int32 vmaj,int32 vmin)
{
dbVerMinor = vmin;
dbVerMajor = vmaj;
dbVerMinor = vmin;
dbVerMajor = vmaj;
}
void trpgHeader::SetTileSize(int id,const trpg2dPoint &pt)
{
if (id < 0 || id >= (int)tileSize.size()) return;
tileSize[id] = pt;
if (id < 0 || id >= (int)tileSize.size()) return;
tileSize[id] = pt;
}
void trpgHeader::SetOrigin(const trpg3dPoint &pt)
{
origin = pt;
origin = pt;
}
void trpgHeader::SetExtents(const trpg2dPoint &in_sw,const trpg2dPoint &in_ne)
{
sw = in_sw;
ne = in_ne;
sw = in_sw;
ne = in_ne;
}
void trpgHeader::SetTileOriginType(trpgTileType type)
{
tileType = type;
tileType = type;
}
void trpgHeader::SetNumLods(int no)
{
if (no < 0) return;
numLods = no;
if (no < 0) return;
numLods = no;
lodSizes.resize(no);
lodRanges.resize(no);
lodSizes.resize(no);
lodRanges.resize(no);
}
void trpgHeader::SetLodSize(int no,const trpg2iPoint &pt)
{
if (no < 0 || no >= numLods)
return;
if (no < 0 || no >= numLods)
return;
lodSizes[no] = pt;
lodSizes[no] = pt;
}
void trpgHeader::SetLodSize(const trpg2iPoint *pt)
{
for (int i=0;i<numLods;i++)
lodSizes[i] = pt[i];
for (int i=0;i<numLods;i++)
lodSizes[i] = pt[i];
}
void trpgHeader::SetLodRange(int no,float64 r)
{
if (no < 0 || no >= numLods)
return;
if (no < 0 || no >= numLods)
return;
lodRanges[no] = r;
lodRanges[no] = r;
}
void trpgHeader::SetLodRange(const float64 *r)
{
for (int i=0;i<numLods;i++)
lodRanges[i] = r[i];
for (int i=0;i<numLods;i++)
lodRanges[i] = r[i];
}
void trpgHeader::AddLod(const trpg2iPoint &pt,const trpg2dPoint &sz,float64 r)
{
lodRanges.push_back(r);
lodSizes.push_back(pt);
tileSize.push_back(sz);
numLods++;
lodRanges.push_back(r);
lodSizes.push_back(pt);
tileSize.push_back(sz);
numLods++;
}
void trpgHeader::SetLod(const trpg2iPoint &pt,const trpg2dPoint &sz,float64 r,unsigned int lod)
{
if (lodRanges.size()<=lod)
lodRanges.resize(lod+1);
lodRanges[lod]=r;
if (lodSizes.size()<=lod)
lodSizes.resize(lod+1);
lodSizes[lod]=pt;
if (tileSize.size()<=lod)
tileSize.resize(lod+1);
tileSize[lod]=sz;
if (numLods<=static_cast<int>(lod))
numLods=lod+1;
}
void trpgHeader::SetMaxGroupID(int id)
{
maxGroupID = id;
maxGroupID = id;
}
int trpgHeader::AddGroupID(void)
{
maxGroupID++;
return maxGroupID;
maxGroupID++;
return maxGroupID;
}
// Write out to a buffer
bool trpgHeader::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGHEADER);
buf.Add((int32)verMajor);
buf.Add((int32)verMinor);
buf.Add((int32)dbVerMajor);
buf.Add((int32)dbVerMinor);
buf.Add(origin);
buf.Add(sw);
buf.Add(ne);
buf.Add((uint8)tileType);
buf.Begin(TRPGHEADER);
buf.Add((int32)verMajor);
buf.Add((int32)verMinor);
buf.Add((int32)dbVerMajor);
buf.Add((int32)dbVerMinor);
buf.Add(origin);
buf.Add(sw);
buf.Add(ne);
buf.Add((uint8)tileType);
buf.Add((int32)numLods);
buf.Add((int32)numLods);
buf.Begin(TRPGHEAD_LODINFO);
for (int i=0;i<numLods;i++) {
buf.Add(lodSizes[i]);
buf.Add(lodRanges[i]);
buf.Add(tileSize[i]);
}
buf.End();
buf.Begin(TRPGHEAD_LODINFO);
for (int i=0;i<numLods;i++) {
buf.Add(lodSizes[i]);
buf.Add(lodRanges[i]);
buf.Add(tileSize[i]);
}
buf.End();
buf.Add(maxGroupID);
buf.Add(maxGroupID);
buf.End();
if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) {
buf.Add(flags);
buf.Add(rows);
buf.Add(cols);
}
return true;
buf.End();
return true;
}
/* ********
@ -197,128 +226,133 @@ bool trpgHeader::Write(trpgWriteBuffer &buf)
// Get Functions
bool trpgHeader::GetVersion(int32 &vmaj,int32 &vmin) const
{
if (!isValid()) return false;
vmin = verMinor;
vmaj = verMajor;
return true;
if (!isValid()) return false;
vmin = verMinor;
vmaj = verMajor;
return true;
}
bool trpgHeader::GetDbVersion(int32 &vmaj,int32 &vmin) const
{
if (!isValid()) return false;
vmaj = dbVerMajor;
vmin = dbVerMinor;
return true;
if (!isValid()) return false;
vmaj = dbVerMajor;
vmin = dbVerMinor;
return true;
}
bool trpgHeader::GetTileSize(int id,trpg2dPoint &pt) const
{
if (!isValid()) return false;
if (id < 0 || id >= (int)tileSize.size()) return false;
pt = tileSize[id];
return true;
if (!isValid()) return false;
if (id < 0 || id >= (int)tileSize.size()) return false;
pt = tileSize[id];
return true;
}
bool trpgHeader::GetOrigin(trpg3dPoint &pt) const
{
if (!isValid()) return false;
pt = origin;
return true;
if (!isValid()) return false;
pt = origin;
return true;
}
bool trpgHeader::GetTileOriginType(trpgTileType &type) const
{
if (!isValid()) return false;
type = tileType;
return true;
if (!isValid()) return false;
type = tileType;
return true;
}
bool trpgHeader::GetNumLods(int32 &no) const
{
if (!isValid()) return false;
no = numLods;
return true;
if (!isValid()) return false;
no = numLods;
return true;
}
bool trpgHeader::GetLodSize(int32 id,trpg2iPoint &pt) const
{
if (!isValid() || (id < 0 || id >= numLods)) return false;
pt = lodSizes[id];
return true;
if (!isValid() || (id < 0 || id >= numLods)) return false;
pt = lodSizes[id];
return true;
}
bool trpgHeader::GetLodRange(int32 id,float64 &range) const
{
if (!isValid() || (id < 0 || id >= numLods)) return false;
range = lodRanges[id];
return true;
if (!isValid() || (id < 0 || id >= numLods)) return false;
range = lodRanges[id];
return true;
}
bool trpgHeader::GetExtents(trpg2dPoint &osw,trpg2dPoint &one) const
{
if (!isValid()) return false;
osw = sw;
one = ne;
return true;
if (!isValid()) return false;
osw = sw;
one = ne;
return true;
}
bool trpgHeader::GetMaxGroupID(int &id) const
{
id = maxGroupID;
return true;
id = maxGroupID;
return true;
}
// Read in the header
bool trpgHeader::Read(trpgReadBuffer &buf)
{
uint8 i8;
trpgToken tok;
bool status;
int32 len;
uint8 i8;
trpgToken tok;
bool status;
int32 len;
try {
buf.Get(verMajor);
buf.Get(verMinor);
buf.Get(dbVerMajor);
buf.Get(dbVerMinor);
buf.Get(origin);
buf.Get(sw);
buf.Get(ne);
buf.Get(i8); tileType = (trpgTileType)i8;
buf.Get(numLods);
if (numLods < 0) throw 1;
try {
buf.Get(verMajor);
buf.Get(verMinor);
buf.Get(dbVerMajor);
buf.Get(dbVerMinor);
buf.Get(origin);
buf.Get(sw);
buf.Get(ne);
buf.Get(i8); tileType = (trpgTileType)i8;
buf.Get(numLods);
if (numLods < 0) throw 1;
// Read in the LOD range info
buf.GetToken(tok,len);
if (tok != TRPGHEAD_LODINFO) throw 1;
buf.PushLimit(len);
status = ReadLodInfo(buf);
buf.PopLimit();
if (!status) throw 1;
// Read in the LOD range info
buf.GetToken(tok,len);
if (tok != TRPGHEAD_LODINFO) throw 1;
buf.PushLimit(len);
status = ReadLodInfo(buf);
buf.PopLimit();
if (!status) throw 1;
// Added after the first version (but still in 1.0)
buf.Get(maxGroupID);
}
// Added after the first version (but still in 1.0)
buf.Get(maxGroupID);
if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) {
buf.Get(flags);
buf.Get(rows);
buf.Get(cols);
}
}
catch (...) {
return false;
}
catch (...) {
return false;
}
return isValid();
return isValid();
}
// Read the LOD info (seperate token)
bool trpgHeader::ReadLodInfo(trpgReadBuffer &buf)
{
float64 range;
trpg2iPoint pt;
trpg2dPoint sz;
float64 range;
trpg2iPoint pt;
trpg2dPoint sz;
try {
for (int i=0;i<numLods;i++) {
buf.Get(pt);
buf.Get(range);
buf.Get(sz);
lodSizes.push_back(pt);
lodRanges.push_back(range);
tileSize.push_back(sz);
}
}
catch (...) {
return false;
}
try {
for (int i=0;i<numLods;i++) {
buf.Get(pt);
buf.Get(range);
buf.Get(sz);
lodSizes.push_back(pt);
lodRanges.push_back(range);
tileSize.push_back(sz);
}
}
catch (...) {
return false;
}
return true;
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,13 @@
*/
/* trpage_label.cpp
Methods for the trpgLable object and its associated support structure
including trpgTextStyle and trpgTextStyleTable.
*/
Methods for the trpgLable object and its associated support structure
including trpgTextStyle and trpgTextStyleTable.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <trpage_geom.h>
@ -114,9 +114,9 @@ bool trpgTextStyle::Write(trpgWriteBuffer &buf)
buf.Begin(TRPG_TEXT_STYLE_BASIC);
buf.Add(font);
buf.Add(bold);
buf.Add(italic);
buf.Add(underline);
buf.Add((int32)bold);
buf.Add((int32)italic);
buf.Add((int32)underline);
buf.Add(characterSize);
buf.Add(matId);
buf.End();
@ -129,8 +129,9 @@ bool trpgTextStyle::Write(trpgWriteBuffer &buf)
// TextStyle CB
// Used to parse tokens from the text style structure.
// If we do it this way it's easier to expand later.
class textStyleCB : public trpgr_Callback {
public:
class textStyleCB : public trpgr_Callback
{
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgTextStyle *style;
};
@ -141,8 +142,10 @@ void * textStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf)
int iVal;
float32 fVal;
try {
switch (tok) {
try
{
switch (tok)
{
case TRPG_TEXT_STYLE_BASIC:
buf.Get(sVal);
style->SetFont(sVal);
@ -161,7 +164,8 @@ void * textStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf)
break;
}
}
catch (...) {
catch (...)
{
return NULL;
}
@ -196,7 +200,7 @@ bool trpgTextStyle::isValid(void) const
bool trpgTextStyle::operator == (const trpgTextStyle& in) const
{
if (font.compare(in.font) != 0)
if (font != in.font)
return false;
if (bold != in.bold ||
@ -220,19 +224,22 @@ trpgTextStyleTable::trpgTextStyleTable()
{
Reset();
}
trpgTextStyleTable::~trpgTextStyleTable()
{
}
void trpgTextStyleTable::Reset()
{
styles.resize(0);
styleMap.clear();
}
bool trpgTextStyleTable::isValid() const
{
for (unsigned int i=0;i<styles.size();i++)
if (!styles[i].isValid())
//for (int i=0;i<styles.size();i++)
StyleMapType::const_iterator itr = styleMap.begin();
for ( ; itr != styleMap.end( ); itr++)
if (!itr->second.isValid())
return false;
return true;
@ -240,30 +247,38 @@ bool trpgTextStyleTable::isValid() const
int trpgTextStyleTable::AddStyle(const trpgTextStyle &style)
{
styles.push_back(style);
return styles.size() -1;
int handle = style.GetHandle();
if(handle==-1) {
handle = styleMap.size();
}
styleMap[handle] = style;
return handle;
}
int trpgTextStyleTable::FindAddStyle(const trpgTextStyle &style)
{
for (unsigned int i=0;i<styles.size();i++)
if (styles[i] == style)
return i;
StyleMapType::const_iterator itr = styleMap.begin();
for ( ; itr != styleMap.end( ); itr++)
if (itr->second == style)
return itr->first;
return AddStyle(style);
}
int trpgTextStyleTable::GetNumStyle() const
{
return styles.size();
return styleMap.size();
}
const trpgTextStyle *trpgTextStyleTable::GetStyleRef(int id) const
{
if (id < 0 || id >= (int)styles.size())
if (id < 0)
return NULL;
return &styles[id];
StyleMapType::const_iterator itr = styleMap.find(id);
if(itr == styleMap.end())
return NULL;
return &itr->second;
}
bool trpgTextStyleTable::Write(trpgWriteBuffer &buf)
@ -274,12 +289,13 @@ bool trpgTextStyleTable::Write(trpgWriteBuffer &buf)
buf.Begin(TRPG_TEXT_STYLE_TABLE);
// Number of styles
int numStyle = styles.size();
int numStyle = styleMap.size();
buf.Add((int32)numStyle);
// Write the styles
for (unsigned int i=0;i<styles.size();i++)
styles[i].Write(buf);
StyleMapType::iterator itr = styleMap.begin();
for ( ; itr != styleMap.end( ); itr++)
itr->second.Write(buf);
buf.End();
@ -293,16 +309,17 @@ bool trpgTextStyleTable::Read(trpgReadBuffer &buf)
int32 len;
bool status;
int numStyle;
int i;
int i;
Reset();
try {
try
{
buf.Get(numStyle);
if (numStyle < 0)
throw 1;
styles.resize(numStyle);
for (i=0;i<numStyle;i++) {
for (i=0;i<numStyle;i++) {
buf.GetToken(styleTok,len);
if (styleTok != TRPG_TEXT_STYLE) throw 1;
buf.PushLimit(len);
@ -310,10 +327,11 @@ bool trpgTextStyleTable::Read(trpgReadBuffer &buf)
status = style.Read(buf);
buf.PopLimit();
if (!status) throw 1;
styles[i] = style;
AddStyle(style);
}
}
catch (...) {
catch (...)
{
return false;
}
@ -338,6 +356,8 @@ void trpgSupportStyle::Reset(void)
{
type = Line;
matId = -1;
handle = -1;
writeHandle = false;
}
void trpgSupportStyle::SetType(SupportType s)
@ -378,7 +398,8 @@ bool trpgSupportStyle::Write(trpgWriteBuffer &buf)
// SupportStyle CB
// Used to parse tokens from the support style structure.
// If we do it this way it's easier to expand later.
class supportStyleCB : public trpgr_Callback {
class supportStyleCB : public trpgr_Callback
{
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgSupportStyle *style;
@ -388,8 +409,10 @@ void * supportStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
int iVal;
try {
switch (tok) {
try
{
switch (tok)
{
case TRPG_SUPPORT_STYLE_BASIC:
buf.Get(iVal);
style->SetType(trpgSupportStyle::SupportType(iVal));
@ -400,7 +423,8 @@ void * supportStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf)
break;
}
}
catch (...) {
catch (...)
{
return NULL;
}
@ -450,44 +474,56 @@ trpgSupportStyleTable::~trpgSupportStyleTable()
void trpgSupportStyleTable::Reset()
{
styles.resize(0);
//styles.resize(0);
supportStyleMap.clear();
}
bool trpgSupportStyleTable::isValid() const
{
for (unsigned int i=0;i<styles.size();i++)
if (!styles[i].isValid())
//for (int i=0;i<styles.size();i++)
SupportStyleMapType::const_iterator itr = supportStyleMap.begin();
for ( ; itr != supportStyleMap.end( ); itr++)
{
if (!itr->second.isValid())
return false;
}
return true;
}
int trpgSupportStyleTable::AddStyle(const trpgSupportStyle &style)
{
styles.push_back(style);
return styles.size() -1;
int handle = style.GetHandle();
if(handle==-1)
{
handle = supportStyleMap.size();
}
supportStyleMap[handle] = style;
return handle;
}
int trpgSupportStyleTable::FindAddStyle(const trpgSupportStyle &style)
{
for (unsigned int i=0;i<styles.size();i++)
if (styles[i] == style)
return i;
SupportStyleMapType::const_iterator itr = supportStyleMap.begin();
for ( ; itr != supportStyleMap.end( ); itr++)
if (itr->second == style)
return itr->first;
return AddStyle(style);
}
int trpgSupportStyleTable::GetNumStyle() const
{
return styles.size();
return supportStyleMap.size();
}
const trpgSupportStyle *trpgSupportStyleTable::GetStyleRef(int id) const
{
if (id < 0 || id >= (int)styles.size())
if (id < 0)
return NULL;
return &styles[id];
SupportStyleMapType::const_iterator itr = supportStyleMap.find(id);
if(itr == supportStyleMap.end())
return NULL;
return &itr->second;
}
bool trpgSupportStyleTable::Write(trpgWriteBuffer &buf)
@ -498,12 +534,13 @@ bool trpgSupportStyleTable::Write(trpgWriteBuffer &buf)
buf.Begin(TRPG_SUPPORT_STYLE_TABLE);
// Number of styles
int numStyle = styles.size();
int numStyle = supportStyleMap.size();
buf.Add((int32)numStyle);
// Write the styles
for (unsigned int i=0;i<styles.size();i++)
styles[i].Write(buf);
SupportStyleMapType::iterator itr = supportStyleMap.begin();
for ( ; itr != supportStyleMap.end( ); itr++)
itr->second.Write(buf);
buf.End();
@ -517,15 +554,17 @@ bool trpgSupportStyleTable::Read(trpgReadBuffer &buf)
int32 len;
bool status;
int numStyle;
int i;
Reset();
try {
try
{
buf.Get(numStyle);
if (numStyle < 0)
throw 1;
styles.resize(numStyle);
for (int i=0;i<numStyle;i++) {
//styles.resize(numStyle);
for (i=0;i<numStyle;i++) {
buf.GetToken(styleTok,len);
if (styleTok != TRPG_SUPPORT_STYLE) throw 1;
buf.PushLimit(len);
@ -533,10 +572,11 @@ bool trpgSupportStyleTable::Read(trpgReadBuffer &buf)
status = style.Read(buf);
buf.PopLimit();
if (!status) throw 1;
styles[i] = style;
AddStyle(style);
}
}
catch (...) {
catch (...)
{
return false;
}
@ -561,6 +601,8 @@ void trpgLabelProperty::Reset(void)
fontId = -1;
supportId = -1;
type = VertBillboard;
handle = -1;
writeHandle = false;
}
void trpgLabelProperty::SetType(LabelType inType)
@ -612,7 +654,8 @@ bool trpgLabelProperty::Write(trpgWriteBuffer &buf)
// LabelProperty CB
// Used to parse tokens from the label property structure.
// If we do it this way it's easier to expand later.
class labelPropertyCB : public trpgr_Callback {
class labelPropertyCB : public trpgr_Callback
{
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgLabelProperty *property;
@ -622,9 +665,11 @@ void * labelPropertyCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
int iVal;
try {
try
{
int ival;
switch (tok) {
switch (tok)
{
case TRPG_LABEL_PROPERTY_BASIC:
buf.Get(iVal);
property->SetFontStyle(iVal);
@ -637,7 +682,8 @@ void * labelPropertyCB::Parse(trpgToken tok,trpgReadBuffer &buf)
break;
}
}
catch (...) {
catch (...)
{
return NULL;
}
@ -686,44 +732,56 @@ trpgLabelPropertyTable::~trpgLabelPropertyTable()
void trpgLabelPropertyTable::Reset()
{
properties.resize(0);
labelPropertyMap.clear();
}
bool trpgLabelPropertyTable::isValid() const
{
for (unsigned int i=0;i<properties.size();i++)
if (!properties[i].isValid())
LabelPropertyMapType::const_iterator itr = labelPropertyMap.begin();
for ( ; itr != labelPropertyMap.end( ); itr++)
{
if (!itr->second.isValid())
return false;
}
return true;
}
int trpgLabelPropertyTable::AddProperty(const trpgLabelProperty &property)
{
properties.push_back(property);
return properties.size() -1;
int handle = property.GetHandle();
if(handle==-1)
{
handle = labelPropertyMap.size();
}
labelPropertyMap[handle] = property;
return handle;
}
int trpgLabelPropertyTable::FindAddProperty(const trpgLabelProperty& property)
{
for (unsigned int i=0;i<properties.size();i++)
if (properties[i] == property)
return i;
LabelPropertyMapType::const_iterator itr = labelPropertyMap.begin();
for ( ; itr != labelPropertyMap.end( ); itr++)
{
if (itr->second == property)
return itr->first;
}
return AddProperty(property);
}
int trpgLabelPropertyTable::GetNumProperty() const
{
return properties.size();
return labelPropertyMap.size();
}
const trpgLabelProperty *trpgLabelPropertyTable::GetPropertyRef(int id) const
{
if (id < 0 || id >= (int)properties.size())
if (id < 0)
return NULL;
return &properties[id];
LabelPropertyMapType::const_iterator itr = labelPropertyMap.find(id);
if(itr == labelPropertyMap.end())
return NULL;
return &itr->second;
}
bool trpgLabelPropertyTable::Write(trpgWriteBuffer &buf)
@ -734,12 +792,15 @@ bool trpgLabelPropertyTable::Write(trpgWriteBuffer &buf)
buf.Begin(TRPG_LABEL_PROPERTY_TABLE);
// Number of styles
int numProperty = properties.size();
int numProperty = labelPropertyMap.size();
buf.Add((int32)numProperty);
// Write the properties
for (unsigned int i=0;i<properties.size();i++)
properties[i].Write(buf);
LabelPropertyMapType::iterator itr = labelPropertyMap.begin();
for ( ; itr != labelPropertyMap.end( ); itr++)
{
itr->second.Write(buf);
}
buf.End();
@ -753,15 +814,17 @@ bool trpgLabelPropertyTable::Read(trpgReadBuffer &buf)
int32 len;
bool status;
int numProperty;
int i;
Reset();
try {
try
{
buf.Get(numProperty);
if (numProperty < 0)
throw 1;
properties.resize(numProperty);
for (unsigned int i=0;i<(unsigned int)numProperty;i++) {
//properties.resize(numProperty);
for (i=0;i<numProperty;i++) {
buf.GetToken(propertyTok,len);
if (propertyTok != TRPG_LABEL_PROPERTY) throw 1;
buf.PushLimit(len);
@ -769,10 +832,12 @@ bool trpgLabelPropertyTable::Read(trpgReadBuffer &buf)
status = property.Read(buf);
buf.PopLimit();
if (!status) throw 1;
properties[i] = property;
//properties[i] = property;
AddProperty(property);
}
}
catch (...) {
catch (...)
{
return false;
}
@ -920,6 +985,8 @@ const std::vector<trpg3dPoint> *trpgLabel::GetSupports() const
bool trpgLabel::Write(trpgWriteBuffer &buf)
{
unsigned int i;
buf.Begin(TRPG_LABEL);
buf.Add(propertyId);
buf.Add(text);
@ -931,7 +998,7 @@ bool trpgLabel::Write(trpgWriteBuffer &buf)
buf.Add(url);
buf.Add(location);
buf.Add((int)supports.size());
for (unsigned i=0;i<supports.size();i++)
for (i=0;i<supports.size();i++)
buf.Add(supports[i]);
buf.End();
@ -940,11 +1007,12 @@ bool trpgLabel::Write(trpgWriteBuffer &buf)
bool trpgLabel::Read(trpgReadBuffer &buf)
{
int numSupport,i;
int numSupport,i;
trpg3dPoint support;
int iVal;
try {
try
{
buf.Get(iVal);
propertyId = iVal;
buf.Get(text);
@ -958,12 +1026,13 @@ bool trpgLabel::Read(trpgReadBuffer &buf)
buf.Get(location);
buf.Get(numSupport);
if (numSupport < 0) throw 1;
for (i=0;i<numSupport;i++) {
for (i=0;i<numSupport;i++) {
buf.Get(support);
supports.push_back(support);
}
}
catch (...) {
catch (...)
{
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -14,9 +14,9 @@
*/
/* trpage_main.cpp
This file is here to provide a DLL Main.
Note: #ifdef this out on non-windows machines
*/
This file is here to provide a DLL Main.
Note: #ifdef this out on non-windows machines
*/
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

File diff suppressed because it is too large Load Diff

View File

@ -19,21 +19,31 @@
#include <deque>
/* This file contains class definitions for managers
that help you keep track of data related to
paging. For instance, which tiles to load
in at any given time and what textures you need
to read for a given tile.
that help you keep track of data related to
paging. For instance, which tiles to load
in at any given time and what textures you need
to read for a given tile.
*/
class trpgPageManager;
// Grid and file location of a tile
struct TileLocationInfo
{
TileLocationInfo(): x(-1), y(-1), lod(-1) {}
TileLocationInfo(int gx, int gy, int glod, const trpgwAppAddress& gaddr): x(gx), y(gy), lod(glod), addr(gaddr) {}
int x, y, lod;
trpgwAppAddress addr;
};
/* Managed Tiles are used by the trpgPageManager to keep
track of which tiles are loaded and what textures (and
models) they need loaded into memory with them.
track of which tiles are loaded and what textures (and
models) they need loaded into memory with them.
*/
TX_EXDECL class TX_CLDECL trpgManagedTile {
friend class trpgPageManager;
public:
TX_EXDECL class TX_CLDECL trpgManagedTile
{
friend class trpgPageManager;
public:
trpgManagedTile(void);
// Called to clear any info out of this tile
@ -43,41 +53,49 @@ public:
Scene parser callback. The managed tile
can then keep track of which textures and models
go with this tile.
*/
*/
bool ParseTileHeader(trpgReadBuffer &);
// Check if the tile is loaded (e.g. the header read in)
bool IsLoaded(void);
/* Set the tile location. This resets any internal
state we may be keeping.
*/
state we may be keeping.
*/
bool SetTileLoc(int x,int y,int lod);
// Get the tile location
bool GetTileLoc(int &x,int &y,int &lod);
bool GetTileLoc(int &x,int &y,int &lod) const;
// In version 2.1 we no longer have the tile table to
// find the tiles, only by traversing the parent can it be
// found. So when we have this info, this is were to save it.
void SetTileAddress(const trpgwAppAddress& gAddr);
void SetTileAddress(int32 file, int32 offset);
const trpgwAppAddress& GetTileAddress() const;
// Return a pointer to the tile header
const trpgTileHeader *GetTileHead(void);
/* Return a pointer to the list of locally defined
materials. As soon as the tile header is read by
ParseTileHeader (which you call) you'll want to get
this list and load the pageable textures. You can
use SetMatData to keep track of our internal texture
structures.
*/
materials. As soon as the tile header is read by
ParseTileHeader (which you call) you'll want to get
this list and load the pageable textures. You can
use SetMatData to keep track of our internal texture
structures.
*/
const std::vector<trpgLocalMaterial> *GetLocMatList(void) const;
/* Returns a pointer to a single local material, if within
the valid range of local materials for this tile.
*/
the valid range of local materials for this tile.
*/
const trpgLocalMaterial *GetLocMaterial(int id) const;
/* Set Local Data for managed tile. The local data would
probably be a pointer to the top of the scene graph you're
using to represent just this tile.
*/
probably be a pointer to the top of the scene graph you're
using to represent just this tile.
*/
void SetLocalData(void *);
/* Returns the local data you set with SetLocalData.
@ -85,25 +103,25 @@ public:
void *GetLocalData(void) const;
/* Associates a void * with one of the materials referenced
within this tile. The idea here is that you'll want
to load the texture for a given local material and then
pass your own internal texture structure into here as
a void *. That way, the trpgPageManager will keep track
of which textures you should unload when this tile goes
out of range.
*/
within this tile. The idea here is that you'll want
to load the texture for a given local material and then
pass your own internal texture structure into here as
a void *. That way, the trpgPageManager will keep track
of which textures you should unload when this tile goes
out of range.
*/
bool SetMatData(int id,void *);
/* Gets the void * data you associated with a given local
material index. See SetMatData for more information.
*/
material index. See SetMatData for more information.
*/
void *GetMatData(int id) const;
/* Add Group ID to this tile. This is called by the page
manager to keep track of which group IDs belong to this tile.
We use this information to NULL out the appropriate positions
in the group map help by the page manager.
*/
manager to keep track of which group IDs belong to this tile.
We use this information to NULL out the appropriate positions
in the group map help by the page manager.
*/
void AddGroupID(int id);
/* Retrieve the list of group IDs for this tile.
@ -111,14 +129,28 @@ public:
const std::vector<int> *GetGroupIDs(void) const;
/* Print the current status and information about this managed
Tile.
*/
Tile.
*/
void Print(trpgPrintBuffer &);
protected:
// Children info, will throw exception if child index is out of bound
unsigned int GetNbChildren() const
{
return (unsigned int)childLocationInfo.size();
}
bool SetChildLocationInfo(int childIdx, int x, int y, const trpgwAppAddress& addr);
bool SetChildLocationInfo(int childIdx, const TileLocationInfo& info);
const TileLocationInfo& GetChildLocationInfo(int childIdx) const;
bool GetChildTileLoc(int childIdx, int &x,int &y,int &lod) const;
const trpgwAppAddress& GetChildTileAddress(int childIdx) const;
protected:
// Set if a tile is currently loaded
bool isLoaded;
// Tile location info
int x,y,lod;
TileLocationInfo location;
// Tile Header associated with this tile
trpgTileHeader tileHead;
// Data to keep associated with each individual local material index
@ -128,194 +160,268 @@ protected:
// Local data (probably the top of the local scene graph)
void *localData;
// What are the children: this to be used for version 2.1 and up.
// Both vector should have the same size
std::vector<TileLocationInfo> childLocationInfo;
// Note: Should do models too if anyone wanted them.
};
/* The Page Manager is a helper class that can be used
to keep track of: (1) which tiles need to be loaded
into memory for a given viewer position, (2) which tiles
are currently loaded and (3) which tiles need to be unloaded
when the viewer position moves. The tile list this
class generates is guaranteed to be in the right order
for loading. You would use this class if you're implementing
a TerraPage reader for your visual run-time system.
*/
TX_EXDECL class TX_CLDECL trpgPageManager {
public:
to keep track of: (1) which tiles need to be loaded
into memory for a given viewer position, (2) which tiles
are currently loaded and (3) which tiles need to be unloaded
when the viewer position moves. The tile list this
class generates is guaranteed to be in the right order
for loading. You would use this class if you're implementing
a TerraPage reader for your visual run-time system.
*/
TX_EXDECL class TX_CLDECL trpgPageManager
{
public:
trpgPageManager(void);
virtual ~trpgPageManager(void);
// Initialize with an archive
virtual void Init(trpgr_Archive *);
virtual void Init(trpgr_Archive *inArch, int maxLod);
/* Set Paging Distance
This is the extra distance outside the visible range
we want to page. The defaults will be valid. You would
set this if you want to pull tiles in earlier. Be sure
to call it before you call Init(), however.
*/
This is the extra distance outside the visible range
we want to page. The defaults will be valid. You would
set this if you want to pull tiles in earlier. Be sure
to call it before you call Init(), however.
*/
virtual bool SetPageDistFactor(double);
/* Updates the current location for paging purposes.
Returns true if any load or unloads need to happen.
*/
Returns true if any load or unloads need to happen.
*/
virtual bool SetLocation(trpg2dPoint &);
/* Get next tile to load.
The paging manager is keeping track of which tiles
need to be loaded and in what order. This method
returns a pointer to the next one. The user is
expected to call AckLoad() after the tile is loaded.
*/
The paging manager is keeping track of which tiles
need to be loaded and in what order. This method
returns a pointer to the next one. The user is
expected to call AckLoad() after the tile is loaded.
*/
virtual trpgManagedTile *GetNextLoad(void);
/* Acknowledge Tile Load.
This method should be called when a tile has been
loaded by the caller. This method is used in conjunction
with GetNextLoad().
*/
virtual void AckLoad(void);
/* Acknowledge Tile Load.
This method should be called when a tile has been
loaded by the caller. This method is used in conjunction
with GetNextLoad().
Version 2.1 and over supports variable lod so that we cannot know
from the tile table if a tile exist or not. So to manage this
the user must parse the loaded tile and extract its list of children
and pass it on to AckLoad() which will add to the appropriate lod list
the children info. If this is not done then only lod 0 will be pageable.
*/
virtual void AckLoad(std::vector<TileLocationInfo> const& children);
// Using this call with version 2.1 and over will only page lod 0 tiles
virtual void AckLoad();
/* Add Group ID to map.
This should be called when the user encounters a group-like
object while processing the scene graph data from a tile.
The groupId is given by TerraPage and the data should be
the corresponding group object that the user creates in
their own scenegraph toolkit. This information can then
be retrieved later by GetGroupData().
*/
This should be called when the user encounters a group-like
object while processing the scene graph data from a tile.
The groupId is given by TerraPage and the data should be
the corresponding group object that the user creates in
their own scenegraph toolkit. This information can then
be retrieved later by GetGroupData().
*/
virtual void AddGroupID(trpgManagedTile *,int groupID,void *data);
/* Get Group Data fetches the data cached by the user and
associated with the given groupID. This would be used in
conjunction with trpgAttach nodes to implement geometry paging.
*/
associated with the given groupID. This would be used in
conjunction with trpgAttach nodes to implement geometry paging.
*/
virtual void *GetGroupData(int groupID);
/* Get next tile to unload.
The paging manager keeps track of which tiles need
to be unloaded based on a change of location. It's
best if you unload tiles before loading them, but
that's really up to you.
*/
The paging manager keeps track of which tiles need
to be unloaded based on a change of location. It's
best if you unload tiles before loading them, but
that's really up to you.
*/
virtual trpgManagedTile *GetNextUnload(void);
/* Acknowledge a tile unload.
You should call this after you've "unloaded" a tile
and all its associated textures.
*/
You should call this after you've "unloaded" a tile
and all its associated textures.
*/
virtual void AckUnload(void);
/* Stop paging entirely. Call this right before you want to
shut down paging. Everything active will wind up on the
unload lists. Then you can unload those tiles and move on.
*/
shut down paging. Everything active will wind up on the
unload lists. Then you can unload those tiles and move on.
*/
virtual bool Stop(void);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
protected:
protected:
trpgr_Archive *archive;
// Center of paging
trpg2dPoint pagePt;
/* Information associated with each terrain level of
detail as related to paging.
*/
class LodPageInfo {
friend class trpgPageManager;
detail as related to paging.
*/
TX_EXDECL class TX_CLDECL LodPageInfo {
friend class trpgPageManager;
public:
LodPageInfo(void);
virtual ~LodPageInfo(void);
LodPageInfo(void);
virtual ~LodPageInfo(void);
/* Initializes the class with its current LOD.
It figures out all the rest.
*/
virtual bool Init(trpgr_Archive *, int myLod, double scale);
/* Initializes the class with its current LOD.
It figures out all the rest.
*/
virtual bool Init(trpgr_Archive *, int myLod, double scale, int freeListDivider = 1);
/* Reset the location. This forces a recalculation
of what to load and unload if the cell has changed
or if this is the first SetLocation.
The location passed in must be relative to the southwest
corner of the TerraPage archive.
*/
virtual bool SetLocation(trpg2dPoint &);
/* Reset the location. This forces a recalculation
of what to load and unload if the cell has changed
or if this is the first SetLocation.
The location passed in must be relative to the southwest
corner of the TerraPage archive.
*/
virtual bool SetLocation(trpg2dPoint &);
// Return the next tile to load for this terrain lod
virtual trpgManagedTile *GetNextLoad(void);
// Acknowledge the load. Move the active tile to the
// loaded list.
virtual void AckLoad();
// Get the lsit of
//bool GetLoadedTile
// Return the next tile to unload for this terrain lod
virtual trpgManagedTile *GetNextUnload(void);
// Acknowledge the unload. Move the active tile to the
// free list.
virtual void AckUnload(void);
// Called to stop paging. Everything active is dumped on
// the unload list.
virtual bool Stop(void);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
const trpg2iPoint& GetLodSize() const
{
return lodSize;
}
int GetLod() const
{
return lod;
}
double GetPageDistance() const
{
return pageDist;
}
const trpg2dPoint& GetCellSize() const
{
return cellSize;
}
// The unit are cellSize
const trpg2iPoint& GetAreaOfInterest() const
{
return aoiSize;
}
// The middle of this cell correspond to our paging
// location
const trpg2iPoint& GetCellPagingLocation() const
{
return cell;
}
// Return the next tile to load for this terrain lod
virtual trpgManagedTile *GetNextLoad(void);
// Acknowledge the load. Move the active tile to the
// loaded list.
virtual void AckLoad(void);
// Return the next tile to unload for this terrain lod
virtual trpgManagedTile *GetNextUnload(void);
// Acknowledge the unload. Move the active tile to the
// free list.
virtual void AckUnload(void);
// Called to stop paging. Everything active is dumped on
// the unload list.
virtual bool Stop(void);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
protected:
virtual void Clean(void);
virtual void Update(void);
virtual void Clean(void);
virtual void Update(void);
// Check if the given tile is within the area we care about
bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne);
// Add to the load list the given tile if it is within the proper
// bound
bool AddToLoadList(int x, int y, const trpgwAppAddress& addr);
bool valid;
// Add the children of the given parent list
// to the load list if it it not already loaded
// or if it is not already in the list
void AddChildrenToLoadList(std::vector<trpgManagedTile*>& parentList);
// Terrain LOD we're responsible for
int lod;
// Check if the given tile is within the area we care about
bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne);
/* Adjusted (e.g. paranoid) distance outward from
which to page this terrain LOD. This takes into
account the distance in the header as well as
any factor the user may have added.
*/
double pageDist;
// Get the list of currently loaded tiles that fall within
// the region calculated from the given paging distance.
void GetLoadedTileWithin(double pagingDistance, std::vector<trpgManagedTile*>& tileList);
/* Max tiles we could have loaded in at any given time.
This is just a guess because it's up to the user
to load (and, more importantly) unload.
*/
int maxNumTiles;
bool valid;
// Size of a single cell. Copied from the archive.
trpg2dPoint cellSize;
// Terrain LOD we're responsible for
int lod;
// Number of tiles (cells) in each direction
trpg2iPoint lodSize;
/* Adjusted (e.g. paranoid) distance outward from
which to page this terrain LOD. This takes into
account the distance in the header as well as
any factor the user may have added.
*/
double pageDist;
/* Area of interest size in cells
This is a linear distance "ahead" of the center cell.
*/
trpg2iPoint aoiSize;
/* Max tiles we could have loaded in at any given time.
This is just a guess because it's up to the user
to load (and, more importantly) unload.
*/
int maxNumTiles;
/* Our effective paging location sits at the middle
of this cell. We don't recalculate unless the
cell changes. */
trpg2iPoint cell;
// Size of a single cell. Copied from the archive.
trpg2dPoint cellSize;
// List of tiles to load
std::deque<trpgManagedTile *> load;
// List of tiles to unload
std::deque<trpgManagedTile *> unload;
// List of currently loaded tiles
std::deque<trpgManagedTile *> current;
// Number of tiles (cells) in each direction
trpg2iPoint lodSize;
// Used by Update. Here because we want to avoid memory allocs, if possible.
std::vector<bool> tmpCurrent;
/* Area of interest size in cells
This is a linear distance "ahead" of the center cell.
*/
trpg2iPoint aoiSize;
// Set if a load is in progress
// Load w/o ACK
bool activeLoad;
// Set if an unload is in progress
// Unload w/o ACK
bool activeUnload;
/* Our effective paging location sits at the middle
of this cell. We don't recalculate unless the
cell changes. */
trpg2iPoint cell;
// List of tile pointers we can reuse
std::deque<trpgManagedTile *> freeList;
// List of tiles to load
std::deque<trpgManagedTile *> load;
// List of tiles to unload
std::deque<trpgManagedTile *> unload;
// List of currently loaded tiles
std::deque<trpgManagedTile *> current;
// Used by Update. Here because we want to avoid memory allocs, if possible.
std::vector<bool> tmpCurrent;
// Set if a load is in progress
// Load w/o ACK
bool activeLoad;
// Set if an unload is in progress
// Unload w/o ACK
bool activeUnload;
// List of tile pointers we can reuse
std::deque<trpgManagedTile *> freeList;
// TerraPage version
int majorVersion, minorVersion;
const trpgTileTable *tileTable;
};
// Per terrain lod paging information
@ -324,8 +430,8 @@ protected:
// Enumerated type for lastLoad
typedef enum {Load,Unload,None} LoadType;
/* Information about what the pending load/unload operation
is. It's up to the user to complete and acknowledge it.
*/
is. It's up to the user to complete and acknowledge it.
*/
LoadType lastLoad;
// LOD for the pending load/unload requested operation
int lastLod;
@ -339,40 +445,80 @@ protected:
typedef std::map<int,void *> ManageGroupMap;
ManageGroupMap groupMap;
// Terrapge Version
int majorVersion, minorVersion;
bool valid;
};
// For Version 2.1 an over, the tile table only contains
// tiles of lod 0. To get access the other tiles, parent tile
// must be parsed to get at trpgChildRef nodes that will contain
// location info about the children. This callback can be use to
// parse the tile data. After parsing the callback object will contain
// the list of trpgChildRef nodes found.
TX_EXDECL class TX_CLDECL trpgr_ChildRefCB : public trpgr_Callback
{
public:
void *Parse(trpgToken tok, trpgReadBuffer& rbuf);
// After parsing this will return the number of trpgChildRef node found.
unsigned int GetNbChildren() const;
// This will return the trpgChildRef node associated with the index.
// Will throw an exception if the index is out of bound
const trpgChildRef& GetChildRef(unsigned int idx) const;
// Clear the children list
void Reset();
protected:
// typedef std::vector<const trpgChildRef> ChildList;
// The const in the template parameter was removed because it causes GCC to
// freak out. I am of the opinion that const doesn't make sense in a template
// parameter for std::vector anyway... const prevents you from changing the
// value, so what exactly is the point? How does one add entries to the vector
// without giving them a value? -ADS
typedef std::vector<trpgChildRef> ChildList;
ChildList childList;
};
/* Page Manager Tester. This class tests a given paging manager
by applying likely
*/
TX_EXDECL class TX_CLDECL trpgPageManageTester {
public:
by applying likely
*/
TX_EXDECL class TX_CLDECL trpgPageManageTester
{
public:
trpgPageManageTester();
virtual ~trpgPageManageTester();
/* Initialize the tester with a paging manager
and an archive.
*/
and an archive.
*/
void Init(trpgPrintBuffer *,trpgPageManager *,trpgr_Archive *);
/* Feeds the paging manager coordinates starting from
the lower left to upper right of the database in the
given increment.
*/
the lower left to upper right of the database in the
given increment.
*/
void Fly_LL_to_UR(double dist=100.0);
/* Jumps around randomly within the archive loading and
unloading as needed.
*/
unloading as needed.
*/
void RandomTest(int no=100,int seed=-1);
protected:
protected:
// Does the work of "load" and "unloading"
void ProcessChanges();
trpgPageManager *manager;
trpgr_Archive *archive;
trpgPrintBuffer *printBuf;
trpgr_ChildRefCB childRefCB;
trpgr_Parser tileParser;
// TerraPage version
int majorVersion, minorVersion;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -17,204 +17,280 @@
#include <stdio.h>
#include <string.h>
/* trpage_mode.cpp
This source file contains the methods trpgModel and trpgModelTable.
You should only modify this code if you want to add data to these classes.
*/
#define OLDMODELSTYLE
/* trpage_model.cpp
This source file contains the methods trpgModel and trpgModelTable.
You should only modify this code if you want to add data to these classes.
*/
#include <trpage_geom.h>
#include <trpage_read.h>
/* Write Model class
Represents a model reference.
*/
Represents a model reference.
*/
trpgModel::trpgModel()
{
name = NULL;
type = External;
useCount = 0;
name = NULL;
type = External;
useCount = 0;
diskRef = -1;
handle = -1;
writeHandle = false;
}
trpgModel::trpgModel(const trpgModel &in):
trpgReadWriteable(in)
{
name = NULL;
type = External;
*this = in;
if (in.name)
{
name = new char[strlen(in.name)+1];
strcpy(name,in.name);
}
else
name = NULL;
type=in.type;
useCount=in.useCount;
diskRef=in.diskRef;
handle = in.handle;
writeHandle = in.writeHandle;
}
// Reset function
void trpgModel::Reset()
{
if (name)
delete [] name;
name = NULL;
useCount = 0;
if (name)
delete [] name;
name = NULL;
useCount = 0;
diskRef = -1;
handle = -1;
writeHandle = false;
}
trpgModel::~trpgModel()
{
Reset();
Reset();
}
// Set functions
void trpgModel::SetType(int t)
{
type = t;
}
void trpgModel::SetName(const char *nm)
{
if (name)
delete [] name;
if (name)
delete [] name;
name = new char[(nm ? strlen(nm) : 0)+1];
strcpy(name,nm);
type = External;
if (nm)
{
name = new char[(nm ? strlen(nm) : 0)+1];
strcpy(name,nm);
}
}
void trpgModel::SetReference(trpgDiskRef pos)
{
if (name)
delete [] name;
diskRef = pos;
type = Local;
diskRef = pos;
}
void trpgModel::SetNumTiles(int num)
{
useCount = num;
useCount = num;
}
void trpgModel::AddTile()
{
useCount++;
useCount++;
}
// Validity check
bool trpgModel::isValid() const
{
if (type == External && !name)
{
strcpy(errMess, "Model is external with no name");
return false;
}
if (type == External && !name)
{
strcpy(errMess, "Model is external with no name");
return false;
}
return true;
return true;
}
// Copy from one to another
trpgModel& trpgModel::operator = (const trpgModel &in)
{
if (name) {
delete [] name;
name = NULL;
}
if (name) {
delete [] name;
name = NULL;
}
type = in.type;
if (in.name)
SetName(in.name);
diskRef = in.diskRef;
useCount = in.useCount;
return *this;
type = in.type;
if (in.name)
SetName(in.name);
diskRef = in.diskRef;
useCount = in.useCount;
writeHandle = in.writeHandle;
handle = in.handle;
return *this;
}
// Compare two models
int trpgModel::operator == (const trpgModel &in) const
{
if (type != in.type)
return 0;
if (type != in.type)
return 0;
switch (type) {
case Local:
if (diskRef == in.diskRef)
return 1;
else
return 0;
break;
case External:
if (!name && !in.name)
return 1;
if (!name || !in.name)
return 0;
if (strcmp(name,in.name))
return 0;
break;
}
switch (type) {
case Local:
if (diskRef == in.diskRef)
return 1;
else
return 0;
break;
case External:
if (!name && !in.name)
return 1;
if (!name || !in.name)
return 0;
if (strcmp(name,in.name))
return 0;
break;
}
return 1;
return 1;
}
// Write a model reference out
bool trpgModel::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGMODELREF);
buf.Add(type);
if (name)
buf.Add(name);
else
// We will use two different tokens to track the
// format used in terrapage 2.2, and older versions
int tok = TRPGMODELREF;
if(writeHandle)
tok = TRPGMODELREF2;
// Nick messed up the model entries when checking into txv4; now we're
// a bit stuck because U3 dbs don't have models in the U2 viewer.
// This will force the old behavior.
#ifdef OLDMODELSTYLE
buf.Begin(tok);
buf.Add(type);
//writeHandle is only set for terrapage 2.2, and we use the different token.
if(writeHandle) {
buf.Add((int)handle);
}
if (name)
buf.Add(name);
else
buf.Add(diskRef);
buf.Add(useCount);
buf.Add(useCount);
buf.End();
#else
buf.Begin(tok);
if(writeHandle) {
buf.Add((int)handle);
}
buf.Add(type);
buf.Add(name);
buf.Add(diskRef);
buf.Add(useCount);
#endif
buf.End();
return true;
return true;
}
/* *******************
Model Read Methods
*******************
*/
/* *******************
Model Read Methods
*******************
*/
// Get methods
bool trpgModel::GetType(int &t)
{
if (!isValid()) return false;
t = type;
return true;
if (!isValid()) return false;
t = type;
return true;
}
bool trpgModel::GetName(char *str,int strLen) const
{
if (!isValid() || type != External) return false;
int len = (name ? strlen(name) : 0);
strncpy(str,name,MIN(len,strLen)+1);
return true;
if (!isValid()) return false;
int len = (name ? strlen(name) : 0);
strncpy(str,name,MIN(len,strLen)+1);
return true;
}
bool trpgModel::GetNumTiles(int &ret) const
{
if (!isValid()) return false;
if (!isValid()) return false;
ret = useCount;
return true;
ret = useCount;
return true;
}
bool trpgModel::GetReference(trpgDiskRef &ref) const
{
if (!isValid() || type != Local) return false;
ref = diskRef;
return true;
if (!isValid() || type != Local) return false;
ref = diskRef;
return true;
}
bool trpgModel::Read(trpgReadBuffer &buf)
bool trpgModel::Read(trpgReadBuffer &buf, bool hasHandle)
{
char tmpName[1024];
// MD: added complexity here - written multiple ways by
// mistake, unraveling the various cases.
char tmpName[1024];
try {
buf.Get(type);
if (type == Local)
buf.Get(diskRef);
else {
buf.Get(tmpName,1023);
SetName(tmpName);
}
buf.Get(useCount);
}
catch(...) {
return false;
}
try {
buf.Get(type);
// TerraPage 2.2 will store the unique handle after the type
// we use a different token, so this is backwards compatible.
if(hasHandle) {
buf.Get((int32 &)handle);
}
else
handle = -1;
if (type == Local) {
// two possibilities:
// name, diskRef, useCount
// diskRef, useCount
// diskRef + useCount = 12 bytes...
if (buf.TestLimit(13))
{
buf.Get(tmpName,1023);
SetName(tmpName);
}
buf.Get(diskRef);
buf.Get(useCount);
}
else
{
// two possibilities:
// name, diskRef, useCount
// name, useCount
buf.Get(tmpName,1023);
SetName(tmpName);
// useCount = 4 bytes...
if (buf.TestLimit(5))
buf.Get(diskRef);
buf.Get(useCount);
}
}
catch(...) {
return false;
}
return isValid();
// going to make this fail if the buffer isn't empty.
if (buf.TestLimit(1)) return false;
return isValid();
}
/* Write Model Reference table
Groups of models for the entire file.
*/
Groups of models for the entire file.
*/
// Constructor
trpgModelTable::trpgModelTable()
@ -227,50 +303,73 @@ trpgModelTable::~trpgModelTable()
// Reset function
void trpgModelTable::Reset()
{
models.resize(0);
modelsMap.clear();
}
// Set functions
void trpgModelTable::SetNumModels(int no)
void trpgModelTable::SetNumModels(int /*no*/)
{
models.resize(no);
// This method isn't needed with a map
//models.resize(no);
}
void trpgModelTable::SetModel(int id,const trpgModel &mod)
{
if (id < 0 || (unsigned int)id >= models.size())
return;
if (id < 0)
return;
models[id] = mod;
modelsMap[id] = mod;
//models[id] = mod;
}
int trpgModelTable::AddModel(const trpgModel &mod)
{
models.push_back(mod);
return models.size()-1;
int trpgModelTable::AddModel(trpgModel &mod)
{
int hdl = modelsMap.size();
if(mod.GetHandle()==-1) {
modelsMap[hdl] = mod;
return hdl;
}
modelsMap[mod.GetHandle()] = mod;
return mod.GetHandle();
}
int trpgModelTable::FindAddModel(const trpgModel &mod)
{
for (unsigned int i=0;i<models.size();i++)
if (models[i] == mod)
return i;
return AddModel(mod);
int trpgModelTable::FindAddModel(trpgModel &mod)
{
ModelMapType::iterator itr = modelsMap.begin();
for ( ; itr != modelsMap.end( ); itr++) {
if(itr->second == mod) {
return itr->first;
}
}
return AddModel(mod);
}
bool trpgModelTable::FindByName(const char *name, unsigned int &mId)
{
ModelMapType::const_iterator itr = modelsMap.begin();
for ( ; itr != modelsMap.end( ); itr++) {
char theName[1023];
itr->second.GetName(theName,1023);
if(strcmp(name,theName)==0) {
mId = itr->first;
return true;
}
}
return false;
}
// Validity check
bool trpgModelTable::isValid() const
{
for (unsigned int i=0;i<models.size();i++)
{
if (!models[i].isValid())
{
if(models[i].getErrMess())
strcpy(errMess, models[i].getErrMess());
return false;
}
}
return true;
ModelMapType::const_iterator itr = modelsMap.begin();
for ( ; itr != modelsMap.end( ); itr++) {
if(!itr->second.isValid()) {
if(itr->second.getErrMess())
strcpy(errMess, itr->second.getErrMess());
return false;
}
}
return true;
}
@ -278,67 +377,85 @@ bool trpgModelTable::isValid() const
// Write out the model table
bool trpgModelTable::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)models.size());
for (unsigned int i=0;i<models.size();i++)
models[i].Write(buf);
buf.End();
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)modelsMap.size());
ModelMapType::iterator itr = modelsMap.begin();
for ( ; itr != modelsMap.end( ); itr++) {
itr->second.Write(buf);
}
buf.End();
return true;
return true;
}
/* ***************
Model Table Read methods
***************
*/
/* ***************
Model Table Read methods
***************
*/
// Get methods
bool trpgModelTable::GetNumModels(int &nm) const
{
if (!isValid()) return false;
nm = models.size();
return true;
if (!isValid()) return false;
nm = modelsMap.size();
return true;
}
bool trpgModelTable::GetModel(int id,trpgModel &model) const
{
if (!isValid() || id < 0 || id >= (int)models.size())
return false;
model = models[id];
return true;
if (!isValid() || id < 0 ) //|| id >= models.size())
return false;
//model = models[id];
ModelMapType::const_iterator itr = modelsMap.find(id);
if(itr == modelsMap.end()) {
return false;
}
model = itr->second;
return true;
}
trpgModel *trpgModelTable::GetModelRef(int id)
{
if (id < 0 || id >= (int)models.size())
return NULL;
return &models[id];
if (id < 0 ) //|| id >= models.size())
return NULL;
//return &models[id];
ModelMapType::iterator itr = modelsMap.find(id);
if(itr == modelsMap.end()) {
return false;
}
return &(itr->second);
}
bool trpgModelTable::Read(trpgReadBuffer &buf)
{
int32 numModel;
trpgModel model;
trpgToken tok;
int32 len;
bool status;
int32 numModel;
trpgToken tok;
int32 len;
bool status;
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
buf.GetToken(tok,len);
if (tok != TRPGMODELREF) throw 1;
buf.PushLimit(len);
status = model.Read(buf);
buf.PopLimit();
if (!status) throw 1;
models.push_back(model);
}
}
catch (...) {
return false;
}
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
trpgModel model;
buf.GetToken(tok,len);
bool readHandle;
if (tok == TRPGMODELREF)
readHandle = false;
else if (tok == TRPGMODELREF2)
readHandle = true;
else
throw 1;
buf.PushLimit(len);
status = model.Read(buf,readHandle);
buf.PopLimit();
if (!status) throw 1;
AddModel(model);
}
}
catch (...) {
return false;
}
return isValid();
return isValid();
}

View File

@ -18,18 +18,18 @@
#include <string.h>
/* trpage_nodes.cpp
The methods for all the hierarchy nodes (e.g. groups, transforms, etc...)
is here.
You should only need to modify this if you want to add something to one
of these classes.
*/
The methods for all the hierarchy nodes (e.g. groups, transforms, etc...)
is here.
You should only need to modify this if you want to add something to one
of these classes.
*/
#include <trpage_geom.h>
#include <trpage_read.h>
/* Write Group
Basic group.
*/
Basic group.
*/
// Constructor
trpgGroup::trpgGroup()
@ -49,8 +49,8 @@ void trpgGroup::Reset()
numChild = 0;
id = -1;
if ( name ) {
delete [] name;
name = 0;
delete [] name;
name = 0;
}
}
@ -71,15 +71,18 @@ void trpgGroup::SetID(int inID)
void trpgGroup::SetName(const char* newname )
{
if ( name ) {
delete [] name;
name = 0;
if ( name )
{
delete [] name;
name = 0;
}
if (newname) {
if ( strlen(newname) ) {
name = new char[strlen(newname)+1];
strcpy(name,newname);
}
if (newname)
{
if ( strlen(newname) )
{
name = new char[strlen(newname)+1];
strcpy(name,newname);
}
}
}
@ -115,14 +118,14 @@ bool trpgGroup::isValid() const
bool trpgGroup::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
buf.Begin(TRPG_GROUP);
buf.Add(numChild);
buf.Add(id);
if ( name && strlen(name) ) {
buf.Add(name);
buf.Add(name);
}
buf.End();
@ -134,27 +137,27 @@ bool trpgGroup::Write(trpgWriteBuffer &buf)
bool trpgGroup::Read(trpgReadBuffer &buf)
{
try {
buf.Get(numChild);
if (numChild < 0) throw 1;
buf.Get(id);
if (id < 0) throw 1;
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
buf.Get(numChild);
if (numChild < 0) throw 1;
buf.Get(id);
if (id < 0) throw 1;
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
}
catch (...) {
return false;
return false;
}
return isValid();
}
/* Write Billboard
Represents rotational billboarded geometry.
*/
Represents rotational billboarded geometry.
*/
// Constructor
trpgBillboard::trpgBillboard()
@ -176,9 +179,10 @@ void trpgBillboard::Reset()
axis = trpg3dPoint(0,0,1);
center = trpg3dPoint(0,0,0);
numChild = 0;
if ( name ) {
delete [] name;
name = 0;
if ( name )
{
delete [] name;
name = 0;
}
}
@ -231,7 +235,7 @@ bool trpgBillboard::GetType(int &t) const
bool trpgBillboard::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
buf.Begin(TRPG_BILLBOARD);
buf.Add(numChild);
@ -242,7 +246,7 @@ bool trpgBillboard::Write(trpgWriteBuffer &buf)
buf.Add(axis);
if ( name && strlen(name) ) {
buf.Add(name);
buf.Add(name);
}
buf.End();
@ -255,28 +259,28 @@ bool trpgBillboard::Read(trpgReadBuffer &buf)
uint8 uChar;
try {
buf.Get(numChild);
buf.Get(id);
buf.Get(uChar); type = uChar;
buf.Get(uChar); mode = uChar;
buf.Get(center);
buf.Get(axis);
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
buf.Get(numChild);
buf.Get(id);
buf.Get(uChar); type = uChar;
buf.Get(uChar); mode = uChar;
buf.Get(center);
buf.Get(axis);
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
}
catch (...) {
return false;
return false;
}
return isValid();
}
/* Write Level of Detail
Represents LOD information.
*/
Represents LOD information.
*/
// Constructor
trpgLod::trpgLod()
@ -299,8 +303,8 @@ void trpgLod::Reset()
rangeIndex = -1;
valid = true;
if ( name ) {
delete [] name;
name = 0;
delete [] name;
name = 0;
}
}
@ -313,7 +317,7 @@ void trpgLod::SetCenter(const trpg3dPoint &pt)
void trpgLod::SetNumChild(int no)
{
if (no < 0)
return;
return;
numRange = no;
}
@ -331,14 +335,14 @@ void trpgLod::SetID(int inID)
void trpgLod::SetName(const char* newname )
{
if ( name ) {
delete [] name;
name = 0;
delete [] name;
name = 0;
}
if (newname) {
if ( strlen(newname) ) {
name = new char[strlen(newname)+1];
strcpy(name,newname);
}
if ( strlen(newname) ) {
name = new char[strlen(newname)+1];
strcpy(name,newname);
}
}
}
@ -393,7 +397,7 @@ bool trpgLod::GetRangeIndex(int &ri) const
bool trpgLod::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
buf.Begin(TRPG_LOD);
buf.Add(id);
@ -404,9 +408,9 @@ bool trpgLod::Write(trpgWriteBuffer &buf)
buf.Add(width);
if ( name && strlen(name) ) {
buf.Add(name);
buf.Add(name);
} else
buf.Add("");
buf.Add("");
buf.End();
@ -418,33 +422,33 @@ bool trpgLod::Write(trpgWriteBuffer &buf)
bool trpgLod::Read(trpgReadBuffer &buf)
{
try {
buf.Get(id);
buf.Get(numRange);
if (numRange < 0) throw 1;
buf.Get(center);
buf.Get(switchIn);
buf.Get(switchOut);
buf.Get(width);
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
if (*nm)
SetName(nm);
// Look for a range index
if (!buf.isEmpty())
buf.Get(rangeIndex);
}
buf.Get(id);
buf.Get(numRange);
if (numRange < 0) throw 1;
buf.Get(center);
buf.Get(switchIn);
buf.Get(switchOut);
buf.Get(width);
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
if (*nm)
SetName(nm);
// Look for a range index
if (!buf.isEmpty())
buf.Get(rangeIndex);
}
}
catch (...) {
return false;
return false;
}
return isValid();
}
/* Write Layer
A layer is just a group with a different opcode.
*/
A layer is just a group with a different opcode.
*/
// Constructor
trpgLayer::trpgLayer()
@ -461,17 +465,17 @@ trpgLayer::~trpgLayer()
bool trpgLayer::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
buf.Begin(TRPG_LAYER);
buf.Add(numChild);
buf.Add(id);
if ( name && strlen(name) ) {
buf.Add(name);
buf.Add(name);
}
buf.End();
buf.End();
return true;
}
@ -480,18 +484,18 @@ bool trpgLayer::Write(trpgWriteBuffer &buf)
bool trpgLayer::Read(trpgReadBuffer &buf)
{
try {
buf.Get(numChild);
if (numChild < 0) throw 1;
buf.Get(id);
if (id < 0) throw 1;
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
buf.Get(numChild);
if (numChild < 0) throw 1;
buf.Get(id);
if (id < 0) throw 1;
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
}
catch (...) {
return false;
return false;
}
return isValid();
@ -502,14 +506,14 @@ void trpgLayer::Reset()
{
numChild = 0;
if ( name ) {
delete [] name;
name = 0;
delete [] name;
name = 0;
}
}
/* Write Transform
Matrix defining the transform with children.
*/
Matrix defining the transform with children.
*/
// Constructor
trpgTransform::trpgTransform()
@ -533,8 +537,8 @@ void trpgTransform::Reset()
m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1;
if ( name ) {
delete [] name;
name = 0;
delete [] name;
name = 0;
}
}
@ -552,9 +556,9 @@ bool trpgTransform::GetMatrix(float64 *rm) const
{
if (!isValid()) return false;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
// Note: is this right?
rm[i*4+j] = m[i][j];
for (int j=0;j<4;j++)
// Note: is this right?
rm[i*4+j] = m[i][j];
return true;
}
@ -562,17 +566,17 @@ bool trpgTransform::GetMatrix(float64 *rm) const
bool trpgTransform::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
buf.Begin(TRPG_TRANSFORM);
buf.Add(numChild);
buf.Add(id);
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Add(m[i][j]);
for (int j=0;j<4;j++)
buf.Add(m[i][j]);
if ( name && strlen(name) ) {
buf.Add(name);
buf.Add(name);
}
buf.End();
@ -583,28 +587,28 @@ bool trpgTransform::Write(trpgWriteBuffer &buf)
bool trpgTransform::Read(trpgReadBuffer &buf)
{
try {
buf.Get(numChild);
buf.Get(id);
if (numChild < 0) throw 1;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Get(m[i][j]);
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
buf.Get(numChild);
buf.Get(id);
if (numChild < 0) throw 1;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Get(m[i][j]);
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
}
catch (...) {
return false;
return false;
}
return isValid();
}
/* Model Reference
This is just a matrix transform and a model ID.
*/
This is just a matrix transform and a model ID.
*/
// Constructor
trpgModelRef::trpgModelRef()
@ -650,9 +654,9 @@ bool trpgModelRef::GetMatrix(float64 *rm) const
{
if (!isValid()) return false;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
// Note: is this right?
rm[i*4+j] = m[i][j];
for (int j=0;j<4;j++)
// Note: is this right?
rm[i*4+j] = m[i][j];
return true;
}
@ -660,13 +664,13 @@ bool trpgModelRef::GetMatrix(float64 *rm) const
bool trpgModelRef::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
buf.Begin(TRPG_MODELREF);
buf.Add(modelRef);
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Add(m[i][j]);
for (int j=0;j<4;j++)
buf.Add(m[i][j]);
buf.End();
return true;
@ -676,14 +680,15 @@ bool trpgModelRef::Write(trpgWriteBuffer &buf)
bool trpgModelRef::Read(trpgReadBuffer &buf)
{
try {
buf.Get(modelRef);
if (modelRef < 0) throw 1;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Get(m[i][j]);
buf.Get(modelRef);
if (modelRef < 0)
throw 1;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Get(m[i][j]);
}
catch (...) {
return false;
return false;
}
valid = true;
@ -691,10 +696,10 @@ bool trpgModelRef::Read(trpgReadBuffer &buf)
}
/* Attach Node
You'll find one of these in each tile, except for the lowest LOD.
It's basically a group with some extra info that tells you where to attach it.
The ID corresponds to the one in Group and LOD.
*/
You'll find one of these in each tile, except for the lowest LOD.
It's basically a group with some extra info that tells you where to attach it.
The ID corresponds to the one in Group and LOD.
*/
// Constructor
trpgAttach::trpgAttach()
@ -713,8 +718,8 @@ void trpgAttach::Reset()
parentID = -1;
childPos = -1;
if ( name ) {
delete [] name;
name = 0;
delete [] name;
name = 0;
}
}
@ -762,7 +767,7 @@ bool trpgAttach::Write(trpgWriteBuffer &buf)
buf.Add(childPos);
if ( name && strlen(name) ) {
buf.Add(name);
buf.Add(name);
}
buf.End();
@ -774,22 +779,165 @@ bool trpgAttach::Write(trpgWriteBuffer &buf)
bool trpgAttach::Read(trpgReadBuffer &buf)
{
try {
buf.Get(numChild);
buf.Get(id);
if (id < 0) throw 1;
buf.Get(parentID);
if (parentID < 0) throw 1;
buf.Get(childPos);
if (childPos < 0) throw 1;
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
buf.Get(numChild);
buf.Get(id);
if (id < 0) throw 1;
buf.Get(parentID);
if (parentID < 0) throw 1;
buf.Get(childPos);
if (childPos < 0) throw 1;
if ( !buf.isEmpty() ) {
char nm[1024] = {0};
buf.Get(nm,1024);
SetName(nm);
}
}
catch (...) {
return false;
return false;
}
return true;
}
/* ChildRef Node
You'll find in the parent tile one of these for each tile children.
It gives the children grid location and file address.
*/
// Constructor
trpgChildRef::trpgChildRef()
{
Reset();
}
trpgChildRef::~trpgChildRef()
{
Reset();
}
// Reset
void trpgChildRef::Reset()
{
x = -1;
y = -1;
lod = -1;
addr.file = -1;
addr.offset = -1;
}
void trpgChildRef::SetTileLoc(int gx,int gy,int glod)
{
x = gx;
y = gy;
lod = glod;
}
bool trpgChildRef::GetTileLoc(int &gx,int &gy,int &glod) const
{
if (!isValid()) return false;
gx = x;
gy = y;
glod = lod;
return true;
}
void trpgChildRef::SetTileAddress(const trpgwAppAddress& gAddr)
{
addr = gAddr;
}
void trpgChildRef::SetTileAddress(int32 file, int32 offset)
{
addr.file = file;
addr.offset = offset;
}
bool trpgChildRef::GetTileAddress(int32& file, int32& offset) const
{
if (!isValid()) return false;
file = addr.file;
offset = addr.offset;
return true;
}
bool trpgChildRef::GetTileAddress(trpgwAppAddress& gAddr) const
{
if (!isValid()) return false;
gAddr = addr;
return true;
}
void trpgChildRef::SetTileZValue( float gZmin, float gZmax)
{
zmin = gZmin;
zmax = gZmax;
}
bool trpgChildRef::GetTileZValue( float& gZmin, float& gZmax) const
{
if (!isValid()) return false;
gZmin = zmin;
gZmax = zmax;
return true;
}
// Validity check
bool trpgChildRef::isValid() const
{
if (lod < 0)
return false;
return true;
}
// Write Attach node
bool trpgChildRef::Write(trpgWriteBuffer &buf)
{
if (!isValid()) return false;
buf.Begin(TRPG_CHILDREF);
buf.Add(lod);
buf.Add(x);
buf.Add(y);
buf.Add(addr.file);
buf.Add(addr.offset);
buf.Add(zmin);
buf.Add(zmax);
buf.End();
return true;
}
// Read Attach node
bool trpgChildRef::Read(trpgReadBuffer &buf)
{
try
{
buf.Get(lod);
if (lod < 0) throw 1;
buf.Get(x);
buf.Get(y);
buf.Get(addr.file);
buf.Get(addr.offset);
buf.Get(zmin);
buf.Get(zmax);
}
catch (...)
{
return false;
}
return true;
}

View File

@ -17,23 +17,23 @@
#include <stdio.h>
/* trpage_parse.cpp
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
trpgr_Parser is the main class. It parses the basic structure of paging archive
data out of Read Buffers. You should not need to change this.
If you want to parse data out of a different structure instead, look at
subclassing trpgReadBuffer and replacing its virtual methods. That's what
trpgMemReadBuffer is doing.
This file also contains the implementation of trpgSceneParser().
That class implements a set of callbacks for handling the Pushes and Pops
in an archive. You fill in the Start/EndChildren callbacks and register
for the rest of the tokens that you want.
*/
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
trpgr_Parser is the main class. It parses the basic structure of paging archive
data out of Read Buffers. You should not need to change this.
If you want to parse data out of a different structure instead, look at
subclassing trpgReadBuffer and replacing its virtual methods. That's what
trpgMemReadBuffer is doing.
This file also contains the implementation of trpgSceneParser().
That class implements a set of callbacks for handling the Pushes and Pops
in an archive. You fill in the Start/EndChildren callbacks and register
for the rest of the tokens that you want.
*/
#include <trpage_read.h>
/* ***************************
Paging token callback structure
Paging token callback structure
***************************
*/
trpgr_Token::trpgr_Token()
@ -59,13 +59,13 @@ void trpgr_Token::init(int in_tok,trpgr_Callback *in_cb,bool in_dest)
void trpgr_Token::Destruct()
{
if (cb && destroy)
delete cb;
delete cb;
cb = NULL;
destroy = true;
}
/* ***************************
Paging parser implementation.
Paging parser implementation.
***************************
*/
@ -98,10 +98,10 @@ class WriteWrapper : public trpgr_Callback {
public:
WriteWrapper(trpgReadWriteable *in_wr) { wr = in_wr; };
void *Parse(trpgToken,trpgReadBuffer &buf) {
if (wr->Read(buf))
return wr;
else
return NULL;
if (wr->Read(buf))
return wr;
else
return NULL;
}
protected:
trpgReadWriteable *wr;
@ -114,6 +114,25 @@ void trpgr_Parser::AddCallback(trpgToken tok,trpgReadWriteable *wr)
AddCallback(tok,new WriteWrapper(wr),true);
}
// Get the claaback associated with a token, will return 0 if none
const trpgr_Callback *trpgr_Parser::GetCallback(trpgToken tok) const
{
tok_map::const_iterator iter = tokenMap.find(tok);
if(iter != tokenMap.end())
return iter->second.cb;
else
return 0;
}
trpgr_Callback *trpgr_Parser::GetCallback(trpgToken tok)
{
tok_map::iterator iter = tokenMap.find(tok);
if(iter != tokenMap.end())
return iter->second.cb;
else
return 0;
}
// Remove Callback
void trpgr_Parser::RemoveCallback(trpgToken tok)
{
@ -129,13 +148,13 @@ void trpgr_Parser::SetDefaultCallback(trpgr_Callback *cb,bool in_dest)
}
/* Token Is Valid
Checks if something *could be* a token.
Doesn't necessarily mean that it is.
*/
Checks if something *could be* a token.
Doesn't necessarily mean that it is.
*/
bool trpgr_Parser::TokenIsValid(trpgToken tok)
{
if (tok < 0)
return false;
return false;
return true;
}
@ -144,97 +163,112 @@ bool trpgr_Parser::TokenIsValid(trpgToken tok)
This runs through the given buffer parsing token sets until
it (1) runs out of buffer or (2) fails.
Note: Good place to return an exception, but keep it simple for now.
*/
*/
bool trpgr_Parser::Parse(trpgReadBuffer &buf)
{
bool ret = true;
try {
while (!buf.isEmpty()) {
/* We're expecting the following
Token (int32)
Length (int32)
Data (variable)
*/
trpgToken tok;
int32 len;
if (!buf.Get(tok)) throw 1;
// Push and Pop are special - no data
if (tok != TRPG_PUSH && tok != TRPG_POP) {
if (!buf.Get(len)) throw 1;
if (!TokenIsValid(tok)) throw 1;
if (len < 0) throw 1;
// Limit what we're reading to the length of this
buf.PushLimit(len);
}
try
{
while (!buf.isEmpty())
{
/* We're expecting the following
Token (int32)
Length (int32)
Data (variable)
*/
trpgToken tok;
int32 len;
if (!buf.Get(tok)) throw 1;
// Push and Pop are special - no data
if (tok != TRPG_PUSH && tok != TRPG_POP)
{
if (!buf.Get(len)) throw 1;
if (!TokenIsValid(tok)) throw 1;
if (len < 0) throw 1;
// Limit what we're reading to the length of this
buf.PushLimit(len);
}
// Call our token handler for this one
try {
const trpgr_Token *tcb = NULL;
tok_map::const_iterator p = tokenMap.find(tok);
if (p != tokenMap.end())
tcb = &(*p).second;
if (!tcb)
// No such token, call the default
tcb = &defCb;
// Call our token handler for this one
try
{
const trpgr_Token *tcb = NULL;
tok_map::const_iterator p = tokenMap.find(tok);
if (p != tokenMap.end())
tcb = &(*p).second;
if (!tcb)
// No such token, call the default
tcb = &defCb;
// Run the callback
if (tcb->cb) {
void *ret = tcb->cb->Parse(tok,buf);
// Note: Do something with the return value
lastObject = ret;
}
}
catch (...) {
// Don't want to screw up the limit stack
}
// No limit to worry about with push and pop
if (tok != TRPG_PUSH && tok != TRPG_POP) {
buf.SkipToLimit();
buf.PopLimit();
}
}
// Run the callback
if (tcb->cb)
{
void *ret = tcb->cb->Parse(tok,buf);
// Note: Do something with the return value
lastObject = ret;
}
}
catch (...)
{
// Don't want to screw up the limit stack
}
// No limit to worry about with push and pop
if (tok != TRPG_PUSH && tok != TRPG_POP)
{
buf.SkipToLimit();
buf.PopLimit();
}
}
}
catch (...) {
// Failed to parse.
ret = false;
catch (...)
{
// Failed to parse.
ret = false;
}
return ret;
}
/* ****************
Scene Parser
****************
*/
/* ****************
Scene Parser
****************
*/
// Helper - callback for Push
class trpgSceneHelperPush : public trpgr_Callback {
class trpgSceneHelperPush : public trpgr_Callback
{
public:
trpgSceneHelperPush(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Call the start children callback
parse->StartChildren(parse->lastObject);
parse->parents.push_back(parse->lastObject);
return (void *)1;
trpgSceneHelperPush(trpgSceneParser *in_parse)
{ parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
{
// Call the start children callback
parse->StartChildren(parse->lastObject);
parse->parents.push_back(parse->lastObject);
return (void *)1;
}
protected:
trpgSceneParser *parse;
};
// Helper - callback for Pop
class trpgSceneHelperPop : public trpgr_Callback {
class trpgSceneHelperPop : public trpgr_Callback
{
public:
trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Make sure we don't have an extra pop
if (parse->parents.size() == 0)
// Note: let someone know about the extra pop
return NULL;
// Call the end children callback
int len = parse->parents.size();
parse->EndChildren(parse->parents[len-1]);
parse->parents.resize(len-1);
return (void *)1;
trpgSceneHelperPop(trpgSceneParser *in_parse)
{ parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
{
// Make sure we don't have an extra pop
if (parse->parents.size() == 0)
// Note: let someone know about the extra pop
return NULL;
// Call the end children callback
int len = parse->parents.size();
parse->EndChildren(parse->parents[len-1]);
parse->parents.resize(len-1);
return (void *)1;
}
protected:
trpgSceneParser *parse;
@ -243,12 +277,14 @@ protected:
// Helper - default callback
// Puts a 1 on the parent stack
// Note: Need to use this fact above
class trpgSceneHelperDefault : public trpgr_Callback {
class trpgSceneHelperDefault : public trpgr_Callback
{
public:
trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Absorb it quietly
return (void *)1;
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
{
// Absorb it quietly
return (void *)1;
}
protected:
trpgSceneParser *parse;

View File

@ -18,183 +18,293 @@
#include <string.h>
/* trpage_pparse.cpp
This file contains classes that can parse a TerraPage
archive for the purpose of printing it out.
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>
#include <trpage_managers.h>
namespace
{
// This will recursivelly call itself up until
// all the tiule are done
void printBuf(int lod, int x, int y, trpgr_Archive *archive, trpgPrintGraphParser& parser, trpgMemReadBuffer &buf, trpgPrintBuffer &pBuf)
{
char ls[1024];
sprintf(ls,"Tile (lod) (x,y) = (%d) (%d,%d)", lod, x, y);
pBuf.prnLine(ls);
pBuf.IncreaseIndent();
parser.Reset();
parser.Parse(buf);
pBuf.DecreaseIndent();
// Save the list
// std::vector<const trpgChildRef> childRefList;
// The const in the template parameter was removed because it causes GCC to
// freak out. I am of the opinion that const doesn't make sense in a template
// parameter for std::vector anyway... const prevents you from changing the
// value, so what exactly is the point? How does one add entries to the vector
// without giving them a value? -ADS
std::vector<trpgChildRef> childRefList;
for(unsigned int idx =0; idx < parser.GetNbChildrenRef(); idx++)
childRefList.push_back(*parser.GetChildRef(idx));
for(unsigned int idx =0; idx < childRefList.size(); idx++)
{
const trpgChildRef& childRef = childRefList[idx];
trpgMemReadBuffer childBuf(archive->GetEndian());
trpgwAppAddress tileAddr;
int glod, gx, gy;
childRef.GetTileAddress(tileAddr);
childRef.GetTileLoc(gx,gy,glod);
trpgTileTable::TileMode mode;
archive->GetTileTable()->GetMode(mode);
bool status;
if(mode == trpgTileTable::Local)
status = archive->ReadTile(tileAddr, childBuf);
else
status = archive->ReadExternalTile(gx, gy, glod, childBuf);
if(status)
printBuf(glod, gx, gy, archive, parser, childBuf, pBuf);
}
}
} // end namespace
/* Set up the callbacks for the scene graph parser.
In our case this is just one read helper with
a switch statement.
In our case this is just one read helper with
a switch statement.
*/
trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelper *inImg,trpgPrintBuffer *inBuf)
trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelper *inImg,trpgPrintBuffer *inBuf):printBuf(inBuf), archive(inArch), imageHelp(inImg), childRefCB(0)
{
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));
// 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_CHILDREF,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));
childRefCB = dynamic_cast<ReadHelper *>(GetCallback(TRPG_CHILDREF));
}
/* Start Children is called when the parser hits a Push
in the read buffer. We just want to indent further when
that happens.
in the read buffer. We just want to indent further when
that happens.
*/
bool trpgPrintGraphParser::StartChildren(void *)
{
printBuf->IncreaseIndent();
printBuf->IncreaseIndent();
return true;
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.
in the read buffer. We just want to reduce the indent
when that happens.
*/
bool trpgPrintGraphParser::EndChildren(void *)
{
printBuf->DecreaseIndent();
printBuf->DecreaseIndent();
return true;
return true;
}
unsigned int trpgPrintGraphParser::GetNbChildrenRef() const
{
if(childRefCB)
return childRefCB->GetNbChildrenRef();
else
return 0;
}
const trpgChildRef* trpgPrintGraphParser::GetChildRef(unsigned int idx) const
{
if(childRefCB)
return childRefCB->GetChildRef(idx);
else
return 0;
}
void trpgPrintGraphParser::Reset()
{
if(childRefCB)
childRefCB->Reset();
}
void trpgPrintGraphParser::ReadHelper::Reset()
{
childRefList.clear();
}
unsigned int trpgPrintGraphParser::ReadHelper::GetNbChildrenRef() const
{
return childRefList.size();
}
const trpgChildRef* trpgPrintGraphParser::ReadHelper::GetChildRef(unsigned int idx) const
{
if(idx >= childRefList.size())
return 0;
else
return &childRefList[idx];
}
/* Read Helper parse method sets up the correct class depending
on the token and asks it to read and print itself.
on the token and asks it to read and print itself. It will save
any child ref node encountered that a user can access to continue
traversal.
*/
void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf)
{
trpgReadWriteable *obj = NULL;
trpgTileHeader *tileHead = NULL;
// This will celar any child ref list from a previous parse.
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;
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_CHILDREF:
childRefList.push_back(trpgChildRef());
obj = &childRefList.back();
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;
};
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);
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 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;
}
}
}
}
}
}
// 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;
}
// We delete all object except the child ref node
if(tok != TRPG_CHILDREF)
delete obj;
}
// Need to return non-zero. Otherwise it's interpreted as an error
return (void *)1;
// 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.
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
@ -202,88 +312,120 @@ void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf)
*/
bool trpgPrintArchive(char *filename,trpgPrintBuffer &pBuf,int flags)
{
trpgr_Archive archive;
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);
// 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);
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;
}
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;
bool status = trpgPrintArchive(&archive,pBuff,flags);
return status;
}
#endif
bool trpgPrintArchive(trpgr_Archive *archive,trpgPrintBuffer &pBuf,int flags)
{
char ls[1024];
char ls[1024];
if (!archive->isValid()) return false;
pBuf.prnLine("====Header Structures====");
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();
// 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
// Read the local images and do the math for the templates
// Now do the tiles
if (!archive->isValid()) return false;
// 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);
int majorVersion, minorVersion;
archive->GetHeader()->GetVersion(majorVersion, minorVersion);
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.");
}
}
// Parser that prints out a tile scene graph
trpgrImageHelper* imageHelp=archive->GetNewRImageHelper(archive->GetEndian(),archive->getDir(),
*archive->GetMaterialTable(),*archive->GetTexTable());
return true;
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;
if(majorVersion == 2 && minorVersion >= 1)
{
// Version 2.1
// Because of variable lod support in version 2.1 and over, we can
// no longer suppose that all lod level are all populated with tiles
// in all of the gaming area. We have to parse the parent to know that.
// Also the tile table only contains lod 0 tiles so we can no longer access
// the tile directly from its grid location. So we have to traverse.
trpg2iPoint blockTileSize;
if(archive->GetHeader()->GetLodSize(0,blockTileSize)) {
for(x = 0; x < blockTileSize.x; x++)
for( y = 0; y < blockTileSize.y; y++)
if (archive->ReadTile(x,y,0,buf))
printBuf(0, x, y, archive, parser, buf, pBuf);
}
}
else
{
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
if (!parser.Parse(buf))
{
char errString[80];
sprintf(errString, "**** Warning: tile anomaly detected: (%d) (%d,%d) ****",nl,x,y);
// send it both ways so it's easier to spot
pBuf.prnLine(errString);
fprintf(stderr,"%s\n",errString);
}
pBuf.DecreaseIndent();
}
} else
pBuf.prnLine(" Couldn't read tile.");
}
}
}
return true;
}

View File

@ -18,20 +18,20 @@
#include <string.h>
/* trpage_print.cpp
Print out the contents of a TerraPage archive.
This module provides an example of how to access each of the classes
within a TerraPage archive.
*/
Print out the contents of a TerraPage archive.
This module provides an example of how to access each of the classes
within a TerraPage archive.
*/
#include <trpage_print.h>
/* ******************************************
Print Buffer implementation
The print buffer is a way to dump debugging data out
to a file (or console). You can make your own subclass
of trpgPrintBuffer if you have specific needs.
The print buffer is a way to dump debugging data out
to a file (or console). You can make your own subclass
of trpgPrintBuffer if you have specific needs.
******************************************
*/
*/
trpgPrintBuffer::trpgPrintBuffer()
{
@ -96,7 +96,8 @@ bool trpgFilePrintBuffer::prnLine(char *str)
if (!fp)
return false;
if (str) {
if (str)
{
fprintf(fp,indentStr);
fprintf(fp,str);
fprintf(fp,"\n");
@ -112,7 +113,7 @@ bool trpgFilePrintBuffer::prnLine(char *str)
is readable/writeable are here. These are used for
debugging.
*************************************
*/
*/
/* Print out the header information.
*/
@ -122,14 +123,20 @@ bool trpgHeader::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Archive Header----");
buf.IncreaseIndent();
sprintf(ls,"verMinor = %d, verMajor = %d",verMinor,verMajor); buf.prnLine(ls);
if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR))
{
sprintf(ls,"isMaster = %s, numRows = %d, numCols = %d",GetIsMaster()?"YES":"NO",rows,cols); buf.prnLine(ls);
}
sprintf(ls,"dbVerMinor = %d, dbVerMajor = %d",dbVerMinor,dbVerMajor); buf.prnLine(ls);
sprintf(ls,"maxGroupID = %d",maxGroupID); buf.prnLine(ls);
sprintf(ls,"sw = (%f,%f), ne = (%f,%f)",sw.x,sw.y,ne.x,ne.y); buf.prnLine(ls);
sprintf(ls,"tileType = %d, origin = (%f,%f,%f)",tileType,origin.x,origin.y,origin.z); buf.prnLine(ls);
sprintf(ls,"numLods = %d",numLods); buf.prnLine(ls);
buf.IncreaseIndent();
for (int i=0;i<numLods;i++) {
for (int i=0;i<numLods;i++)
{
sprintf(ls,"tileSize = (%f,%f), lodSizes = (%d,%d), lodRanges = %f",tileSize[i].x,tileSize[i].y,lodSizes[i].x,lodSizes[i].y,lodRanges[i]); buf.prnLine(ls);
}
buf.DecreaseIndent(2);
@ -176,7 +183,8 @@ bool trpgMaterial::Print(trpgPrintBuffer &buf) const
sprintf(ls,"numTile = %d",numTile); buf.prnLine(ls);
sprintf(ls,"numTex = %d",numTex); buf.prnLine(ls);
buf.IncreaseIndent();
for (int i=0;i<numTex;i++) {
for (int i=0;i<numTex;i++)
{
sprintf(ls,"texID[%d] = %d",i,texids[i]); buf.prnLine(ls);
buf.IncreaseIndent();
texEnvs[i].Print(buf);
@ -199,16 +207,18 @@ bool trpgMatTable::Print(trpgPrintBuffer &buf) const
sprintf(ls,"numTable = %d",numTable); buf.prnLine(ls);
sprintf(ls,"numMat = %d",numMat); buf.prnLine(ls);
buf.IncreaseIndent();
for (int j=0;j<numTable;j++) {
sprintf(ls,"----Sub Table %d----",j); buf.prnLine(ls);
buf.IncreaseIndent();
for (int i=0;i<numMat;i++) {
const trpgMaterial *mat;
sprintf(ls,"Material %d",i); buf.prnLine(ls);
mat = (const_cast<trpgMatTable *>(this))->GetMaterialRef(j,i);
mat->Print(buf);
MaterialMapType::const_iterator itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++)
{
const trpgMaterial *mat;
sprintf(ls,"Material %d",itr->first); buf.prnLine(ls);
mat = (const_cast<trpgMatTable *>(this))->GetMaterialRef(0,itr->first);
if(!mat)
{
sprintf(ls,"Error: Unable to load material!"); buf.prnLine(ls);
}
buf.DecreaseIndent();
else
mat->Print(buf);
}
buf.DecreaseIndent(2);
@ -227,9 +237,10 @@ bool trpgTexture::Print(trpgPrintBuffer &buf) const
sprintf(ls,"Name = %s",name); buf.prnLine(ls);
sprintf(ls,"useCount = %d",useCount); buf.prnLine(ls);
sprintf(ls,"sizeX = %d, sizeY = %d, sizeZ = %d",sizeX,sizeY,numLayer); buf.prnLine(ls);
sprintf(ls,"sensor band organization = %d",org); buf.prnLine(ls);
// sprintf(ls,"sensor band organization = %d",org); buf.prnLine(ls); // does this need to be added?
sprintf(ls,"ismipmap = %d",isMipmap); buf.prnLine(ls);
sprintf(ls,"addr.file = %d, addr.offset = %d",addr.file,addr.offset); buf.prnLine(ls);
sprintf(ls,"addr.col = %d, addr.row = %d",addr.col,addr.row); buf.prnLine(ls);
buf.DecreaseIndent();
buf.prnLine();
@ -245,9 +256,11 @@ bool trpgTexTable::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Texture Table----");
buf.IncreaseIndent();
for (unsigned int i=0;i<texList.size();i++) {
sprintf(ls,"Texture %d",i); buf.prnLine(ls);
texList[i].Print(buf);
TextureMapType::const_iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++)
{
sprintf(ls,"Texture %d",itr->first); buf.prnLine(ls);
itr->second.Print(buf);
}
buf.DecreaseIndent();
@ -264,9 +277,11 @@ bool trpgModelTable::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Model Table----");
buf.IncreaseIndent();
for (unsigned int i=0;i<models.size();i++) {
sprintf(ls,"Model %d",i); buf.prnLine(ls);
models[i].Print(buf);
ModelMapType::const_iterator itr = modelsMap.begin();
for ( ; itr != modelsMap.end( ); itr++)
{
sprintf(ls,"Model %d",itr->first); buf.prnLine(ls);
itr->second.Print(buf);
}
buf.DecreaseIndent();
@ -284,7 +299,8 @@ bool trpgModel::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Model----");
buf.IncreaseIndent();
sprintf(ls,"type = %d",type); buf.prnLine(ls);
if (name) {
if (name)
{
sprintf(ls,"name = %s",name); buf.prnLine(ls);
}
sprintf(ls,"diskRef = %d",(int)diskRef), buf.prnLine(ls);
@ -308,14 +324,16 @@ bool trpgTileHeader::Print(trpgPrintBuffer &buf) const
sprintf(ls,"matList size = %d",static_cast<int>(matList.size())); buf.prnLine(ls);
buf.IncreaseIndent();
unsigned int i;
for (i=0;i<matList.size();i++) {
for (i=0;i<matList.size();i++)
{
sprintf(ls,"matList[%d] = %d",i,matList[i]); buf.prnLine(ls);
}
buf.DecreaseIndent();
sprintf(ls,"modelList size = %d",static_cast<int>(modelList.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (i=0;i<modelList.size();i++) {
for (i=0;i<modelList.size();i++)
{
sprintf(ls,"modelList[%d] = %d",i,modelList[i]); buf.prnLine(ls);
}
buf.DecreaseIndent();
@ -344,7 +362,8 @@ bool trpgColorInfo::Print(trpgPrintBuffer &buf) const
sprintf(ls,"type = %d, bind = %d",type,bind); buf.prnLine(ls);
sprintf(ls,"colorData size = %d",static_cast<int>(data.size()));
buf.IncreaseIndent();
for (unsigned int i=0;i<data.size();i++) {
for (unsigned int i=0;i<data.size();i++)
{
sprintf(ls,"color[%d] = (%f,%f,%f)",i,data[i].red,data[i].blue,data[i].green); buf.prnLine(ls);
}
buf.DecreaseIndent(2);
@ -363,18 +382,24 @@ bool trpgTexData::Print(trpgPrintBuffer &buf) const
buf.IncreaseIndent();
sprintf(ls,"bind = %d",bind); buf.prnLine(ls);
if (floatData.size()) {
if (floatData.size())
{
sprintf(ls,"tex coords (float) = %d",static_cast<int>(floatData.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (unsigned int i=0;i<floatData.size()/2;i++) {
for (unsigned int i=0;i<floatData.size()/2;i++)
{
sprintf(ls,"tex coord[%d] = (%f,%f)",i,floatData[i*2+0],floatData[i*2+1]); buf.prnLine(ls);
}
buf.DecreaseIndent();
} else {
if (doubleData.size()) {
}
else
{
if (doubleData.size())
{
sprintf(ls,"tex coords (double) = %d",static_cast<int>(doubleData.size()));
buf.IncreaseIndent();
for (unsigned int i=0;i<doubleData.size()/2;i++) {
for (unsigned int i=0;i<doubleData.size()/2;i++)
{
sprintf(ls,"tex coord[%d] = (%f,%f)",i,doubleData[i*2+0],doubleData[i*2+1]), buf.prnLine(ls);
}
buf.DecreaseIndent();
@ -400,7 +425,8 @@ bool trpgGeometry::Print(trpgPrintBuffer &buf) const
buf.IncreaseIndent();
ls[0] = 0;
unsigned int i;
for (i=0;i<materials.size();i++) {
for (i=0;i<materials.size();i++)
{
char locStr[100];
sprintf(locStr,"%d ",materials[i]);
strcat(ls,locStr);
@ -412,7 +438,8 @@ bool trpgGeometry::Print(trpgPrintBuffer &buf) const
sprintf(ls,"primLength size = %d",static_cast<int>(primLength.size())); buf.prnLine(ls);
buf.IncreaseIndent();
ls[0] = 0;
for (i=0;i<primLength.size();i++) {
for (i=0;i<primLength.size();i++)
{
char locStr[100];
sprintf(locStr,"%d ",primLength[i]);
strcat(ls,locStr);
@ -420,21 +447,27 @@ bool trpgGeometry::Print(trpgPrintBuffer &buf) const
buf.prnLine(ls);
buf.DecreaseIndent();
if (vertDataFloat.size()) {
if (vertDataFloat.size())
{
sprintf(ls,"vert data (float) length = %d",static_cast<int>(vertDataFloat.size()));
buf.prnLine(ls);
buf.IncreaseIndent();
for (i=0;i<vertDataFloat.size()/3;i++) {
for (i=0;i<vertDataFloat.size()/3;i++)
{
sprintf(ls,"(%f, %f, %f)",vertDataFloat[3*i],vertDataFloat[3*i+1],vertDataFloat[3*i+2]);
buf.prnLine(ls);
}
buf.DecreaseIndent();
} else {
if (vertDataDouble.size()) {
}
else
{
if (vertDataDouble.size())
{
sprintf(ls,"vert data (double) length = %d",static_cast<int>(vertDataDouble.size()));
buf.prnLine(ls);
buf.IncreaseIndent();
for (i=0;i<vertDataDouble.size()/3;i++) {
for (i=0;i<vertDataDouble.size()/3;i++)
{
sprintf(ls,"(%f, %f, %f)",vertDataDouble[3*i],vertDataDouble[3*i+1],vertDataDouble[3*i+2]);
buf.prnLine(ls);
}
@ -444,21 +477,27 @@ bool trpgGeometry::Print(trpgPrintBuffer &buf) const
sprintf(ls,"normBind = %d",normBind); buf.prnLine(ls);
if (normDataFloat.size()) {
if (normDataFloat.size())
{
sprintf(ls,"norm data (float) length = %d",static_cast<int>(normDataFloat.size()));
buf.prnLine(ls);
buf.IncreaseIndent();
for (i=0;i<normDataFloat.size()/3;i++) {
for (i=0;i<normDataFloat.size()/3;i++)
{
sprintf(ls,"(%f, %f, %f)",normDataFloat[3*i],normDataFloat[3*i+1],normDataFloat[3*i+2]);
buf.prnLine(ls);
}
buf.DecreaseIndent();
} else {
if (normDataDouble.size()) {
}
else
{
if (normDataDouble.size())
{
sprintf(ls,"norm data (double) length = %d",static_cast<int>(normDataDouble.size()));
buf.prnLine(ls);
buf.IncreaseIndent();
for (i=0;i<normDataDouble.size()/3;i++) {
for (i=0;i<normDataDouble.size()/3;i++)
{
sprintf(ls,"(%f, %f, %f)",normDataDouble[3*i],normDataDouble[3*i+1],normDataDouble[3*i+2]);
buf.prnLine(ls);
}
@ -468,14 +507,16 @@ bool trpgGeometry::Print(trpgPrintBuffer &buf) const
sprintf(ls,"color info size = %d",static_cast<int>(colors.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (i=0;i<colors.size();i++) {
for (i=0;i<colors.size();i++)
{
colors[i].Print(buf);
}
buf.DecreaseIndent();
sprintf(ls,"tex data size = %d",static_cast<int>(texData.size()));
buf.IncreaseIndent();
for (i=0;i<texData.size();i++) {
for (i=0;i<texData.size();i++)
{
texData[i].Print(buf);
}
buf.DecreaseIndent();
@ -497,7 +538,7 @@ bool trpgGroup::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Group Node----");
buf.IncreaseIndent();
sprintf(ls,"id = %d, numChild = %d",id,numChild); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
buf.DecreaseIndent();
@ -515,7 +556,25 @@ bool trpgAttach::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Attach Node----");
buf.IncreaseIndent();
sprintf(ls,"id = %d, parentID = %d, childPos = %d",id,parentID,childPos); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
buf.DecreaseIndent();
buf.prnLine();
return true;
}
/* Print ChildRef info
*/
bool trpgChildRef::Print(trpgPrintBuffer &buf) const
{
char ls[1024];
buf.prnLine("----RefChild Node----");
buf.IncreaseIndent();
sprintf(ls,"lod = %d, x = %d, y = %d", lod, x, y); buf.prnLine(ls);
sprintf(ls,"file = %d, offset = %d", addr.file, addr.offset); buf.prnLine(ls);
sprintf(ls,"zmin = %f, zmax = %f", zmin, zmax); buf.prnLine(ls);
buf.DecreaseIndent();
buf.prnLine();
@ -534,7 +593,7 @@ bool trpgBillboard::Print(trpgPrintBuffer &buf) const
sprintf(ls,"id = %d, type = %d, mode = %d",id,type,mode); buf.prnLine(ls);
sprintf(ls,"center = (%f,%f,%f)",center.x,center.y,center.z); buf.prnLine(ls);
sprintf(ls,"axis = (%f,%f,%f)",axis.x,axis.y,axis.z); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
buf.DecreaseIndent();
buf.prnLine();
@ -554,7 +613,7 @@ bool trpgLod::Print(trpgPrintBuffer &buf) const
sprintf(ls,"numRange (hint) = %d",numRange); buf.prnLine(ls);
sprintf(ls,"switchIn = %f, switchOut = %f, width = %f",switchIn,switchOut,width); buf.prnLine(ls);
sprintf(ls,"center = (%f,%f,%f)",center.x,center.y,center.z);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"rangeIndex = %d",rangeIndex); buf.prnLine(ls);
buf.DecreaseIndent();
@ -572,7 +631,7 @@ bool trpgLayer::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Layer Node----");
buf.IncreaseIndent();
sprintf(ls,"id = %d",id); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
buf.DecreaseIndent();
buf.prnLine();
@ -590,12 +649,13 @@ bool trpgTransform::Print(trpgPrintBuffer &buf) const
buf.IncreaseIndent();
sprintf(ls,"id = %d",id); buf.prnLine(ls);
buf.IncreaseIndent();
for (int i=0;i<4;i++) {
for (int i=0;i<4;i++)
{
sprintf(ls,"%f %f %f %f",m[i][0],m[i][1],m[i][2],m[i][3]);
buf.prnLine(ls);
}
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
sprintf(ls,"name = %s", name ? name : "noname" ); buf.prnLine(ls);
buf.DecreaseIndent(2);
buf.prnLine();
@ -612,11 +672,12 @@ bool trpgModelRef::Print(trpgPrintBuffer &buf) const
buf.IncreaseIndent();
sprintf(ls,"modelRef = %d",modelRef); buf.prnLine(ls);
buf.IncreaseIndent();
for (int i=0;i<4;i++) {
for (int i=0;i<4;i++)
{
sprintf(ls,"%f %f %f %f",m[i][0],m[i][1],m[i][2],m[i][3]);
buf.prnLine(ls);
}
buf.DecreaseIndent(2);
buf.prnLine();
@ -631,14 +692,30 @@ bool trpgTileTable::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Tile Table----");
buf.IncreaseIndent();
sprintf(ls,"mode = %d",mode); buf.prnLine(ls);
switch(mode)
{
case Local:
sprintf(ls,"mode = %d(Local)",mode); buf.prnLine(ls);
break;
case External:
sprintf(ls,"mode = %d(External)",mode); buf.prnLine(ls);
break;
case ExternalSaved:
sprintf(ls,"mode = %d(ExternalSaved)",mode); buf.prnLine(ls);
break;
default:
sprintf(ls,"mode = %d",mode); buf.prnLine(ls);
}
sprintf(ls,"numLod = %d",static_cast<int>(lodInfo.size())); buf.prnLine(ls);
for (unsigned int i=0;i<lodInfo.size();i++) {
for (unsigned int i=0;i<lodInfo.size();i++)
{
const LodInfo &li = lodInfo[i];
sprintf(ls,"LOD %d, numX = %d, numY = %d",i,li.numX,li.numY); buf.prnLine(ls);
buf.prnLine("File ID, Offset, Zmin, Zmax");
buf.IncreaseIndent();
for (unsigned int j=0;j<li.addr.size();j++) {
for (unsigned int j=0;j<li.addr.size();j++)
{
sprintf(ls,"%d %d %f %f",li.addr[j].file,li.addr[j].offset,li.elev_min[j],li.elev_max[j]); buf.prnLine(ls);
}
buf.DecreaseIndent();
@ -660,7 +737,8 @@ bool trpgLocalMaterial::Print(trpgPrintBuffer &buf) const
sprintf(ls,"baseMat = %d",baseMat); buf.prnLine(ls);
sprintf(ls,"(sx,sy) -> (ex,ey) = (%d,%d) -> (%d,%d)",sx,sy,ex,ey); buf.prnLine(ls);
sprintf(ls,"dest (width,height) = (%d,%d)",destWidth,destHeight); buf.prnLine(ls);
for (unsigned int i=0;i<addr.size();i++) {
for (unsigned int i=0;i<addr.size();i++)
{
sprintf(ls,"addr (file,offset) = (%d,%d)",addr[i].file,addr[i].offset); buf.prnLine(ls);
}
buf.DecreaseIndent();
@ -670,7 +748,7 @@ bool trpgLocalMaterial::Print(trpgPrintBuffer &buf) const
}
/* Light Attribute Print
*/
*/
bool trpgLightAttr::Print(trpgPrintBuffer &buf) const
{
char ls[1024];
@ -681,84 +759,85 @@ bool trpgLightAttr::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Light Attribute----");
buf.IncreaseIndent();
sprintf(ls,"type = %s",strType[(int)(data.type)]); buf.prnLine(ls);
sprintf(ls,"directionality = %s",strDirect[(int)(data.directionality)]);buf.prnLine(ls);
sprintf(ls,"type = %s",strType[(int)(data.type)]); buf.prnLine(ls);
sprintf(ls,"directionality = %s",strDirect[(int)(data.directionality)]); buf.prnLine(ls);
sprintf(ls,"front color (RGB) = %.2lf, %.2lf, %.2lf",
data.frontColor.red, data.frontColor.green,data.frontColor.blue ); buf.prnLine(ls);
sprintf(ls,"front intensity = %.2lf", data.frontIntensity ); buf.prnLine(ls);
data.frontColor.red, data.frontColor.green,data.frontColor.blue ); buf.prnLine(ls);
sprintf(ls,"front intensity = %.2lf", data.frontIntensity ); buf.prnLine(ls);
sprintf(ls,"back color (RGB) = %.2lf, %.2lf, %.2lf",
data.backColor.red, data.backColor.green,data.backColor.blue ); buf.prnLine(ls);
sprintf(ls,"back intensity = %.2lf", data.backIntensity ); buf.prnLine(ls);
data.backColor.red, data.backColor.green,data.backColor.blue ); buf.prnLine(ls);
sprintf(ls,"back intensity = %.2lf", data.backIntensity ); buf.prnLine(ls);
sprintf(ls,"normal (xyz) = %.2lf,%.2lf,%.2lf",
data.normal.x,data.normal.y,data.normal.z ); buf.prnLine(ls);
sprintf(ls,"smc = %d",data.smc); buf.prnLine(ls);
sprintf(ls,"fid = %d",data.fid); buf.prnLine(ls);
data.normal.x,data.normal.y,data.normal.z ); buf.prnLine(ls);
sprintf(ls,"smc = %d",data.smc); buf.prnLine(ls);
sprintf(ls,"fid = %d",data.fid); buf.prnLine(ls);
sprintf(ls,"visible at DAY = %s",
(data.flags & trpgLightAttr::trpg_Day ? "yes" : "no") ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Day ? "yes" : "no") ); buf.prnLine(ls);
sprintf(ls,"visible at DUSK = %s",
(data.flags & trpgLightAttr::trpg_Dusk ? "yes" : "no") ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Dusk ? "yes" : "no") ); buf.prnLine(ls);
sprintf(ls,"visible at NIGHT = %s",
(data.flags & trpgLightAttr::trpg_Night ? "yes" : "no") ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Night ? "yes" : "no") ); buf.prnLine(ls);
sprintf(ls,"enable directionality = %s",
(data.flags & trpgLightAttr::trpg_Directional ? "yes" : "no" )); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Directional ? "yes" : "no" )); buf.prnLine(ls);
sprintf(ls,"enable back color = %s",
(data.flags & trpgLightAttr::trpg_BackColor ? "yes" : "no" )); buf.prnLine(ls);
sprintf(ls,"horizontal lobe angle = %.2lf",data.horizontalLobeAngle); buf.prnLine(ls);
sprintf(ls,"vertical lobe angle = %.2lf",data.verticalLobeAngle); buf.prnLine(ls);
sprintf(ls,"lobe roll angle = %.2lf",data.lobeRollAngle); buf.prnLine(ls);
sprintf(ls,"lobe falloff = %.2lf",data.lobeFalloff); buf.prnLine(ls);
sprintf(ls,"ambient intensity = %.2lf",data.ambientIntensity); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_BackColor ? "yes" : "no" )); buf.prnLine(ls);
sprintf(ls,"horizontal lobe angle = %.2lf",data.horizontalLobeAngle); buf.prnLine(ls);
sprintf(ls,"vertical lobe angle = %.2lf",data.verticalLobeAngle); buf.prnLine(ls);
sprintf(ls,"lobe roll angle = %.2lf",data.lobeRollAngle); buf.prnLine(ls);
sprintf(ls,"lobe falloff = %.2lf",data.lobeFalloff); buf.prnLine(ls);
sprintf(ls,"ambient intensity = %.2lf",data.ambientIntensity); buf.prnLine(ls);
sprintf(ls,"reflective only = %s",
(data.flags & trpgLightAttr::trpg_Reflective ? "yes" : "no") ); buf.prnLine(ls);
sprintf(ls,"quality = %s", strQuality[(int)(data.quality)]); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Reflective ? "yes" : "no") ); buf.prnLine(ls);
sprintf(ls,"quality = %s", strQuality[(int)(data.quality)]); buf.prnLine(ls);
sprintf(ls,"significance for RASCAL lights = %.2lf",
data.rascalSignificance ); buf.prnLine(ls);
data.rascalSignificance ); buf.prnLine(ls);
sprintf(ls,"calligraphic draw order = %d",
data.calligraphicAttr.drawOrder ); buf.prnLine(ls);
data.calligraphicAttr.drawOrder ); buf.prnLine(ls);
sprintf(ls,"calligraphic lights maximum defocus = %f",
data.calligraphicAttr.maxDefocus ); buf.prnLine(ls);
data.calligraphicAttr.maxDefocus ); buf.prnLine(ls);
sprintf(ls,"calligraphic lights minimum defocus = %f",
data.calligraphicAttr.minDefocus ); buf.prnLine(ls);
data.calligraphicAttr.minDefocus ); buf.prnLine(ls);
sprintf(ls,"randomize intensity = %s",
strQuality[(int)(data.randomIntensity)]); buf.prnLine(ls);
strQuality[(int)(data.randomIntensity)]); buf.prnLine(ls);
sprintf(ls,"performer perspective mode = %s",
(data.flags & trpgLightAttr::trpg_Perspective ? "yes" : "no" ) ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Perspective ? "yes" : "no" ) ); buf.prnLine(ls);
sprintf(ls,"performer fade = %s",
(data.flags & trpgLightAttr::trpg_Fade ? "yes" : "no" ) ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Fade ? "yes" : "no" ) ); buf.prnLine(ls);
sprintf(ls,"performer fog punch = %s",
(data.flags & trpgLightAttr::trpg_FogPunch ? "yes" : "no" ) ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_FogPunch ? "yes" : "no" ) ); buf.prnLine(ls);
sprintf(ls,"performer range mode enable Z buffer = %s",
(data.flags & trpgLightAttr::trpg_ZBuffer ? "yes" : "no" ) ); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_ZBuffer ? "yes" : "no" ) ); buf.prnLine(ls);
sprintf(ls,"performer maximum pixel size = %.2lf",
data.performerAttr.maxPixelSize ); buf.prnLine(ls);
data.performerAttr.maxPixelSize ); buf.prnLine(ls);
sprintf(ls,"performer minimum pixel size = %.2lf",
data.performerAttr.minPixelSize ); buf.prnLine(ls);
data.performerAttr.minPixelSize ); buf.prnLine(ls);
sprintf(ls,"performer actual size = %.2lf",
data.performerAttr.actualSize ); buf.prnLine(ls);
data.performerAttr.actualSize ); buf.prnLine(ls);
sprintf(ls,"performer transparent pixel size = %.2lf",
data.performerAttr.transparentPixelSize ); buf.prnLine(ls);
data.performerAttr.transparentPixelSize ); buf.prnLine(ls);
sprintf(ls,"performer transparent falloff exponent = %.2lf",
data.performerAttr.transparentFallofExp ); buf.prnLine(ls);
data.performerAttr.transparentFallofExp ); buf.prnLine(ls);
sprintf(ls,"performer transparent scale = %.2lf",
data.performerAttr.transparentScale ); buf.prnLine(ls);
data.performerAttr.transparentScale ); buf.prnLine(ls);
sprintf(ls,"performer transparent clamp = %.2lf",
data.performerAttr.transparentClamp ); buf.prnLine(ls);
data.performerAttr.transparentClamp ); buf.prnLine(ls);
sprintf(ls,"performer fog scale = %.2lf",
data.performerAttr.fogScale ); buf.prnLine(ls);
sprintf(ls,"animation period = %.2lf",data.animationAttr.period); buf.prnLine(ls);
data.performerAttr.fogScale ); buf.prnLine(ls);
sprintf(ls,"animation period = %.2lf",data.animationAttr.period); buf.prnLine(ls);
sprintf(ls,"animation phase delay = %.2lf",
data.animationAttr.phaseDelay ); buf.prnLine(ls);
sprintf(ls,"animation time on = %.2lf",data.animationAttr.timeOn); buf.prnLine(ls);
data.animationAttr.phaseDelay ); buf.prnLine(ls);
sprintf(ls,"animation time on = %.2lf",data.animationAttr.timeOn); buf.prnLine(ls);
sprintf(ls,"animation vector (ijk) = %.2lf, %.2lf, %.2lf",
data.animationAttr.vector.x,data.animationAttr.vector.y,
data.animationAttr.vector.z); buf.prnLine(ls);
data.animationAttr.vector.x,data.animationAttr.vector.y,
data.animationAttr.vector.z); buf.prnLine(ls);
sprintf(ls,"animation - flashing = %s",
(data.flags & trpgLightAttr::trpg_Flashing ? "yes" : "no" )); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Flashing ? "yes" : "no" )); buf.prnLine(ls);
sprintf(ls,"animation - rotating = %s",
(data.flags & trpgLightAttr::trpg_Rotating ? "yes" : "no" )); buf.prnLine(ls);
(data.flags & trpgLightAttr::trpg_Rotating ? "yes" : "no" )); buf.prnLine(ls);
sprintf(ls,"animation - counter clockwise = %s",
(data.flags & trpgLightAttr::trpg_ClockWise ? "yes" : "no" )); buf.prnLine(ls);
if (data.commentStr) {
(data.flags & trpgLightAttr::trpg_ClockWise ? "yes" : "no" )); buf.prnLine(ls);
if (data.commentStr)
{
sprintf(ls,"comment = %s",data.commentStr); buf.prnLine(ls);
}
@ -776,19 +855,21 @@ bool trpgLightTable::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Light Table----");
buf.IncreaseIndent();
for (unsigned int i=0;i<lightList.size();i++) {
sprintf(ls,"Light %d",i); buf.prnLine(ls);
lightList[i].Print(buf);
LightMapType::const_iterator itr = lightMap.begin();
for ( ; itr != lightMap.end( ); itr++)
{
sprintf(ls,"Light %d",itr->first); buf.prnLine(ls);
itr->second.Print(buf);
}
buf.DecreaseIndent();
buf.prnLine();
return true;
}
/* Print out a light node
*/
*/
bool trpgLight::Print(trpgPrintBuffer &buf) const
{
@ -797,8 +878,8 @@ bool trpgLight::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Light----");
buf.IncreaseIndent();
sprintf(ls,"Light Index = %d",index); buf.prnLine(ls);
sprintf(ls,"# Light Locations = %d",static_cast<int>(lightPoints.size()) ); buf.prnLine(ls);
sprintf(ls,"Light Index = %d",index); buf.prnLine(ls);
sprintf(ls,"# Light Locations = %d",static_cast<int>(lightPoints.size()) ); buf.prnLine(ls);
buf.DecreaseIndent();
@ -834,9 +915,11 @@ bool trpgRangeTable::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Range Table----");
buf.IncreaseIndent();
for (unsigned int i=0;i<rangeList.size();i++) {
RangeMapType::const_iterator itr = rangeMap.begin();
for (int i = 0; itr != rangeMap.end( ); itr++, i++)
{
sprintf(ls,"----Range %d----",i); buf.prnLine(ls);
rangeList[i].Print(buf);
itr->second.Print(buf);
}
buf.DecreaseIndent();
@ -863,8 +946,9 @@ bool trpgLabel::Print(trpgPrintBuffer &buf) const
sprintf(ls,"location: (%f %f %f)",location.x,location.y,location.z); buf.prnLine(ls);
sprintf(ls,"%d support points",static_cast<int>(supports.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (unsigned int i=0;i<supports.size();i++) {
sprintf(ls,"%f %f %f",supports[i].x,supports[i].y,supports[i].z); buf.prnLine(ls);
for (unsigned int i=0;i<supports.size();i++)
{
sprintf(ls,"%f %f %f",supports[i].x,supports[i].y,supports[i].z); buf.prnLine(ls);
}
buf.DecreaseIndent();
buf.prnLine();
@ -899,11 +983,13 @@ bool trpgTextStyleTable::Print(trpgPrintBuffer &buf) const
buf.prnLine();
buf.prnLine("----Text Style Table----");
buf.IncreaseIndent();
sprintf(ls,"numStyle = %d",static_cast<int>(styles.size())); buf.prnLine(ls);
sprintf(ls,"numStyle = %d",static_cast<int>(styleMap.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (unsigned int i=0;i<styles.size();i++) {
StyleMapType::const_iterator itr = styleMap.begin();
for (int i = 0; itr != styleMap.end( ); itr++, i++)
{
sprintf(ls,"Style %d",i); buf.prnLine(ls);
styles[i].Print(buf);
itr->second.Print(buf);
}
buf.DecreaseIndent();
buf.DecreaseIndent();
@ -935,11 +1021,13 @@ bool trpgSupportStyleTable::Print(trpgPrintBuffer &buf) const
buf.prnLine();
buf.prnLine("----Support Style Table----");
buf.IncreaseIndent();
sprintf(ls,"numStyle = %d",static_cast<int>(styles.size())); buf.prnLine(ls);
sprintf(ls,"numStyle = %d",static_cast<int>(supportStyleMap.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (unsigned int i=0;i<styles.size();i++) {
SupportStyleMapType::const_iterator itr = supportStyleMap.begin();
for (int i = 0; itr != supportStyleMap.end( ); itr++, i++)
{
sprintf(ls,"Style %d",i); buf.prnLine(ls);
styles[i].Print(buf);
itr->second.Print(buf);
}
buf.DecreaseIndent();
buf.DecreaseIndent();
@ -973,11 +1061,13 @@ bool trpgLabelPropertyTable::Print(trpgPrintBuffer &buf) const
buf.prnLine();
buf.prnLine("----Label Property Table----");
buf.IncreaseIndent();
sprintf(ls,"numProperty = %d",static_cast<int>(properties.size())); buf.prnLine(ls);
sprintf(ls,"numProperty = %d",static_cast<int>(labelPropertyMap.size())); buf.prnLine(ls);
buf.IncreaseIndent();
for (unsigned int i=0;i<properties.size();i++) {
LabelPropertyMapType::const_iterator itr = labelPropertyMap.begin();
for (int i = 0; itr != labelPropertyMap.end( ); itr++, i++)
{
sprintf(ls,"Property %d",i); buf.prnLine(ls);
properties[i].Print(buf);
itr->second.Print(buf);
}
buf.DecreaseIndent();
buf.DecreaseIndent();

View File

@ -17,13 +17,16 @@
#define trpage_print_h_
#include <trpage_read.h>
#include <trpage_managers.h>
#include <stack>
/* Print Buffer for TerraPage. Subclasses of this object
are used to print out to stdout or disk (or whatever).
You won't create one of these directly, instead you'll create
something which inherits from it.
are used to print out to stdout or disk (or whatever).
You won't create one of these directly, instead you'll create
something which inherits from it.
*/
TX_EXDECL class TX_CLDECL trpgPrintBuffer {
TX_EXDECL class TX_CLDECL trpgPrintBuffer
{
public:
trpgPrintBuffer(void);
virtual ~trpgPrintBuffer(void) { };
@ -38,17 +41,17 @@ public:
virtual void IncreaseIndent(int amount=1);
// Decreases the current indentation by the amount given (defaults to one)
virtual void DecreaseIndent(int amount=1);
protected:
protected:
void updateIndent(void);
int curIndent;
char indentStr[200];
};
/* File print buffer for TerraPage. The file print buffer writes
debugging output to a file.
*/
debugging output to a file.
*/
TX_EXDECL class TX_CLDECL trpgFilePrintBuffer : public trpgPrintBuffer {
public:
public:
// This class can be constructed with either a FILE pointer or a file name
trpgFilePrintBuffer(FILE *);
trpgFilePrintBuffer(char *);
@ -59,47 +62,83 @@ public:
// For a file printer buffer, this writes a string out to a file
bool prnLine(char *str = NULL);
protected:
protected:
bool valid;
bool isMine;
FILE *fp;
};
/* The Print Graph Parser is a scene graph parser that
prints out the scene graph as it goes. It's simpler
than the scene example in trpage_scene.cpp since it
isn't trying to build up a working scene graph.
*/
TX_EXDECL class TX_CLDECL trpgPrintGraphParser : public trpgSceneParser {
public:
prints out the scene graph as it goes. It's simpler
than the scene example in trpage_scene.cpp since it
isn't trying to build up a working scene graph.
*/
TX_EXDECL class TX_CLDECL trpgPrintGraphParser : public trpgSceneParser
{
public:
trpgPrintGraphParser(trpgr_Archive *,trpgrImageHelper *,trpgPrintBuffer *);
virtual ~trpgPrintGraphParser(void) { };
// Clear all list and free associated pointer
void Reset();
// After parsing this will return the number of trpgChildRef node found.
unsigned int GetNbChildrenRef() const;
// This will return the trpgChildRef node pointer associated with the index.
// Will return 0 if index is out of bound
const trpgChildRef* GetChildRef(unsigned int idx) const;
/* The read helper class is the callback for all the various
token (node) types. Normally we would use a number of
these, probably one per token. However, since we're just
printing we can use a switch statement instead.
*/
class ReadHelper : public trpgr_Callback {
token (node) types. Normally we would use a number of
these, probably one per token. However, since we're just
printing we can use a switch statement instead.
*/
class ReadHelper : public trpgr_Callback
{
public:
ReadHelper(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf) {pBuf = inBuf; parse = inPG;};
void *Parse(trpgToken,trpgReadBuffer &buf);
// typedef std::vector<const trpgChildRef> ChildRefList;
// The const in the template parameter was removed because it causes GCC to
// freak out. I am of the opinion that const doesn't make sense in a template
// parameter for std::vector anyway... const prevents you from changing the
// value, so what exactly is the point? How does one add entries to the vector
// without giving them a value? -ADS
typedef std::vector<trpgChildRef> ChildRefList;
ReadHelper(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf): pBuf(inBuf), parse(inPG) {}
~ReadHelper() { Reset();}
void *Parse(trpgToken,trpgReadBuffer &buf);
void Reset();
// After parsing this will return the number of trpgChildRef node found.
unsigned int GetNbChildrenRef() const;
// This will return the trpgChildRef node associated with the index.
// this will retrun 0 if idx is out of bound
const trpgChildRef* GetChildRef(unsigned int idx) const;
protected:
trpgPrintBuffer *pBuf;
trpgPrintGraphParser *parse;
trpgPrintBuffer *pBuf;
trpgPrintGraphParser *parse;
private:
ChildRefList childRefList;
};
// Fetch the archive associated with this print
trpgr_Archive *GetArchive() {return archive; };
trpgrImageHelper *GetImageHelp() {return imageHelp; };
protected:
protected:
bool StartChildren(void *);
bool EndChildren(void *);
trpgPrintBuffer *printBuf;
trpgr_Archive *archive;
trpgrImageHelper *imageHelp;
ReadHelper *childRefCB;
};
// Print utitility for while archive

View File

@ -14,9 +14,9 @@
*/
/* trpage_range.cpp
Methods for the Range Table. Consult trpg_geom.h for details
on what this is and how it works.
*/
Methods for the Range Table. Consult trpg_geom.h for details
on what this is and how it works.
*/
#include <stdlib.h>
#include <stdio.h>
@ -26,290 +26,328 @@
#include <trpage_read.h>
/* *******************
Range Methods
Range Methods
*******************
*/
trpgRange::trpgRange(void)
{
category = NULL;
subCategory = NULL;
Reset();
category = NULL;
subCategory = NULL;
Reset();
}
trpgRange::~trpgRange(void)
{
Reset();
Reset();
}
trpgRange::trpgRange(const trpgRange &in):
trpgReadWriteable(in)
{
category = NULL;
subCategory = NULL;
*this = in;
category = NULL;
subCategory = NULL;
*this = in;
}
void trpgRange::Reset(void)
{
errMess[0] = '\0';
if (category)
delete [] category;
category = NULL;
if (subCategory)
delete [] subCategory;
subCategory = NULL;
errMess[0] = '\0';
if (category)
delete [] category;
category = NULL;
if (subCategory)
delete [] subCategory;
subCategory = NULL;
inLod = outLod = 0.0;
priority = 0;
inLod = outLod = 0.0;
priority = 0;
handle = -1;
writeHandle = false;
}
void trpgRange::SetCategory(const char *cat,const char *subCat)
{
if (category) delete [] category;
category = NULL;
if (cat) {
category = new char[strlen(cat)+1];
strcpy(category,cat);
}
if (category) delete [] category;
category = NULL;
if (cat) {
category = new char[strlen(cat)+1];
strcpy(category,cat);
}
if (subCategory) delete [] subCategory;
subCategory = NULL;
if (subCat) {
subCategory = new char[strlen(subCat)+1];
strcpy(subCategory,subCat);
}
if (subCategory) delete [] subCategory;
subCategory = NULL;
if (subCat) {
subCategory = new char[strlen(subCat)+1];
strcpy(subCategory,subCat);
}
}
void trpgRange::GetCategory(char *cat,int catLen,char *subCat,int subCatLen) const
{
if (category && cat) {
strncpy(cat,category,catLen);
} else
*cat = 0;
if (subCategory && subCat) {
strncpy(subCat,subCategory,subCatLen);
} else
*subCat = 0;
if (category && cat) {
strncpy(cat,category,catLen);
} else
*cat = 0;
if (subCategory && subCat) {
strncpy(subCat,subCategory,subCatLen);
} else
*subCat = 0;
}
void trpgRange::SetLodInfo(double in,double out)
{
inLod = in;
outLod = out;
inLod = in;
outLod = out;
}
void trpgRange::GetLodInfo(double &in,double &out) const
{
in = inLod;
out = outLod;
in = inLod;
out = outLod;
}
void trpgRange::SetPriority(int prior)
{
priority = prior;
priority = prior;
}
void trpgRange::GetPriority(int &prior) const
{
prior = priority;
prior = priority;
}
trpgRange & trpgRange::operator = (const trpgRange &other)
{
Reset();
inLod = other.inLod;
outLod = other.outLod;
SetCategory(other.category,other.subCategory);
priority = other.priority;
return *this;
Reset();
inLod = other.inLod;
outLod = other.outLod;
SetCategory(other.category,other.subCategory);
priority = other.priority;
handle = other.handle;
writeHandle = other.writeHandle;
return *this;
}
bool trpgRange::operator == (const trpgRange &in) const
{
if (inLod != in.inLod || outLod != in.outLod)
return false;
if (priority != in.priority) return false;
if (inLod != in.inLod || outLod != in.outLod)
return false;
if (priority != in.priority) return false;
if (category && in.category) {
if (strcmp(category,in.category))
return false;
} else {
if (category && !in.category ||
!category && in.category)
return false;
}
if (category && in.category) {
if (strcmp(category,in.category))
return false;
} else {
if (category && !in.category ||
!category && in.category)
return false;
}
if (subCategory && in.subCategory) {
if (strcmp(subCategory,in.subCategory))
return false;
} else {
if (subCategory && !in.subCategory ||
!subCategory && in.subCategory)
return false;
}
return true;
if (subCategory && in.subCategory) {
if (strcmp(subCategory,in.subCategory))
return false;
} else {
if (subCategory && !in.subCategory ||
!subCategory && in.subCategory)
return false;
}
if(handle != in.handle)
return false;
if(writeHandle != in.writeHandle)
return false;
return true;
}
bool trpgRange::Write(trpgWriteBuffer &buf)
{
buf.Begin(TRPG_RANGE);
buf.Add(inLod);
buf.Add(outLod);
buf.Add(priority);
buf.Add((category ? category : ""));
buf.Add((subCategory ? subCategory : ""));
buf.End();
buf.Begin(TRPG_RANGE);
buf.Add(inLod);
buf.Add(outLod);
buf.Add(priority);
buf.Add((category ? category : ""));
buf.Add((subCategory ? subCategory : ""));
if(writeHandle) {
buf.Add((int32)handle);
}
buf.End();
return true;
return true;
}
bool trpgRange::Read(trpgReadBuffer &buf)
{
char catStr[1024],subStr[1024];
char catStr[1024],subStr[1024];
Reset();
valid = false;
Reset();
valid = false;
try {
buf.Get(inLod);
buf.Get(outLod);
buf.Get(priority);
buf.Get(catStr,1024);
buf.Get(subStr,1024);
SetCategory(catStr,subStr);
valid = true;
}
try {
buf.Get(inLod);
buf.Get(outLod);
buf.Get(priority);
buf.Get(catStr,1024);
buf.Get(subStr,1024);
SetCategory(catStr,subStr);
catch (...) {
return false;
}
// Read the handle if we can..
try {
if(!buf.Get((int32 &)handle)) {
handle = -1;
}
}
catch (...) {
handle = -1;
}
valid = true;
}
return isValid();
catch (...) {
return false;
}
return isValid();
}
/* ***************
Range Table methods
***************
Range Table methods
***************
*/
trpgRangeTable::trpgRangeTable(void)
{
valid = true;
valid = true;
}
trpgRangeTable::~trpgRangeTable(void)
{
// vector cleans up itself
// vector cleans up itself
}
void trpgRangeTable::Reset(void)
{
rangeList.resize(0);
valid = true;
rangeMap.clear();
valid = true;
}
bool trpgRangeTable::GetRange(int id,trpgRange &ret) const
{
if (!isValid())
return false;
if (!isValid())
return false;
if (id < 0 || id >= (int)rangeList.size())
return false;
if (id < 0)// || id >= rangeList.size())
return false;
ret = rangeList[id];
return true;
RangeMapType::const_iterator itr = rangeMap.find(id);
if(itr == rangeMap.end()) {
return false;
}
ret = itr->second;
return true;
}
bool trpgRangeTable::SetRange(int id,trpgRange &inRange)
{
if (!isValid())
return false;
if (!isValid())
return false;
if (id < 0 || id >= (int)rangeList.size())
return false;
if (id < 0)// || id >= rangeList.size())
return false;
rangeList[id] = inRange;
rangeMap[id] = inRange;
return true;
return true;
}
int trpgRangeTable::AddRange(trpgRange &range)
{
rangeList.push_back(range);
int handle = range.GetHandle();
if(handle==-1) {
handle = rangeMap.size();
}
rangeMap[handle] = range;
return handle;
return rangeList.size()-1;
}
int trpgRangeTable::FindAddRange(trpgRange &range)
{
for (unsigned int i=0;i<rangeList.size();i++) {
if (range == rangeList[i])
return i;
}
RangeMapType::iterator itr = rangeMap.begin();
for ( ; itr != rangeMap.end( ); itr++) {
if(itr->second==range)
return itr->first;
}
return AddRange(range);
#if 0
for (int i=0;i<rangeList.size();i++) {
if (range == rangeList[i])
return i;
}
#endif
return AddRange(range);
}
bool trpgRangeTable::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGRANGETABLE);
buf.Add((int32)rangeList.size());
buf.Begin(TRPGRANGETABLE);
buf.Add((int32)rangeMap.size());
for (unsigned int i=0;i<rangeList.size();i++) {
trpgRange &range = rangeList[i];
range.Write(buf);
}
RangeMapType::iterator itr = rangeMap.begin();
for ( ; itr != rangeMap.end( ); itr++) {
trpgRange &range = itr->second;
range.Write(buf);
}
buf.End();
buf.End();
return true;
return true;
}
bool trpgRangeTable::Read(trpgReadBuffer &buf)
{
int32 numRange;
trpgToken tok;
int32 len;
valid = false;
int32 numRange;
trpgToken tok;
int32 len;
valid = false;
try {
buf.Get(numRange);
if (numRange < 0) throw 1;
for (int i=0;i<numRange;i++) {
// Read in the individual range
buf.GetToken(tok,len);
if (tok != TRPG_RANGE) throw 1;
buf.PushLimit(len);
trpgRange range;
bool status = range.Read(buf);
buf.PopLimit();
if (!status) throw 1;
rangeList.push_back(range);
}
try {
buf.Get(numRange);
if (numRange < 0) throw 1;
for (int i=0;i<numRange;i++) {
// Read in the individual range
buf.GetToken(tok,len);
if (tok != TRPG_RANGE) throw 1;
buf.PushLimit(len);
trpgRange range;
bool status = range.Read(buf);
buf.PopLimit();
if (!status) throw 1;
AddRange(range);
}
valid = true;
}
valid = true;
}
catch (...) {
return false;
}
catch (...) {
return false;
}
return isValid();
return isValid();
}
trpgRangeTable & trpgRangeTable::operator = (const trpgRangeTable &inTab)
{
Reset();
Reset();
RangeMapType::const_iterator itr = inTab.rangeMap.begin();
for ( ; itr != inTab.rangeMap.end( ); itr++)
rangeMap[itr->first] = itr->second;
for (unsigned int i=0;i<inTab.rangeList.size();i++)
rangeList.push_back(inTab.rangeList[i]);
return *this;
#if 0
for (int i=0;i<inTab.rangeList.size();i++)
rangeList.push_back(inTab.rangeList[i]);
#endif
return *this;
}

View File

@ -18,9 +18,9 @@
#include <string.h>
/* trpage_rarchive.cpp
This source file implements the methods for a trpgr_Archive.
The Read Archive is used to read a paging archive from disk.
*/
This source file implements the methods for a trpgr_Archive.
The Read Archive is used to read a paging archive from disk.
*/
#include <trpage_read.h>
#include <trpage_compat.h>
@ -38,10 +38,15 @@ trpgr_Archive::trpgr_Archive()
trpgr_Archive::~trpgr_Archive()
{
if (fp)
fclose(fp);
fclose(fp);
fp = NULL;
if (tileCache)
delete tileCache;
delete tileCache;
}
int32 trpgr_Archive::GetHeaderData(char *dataPtr, int length, FILE *filehandle)
{
return fread(dataPtr,1,length,filehandle);
}
// Set the directory where the archive is
@ -60,72 +65,169 @@ bool trpgr_Archive::OpenFile(const char *name)
CloseFile();
if (!(fp = fopen(file,"rb")))
return false;
return false;
// Look for a magic # and endianness
int32 magic;
if (fread(&magic,sizeof(int32),1,fp) != 1)
return false;
return false;
headerRead = false;
// Figure out the endianness from the magic number
trpgEndian cpuNess = trpg_cpu_byte_order();
if (magic == TRPG_MAGIC) {
ness = cpuNess;
return true;
if (magic == GetMagicNumber()) {
ness = cpuNess;
return true;
}
if (trpg_byteswap_int(magic) == TRPG_MAGIC) {
if (cpuNess == LittleEndian)
ness = BigEndian;
else
ness = LittleEndian;
return true;
if (trpg_byteswap_int(magic) == GetMagicNumber()) {
if (cpuNess == LittleEndian)
ness = BigEndian;
else
ness = LittleEndian;
return true;
}
if (magic != TRPG_MAGIC)
return false;
if (magic != GetMagicNumber())
return false;
// Not one of our files
return false;
}
// Get new reading app file cache
trpgrAppFileCache* trpgr_Archive::GetNewRAppFileCache(const char *fullBase, const char *ext)
{
return new trpgrAppFileCache(fullBase,ext);
}
trpgrImageHelper* trpgr_Archive::GetNewRImageHelper(trpgEndian ness,char *dir,const trpgMatTable &matTable,const trpgTexTable &texTable)
{
bool separateGeo = false;
int majorVer,minorVer;
GetHeader()->GetVersion(majorVer,minorVer);
if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) {
separateGeo = true;
}
return new trpgrImageHelper(ness,dir,matTable,texTable,separateGeo);
}
// Close File
// Close the currently open file
void trpgr_Archive::CloseFile()
{
if (fp)
fclose(fp);
fclose(fp);
fp = NULL;
if (tileCache)
delete tileCache;
delete tileCache;
tileCache = NULL;
}
/**
* Read a sub block from a 2.2 TXP database. This can be called any time after ReadHeader is called
* if ReadHeader is called with the false parameter to specify not to read all the sub-archives.
* This can make a huge improvement in startup time for loading a very large archive with many blocks.
**/
bool trpgr_Archive::ReadSubArchive(int row, int col, trpgEndian cpuNess)
{
int ret;
trpgHeader blockHeader;
trpgr_Parser bparser;
char blockpath[1024];
//open the block archive
// the block archive will be in the base dir + \\cols\\row\\archive.txp
sprintf(blockpath,"%s%s%d%s%d%sarchive.txp",dir,PATHSEPERATOR,col,PATHSEPERATOR,row,PATHSEPERATOR);
FILE *bfp = fopen(blockpath,"rb");
if(!bfp) {
return false;
}
// Look for a magic # and endianness
int32 bmagic;
if (fread(&bmagic,sizeof(int32),1,bfp) != 1)
return false;
// The block archive will always be the same endianness as the master
if ( (bmagic != GetMagicNumber()) && (trpg_byteswap_int(bmagic) != GetMagicNumber()) )
return false;
int32 bheaderSize=0;
if (fread(&bheaderSize,sizeof(int32),1,bfp) != 1)
return false;
if (ness != cpuNess)
bheaderSize = trpg_byteswap_int(bheaderSize);
int bheadLen = bheaderSize;
if (bheadLen < 0)
return false;
// Read in the header whole
trpgMemReadBuffer bbuf(ness);
bbuf.SetLength(bheadLen);
char *bdata = bbuf.GetDataPtr();
if ((ret = GetHeaderData(bdata,bheadLen,bfp)) != bheadLen)
return false;
//keep track of where this came from in the master table.
tileTable.SetCurrentBlock(row,col,true);
texTable.SetCurrentBlock(row,col);
bparser.AddCallback(TRPGHEADER,&blockHeader);
bparser.AddCallback(TRPGMATTABLE,&materialTable); // Went back to oldest style for 2.0
//if(!headerHasTexTable) {
bparser.AddCallback(TRPGTEXTABLE2,&texTable); // Added for 2.0
//}
bparser.AddCallback(TRPGMODELTABLE,&modelTable);
bparser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0
bparser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0
bparser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1
bparser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable);
bparser.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
bparser.AddCallback(TRPGTILETABLE2,&tileTable);
// Parse the buffer
if (!bparser.Parse(bbuf))
return false;
//close the block archive
fclose(bfp);
tileTable.SetCurrentBlock(-1,-1,false);
return true;
}
bool trpgr_Archive::ReadHeader()
{
return ReadHeader(true);
}
// Read Header
// Run through the rest of the header information
bool trpgr_Archive::ReadHeader()
bool trpgr_Archive::ReadHeader(bool readAllBlocks)
{
int ret;
if (!fp || headerRead)
return false;
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 (fread(&headerSize,sizeof(int32),1,fp) != 1)
return false;
if (ness != cpuNess)
headerSize = trpg_byteswap_int(headerSize);
headerSize = trpg_byteswap_int(headerSize);
int headLen = headerSize;
if (headLen < 0) return false;
if (headLen < 0)
return false;
// Read in the header whole
trpgMemReadBuffer buf(ness);
buf.SetLength(headLen);
char *data = buf.GetDataPtr();
if ((ret = fread(data,1,headLen,fp)) != headLen) return false;
if ((ret = GetHeaderData(data,headLen,fp)) != headLen)
return false;
// Set up a parser
// Catch the tables we need for the archive
@ -136,37 +238,72 @@ bool trpgr_Archive::ReadHeader()
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(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);
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;
return false;
if(header.GetIsMaster())
{
// bool firstBlock = true;
bool headerHasTexTable = false;
//if the master has textures, we want to use them instead of the tables in the
//block archives
int numTex = 0;
texTable.GetNumTextures(numTex);
if(numTex)
headerHasTexTable = true;
// 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;
materialTable = oldMatTable;
if (oldTexTable.isValid())
texTable = oldTexTable;
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[1024];
sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir);
tileCache = new trpgrAppFileCache(fullBase,"tpf");
if (tileCache) delete tileCache;
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir);
tileCache = GetNewRAppFileCache(fullBase,"tpf");
}
valid = true;
@ -176,65 +313,116 @@ bool trpgr_Archive::ReadHeader()
// Read Tile
// Read a tile into a read buffer
// For version 2.1 only tile with lod=0 are stored in the tile table, so an
// error will be returned if you try to use the table with a differrent lod.
bool trpgr_Archive::ReadTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
{
if (!isValid()) return false;
if (!isValid())
return false;
// Reality check the address
int32 numLods;
header.GetNumLods(numLods);
if (lod >= (unsigned int)numLods) return false;
if (static_cast<int>(lod) >= numLods)
return false;
trpg2iPoint lodSize;
header.GetLodSize(lod,lodSize);
if (x >= (unsigned int)lodSize.x || y >= (unsigned int)lodSize.y) return false;
if (static_cast<int>(x) >= lodSize.x || static_cast<int>(y) >= lodSize.y)
return false;
trpgTileTable::TileMode tileMode;
tileTable.GetMode(tileMode);
if (tileMode == trpgTileTable::External) {
// Figure out the file name
// Note: This assumes External tiles
char filename[1024];
sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod);
// Open the file and read the contents
FILE *fp=NULL;
try {
if (!(fp = fopen(filename,"rb"))) throw 1;
// Find the file end
if (fseek(fp,0,SEEK_END)) throw 1;
// Note: This means tile is capped at 2 gigs
long pos = ftell(fp);
if (fseek(fp,0,SEEK_SET)) throw 1;
// Now we know the size. Read the whole file
buf.SetLength(pos);
char *data = buf.GetDataPtr();
if (fread(data,pos,1,fp) != 1) throw 1;
fclose(fp); fp = NULL;
}
catch (...) {
if (fp)
fclose(fp);
return false;
}
bool status = true;
if (tileMode == trpgTileTable::External || tileMode == trpgTileTable::ExternalSaved) {
status = ReadExternalTile(x, y, lod, buf);
} else {
// Local tile. Figure out where it is (which file)
trpgwAppAddress addr;
float zmin,zmax;
if (!tileTable.GetTile(x,y,lod,addr,zmin,zmax))
return false;
// Local tile. Figure out where it is (which file)
int majorVersion, minorVersion;
header.GetVersion(majorVersion, minorVersion);
if(majorVersion == 2 && minorVersion >=1)
{
// Version 2.1
// Tile table contains only lod 0 tiles
if(lod != 0)
status = false;
}
// Fetch the appendable file from the cache
trpgrAppFile *tf = tileCache->GetFile(ness,addr.file);
if (!tf) return false;
if(status)
{
trpgwAppAddress addr;
float zmin,zmax;
status = tileTable.GetTile(x,y,lod,addr,zmin,zmax);
// Fetch the tile
if (!tf->Read(&buf,addr.offset))
return false;
if(status)
status = ReadTile(addr, buf);
}
}
return status;
}
bool trpgr_Archive::ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf)
{
// Figure out the file name
char filename[1024];
int majorVer,minorVer;
header.GetVersion(majorVer,minorVer);
if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer >= TRPG_NOMERGE_VERSION_MINOR)) {
int blockx,blocky;
unsigned int denom = (1 << lod); // this should work up to lod 31
blockx = x/denom;
blocky = y/denom;
sprintf(filename,"%s" PATHSEPERATOR "%d" PATHSEPERATOR "%d" PATHSEPERATOR "tile_%d_%d_%d.tpt",
dir,blockx,blocky,x,y,lod);
}
else {
sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod);
}
// Open the file and read the contents
FILE *fp= 0;
try {
if (!(fp = fopen(filename,"rb"))) {
throw 1;
}
// Find the file end
if (fseek(fp,0,SEEK_END))
throw 1;
// Note: This means tile is capped at 2 gigs
long pos = ftell(fp);
if (fseek(fp,0,SEEK_SET))
throw 1;
// Now we know the size. Read the whole file
buf.SetLength(pos);
char *data = buf.GetDataPtr();
if (fread(data,pos,1,fp) != 1)
throw 1;
fclose(fp);
fp = NULL;
}
catch (...) {
if (fp)
fclose(fp);
return false;
}
return true;
}
bool trpgr_Archive::ReadTile(const trpgwAppAddress& addr, trpgMemReadBuffer &buf)
{
// Fetch the appendable file from the cache
trpgrAppFile *tf = tileCache->GetFile(ness,addr.file,addr.col,addr.row);
if (!tf)
return false;
// Fetch the tile
if (!tf->Read(&buf,addr.offset))
return false;
else
return true;
}
// Get methods
const trpgHeader *trpgr_Archive::GetHeader() const
@ -245,7 +433,7 @@ const trpgMatTable *trpgr_Archive::GetMaterialTable() const
{
return &materialTable;
}
const trpgTexTable *trpgr_Archive::GetTexTable() const
trpgTexTable *trpgr_Archive::GetTexTable()
{
return &texTable;
}
@ -286,13 +474,13 @@ trpgEndian trpgr_Archive::GetEndian() const
bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,trpg3dPoint &ur) const
{
if (!header.isValid())
return false;
return false;
int32 numLod;
header.GetNumLods(numLod);
trpg2iPoint maxXY;
header.GetLodSize(lod,maxXY);
if (x >= (unsigned int)maxXY.x || y>= (unsigned int)maxXY.y)
return false;
if (static_cast<int>(x) >= maxXY.x || static_cast<int>(y)>= maxXY.y)
return false;
trpg3dPoint origin;
header.GetOrigin(origin);
@ -316,13 +504,20 @@ bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,
/* *****************
Read Image Helper
*****************
*/
*/
trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir,
const trpgMatTable &inMatTable,const trpgTexTable &inTexTable)
const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp)
{
Init(inNess,inDir,inMatTable,inTexTable,separateGeoTyp);
}
void trpgrImageHelper::Init(trpgEndian inNess,char *inDir,
const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp)
{
ness = inNess;
strcpy(dir,inDir);
this->separateGeoTyp = separateGeoTyp;
matTable = &inMatTable;
texTable = &inTexTable;
@ -330,13 +525,32 @@ trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir,
// It doesn't do anything until it's called anyway
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPERATOR "texFile",dir);
texCache = new trpgrAppFileCache(fullBase,"txf");
texCache = GetNewRAppFileCache(fullBase,"txf");
if(separateGeoTyp) {
sprintf(fullBase,"%s" PATHSEPERATOR "geotypFile",dir);
geotypCache = GetNewRAppFileCache(fullBase,"txf");
}
else {
geotypCache = texCache;
}
}
trpgrImageHelper::~trpgrImageHelper()
{
if (texCache)
delete texCache;
if (texCache) {
delete texCache;
texCache = NULL;
}
if(separateGeoTyp && geotypCache) {
delete geotypCache;
geotypCache = NULL;
}
}
trpgrAppFileCache* trpgrImageHelper::GetNewRAppFileCache(const char *fullBase,const char* /*ext*/)
{
return new trpgrAppFileCache(fullBase,"txf");
}
bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
@ -345,16 +559,16 @@ bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if (mode != trpgTexture::Local)
return false;
return false;
// Fetch data data
trpgwAppAddress addr;
tex->GetImageAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
trpgrAppFile *af = geotypCache->GetFile(ness,addr.file,addr.col,addr.row);
if (!af)
return false;
return false;
if (!af->Read(data,addr.offset,0,size))
return false;
return false;
return true;
}
@ -362,37 +576,37 @@ bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,char *data,int32 dataSize)
{
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
return false;
// Make sure the texture is Local
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if (mode != trpgTexture::Local)
return false;
return false;
// Fetch data data
trpgwAppAddress addr;
tex->GetImageAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
if (!af)
return false;
return false;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset,level_offset,dataSize))
return false;
return false;
return true;
}
bool trpgrImageHelper::GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
{
return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize);
}
bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
{
// Get the base material for the Local Material
int32 matSubTable,matID;
@ -401,18 +615,23 @@ bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMa
// Eventually, either store multiple base materials for each local material,
// or overhaul this in some other fashion.
int numTables;
if (!matTable->GetNumTable(numTables)) return false;
if (index>=numTables) return false;
if (!matTable->GetNumTable(numTables))
return false;
if (index>=numTables)
return false;
if (index>0) matSubTable=index; // otherwise, leave it alone - could be nonzero
const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID);
if (!mat) return false;
if (!mat)
return false;
// Now get the texture (always the first one)
trpgTextureEnv texEnv;
int32 texID;
if (!mat->GetTexture(0,texID,texEnv)) return false;
if (!mat->GetTexture(0,texID,texEnv))
return false;
const trpgTexture *tex = texTable->GetTextureRef(texID);
if (!tex) return false;
if (!tex)
return false;
totSize = tex->CalcTotalSize();
@ -428,36 +647,38 @@ bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char
bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,int index, char *data,int dataSize)
{
if (!locMat->isValid()) return false;
if (!locMat->isValid())
return false;
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
return false;
// Determine the type
trpgTexture::ImageMode imageMode;
tex->GetImageMode(imageMode);
switch (imageMode) {
case trpgTexture::Template:
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
if (!locMat->GetNthAddr(index,addr)) return false;
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af) return false;
if (!af->Read(data,addr.offset,0,dataSize))
return false;
}
break;
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
if (!locMat->GetNthAddr(index,addr)) return false;
trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
if (!af)
return false;
if (!af->Read(data,addr.offset,0,dataSize))
return false;
}
break;
case trpgTexture::Global:
// Note: Not dealing with Global textures yet
return false;
break;
// Note: Not dealing with Global textures yet
return false;
break;
default:
// This is not a valid Local Material
return false;
// This is not a valid Local Material
return false;
};
return true;
@ -477,35 +698,35 @@ bool trpgrImageHelper::GetNthImageMipLevelForLocalMat(int miplevel, const trpgLo
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
return false;
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
return false;
// Determine the type
trpgTexture::ImageMode imageMode;
tex->GetImageMode(imageMode);
switch (imageMode) {
case trpgTexture::Template:
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
if (!locMat->GetNthAddr(index,addr)) return false;
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af) return false;
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
if (!locMat->GetNthAddr(index,addr)) return false;
trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
if (!af) return false;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset,level_offset,dataSize))
return false;
}
break;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset,level_offset,dataSize))
return false;
}
break;
case trpgTexture::Global:
// Note: Not dealing with Global textures yet
return false;
break;
// Note: Not dealing with Global textures yet
return false;
break;
default:
// This is not a valid Local Material
return false;
// This is not a valid Local Material
return false;
};
return true;
@ -518,8 +739,8 @@ bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pa
tex->GetName(name,nameLen);
nameLen = strlen(name);
if ((int)strlen(dir) + nameLen + 2 > pathLen)
return false;
if (static_cast<int>(strlen(dir)) + nameLen + 2 > pathLen)
return false;
sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);

View File

@ -18,45 +18,48 @@
#define _txpage_read_h_
/* txpage_read.h
Classes used to represent read objects for paging files.
*/
Classes used to represent read objects for paging files.
*/
#include <trpage_sys.h>
#include <trpage_geom.h>
/* Callback base class
Called when a given token is found.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Callback {
public:
Called when a given token is found.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Callback
{
public:
virtual ~trpgr_Callback(void) { };
virtual void *Parse(trpgToken,trpgReadBuffer &) { return (void *)1; };
};
/* Paging Token
Stores callback info associated with a given token.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Token {
public:
Stores callback info associated with a given token.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Token
{
public:
trpgr_Token(void);
trpgr_Token(int,trpgr_Callback *,bool destroy=true);
~trpgr_Token(void);
void init(int,trpgr_Callback *,bool destroy=true);
int Token; // Constant token value
int Token; // Constant token value
trpgr_Callback *cb; // Callback when we hit this token
bool destroy; // Should we call delete on the callback or not
void Destruct(void); // Not quite like delete
};
/* Parse class for paging data structures.
This executes callbacks
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Parser {
public:
This executes callbacks
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Parser
{
public:
trpgr_Parser(void);
virtual ~trpgr_Parser(void);
bool isValid(void) const;
@ -64,68 +67,75 @@ public:
// Add and remove token callbacks
virtual void AddCallback(trpgToken,trpgr_Callback *,bool destroy = true);
virtual void AddCallback(trpgToken,trpgReadWriteable *);
virtual const trpgr_Callback *GetCallback(trpgToken tok) const;
virtual trpgr_Callback *GetCallback(trpgToken tok);
virtual void RemoveCallback(trpgToken);
virtual void SetDefaultCallback(trpgr_Callback *,bool destroy = true);
// Parse a read buffer
virtual bool Parse(trpgReadBuffer &);
virtual bool TokenIsValid(trpgToken); // Check token validity
protected:
protected:
void *lastObject;
private:
private:
// Note: Just how slow is a map<> anyway?
// This usage is self-contained and could be replaced with an array
// This usage is self-contained and could be replaced with an array
#if defined(_WIN32)
typedef std::map<trpgToken,trpgr_Token> tok_map;
#else
typedef std::map<trpgToken,trpgr_Token,std::less<trpgToken> > tok_map;
typedef std::map< trpgToken,trpgr_Token,std::less<trpgToken> > tok_map;
#endif
tok_map tokenMap;
trpgr_Token defCb; // Call this when no others are called
};
/* Image Read Helper.
Used to help read Local and Tile Local textures into
memory (in OpenGL format). You're on your own for External
textures.
If you want to add additional ways to read textures, feel free
to subclass this object.
*/
TX_EXDECL class TX_CLDECL trpgrImageHelper {
public:
trpgrImageHelper(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &);
Used to help read Local and Tile Local textures into
memory (in OpenGL format). You're on your own for External
textures.
If you want to add additional ways to read textures, feel free
to subclass this object.
*/
class trpgwImageHelper;
TX_EXDECL class TX_CLDECL trpgrImageHelper
{
public:
trpgrImageHelper() {;};
trpgrImageHelper(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &,bool separateGeoTyp);
// real construction is here
virtual void Init(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &,bool separateGeoTyp);
virtual ~trpgrImageHelper(void);
/* Fetch the bytes for the given texture.
This is only valid for Local textures.
*/
This is only valid for Local textures.
*/
virtual bool GetLocalGL(const trpgTexture *,char *data,int32 dataSize);
/* Fetch the bytes for the given mip level of a given texture.
This is only valid for Local textures.
*/
This is only valid for Local textures.
*/
virtual bool GetMipLevelLocalGL(int miplevel, const trpgTexture *,char *data,int32 dataSize);
/* Do the lookups to figure out the correct material
and Template (or Local) texture for a given Local Material.
You'll need this for sizes (among other things).
This routine also calculates the total size, including mipmaps if they're there.
*/
and Template (or Local) texture for a given Local Material.
You'll need this for sizes (among other things).
This routine also calculates the total size, including mipmaps if they're there.
*/
virtual bool GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
/* Same as above, but gets info for nth image associated with this local material
*/
virtual bool GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
/* Fetch the bytes for the given Local Material (and
associated texture). This is for Tile Local and
Global textures.
Data is a pre-allocated buffer for the data and
dataSize is the size of that buffer.
*/
associated texture). This is for Tile Local and
Global textures.
Data is a pre-allocated buffer for the data and
dataSize is the size of that buffer.
*/
virtual bool GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize);
/* Same as above, but gets nth image associated with this local material
@ -133,48 +143,68 @@ public:
virtual bool GetNthImageForLocalMat(const trpgLocalMaterial *locMat, int index, char *data,int dataSize);
/* Same as the one above, just fetch single mip levels
*/
*/
virtual bool GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize);
/* Get mip levels for one of multiple images
*/
*/
virtual bool GetNthImageMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat, int index, char *data,int dataSize);
/* Determine the full path of the image in the given
trpgTexture class.
trpgTexture class.
Only useful for External images.
*/
*/
virtual bool GetImagePath(const trpgTexture *,char *,int len);
protected:
virtual trpgrAppFileCache* GetNewRAppFileCache(const char *fullBase,const char *ext);
trpgrAppFileCache *GetGeoTypCache()
{
return geotypCache;
}
void SetTexTable(trpgTexTable *texTable)
{
this->texTable = texTable;
}
protected:
char dir[1024];
trpgEndian ness;
const trpgMatTable *matTable;
const trpgTexTable *texTable;
trpgrAppFileCache *texCache;
trpgrAppFileCache *geotypCache;
bool separateGeoTyp;
};
/* Paging Archive (read version)
This just reads the first bits of the file (and the header)
and lets you parse from there.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable {
public:
This just reads the first bits of the file (and the header)
and lets you parse from there.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable
{
public:
trpgr_Archive(void);
virtual ~trpgr_Archive(void);
virtual void SetDirectory(const char *);
virtual bool OpenFile(const char *); // Open File
virtual bool OpenFile(const char *); // Open File
virtual void CloseFile(void);
virtual bool ReadHeader(void); // Read header (materials, tile table. etc..)
virtual bool ReadHeader(void); // Read header (materials, tile table. etc..)
//overload that lets you specify if you want to read all the blocks now,
//or defer reading them for later.
virtual bool ReadHeader(bool readAllBlocks);
bool ReadSubArchive(int row, int col, trpgEndian cpuNess);
// In version 2.1, only tile at lod 0 are fetchable via the tile table
virtual bool ReadTile(uint32 x, uint32 y, uint32 lod,trpgMemReadBuffer &);
virtual bool ReadTile(const trpgwAppAddress& addr, trpgMemReadBuffer &buf);
virtual bool ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf);
// Get access to header info
virtual const trpgHeader *GetHeader(void) const;
virtual const trpgMatTable *GetMaterialTable(void) const;
virtual const trpgTexTable *GetTexTable(void) const;
virtual trpgTexTable *GetTexTable(void) ;
virtual const trpgModelTable *GetModelTable(void) const;
virtual const trpgTileTable *GetTileTable(void) const;
virtual const trpgLightTable *GetLightTable(void) const;
@ -185,11 +215,15 @@ public:
// Utility routine to calculate the MBR of a given tile
virtual bool trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,
trpg3dPoint &ll,trpg3dPoint &ur) const;
trpg3dPoint &ll,trpg3dPoint &ur) const;
trpgEndian GetEndian(void) const;
char* getDir(void){return dir;};
protected:
virtual trpgrImageHelper* GetNewRImageHelper(trpgEndian ness,char *dir,const trpgMatTable &matTable,const trpgTexTable &texTable);
virtual trpgrAppFileCache* GetNewRAppFileCache(const char *fullBase, const char *ext);
virtual int32 GetHeaderData(char *dataPtr,int32 length,FILE *filehandle);
virtual int32 GetMagicNumber() {return TRPG_MAGIC;};
protected:
bool headerRead;
trpgEndian ness;
FILE *fp;
@ -214,19 +248,20 @@ class trpgSceneHelperPush;
class trpgSceneHelperPop;
class trpgSceneHelperDefault;
/* Scene Parser
This class assists in parsing a scene graph structure (tiles and models).
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
parser.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser {
This class assists in parsing a scene graph structure (tiles and models).
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
parser.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser
{
friend class trpgSceneHelperPush;
friend class trpgSceneHelperPop;
friend class trpgSceneHelperDefault;
public:
public:
trpgSceneParser(void);
virtual ~trpgSceneParser(void);
protected:
protected:
// Start defining children for the given object
virtual bool StartChildren(void *) { return true;};
virtual bool EndChildren(void *) { return true;};

View File

@ -18,15 +18,15 @@
#include <math.h>
/* trpage_readbuf.cpp
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
#include <trpage_io.h>
#include <trpage_swap.h>
@ -43,9 +43,9 @@ bool trpgReadBuffer::Get(int32 &ret)
if (!GetData((char *)&val,sizeof(int32))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_int(val);
ret = trpg_byteswap_int(val);
else
ret = val;
ret = val;
return true;
}
@ -54,10 +54,11 @@ bool trpgReadBuffer::Get(int64 &ret)
int64 val;
if (!GetData((char *)&val,sizeof(int64))) return false;
// trpg_byteswap_llong is defined to be 64 bit
if (ness != cpuNess)
ret = trpg_byteswap_llong(val);
ret = trpg_byteswap_llong(val);
else
ret = val;
ret = val;
return true;
}
@ -74,7 +75,7 @@ bool trpgReadBuffer::Get(char *ret,int retLen)
ret[rlen] = 0;
// Skip the rest
if (!Skip(rlen-len)) return false;
if (!Skip(len-rlen)) return false;
return true;
}
@ -86,7 +87,7 @@ bool trpgReadBuffer::Get(std::string &str)
if (!Get(len)) return false;
if (len < 0)
return false;
return false;
// Note: Should fix this
char *tmpStr = new char[len+1];
@ -104,10 +105,10 @@ bool trpgReadBuffer::Get(float32 &ret)
if (!GetData(cval,sizeof(float32))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,4);
else
ret = trpg_byteswap_4bytes_to_float(cval);
if (ness == cpuNess)
memcpy(&ret,cval,4);
else
ret = trpg_byteswap_4bytes_to_float(cval);
}
catch (...) {
}
@ -120,10 +121,10 @@ bool trpgReadBuffer::Get(float64 &ret)
if (!GetData(cval,sizeof(float64))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,8);
else
ret = trpg_byteswap_8bytes_to_double(cval);
if (ness == cpuNess)
memcpy(&ret,cval,8);
else
ret = trpg_byteswap_8bytes_to_double(cval);
}
catch (...) {
}
@ -161,9 +162,9 @@ bool trpgReadBuffer::Get(trpgDiskRef &ret)
if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false;
if (ness == cpuNess)
ret = val;
ret = val;
else
ret = trpg_byteswap_llong(val);
ret = trpg_byteswap_llong(val);
return true;
}
@ -175,9 +176,9 @@ bool trpgReadBuffer::Get(trpgToken &ret)
if (!GetData((char *)&val,sizeof(trpgToken))) return false;
if (ness == cpuNess)
ret = val;
ret = val;
else
ret = trpg_byteswap_short(val);
ret = trpg_byteswap_short(val);
return true;
}
@ -186,13 +187,13 @@ bool trpgReadBuffer::Get(trpgToken &ret)
bool trpgReadBuffer::GetArray(int len,float32 **arr)
{
if (!GetDataRef((char **)arr,sizeof(float32)*len))
return false;
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
@ -200,39 +201,39 @@ bool trpgReadBuffer::GetArray(int len,float32 **arr)
bool trpgReadBuffer::GetArray(int len,float64 **arr)
{
if (!GetDataRef((char **)arr,sizeof(float64)*len))
return false;
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_eight(ptr,ptr);
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_eight(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,int32 **arr)
{
if (!GetDataRef((char **)arr,sizeof(int32)*len))
return false;
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,trpgColor **arr)
{
if (!GetDataRef((char **)arr,sizeof(trpgColor)*len))
return false;
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_four(ptr,ptr);
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_four(ptr,ptr);
}
return true;
}
@ -245,25 +246,25 @@ bool trpgReadBuffer::GetArray(int len,char **arr)
bool trpgReadBuffer::Get(trpg2iPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y))
return false;
return false;
return true;
}
bool trpgReadBuffer::Get(trpg2dPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y))
return false;
return false;
return true;
}
bool trpgReadBuffer::Get(trpg3dPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y) || !Get(pt.z))
return false;
return false;
return true;
}
bool trpgReadBuffer::Get(trpgColor &color)
{
if (!Get(color.red) || !Get(color.green) || !Get(color.blue))
return false;
return false;
return true;
}
@ -271,16 +272,16 @@ bool trpgReadBuffer::Get(trpgColor &color)
bool trpgReadBuffer::GetToken(trpgToken &tok,int32 &len)
{
if (!Get(tok) || !Get(len))
return false;
return false;
return true;
}
/* Limit Handling functions
These impose arbitrary lenght limits on the read buffer.
This keeps us from reading pased a token group and parsing
random data within an archive.
*/
These impose arbitrary lenght limits on the read buffer.
This keeps us from reading pased a token group and parsing
random data within an archive.
*/
// Push Limit
// Add another limit to the top of the stack
void trpgReadBuffer::PushLimit(int limit)
@ -295,7 +296,7 @@ void trpgReadBuffer::PopLimit()
int len = limits.size();
if (len > 0)
limits.resize(len-1);
limits.resize(len-1);
}
// Skip To Limit
@ -306,10 +307,10 @@ bool trpgReadBuffer::SkipToLimit()
int len=0;
if (limits.size() != 0)
len = limits[limits.size()-1];
len = limits[limits.size()-1];
if (len > 0)
return Skip(len);
return Skip(len);
return true;
}
@ -319,8 +320,8 @@ bool trpgReadBuffer::SkipToLimit()
bool trpgReadBuffer::TestLimit(int len)
{
for (unsigned int i=0;i<limits.size();i++)
if (len > limits[i])
return false;
if (len > limits[i])
return false;
return true;
}
@ -330,7 +331,7 @@ bool trpgReadBuffer::TestLimit(int len)
void trpgReadBuffer::UpdateLimits(int len)
{
for (unsigned int i=0;i<limits.size();i++)
limits[i] -= len;
limits[i] -= len;
}
/* *************************
@ -347,7 +348,7 @@ trpgMemReadBuffer::trpgMemReadBuffer(trpgEndian in_ness)
trpgMemReadBuffer::~trpgMemReadBuffer()
{
if (data)
delete [] data;
delete [] data;
}
// Empty check
@ -356,11 +357,11 @@ bool trpgMemReadBuffer::isEmpty()
if (!data) return true;
if (pos >= len)
return true;
return true;
// Also test the limits
for (unsigned int i=0;i<limits.size();i++)
if (limits[i] == 0) return true;
if (limits[i] == 0) return true;
return false;
}
@ -370,10 +371,10 @@ bool trpgMemReadBuffer::isEmpty()
void trpgMemReadBuffer::SetLength(int newLen)
{
if (newLen > totLen) {
if (data)
delete [] data;
data = new char[newLen];
totLen = newLen;
if (data)
delete [] data;
data = new char[newLen];
totLen = newLen;
}
len = newLen;
pos = 0;
@ -391,7 +392,7 @@ char *trpgMemReadBuffer::GetDataPtr()
bool trpgMemReadBuffer::GetData(char *ret,int rlen)
{
if (rlen < 0)
return false;
return false;
// Test against limits imposed from without
if (!TestLimit(rlen)) throw 1;
@ -433,8 +434,11 @@ bool trpgMemReadBuffer::GetDataRef(char **ret,int rlen)
// Same as read except we're not, uh, reading
bool trpgMemReadBuffer::Skip(int rlen)
{
if (rlen == 0)
return true;
if (rlen < 0)
return false;
return false;
// Test against limits
if (!TestLimit(rlen)) return false;
@ -451,13 +455,18 @@ bool trpgMemReadBuffer::Skip(int rlen)
*/
trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName)
{
Init(inNess,fileName);
}
void trpgrAppFile::Init(trpgEndian inNess,const char *fileName)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
if (!(fp = fopen(fileName,"rb")))
return;
return;
valid = true;
}
@ -465,11 +474,16 @@ trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName)
trpgrAppFile::~trpgrAppFile()
{
if (fp)
fclose(fp);
fclose(fp);
valid = false;
}
bool trpgrAppFile::isValid(void) const
{
return valid;
}
// Read a section of data from the given file
// and dump it into the given buffer
bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset)
@ -478,44 +492,44 @@ bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset)
// Seek to the right location
if (fseek(fp,offset,SEEK_SET))
return false;
return false;
// Read a length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
valid = false;
return false;
}
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
len = trpg_byteswap_int(len);
if (len < 0) {
valid = false;
return false;
valid = false;
return false;
}
buf->SetLength(len);
char *data = buf->GetDataPtr();
if (!data) {
valid = false;
return false;
valid = false;
return false;
}
if (fread(data,sizeof(char),len,fp) != (unsigned int)len) {
valid = false;
return false;
if (fread(data,sizeof(char),len,fp) != (uint32)len) {
valid = false;
return false;
}
return true;
}
/* Read a section of data from the given file
and dump it into the given memory. Sanity
check the length against the size of the memory
passed into dataSize.
*/
and dump it into the given memory. Sanity
check the length against the size of the memory
passed into dataSize.
*/
bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSize)
{
if (!valid) return false;
@ -523,53 +537,58 @@ bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSi
// Seek to the right place
int result;
if ((result = fseek(fp,baseOffset,SEEK_SET))) {
valid = false;
return false;
valid = false;
return false;
}
// Read the total object length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
valid = false;
return false;
}
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
len = trpg_byteswap_int(len);
if (len < 0) {
valid = false;
return false;
valid = false;
return false;
}
// It's all right to read less than the whole data block
if (objOffset+dataSize > len)
return false;
return false;
// Skip to the object offset
if (fseek(fp,objOffset,SEEK_CUR)) {
valid = false;
return false;
valid = false;
return false;
}
// Read the raw data
// Note: What about byte swapping?
if (fread(data,sizeof(char),dataSize,fp) != (unsigned int)dataSize) {
valid = false;
return false;
if (fread(data,sizeof(char),dataSize,fp) != (uint32)dataSize) {
valid = false;
return false;
}
return true;
}
/* App File Cache
This class manages a group of appendable files with
the same base name and extension. It will keep a certain
number of them open to facilitate caching.
*/
This class manages a group of appendable files with
the same base name and extension. It will keep a certain
number of them open to facilitate caching.
*/
trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noFiles)
{
Init(inPre,inExt,noFiles);
}
void trpgrAppFileCache::Init(const char *inPre,const char *inExt,int noFiles)
{
strcpy(baseName,inPre);
strcpy(ext,inExt);
@ -580,56 +599,101 @@ trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noF
trpgrAppFileCache::~trpgrAppFileCache()
{
for (unsigned int i=0;i<files.size();i++) {
if (files[i].afile) {
delete files[i].afile;
files[i].afile = NULL;
}
unsigned int len = files.size();
for (unsigned int i=0;i<len;i++) {
if (files[i].afile) {
delete files[i].afile;
files[i].afile = NULL;
}
}
}
trpgrAppFile *trpgrAppFileCache::GetNewRAppFile(trpgEndian ness, const char *fileName)
{
return new trpgrAppFile(ness,fileName);
}
trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id)
{
return GetFile(ness,id,-1,-1);
}
/*
*/
trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id)
trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id,int col,int row)
{
// Look for it already here
int foundID = -1;
unsigned int i;
for (i=0;i<files.size();i++) {
if (files[i].id == id) {
foundID = i;
break;
}
if ((files[i].id == id)&&
(files[i].col == col) &&
(files[i].row == row)) {
foundID = i;
break;
}
}
// Found it in cache, just return
if (foundID != -1) {
OpenFile &of = files[foundID];
of.lastUsed = timeCount;
return of.afile;
OpenFile &of = files[foundID];
if (of.afile->isValid())
{
of.lastUsed = timeCount;
return of.afile;
}
else
{
if (of.afile)
delete of.afile;
of.afile = NULL;
}
}
// Didn't find it. Need to reclaim one
// Look for the oldest used
int oldTime=-1,oldID=-1;
for (i=0;i<files.size();i++) {
OpenFile &of = files[i];
if (!of.afile || (oldTime == -1) || (of.lastUsed < oldTime)) {
oldID = i;
oldTime = of.lastUsed;
if (!of.afile)
break;
}
OpenFile &of = files[i];
if (!of.afile || (oldTime == -1) || (of.lastUsed < oldTime)) {
oldID = i;
oldTime = of.lastUsed;
if (!of.afile)
break;
}
}
// Reclaim this one
OpenFile &of = files[oldID];
if (of.afile) delete of.afile;
if (of.afile)
delete of.afile;
char fileName[1024];
sprintf(fileName,"%s_%d.%s",baseName,id,ext);
of.afile = new trpgrAppFile(ness,fileName);
if(col==-1) {
sprintf(fileName,"%s_%d.%s",baseName,id,ext);
}
else {
char dir[1024];
char filebase[1024];
//this is very ugly, but it avoids radical API changes
// find the last PATHSEPERATOR in the baseName string
int len = strlen(baseName);
while(--len > 0) {
if(baseName[len]==PATHSEPERATOR[0]) {
strcpy(filebase,&baseName[len+1]);
strcpy(dir,baseName);
dir[len]='\0';
break;
}
}
sprintf(fileName,"%s" PATHSEPERATOR "%d" PATHSEPERATOR "%d" PATHSEPERATOR "%s_%d.%s",
dir,col,row,filebase,id,ext);
}
of.afile = GetNewRAppFile(ness,fileName);
of.id = id;
of.row = row;
of.col = col;
of.lastUsed = timeCount;
timeCount++;

View File

@ -19,448 +19,473 @@
#include <string.h>
/* trpage_scene.cpp
This file implements a bunch of stuff, all of it optional. See trpage_scene.h
for more information.
Scene Graph nodes -
All the methods for the simple scene graph are here.
trpgSceneGraphParser -
This is a subclass of trpgSceneParser. It uses that utility class to keep track
of pushes and pops. It also registers an interest in all the node types it
knows about (Geometry,Group,LOD,ModelRef). When one of those is encountered
by the trpgr_Parser (which it's also a subclass of) it reads it into the
appropriate trpgRead* type.
Unless you're reading into the scene graph defined in trpage_scene.h, you won't
use this class directly. Instead, copy it and use it as a template for how
to read into a scene graph. You'll need to replace the helpers, primarily.
*/
This file implements a bunch of stuff, all of it optional. See trpage_scene.h
for more information.
Scene Graph nodes -
All the methods for the simple scene graph are here.
trpgSceneGraphParser -
This is a subclass of trpgSceneParser. It uses that utility class to keep track
of pushes and pops. It also registers an interest in all the node types it
knows about (Geometry,Group,LOD,ModelRef). When one of those is encountered
by the trpgr_Parser (which it's also a subclass of) it reads it into the
appropriate trpgRead* type.
Unless you're reading into the scene graph defined in trpage_scene.h, you won't
use this class directly. Instead, copy it and use it as a template for how
to read into a scene graph. You'll need to replace the helpers, primarily.
*/
#include <trpage_read.h>
#include <trpage_scene.h>
/* ****************
MBR Calculation and handling
****************
*/
MBR Calculation and handling
****************
*/
trpgMBR::trpgMBR()
{
valid = false;
valid = false;
}
bool trpgMBR::isValid() const
{
return valid;
return valid;
}
void trpgMBR::Reset()
{
valid = false;
valid = false;
}
trpg3dPoint trpgMBR::GetLL() const
{
return ll;
return ll;
}
trpg3dPoint trpgMBR::GetUR() const
{
return ur;
return ur;
}
void trpgMBR::AddPoint(const trpg3dPoint &pt)
{
if (valid) {
ll.x = MIN(pt.x,ll.x);
ll.y = MIN(pt.y,ll.y);
ll.z = MIN(pt.z,ll.z);
ur.x = MAX(pt.x,ur.x);
ur.y = MAX(pt.y,ur.y);
ur.z = MAX(pt.z,ur.z);
} else {
valid = true;
ll = ur = pt;
}
if (valid) {
ll.x = MIN(pt.x,ll.x);
ll.y = MIN(pt.y,ll.y);
ll.z = MIN(pt.z,ll.z);
ur.x = MAX(pt.x,ur.x);
ur.y = MAX(pt.y,ur.y);
ur.z = MAX(pt.z,ur.z);
} else {
valid = true;
ll = ur = pt;
}
}
void trpgMBR::AddPoint(double x,double y,double z)
{
AddPoint(trpg3dPoint(x,y,z));
AddPoint(trpg3dPoint(x,y,z));
}
void trpgMBR::GetMBR(trpg3dPoint &oll,trpg3dPoint &our) const
{
oll = ll;
our = ur;
oll = ll;
our = ur;
}
// Add the input MBR to this one
void trpgMBR::Union(const trpgMBR &in)
{
if (valid) {
if (in.isValid()) {
AddPoint(in.GetLL());
AddPoint(in.GetUR());
}
} else {
valid = true;
*this = in;
}
if (valid) {
if (in.isValid()) {
AddPoint(in.GetLL());
AddPoint(in.GetUR());
}
} else {
valid = true;
*this = in;
}
}
// See if there's any overlap between the two MBRs
bool trpgMBR::Overlap(const trpg2dPoint &ill, const trpg2dPoint &iur) const
{
if (!isValid()) return false;
if (!isValid()) return false;
trpg2dPoint ilr = trpg2dPoint(iur.x,ill.y);
trpg2dPoint iul = trpg2dPoint(ill.x,iur.y);
trpg2dPoint ilr = trpg2dPoint(iur.x,ill.y);
trpg2dPoint iul = trpg2dPoint(ill.x,iur.y);
// B MBR falls within A
if (Within(ill) || Within(iur) || Within(ilr) || Within(iul))
return true;
// B MBR falls within A
if (Within(ill) || Within(iur) || Within(ilr) || Within(iul))
return true;
// A MBR falls within B
if ((inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ll.y)) ||
(inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ll.y)) ||
(inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ur.y)) ||
(inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ur.y)))
return true;
// A MBR falls within B
if ((inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ll.y)) ||
(inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ll.y)) ||
(inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ur.y)) ||
(inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ur.y)))
return true;
if ((inRange(ll.x,ur.x,ill.x) && ill.y < ll.y && iur.y > ur.y) ||
(inRange(ll.y,ur.y,ill.y) && ill.x < ll.x && iur.x > ur.x))
return true;
if ((inRange(ll.x,ur.x,ill.x) && ill.y < ll.y && iur.y > ur.y) ||
(inRange(ll.y,ur.y,ill.y) && ill.x < ll.x && iur.x > ur.x))
return true;
return false;
return false;
}
// Check if a given 2d point is within the MBR
bool trpgMBR::Within(const trpg2dPoint &pt) const
{
if (inRange(ll.x,ur.x,pt.x) && inRange(ll.y,ur.y,pt.y))
return true;
return false;
if (inRange(ll.x,ur.x,pt.x) && inRange(ll.y,ur.y,pt.y))
return true;
return false;
}
/* ****************
Read Group Base
Base class for all group structures.
****************
*/
/* ****************
Read Group Base
Base class for all group structures.
****************
*/
// Destructor
trpgReadGroupBase::~trpgReadGroupBase()
{
DeleteChildren();
DeleteChildren();
}
// Delete all children
void trpgReadGroupBase::DeleteChildren()
{
for (unsigned int i=0;i<children.size();i++)
if (children[i])
delete children[i];
for (unsigned int i=0;i<children.size();i++)
if (children[i])
delete children[i];
}
// Add a child to the list
void trpgReadGroupBase::AddChild(trpgReadNode *n)
{
children.push_back(n);
children.push_back(n);
}
// Unref a child (but don't delete it)
void trpgReadGroupBase::unRefChild(int id)
{
if (id < 0 || id >= (int)children.size())
return;
children[id] = NULL;
if (id < 0 || id >= (int)children.size())
return;
children[id] = NULL;
}
// Unref all the children (they've probably been moved elsewhere)
void trpgReadGroupBase::unRefChildren()
{
for (unsigned int i=0;i<children.size();i++)
unRefChild(i);
for (unsigned int i=0;i<children.size();i++)
unRefChild(i);
}
// Calculate an MBR
trpgMBR trpgReadGroupBase::GetMBR() const
{
if (mbr.isValid())
return mbr;
else {
// Calculate and cache a new MBR
trpgMBR *cmbr = const_cast<trpgMBR *>(&mbr);
trpgMBR kmbr;
// Ask the kids
for (unsigned int i=0;i<children.size();i++) {
kmbr = children[i]->GetMBR();
cmbr->Union(kmbr);
}
return *cmbr;
}
if (mbr.isValid())
return mbr;
else {
// Calculate and cache a new MBR
trpgMBR *cmbr = const_cast<trpgMBR *>(&mbr);
trpgMBR kmbr;
// Ask the kids
for (unsigned int i=0;i<children.size();i++) {
kmbr = children[i]->GetMBR();
cmbr->Union(kmbr);
}
return *cmbr;
}
}
/* ****************
Read Geometry
****************
*/
Read Geometry
****************
*/
// Calculate an MBR
trpgMBR trpgReadGeometry::GetMBR() const
{
if (mbr.isValid())
return mbr;
if (mbr.isValid())
return mbr;
trpgMBR *pmbr = const_cast<trpgMBR *>(&mbr);
trpgMBR *pmbr = const_cast<trpgMBR *>(&mbr);
int numVert,i;
trpg3dPoint pt;
data.GetNumVertex(numVert);
numVert /= 3;
for (i=0;i<numVert;i++) {
data.GetVertex(i,pt);
pmbr->AddPoint(pt);
}
int numVert,i;
trpg3dPoint pt;
data.GetNumVertex(numVert);
numVert /= 3;
for (i=0;i<numVert;i++) {
data.GetVertex(i,pt);
pmbr->AddPoint(pt);
}
return mbr;
return mbr;
}
/* ****************
Scene Graph Parser
****************
*/
/* ****************
Scene Graph Parser
****************
*/
/* Scene Graph Parser Helpers
Each of these classes reads a certain kind of data (e.g. a group)
and creates the appropriate trpgrRead* form and returns that.
*/
Each of these classes reads a certain kind of data (e.g. a group)
and creates the appropriate trpgrRead* form and returns that.
*/
/* This is a helper registered by trpgSceneGraphParser that readers trpgGeometry
nodes and adds them to the current scene graph. trpgGeometry nodes are
always leaves so there should be no pushes after this node. The Parse method
also adds the new node as a child to any existing (e.g. top) group.
{group:Demonstration Scene Graph}
nodes and adds them to the current scene graph. trpgGeometry nodes are
always leaves so there should be no pushes after this node. The Parse method
also adds the new node as a child to any existing (e.g. top) group.
{group:Demonstration Scene Graph}
*/
class trpgReadGeometryHelper : public trpgr_Callback {
public:
trpgReadGeometryHelper(trpgSceneGraphParser *in_parse) { parse = in_parse;}
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadGeometry *geom = new trpgReadGeometry();
trpgGeometry *data = geom->GetData();
if (!data->Read(buf)) {
delete geom;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(geom);
else
delete geom;
trpgReadGeometryHelper(trpgSceneGraphParser *in_parse) { parse = in_parse;}
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadGeometry *geom = new trpgReadGeometry();
trpgGeometry *data = geom->GetData();
if (!data->Read(buf)) {
delete geom;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(geom);
else
delete geom;
return geom;
}
return geom;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
/* This helper is registered by trpgSceneGraphParser. It reads a trpgGroup
from the trpgReadBuffer. It then adds it to our current scene graph.
It also adds an index corresponding to the group's group ID in our group
mapping in trpgSceneGraphParser. The new group becomes the top one
after returning from the Parse call.
{group:Demonstration Scene Graph}
from the trpgReadBuffer. It then adds it to our current scene graph.
It also adds an index corresponding to the group's group ID in our group
mapping in trpgSceneGraphParser. The new group becomes the top one
after returning from the Parse call.
{group:Demonstration Scene Graph}
*/
class trpgReadGroupHelper : public trpgr_Callback {
public:
trpgReadGroupHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadGroup *group = new trpgReadGroup();
trpgGroup *data = group->GetData();
if (!data->Read(buf)) {
delete group;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(group);
else
delete group;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = group;
return group;
}
trpgReadGroupHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadGroup *group = new trpgReadGroup();
trpgGroup *data = group->GetData();
if (!data->Read(buf)) {
delete group;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(group);
else
delete group;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = group;
return group;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
class trpgReadBillboardHelper : public trpgr_Callback {
public:
trpgReadBillboardHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadBillboard *group = new trpgReadBillboard();
trpgBillboard *data = group->GetData();
if (!data->Read(buf)) {
delete group;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(group);
else
delete group;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = group;
return group;
}
trpgReadBillboardHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadBillboard *group = new trpgReadBillboard();
trpgBillboard *data = group->GetData();
if (!data->Read(buf)) {
delete group;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(group);
else
delete group;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = group;
return group;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
class trpgReadAttachHelper : public trpgr_Callback {
public:
trpgReadAttachHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadAttach *attach = new trpgReadAttach();
trpgAttach *data = attach->GetData();
if (!data->Read(buf)) {
delete attach;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(attach);
else
delete attach;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = attach;
return attach;
}
trpgReadAttachHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadAttach *attach = new trpgReadAttach();
trpgAttach *data = attach->GetData();
if (!data->Read(buf)) {
delete attach;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(attach);
else
delete attach;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = attach;
return attach;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
class trpgReadChildRefHelper : public trpgr_Callback {
public:
trpgReadChildRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadChildRef *childRef = new trpgReadChildRef();
trpgChildRef *data = childRef->GetData();
if (!data->Read(buf)) {
delete childRef;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
// NOTE: this is bad, we delete the pointer then we save it.
// this is done everywhere and should be corrected
if (top)
top->AddChild(childRef);
else
delete childRef;
return childRef;
}
protected:
trpgSceneGraphParser *parse;
};
class trpgReadLodHelper : public trpgr_Callback {
public:
trpgReadLodHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadLod *lod = new trpgReadLod();
trpgLod *data = lod->GetData();
if (!data->Read(buf)) {
delete lod;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(lod);
else
delete lod;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = lod;
return lod;
}
trpgReadLodHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadLod *lod = new trpgReadLod();
trpgLod *data = lod->GetData();
if (!data->Read(buf)) {
delete lod;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(lod);
else
delete lod;
// Add to the group map
int id;
data->GetID(id);
trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
(*gmap)[id] = lod;
return lod;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
class trpgReadModelRefHelper : public trpgr_Callback {
public:
trpgReadModelRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadModelRef *mod = new trpgReadModelRef();
trpgModelRef *data = mod->GetData();
if (!data->Read(buf)) {
delete mod;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(mod);
else
delete mod;
return mod;
}
trpgReadModelRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadModelRef *mod = new trpgReadModelRef();
trpgModelRef *data = mod->GetData();
if (!data->Read(buf)) {
delete mod;
return NULL;
}
trpgReadGroupBase *top = parse->GetCurrTop();
if (top)
top->AddChild(mod);
else
delete mod;
return mod;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
class trpgReadTileHeaderHelper : public trpgr_Callback {
public:
trpgReadTileHeaderHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadTileHeader *th = parse->GetTileHeaderRef();
trpgTileHeader *data = th->GetData();
if (!data->Read(buf))
return NULL;
return th;
}
trpgReadTileHeaderHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
trpgReadTileHeader *th = parse->GetTileHeaderRef();
trpgTileHeader *data = th->GetData();
if (!data->Read(buf))
return NULL;
return th;
}
protected:
trpgSceneGraphParser *parse;
trpgSceneGraphParser *parse;
};
/* The Scene Graph Parser constructor does two things. First, it sets
up any internal variables like a normal constructor. Then it registers
an interest in all the node types it knows how to parse. It does this
by calling AddCallback, which is a method of its parent. It passes in
a token representing the node type (see trpg_io.h) and an object that
is capable of parsing the given type.
up any internal variables like a normal constructor. Then it registers
an interest in all the node types it knows how to parse. It does this
by calling AddCallback, which is a method of its parent. It passes in
a token representing the node type (see trpg_io.h) and an object that
is capable of parsing the given type.
The objects we pass in here are called helpers. They parse specific
objects and add them to the user defined scene graph. Examples include
trpgReadGeometryHelper, trpgReadGroupHelper, trpgReadAttachHelper,
trpgReadBillboardHelper, trpgReadLodHelper, trpgReadModelRefHelper,
trpgReadTileHeaderHelper. These are all derived from trpgr_Callback.
You should not use any of these yourself. Instead look at these classes
as examples of how to implement your own subclass of trpgSceneParser.
*/
The objects we pass in here are called helpers. They parse specific
objects and add them to the user defined scene graph. Examples include
trpgReadGeometryHelper, trpgReadGroupHelper, trpgReadAttachHelper,
trpgReadBillboardHelper, trpgReadLodHelper, trpgReadModelRefHelper,
trpgReadTileHeaderHelper. These are all derived from trpgr_Callback.
You should not use any of these yourself. Instead look at these classes
as examples of how to implement your own subclass of trpgSceneParser.
*/
trpgSceneGraphParser::trpgSceneGraphParser()
{
top = currTop = NULL;
top = currTop = NULL;
// Register the readers
AddCallback(TRPG_GEOMETRY,new trpgReadGeometryHelper(this));
AddCallback(TRPG_GROUP,new trpgReadGroupHelper(this));
AddCallback(TRPG_ATTACH,new trpgReadAttachHelper(this));
AddCallback(TRPG_BILLBOARD,new trpgReadBillboardHelper(this));
AddCallback(TRPG_LOD,new trpgReadLodHelper(this));
// AddCallback(TRPG_TRANSFORM,new trpgReadTransformHelper(this));
AddCallback(TRPG_MODELREF,new trpgReadModelRefHelper(this));
// AddCallback(TRPG_LAYER,new trpgReadLayerHelper(this));
AddCallback(TRPGTILEHEADER,new trpgReadTileHeaderHelper(this));
// Register the readers
AddCallback(TRPG_GEOMETRY,new trpgReadGeometryHelper(this));
AddCallback(TRPG_GROUP,new trpgReadGroupHelper(this));
AddCallback(TRPG_ATTACH,new trpgReadAttachHelper(this));
AddCallback(TRPG_CHILDREF,new trpgReadChildRefHelper(this));
AddCallback(TRPG_BILLBOARD,new trpgReadBillboardHelper(this));
AddCallback(TRPG_LOD,new trpgReadLodHelper(this));
// AddCallback(TRPG_TRANSFORM,new trpgReadTransformHelper(this));
AddCallback(TRPG_MODELREF,new trpgReadModelRefHelper(this));
// AddCallback(TRPG_LAYER,new trpgReadLayerHelper(this));
AddCallback(TRPGTILEHEADER,new trpgReadTileHeaderHelper(this));
}
// Get Current Top node
trpgReadGroupBase *trpgSceneGraphParser::GetCurrTop()
{
if (!currTop)
return NULL;
if (currTop->isGroupType())
return (trpgReadGroupBase *)currTop;
if (!currTop)
return NULL;
if (currTop->isGroupType())
return (trpgReadGroupBase *)currTop;
return NULL;
return NULL;
}
// Return a pointer to the tile header record
trpgReadTileHeader *trpgSceneGraphParser::GetTileHeaderRef()
{
return &tileHead;
return &tileHead;
}
// Parse Scene
// Parse a buffer and return the resulting scene graph
trpgReadNode *trpgSceneGraphParser::ParseScene(trpgReadBuffer &buf,GroupMap &inGmap)
{
gmap = &inGmap;
trpgTileHeader *data = tileHead.GetData();
data->Reset();
gmap = &inGmap;
trpgTileHeader *data = tileHead.GetData();
data->Reset();
// Always put a group up top, since there might be more than
// one node at the top level in the file.
top = currTop = new trpgReadGroup();
// Always put a group up top, since there might be more than
// one node at the top level in the file.
top = currTop = new trpgReadGroup();
// All the setup for tokens is handled in the constructor
// Just call parse
if (!Parse(buf)) {
// Failed to parse correctly. Give up.
delete top;
return NULL;
}
// All the setup for tokens is handled in the constructor
// Just call parse
if (!Parse(buf)) {
// Failed to parse correctly. Give up.
delete top;
return NULL;
}
return top;
return top;
}
// Start Children
@ -468,19 +493,19 @@ trpgReadNode *trpgSceneGraphParser::ParseScene(trpgReadBuffer &buf,GroupMap &inG
// We'll want to make the node it's handing us the "top" node
bool trpgSceneGraphParser::StartChildren(void *in_node)
{
trpgReadNode *node = (trpgReadNode *)in_node;
trpgReadNode *node = (trpgReadNode *)in_node;
if (!node || !node->isGroupType()) {
// Looks like there's a push in the wrong place
// Make the current "top" NULL.
// This will drop all node until we pop back above
currTop = NULL;
} else {
// This node is our new "top"
currTop = node;
}
if (!node || !node->isGroupType()) {
// Looks like there's a push in the wrong place
// Make the current "top" NULL.
// This will drop all node until we pop back above
currTop = NULL;
} else {
// This node is our new "top"
currTop = node;
}
return true;
return true;
}
/* This is called whent he parser hits a pop.
@ -488,67 +513,67 @@ bool trpgSceneGraphParser::StartChildren(void *in_node)
for the parent above the current one.
If there isn't one, we'll just stick things in our top group.
*/
bool trpgSceneGraphParser::EndChildren(void * /*in_node*/)
bool trpgSceneGraphParser::EndChildren(void* /*in_node*/)
{
// We don't need it here, but this is the node we just
// finished putting children under. If you need to close
// it out in some way, do that here
//trpgReadNode *node = (trpgReadNode *)in_node;
// We don't need it here, but this is the node we just
// finished putting children under. If you need to close
// it out in some way, do that here
//trpgReadNode *node = (trpgReadNode *)in_node;
// Get the parent above the current one
int pos = parents.size()-2;
if (pos < 0)
// Nothing above the current one. Fall back on our top group
currTop = top;
else
currTop = (trpgReadNode *)parents[pos];
// Get the parent above the current one
int pos = parents.size()-2;
if (pos < 0)
// Nothing above the current one. Fall back on our top group
currTop = top;
else
currTop = (trpgReadNode *)parents[pos];
return true;
return true;
}
// Return group map (for use by helpers)
trpgSceneGraphParser::GroupMap *trpgSceneGraphParser::GetGroupMap()
{
return gmap;
return gmap;
}
/* ***********
Test functions
***********
*/
Test functions
***********
*/
// Test all the tiles in an archive
bool trpgTestArchive(trpgr_Archive &archive)
{
int numLod;
trpg2iPoint tileSize;
trpgSceneGraphParser parse;
trpgReadNode *scene;
trpgSceneGraphParser::GroupMap gmap;
int numLod;
trpg2iPoint tileSize;
trpgSceneGraphParser parse;
trpgReadNode *scene;
trpgSceneGraphParser::GroupMap gmap;
if (!archive.isValid()) return false;
if (!archive.isValid()) return false;
const trpgHeader *head = archive.GetHeader();
head->GetNumLods(numLod);
const trpgHeader *head = archive.GetHeader();
head->GetNumLods(numLod);
// Iterate over the lods
int nl,x,y;
trpgMemReadBuffer buf(archive.GetEndian());
trpg3dPoint ll,ur;
for (nl = 0;nl < numLod;nl++) {
head->GetLodSize(nl,tileSize);
// Iterate over the tiles within those
for (x = 0; x < tileSize.x; x++)
for (y = 0; y < tileSize.y; y++) {
archive.trpgGetTileMBR(x,y,nl,ll,ur);
if (archive.ReadTile(x,y,nl,buf)) {
// Parse it
scene = parse.ParseScene(buf,gmap);
if (scene)
delete scene;
}
}
}
// Iterate over the lods
int nl,x,y;
trpgMemReadBuffer buf(archive.GetEndian());
trpg3dPoint ll,ur;
for (nl = 0;nl < numLod;nl++) {
head->GetLodSize(nl,tileSize);
// Iterate over the tiles within those
for (x = 0; x < tileSize.x; x++)
for (y = 0; y < tileSize.y; y++) {
archive.trpgGetTileMBR(x,y,nl,ll,ur);
if (archive.ReadTile(x,y,nl,buf)) {
// Parse it
scene = parse.ParseScene(buf,gmap);
if (scene)
delete scene;
}
}
}
return true;
return true;
}

View File

@ -18,221 +18,234 @@
#define _txpage_scene_h_
/* trpage_scene.h
Scene Graph definition.
This is a small scene graph we use for testing.
It's not intended to replace the scene graph you may already be using.
You do not need to translate from this scene graph structure to your own,
at run-time. Instead, use this file and trpage_scene.cpp as a guideline
for how to read TerraPage format into your own scene graph.
Scene Graph definition.
This is a small scene graph we use for testing.
It's not intended to replace the scene graph you may already be using.
You do not need to translate from this scene graph structure to your own,
at run-time. Instead, use this file and trpage_scene.cpp as a guideline
for how to read TerraPage format into your own scene graph.
*/
#include <trpage_geom.h>
/*
{group:Demonstration Scene Graph}
*/
{group:Demonstration Scene Graph}
*/
TX_EXDECL class TX_CLDECL trpgMBR {
public:
trpgMBR(void);
~trpgMBR(void) { };
bool isValid(void) const;
void Reset(void);
void AddPoint(const trpg3dPoint &);
void AddPoint(double,double,double);
void GetMBR(trpg3dPoint &ll,trpg3dPoint &ur) const;
trpg3dPoint GetLL(void) const;
trpg3dPoint GetUR(void) const;
void Union(const trpgMBR &);
// bool Overlap(const trpgMBR &) const;
bool Overlap(const trpg2dPoint &ll, const trpg2dPoint &ur) const;
// bool Within(const trpg3dPoint &) const
bool Within(const trpg2dPoint &) const;
trpgMBR(void);
~trpgMBR(void) { };
bool isValid(void) const;
void Reset(void);
void AddPoint(const trpg3dPoint &);
void AddPoint(double,double,double);
void GetMBR(trpg3dPoint &ll,trpg3dPoint &ur) const;
trpg3dPoint GetLL(void) const;
trpg3dPoint GetUR(void) const;
void Union(const trpgMBR &);
// bool Overlap(const trpgMBR &) const;
bool Overlap(const trpg2dPoint &ll, const trpg2dPoint &ur) const;
// bool Within(const trpg3dPoint &) const
bool Within(const trpg2dPoint &) const;
protected:
inline bool inRange(double minv,double maxv,double val) const { return (val >= minv && val <= maxv); }
bool valid;
trpg3dPoint ll,ur;
inline bool inRange(double minv,double maxv,double val) const { return (val >= minv && val <= maxv); }
bool valid;
trpg3dPoint ll,ur;
};
// Read Node
// Simple Scenegraph node used for read testing
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadNode {
public:
virtual ~trpgReadNode(void) { };
virtual bool isGroupType(void) = 0;
virtual int GetType(void) { return type; }
virtual trpgMBR GetMBR(void) const { return trpgMBR(); }
virtual ~trpgReadNode(void) { };
virtual bool isGroupType(void) = 0;
virtual int GetType(void) { return type; }
virtual trpgMBR GetMBR(void) const { return trpgMBR(); }
protected:
int type;
int type;
};
// Read Group Base
// Base class for all group nodes
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadGroupBase : public trpgReadNode {
public:
virtual ~trpgReadGroupBase(void);
void AddChild(trpgReadNode *);
bool isGroupType(void) { return true; }
int GetNumChildren(void) { return children.size(); }
trpgReadNode *GetChild(int i) { return children[i]; }
trpgMBR GetMBR(void) const;
void unRefChild(int i);
void unRefChildren(void);
virtual ~trpgReadGroupBase(void);
void AddChild(trpgReadNode *);
bool isGroupType(void) { return true; }
int GetNumChildren(void) { return int(children.size()); }
trpgReadNode *GetChild(int i) { return children[i]; }
trpgMBR GetMBR(void) const;
void unRefChild(int i);
void unRefChildren(void);
protected:
trpgMBR mbr;
void DeleteChildren(void);
std::vector<trpgReadNode *> children;
trpgMBR mbr;
void DeleteChildren(void);
std::vector<trpgReadNode *> children;
};
// Read Geometry
// The leaf for this scene graph
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadGeometry : public trpgReadNode {
public:
trpgReadGeometry(void) { type = TRPG_GEOMETRY; }
~trpgReadGeometry(void) { };
bool isGroupType(void) { return false; }
trpgGeometry *GetData(void) { return &data; }
trpgMBR GetMBR(void) const;
trpgReadGeometry(void) { type = TRPG_GEOMETRY; }
~trpgReadGeometry(void) { };
bool isGroupType(void) { return false; }
trpgGeometry *GetData(void) { return &data; }
trpgMBR GetMBR(void) const;
protected:
trpgMBR mbr;
trpgGeometry data;
trpgMBR mbr;
trpgGeometry data;
};
// Read Tile Header
// One per tile. Info about what materials and models are used
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadTileHeader : public trpgReadNode {
public:
trpgReadTileHeader(void) { type = TRPGTILEHEADER; }
~trpgReadTileHeader(void) { };
bool isGroupType(void) { return false; }
trpgTileHeader *GetData(void) { return &data; }
trpgMBR GetMBR(void) const { trpgMBR mbr; return mbr; };
trpgReadTileHeader(void) { type = TRPGTILEHEADER; }
~trpgReadTileHeader(void) { };
bool isGroupType(void) { return false; }
trpgTileHeader *GetData(void) { return &data; }
trpgMBR GetMBR(void) const { trpgMBR mbr; return mbr; };
protected:
trpgTileHeader data;
trpgTileHeader data;
};
// Read Group
// Simple group structure
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadGroup : public trpgReadGroupBase {
public:
trpgReadGroup(void) { type = TRPG_GROUP; }
~trpgReadGroup(void) { };
trpgGroup *GetData(void) { return &data; }
trpgReadGroup(void) { type = TRPG_GROUP; }
~trpgReadGroup(void) { };
trpgGroup *GetData(void) { return &data; }
protected:
trpgGroup data;
trpgGroup data;
};
// Read Attach
// Should be the top of a higher LOD tile
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadAttach : public trpgReadGroupBase {
public:
trpgReadAttach(void) { type = TRPG_ATTACH; }
~trpgReadAttach(void) { };
trpgAttach *GetData(void) { return &data; }
trpgReadAttach(void) { type = TRPG_ATTACH; }
~trpgReadAttach(void) { };
trpgAttach *GetData(void) { return &data; }
protected:
trpgAttach data;
trpgAttach data;
};
// Read ChildRef
// Should point to a block tile
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadChildRef : public trpgReadGroupBase {
public:
trpgReadChildRef(void) { type = TRPG_CHILDREF; }
~trpgReadChildRef(void) { };
bool isGroupType(void) { return false;}
trpgChildRef *GetData(void) { return &data; }
protected:
trpgChildRef data;
};
// Read billboard
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadBillboard : public trpgReadGroupBase {
public:
trpgReadBillboard(void) { type = TRPG_BILLBOARD; }
~trpgReadBillboard(void) { };
trpgBillboard *GetData(void) { return &data; }
trpgReadBillboard(void) { type = TRPG_BILLBOARD; }
~trpgReadBillboard(void) { };
trpgBillboard *GetData(void) { return &data; }
protected:
trpgBillboard data;
trpgBillboard data;
};
// Read LOD
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadLod : public trpgReadGroupBase {
public:
trpgReadLod(void) { type = TRPG_LOD; }
~trpgReadLod(void) { };
trpgLod *GetData(void) { return &data; }
trpgReadLod(void) { type = TRPG_LOD; }
~trpgReadLod(void) { };
trpgLod *GetData(void) { return &data; }
protected:
trpgLod data;
trpgLod data;
};
// Read Layer
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadLayer : public trpgReadGroupBase {
public:
trpgReadLayer(void) { type = TRPG_LAYER; }
~trpgReadLayer(void) { };
trpgLayer *GetData(void) { return &data; }
trpgReadLayer(void) { type = TRPG_LAYER; }
~trpgReadLayer(void) { };
trpgLayer *GetData(void) { return &data; }
protected:
trpgLayer data;
trpgLayer data;
};
// Read Transform
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadTransform : public trpgReadGroupBase {
public:
trpgReadTransform(void) { type = TRPG_TRANSFORM; }
~trpgReadTransform(void) { };
trpgTransform *GetData(void) { return &data; }
trpgReadTransform(void) { type = TRPG_TRANSFORM; }
~trpgReadTransform(void) { };
trpgTransform *GetData(void) { return &data; }
protected:
trpgTransform data;
trpgTransform data;
};
// Read Model Reference
// {group:Demonstration Scene Graph}
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgReadModelRef : public trpgReadGroupBase {
public:
trpgReadModelRef(void) { type = TRPG_MODELREF; }
~trpgReadModelRef(void) { };
trpgModelRef *GetData(void) { return &data; }
trpgReadModelRef(void) { type = TRPG_MODELREF; }
~trpgReadModelRef(void) { };
trpgModelRef *GetData(void) { return &data; }
protected:
trpgModelRef data;
trpgModelRef data;
};
/* Scene Graph Parser
Parses a read buffer and returns a full scenegraph.
You don't want to use this if you're reading into your own scenegraph.
Instead, you'll want to sublcass trpgSceneParser, which is a helper
class to keep track of pushes and pops and implement the same functionality
that trpgSceneGraphParser has for your own scene graph.
*/
// {group:Demonstration Scene Graph}
Parses a read buffer and returns a full scenegraph.
You don't want to use this if you're reading into your own scenegraph.
Instead, you'll want to sublcass trpgSceneParser, which is a helper
class to keep track of pushes and pops and implement the same functionality
that trpgSceneGraphParser has for your own scene graph.
*/
// {group:Demonstration Scene Graph}
TX_EXDECL class TX_CLDECL trpgSceneGraphParser : public trpgSceneParser {
public:
#if defined(_WIN32)
typedef std::map<int,trpgReadGroupBase *> GroupMap;
typedef std::map<int,trpgReadGroupBase *> GroupMap;
#else
typedef std::map<int,trpgReadGroupBase *,std::less<int> > GroupMap;
typedef std::map< int,trpgReadGroupBase *,std::less<int> > GroupMap;
#endif
trpgSceneGraphParser(void);
virtual ~trpgSceneGraphParser(void) { };
// Call this instead of Parse()
// Deleting it is your responsibility
trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &);
trpgReadGroupBase *GetCurrTop(void); // Get the current parent object
trpgReadTileHeader *GetTileHeaderRef(void);
trpgSceneGraphParser(void);
virtual ~trpgSceneGraphParser(void) { };
// Call this instead of Parse()
// Deleting it is your responsibility
trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &);
trpgReadGroupBase *GetCurrTop(void); // Get the current parent object
trpgReadTileHeader *GetTileHeaderRef(void);
// For use by the helpers only
GroupMap *GetGroupMap(void);
// For use by the helpers only
GroupMap *GetGroupMap(void);
protected:
bool StartChildren(void *);
bool EndChildren(void *);
trpgReadNode *currTop; // Current parent group
trpgReadNode *top; // Top of everything
GroupMap *gmap;
trpgReadTileHeader tileHead; // Tile header gets read into here
bool StartChildren(void *);
bool EndChildren(void *);
trpgReadNode *currTop; // Current parent group
trpgReadNode *top; // Top of everything
GroupMap *gmap;
trpgReadTileHeader tileHead; // Tile header gets read into here
};
/* Test Archive
Utility function that loads and tests all tiles.
The only reason you'd want to call this is to test a TerraPage archive
you'd written.
*/
// {group:Demonstration Scene Graph}
Utility function that loads and tests all tiles.
The only reason you'd want to call this is to test a TerraPage archive
you'd written.
*/
// {group:Demonstration Scene Graph}
TX_CPPDECL bool trpgTestArchive(trpgr_Archive &);
#endif

View File

@ -17,15 +17,15 @@
#include <stdio.h>
/* trpage_swap.h
Byte swapping utility functions.
*/
Byte swapping utility functions.
*/
#include <trpage_swap.h>
/*
** func: swap_two( in, out )
** func: swap_two( in, out )
**
** desc: byte-swaps a two-byte array.
** desc: byte-swaps a two-byte array.
*/
void trpg_swap_two ( const char *in, char *out )
{
@ -38,9 +38,9 @@ void trpg_swap_two ( const char *in, char *out )
}
/*
** func: swap_four( in, out )
** func: swap_four( in, out )
**
** desc: byte-swaps a four-byte array.
** desc: byte-swaps a four-byte array.
*/
void trpg_swap_four ( const char *in, char *out )
{
@ -55,9 +55,9 @@ void trpg_swap_four ( const char *in, char *out )
}
/*
** func: swap_eight( in, out )
** func: swap_eight( in, out )
**
** desc: byte-swaps an eight-byte array.
** desc: byte-swaps an eight-byte array.
*/
void trpg_swap_eight ( const char *in, char *out )
{
@ -76,9 +76,9 @@ void trpg_swap_eight ( const char *in, char *out )
}
/*
** func: swap_sixteen( in, out )
** func: swap_sixteen( in, out )
**
** desc: byte-swaps an sixteen-byte array.
** desc: byte-swaps an sixteen-byte array.
*/
void trpg_swap_sixteen ( const char *in, char *out )
{
@ -105,105 +105,105 @@ void trpg_swap_sixteen ( const char *in, char *out )
}
/*
** func: tx_byteswap_short( number )
** func: tx_byteswap_short( number )
**
** desc: byte-swaps a short int.
** desc: byte-swaps a short int.
*/
short trpg_byteswap_short( short number )
{
short result;
short result;
trpg_swap_two( (const char*) &number, (char*) &result );
return result;
trpg_swap_two( (const char*) &number, (char*) &result );
return result;
}
/*
** func: tx_byteswap_int( number )
** func: tx_byteswap_int( number )
**
** desc: byte-swaps an int.
** desc: byte-swaps an int.
*/
int trpg_byteswap_int( int number )
TX_CPPDECL int trpg_byteswap_int( int number )
{
int result;
int result;
trpg_swap_four( (const char*) &number, (char*) &result );
return result;
trpg_swap_four( (const char*) &number, (char*) &result );
return result;
}
/*
** func: tx_byteswap_long( number )
** func: tx_byteswap_long( number )
**
** desc: byte-swaps a long int.
** desc: byte-swaps a long int.
*/
long trpg_byteswap_long( long number )
{
long result;
long result;
trpg_swap_four( (const char*) &number, (char*) &result );
return result;
trpg_swap_four( (const char*) &number, (char*) &result );
return result;
}
/*
** func: tx_byteswap_float( number )
** func: tx_byteswap_float( number )
**
** desc: byte-swaps a float.
** desc: byte-swaps a float.
*/
void trpg_byteswap_float_to_4bytes( float number, char result[4] )
{
trpg_swap_four( (const char*) &number, result );
trpg_swap_four( (const char*) &number, result );
}
/*
** func: tx_byteswap_double_to_8bytes( number )
** func: tx_byteswap_double_to_8bytes( number )
**
** desc: byte-swaps a double.
** desc: byte-swaps a double.
*/
void trpg_byteswap_double_to_8bytes( double number, char result[8] )
{
trpg_swap_eight( (const char*) &number, result );
trpg_swap_eight( (const char*) &number, result );
}
/*
** func: tx_byteswap_float( number )
** func: tx_byteswap_float( number )
**
** desc: byte-swaps a float.
** desc: byte-swaps a float.
*/
float trpg_byteswap_4bytes_to_float( const char result[4] )
{
float number;
trpg_swap_four( result, (char*) &number );
return number;
float number;
trpg_swap_four( result, (char*) &number );
return number;
}
/*
** func: tx_byteswap_double_to_8bytes( number )
** func: tx_byteswap_double_to_8bytes( number )
**
** desc: byte-swaps a double.
** desc: byte-swaps a double.
*/
double trpg_byteswap_8bytes_to_double( const char result[8] )
{
double number;
trpg_swap_eight( result, (char*) &number );
return number;
double number;
trpg_swap_eight( result, (char*) &number );
return number;
}
trpgllong trpg_byteswap_llong ( trpgllong number )
{
trpgllong result;
trpgllong result;
trpg_swap_sixteen ( (char *) &number, (char *) &result);
trpg_swap_sixteen ( (char *) &number, (char *) &result);
return result;
return result;
}
trpgEndian trpg_cpu_byte_order(void)
TX_CPPDECL trpgEndian trpg_cpu_byte_order(void)
{
static char big_endian_100[2] = { 0, 100 };
static char big_endian_100[2] = { 0, 100 };
if ( (*((short*) big_endian_100)) == 100 )
return BigEndian;
else
return LittleEndian;
if ( (*((short*) big_endian_100)) == 100 )
return BigEndian;
else
return LittleEndian;
}

View File

@ -17,7 +17,7 @@
#define trpage_swap_h_
/* trpage_swap.h
Byte swapping utility functions.
Byte swapping utility functions.
*/
#include <trpage_sys.h>
@ -29,7 +29,7 @@
short trpg_byteswap_short( short number );
// Byte swap and return an integer
// {group:Byte Ordering Utilities}
int trpg_byteswap_int( int number );
TX_CPPDECL int trpg_byteswap_int( int number );
// Byte swap and return a long
// {group:Byte Ordering Utilities}
long trpg_byteswap_long( long number );
@ -50,7 +50,7 @@ float trpg_byteswap_4bytes_to_float( const char result[4] );
double trpg_byteswap_8bytes_to_double( const char result[8] );
// Determine the current CPU's byte ordering
// {group:Byte Ordering Utilities}
trpgEndian trpg_cpu_byte_order(void);
TX_CPPDECL trpgEndian trpg_cpu_byte_order(void);
// Swap two chars
// {group:Byte Ordering Utilities}

View File

@ -14,8 +14,8 @@
*/
/* trpage_sys.h
System specific declarations.
*/
System specific declarations.
*/
#ifndef trpage_sys_h_
#define trpage_sys_h_
@ -29,11 +29,11 @@
#endif
#if defined(_WIN32)
/* *********************
System Specific Section.
This is currently set up for win32.
*********************
*/
/* *********************
System Specific Section.
This is currently set up for win32.
*********************
*/
#include <windows.h>
@ -86,15 +86,15 @@ typedef float float32;
typedef double float64;
#endif
// Note: replace this with your own STL implementation
// You can use the Microsoft provided one by deleting the first #include
#ifdef USEROGUE
#include <txRogueWave.h>
#endif
#if defined(_WIN32) || defined(linux)
#include <vector>
#include <map>
#include <string>
#else
#include <vector.h>
#include <map.h>
#endif
#if defined(_WIN32) // PJM
// Had to take this out because of an iostream conflict

View File

@ -17,234 +17,316 @@
#include <stdio.h>
#include <string.h>
/* trpage_tile.cpp
This source file contains the implementation of trpgTileTable and trpgTileHeader.
You'll need to edit these if you want to add something to the Tile Table (at
the front of an archive) or the Tile Header (at the beginning of each tile).
*/
This source file contains the implementation of trpgTileTable and trpgTileHeader.
You'll need to edit these if you want to add something to the Tile Table (at
the front of an archive) or the Tile Header (at the beginning of each tile).
*/
#include <trpage_geom.h>
#include <trpage_read.h>
/* Write Tile Table
Keeps track of tiles written to disk.
*/
Keeps track of tiles written to disk.
*/
// Constructor
trpgTileTable::trpgTileTable()
{
Reset();
localBlock = false;
Reset();
}
// Reset function
void trpgTileTable::Reset()
{
errMess[0] = '\0';
mode = External;
lodInfo.resize(0);
valid = true;
errMess[0] = '\0';
mode = External;
lodInfo.resize(0);
valid = true;
currentRow = -1;
currentCol = -1;
}
// Destructor
trpgTileTable::~trpgTileTable()
{
valid = false;
}
// Set functions
void trpgTileTable::SetMode(TileMode inMode)
{
Reset();
mode = inMode;
Reset();
mode = inMode;
}
void trpgTileTable::SetNumLod(int numLod)
{
lodInfo.resize(numLod);
lodInfo.resize(numLod);
}
void trpgTileTable::SetNumTiles(int nx,int ny,int lod)
{
if (nx <= 0 || ny <= 0 || lod < 0 || lod >= (int)lodInfo.size())
return;
if(localBlock) {
LodInfo &li = lodInfo[lod];
li.numX = nx; li.numY = ny;
li.addr.resize(1);
li.elev_min.resize(1,0.0);
li.elev_max.resize(1,0.0);
valid = true;
// no need to do anything else if we only have one block.
return;
}
if (nx <= 0 || ny <= 0 || lod < 0 || lod >= static_cast<int>(lodInfo.size()))
return;
// Got a table we need to maintain
if (mode == Local) {
// If there's a pre-existing table, we need to preserve the entries
LodInfo oldLodInfo = lodInfo[lod];
// Got a table we need to maintain
if (mode == Local || mode == ExternalSaved) {
// If there's a pre-existing table, we need to preserve the entries
LodInfo oldLodInfo = lodInfo[lod];
LodInfo &li = lodInfo[lod];
li.numX = nx; li.numY = ny;
int numTile = li.numX*li.numY;
li.addr.resize(numTile);
li.elev_min.resize(numTile,0.0);
li.elev_max.resize(numTile,0.0);
LodInfo &li = lodInfo[lod];
li.numX = nx; li.numY = ny;
int numTile = li.numX*li.numY;
li.addr.resize(numTile);
li.elev_min.resize(numTile,0.0);
li.elev_max.resize(numTile,0.0);
// Copy pre-existing data if it's there
if (oldLodInfo.addr.size() > 0) {
for (int x=0;x<oldLodInfo.numX;x++) {
for (int y=0;y<oldLodInfo.numY;y++) {
int oldLoc = y*oldLodInfo.numX + x;
int newLoc = y*li.numX + x;
li.addr[newLoc] = oldLodInfo.addr[oldLoc];
li.elev_min[newLoc] = oldLodInfo.elev_min[oldLoc];
li.elev_max[newLoc] = oldLodInfo.elev_max[oldLoc];
}
}
}
}
valid = true;
// Copy pre-existing data if it's there
if (oldLodInfo.addr.size() > 0) {
for (int x=0;x<oldLodInfo.numX;x++) {
for (int y=0;y<oldLodInfo.numY;y++) {
int oldLoc = y*oldLodInfo.numX + x;
int newLoc = y*li.numX + x;
li.addr[newLoc] = oldLodInfo.addr[oldLoc];
li.elev_min[newLoc] = oldLodInfo.elev_min[oldLoc];
li.elev_max[newLoc] = oldLodInfo.elev_max[oldLoc];
}
}
}
}
valid = true;
}
void trpgTileTable::SetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 zmin,float32 zmax)
{
if (lod < 0 || lod >= (int)lodInfo.size()) return;
if (mode != Local)
return;
LodInfo &li = lodInfo[lod];
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return;
int loc = y*li.numX + x;
li.addr[loc] = ref;
li.elev_min[loc] = zmin;
li.elev_max[loc] = zmax;
if (lod < 0 || lod >= static_cast<int>(lodInfo.size()))
return;
if (mode == External)
return;
LodInfo &li = lodInfo[lod];
int loc;
if(localBlock) {
loc = 0;
}
else {
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return;
loc = y*li.numX + x;
}
li.addr[loc] = ref;
li.elev_min[loc] = zmin;
li.elev_max[loc] = zmax;
}
bool trpgTileTable::isValid() const
{
return valid;
return valid;
}
// Get methods
bool trpgTileTable::GetMode(TileMode &outMode) const
{
if (!isValid()) return false;
if (!isValid()) return false;
outMode = mode;
return true;
outMode = mode;
return true;
}
bool trpgTileTable::GetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 &zmin,float32 &zmax) const
{
if (!isValid()) return false;
if (!isValid()) return false;
if (lod < 0 || lod >= (int)lodInfo.size()) return false;
if (mode != Local)
return false;
const LodInfo &li = lodInfo[lod];
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return false;
if (lod < 0 || lod >= static_cast<int>(lodInfo.size())) return false;
if (mode == External)
return false;
int loc = y*li.numX + x;
ref = li.addr[loc];
zmin = li.elev_min[loc];
zmax = li.elev_max[loc];
const LodInfo &li = lodInfo[lod];
int loc;
if(localBlock) {
loc = 0;
}
else {
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return false;
loc = y*li.numX + x;
}
ref = li.addr[loc];
zmin = li.elev_min[loc];
zmax = li.elev_max[loc];
return true;
return true;
}
// Write tile table
bool trpgTileTable::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGTILETABLE2);
// Write the mode
buf.Add(mode);
buf.Begin(TRPGTILETABLE2);
// Write the mode
buf.Add(mode);
// Depending on the mode we'll have a lot or a little data
if (mode == Local) {
// The lod sizing is redundant, but it's convenient here
int numLod = lodInfo.size();
buf.Add(numLod);
// Depending on the mode we'll have a lot or a little data
if (mode == Local || mode == ExternalSaved) {
// The lod sizing is redundant, but it's convenient here
int numLod = lodInfo.size();
buf.Add(numLod);
// Write each terrain LOD set
for (int i=0;i<numLod;i++) {
LodInfo &li = lodInfo[i];
buf.Add(li.numX);
buf.Add(li.numY);
// Now for the interesting stuff
unsigned int j;
for (j=0;j<li.addr.size();j++) {
trpgwAppAddress &ref = li.addr[j];
buf.Add((int32)ref.file);
buf.Add((int32)ref.offset);
}
for (j=0;j<li.elev_min.size();j++) {
buf.Add(li.elev_min[j]);
buf.Add(li.elev_max[j]);
}
}
}
// Write each terrain LOD set
for (int i=0;i<numLod;i++) {
LodInfo &li = lodInfo[i];
if(localBlock) {
// only one x and one y in a local archive
buf.Add(1);
buf.Add(1);
// local blocks always use index 0
trpgwAppAddress &ref = li.addr[0];
buf.Add((int32)ref.file);
buf.Add((int32)ref.offset);
buf.End();
buf.Add(li.elev_min[0]);
buf.Add(li.elev_max[0]);
}
else {
buf.Add(li.numX);
buf.Add(li.numY);
// Now for the interesting stuff
unsigned int j;
for (j=0;j<li.addr.size();j++) {
trpgwAppAddress &ref = li.addr[j];
buf.Add((int32)ref.file);
buf.Add((int32)ref.offset);
}
for (j=0;j<li.elev_min.size();j++) {
buf.Add(li.elev_min[j]);
buf.Add(li.elev_max[j]);
}
}
}
}
return true;
buf.End();
return true;
}
/* **************
Tile Table Read method
**************
*/
/* **************
Tile Table Read method
**************
*/
bool trpgTileTable::Read(trpgReadBuffer &buf)
{
valid = false;
valid = false;
try {
int imode;
buf.Get(imode); mode = (TileMode)imode;
if (mode != External && mode != Local) throw 1;
if (mode == Local) {
int numLod;
buf.Get(numLod);
if (numLod <= 0) throw 1;
lodInfo.resize(numLod);
try {
int imode;
buf.Get(imode); mode = (TileMode)imode;
if (mode != External && mode != Local && mode != ExternalSaved) throw 1;
if (mode == Local || mode == ExternalSaved) {
int numLod;
buf.Get(numLod);
if (numLod <= 0) throw 1;
lodInfo.resize(numLod);
for (int i=0;i<numLod;i++) {
LodInfo &li = lodInfo[i];
buf.Get(li.numX);
buf.Get(li.numY);
if (li.numX <= 0 || li.numY <= 0) throw 1;
int numTile = li.numX*li.numY;
li.addr.resize(numTile);
li.elev_min.resize(numTile);
li.elev_max.resize(numTile);
int j;
for (j=0;j<numTile;j++) {
trpgwAppAddress &ref = li.addr[j];
buf.Get(ref.file);
buf.Get(ref.offset);
}
for (j=0;j<numTile;j++) {
buf.Get(li.elev_min[j]);
buf.Get(li.elev_max[j]);
}
}
}
for (int i=0;i<numLod;i++) {
valid = true;
}
catch (...) {
return false;
}
LodInfo &li = lodInfo[i];
if(localBlock) {
if(li.addr.size()==0) {
li.addr.resize(1);
li.elev_min.resize(1,0.0);
li.elev_max.resize(1,0.0);
}
int32 x,y;
buf.Get(x);
buf.Get(y);
int pos = (currentRow * li.numX) + currentCol;
int32 file,offset;
buf.Get(file);
buf.Get(offset);
trpgwAppAddress &ref = li.addr[pos];
ref.file = file;
ref.offset = offset;
ref.col = currentCol;
ref.row = currentRow;
float emin,emax;
buf.Get(emin);
buf.Get(emax);
return isValid();
li.elev_max[pos] = emax;
li.elev_min[pos] = emin;
}
else {
buf.Get(li.numX);
buf.Get(li.numY);
if (li.numX <= 0 || li.numY <= 0)
throw 1;
int numTile = li.numX*li.numY;
li.addr.resize(numTile);
li.elev_min.resize(numTile);
li.elev_max.resize(numTile);
int j;
for (j=0;j<numTile;j++) {
int32 file,offset;
buf.Get(file);
buf.Get(offset);
trpgwAppAddress &ref = li.addr[j];
ref.file = file;
ref.offset = offset;
}
for (j=0;j<numTile;j++) {
float emin,emax;
buf.Get(emin);
buf.Get(emax);
li.elev_max[j] = emax;
li.elev_min[j] = emin;
}
}
}
}
valid = true;
}
catch (...) {
printf("Caught an exception\n");
return false;
}
return isValid();
}
/* Tile Header
Each distinct tile (or model) must have a header
which tells you what models and materials are
referenced in that tile.
*/
Each distinct tile (or model) must have a header
which tells you what models and materials are
referenced in that tile.
*/
// Constructor
trpgTileHeader::trpgTileHeader()
{
col = -1;
row = -1;
}
trpgTileHeader::~trpgTileHeader()
{
@ -252,45 +334,47 @@ trpgTileHeader::~trpgTileHeader()
void trpgTileHeader::Reset()
{
matList.resize(0);
modelList.resize(0);
locMats.resize(0);
matList.resize(0);
modelList.resize(0);
locMats.resize(0);
col = -1;
row = -1;
}
// Set functions
void trpgTileHeader::SetMaterial(int no,int id)
{
if (no < 0 || no >= (int)matList.size())
return;
matList[no] = id;
if (no < 0 || no >= static_cast<int>(matList.size()))
return;
matList[no] = id;
}
void trpgTileHeader::SetModel(int no,int id)
{
if (no < 0 || no >= (int)modelList.size())
return;
modelList[no] = id;
if (no < 0 || no >= static_cast<int>(modelList.size()))
return;
modelList[no] = id;
}
// Set functions
void trpgTileHeader::AddMaterial(int id)
{
// Look for it first
// Look for it first
for (unsigned int i=0;i<matList.size();i++)
if (matList[i] == id)
return;
// Didn't find it, add it.
matList.push_back(id);
if (matList[i] == id)
return;
// Didn't find it, add it.
matList.push_back(id);
}
void trpgTileHeader::AddModel(int id)
{
for (unsigned int i=0;i<modelList.size();i++)
if (modelList[i] == id)
return;
modelList.push_back(id);
if (modelList[i] == id)
return;
modelList.push_back(id);
}
void trpgTileHeader::SetDate(int32 d)
{
date = d;
date = d;
}
// Local material methods
@ -310,8 +394,8 @@ bool trpgTileHeader::GetNumLocalMaterial(int32 &retNum) const
bool trpgTileHeader::GetLocalMaterial(int32 id,trpgLocalMaterial &retMat) const
{
if (id < 0 || id >= (int)locMats.size())
return false;
if (id < 0 || id >= static_cast<int>(locMats.size()))
return false;
retMat = locMats[id];
@ -328,78 +412,78 @@ const std::vector<trpgLocalMaterial> *trpgTileHeader::GetLocalMaterialList() con
// Get methods
bool trpgTileHeader::GetNumMaterial(int32 &no) const
{
if (!isValid()) return false;
no = matList.size();
return true;
if (!isValid()) return false;
no = matList.size();
return true;
}
bool trpgTileHeader::GetMaterial(int32 id,int32 &mat) const
{
if (!isValid() || id < 0 || id >= (int)matList.size())
return false;
mat = matList[id];
return true;
if (!isValid() || id < 0 || id >= static_cast<int>(matList.size()))
return false;
mat = matList[id];
return true;
}
bool trpgTileHeader::GetNumModel(int32 &no) const
{
if (!isValid()) return false;
no = modelList.size();
return true;
if (!isValid()) return false;
no = modelList.size();
return true;
}
bool trpgTileHeader::GetModel(int32 id,int32 &m) const
{
if (!isValid() || id < 0 || id >= (int)modelList.size())
return false;
m = modelList[id];
return true;
if (!isValid() || id < 0 || id >= static_cast<int>(modelList.size()))
return false;
m = modelList[id];
return true;
}
bool trpgTileHeader::GetDate(int32 &d) const
{
if (!isValid()) return false;
d = date;
return true;
if (!isValid()) return false;
d = date;
return true;
}
// Validity check
bool trpgTileHeader::isValid() const
{
return true;
return true;
}
// Write to a buffer
bool trpgTileHeader::Write(trpgWriteBuffer &buf)
{
unsigned int i;
unsigned int i;
if (!isValid())
return false;
for (i=0;i<locMats.size();i++)
if (!locMats[i].isValid())
return false;
if (!isValid())
return false;
for (i=0;i<locMats.size();i++)
if (!locMats[i].isValid())
return false;
buf.Begin(TRPGTILEHEADER);
buf.Begin(TRPGTILEHEADER);
buf.Begin(TRPG_TILE_MATLIST);
buf.Add((int32)matList.size());
for (i=0;i<matList.size();i++)
buf.Add(matList[i]);
buf.End();
buf.Begin(TRPG_TILE_MODELLIST);
buf.Add((int32)modelList.size());
for (i=0;i<modelList.size();i++)
buf.Add(modelList[i]);
buf.End();
buf.Begin(TRPG_TILE_DATE);
buf.Add(date);
buf.End();
buf.Begin(TRPG_TILE_LOCMATLIST);
buf.Add((int32)locMats.size());
for (i=0;i<locMats.size();i++)
locMats[i].Write(buf);
buf.End();
buf.Begin(TRPG_TILE_MATLIST);
buf.Add((int32)matList.size());
for (i=0;i<matList.size();i++)
buf.Add(matList[i]);
buf.End();
buf.Begin(TRPG_TILE_MODELLIST);
buf.Add((int32)modelList.size());
for (i=0;i<modelList.size();i++)
buf.Add(modelList[i]);
buf.End();
buf.Begin(TRPG_TILE_DATE);
buf.Add(date);
buf.End();
buf.Begin(TRPG_TILE_LOCMATLIST);
buf.Add((int32)locMats.size());
for (i=0;i<locMats.size();i++)
locMats[i].Write(buf);
buf.End();
buf.End();
buf.End();
return true;
return true;
}
// Tile Header CB
@ -407,81 +491,87 @@ bool trpgTileHeader::Write(trpgWriteBuffer &buf)
// We want the tile header to be expandable, so be careful here
class tileHeaderCB : public trpgr_Callback {
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgTileHeader *head;
void * Parse(trpgToken,trpgReadBuffer &);
trpgTileHeader *head;
};
void * tileHeaderCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
int32 no,id,date,i;
int32 no,id,date,i;
try {
switch (tok) {
case TRPG_TILE_MATLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i = 0;i < no; i++) {
buf.Get(id);
head->AddMaterial(id);
}
break;
case TRPG_TILE_MODELLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i=0;i<no;i++) {
buf.Get(id);
head->AddModel(id);
}
break;
case TRPG_TILE_DATE:
buf.Get(date);
head->SetDate(date);
break;
case TRPG_TILE_LOCMATLIST:
{
int32 numLocMat;
buf.Get(numLocMat);
if (numLocMat < 0) throw 1;
std::vector<trpgLocalMaterial> *locMats;
locMats = const_cast<std::vector<trpgLocalMaterial> *> (head->GetLocalMaterialList());
locMats->resize(numLocMat);
for (i=0;i<numLocMat;i++) {
trpgToken matTok;
int32 len;
buf.GetToken(matTok,len);
if (matTok != TRPGLOCALMATERIAL) throw 1;
buf.PushLimit(len);
trpgLocalMaterial &locMat = (*locMats)[i];
locMat.Read(buf);
buf.PopLimit();
}
}
break;
default:
// Don't care
break;
}
}
catch (...) {
return NULL;
}
try {
switch (tok) {
case TRPG_TILE_MATLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i = 0;i < no; i++) {
buf.Get(id);
head->AddMaterial(id);
}
break;
case TRPG_TILE_MODELLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i=0;i<no;i++) {
buf.Get(id);
head->AddModel(id);
}
break;
case TRPG_TILE_DATE:
buf.Get(date);
head->SetDate(date);
break;
case TRPG_TILE_LOCMATLIST:
{
int32 numLocMat;
buf.Get(numLocMat);
if (numLocMat < 0) throw 1;
std::vector<trpgLocalMaterial> *locMats;
locMats = const_cast<std::vector<trpgLocalMaterial> *> (head->GetLocalMaterialList());
locMats->resize(numLocMat);
for (i=0;i<numLocMat;i++) {
trpgToken matTok;
int32 len;
buf.GetToken(matTok,len);
if (matTok != TRPGLOCALMATERIAL) throw 1;
buf.PushLimit(len);
trpgLocalMaterial &locMat = (*locMats)[i];
locMat.Read(buf);
// Set the row/col for later finding
trpgwAppAddress addr;
locMat.GetAddr(addr);
head->GetBlockNo(addr.row,addr.col);
locMat.SetAddr(addr);
return head;
buf.PopLimit();
}
}
break;
default:
// Don't care
break;
}
}
catch (...) {
return NULL;
}
return head;
}
// Read tile header
bool trpgTileHeader::Read(trpgReadBuffer &buf)
{
tileHeaderCB tcb;
trpgr_Parser parse;
tileHeaderCB tcb;
trpgr_Parser parse;
tcb.head = this;
parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_DATE,&tcb,false);
// New for 2.0
parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false);
parse.Parse(buf);
tcb.head = this;
parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_DATE,&tcb,false);
// New for 2.0
parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false);
parse.Parse(buf);
return isValid();
return isValid();
}

View File

@ -16,8 +16,8 @@
#include <trpage_util.h>
/* trpage_util.cpp
This source file implements various utility routines for paging archive
*/
This source file implements various utility routines for paging archive
*/
/* The merge routine used to be in here.
However, merge isn't actually general enough to be part of the library.
@ -25,4 +25,3 @@
Instead, there's a Windows specific program that merges TerraPage archives in
the merge/ directory of this distribution.
*/

View File

@ -14,8 +14,8 @@
*/
/* trpage_sys.h
System specific declarations.
*/
System specific declarations.
*/
#ifndef trpage_util_h_
#define trpage_util_h_
@ -26,7 +26,7 @@
TX_EXDECL class TX_CLDECL trpgUtil {
public:
enum {DoReport = 1<<0,DoCopy = 1<<1, DoTileOpt = 1<<2};
int merge(trpgr_Archive &inArch1,trpgr_Archive &inArch2,trpgwArchive &outArch, int flags = 0);
enum {DoReport = 1<<0,DoCopy = 1<<1, DoTileOpt = 1<<2};
int merge(trpgr_Archive &inArch1,trpgr_Archive &inArch2,trpgwArchive &outArch, int flags = 0);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -18,313 +18,342 @@
#define _txpage_write_h_
/* trpage_write.h
Classes that are used to write paging archives.
*/
Classes that are used to write paging archives.
*/
#include <trpage_sys.h>
#include <trpage_io.h>
#include <trpage_swap.h>
#include <trpage_read.h>
/* Geometry Stats
Used with a Geometry Helper to keep track of what go built.
{group:Archive Writing}
*/
Used with a Geometry Helper to keep track of what go built.
{group:Archive Writing}
*/
TX_EXDECL class TX_CLDECL trpgwGeomStats {
public:
trpgwGeomStats(void);
~trpgwGeomStats(void);
trpgwGeomStats(void);
~trpgwGeomStats(void);
int totalTri; // Total # of triangles
int totalTri; // Total # of triangles
int totalQuad; // Total # of quads
int totalQuad; // Total # of quads
// Add up to totalTri
int totalStripTri; // triangles in strips
int totalFanTri; // triangles in fans
int totalBagTri; // loose triangles
// Add up to totalTri
int totalStripTri; // triangles in strips
int totalFanTri; // triangles in fans
int totalBagTri; // loose triangles
int numStrip; // Number of distinct strips
int numFan; // Number of distinct fans
int numStrip; // Number of distinct strips
int numFan; // Number of distinct fans
int stripStat[15]; // Strip length stats
int fanStat[15]; // Fan length stats
int stripStat[15]; // Strip length stats
int fanStat[15]; // Fan length stats
int stripGeom; // Number of seperate trpgGeometry nodes for strips
int fanGeom; // Same for fans
int bagGeom; // Same for bags
int stripGeom; // Number of seperate trpgGeometry nodes for strips
int fanGeom; // Same for fans
int bagGeom; // Same for bags
int stateChanges; // Number of distinct material switches
int stateChanges; // Number of distinct material switches
// Helper functions
inline void AddStripStat(int val) { stripStat[MIN(14,val)]++; totalStripTri += val; totalTri += val; numStrip++;}
inline void AddFanStat(int val) { fanStat[MIN(14,val)]++; totalFanTri += val; totalTri += val; numFan++;}
inline void AddBagStat(int val) { totalBagTri += val; totalTri += val;}
// Helper functions
inline void AddStripStat(int val) { stripStat[MIN(14,val)]++; totalStripTri += val; totalTri += val; numStrip++;}
inline void AddFanStat(int val) { fanStat[MIN(14,val)]++; totalFanTri += val; totalTri += val; numFan++;}
inline void AddBagStat(int val) { totalBagTri += val; totalTri += val;}
inline void AddQuadStat(int val) { totalQuad += val; }
};
/* Geometry Helper
Collects up geometry and tries to form triangle strips, fans,
and groups of triangles.
Right now this looks for a very careful ordering. If that ordering
isn't there you won't get useful tristrips or fans. You can, however
use this class as a starting point and build something more akin
to the geometry builder in Performer.
{group:Archive Writing}
Collects up geometry and tries to form triangle strips, fans,
and groups of triangles.
Right now this looks for a very careful ordering. If that ordering
isn't there you won't get useful tristrips or fans. You can, however
use this class as a starting point and build something more akin
to the geometry builder in Performer.
{group:Archive Writing}
*/
TX_EXDECL class TX_CLDECL trpgwGeomHelper {
public:
trpgwGeomHelper(void);
virtual ~trpgwGeomHelper(void);
enum {UseDouble,UseFloat};
trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble);
void init(trpgWriteBuffer *,int dataType=UseDouble);
virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default)
virtual void Reset(void);
// Start/End polygon definition
virtual void StartPolygon(void);
virtual void EndPolygon(void);
virtual void ResetPolygon(void); // If you change your mind about the current poly
// Set the current state
// Note: Currently you *must* set all of these
virtual void SetColor(trpgColor &);
virtual void SetTexCoord(trpg2dPoint &);
virtual void AddTexCoord(trpg2dPoint &); // for multiple textures
virtual void SetNormal(trpg3dPoint &);
virtual void SetMaterial(int32);
virtual void AddMaterial(int32); // for multiple textures
// Pull the state info together and add a vertex
virtual void AddVertex(trpg3dPoint &);
trpgwGeomHelper(void);
virtual ~trpgwGeomHelper(void);
enum {UseDouble,UseFloat};
trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble);
void init(trpgWriteBuffer *,int dataType=UseDouble);
virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default)
virtual void Reset(void);
// Start/End polygon definition
virtual void StartPolygon(void);
virtual void EndPolygon(void);
virtual void ResetPolygon(void); // If you change your mind about the current poly
// Set the current state
// Note: Currently you *must* set all of these
virtual void SetColor(trpgColor &);
virtual void SetTexCoord(trpg2dPoint &);
virtual void AddTexCoord(trpg2dPoint &); // for multiple textures
virtual void SetNormal(trpg3dPoint &);
virtual void SetMaterial(int32);
virtual void AddMaterial(int32); // for multiple textures
// Pull the state info together and add a vertex
virtual void AddVertex(trpg3dPoint &);
// Dump whatever we're doing and move on
virtual void FlushGeom(void);
// Dump whatever we're doing and move on
virtual void FlushGeom(void);
// Get the Min and Max Z values
virtual void GetZMinMax(double &min,double &max);
// Get the Min and Max Z values
virtual void GetZMinMax(double &min,double &max);
// Get statistics for whatever we built
trpgwGeomStats *GetStats(void) { return &stats; }
// Get statistics for whatever we built
trpgwGeomStats *GetStats(void) { return &stats; }
protected:
int mode;
int dataType;
trpgWriteBuffer *buf;
int mode;
int dataType;
trpgWriteBuffer *buf;
/* Builds strips and fans from the triangle array.
We (TERREX) are assuming a certain ordering in our vertex array
because we do this optimization elsewhere. This won't work well
for anyone else. What you will need to do if you want good
performance is to implement a more generic form of this method.
All you should have to do is override Optimize(). You've
got the triangle arrays and a guarantee that the triangles
have the same material. All you really need is a decent fan/strip
algorithm.
*/
virtual void Optimize(void);
/* Builds strips and fans from the triangle array.
We (TERREX) are assuming a certain ordering in our vertex array
because we do this optimization elsewhere. This won't work well
for anyone else. What you will need to do if you want good
performance is to implement a more generic form of this method.
All you should have to do is override Optimize(). You've
got the triangle arrays and a guarantee that the triangles
have the same material. All you really need is a decent fan/strip
algorithm.
*/
virtual void Optimize(void);
// Reset Triangle arrays
virtual void ResetTri(void);
// Reset Triangle arrays
virtual void ResetTri(void);
// Collections of geometry
trpgGeometry strips,fans,bags;
// Collections of geometry
trpgGeometry strips,fans,bags;
// Temporary data arrays for triangles/quads
std::vector<int32> matTri;
std::vector<trpg2dPoint> tex;
std::vector<trpg3dPoint> norm,vert;
// Data arrays for a polygon
std::vector<int32> matPoly;
std::vector<trpg2dPoint> polyTex;
std::vector<trpg3dPoint> polyNorm,polyVert;
// Single points
std::vector<trpg2dPoint> tmpTex;
trpg3dPoint tmpNorm;
trpgColor tmpCol;
// Temporary data arrays for triangles/quads
std::vector<int32> matTri;
std::vector<trpg2dPoint> tex;
std::vector<trpg3dPoint> norm,vert;
// Data arrays for a polygon
std::vector<int32> matPoly;
std::vector<trpg2dPoint> polyTex;
std::vector<trpg3dPoint> polyNorm,polyVert;
// Single points
std::vector<trpg2dPoint> tmpTex;
trpg3dPoint tmpNorm;
trpgColor tmpCol;
// Geometry status built up as we go
trpgwGeomStats stats;
// Geometry status built up as we go
trpgwGeomStats stats;
// Keeps track of min and max z values
double zmin,zmax;
// Keeps track of min and max z values
double zmin,zmax;
};
/* Image Write Helper.
Used to manage textures being added to a TerraPage archive.
It can write Local and Tile Local textures and also manages
the names of External textures (but you have to write those yourself).
Used to manage textures being added to a TerraPage archive.
It can write Local and Tile Local textures and also manages
the names of External textures (but you have to write those yourself).
*/
TX_EXDECL class TX_CLDECL trpgwImageHelper {
public:
trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &);
virtual ~trpgwImageHelper(void);
trpgwImageHelper() {;};
trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &,bool separateGeoTypical);
// construction is really here
virtual void Init(trpgEndian ness,char *dir,trpgTexTable &,bool separateGeoTypical);
// Adds an entry to the texture table for an external texture
virtual bool AddExternal(char *name,int &texID,bool lookForExisting=true);
virtual ~trpgwImageHelper(void);
/* Adds an entry to the texture table for a local texture and
writes the data for that texture out to one of our texture
archive files.
*/
virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data,int &texID);
virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,int sizeZ,trpgTexture::ImageOrg org,bool isMipmap,char *data,int &texID);
// Adds an entry to the texture table for an external texture
virtual bool AddExternal(char *name,int &texID,bool lookForExisting=true);
/* Write a Tile Local texture out to one of our texture archive files.
Also creates a texture template, if necessary.
Caller is responsible for creating the Tile Local material and
placing it in the appropriate tile.
*/
virtual bool AddTileLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data, int &texID,trpgwAppAddress &addr);
virtual bool AddTileLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,int sizeZ,trpgTexture::ImageOrg org,bool isMipmap,char *data, int &texID,trpgwAppAddress &addr);
/* Adds an entry to the texture table for a local texture and
writes the data for that texture out to one of our texture
archive files.
*/
virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data,int &texID,bool deferWrite);
/* Sets the maximum advised length for a texture archive file.
Once the length is exceeded, the image write helper will move
on to the next tex file.
*/
virtual void SetMaxTexFileLength(int len);
/* Replaces texture table information for a local texture and
writes the data for that texture out to one of our texture
archive files.
Up to you to ensure data is appropriate for the texture.
*/
virtual bool ReplaceLocal(char *data,int &texID);
/* Texture archive files are managed by this class and will
be created as needed. This method will increment to
the next texture file.
Note: This may create more files than we really need.
*/
virtual bool IncrementTextureFile(void);
/* Write a Tile Local texture out to one of our texture archive files.
Also creates a texture template, if necessary.
Caller is responsible for creating the Tile Local material and
placing it in the appropriate tile.
*/
virtual bool AddTileLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data, int &texID,trpgwAppAddress &addr);
/* Close the current texture file and go on to one with the
given base name. This is used for regenerate.
*/
virtual bool DesignateTextureFile(int);
/* Sets the maximum advised length for a texture archive file.
Once the length is exceeded, the image write helper will move
on to the next tex file.
*/
virtual void SetMaxTexFileLength(int len);
// Flush current texture output files
virtual bool Flush(void);
/* Texture archive files are managed by this class and will
be created as needed. This method will increment to
the next texture file.
Note: This may create more files than we really need.
*/
virtual trpgwAppFile * IncrementTextureFile(bool geotyp);
/* Close the current texture file and go on to one with the
given base name. This is used for regenerate.
*/
virtual bool DesignateTextureFile(int);
// Flush current texture output files
virtual bool Flush(void);
// Get a new appendable file
virtual trpgwAppFile* GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse=false);
// Write the given texture data into one our local archives
bool WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr,bool geotyp=false);
// Merge block textable into a master.
protected:
// Write the given texture data into one our local archives
bool WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr);
trpgEndian ness;
char dir[1024];
trpgTexTable *texTable;
std::vector<int> texFileIDs;
trpgwAppFile *texFile;
int maxTexFileLen;
trpgEndian ness;
char dir[1024];
trpgTexTable *texTable;
std::vector<int> texFileIDs;
trpgwAppFile *texFile;
std::vector<int> geotypFileIDs;
trpgwAppFile *geotypFile;
bool separateGeoTypical;
int maxTexFileLen;
};
/* Paging Archive
This is a writeable paging archive.
It organizes where things get written and how.
{group:Archive Writing}
*/
This is a writeable paging archive.
It organizes where things get written and how.
{group:Archive Writing}
*/
TX_EXDECL class TX_CLDECL trpgwArchive : public trpgCheckable {
public:
// Tiles can be stored as individual files (External) or grouped together (Local)
typedef enum {TileLocal,TileExternal} TileMode;
// Tiles can be stored as individual files (External) or grouped together (Local)
enum TileMode {TileLocal,TileExternal,TileExternalSaved};
// Add data to an existing archive
trpgwArchive(char *baseDir,char *name,trpg2dPoint &ll,trpg2dPoint &ur);
// Start an archive from scratch.
trpgwArchive(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int version=2);
virtual ~trpgwArchive(void);
// real constructor work done in Init(...) now for quasi-virtual ctor action.
// Add data to an existing archive
trpgwArchive(char *baseDir,char *name,trpg2dPoint &ll,trpg2dPoint &ur, int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR);
virtual void Init(char *baseDir,char *name,trpg2dPoint &ll,trpg2dPoint &ur, int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR);
// Start an archive from scratch.
trpgwArchive(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR);
virtual void Init(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR);
// dummy constructor, does nothing so subclasses can have more control
trpgwArchive(int ) {;};
virtual ~trpgwArchive(void);
// Set the maximum length for a tile file (if using them)
// This is only a suggestion for when to stop appending
virtual void SetMaxTileFileLength(int len);
// Set the maximum length for a tile file (if using them)
// This is only a suggestion for when to stop appending
virtual void SetMaxTileFileLength(int len);
// Set functions. Have to fill all these out before writing
virtual bool SetHeader(const trpgHeader &);
virtual bool SetMaterialTable(const trpgMatTable &);
virtual bool SetTextureTable(const trpgTexTable &);
virtual bool SetModelTable(const trpgModelTable &);
virtual bool SetLightTable(const trpgLightTable &);
virtual bool SetRangeTable(const trpgRangeTable &);
virtual bool SetLabelPropertyTable(const trpgLabelPropertyTable &);
virtual bool SetSupportStyleTable(const trpgSupportStyleTable &);
virtual bool SetTextStyleTable(const trpgTextStyleTable &);
// Set functions. Have to fill all these out before writing
virtual bool SetHeader(const trpgHeader &);
virtual bool SetMaterialTable(const trpgMatTable &);
virtual bool SetTextureTable(const trpgTexTable &);
virtual bool SetModelTable(const trpgModelTable &);
virtual bool SetLightTable(const trpgLightTable &);
virtual bool SetRangeTable(const trpgRangeTable &);
virtual bool SetLabelPropertyTable(const trpgLabelPropertyTable &);
virtual bool SetSupportStyleTable(const trpgSupportStyleTable &);
virtual bool SetTextStyleTable(const trpgTextStyleTable &);
// Get functions. If we're doing a regenerate we need to get at these
virtual trpgHeader *GetHeader();
virtual trpgMatTable *GetMatTable();
virtual trpgTexTable *GetTextureTable();
virtual trpgModelTable *GetModelTable();
virtual trpgLightTable *GetLightTable();
virtual trpgRangeTable *GetRangeTable();
virtual trpgLabelPropertyTable *GetLabelPropertyTable();
virtual trpgTextStyleTable *GetTextStyleTable();
virtual trpgSupportStyleTable *GetSupportStyleTable();
// Get functions. If we're doing a regenerate we need to get at these
virtual trpgHeader *GetHeader();
virtual trpgMatTable *GetMatTable();
virtual trpgTexTable *GetTextureTable();
virtual trpgModelTable *GetModelTable();
virtual trpgLightTable *GetLightTable();
virtual trpgRangeTable *GetRangeTable();
virtual trpgLabelPropertyTable *GetLabelPropertyTable();
virtual trpgTextStyleTable *GetTextStyleTable();
virtual trpgSupportStyleTable *GetSupportStyleTable();
virtual bool IncrementTileFile(void);
virtual bool DesignateTileFile(int);
virtual bool IncrementTileFile(void);
virtual bool DesignateTileFile(int);
// Write functions.
// For now, the header is written last.
// Write functions.
// For now, the header is written last.
virtual bool OpenFile(const char *,const char *);
virtual void CloseFile(void);
virtual bool WriteHeader(void);
virtual bool CheckpointHeader(void);
virtual bool WriteTile(unsigned int,unsigned int,unsigned int,float zmin,float zmax,
const trpgMemWriteBuffer *,const trpgMemWriteBuffer *);
// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &);
bool isValid(void) const;
const char *getErrMess() const;
char* getDir(void){return dir;};
class TileFileEntry {
public:
int x,y,lod; // Identifying info for tile
float zmin,zmax;
int32 offset; // Offset into file
};
class TileFile {
public:
int id;
std::vector<TileFileEntry> tiles;
};
virtual bool OpenFile(const char *,const char *);
virtual void CloseFile(void);
virtual bool WriteHeader(void);
virtual bool CheckpointHeader(void);
virtual bool WriteTile(unsigned int,unsigned int,unsigned int,float zmin,float zmax,
const trpgMemWriteBuffer *,const trpgMemWriteBuffer *, int32& fileId, int32& fileOffset);
// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &);
bool isValid(void) const;
const char *getErrMess() const;
char* getDir(void){return dir;};
virtual trpgwImageHelper* GetNewWImageHelper(trpgEndian ness,char *dir,trpgTexTable &);
virtual trpgwAppFile* GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse=false);
virtual trpgr_Archive* GetArchiveReader() {return new trpgr_Archive();};
virtual int32 WriteHeaderData(const char *dataPtr,int32 length,FILE *filehandle);
virtual int32 GetMagicNumber() {return TRPG_MAGIC;};
protected:
// Set if we're adding to an existing archive
bool isRegenerate;
// Set if we're adding to an existing archive
bool isRegenerate;
// Used to keep track of which tiles are in which file
// Used to keep track of which tiles are in which file
class TileFileEntry {
public:
int x,y,lod; // Identifying info for tile
float zmin,zmax;
int32 offset; // Offset into file
};
class TileFile {
public:
int id;
std::vector<TileFileEntry> tiles;
};
trpgEndian ness,cpuNess;
int version;
// Fed in from the outside
char dir[1024]; // Directory where we're doing all this
trpgEndian ness,cpuNess;
int majorVersion, minorVersion;
// Fed in from the outside
char dir[1024]; // Directory where we're doing all this
// These are passed in
// These are passed in
trpgHeader header;
trpgMatTable matTable;
trpgTexTable texTable;
trpgModelTable modelTable;
trpgLightTable lightTable;
trpgRangeTable rangeTable;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
trpgHeader header;
trpgMatTable matTable;
trpgTexTable texTable;
trpgModelTable modelTable;
trpgLightTable lightTable;
trpgRangeTable rangeTable;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
trpgTileTable tileTable;
trpgTileTable tileTable;
int numX,numY,numLod;
TileMode tileMode;
int numX,numY,numLod;
TileMode tileMode;
trpgwAppFile *tileFile;
int tileFileCount;
trpgwAppFile *tileFile;
int tileFileCount;
std::vector<TileFile> tileFiles;
std::vector<TileFile> tileFiles;
int maxTileFileLen;
std::vector<TileFileEntry> externalTiles;
// This offset is used when we're adding to an existing archive
trpg2iPoint addOffset;
int maxTileFileLen;
FILE *fp;
// This offset is used when we're adding to an existing archive
trpg2iPoint addOffset;
bool firstHeaderWrite;
FILE *fp;
mutable char errMess[512];
bool firstHeaderWrite;
mutable char errMess[512];
};
#endif

View File

@ -18,16 +18,16 @@
#include <string.h>
/* trpage_writebuf.cpp
This source file contains the implementation of trpgMemWriteBuffer.
That is a subclass of trpgWriteBuffer, which implements an interface
definition for an object which can accept data to be written.
The Mem version is used to write (for example) a tile's worth of data.
That data can then be written to a file (or sent over the network).
You should not need to change this implementation. Simply sublcass
trpgWriteBuffer and implement all of the required methods. The
resulting class can then be used in all the places a trpgWriteBuffer
is required.
*/
This source file contains the implementation of trpgMemWriteBuffer.
That is a subclass of trpgWriteBuffer, which implements an interface
definition for an object which can accept data to be written.
The Mem version is used to write (for example) a tile's worth of data.
That data can then be written to a file (or sent over the network).
You should not need to change this implementation. Simply sublcass
trpgWriteBuffer and implement all of the required methods. The
resulting class can then be used in all the places a trpgWriteBuffer
is required.
*/
#include <trpage_io.h>
#include <trpage_swap.h>
@ -39,158 +39,158 @@
// Constructor
trpgMemWriteBuffer::trpgMemWriteBuffer(trpgEndian in_ness)
{
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
data = NULL;
curLen = totLen = 0;
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
data = NULL;
curLen = totLen = 0;
}
// Destructor
trpgMemWriteBuffer::~trpgMemWriteBuffer()
{
if (data)
delete [] data;
data = NULL;
if (data)
delete [] data;
data = NULL;
}
/* Length()
Return the length of the given buffer.
*/
Return the length of the given buffer.
*/
int trpgMemWriteBuffer::length() const
{
return curLen;
return curLen;
}
/* getData()
Return a pointer to the memory buffer.
*/
Return a pointer to the memory buffer.
*/
const char *trpgMemWriteBuffer::getData() const
{
return data;
return data;
}
/* Length()
Set the maximum buffer length.
*/
Set the maximum buffer length.
*/
void trpgMemWriteBuffer::setLength(unsigned int len)
{
if ((int)len > totLen) {
char *old_data = data;
int oldLen = totLen;
totLen = 2*len;
data = new char[totLen];
if ((int)len > totLen) {
char *old_data = data;
int oldLen = totLen;
totLen = 2*len;
data = new char[totLen];
if (old_data) {
memcpy(data,old_data,oldLen);
delete [] old_data;
}
}
if (old_data) {
memcpy(data,old_data,oldLen);
delete [] old_data;
}
}
}
/* append()
Append the given data to our buffer.
*/
Append the given data to our buffer.
*/
void trpgMemWriteBuffer::append(unsigned int len,const char *val)
{
if (len == 0) return;
setLength(curLen+len);
memcpy(&data[curLen],val,len);
curLen += len;
if (len == 0) return;
setLength(curLen+len);
memcpy(&data[curLen],val,len);
curLen += len;
}
/* set()
Set a specific portion of the buffer to a given value.
*/
Set a specific portion of the buffer to a given value.
*/
void trpgMemWriteBuffer::set(unsigned int pos,unsigned int len,const char *val)
{
if (len == 0) return;
if (pos+len > (unsigned int)curLen) return;
if (len == 0) return;
if (pos+len > (unsigned int)curLen) return;
memcpy(&data[pos],val,len);
memcpy(&data[pos],val,len);
}
/* --- replacement virtual functions --- */
/* Reset()
Drop whatever's being stored.
*/
Drop whatever's being stored.
*/
void trpgMemWriteBuffer::Reset()
{
curLen = 0;
curLen = 0;
}
// Add(Int32)
void trpgMemWriteBuffer::Add(int32 val)
{
if (ness != cpuNess)
val = trpg_byteswap_int(val);
append(sizeof(int32),(const char *)&val);
if (ness != cpuNess)
val = trpg_byteswap_int(val);
append(sizeof(int32),(const char *)&val);
}
// Add(int64)
void trpgMemWriteBuffer::Add(int64 val)
{
if (ness != cpuNess)
val = trpg_byteswap_llong(val);
append(sizeof(int64),(const char *)&val);
if (ness != cpuNess)
val = trpg_byteswap_llong(val);
append(sizeof(int64),(const char *)&val);
}
// Add(string)
// [len] [value...]
void trpgMemWriteBuffer::Add(const char *val)
{
int32 len = (val ? strlen(val) : 0),vlen = len;
if (ness != cpuNess)
vlen = trpg_byteswap_int(vlen);
append(sizeof(int32),(const char *)&vlen);
append(len,val);
int32 len = (val ? strlen(val) : 0),vlen = len;
if (ness != cpuNess)
vlen = trpg_byteswap_int(vlen);
append(sizeof(int32),(const char *)&vlen);
append(len,val);
}
// Add(std::string)
void trpgMemWriteBuffer::Add(std::string &val)
{
Add(val.c_str());
Add(val.c_str());
}
// Add(float32)
void trpgMemWriteBuffer::Add(float32 val)
{
char cval[4];
if (ness != cpuNess)
trpg_byteswap_float_to_4bytes(val,cval);
else
memcpy(cval,&val,4);
char cval[4];
if (ness != cpuNess)
trpg_byteswap_float_to_4bytes(val,cval);
else
memcpy(cval,&val,4);
append(sizeof(float32),cval);
append(sizeof(float32),cval);
}
// Add(float64)
void trpgMemWriteBuffer::Add(float64 val)
{
char cval[8];
if (ness != cpuNess)
trpg_byteswap_double_to_8bytes(val,cval);
else
memcpy(cval,&val,8);
char cval[8];
if (ness != cpuNess)
trpg_byteswap_double_to_8bytes(val,cval);
else
memcpy(cval,&val,8);
append(sizeof(float64),cval);
append(sizeof(float64),cval);
}
// Add(int8)
void trpgMemWriteBuffer::Add(uint8 val)
{
// No byte swapping needed
append(sizeof(uint8),(const char *)&val);
// No byte swapping needed
append(sizeof(uint8),(const char *)&val);
}
//#if (bool != int32)
// Add(bool)
void trpgMemWriteBuffer::Add(bool val)
{
uint8 ival;
uint8 ival;
ival = (val ? 1 : 0);
Add(ival);
ival = (val ? 1 : 0);
Add(ival);
}
//#endif
@ -198,127 +198,169 @@ void trpgMemWriteBuffer::Add(bool val)
// Add(trpgDiskRef)
void trpgMemWriteBuffer::Add(trpgDiskRef val)
{
if (ness != cpuNess)
val = trpg_byteswap_llong(val);
if (ness != cpuNess)
val = trpg_byteswap_llong(val);
append(sizeof(trpgDiskRef),(const char *)&val);
append(sizeof(trpgDiskRef),(const char *)&val);
}
#endif
// Add(trpgToken)
void trpgMemWriteBuffer::Add(trpgToken val)
{
if (ness != cpuNess)
val = trpg_byteswap_short(val);
if (ness != cpuNess)
val = trpg_byteswap_short(val);
append(sizeof(trpgToken),(const char *)&val);
append(sizeof(trpgToken),(const char *)&val);
}
// Add(tx2iPoint)
void trpgWriteBuffer::Add(const trpg2iPoint &val)
{
Add((int32)val.x);
Add((int32)val.y);
Add((int32)val.x);
Add((int32)val.y);
}
// Add(tx2dPoint)
void trpgWriteBuffer::Add(const trpg2dPoint &val)
{
Add((float64)val.x);
Add((float64)val.y);
Add((float64)val.x);
Add((float64)val.y);
}
// Add(trpg3dPoint)
void trpgWriteBuffer::Add(const trpg3dPoint &val)
{
Add((float64)val.x);
Add((float64)val.y);
Add((float64)val.z);
Add((float64)val.x);
Add((float64)val.y);
Add((float64)val.z);
}
// Add(trpgColor)
void trpgWriteBuffer::Add(const trpgColor &val)
{
Add(val.red);
Add(val.green);
Add(val.blue);
Add(val.red);
Add(val.green);
Add(val.blue);
}
// Add(std::string)
void trpgWriteBuffer::Add(const std::string &val)
{
Add(val.c_str());
Add(val.c_str());
}
/* Push()
Starts defining a new object.
Need to keep track of where length goes.
*/
Starts defining a new object.
Need to keep track of where length goes.
*/
void trpgMemWriteBuffer::Begin(trpgToken tok)
{
Add(tok);
lengths.push_back(curLen);
Add((int32)0);
Add(tok);
lengths.push_back(curLen);
Add((int32)0);
}
/* Push()
Pushes a level on the stack. For defining children.
*/
Pushes a level on the stack. For defining children.
*/
void trpgMemWriteBuffer::Push()
{
Add((trpgToken)TRPG_PUSH);
Add((trpgToken)TRPG_PUSH);
}
/* Pop()
Pops a level off the "stack".
*/
Pops a level off the "stack".
*/
void trpgMemWriteBuffer::Pop()
{
Add((trpgToken)TRPG_POP);
Add((trpgToken)TRPG_POP);
}
/* Will take out a pop from the end of the buffer, if there is one */
bool trpgMemWriteBuffer::UnPop()
{
//Check to see if there is a pop token ant the end
trpgToken tk;
memcpy(&tk, &data[curLen - sizeof(trpgToken)], sizeof(trpgToken));
if(tk == TRPG_POP)
{
curLen -= sizeof(trpgToken);
return true;
}
else
return false;
}
/* Will take out a push from the end of the buffer, if there is one */
bool trpgMemWriteBuffer::UnPush()
{
//Check to see if there is a push token ant the end
trpgToken tk;
memcpy(&tk, &data[curLen - sizeof(trpgToken)], sizeof(trpgToken));
if(tk == TRPG_PUSH)
{
curLen -= sizeof(trpgToken);
return true;
}
else
return false;
}
/* End()
Finished defining an object.
Write the length out where appropriate.
*/
Finished defining an object.
Write the length out where appropriate.
*/
void trpgMemWriteBuffer::End()
{
if (lengths.size() == 0)
// Note: say something clever here
return;
if (lengths.size() == 0)
// Note: say something clever here
return;
int id = lengths.size()-1;
int32 len = curLen - lengths[id];
int32 rlen = len-sizeof(int32);
if (ness != cpuNess)
rlen = trpg_byteswap_int(rlen);
set(curLen - len,sizeof(int32),(const char *)&rlen);
lengths.resize(id);
int id = lengths.size()-1;
int32 len = curLen - lengths[id];
int32 rlen = len-sizeof(int32);
if (ness != cpuNess)
rlen = trpg_byteswap_int(rlen);
set(curLen - len,sizeof(int32),(const char *)&rlen);
lengths.resize(id);
}
/* Appendable File
This class is used as a simple appendable file. It's used
for dumping tile and texture (or most anything) into.
This class is used as a simple appendable file. It's used
for dumping tile and texture (or most anything) into.
*/
trpgwAppFile::trpgwAppFile(trpgEndian inNess,const char *fileName)
trpgwAppFile::trpgwAppFile(trpgEndian inNess,const char *fileName,bool reuse)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
Init(inNess,fileName,reuse);
}
if (!(fp = fopen(fileName,"wb")))
return;
void trpgwAppFile::Init(trpgEndian inNess,const char *fileName,bool reuse)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
lengthSoFar = 0;
valid = true;
if (reuse==false) {
if (!(fp = fopen(fileName,"wb")))
return;
lengthSoFar = 0;
valid = true;
} else {
if (!(fp = fopen(fileName,"ab")))
return;
// ftell is still zero, dammit. Arg.
fseek(fp,0,SEEK_END);
lengthSoFar = ftell(fp);
valid = true;
}
}
trpgwAppFile::~trpgwAppFile()
{
if (fp)
fclose(fp);
valid = false;
if (fp)
fclose(fp);
valid = false;
}
// Return the amount of data written so far (in total)
@ -330,87 +372,87 @@ int trpgwAppFile::GetLengthWritten()
// Append the given buffer to our appendable file
bool trpgwAppFile::Append(const trpgMemWriteBuffer *buf1,const trpgMemWriteBuffer *buf2)
{
if (!isValid()) return false;
if (!isValid()) return false;
// Get the total length
int totLen = buf1->length() + (buf2 ? buf2->length() : 0);
// Get the total length
int totLen = buf1->length() + (buf2 ? buf2->length() : 0);
// Write the length out
if (fwrite(&totLen,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Write the length out
if (fwrite(&totLen,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Write the data out
const char *data = buf1->getData();
int len = buf1->length();
if (fwrite(data,sizeof(char),len,fp) != (unsigned int)len) {
valid = false;
return false;
}
if (buf2) {
data = buf2->getData();
len = buf2->length();
if (fwrite(data,sizeof(char),len,fp) != (unsigned int)len) {
valid = false;
return false;
}
}
// Write the data out
const char *data = buf1->getData();
unsigned int len = buf1->length();
if (fwrite(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
if (buf2) {
data = buf2->getData();
len = buf2->length();
if (fwrite(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
}
lengthSoFar += totLen;
lengthSoFar += totLen;
return true;
return true;
}
// Append the given raw data to our appendable file
bool trpgwAppFile::Append(const char *data,int size)
{
if (!isValid()) return false;
if (!isValid()) return false;
if (!data)
return false;
if (!data)
return false;
// Write the length out
if (fwrite(&size,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Write the length out
if (fwrite(&size,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Write the data out
if (fwrite(data,sizeof(char),size,fp) != (unsigned int)size) {
valid = false;
return false;
}
// Write the data out
if (fwrite(data,sizeof(char),size,fp) != (size_t)size) {
valid = false;
return false;
}
lengthSoFar += size;
lengthSoFar += size;
return true;
return true;
}
// Flushes the current tile file
bool trpgwAppFile::Flush()
{
// Flush the File *
if (fp)
fflush(fp);
// Flush the File *
if (fp)
fflush(fp);
return true;
return true;
}
// Return the current file position
int64 trpgwAppFile::Pos() const
{
if (!isValid())
return 0;
// Note: This means an appendable file is capped at 2GB
long pos = ftell(fp);
if (!isValid())
return 0;
// Note: This means an appendable file is capped at 2GB
long pos = ftell(fp);
return pos;
return pos;
}
// Validity check
bool trpgwAppFile::isValid() const
{
return valid;
return valid;
}