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",
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d",
archive->getDir(),
lod,
x,
y,
archive->getId()
);
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,17 +179,154 @@ 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();
if(majorVersion == 2 && minorVersion >= 1)
{
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)
{
ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "'subtile' filename children parsing failed " << std::endl;
return ReadResult::ERROR_IN_READING_FILE;
}
const trpgHeader* header = archive->GetHeader();
trpgHeader::trpgTileType tileType;
header->GetTileOriginType(tileType);
TXPArchive::TileLocationInfo plInfo;
plInfo.x = x;
plInfo.y = y;
plInfo.lod = lod;
TXPArchive::TileInfo parentInfo;
archive->getTileInfo(plInfo,parentInfo);
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;
osg::ref_ptr<osg::Node> tileContent = getTileContent(info, loc, archive, childrenChildLoc);
tileContent->setName("TileContent");
if(childrenChildLoc.size() > 0)
{
std::string childInfoStr;
createChildrenLocationString(childrenChildLoc, childInfoStr);
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::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());
}
}
}
else
{
int sizeX, sizeY;
archive->getLODSize(lod+1,sizeX,sizeY);
@ -143,7 +349,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
if (!archive->getTileInfo(tileX,tileY,tileLOD,info))
continue;
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive);
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive, childrenLoc);
tileContent->setName("TileContent");
@ -155,12 +361,22 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
tileLOD,
tileX,
tileY,
archive->getId()
);
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;
// 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);
@ -206,15 +422,136 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
}
}
}
//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,10 +616,10 @@ 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 ):
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)
{
@ -305,19 +642,24 @@ 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);
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)
_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;
@ -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;
if (GetTexMapEntry(i).get())
return true;
trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable);
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.
@ -358,28 +398,30 @@ bool TXPArchive::loadTexture(int i)
osg::notify(osg::WARN) << "TrPageArchive::LoadMaterials() error: "
<< "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
@ -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;
@ -544,8 +587,10 @@ void trim(std::string& str)
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;
@ -560,7 +605,7 @@ bool TXPArchive::loadTextStyles()
std::string line;
while (std::getline(fmapfile,line))
{
unsigned int ix = line.find_first_of('=');
std::string::size_type ix = line.find_first_of('=');
if (ix != std::string::npos)
{
std::string fontname = line.substr(0,ix);
@ -581,21 +626,24 @@ bool TXPArchive::loadTextStyles()
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;
if ( !fontName )
continue;
std::string fontfilename = fontmap[*fontName];
if (!fontfilename.length()) fontfilename = "arial.ttf";
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)
@ -610,7 +658,7 @@ bool TXPArchive::loadTextStyles()
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 );
}
}
}
@ -618,16 +666,16 @@ bool TXPArchive::loadTextStyles()
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,58 +685,102 @@ 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;
info.center.set(
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),
loc.zmin
),
osg::Vec3(
info.center.x()+(size.x/2.f),
info.center.y()+(size.y/2.f),
loc.zmax
)
);
info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3;
return true;
}
bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info)
{
if(_majorVersion == 2 && _minorVersion >=1)
{
// Version 2.1
// Tile table contain only lod 0
if(lod > 0)
return false;
}
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
);
info.bbox.set(
osg::Vec3(
info.center.x()-(size.x/2.f),
info.center.y()-(size.y/2.f),
minz
),
osg::Vec3(
info.center.x()+(size.x/2.f),
info.center.y()+(size.y/2.f),
maxz
)
);
info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3;
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,
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);
return true;
}
class ModelVisitor : public osg::NodeVisitor
{
TXPArchive* _archive;
int _x;
int _y;
int _lod;
TXPArchive::TileLocationInfo _tileInfo;
// int _x;
// int _y;
// int _lod;
public:
ModelVisitor(TXPArchive* archive, int x, int y, int lod):
ModelVisitor(TXPArchive* archive, const TXPArchive::TileLocationInfo& loc):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_archive(archive), _x(x), _y(y), _lod(lod)
_archive(archive), _tileInfo(loc)
{
}
@ -712,8 +804,8 @@ public:
offset[0] -= bbox._min[0];
offset[1] -= bbox._min[1];
trpg2dPoint offsetXY, tileID(_x,_y);
int divider = (0x01 << _lod);
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;
@ -729,12 +821,14 @@ public:
osg::Group* TXPArchive::getTileContent(
int x, int y, int lod,
const TileLocationInfo& loc,
double realMinRange,
double realMaxRange,
double usedMaxRange,
osg::Vec3& tileCenter)
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))
{
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

@ -68,7 +68,6 @@ public:
// 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);
@ -83,13 +82,22 @@ public:
// 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; }
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);
void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude,int handle);
int getNumLightAttributes() { return _lights.size(); }
int getNumLightAttributes()
{
return _lights.size();
}
// Get light attrib
inline DeferredLightAttribute& getLightAttribute(unsigned int i)
@ -108,7 +116,20 @@ public:
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)
@ -143,22 +164,41 @@ public:
// Returns global texture
inline osg::Texture2D* getGlobalTexture(int id)
{
return _textures[id].get();
return GetTexMapEntry(id).get();
}
// Returns scenegraph representing the Tile
osg::Group* getTileContent(
// 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);
osg::Vec3& tileCenter,
std::vector<TXPArchive::TileLocationInfo>& childInfoList);
// 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:
// Destructor
@ -178,26 +218,41 @@ protected:
osg::ref_ptr<TXPParser> _parser;
// Textures
std::vector< osg::ref_ptr<osg::Texture2D> > _textures;
typedef std::map<int,osg::ref_ptr<osg::Texture2D> > OSGTexMapType;
OSGTexMapType _texmap;
void SetTexMap(int key,osg::ref_ptr<osg::Texture2D> ref);
osg::ref_ptr<osg::Texture2D> GetTexMapEntry(int key);
// States
std::vector< osg::ref_ptr<osg::StateSet> > _gstates;
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
std::vector< osg::ref_ptr<osg::Node> > _models;
typedef std::map<int,osg::ref_ptr<osg::Node> > OSGModelsMapType;
OSGModelsMapType _models;
// Light attributes vector
std::vector<DeferredLightAttribute> _lights;
std::map<int, DeferredLightAttribute> _lights;
// Text styles / Fonts
std::vector< osg::ref_ptr<osgText::Font> > _fonts;
std::map<int, osg::ref_ptr<osgText::Font> > _fonts;
// Text colors
std::vector< osg::Vec4 > _fcolors;
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):
@ -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;
@ -275,6 +319,7 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod)
else
{
_nodesToAdd.push_back(pagedLOD);
return pagedLOD;
}
}

View File

@ -45,6 +45,7 @@
namespace txp
{
class TXPNode : public osg::Group
{
public:
@ -68,7 +69,10 @@ public:
TXPArchive* getArchive();
void setArchive(TXPArchive* archive) { _archive = archive; }
void setArchive( TXPArchive* archive )
{
_archive = archive;
}
virtual osg::BoundingSphere computeBound() const;
@ -76,11 +80,11 @@ 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;

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);
}

View File

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

View File

@ -6,12 +6,12 @@
#include <osg/Geode>
#include <osg/Billboard>
#include <osg/Matrix>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osg/CullFace>
#include <osg/Light>
#include <osg/Notify>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/PagedLOD>
#include <osgSim/LightPointNode>
#include <osg/Point>
@ -23,10 +23,10 @@
#include "TXPArchive.h"
#include "TileMapper.h"
#include <sstream>
using namespace txp;
#include <sstream>
static osg::ApplicationUsageProxy TXP_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TXP_DEFAULT_MAX_ANISOTROPY \"<value> [<value>]\"","1.0 | 2.0 | 4.0 | 8.0 | 16.0");
TXPParser::TXPParser():
@ -41,9 +41,11 @@ _layerGeode(0),
_defaultMaxAnisotropy(1.0f),
_realMinRange(0.0),
_realMaxRange(0.0),
_usedMaxRange(0.0)
_usedMaxRange(0.0),
_childRefCB(0)
{
AddCallback(TRPG_ATTACH, new attachRead(this));
AddCallback(TRPG_CHILDREF, new childRefRead(this));
AddCallback(TRPG_GEOMETRY, new geomRead(this));
AddCallback(TRPG_GROUP, new groupRead(this));
AddCallback(TRPG_LOD, new lodRead(this));
@ -54,6 +56,8 @@ _usedMaxRange(0.0)
AddCallback(TRPG_LABEL, new labelRead(this));
AddCallback(TRPGTILEHEADER, new tileHeaderRead(this));
_childRefCB = dynamic_cast<childRefRead *>(GetCallback(TRPG_CHILDREF));
if (getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY"))
{
_defaultMaxAnisotropy = atof(getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY"));
@ -67,16 +71,20 @@ TXPParser::~TXPParser()
osg::Group *TXPParser::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)
{
if (_archive == 0) return NULL;
if (_archive == 0)
return NULL;
if(_childRefCB)
_childRefCB->Reset();
_root = new osg::Group();
_currentTop = _root.get();
_materials = &materials;
_materialMap = &materials;
_localMaterials.clear();
_models = &models;
@ -116,8 +124,10 @@ void TXPParser::replaceTileLod(osg::Group* group)
if (loLOD && hiLOD)
{
osg::Group *g = dynamic_cast<osg::Group*>(hiLOD->getChild(0));
if (!g) return;
if (g->getNumChildren()) return;
if (!g)
return;
if (g->getNumChildren())
return;
_tileCenter = loLOD->getCenter();
@ -128,19 +138,38 @@ void TXPParser::replaceTileLod(osg::Group* group)
}
}
unsigned int TXPParser::GetNbChildrenRef() const
{
if(_childRefCB)
return _childRefCB->GetNbChildrenRef();
else
return 0;
}
const trpgChildRef* TXPParser::GetChildRef(unsigned int idx) const
{
if(_childRefCB)
return _childRefCB->GetChildRef(idx);
else
return 0;
}
bool TXPParser::StartChildren(void * /*in*/)
{
bool pushParent = true;
if (_underBillboardSubgraph )
{
if (_numBillboardLevels > 0) pushParent = false;
if (_numBillboardLevels > 0)
pushParent = false;
_numBillboardLevels++;
}
else
if (_underLayerSubgraph)
{
if (_numLayerLevels > 0) pushParent = false;
if (_numLayerLevels > 0)
pushParent = false;
_numLayerLevels++;
}
if (pushParent)
@ -199,7 +228,9 @@ class FindEmptyGroupsVisitor : public osg::NodeVisitor
{
public:
FindEmptyGroupsVisitor(osg::NodeList& nl):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _nl(nl) {};
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _nl(nl)
{
}
virtual void apply(osg::Group& group)
{
@ -225,13 +256,15 @@ void TXPParser::removeEmptyGroups()
for (unsigned int i = 0; i < nl.size(); i++)
{
osg::Node* node = nl[i].get();
if (node == NULL) continue;
if (node == NULL)
continue;
osg::Node::ParentList parents = node->getParents();
for (unsigned int j = 0; j < parents.size(); j++)
{
osg::Group* parent = parents[j];
if (parent) parent->removeChild(node);
if (parent)
parent->removeChild(node);
}
}
}
@ -288,12 +321,19 @@ osg::Geode* TXPParser::createBoundingBox(int x,int y, int lod)
void TXPParser::loadLocalMaterials()
{
bool separateGeo = false;
int majorVer,minorVer;
this->getArchive()->GetVersion(majorVer,minorVer);
if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) {
separateGeo = true;
}
// new to 2.0 LOCAL materials
trpgrImageHelper image_helper(
_archive->GetEndian(),
_archive->getDir(),
*_archive->GetMaterialTable(),
*_archive->GetTexTable()
*_archive->GetTexTable(),
separateGeo
);
trpgTileHeader* tile_head = getTileHeaderRef();
@ -313,8 +353,8 @@ void TXPParser::loadLocalMaterials()
trpgLocalMaterial locmat;
tile_head->GetLocalMaterial(i,locmat);
const trpgMaterial* mat;
const trpgTexture *tex;
const trpgMaterial* mat = NULL;
const trpgTexture *tex = NULL;
int32 size;
image_helper.GetImageInfoForLocalMat(&locmat, &mat,&tex,size);
@ -477,7 +517,8 @@ bool TXPParser::requestModel(int ix)
void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgLod lod;
if (!lod.Read(buf)) return NULL;
if (!lod.Read(buf))
return NULL;
// Pull out the LOD data we'll need
trpg3dPoint center;
@ -542,7 +583,8 @@ void* tileHeaderRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgModelRef model;
if (!model.Read(buf)) return NULL;
if (!model.Read(buf))
return NULL;
// Get the matrix and pfNode for the model
int modelID;
@ -556,11 +598,8 @@ void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
(float)mat[12],(float)mat[13],(float)mat[14],(float)mat[15]
);
// Note: Array check before you do this
osg::Node *osg_Model = NULL;
std::vector<osg::ref_ptr<osg::Node> >*modelList = _parse->getModels();
if( modelList->size() > size_t(modelID) )
{
std::map<int,osg::ref_ptr<osg::Node> >*modelList = _parse->getModels();
osg_Model = (*modelList)[modelID].get();
if (osg_Model==NULL)
@ -581,7 +620,6 @@ void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
_parse->setCurrentNode(scs);
_parse->getCurrTop()->addChild(scs);
}
}
return (void *) 1;
}
@ -594,7 +632,8 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
// Read in the txp billboard
trpgBillboard bill;
if (!bill.Read(buf)) return NULL;
if (!bill.Read(buf))
return NULL;
if (_parse->underBillboardSubgraph())
{
@ -626,9 +665,11 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgGroup group;
if (!group.Read(buf)) return NULL;
if (!group.Read(buf))
return NULL;
if (_parse->underLayerSubgraph()) return (void*)1;
if (_parse->underLayerSubgraph())
return (void*)1;
osg::ref_ptr<GeodeGroup> osgGroup = new GeodeGroup();
_parse->setCurrentNode(osgGroup.get());
@ -644,7 +685,8 @@ void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgAttach group;
if (!group.Read(buf)) return NULL;
if (!group.Read(buf))
return NULL;
// Create a new group
osg::ref_ptr<osg::Group> osgGroup = new osg::Group();
@ -653,6 +695,27 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
return (void*)1;
}
void* childRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
// This object contribute nothing to the scenegraph, except
// where the children tile should connect.
// It only contain location info of the children tile
childRefList.push_back(trpgChildRef());
trpgReadWriteable& obj = childRefList.back();
if(obj.Read(buf))
return &obj;
else
return 0;
}
void childRefRead::Reset()
{
childRefList.clear();
}
//----------------------------------------------------------------------------
//
// light Reader Class
@ -661,7 +724,8 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgLight light;
if (!light.Read(buf)) return NULL;
if (!light.Read(buf))
return NULL;
int attr_index;
light.GetAttrIndex(attr_index);
@ -729,18 +793,12 @@ void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgLayer group;
if (!group.Read(buf)) return NULL;
if (!group.Read(buf))
return NULL;
#if 0
osg::Group* osgGroup = new osg::Group;
_parse->setCurrentNode(osgGroup);
_parse->getCurrTop()->addChild(osgGroup);
_parse->addLayer(osgGroup);
if (_parse->underLayerSubgraph())
return (void*)1;
#else
if (_parse->underLayerSubgraph()) return (void*)1;
osg::ref_ptr<GeodeGroup> layer = new GeodeGroup;
_parse->setLayerGeode(layer->getGeode());
@ -749,7 +807,6 @@ void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
_parse->getCurrTop()->addChild(layer.get());
return (void *)1;
#endif
}
//----------------------------------------------------------------------------
@ -760,10 +817,12 @@ void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgLabel label;
if (!label.Read(buf)) return NULL;
if (!label.Read(buf))
return NULL;
const std::string *labelText = label.GetText();
if (!labelText) return (void*)1;
if (!labelText)
return (void*)1;
osg::Vec3 pos(label.GetLocation().x, label.GetLocation().y, label.GetLocation().z);
@ -772,7 +831,7 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Text
std::ostringstream os;
unsigned int nl;
std::string::size_type nl;
std::string lb = *labelText;
while ( (nl=lb.find_first_of('\\')) != std::string::npos)
{
@ -781,7 +840,8 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
case 'n':
lb.erase(0,nl+2);
if (sub.length()) os << sub << std::endl;
if (sub.length())
os << sub << std::endl;
break;
case 't':
lb.erase(0,nl+2);
@ -794,7 +854,8 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
}
}
if (lb.length()) os << lb;
if (lb.length())
os << lb;
text->setText(os.str());
// Position
@ -822,10 +883,12 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
if (labelProperty)
{
const trpgTextStyleTable *textStyleTable = _parse->getArchive()->GetTextStyleTable();
if (!textStyleTable) return (void*)1;
if (!textStyleTable)
return (void*)1;
const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(labelProperty->GetFontStyle());
if (!textStyle) return (void*)1;
if (!textStyle)
return (void*)1;
// Size
text->setCharacterSize(textStyle->GetCharacterSize()*label.GetScale()*2);
@ -1068,7 +1131,8 @@ public:
_im.invert(_m);
}
virtual ~TransformFunctor() {}
virtual ~TransformFunctor()
{}
virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
{
@ -1104,7 +1168,8 @@ public:
void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgGeometry geom;
if (!geom.Read(buf)) return NULL;
if (!geom.Read(buf))
return NULL;
// Get the necessary info out of the geom
trpgGeometry::PrimType primType;
@ -1251,9 +1316,10 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
_parse->loadMaterial(matId);
tmp_ss = (*_parse->getMaterials())[matId];
}
if(sset.valid())
if((sset!=0L) && sset.valid())
{
if(tmp_ss.valid())
{
if(tmp_ss.valid()){
osg::StateAttribute* texenv0 = tmp_ss->getTextureAttribute(0,osg::StateAttribute::TEXENV);
if(texenv0)
sset->setTextureAttribute(n_mat,texenv0);
@ -1420,11 +1486,6 @@ namespace
internalFormat = GL_LUMINANCE_ALPHA;
pixelFormat = GL_LUMINANCE_ALPHA;
break;
case trpgTexture::trpg_FXT1:
case trpgTexture::trpg_Filler:
case trpgTexture::trpg_RGBX: // MCM
case trpgTexture::trpg_Unknown:
break;
case trpgTexture::trpg_DDS:
case trpgTexture::trpg_DXT1:
if(depth == 3)
@ -1460,6 +1521,16 @@ namespace
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
break;
case trpgTexture::trpg_MCM5:
case trpgTexture::trpg_MCM6R:
case trpgTexture::trpg_MCM6A:
case trpgTexture::trpg_MCM7RA:
case trpgTexture::trpg_MCM7AR:
case trpgTexture::trpg_FXT1:
case trpgTexture::trpg_Filler:
case trpgTexture::trpg_RGBX: // MCM
case trpgTexture::trpg_Unknown:
break;
}
}
}

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
@ -117,13 +118,16 @@ public:
}
// Gets the archive
inline TXPArchive* getArchive() { return _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); }
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;
}
// 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;
inline void setCurrentNode(osg::Node* node) { _currentNode = node; }
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;
@ -343,6 +366,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,7 +77,8 @@ void TileMapper::apply(osg::Group& node)
return;
}
if (isCulled(node)) return;
if (isCulled(node))
return;
// push the culling mode.
pushCurrentMask();
@ -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();
@ -187,7 +197,6 @@ 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);
@ -201,11 +210,8 @@ 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();
}
@ -360,11 +366,14 @@ 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();
@ -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())
@ -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;
}
@ -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

@ -30,6 +30,8 @@
trpgCheckable::trpgCheckable()
{
valid = false;
handle = -1;
writeHandle = false;
}
trpgCheckable::~trpgCheckable()
{

View File

@ -105,8 +105,9 @@ bool trpgMatTable1_0::Read(trpgReadBuffer &buf)
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];
AddMaterial(baseMat,false);
trpgMaterial newMat = baseMat;
newMat.SetNumTexture(shortMat.texids.size());
for (j=0;j<shortMat.texids.size();j++) {
int texId;
@ -128,11 +129,13 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
// 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];
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;
@ -145,6 +148,7 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
sMat.texids.push_back(texId);
sMat.baseMat = i;
}
i++;
}
// Write the 1.0 material table
@ -154,7 +158,7 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
// Write the short materials
buf.Begin(TRPGSHORTMATTABLE);
for (i=0;i<(int)shortMats.size();i++) {
for (i=0;i<static_cast<int>(shortMats.size());i++) {
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
@ -165,9 +169,13 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
buf.End();
// Write the regular materials
buf.Add(numTable*numMat);
for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = matTables[i];
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);
@ -227,11 +235,12 @@ bool trpgTexTable1_0::Read(trpgReadBuffer &buf)
try {
buf.Get(numTex);
texList.resize(numTex);
for (unsigned int i=0;i<(unsigned int)numTex;i++) {
//texList.resize(numTex);
for (int i=0;i<numTex;i++) {
trpgTexture1_0 tex1_0;
tex1_0.Read(buf);
texList[i] = tex1_0;
AddTexture(tex1_0);
//texList[i] = tex1_0;
}
}
catch (...) {
@ -250,11 +259,13 @@ bool trpgTexTable1_0::Write(trpgWriteBuffer &buf)
return false;
buf.Begin(TRPGTEXTABLE);
numTex = texList.size();
numTex = textureMap.size();
buf.Add(numTex);
for (unsigned int i=0;i<texList.size();i++) {
TextureMapType::const_iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++) {
trpgTexture1_0 tex1_0;
tex1_0 = texList[i];
tex1_0 = itr->second;
if (!tex1_0.Write(buf))
return false;
}

View File

@ -457,14 +457,11 @@ bool trpgGeometry::GetTexCoordSet(int id,trpgTexData *tx) const
*tx = texData[id];
return true;
}
const trpgTexData *trpgGeometry::GetTexCoordSet(int id) const
{
if (!isValid() || id < 0 || id >= (int)texData.size()) return 0;
return &(texData[id]);
}
bool trpgGeometry::GetNumEdgeFlag(int &n) const
{
if (!isValid()) return false;

View File

@ -26,6 +26,8 @@
#include <trpage_io.h>
#include <trpage_swap.h>
// Forward declarations
class trpgMaterial;
@ -40,7 +42,8 @@ class trpgMatTable;
reading this class. Since it's only read once, the overhead is low.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgHeader : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgHeader : public trpgReadWriteable
{
public:
trpgHeader(void);
~trpgHeader(void);
@ -82,6 +85,9 @@ public:
// Increase the number of terrain LODs, adding a new one with the given size and range
void AddLod(const trpg2iPoint &size,const trpg2dPoint &ext,float64 range);
// Set details for an LOD, resizing if necessary
void SetLod(const trpg2iPoint &size,const trpg2dPoint &ext,float64 range,unsigned int lod);
// Keep track of the maximum assigned group IDs (for tile paging)
void SetMaxGroupID(int);
/* Instead of keeping a count of all the group IDs you added and then
@ -138,6 +144,11 @@ public:
Each of these terrain LODs is accessed seperately (as are the tiles within them).
This returns the number of terrain LODs in the file. It will be at least 1.
See trpgAttach for instructions on how to hook the terrain LODs together.
For version 2.1 and over, this number represent the depest lod that was found
in the gaming area. With variable lod, tiles will not ncessarily fill out all of
the gaming area for all of the lods. trpgAttach node are no longer used, instead
see trpgChildRef
*/
bool GetNumLods(int32 &) const;
/* A terrain LOD conceptually covers the entire database and is broken up
@ -165,6 +176,44 @@ public:
// {secret}
bool ReadLodInfo(trpgReadBuffer &);
void SetMaster(bool isMaster)
{
if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR))
{
if(isMaster)
flags |= ISMASTER;//set the master flag
else
flags &= ~ISMASTER;//clear the master flag
}
}
bool GetIsMaster() const
{
return ((flags & ISMASTER)==ISMASTER);
}
void SetLocal(bool isLocal)
{
if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR))
{
if(isLocal)
flags |= ISLOCAL;//set the local flag
else
flags &= ~ISLOCAL;//clear the local flag
}
}
bool GetIsLocal() const
{
return ((flags & ISLOCAL)==ISLOCAL);
}
void SetBlocks(int rows,int cols)
{
this->rows = rows;
this->cols = cols;
}
void GetBlocks(int &rows,int &cols)
{
rows = this->rows;
cols = this->cols;
}
protected:
int verMinor,verMajor;
int dbVerMinor,dbVerMajor;
@ -177,6 +226,11 @@ protected:
std::vector<trpg2dPoint> tileSize;
std::vector<trpg2iPoint> lodSizes;
std::vector<float64> lodRanges;
const static int ISMASTER = 1;
const static int ISLOCAL = 2;
int32 flags;
int32 rows;
int32 cols;
};
/* The Texture Environment is used by the trpgMaterial to define texture
@ -191,7 +245,8 @@ protected:
need to build these in the course of building a trpgMaterial.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTextureEnv : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTextureEnv : public trpgReadWriteable
{
friend class trpgMatTable;
public:
trpgTextureEnv(void);
@ -286,7 +341,8 @@ protected:
fill in what you need to use.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgMaterial : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgMaterial : public trpgReadWriteable
{
friend class trpgMatTable;
public:
trpgMaterial(void);
@ -455,7 +511,8 @@ protected:
bool autoNormal;
int numTex;
int32 numTile;
struct _attrSet {
struct _attrSet
{
int fid;
int smc;
int stp;
@ -471,7 +528,8 @@ protected:
It's best to consult the Get methods to figure out what options
are available.
*/
TX_EXDECL class TX_CLDECL trpgLightAttr : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLightAttr : public trpgReadWriteable
{
public:
// Default constructor
trpgLightAttr(void);
@ -481,7 +539,8 @@ public:
~trpgLightAttr(void);
// Light Flags
enum {
enum
{
// Light flags
trpg_Day = 0x0001,
trpg_Dusk = 0x0002,
@ -505,21 +564,24 @@ public:
} LightFlags;
// Light Type
typedef enum {
typedef enum
{
trpg_Raster,
trpg_Calligraphic,
trpg_RASCAL
} LightType;
// Light Directionality
typedef enum {
typedef enum
{
trpg_Omnidirectional,
trpg_Bidirectional,
trpg_Unidirectional
} LightDirectionality;
// Light Quality
typedef enum {
typedef enum
{
trpg_Off,
trpg_Low,
trpg_Medium,
@ -528,7 +590,8 @@ public:
} LightQuality;
// Struct for Performer Lights
typedef struct PerformerAttr {
typedef struct PerformerAttr
{
PerformerAttr() : flags(0),minPixelSize(0),maxPixelSize(0),actualSize(0),
transparentPixelSize(0),transparentFallofExp(0),transparentScale(0),
transparentClamp(0),fogScale(0) {};
@ -541,25 +604,27 @@ public:
float64 transparentScale;
float64 transparentClamp;
float64 fogScale;
} _PerformerAttr;
};
// Struct for Animated Lights
typedef struct AnimationAttr {
typedef struct AnimationAttr
{
AnimationAttr() : period(0),phaseDelay(0),timeOn(0),vector(trpg3dPoint(0,0,0)),flags(0) {};
float64 period;
float64 phaseDelay;
float64 timeOn;
trpg3dPoint vector;
int32 flags;
} _AnimationAttr;
};
// Struct for Calligraphic Lights
typedef struct CalligraphicAttr {
typedef struct CalligraphicAttr
{
CalligraphicAttr() : drawOrder(0),minDefocus(0),maxDefocus(0) {} ;
int32 drawOrder;
float64 minDefocus;
float64 maxDefocus;
} _CalligraphicAttr;
};
// Setters
// Set Type
@ -741,8 +806,10 @@ public:
// Resets the contents back to empty
void Reset(void);
protected:
struct DataSet {
struct DataSet
{
LightType type;
LightDirectionality directionality;
trpgColor frontColor;
@ -773,7 +840,8 @@ protected:
These may consist of single lights or light strings.
The trpgLight points into the trpgLightTable for its attributes.
*/
TX_EXDECL class TX_CLDECL trpgLight : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLight : public trpgReadWriteable
{
public:
// Default constructor
trpgLight(void);
@ -831,7 +899,8 @@ protected:
the attributes for all light points. trpgLight structures will index
into this table to define their appearance.
*/
TX_EXDECL class TX_CLDECL trpgLightTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLightTable : public trpgReadWriteable
{
public:
// Default constructor
trpgLightTable(void);
@ -875,9 +944,12 @@ public:
// operator
trpgLightTable & operator = (const trpgLightTable &);
typedef std::map<int,trpgLightAttr> LightMapType;
LightMapType *getLightMap() { return &lightMap; }
protected:
// Here we store the light attributes
std::vector<trpgLightAttr> lightList;
//std::vector<trpgLightAttr> lightList;
LightMapType lightMap;
};
@ -887,7 +959,8 @@ protected:
data to the run-time system about the relative priorities of classes of
features. See the trpgRangeTable for a complete explanation.
*/
TX_EXDECL class TX_CLDECL trpgRange : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgRange : public trpgReadWriteable
{
public:
trpgRange(void);
~trpgRange(void);
@ -978,7 +1051,8 @@ protected:
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgRangeTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgRangeTable : public trpgReadWriteable
{
public:
trpgRangeTable(void);
~trpgRangeTable(void);
@ -986,6 +1060,8 @@ public:
// Get the given range info
bool GetRange(int id,trpgRange &) const;
// Get the number of entries in the table
int GetNumRanges() {return int(rangeMap.size());}
// Set the range info for the given ID
bool SetRange(int id,trpgRange &);
@ -1011,7 +1087,9 @@ public:
trpgRangeTable & operator = (const trpgRangeTable &);
protected:
std::vector<trpgRange> rangeList;
typedef std::map<int,trpgRange> RangeMapType;
RangeMapType rangeMap;
//std::vector<trpgRange> rangeList;
};
/* All materials are centrally indexed in TerraPage. There is one material
@ -1037,7 +1115,8 @@ protected:
trpgMaterial, modify just a few fields and call AddMaterial repeatedly.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgMatTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgMatTable : public trpgReadWriteable
{
public:
trpgMatTable(void);
~trpgMatTable(void);
@ -1055,7 +1134,7 @@ public:
AddMaterial instead.
The two argument version assumes subTable = 0
*/
void SetMaterial(int subTable,int mat,const trpgMaterial &);
//void SetMaterial(int subTable,int mat,const trpgMaterial &);
void SetMaterial(int,const trpgMaterial &);
/* This function should be used if you only have a single material sub-table.
@ -1064,11 +1143,13 @@ public:
*/
int AddMaterial(const trpgMaterial &,bool lookForExisting=true);
// The following method is unused currently
/* This function should be used when adding materials to multiple sub-tables.
It searches for a matching material and then adds a new one if it doesn't
find a match. The new (or old) ID is returned.
*/
int AddMaterialInSubtable(const trpgMaterial &,int table,bool lookForExisting=true);
//int AddMaterialInSubtable(const trpgMaterial &,int table,bool lookForExisting=true);
/* Return the number of sub-tables. This will, most commonly, be 1.
Any value more than 1 means the archive has alternate material definitions
@ -1110,7 +1191,8 @@ public:
protected:
int numTable;
int numMat;
std::vector<trpgMaterial> matTables;
typedef std::map<int,trpgMaterial> MaterialMapType;
MaterialMapType materialMap;
};
/* This class holds the texture definition TerraPage uses. Textures are a little
@ -1140,7 +1222,8 @@ protected:
of this. It's best to use those.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTexture : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTexture : public trpgReadWriteable
{
public:
trpgTexture(void);
trpgTexture(const trpgTexture &);
@ -1165,28 +1248,30 @@ public:
image modes (see ImageMode). If the image is External or Global, anything
is fair game, but these are the only types TerraPage can store itself.
*/
typedef enum {
typedef enum
{
trpg_RGB8,
trpg_RGBA8,
trpg_INT8,
trpg_INTA8,
trpg_FXT1,
trpg_Filler, // This is not a texture format. It's here to keep the numbering consistent
trpg_RGBX, // MCM
trpg_RGBX, // MCM no longer
trpg_Unknown,
trpg_DDS,
trpg_DXT1,
trpg_DXT3,
trpg_DXT5
trpg_DXT5,
// This is a bit ugly, but we can't change the size of the texture record without
// breaking existing readers. So there will be multiple MCM types to indicate the number
// of bands and the nature of the extra channels, if any
trpg_MCM5,
trpg_MCM6R,
trpg_MCM6A,
trpg_MCM7RA,
trpg_MCM7AR
} ImageType;
// How the image bit planes are organized
typedef enum {
trpg_RGBX_Neither=0,
trpg_RGBX_AlphaFirst,
trpg_RGBX_RegionFirst
} ImageOrg;
// Set the texture name.
void SetName(const char *);
/* This is the texture name. You pass in a string of a pre-defined length
@ -1217,10 +1302,6 @@ public:
// This method is only used if ImageMode is Local or Template
bool GetImageType(ImageType &) const;
// Find out how the bit planes are organized. Only important for some types
// of images
bool GetImageOrganization(ImageOrg &) const;
// Retrieve the size of this image. Valid only for Local and Template textures.
bool GetImageSize(trpg2iPoint &) const;
@ -1239,10 +1320,6 @@ public:
// Set the image type of this texture. See GetImageType for details.
void SetImageType(ImageType);
// Sets a constant the dictates bit plane organization. Not used for all image
// types
void SetImageOrganization(ImageOrg);
// Set the image size of this texture. See GetImageSize for details
void SetImageSize(const trpg2iPoint &);
@ -1303,9 +1380,6 @@ protected:
// Type of texture (only valid if ImageMode is Local or Template)
ImageType type;
// Organize of image bit planes
ImageOrg org;
// The name really only has meaning for External or Global textures
char *name;
int useCount;
@ -1360,7 +1434,8 @@ protected:
can be done right before you close the archive.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTexTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTexTable : public trpgReadWriteable
{
public:
trpgTexTable(void);
trpgTexTable(const trpgTexTable &);
@ -1410,8 +1485,27 @@ public:
trpgTexTable & operator = (const trpgTexTable &);
const trpgTexture *FindByName(const char *name, int &texid) const;
void SetCurrentBlock(int row, int col)
{
currentRow = row;
currentCol = col;
}
//bool dumpGeoTypicalTextures(trpgwImageHelper *ihelper);
typedef std::map<int,trpgTexture> TextureMapType;
TextureMapType *getTextureMap()
{
return &textureMap;
}
protected:
std::vector<trpgTexture> texList;
TextureMapType textureMap;
//These are used to initialize the row/col values for
//multi-archive archives
int currentRow;
int currentCol;
};
/* Models are basically just references in TerraPage. This class just points
@ -1440,16 +1534,23 @@ protected:
quite there yet.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgModel : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgModel : public trpgReadWriteable
{
public:
trpgModel(void);
trpgModel(const trpgModel &);
~trpgModel(void);
enum {Local,External};
// Sets the name of the external model file and sets this model to External type.
// 5.28.04 - It will not set the model to be as of external type. Use the method
// from below to set the type of the model
void SetName(const char *);
// Sets the on-disk reference to an internal model and sets this model to Internal type.
// 5.28.04 - It will not set the model to be as of internal type. Use the method
// from below to set the type of the model
void SetReference(trpgDiskRef);
// Sets the model type
void SetType(int);
/* Models are reference counted (per-tile). It's up to the writer to set this
value. */
void SetNumTiles(int);
@ -1480,13 +1581,15 @@ public:
// Writes this class to a write buffer
bool Write(trpgWriteBuffer &);
// Reads this class from a read buffer
bool Read(trpgReadBuffer &);
bool Read(trpgReadBuffer &, bool);
// Prints this class to a print buffer
bool Print(trpgPrintBuffer &) const;
trpgModel & operator = (const trpgModel &);
int operator == (const trpgModel &) const;
protected:
int type;
char *name;
@ -1509,7 +1612,8 @@ protected:
The finished table will be passed to trpgwArchive at the end.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgModelTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgModelTable : public trpgReadWriteable
{
public:
trpgModelTable(void);
~trpgModelTable(void);
@ -1521,9 +1625,9 @@ public:
/* Add the given model to the table. Makes a copy of the model you pass in
and returns the new model ID which you'll need to reference in trpgModelRef.
*/
int AddModel(const trpgModel &);
int AddModel(trpgModel &);
/* Look for a given model. If it's not there, add it. */
int FindAddModel(const trpgModel &);
int FindAddModel(trpgModel &);
/* Sets the model definition corresponding to the given ID. Use this in conjunction
with SetNumModels. */
void SetModel(int,const trpgModel &);
@ -1552,26 +1656,41 @@ public:
// Prints this class to a print buffer
bool Print(trpgPrintBuffer &) const;
bool FindByName(const char *name, unsigned int &mId);
typedef std::map<int,trpgModel> ModelMapType;
ModelMapType *GetModelMap()
{
return &modelsMap;
}
protected:
std::vector<trpgModel> models;
ModelMapType modelsMap;
};
/* The tile table keeps track of tile locations within a TerraPage archive.
Tiles can be stored either externally (as individual files) or locally
(grouped together into bigger files). The details are hidden from the
reader completely and the writer in most cases.
In version 2.1 the tile table only contains the location of lod 0 tiles.
All other tiles location are stored in the parent tile as trpgChildRef
nodes, so you need to parse the parent tile to get at them.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTileTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTileTable : public trpgReadWriteable
{
public:
// Tiles can be stored individually (External) or in grouped files (Local)
typedef enum {Local,External} TileMode;
// Tiles can be stored individually (External and ExternalSaved) or in grouped files (Local).
// ExternalSaved still have an entry in the table. In this case the addess data is not valid.
trpgTileTable(void);
enum TileMode {Local,External, ExternalSaved};
trpgTileTable();
~trpgTileTable(void);
// Set the tile storage mode: external or local
void SetMode(TileMode);
// Set the total number of LODs
// For version 2.1 only lod 0 is stored in the table
void SetNumLod(int numLod);
// Set the number of tiles in each dimenion for each terrain LOD
// This must agree with trpgHeader
@ -1595,11 +1714,22 @@ public:
bool Read(trpgReadBuffer &);
// Prints this class to a print buffer
bool Print(trpgPrintBuffer &) const;
/**
* SetCurrentBlock is used in two cases:
* 1. When building a block specific tile archive (MMB and non-MMB). (local is TRUE)
* 2. When merging several blocks into memory for visualization. (local is FALSE)
**/
void SetCurrentBlock(int row, int col, bool local)
{
currentRow = row;
currentCol = col;
localBlock = local;
}
protected:
TileMode mode;
class LodInfo {
class LodInfo
{
public:
int numX,numY;
// Tile addresses into external Appendable files
@ -1610,8 +1740,14 @@ protected:
std::vector<float> elev_max;
};
std::vector <LodInfo> lodInfo;
//These are used to initialize the row/col values for
//multi-archive archives
int currentRow;
int currentCol;
bool localBlock; // if true, this tile table should only contain entries for one block.
};
/* Local materials are new to TerraPage 2.0.
The idea is that for pageable one-time textures it makes more sense
to define them in the tiles. This keeps the size of Texture and
@ -1623,7 +1759,8 @@ protected:
In either case, you can pass this class to trpgrTextureHelper and let
it get the image data for you.
*/
TX_EXDECL class TX_CLDECL trpgLocalMaterial : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLocalMaterial : public trpgReadWriteable
{
public:
trpgLocalMaterial(void);
~trpgLocalMaterial(void);
@ -1646,7 +1783,8 @@ public:
*/
bool GetBaseMaterial(int32 &matSubTable,int32 &matID) const;
class SubImageInfo {
class SubImageInfo
{
public:
int32 sx,sy; // Source (sx,sy) in pixels
int32 ex,ey; // Source (ex,ey) in pixels
@ -1710,9 +1848,10 @@ protected:
};
/* The tile header is one of the more interesting parts of TerraPage. Basically,
it's a list of all the materials, local material and models used in a tile. Tile headers are
stuck at the beginning of terrain tiles to give you this information. They
can be read separately, in theory, although no one is doing that at present.
it's a list of all the materials, local material and models used in a tile.
Tile headers are stuck at the beginning of terrain tiles to give you this
information. They can be read separately, in theory, although no one is doing
that at present.
If you're doing a TerraPage reader you will encounter one of these first thing
when you parse a terrain tile. These are here to aid texture and model paging.
@ -1755,7 +1894,8 @@ protected:
be passed to trpgwArchive along with the tile geometry and written to disk.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTileHeader : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTileHeader : public trpgReadWriteable
{
public:
trpgTileHeader(void);
~trpgTileHeader(void);
@ -1819,13 +1959,25 @@ public:
bool Read(trpgReadBuffer &);
// Prints this class to a print buffer
bool Print(trpgPrintBuffer &) const;
void SetBlockNo(int row, int col)
{
this->row = row;
this->col = col;
}
void GetBlockNo(int &row, int &col)
{
row = this->row;
col = this->col;
}
protected:
std::vector<int> matList;
std::vector<int> modelList;
std::vector<trpgLocalMaterial> locMats;
// {secret}
int date;
//These are used to find them in the block archive.
int row;
int col;
};
/* The color info structure is used by the trpgGeometry class to store
@ -1834,7 +1986,8 @@ protected:
trpgGeometry::GetColorSet().
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgColorInfo {
TX_EXDECL class TX_CLDECL trpgColorInfo
{
public:
trpgColorInfo(void);
~trpgColorInfo(void);
@ -1867,7 +2020,8 @@ public:
this structure is used for.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTexData {
TX_EXDECL class TX_CLDECL trpgTexData
{
public:
trpgTexData(void);
~trpgTexData(void);
@ -1918,7 +2072,8 @@ public:
such before diving into this structure.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgGeometry : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgGeometry : public trpgReadWriteable
{
public:
trpgGeometry(void);
~trpgGeometry(void);
@ -2114,13 +2269,11 @@ public:
coordinate sets.
*/
bool GetTexCoordSet(int id,trpgTexData *) const;
/* This method returns this trpgGeometry's texture coordinate set specified by the given
index. GetNumTexCoordSets determines the total number of texture
coordinate sets.
*/
const trpgTexData *GetTexCoordSet(int id) const;
/* Returns the number of edge flags in this geometry node.
Edge flags are used on certain primitive types, but are rather rare.
*/
@ -2183,7 +2336,8 @@ protected:
pageable chunk of terrain hierarchy.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgGroup : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgGroup : public trpgReadWriteable
{
public:
trpgGroup(void);
virtual ~trpgGroup(void);
@ -2283,7 +2437,8 @@ protected:
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgAttach : public trpgGroup {
TX_EXDECL class TX_CLDECL trpgAttach : public trpgGroup
{
public:
trpgAttach(void);
~trpgAttach(void);
@ -2317,6 +2472,48 @@ protected:
int parentID,childPos;
};
TX_EXDECL class TX_CLDECL trpgChildRef : public trpgReadWriteable
{
public:
trpgChildRef();
~trpgChildRef();
// Resets the contents back to empty
void Reset();
// Set the tile grid location
void SetTileLoc(int gx,int gy,int glod);
// Get the tile grid location
bool GetTileLoc(int &gx,int &gy,int &glod) const;
void SetTileAddress(const trpgwAppAddress& gAddr);
void SetTileAddress(int32 file, int32 offset);
void SetTileZValue( float gZmin, float gZmax);
bool GetTileAddress(int32& file, int32& offset) const;
bool GetTileAddress(trpgwAppAddress& gAddr) const;
bool GetTileZValue( float& gZmin, float& gZmax) const;
// Validity check
bool isValid(void) const;
// Writes this class to a write buffer
bool Write(trpgWriteBuffer &);
// Reads this class from a read buffer
bool Read(trpgReadBuffer &);
// Prints this class to a print buffer
bool Print(trpgPrintBuffer &) const;
protected:
// Grid Location
int x,y,lod;
// File Location
trpgwAppAddress addr;
float zmin, zmax;
};
/* The billboard inherits from the standard trpgGroup. It tells the reader that
everything underneath this node is supposed to be treated like a stamp or billboard
(depending on your terminology). That means it's supposed to be rotated towards
@ -2332,7 +2529,8 @@ protected:
use one of these with one or more trpgGeometry children.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgBillboard : public trpgGroup {
TX_EXDECL class TX_CLDECL trpgBillboard : public trpgGroup
{
public:
trpgBillboard(void);
~trpgBillboard(void);
@ -2424,7 +2622,8 @@ protected:
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgLod : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLod : public trpgReadWriteable
{
public:
trpgLod(void);
~trpgLod(void);
@ -2497,7 +2696,8 @@ protected:
very poorly on most OpenGL systems.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgLayer : public trpgGroup {
TX_EXDECL class TX_CLDECL trpgLayer : public trpgGroup
{
public:
trpgLayer(void);
~trpgLayer(void);
@ -2518,7 +2718,8 @@ protected:
like a trpgGroup.
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgTransform : public trpgGroup {
TX_EXDECL class TX_CLDECL trpgTransform : public trpgGroup
{
public:
trpgTransform(void);
~trpgTransform(void);
@ -2561,7 +2762,8 @@ protected:
{group:Read/Write Classes}
*/
TX_EXDECL class TX_CLDECL trpgModelRef : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgModelRef : public trpgReadWriteable
{
public:
trpgModelRef(void);
~trpgModelRef(void);
@ -2595,7 +2797,8 @@ protected:
For the most part, text styles are very simple, consisting of
very basic font and material information.
*/
TX_EXDECL class TX_CLDECL trpgTextStyle : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTextStyle : public trpgReadWriteable
{
public:
trpgTextStyle(void);
~trpgTextStyle(void);
@ -2655,7 +2858,8 @@ protected:
whole archive. Individual text styles will be indexed by trpgLabelProperty
objects. It is from these that you decide how to display a given label.
*/
TX_EXDECL class TX_CLDECL trpgTextStyleTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgTextStyleTable : public trpgReadWriteable
{
public:
trpgTextStyleTable(void);
~trpgTextStyleTable(void);
@ -2682,9 +2886,12 @@ public:
bool Read(trpgReadBuffer &);
// Print this class to a print buffer
bool Print(trpgPrintBuffer &) const;
typedef std::map<int,trpgTextStyle> StyleMapType;
const StyleMapType *getStyleMap()const { return &styleMap; }
protected:
std::vector<trpgTextStyle> styles;
//std::vector<trpgTextStyle> styles;
StyleMapType styleMap;
};
@ -2693,7 +2900,8 @@ protected:
For the most part, support styles are very simple, consisting of
very basic description of object to use for drawing suport.
*/
TX_EXDECL class TX_CLDECL trpgSupportStyle : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgSupportStyle : public trpgReadWriteable
{
public:
trpgSupportStyle(void);
~trpgSupportStyle(void);
@ -2739,7 +2947,8 @@ protected:
whole archive. Individual support styles will be indexed by trpgLabelProperty
objects. It is from these that you decide how to display a given support.
*/
TX_EXDECL class TX_CLDECL trpgSupportStyleTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgSupportStyleTable : public trpgReadWriteable
{
public:
trpgSupportStyleTable(void);
~trpgSupportStyleTable(void);
@ -2768,7 +2977,9 @@ public:
bool Print(trpgPrintBuffer &) const;
protected:
std::vector<trpgSupportStyle> styles;
//std::vector<trpgSupportStyle> styles;
typedef std::map<int,trpgSupportStyle> SupportStyleMapType;
SupportStyleMapType supportStyleMap;
};
@ -2777,7 +2988,8 @@ protected:
Label properties are very simple, consisting of
basic font style and support properties.
*/
TX_EXDECL class TX_CLDECL trpgLabelProperty : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLabelProperty : public trpgReadWriteable
{
public:
trpgLabelProperty(void);
~trpgLabelProperty(void);
@ -2829,7 +3041,8 @@ protected:
whole archive. Individual label property will be indexed by trpgLable
objects.
*/
TX_EXDECL class TX_CLDECL trpgLabelPropertyTable : public trpgReadWriteable {
TX_EXDECL class TX_CLDECL trpgLabelPropertyTable : public trpgReadWriteable
{
public:
trpgLabelPropertyTable(void);
~trpgLabelPropertyTable(void);
@ -2859,7 +3072,9 @@ public:
bool Print(trpgPrintBuffer &) const;
protected:
std::vector<trpgLabelProperty> properties;
//std::vector<trpgLabelProperty> properties;
typedef std::map<int,trpgLabelProperty> LabelPropertyMapType;
LabelPropertyMapType labelPropertyMap;
};
/* Labels are objects that float above the terrain (usually) and display

View File

@ -42,6 +42,12 @@ trpgHeader::~trpgHeader()
// Validity check
bool trpgHeader::isValid() const
{
// 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");
@ -53,6 +59,7 @@ bool trpgHeader::isValid() const
return false;
}
}
return true;
}
@ -74,8 +81,10 @@ void trpgHeader::Reset()
lodRanges.resize(0);
tileSize.resize(0);
maxGroupID = -1;
flags = 0;
errMess[0] = '\0';
cols = -1;
rows = -1;
}
// Set functions
@ -146,6 +155,20 @@ void trpgHeader::AddLod(const trpg2iPoint &pt,const trpg2dPoint &sz,float64 r)
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;
@ -185,6 +208,12 @@ bool trpgHeader::Write(trpgWriteBuffer &buf)
buf.Add(maxGroupID);
if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) {
buf.Add(flags);
buf.Add(rows);
buf.Add(cols);
}
buf.End();
return true;
@ -289,6 +318,11 @@ bool trpgHeader::Read(trpgReadBuffer &buf)
// 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 (...) {

View File

@ -22,6 +22,14 @@
#include <trpage_sys.h>
#ifndef TeAttrH
/* was unsigned long, but it is used as if it was signed in the constructor
* and code that set the handle are using a signed value.
* 01-10-2006 David Fries
*/
typedef long TeAttrHdl;
#endif
// Macros we may need
#ifndef MIN
// {secret}
@ -38,7 +46,12 @@
// Current TerraPage major version
#define TRPG_VERSION_MAJOR 2
// Current TerraPage minor version
#define TRPG_VERSION_MINOR 0
#define TRPG_VERSION_MINOR 2
// defined values for the version that doesn't need
// a merge
#define TRPG_NOMERGE_VERSION_MAJOR 2
#define TRPG_NOMERGE_VERSION_MINOR 2
// Non-existent token
// {secret}
@ -91,6 +104,8 @@ typedef short trpgToken;
#define TRPGMAT_BUMP 408
// {secret}
#define TRPGMAT_ATTR 409
// {secret}
#define TRPGMAT_HANDLE 410
// {secret}
#define TRPGMAT_TEXENV 500
@ -112,7 +127,8 @@ typedef short trpgToken;
// {secret}
#define TRPGMODELREF 700
// {secret}
#define TRPGMODELREF2 701
// {secret}
#define TRPGMODELTABLE 800
@ -155,6 +171,8 @@ typedef short trpgToken;
// {secret}
#define TRPGLIGHTATTR_COMMENT 1156
// {secret}
#define TRPGLIGHTATTR_HANDLE 1157
// {secret}
#define TRPGLIGHT 1160
// {secret}
#define TRPG_LIGHT 1160
@ -231,7 +249,10 @@ typedef short trpgToken;
#define TRPG_ATTACH 4000
// {secret}
#define TRPG_MAXTOKEN 4000
#define TRPG_CHILDREF 5000
// {secret}
#define TRPG_MAXTOKEN 5000
// Basic data types
@ -406,6 +427,12 @@ public:
/* Adds the TRPG_POP token to the current buffer. This is done by objects
that have defined children. See Push. */
virtual void Pop(void);
/* Take out the pop from the end of the buffer, if there is one */
/* Will return true if a pop was actually taken out */
virtual bool UnPop();
/* Take out the push from the end of the buffer, if there is one */
/* Will return true if a push was actually taken out */
virtual bool UnPush();
protected:
virtual void append(unsigned int,const char *);
@ -472,6 +499,11 @@ public:
// Buffer is empty
virtual bool isEmpty(void) = 0;
// MD: making this public to unravel trpgModel read problem.
/* A utility function for subclasses to use to see if they would exceed an
outside imposed limit by reading the given number of bytes. */
virtual bool TestLimit(int);
protected:
trpgEndian ness; // Endianness of the source we're reading
trpgEndian cpuNess; // Endiannees of the CPU
@ -486,9 +518,6 @@ protected:
/* This virtual method must be filled in by the subclass so that SkipToLimit
will work correctly. */
virtual bool Skip(int) = 0;
/* A utility function for subclasses to use to see if they would exceed an
outside imposed limit by reading the given number of bytes. */
virtual bool TestLimit(int);
/* Utility function that must be called after a successfull read to update
the outside imposed read limits. */
virtual void UpdateLimits(int);
@ -509,6 +538,8 @@ public:
bool isEmpty(void);
// Sets the size of this read buffer.
void SetLength(int);
// Gets the size of the buffer.
int GetLength(void) { return len; }
/* Return a pointer to the raw data cache for this object. Data will
be dumped straight into here (from disk, for example) and then parsed
by something that takes a trpgReadBuffer as input. */
@ -533,10 +564,21 @@ public:
virtual ~trpgCheckable(void);
// Returns the state of the valid flag, or can be overriden by a subclass to do a more complex check.
bool isValid(void) const;
virtual TeAttrHdl GetHandle() const {
return handle;
}
virtual void SetHandle(TeAttrHdl hdl) {
writeHandle = true;
handle = hdl;
}
protected:
/* Set this flag to true if your checkable structure doesn't have a complex
check it needs to do. */
bool valid;
TeAttrHdl handle;
bool writeHandle;
};
class trpgPrintBuffer;
@ -589,12 +631,17 @@ protected:
*/
TX_EXDECL class TX_CLDECL trpgwAppAddress {
public:
trpgwAppAddress() {file = -1; offset = -1;};
trpgwAppAddress() {file = -1; offset = -1; row = -1; col = -1;};
// Which file
int32 file;
// Offset within the file
// Note: This is not a 64 bit value
int32 offset;
// Row and col are used for TerraPage 2.3 archives, so we
// can know which block to get the appropriate file from
int32 row;
int32 col;
};
/* Archive File.
@ -604,13 +651,15 @@ public:
*/
TX_EXDECL class TX_CLDECL trpgwAppFile {
public:
trpgwAppFile(trpgEndian,const char *);
trpgwAppFile() {valid=false;};
trpgwAppFile(trpgEndian,const char *,bool reuse=false);
virtual ~trpgwAppFile(void);
virtual bool Append(const trpgMemWriteBuffer *,const trpgMemWriteBuffer *);
virtual bool Append(const char *,int size);
virtual int64 Pos(void) const;
virtual int GetLengthWritten();
virtual bool Flush(void);
virtual void Init(trpgEndian,const char *,bool reuse=false);
bool isValid(void) const;
protected:
@ -627,7 +676,10 @@ protected:
*/
TX_EXDECL class TX_CLDECL trpgrAppFile {
public:
trpgrAppFile() {valid=false;};
trpgrAppFile(trpgEndian,const char *);
// real construction is here
virtual void Init(trpgEndian,const char *);
virtual ~trpgrAppFile(void);
virtual bool Read(trpgMemReadBuffer *,int32 offset);
virtual bool Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSize);
@ -644,9 +696,14 @@ protected:
*/
TX_EXDECL class TX_CLDECL trpgrAppFileCache {
public:
trpgrAppFileCache(){;};
trpgrAppFileCache(const char *prefix,const char *ext,int noFiles=32);
~trpgrAppFileCache(void);
trpgrAppFile *GetFile(trpgEndian ness,int id);
// real construction is here
virtual void Init(const char *prefix,const char *ext,int noFiles);
virtual ~trpgrAppFileCache(void);
virtual trpgrAppFile *GetFile(trpgEndian ness,int id,int col,int row);
virtual trpgrAppFile *GetFile(trpgEndian ness,int id);
virtual trpgrAppFile *GetNewRAppFile(trpgEndian ness, const char *fileName);
protected:
// Prefix name and extension
char baseName[1024],ext[20];
@ -655,6 +712,8 @@ protected:
public:
OpenFile(void);
int id; // ID of open file
int row;
int col;
trpgrAppFile *afile;
int lastUsed; // When the file was last accessed
};

View File

@ -20,7 +20,7 @@
#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,7 +129,8 @@ 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 {
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();
@ -297,11 +313,12 @@ bool trpgTextStyleTable::Read(trpgReadBuffer &buf)
Reset();
try {
try
{
buf.Get(numStyle);
if (numStyle < 0)
throw 1;
styles.resize(numStyle);
for (i=0;i<numStyle;i++) {
buf.GetToken(styleTok,len);
if (styleTok != TRPG_TEXT_STYLE) throw 1;
@ -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();
@ -944,7 +1011,8 @@ bool trpgLabel::Read(trpgReadBuffer &buf)
trpg3dPoint support;
int iVal;
try {
try
{
buf.Get(iVal);
propertyId = iVal;
buf.Get(text);
@ -963,7 +1031,8 @@ bool trpgLabel::Read(trpgReadBuffer &buf)
supports.push_back(support);
}
}
catch (...) {
catch (...)
{
return false;
}

View File

@ -439,6 +439,11 @@ bool trpgLightAttr::Write(trpgWriteBuffer &buf)
buf.End();
}
if(writeHandle) {
buf.Begin(TRPGLIGHTATTR_HANDLE);
buf.Add((int)handle);
buf.End();
}
buf.End();
return true;
@ -547,6 +552,11 @@ void * lightAttrCB::Parse(trpgToken tok,trpgReadBuffer &buf)
buf.Get(commentStr,1024);
lightAttr->SetComment(commentStr);
break;
case TRPGLIGHTATTR_HANDLE:
int hdl;
buf.Get(hdl);
lightAttr->SetHandle(hdl);
break;
default:
break;
}
@ -575,6 +585,7 @@ bool trpgLightAttr::Read(trpgReadBuffer &buf)
parse.AddCallback(TRPGLIGHTATTR_CALLIGRAPHIC,&lightAttrCb,false);
parse.AddCallback(TRPGLIGHTATTR_ANIMATION,&lightAttrCb,false);
parse.AddCallback(TRPGLIGHTATTR_COMMENT,&lightAttrCb,false);
parse.AddCallback(TRPGLIGHTATTR_HANDLE,&lightAttrCb,false);
parse.Parse(buf);
return isValid();
@ -592,6 +603,8 @@ trpgLightAttr& trpgLightAttr::operator = (const trpgLightAttr& in)
data.commentStr = new char[strlen(in.data.commentStr)+1];
strcpy(data.commentStr,in.data.commentStr);
}
handle = in.handle;
writeHandle = in.writeHandle;
return *this;
}
@ -675,7 +688,10 @@ bool trpgLightAttr::operator == (const trpgLightAttr& in)
return false;
if (data.commentStr && in.data.commentStr && strcmp(data.commentStr,in.data.commentStr))
return false;
if (handle != in.handle)
return false;
if (writeHandle != in.writeHandle)
return false;
return true;
}
@ -725,6 +741,8 @@ void trpgLightAttr::Reset(void)
if (data.commentStr)
delete [] data.commentStr;
data.commentStr = NULL;
handle = -1;
writeHandle = false;
}
/**************
@ -778,10 +796,12 @@ bool trpgLight::GetVertex(uint32 ix, trpg3dPoint &pt) const
bool trpgLight::GetVertices(trpg3dPoint *pts) const
{
unsigned int i;
if (!isValid()) return false;
if (lightPoints.size() != 0)
for (unsigned int i=0;i<lightPoints.size();i++)
for (i=0;i<lightPoints.size();i++)
pts[i] = lightPoints[i];
return true;
@ -789,12 +809,13 @@ bool trpgLight::GetVertices(trpg3dPoint *pts) const
bool trpgLight::GetVertices(float64 *fts) const
{
unsigned int i;
unsigned int j = 0;
if (!isValid()) return false;
if (lightPoints.size() != 0)
for (unsigned int i=0;i<lightPoints.size();i++) {
for (i=0;i<lightPoints.size();i++) {
fts[j++] = lightPoints[i].x;
fts[j++] = lightPoints[i].y;
fts[j++] = lightPoints[i].z;
@ -805,12 +826,13 @@ bool trpgLight::GetVertices(float64 *fts) const
bool trpgLight::GetVertices(float32 *fts) const
{
int j = 0;
unsigned int i;
unsigned int j = 0;
if (!isValid()) return false;
if (lightPoints.size() != 0)
for (unsigned int i=0;i<lightPoints.size();i++) {
for (i=0;i<lightPoints.size();i++) {
fts[j++] = (float32)lightPoints[i].x;
fts[j++] = (float32)lightPoints[i].y;
fts[j++] = (float32)lightPoints[i].z;
@ -908,7 +930,8 @@ trpgLightTable::trpgLightTable(const trpgLightTable &in):
void trpgLightTable::Reset()
{
errMess[0] = '\0';
lightList.clear();
//lightList.clear();
lightMap.clear();
}
// Destructor
@ -920,12 +943,13 @@ trpgLightTable::~trpgLightTable()
// Validity check
bool trpgLightTable::isValid() const
{
for (unsigned int i=0;i<lightList.size();i++)
LightMapType::const_iterator itr = lightMap.begin();
for ( ; itr != lightMap.end( ); itr++)
{
if (!lightList[i].isValid())
if (!itr->second.isValid())
{
if(lightList[i].getErrMess())
strcpy(errMess, lightList[i].getErrMess());
if(itr->second.getErrMess())
strcpy(errMess, itr->second.getErrMess());
return false;
}
}
@ -936,15 +960,20 @@ bool trpgLightTable::isValid() const
// Set functions
int trpgLightTable::AddLightAttr(const trpgLightAttr& inLight)
{
lightList.push_back(inLight);
return lightList.size()-1;
int handle = inLight.GetHandle();
if(handle==-1) {
handle = lightMap.size();
}
lightMap[handle] = inLight;
return handle;
}
int trpgLightTable::FindAddLightAttr(const trpgLightAttr& inLight)
{
for (unsigned int i=0;i<lightList.size();i++)
if (lightList[i] == inLight)
return i;
LightMapType::iterator itr = lightMap.begin();
for ( ; itr != lightMap.end( ); itr++) {
if(itr->second==inLight)
return itr->first;
}
return AddLightAttr(inLight);
}
@ -953,9 +982,13 @@ int trpgLightTable::FindAddLightAttr(const trpgLightAttr& inLight)
trpgLightTable &trpgLightTable::operator = (const trpgLightTable &in)
{
Reset();
for (unsigned int i=0;i<in.lightList.size();i++)
AddLightAttr(in.lightList[i]);
LightMapType::const_iterator itr = in.lightMap.begin();
for ( ; itr != in.lightMap.end( ); itr++) {
AddLightAttr(itr->second);
}
//for (int i=0;i<in.lightList.size();i++)
// AddLightAttr(in.lightList[i]);
return *this;
}
@ -968,10 +1001,13 @@ bool trpgLightTable::Write(trpgWriteBuffer &buf)
return false;
buf.Begin(TRPGLIGHTTABLE);
numLights = lightList.size();
numLights = lightMap.size();
buf.Add(numLights);
for (unsigned int i=0;i<lightList.size();i++)
lightList[i].Write(buf);
LightMapType::iterator itr = lightMap.begin();
for ( ; itr != lightMap.end( ); itr++)
itr->second.Write(buf);
//for (unsigned int i=0;i<lightList.size();i++)
// lightList[i].Write(buf);
buf.End();
return true;
@ -985,14 +1021,20 @@ bool trpgLightTable::Write(trpgWriteBuffer &buf)
bool trpgLightTable::GetNumLightAttrs(int &no) const
{
if (!isValid()) return false;
no = lightList.size();
no = lightMap.size();
return true;
}
const trpgLightAttr* trpgLightTable::GetLightAttrRef(int id) const
{
if (id < 0 || id >= (int)lightList.size()) return NULL;
return &lightList[id];
if (id < 0) return NULL;
LightMapType::const_iterator itr = lightMap.find(id);
if(itr == lightMap.end()) {
return NULL;
}
return &itr->second;
}
bool trpgLightTable::Read(trpgReadBuffer &buf)
@ -1003,15 +1045,15 @@ bool trpgLightTable::Read(trpgReadBuffer &buf)
try {
buf.Get(numLights);
lightList.resize(numLights);
for (int i=0;i<numLights;i++) {
buf.GetToken(lightTok,len);
if (lightTok != TRPGLIGHTATTR) throw 1;
buf.PushLimit(len);
trpgLightAttr &light = lightList[i];
trpgLightAttr light;// = lightList[i];
bool status = light.Read(buf);
buf.PopLimit();
if (!status) throw 1;
AddLightAttr(light);
}
}
catch (...) {

View File

@ -16,6 +16,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdexcept>
#include <trpage_sys.h>
#include <trpage_geom.h>
@ -30,8 +31,8 @@
trpgManagedTile::trpgManagedTile()
{
isLoaded = false;
x = y = -1;
lod = -1;
location.x = location.y = -1;
location.lod = -1;
localData = NULL;
}
@ -43,9 +44,12 @@ void trpgManagedTile::Reset()
groupIDs.resize(0);
isLoaded = false;
x = y = -1;
lod = -1;
location.x = location.y = -1;
location.lod = -1;
localData = NULL;
childLocationInfo.clear();
}
bool trpgManagedTile::ParseTileHeader(trpgReadBuffer &buf)
@ -72,21 +76,105 @@ bool trpgManagedTile::IsLoaded()
bool trpgManagedTile::SetTileLoc(int inX,int inY,int inLod)
{
x = inX; y = inY;
location.x = inX;
location.y = inY;
if (inLod < 0)
return false;
lod = inLod;
location.lod = inLod;
return true;
}
bool trpgManagedTile::GetTileLoc(int &retx,int &rety,int &retLod)
bool trpgManagedTile::GetTileLoc(int &retx,int &rety,int &retLod) const
{
retx = x; rety = y; retLod = lod;
retx = location.x; rety = location.y; retLod = location.lod;
return true;
}
void trpgManagedTile::SetTileAddress(const trpgwAppAddress& gAddr)
{
location.addr = gAddr;
}
void trpgManagedTile::SetTileAddress(int32 file, int32 offset)
{
location.addr.file = file;
location.addr.offset = offset;
}
const trpgwAppAddress& trpgManagedTile::GetTileAddress() const
{
return location.addr;
}
bool trpgManagedTile::SetChildLocationInfo(int childIdx, int x, int y, const trpgwAppAddress& addr)
{
if(childIdx < 0)
throw std::invalid_argument(
"trpgManagedTile::SetChildLocationInfo(): index argument out of bound.");
int size = childLocationInfo.size();
if(childIdx < size)
childLocationInfo[childIdx] = TileLocationInfo(x, y, location.lod+1, addr);
else if(childIdx == size)
childLocationInfo.push_back(TileLocationInfo(x, y, location.lod+1, addr));
else
{
childLocationInfo.resize(childIdx+1);
childLocationInfo[childIdx] = TileLocationInfo(x, y, location.lod+1, addr);
}
return true;
}
bool trpgManagedTile::SetChildLocationInfo(int childIdx, const TileLocationInfo& info)
{
if(childIdx < 0)
throw std::invalid_argument(
"trpgManagedTile::SetChildLocationInfo(): index argument out of bound.");
int size = childLocationInfo.size();
if(childIdx < size)
childLocationInfo[childIdx] = info;
else if(childIdx == size)
childLocationInfo.push_back(info);
else
{
childLocationInfo.resize(childIdx+1);
childLocationInfo[childIdx] = info;
}
return true;
}
const TileLocationInfo& trpgManagedTile::GetChildLocationInfo(int childIdx) const
{
if(childIdx < 0 || childIdx >= (int)childLocationInfo.size())
throw std::invalid_argument(
"trpgManagedTile::GetChildLocationInfo(): index argument out of bound.");
return childLocationInfo[childIdx];
}
bool trpgManagedTile::GetChildTileLoc(int childIdx, int &x,int &y,int &lod) const
{
if(childIdx < 0 || childIdx >= (int)childLocationInfo.size())
throw std::invalid_argument(
"trpgManagedTile::GetChildTileLoc(): index argument out of bound.");
TileLocationInfo const& info = childLocationInfo[childIdx];
x = info.x;
y = info.y;
lod = info.lod;
return true;
}
const trpgwAppAddress& trpgManagedTile::GetChildTileAddress(int childIdx) const
{
if(childIdx < 0 || childIdx >= (int)childLocationInfo.size())
throw std::invalid_argument(
"trpgManagedTile::GetChildTileAddress(): index argument out of bound.");
return childLocationInfo[childIdx].addr;
}
const trpgTileHeader *trpgManagedTile::GetTileHead()
{
return &tileHead;
@ -149,7 +237,7 @@ const std::vector<int> *trpgManagedTile::GetGroupIDs() const
void trpgManagedTile::Print(trpgPrintBuffer &buf)
{
char line[1024];
sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); buf.prnLine(line);
sprintf(line,"x = %d, y = %d, lod = %d",location.x, location.y, location.lod); buf.prnLine(line);
// Note: Should print the rest too, probably.
}
@ -193,7 +281,7 @@ void trpgPageManager::LodPageInfo::Clean()
activeUnload = false;
}
bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, double scale)
bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, double scale, int freeListDivider)
{
Clean();
@ -202,6 +290,8 @@ bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, doubl
// really want to deal with that.
if (scale < 0) scale = 0.0;
tileTable = archive->GetTileTable();
// Need some size and shape info about our terrain LOD
const trpgHeader *head = archive->GetHeader();
head->GetTileSize(lod,cellSize);
@ -209,6 +299,9 @@ bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, doubl
head->GetLodSize(lod,lodSize);
pageDist *= scale;
head->GetVersion(majorVersion, minorVersion);
// Area of interest size (in cells)
aoiSize.x = (int)(pageDist/cellSize.x);
aoiSize.y = (int)(pageDist/cellSize.y);
@ -218,8 +311,19 @@ bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, doubl
From the area of interest in cells, we can guess the max
number of tiles (aka cells) we'll have loaded in at once.
Note that the AOI size is only ahead, so it must be doubled.
Version 2.1 now support variable lods, it might be overkill to
allocate a free list by supposing that the tiles exist.
So only for version 2.1 an over we will use the divider to allocate less
*/
maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1));
if(majorVersion == 2 && minorVersion >= 1)
maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1)/freeListDivider);
else
maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1));
// Allocate 'em
for (int i=0;i<maxNumTiles;i++) {
@ -318,10 +422,12 @@ bool trpgPageManager::LodPageInfo::isWithin(trpgManagedTile *tile,trpg2iPoint &s
{
int tileX,tileY,tileLod;
tile->GetTileLoc(tileX,tileY,tileLod);
if (tileX >= sw.x && tileX <= ne.x &&
tileY >= sw.y && tileY <= ne.y)
if (tileX >= sw.x &&
tileX <= ne.x &&
tileY >= sw.y &&
tileY <= ne.y)
return true;
else
return false;
}
@ -341,6 +447,113 @@ bool trpgPageManager::LodPageInfo::Stop()
return (unload.size() > 0);
}
void trpgPageManager::LodPageInfo::AddChildrenToLoadList(std::vector<trpgManagedTile*>& parentList)
{
if(parentList.size() == 0)
return;
// Area coverage, in cell unit
trpg2iPoint sw,ne;
sw.x = cell.x - aoiSize.x;
sw.y = cell.y - aoiSize.y;
ne.x = cell.x + aoiSize.x;
ne.y = cell.y + aoiSize.y;
sw.x = MAX(0,sw.x);
sw.y = MAX(0,sw.y);
ne.x = MIN(lodSize.x-1,ne.x);
ne.y = MIN(lodSize.y-1,ne.y);
int dx = ne.x - sw.x +1;
int dy = ne.y - sw.y +1;
// Mark the one that are already there
tmpCurrent.resize(dx*dy);
std::fill(tmpCurrent.begin(), tmpCurrent.end(), false);
for (unsigned int i = 0; i<current.size(); i++) {
trpgManagedTile *tile = current[i];
if (tile) {
int tileX,tileY,tileLod;
tile->GetTileLoc(tileX,tileY,tileLod);
tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true;
}
}
for (unsigned int i=0;i<load.size();i++) {
trpgManagedTile *tile = load[i];
if (tile) {
int tileX,tileY,tileLod;
tile->GetTileLoc(tileX,tileY,tileLod);
tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true;
}
}
for(unsigned int parentIdx = 0; parentIdx < parentList.size(); ++parentIdx) {
trpgManagedTile* parentTile = parentList[parentIdx];
unsigned int nbChildren = parentTile->GetNbChildren();
for(unsigned int childIdx = 0; childIdx < nbChildren; ++childIdx) {
const TileLocationInfo& childLoc = parentTile->GetChildLocationInfo(childIdx);
// a sanity check: if the lod is not the same then this
// parent is not at the right place
if(childLoc.lod != lod)
break;
// Make sure it is within
if (childLoc.x >= sw.x &&
childLoc.x <= ne.x &&
childLoc.y >= sw.y &&
childLoc.y <= ne.y) {
// Is it alread there ?
if(!tmpCurrent[(childLoc.y - sw.y)*dx + (childLoc.x - sw.x)]) {
// Not there, add it
AddToLoadList(childLoc.x, childLoc.y, childLoc.addr);
}
}
}
}
}
bool trpgPageManager::LodPageInfo::AddToLoadList(int x, int y, const trpgwAppAddress& addr)
{
trpg2iPoint sw,ne;
// Figure out the lower left and upper right corners
// in cell coordinates
sw.x = cell.x - aoiSize.x;
sw.y = cell.y - aoiSize.y;
ne.x = cell.x + aoiSize.x;
ne.y = cell.y + aoiSize.y;
sw.x = MAX(0,sw.x);
sw.y = MAX(0,sw.y);
ne.x = MIN(lodSize.x-1,ne.x);
ne.y = MIN(lodSize.y-1,ne.y);
if (x >= sw.x &&
x <= ne.x &&
y >= sw.y &&
y <= ne.y) {
trpgManagedTile *tile = 0;
if(freeList.size() > 0){
tile = freeList[0];
freeList.pop_front();
}
else
tile = new trpgManagedTile();
tile->SetTileLoc(x, y, lod);
tile->SetTileAddress(addr);
load.push_back(tile);
return true;
}
else
return false;
}
/* Update does the major work of figuring out what to load and
what to unload.
@ -405,7 +618,17 @@ void trpgPageManager::LodPageInfo::Update()
}
current.resize(curPos);
bool doUpdate = true;
if(majorVersion == 2 && minorVersion >= 1)
{
// Version 2.1, we update only lod 0 since the tile table
// will only contain lod 0. All tiles from other lod must be
// update through the trpgPageManager::AckLoad(tile info)
if(lod != 0)
doUpdate = false;
}
if(doUpdate)
{
// Sort the currently loaded stuff into a spatial array
// so we can figure out what needs to be loaded in addition.
int dx,dy;
@ -434,15 +657,47 @@ void trpgPageManager::LodPageInfo::Update()
} else
tile = new trpgManagedTile();
tile->SetTileLoc(x+sw.x,y+sw.y,lod);
trpgwAppAddress addr;
float32 zmin, zmax;
if(tileTable && tileTable->GetTile(x+sw.x, y+sw.y, lod, addr, zmin, zmax))
tile->SetTileAddress(addr);
load.push_back(tile);
}
}
}
}
// That's it. All the rest is handled by the caller
// iterating through the tiles to load and unload.
}
// Get the list of currently loaded tiles that falls wiithin the area calculted from
// the given paging distance
void trpgPageManager::LodPageInfo::GetLoadedTileWithin(double pagingDistance, std::vector<trpgManagedTile*>& tileList)
{
trpg2iPoint aoi_size((int)(pagingDistance/cellSize.x) +1,
(int)(pagingDistance/cellSize.y) +1);
// Calculate the area that we must check, in parent cell coordinate
trpg2iPoint sw, ne;
sw.x = cell.x - aoi_size.x;
sw.y = cell.y - aoi_size.y;
ne.x = cell.x + aoi_size.x;
ne.y = cell.y + aoi_size.y;
sw.x = MAX(0,sw.x);
sw.y = MAX(0,sw.y);
ne.x = MIN(lodSize.x-1,ne.x);
ne.y = MIN(lodSize.y-1,ne.y);
tileList.clear();
for (unsigned i=0; i <current.size(); i++) {
if (current[i] && isWithin(current[i],sw,ne))
tileList.push_back(current[i]);
}
}
void trpgPageManager::LodPageInfo::Print(trpgPrintBuffer &buf)
{
char line[1024];
@ -508,11 +763,49 @@ void trpgPageManager::Init(trpgr_Archive *inArch)
const trpgHeader *head = archive->GetHeader();
int numLod;
head->GetNumLods(numLod);
head->GetVersion(majorVersion, minorVersion);
// Reset the terrain LOD paging classes.
valid = true;
pageInfo.resize(numLod);
for (int i=0;i<numLod;i++) {
if(i > 3)
pageInfo[i].Init(archive,i,scale, 4);
else
pageInfo[i].Init(archive,i,scale);
}
}
// We might want to init only to support the tile table content.
// For Version 2.1 the tile table contain only lod 0.
// We might want to do that to use another paging scheme for
// lower lod
void trpgPageManager::Init(trpgr_Archive *inArch, int maxLod)
{
archive = inArch;
// We're resetting everything. In general, Init should only
// be called once, but it'll work fine if you call it more than once.
lastLoad = None;
lastTile = NULL;
lastLod = -1;
// Need to know the number of terrain LODs
const trpgHeader *head = archive->GetHeader();
int numLod;
head->GetNumLods(numLod);
head->GetVersion(majorVersion, minorVersion);
if(maxLod > numLod)
maxLod = numLod;
// Reset the terrain LOD paging classes.
valid = true;
pageInfo.resize(maxLod);
for (int i=0;i<maxLod;i++) {
if(i > 3)
pageInfo[i].Init(archive,i,scale, 4);
else
pageInfo[i].Init(archive,i,scale);
}
}
@ -543,6 +836,34 @@ bool trpgPageManager::SetLocation(trpg2dPoint &pt)
change = true;
}
if(majorVersion == 2 && minorVersion >= 1 && change) {
// Version 2.1 and over
// Since we don't have a tile table for lod > 0,
// we must rely on the parent to see if children
// tiles have to be loaded:
// First we get the list of parent tiles that falls
// in the area of interest of the children,
// Second we add to the load list all the parent's
// children that are no already part of the list
for(unsigned int lodIdx = 1; lodIdx < pageInfo.size(); ++lodIdx) {
LodPageInfo& parentInfo = pageInfo[lodIdx -1];
LodPageInfo& childInfo = pageInfo[lodIdx];
// Get the list of parents tile that are currently
// loaded in the children aoi
std::vector<trpgManagedTile*> parentList;
parentInfo.GetLoadedTileWithin(childInfo.GetPageDistance(), parentList);
// Add the children of those parents to the load list
// of the children info, if they are not already there
childInfo.AddChildrenToLoadList(parentList);
}
}
return change;
}
@ -565,20 +886,43 @@ trpgManagedTile *trpgPageManager::GetNextLoad()
if (tile) {
lastLoad = Load;
lastTile = tile;
lastLod = tile->lod;
lastLod = tile->location.lod;
}
return tile;
}
void trpgPageManager::AckLoad()
{
std::vector<TileLocationInfo> children;
AckLoad(children);
}
void trpgPageManager::AckLoad(std::vector<TileLocationInfo> const& children)
{
// If we're not in the middle of a load, register our displeasure
if (lastLoad != Load)
throw 1;
LodPageInfo &info = pageInfo[lastLod];
info.AckLoad();
if(majorVersion >= 2 && minorVersion >=1)
{
if(children.size() > 0)
{
LodPageInfo& childInfo = pageInfo[lastLod+1];
for(unsigned int idx = 0; idx < children.size(); ++idx)
{
TileLocationInfo const&childLocInfo = children[idx];
if(childLocInfo.lod != lastLod+1)
continue; // Something wrong here
childInfo.AddToLoadList(childLocInfo.x, childLocInfo.y, childLocInfo.addr);
// Also save info in parent tile
lastTile->SetChildLocationInfo(idx, childLocInfo);
}
}
}
pageInfo[lastLod].AckLoad();
lastLoad = None;
lastTile = NULL;
}
@ -617,7 +961,7 @@ trpgManagedTile *trpgPageManager::GetNextUnload()
if (tile) {
lastLoad = Unload;
lastTile = tile;
lastLod = tile->lod;
lastLod = tile->location.lod;
}
return tile;
@ -668,6 +1012,40 @@ void trpgPageManager::Print(trpgPrintBuffer &buf)
}
}
void *trpgr_ChildRefCB::Parse(trpgToken tok, trpgReadBuffer& rbuf)
{
// It should be a tile ref token, if not then something is wrong
if(tok == TRPG_CHILDREF)
{
childList.push_back(trpgChildRef());
trpgChildRef &childRef = childList.back();
if(childRef.Read(rbuf))
return &childRef;
else
return false;
}
else
return 0;
}
void trpgr_ChildRefCB::Reset()
{
childList.clear();
}
unsigned int trpgr_ChildRefCB::GetNbChildren() const
{
return childList.size();
}
const trpgChildRef& trpgr_ChildRefCB::GetChildRef(unsigned int idx) const
{
if(idx >= childList.size())
throw std::invalid_argument(
"trpgPageManageTester::ChildRefCB::GetChild(): index argument out of bound.");
else
return childList[idx];
}
/* Page Manager Tester
These methods are used to test the Paging Manager.
*/
@ -691,6 +1069,11 @@ void trpgPageManageTester::Init(trpgPrintBuffer *pBuf,trpgPageManager *pMan,trpg
if (!archive->isValid())
throw 1;
const trpgHeader *header = archive->GetHeader();
header->GetVersion(majorVersion, minorVersion);
tileParser.AddCallback(TRPG_CHILDREF, &childRefCB, false);
// Start up the paging manager
manager->Init(archive);
}
@ -801,6 +1184,42 @@ void trpgPageManageTester::ProcessChanges()
while ((loadTile = manager->GetNextLoad())) {
loadTile->GetTileLoc(x,y,lod);
sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line);
if(majorVersion == 2 && minorVersion >= 1)
{
// Version 2.1 and over
// We need to parse the loaded tile to get all of its children info
const trpgwAppAddress& tileAddress = loadTile->GetTileAddress();
trpgMemReadBuffer buf(archive->GetEndian());
if(archive->ReadTile(tileAddress, buf))
{
childRefCB.Reset();
if(tileParser.Parse(buf))
{
// childRefCB should now have alist of trpgChildRef found in the tile
unsigned int nbChildRef = childRefCB.GetNbChildren();
if(nbChildRef > 0)
{
std::vector<TileLocationInfo> locInfoList;
for(unsigned int idx = 0; idx < nbChildRef; ++idx)
{
const trpgChildRef& childRef = childRefCB.GetChildRef(idx);
locInfoList.push_back(TileLocationInfo());
TileLocationInfo& locInfo = locInfoList.back();
childRef.GetTileLoc(locInfo.x, locInfo.y, locInfo.lod);
childRef.GetTileAddress(locInfo.addr);
}
manager->AckLoad(locInfoList);
}
else
manager->AckLoad();
}
}
else
manager->AckLoad();
}
else
manager->AckLoad();
}
printBuf->DecreaseIndent();

View File

@ -27,11 +27,21 @@
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.
*/
TX_EXDECL class TX_CLDECL trpgManagedTile {
TX_EXDECL class TX_CLDECL trpgManagedTile
{
friend class trpgPageManager;
public:
trpgManagedTile(void);
@ -53,9 +63,17 @@ public:
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);
@ -114,11 +132,25 @@ public:
Tile.
*/
void Print(trpgPrintBuffer &);
// 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,6 +160,10 @@ 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.
};
@ -140,13 +176,15 @@ protected:
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 {
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
@ -172,8 +210,18 @@ public:
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(void);
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
@ -204,6 +252,7 @@ public:
*/
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.
@ -222,7 +271,7 @@ protected:
/* Information associated with each terrain level of
detail as related to paging.
*/
class LodPageInfo {
TX_EXDECL class TX_CLDECL LodPageInfo {
friend class trpgPageManager;
public:
LodPageInfo(void);
@ -231,7 +280,7 @@ protected:
/* Initializes the class with its current LOD.
It figures out all the rest.
*/
virtual bool Init(trpgr_Archive *, int myLod, double scale);
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
@ -245,7 +294,11 @@ protected:
virtual trpgManagedTile *GetNextLoad(void);
// Acknowledge the load. Move the active tile to the
// loaded list.
virtual void AckLoad(void);
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
@ -256,13 +309,61 @@ protected:
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;
}
protected:
virtual void Clean(void);
virtual void Update(void);
// Add to the load list the given tile if it is within the proper
// bound
bool AddToLoadList(int x, int y, const trpgwAppAddress& addr);
// 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);
// Check if the given tile is within the area we care about
bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne);
// 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);
bool valid;
// Terrain LOD we're responsible for
@ -316,6 +417,11 @@ protected:
// List of tile pointers we can reuse
std::deque<trpgManagedTile *> freeList;
// TerraPage version
int majorVersion, minorVersion;
const trpgTileTable *tileTable;
};
// Per terrain lod paging information
@ -339,13 +445,46 @@ 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 {
TX_EXDECL class TX_CLDECL trpgPageManageTester
{
public:
trpgPageManageTester();
virtual ~trpgPageManageTester();
@ -367,12 +506,19 @@ public:
void RandomTest(int no=100,int seed=-1);
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

View File

@ -44,18 +44,21 @@ void trpgMatTable::Reset()
{
numTable = 0;
numMat = 0;
matTables.resize(0);
materialMap.clear();
}
// Validity check
bool trpgMatTable::isValid() const
{
if (numTable <= 0 || numMat <= 0)
if(materialMap.size()==0)
return false;
for (unsigned int i=0;i<matTables.size();i++)
if (!matTables[i].isValid())
// get an iterator for the materialMap
MaterialMapType::const_iterator itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++) {
if(!(*itr).second.isValid()) {
return false;
}
}
return true;
}
@ -66,82 +69,24 @@ void trpgMatTable::SetNumTable(int no)
if ((no < 0) || (no==numTable))
return;
numTable = no;
matTables.resize(numTable*numMat);
}
void trpgMatTable::SetNumMaterial(int no)
void trpgMatTable::SetNumMaterial(int /*no*/)
{
if (no < 0)
return;
// This method is obsolete since we're using the project handle
// and a map to store the materials, instead of a vector
}
// Note: Doesn't preserve the order of what was there
// It has to, if we're going to have multiple material subtables.
// Perhaps the manner of organizing these should be revisited. This is
// pretty inefficient, but it will hopefully only amount to extra
// minutes per build at most.
matTables.resize(no*numTable);
if ((no<=numMat) || (numTable==1)) {
// If they're shrinking the table, they had better be starting over.
// If there's only one table, no problems.
numMat = no;
} else {
// For each table, determine the last 'used' element.
// Then, move them all, starting with the last one, and
// reset the others. Slow, slow, slow.
int loop;
for (int tableIter=numTable-1;tableIter>=0;tableIter--) {
int lastEntry;
for (lastEntry=0;lastEntry<numMat;lastEntry++) {
if (matTables[tableIter*numMat+lastEntry].shadeModel==999) break;
}
// move them
if (tableIter && lastEntry) { // no need to move the first subtable
for (loop=lastEntry-1;loop>=0;loop--)
matTables[tableIter*no+loop]=matTables[tableIter*numMat+loop];
}
// reset the others
for (loop=lastEntry;loop<no;loop++) matTables[tableIter*no+loop].Reset();
}
numMat = no;
}
}
void trpgMatTable::SetMaterial(int nt,int nm,const trpgMaterial &mat)
{
if (nt < 0 || nt >= numTable)
return;
if (nm < 0 || nm >= numMat)
return;
matTables[nt*numMat+nm] = mat;
// ensure that this entry isn't re-used
if (mat.shadeModel>100) matTables[nt*numMat+nm].shadeModel=trpgMaterial::Smooth;
}
void trpgMatTable::SetMaterial(int nm,const trpgMaterial &mat)
{
if (nm < 0 || nm >= numMat)
return;
for (int i=0;i<numTable;i++) {
matTables[i*numMat+nm] = mat;
// ensure that this entry isn't re-used
if (mat.shadeModel>100) matTables[i*numMat+nm].shadeModel=trpgMaterial::Smooth;
}
materialMap[nm] = mat;
numMat = materialMap.size();
}
#define CEQ(ca,cb) (ca.red == cb.red && ca.green == cb.green && ca.blue == cb.blue)
int trpgMatTable::AddMaterial(const trpgMaterial &mat,bool lookForExisting)
{
return AddMaterialInSubtable(mat, 1, lookForExisting);
}
int trpgMatTable::AddMaterialInSubtable(const trpgMaterial &mat,int table, bool lookForExisting)
{
// Doesn't work if there's more than one table
//if (numTable != 1)
// return -1;
trpgMaterial cmat = mat; // necessary?
// having a shadeModel of 999 indicates that the entry is free. I thought this would
@ -149,24 +94,18 @@ int trpgMatTable::AddMaterialInSubtable(const trpgMaterial &mat,int table, bool
// at all. Now my kludge takes so much work it's almost worth doing it right.
if (cmat.shadeModel>100) cmat.shadeModel=trpgMaterial::Smooth;
int baseMat=numMat;
int offset=(table-1)*numMat+baseMat;
if (table>numTable) {
// Add another table. But we don't have to shuffle indices or reset entries
SetNumTable(table);
offset=(table-1)*numMat;
matTables[offset] = cmat;
return 0;
}
int baseMat=0;
bool spaceInTable=false;
//int offset=baseMat;
if (lookForExisting) {
// Look for a matching base material minus the textures
for (baseMat = 0;baseMat < numMat;baseMat++) {
offset=(table-1)*numMat+baseMat;
trpgMaterial &bm = matTables[offset];
//for (baseMat = 0;baseMat < numMat;baseMat++) {
MaterialMapType::const_iterator itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++) {
baseMat = itr->first;
const trpgMaterial &bm = itr->second;
if (bm.shadeModel==999) {
// this is an 'empty' entry. Means we won't find it, either.
spaceInTable=true;
@ -187,8 +126,8 @@ int trpgMatTable::AddMaterialInSubtable(const trpgMaterial &mat,int table, bool
bool isSame=true;
unsigned int i;
for (i=0;i<cmat.texEnvs.size();i++) {
trpgTextureEnv &e1 = cmat.texEnvs[i];
trpgTextureEnv &e2 = bm.texEnvs[i];
const trpgTextureEnv &e1 = cmat.texEnvs[i];
const trpgTextureEnv &e2 = bm.texEnvs[i];
if (e1.envMode != e2.envMode ||
e1.minFilter != e2.minFilter ||
e1.magFilter != e2.magFilter ||
@ -208,14 +147,14 @@ int trpgMatTable::AddMaterialInSubtable(const trpgMaterial &mat,int table, bool
}
// Didn't find it. Add it
if (spaceInTable) {
matTables[offset]=cmat;
return baseMat;
} else {
SetNumMaterial(baseMat+1); // shifts values, changes numMat
matTables[table*numMat-1]=cmat;
return baseMat;
}
int idx;
if(cmat.writeHandle)
idx = cmat.GetHandle();
else
idx = numMat;
materialMap[idx] = cmat;
numMat = materialMap.size();
return idx;
}
// Write out material table
@ -231,9 +170,10 @@ bool trpgMatTable::Write(trpgWriteBuffer &buf)
buf.Add((int32)numMat);
// Write the materials
for (unsigned int i=0;i<matTables.size();i++)
matTables[i].Write(buf);
MaterialMapType::const_iterator itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++) {
((trpgMaterial)(*itr).second).Write(buf);
}
buf.End();
return true;
@ -247,30 +187,41 @@ bool trpgMatTable::Write(trpgWriteBuffer &buf)
// Get functions
bool trpgMatTable::GetNumTable(int &no) const
{
if (!isValid()) return false;
if (!isValid()) {
no = 0; // otherwise this causes errors because it is uninitialized.
return false;
}
no = numTable;
return true;
}
bool trpgMatTable::GetNumMaterial(int &no) const
{
if (!isValid()) return false;
if (!isValid()) {
no = 0;
return false;
}
no = numMat;
return true;
}
bool trpgMatTable::GetMaterial(int nt,int nm,trpgMaterial &mat) const
{
if (!isValid()) return false;
if (nt < 0 || nt >= numTable || nm < 0 || nm >= numMat)
return false;
mat = matTables[nt*numMat+nm];
MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm);
if(itr == materialMap.end())
return false;
mat = (*itr).second;
return true;
}
const trpgMaterial *trpgMatTable::GetMaterialRef(int nt,int nm) const
{
if (nt < 0 || nt >= numTable || nm < 0 || nm >= numMat)
MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm);
if(itr == materialMap.end())
return false;
return const_cast<trpgMaterial *>(&matTables[nt*numMat+nm]);
return const_cast<trpgMaterial *>(&(*itr).second);
}
@ -281,15 +232,15 @@ bool trpgMatTable::Read(trpgReadBuffer &buf)
int32 len;
bool status;
int i,j;
int nMat,nTable;
try {
buf.Get(numTable);
buf.Get(numMat);
if (numTable <= 0 || numMat < 0) throw 1;
buf.Get(nTable);
buf.Get(nMat);
if (nTable <= 0 || nMat < 0) throw 1;
// Read the materials
matTables.resize(numTable*numMat);
for (i=0;i<numTable;i++)
for (j=0;j<numMat;j++) {
for (i=0;i<nTable;i++)
for (j=0;j<nMat;j++) {
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
@ -297,8 +248,10 @@ bool trpgMatTable::Read(trpgReadBuffer &buf)
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
matTables[i*numMat+j] = mat;
AddMaterial(mat,false);
}
numTable += nTable;
numMat = materialMap.size();
}
catch (...) {
return false;
@ -533,6 +486,8 @@ void trpgMaterial::Reset()
attrSet.smc = -1;
attrSet.stp = -1;
attrSet.swc = -1;
handle = -1;
writeHandle = false;
}
// Validity check
@ -704,7 +659,7 @@ bool trpgMaterial::Write(trpgWriteBuffer &buf)
buf.End();
buf.Begin(TRPGMAT_NORMAL);
buf.Add(autoNormal);
buf.Add((int32)autoNormal);
buf.End();
buf.Begin(TRPGMAT_TEXTURE);
@ -717,7 +672,7 @@ bool trpgMaterial::Write(trpgWriteBuffer &buf)
// Bump mapping properties
buf.Begin(TRPGMAT_BUMP);
buf.Add(isBump);
buf.Add((int32)isBump);
buf.End();
// Attributes (e.g. fid, smc)
@ -728,6 +683,15 @@ bool trpgMaterial::Write(trpgWriteBuffer &buf)
buf.Add(attrSet.swc);
buf.End();
/**
* If the terrapage version is >= 2.3, handle will be set to a unique identifier.
**/
if(writeHandle) {
buf.Begin(TRPGMAT_HANDLE);
buf.Add((int)handle);
buf.End();
}
buf.End();
return true;
@ -871,6 +835,7 @@ bool trpgMaterial::GetAttr(int attrCode,int &ret) const
return true;
}
/* Material CB
Used to parse tokens for a material.
*/
@ -938,7 +903,7 @@ void * materialCB::Parse(trpgToken tok,trpgReadBuffer &buf)
break;
case TRPGMAT_NORMAL:
{
int tmp;
int32 tmp;
buf.Get(tmp);
if (tmp)
autoNormal = true;
@ -964,7 +929,7 @@ void * materialCB::Parse(trpgToken tok,trpgReadBuffer &buf)
break;
case TRPGMAT_BUMP:
{
int tmp;
int32 tmp;
buf.Get(tmp);
bool isBump = (tmp) ? true : false;
mat->SetIsBumpMap(isBump);
@ -983,6 +948,13 @@ void * materialCB::Parse(trpgToken tok,trpgReadBuffer &buf)
mat->SetAttr(trpgMaterial::TR_SWC,tmp);
}
break;
case TRPGMAT_HANDLE:
{
int hdl;
buf.Get(hdl);
mat->SetHandle(hdl);
}
break;
default:
break;
}
@ -1011,6 +983,7 @@ bool trpgMaterial::Read(trpgReadBuffer &buf)
parse.AddCallback(TRPGMAT_TEXTURE,&matCb,false);
parse.AddCallback(TRPGMAT_BUMP,&matCb,false);
parse.AddCallback(TRPGMAT_ATTR,&matCb,false);
parse.AddCallback(TRPGMAT_HANDLE,&matCb,false);
parse.Parse(buf);
return isValid();
@ -1027,13 +1000,16 @@ trpgTexture::trpgTexture()
mode = External;
type = trpg_Unknown;
numLayer = -1;
org = trpg_RGBX_Neither;
name = NULL;
useCount = 0;
sizeX = sizeY = -1;
addr.file = 0;
addr.offset = 0;
addr.col = -1;
addr.row = -1;
isMipmap = false;
writeHandle = false;
handle = -1;
}
// Copy construction
@ -1043,15 +1019,18 @@ trpgTexture::trpgTexture(const trpgTexture &in):
mode = in.mode;
type = in.type;
numLayer = in.numLayer; // RGBX
org = in.org; // RGBX
name = NULL;
SetName(in.name);
useCount = in.useCount;
sizeX = in.sizeX; sizeY = in.sizeY;
addr.file = in.addr.file;
addr.offset = in.addr.offset;
addr.row = in.addr.row;
addr.col = in.addr.col;
isMipmap = in.isMipmap;
// storageSize + levelOffset
handle = in.handle;
writeHandle = in.writeHandle;
}
// Destruction
@ -1066,7 +1045,6 @@ void trpgTexture::Reset()
mode = External;
type = trpg_Unknown;
numLayer = -1;
org = trpg_RGBX_Neither;
if (name)
delete [] name;
name = NULL;
@ -1074,11 +1052,18 @@ void trpgTexture::Reset()
sizeX = sizeY = -1;
addr.file = 0;
addr.offset = 0;
addr.row = -1;
addr.col = -1;
isMipmap = false;
storageSize.clear();
levelOffset.clear();
handle = -1;
writeHandle = false;
}
// Valid if we've got a name
bool trpgTexture::isValid() const
{
@ -1120,7 +1105,8 @@ void trpgTexture::SetName(const char *inName)
// Get Name
bool trpgTexture::GetName(char *outName,int outLen) const
{
if (!isValid()) return false;
if (!isValid())
return false;
int len = (name) ? strlen(name) : 0;
strncpy(outName,name,MIN(len,outLen)+1);
@ -1149,18 +1135,6 @@ bool trpgTexture::GetImageType(ImageType &outType) const
return true;
}
void trpgTexture::SetImageOrganization(ImageOrg inOrg)
{
org = inOrg;
}
bool trpgTexture::GetImageOrganization(ImageOrg &outOrg) const
{
outOrg = org;
return true;
}
void trpgTexture::SetImageSize(const trpg2iPoint &inSize)
{
sizeX = inSize.x;
@ -1218,17 +1192,25 @@ bool trpgTexture::GetImageDepth(int32 &depth) const
case trpg_RGBX:
depth = numLayer;
break;
case trpg_DDS:
depth = 3;
break;
case trpg_DXT1:
depth = 3;
break;
case trpg_DXT3:
depth = 4;
depth = 3;
break;
case trpg_DXT5:
depth = 4;
depth = 3;
break;
case trpg_MCM5:
depth = 5;
break;
case trpg_MCM6R:
case trpg_MCM6A:
depth = 6;
break;
case trpg_MCM7RA:
case trpg_MCM7AR:
depth = 7;
break;
default:
depth = -1;
@ -1245,8 +1227,9 @@ void trpgTexture::SetNumLayer(int layers)
bool trpgTexture::GetNumLayer(int &layers) const
{
if (!isValid()) return false;
layers = numLayer;
if (!isValid())
return false;
GetImageDepth(layers);
return true;
}
@ -1261,7 +1244,8 @@ void trpgTexture::AddTile()
}
bool trpgTexture::GetNumTile(int &num) const
{
if (!isValid()) return false;
if (!isValid())
return false;
num = useCount;
return true;
}
@ -1282,11 +1266,13 @@ trpgTexture &trpgTexture::operator = (const trpgTexture &in)
// RGBX
numLayer = in.numLayer;
org = in.org;
isMipmap = in.isMipmap;
addr = in.addr;
writeHandle = in.writeHandle;
handle = in.handle;
return *this;
}
@ -1308,13 +1294,13 @@ int trpgTexture::operator == (const trpgTexture &in) const
if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY &&
isMipmap == in.isMipmap &&
addr.file == in.addr.file && addr.offset == in.addr.offset &&
numLayer == in.numLayer && org == in.org)
addr.row == in.addr.row && addr.col==in.addr.col )
return 1;
break;
case Global:
case Template:
if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY &&
isMipmap == in.isMipmap && numLayer == in.numLayer && org == in.org)
isMipmap == in.isMipmap)
return 1;
}
@ -1394,10 +1380,10 @@ bool trpgTexture::Write(trpgWriteBuffer &buf)
buf.Add(sizeY);
buf.Add(addr.file);
buf.Add(addr.offset);
buf.Add(isMipmap);
// More for MCMs
buf.Add(numLayer);
buf.Add((unsigned char)org);
buf.Add((int32)isMipmap);
if(writeHandle) {
buf.Add((int32)handle);
}
buf.End();
return true;
@ -1418,17 +1404,26 @@ bool trpgTexture::Read(trpgReadBuffer &buf)
unsigned char bval;
buf.Get(bval); mode = (trpgTexture::ImageMode)bval;
buf.Get(bval); type = (trpgTexture::ImageType)bval;
GetImageDepth(numLayer); // heh
buf.Get(sizeX);
buf.Get(sizeY);
buf.Get(addr.file);
buf.Get(addr.offset);
int ival;
int32 ival;
buf.Get(ival);
isMipmap = (ival) ? true : false;
if ( !buf.isEmpty() ) {
buf.Get(numLayer);
buf.Get(bval); org = (trpgTexture::ImageOrg)bval;
// Read the handle if we can..
try {
if(!buf.Get((int32 &)handle)) {
handle = -1;
}
else {
writeHandle = true;
}
}
catch (...) {
handle = -1;
}
isMipmap = (ival) ? true : false;
}
catch (...) {
return false;
@ -1475,6 +1470,20 @@ void trpgTexture::CalcMipLevelSizes()
pad_size = 4;
pixel_size = numLayer;
break;
case trpg_MCM5:
pad_size = 4;
pixel_size = 5;
break;
case trpg_MCM6R:
case trpg_MCM6A:
pad_size = 4;
pixel_size = 6;
break;
case trpg_MCM7RA:
case trpg_MCM7AR:
pad_size = 4;
pixel_size = 7;
break;
case trpg_INT8:
pad_size = 4;
pixel_size = 1;
@ -1588,7 +1597,8 @@ void trpgTexture::CalcMipLevelSizes()
// Constructor
trpgTexTable::trpgTexTable()
{
currentRow = -1;
currentCol = -1;
}
trpgTexTable::trpgTexTable(const trpgTexTable &in):
trpgReadWriteable(in)
@ -1600,7 +1610,9 @@ trpgTexTable::trpgTexTable(const trpgTexTable &in):
void trpgTexTable::Reset()
{
errMess[0] = '\0';
texList.resize(0);
textureMap.clear();
currentRow = -1;
currentCol = -1;
}
// Destructor
@ -1612,58 +1624,71 @@ trpgTexTable::~trpgTexTable()
// Validity check
bool trpgTexTable::isValid() const
{
if (!texList.size())
if (!textureMap.size())
{
strcpy(errMess, "Texture table list is empty");
return false;
}
for (unsigned int i=0;i<texList.size();i++)
{
if (!texList[i].isValid())
{
TextureMapType::const_iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++) {
if(!itr->second.isValid()) {
strcpy(errMess, "A texture in the texture table is invalid");
return false;
}
}
return true;
}
// Set functions
void trpgTexTable::SetNumTextures(int no)
void trpgTexTable::SetNumTextures(int /*no*/)
{
texList.resize(no);
// obsolete. This method doesn't need to do anything since we're using a map instead of a vector.
// texList.resize(no);
}
int trpgTexTable::AddTexture(const trpgTexture &inTex)
{
texList.resize(texList.size()+1);
texList[texList.size()-1] = inTex;
return texList.size()-1;
TeAttrHdl hdl = inTex.GetHandle();
if(hdl==-1) {
// if no handle is specified, we will use an index as the handle (just like before 2.3)
hdl = textureMap.size();
}
TextureMapType::iterator itr = textureMap.find(hdl);
// Don't overwrite the texture if it was already there
if(itr==textureMap.end())
textureMap[hdl] = inTex;
return hdl;
}
int trpgTexTable::FindAddTexture(const trpgTexture &inTex)
{
for (unsigned int i=0;i<texList.size();i++)
if (texList[i] == inTex)
return i;
TextureMapType::iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++) {
trpgTexture tx = itr->second;
if(tx == inTex) {
return itr->first;
}
}
return AddTexture(inTex);
}
void trpgTexTable::SetTexture(int id,const trpgTexture &inTex)
{
if (id < 0 || (unsigned int)id >= texList.size())
if (id < 0)
return;
texList[id] = inTex;
textureMap[id] = inTex;
}
// Copy operator
trpgTexTable &trpgTexTable::operator = (const trpgTexTable &in)
{
Reset();
for (unsigned int i=0;i<in.texList.size();i++)
AddTexture(in.texList[i]);
TextureMapType::const_iterator itr = in.textureMap.begin();
for ( ; itr != in.textureMap.end( ); itr++) {
trpgTexture tex = itr->second;
in.GetTexture(itr->first,tex);
AddTexture(tex);
}
return *this;
}
@ -1677,10 +1702,12 @@ bool trpgTexTable::Write(trpgWriteBuffer &buf)
return false;
buf.Begin(TRPGTEXTABLE2);
numTex = texList.size();
numTex = textureMap.size();
buf.Add(numTex);
for (unsigned int i=0;i<texList.size();i++)
texList[i].Write(buf);
TextureMapType::iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++) {
itr->second.Write(buf);
}
buf.End();
return true;
@ -1693,22 +1720,51 @@ bool trpgTexTable::Write(trpgWriteBuffer &buf)
// Get functions
bool trpgTexTable::GetNumTextures(int &no) const
{
no = texList.size();
no = textureMap.size();
if (!isValid()) return false;
return true;
}
bool trpgTexTable::GetTexture(int id,trpgTexture &ret) const
{
if (!isValid()) return false;
if (id < 0 || id >= (int)texList.size()) return false;
if (!isValid())
return false;
if (id < 0)
return false;
TextureMapType::const_iterator itr = textureMap.find(id);
if(itr == textureMap.end()) {
return false;
}
ret = itr->second;
ret = texList[id];
return true;
}
const trpgTexture *trpgTexTable::GetTextureRef(int id) const
{
if (id < 0 || id >= (int)texList.size()) return NULL;
return &texList[id];
if (id < 0)
return false;
TextureMapType::const_iterator itr = textureMap.find(id);
if(itr == textureMap.end()) {
return false;
}
const trpgTexture *ret = &(itr->second);
return ret;
}
const trpgTexture *trpgTexTable::FindByName(const char *name, int &texid) const
{
TextureMapType::const_iterator itr = textureMap.begin();
for ( ; itr != textureMap.end( ); itr++) {
char thisName[1024];
thisName[0] = '\0';
itr->second.GetName(thisName,1023);
if(strcasecmp(thisName,name)==0)
{
texid = itr->first;
return &(itr->second);
}
}
return false;
}
bool trpgTexTable::Read(trpgReadBuffer &buf)
@ -1719,13 +1775,22 @@ bool trpgTexTable::Read(trpgReadBuffer &buf)
try {
buf.Get(numTex);
texList.resize(numTex);
for (int i=0;i<numTex;i++) {
buf.GetToken(texTok,len);
if (texTok != TRPGTEXTURE) throw 1;
buf.PushLimit(len);
trpgTexture &tex = texList[i];
trpgTexture tex;
bool status = tex.Read(buf);
//set the block for multi-archive archives (version>=2.3)
if((currentRow!=-1)&&(currentCol!=-1)) {
trpgwAppAddress taddr;
tex.GetImageAddr(taddr);
taddr.col = currentCol;
taddr.row = currentRow;
tex.SetImageAddr(taddr);
}
AddTexture(tex);
buf.PopLimit();
if (!status) throw 1;
}
@ -1737,6 +1802,7 @@ bool trpgTexTable::Read(trpgReadBuffer &buf)
return true;
}
/* **************
Local Material
**************
@ -1749,6 +1815,8 @@ trpgLocalMaterial::trpgLocalMaterial()
addr.resize(1);
addr[0].file = 0;
addr[0].offset = 0;
addr[0].col = -1;
addr[0].row = -1;
}
trpgLocalMaterial::~trpgLocalMaterial()
@ -1769,6 +1837,8 @@ void trpgLocalMaterial::Reset()
addr.resize(1);
addr[0].file = 0;
addr[0].offset = 0;
addr[0].col = -1;
addr[0].row = -1;
}
bool trpgLocalMaterial::GetBaseMaterial(int32 &subTable,int32 &matID) const
@ -1885,8 +1955,8 @@ bool trpgLocalMaterial::Write(trpgWriteBuffer &buf)
buf.Add(addr[0].offset);
// and in case there's more...
int numAddrs=(int)(addr.size());
buf.Add(numAddrs-1); // write even if its zero for reading purposes
if (numAddrs>1) {
buf.Add(numAddrs-1); // suppressed due to breaking old readers.
for (int i=1;i<numAddrs;i++) {
buf.Add(addr[i].file);
buf.Add(addr[i].offset);
@ -1921,6 +1991,8 @@ bool trpgLocalMaterial::Read(trpgReadBuffer &buf)
for (int i=1;i<=extraAddrs;i++) {
buf.Get(addr[i].file);
buf.Get(addr[i].offset);
addr[i].col = -1;
addr[i].row = -1;
}
}
}

View File

@ -17,7 +17,9 @@
#include <stdio.h>
#include <string.h>
/* trpage_mode.cpp
#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.
*/
@ -33,14 +35,29 @@ trpgModel::trpgModel()
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()
@ -49,6 +66,9 @@ void trpgModel::Reset()
delete [] name;
name = NULL;
useCount = 0;
diskRef = -1;
handle = -1;
writeHandle = false;
}
trpgModel::~trpgModel()
@ -57,24 +77,25 @@ trpgModel::~trpgModel()
}
// Set functions
void trpgModel::SetType(int t)
{
type = t;
}
void trpgModel::SetName(const char *nm)
{
if (name)
delete [] name;
if (nm)
{
name = new char[(nm ? strlen(nm) : 0)+1];
strcpy(name,nm);
type = External;
}
}
void trpgModel::SetReference(trpgDiskRef pos)
{
if (name)
delete [] name;
diskRef = pos;
type = Local;
}
void trpgModel::SetNumTiles(int num)
{
@ -110,7 +131,8 @@ trpgModel& trpgModel::operator = (const trpgModel &in)
SetName(in.name);
diskRef = in.diskRef;
useCount = in.useCount;
writeHandle = in.writeHandle;
handle = in.handle;
return *this;
}
@ -146,14 +168,38 @@ bool trpgModel::Write(trpgWriteBuffer &buf)
if (!isValid())
return false;
buf.Begin(TRPGMODELREF);
// 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);
#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;
@ -172,7 +218,7 @@ bool trpgModel::GetType(int &t)
}
bool trpgModel::GetName(char *str,int strLen) const
{
if (!isValid() || type != External) return false;
if (!isValid()) return false;
int len = (name ? strlen(name) : 0);
strncpy(str,name,MIN(len,strLen)+1);
return true;
@ -191,24 +237,54 @@ bool trpgModel::GetReference(trpgDiskRef &ref) const
return true;
}
bool trpgModel::Read(trpgReadBuffer &buf)
bool trpgModel::Read(trpgReadBuffer &buf, bool hasHandle)
{
// 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 {
// 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;
}
// going to make this fail if the buffer isn't empty.
if (buf.TestLimit(1)) return false;
return isValid();
}
@ -227,49 +303,72 @@ 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())
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;
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());
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;
}
@ -282,9 +381,11 @@ bool trpgModelTable::Write(trpgWriteBuffer &buf)
return false;
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)models.size());
for (unsigned int i=0;i<models.size();i++)
models[i].Write(buf);
buf.Add((int32)modelsMap.size());
ModelMapType::iterator itr = modelsMap.begin();
for ( ; itr != modelsMap.end( ); itr++) {
itr->second.Write(buf);
}
buf.End();
return true;
@ -299,27 +400,36 @@ bool trpgModelTable::Write(trpgWriteBuffer &buf)
bool trpgModelTable::GetNumModels(int &nm) const
{
if (!isValid()) return false;
nm = models.size();
nm = modelsMap.size();
return true;
}
bool trpgModelTable::GetModel(int id,trpgModel &model) const
{
if (!isValid() || id < 0 || id >= (int)models.size())
if (!isValid() || id < 0 ) //|| id >= models.size())
return false;
model = models[id];
//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())
if (id < 0 ) //|| id >= models.size())
return NULL;
return &models[id];
//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;
@ -327,13 +437,20 @@ bool trpgModelTable::Read(trpgReadBuffer &buf)
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
trpgModel model;
buf.GetToken(tok,len);
if (tok != TRPGMODELREF) throw 1;
bool readHandle;
if (tok == TRPGMODELREF)
readHandle = false;
else if (tok == TRPGMODELREF2)
readHandle = true;
else
throw 1;
buf.PushLimit(len);
status = model.Read(buf);
status = model.Read(buf,readHandle);
buf.PopLimit();
if (!status) throw 1;
models.push_back(model);
AddModel(model);
}
}
catch (...) {

View File

@ -71,12 +71,15 @@ void trpgGroup::SetID(int inID)
void trpgGroup::SetName(const char* newname )
{
if ( name ) {
if ( name )
{
delete [] name;
name = 0;
}
if (newname) {
if ( strlen(newname) ) {
if (newname)
{
if ( strlen(newname) )
{
name = new char[strlen(newname)+1];
strcpy(name,newname);
}
@ -176,7 +179,8 @@ void trpgBillboard::Reset()
axis = trpg3dPoint(0,0,1);
center = trpg3dPoint(0,0,0);
numChild = 0;
if ( name ) {
if ( name )
{
delete [] name;
name = 0;
}
@ -677,7 +681,8 @@ bool trpgModelRef::Read(trpgReadBuffer &buf)
{
try {
buf.Get(modelRef);
if (modelRef < 0) throw 1;
if (modelRef < 0)
throw 1;
for (int i=0;i<4;i++)
for (int j=0;j<4;j++)
buf.Get(m[i][j]);
@ -793,3 +798,146 @@ bool trpgAttach::Read(trpgReadBuffer &buf)
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

@ -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)
{
@ -149,8 +168,10 @@ bool trpgr_Parser::Parse(trpgReadBuffer &buf)
{
bool ret = true;
try {
while (!buf.isEmpty()) {
try
{
while (!buf.isEmpty())
{
/* We're expecting the following
Token (int32)
Length (int32)
@ -160,7 +181,8 @@ bool trpgr_Parser::Parse(trpgReadBuffer &buf)
int32 len;
if (!buf.Get(tok)) throw 1;
// Push and Pop are special - no data
if (tok != TRPG_PUSH && tok != TRPG_POP) {
if (tok != TRPG_PUSH && tok != TRPG_POP)
{
if (!buf.Get(len)) throw 1;
if (!TokenIsValid(tok)) throw 1;
if (len < 0) throw 1;
@ -169,7 +191,8 @@ bool trpgr_Parser::Parse(trpgReadBuffer &buf)
}
// Call our token handler for this one
try {
try
{
const trpgr_Token *tcb = NULL;
tok_map::const_iterator p = tokenMap.find(tok);
if (p != tokenMap.end())
@ -179,23 +202,27 @@ bool trpgr_Parser::Parse(trpgReadBuffer &buf)
tcb = &defCb;
// Run the callback
if (tcb->cb) {
if (tcb->cb)
{
void *ret = tcb->cb->Parse(tok,buf);
// Note: Do something with the return value
lastObject = ret;
}
}
catch (...) {
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) {
if (tok != TRPG_PUSH && tok != TRPG_POP)
{
buf.SkipToLimit();
buf.PopLimit();
}
}
}
catch (...) {
catch (...)
{
// Failed to parse.
ret = false;
}
@ -208,10 +235,14 @@ bool trpgr_Parser::Parse(trpgReadBuffer &buf)
****************
*/
// 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*/) {
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);
@ -222,10 +253,13 @@ protected:
};
// 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*/) {
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
@ -243,10 +277,12 @@ 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*/) {
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
{
// Absorb it quietly
return (void *)1;
}

View File

@ -24,21 +24,78 @@
#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.
*/
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_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));
@ -47,6 +104,8 @@ trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelpe
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
@ -72,11 +131,56 @@ bool trpgPrintGraphParser::EndChildren(void *)
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)
{
// This will celar any child ref list from a previous parse.
trpgReadWriteable *obj = NULL;
trpgTileHeader *tileHead = NULL;
@ -90,6 +194,10 @@ void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf)
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;
@ -184,6 +292,8 @@ void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf)
}
}
// We delete all object except the child ref node
if(tok != TRPG_CHILDREF)
delete obj;
}
@ -254,10 +364,14 @@ bool trpgPrintArchive(trpgr_Archive *archive,trpgPrintBuffer &pBuf,int flags)
// Now do the tiles
if (!archive->isValid()) return false;
int majorVersion, minorVersion;
archive->GetHeader()->GetVersion(majorVersion, minorVersion);
// Parser that prints out a tile scene graph
trpgrImageHelper imageHelp(archive->GetEndian(),archive->getDir(),*archive->GetMaterialTable(),
*archive->GetTexTable());
trpgPrintGraphParser parser(archive,&imageHelp,&pBuf);
trpgrImageHelper* imageHelp=archive->GetNewRImageHelper(archive->GetEndian(),archive->getDir(),
*archive->GetMaterialTable(),*archive->GetTexTable());
trpgPrintGraphParser parser(archive,imageHelp,&pBuf);
pBuf.prnLine("====Tile Data====");
int nl,x,y;
@ -266,6 +380,26 @@ bool trpgPrintArchive(trpgr_Archive *archive,trpgPrintBuffer &pBuf,int flags)
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
@ -277,13 +411,21 @@ bool trpgPrintArchive(trpgr_Archive *archive,trpgPrintBuffer &pBuf,int flags)
if (flags & TRPGPRN_BODY) {
pBuf.IncreaseIndent();
// Parse it (also prints it
parser.Parse(buf);
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

@ -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");
@ -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++) {
MaterialMapType::const_iterator itr = materialMap.begin();
for ( ; itr != materialMap.end( ); itr++)
{
const trpgMaterial *mat;
sprintf(ls,"Material %d",i); buf.prnLine(ls);
mat = (const_cast<trpgMatTable *>(this))->GetMaterialRef(j,i);
mat->Print(buf);
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();
@ -523,6 +564,24 @@ bool trpgAttach::Print(trpgPrintBuffer &buf) const
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();
return true;
}
/* Print billboard info
*/
bool trpgBillboard::Print(trpgPrintBuffer &buf) const
@ -590,7 +649,8 @@ 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);
}
@ -612,7 +672,8 @@ 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);
}
@ -631,14 +692,30 @@ bool trpgTileTable::Print(trpgPrintBuffer &buf) const
buf.prnLine("----Tile Table----");
buf.IncreaseIndent();
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();
@ -758,7 +836,8 @@ bool trpgLightAttr::Print(trpgPrintBuffer &buf) const
(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) {
if (data.commentStr)
{
sprintf(ls,"comment = %s",data.commentStr); buf.prnLine(ls);
}
@ -776,9 +855,11 @@ 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();
@ -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,7 +946,8 @@ 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++) {
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();
@ -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.
*/
TX_EXDECL class TX_CLDECL trpgPrintBuffer {
TX_EXDECL class TX_CLDECL trpgPrintBuffer
{
public:
trpgPrintBuffer(void);
virtual ~trpgPrintBuffer(void) { };
@ -70,23 +73,56 @@ protected:
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 {
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 {
class ReadHelper : public trpgr_Callback
{
public:
ReadHelper(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf) {pBuf = inBuf; parse = inPG;};
// 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;
private:
ChildRefList childRefList;
};
// Fetch the archive associated with this print
@ -100,6 +136,9 @@ protected:
trpgPrintBuffer *printBuf;
trpgr_Archive *archive;
trpgrImageHelper *imageHelp;
ReadHelper *childRefCB;
};
// Print utitility for while archive

View File

@ -62,6 +62,8 @@ void trpgRange::Reset(void)
inLod = outLod = 0.0;
priority = 0;
handle = -1;
writeHandle = false;
}
void trpgRange::SetCategory(const char *cat,const char *subCat)
@ -122,7 +124,8 @@ trpgRange & trpgRange::operator = (const trpgRange &other)
outLod = other.outLod;
SetCategory(other.category,other.subCategory);
priority = other.priority;
handle = other.handle;
writeHandle = other.writeHandle;
return *this;
}
@ -149,7 +152,10 @@ bool trpgRange::operator == (const trpgRange &in) const
!subCategory && in.subCategory)
return false;
}
if(handle != in.handle)
return false;
if(writeHandle != in.writeHandle)
return false;
return true;
}
@ -161,6 +167,9 @@ bool trpgRange::Write(trpgWriteBuffer &buf)
buf.Add(priority);
buf.Add((category ? category : ""));
buf.Add((subCategory ? subCategory : ""));
if(writeHandle) {
buf.Add((int32)handle);
}
buf.End();
return true;
@ -180,6 +189,16 @@ bool trpgRange::Read(trpgReadBuffer &buf)
buf.Get(catStr,1024);
buf.Get(subStr,1024);
SetCategory(catStr,subStr);
// Read the handle if we can..
try {
if(!buf.Get((int32 &)handle)) {
handle = -1;
}
}
catch (...) {
handle = -1;
}
valid = true;
}
@ -207,7 +226,7 @@ trpgRangeTable::~trpgRangeTable(void)
void trpgRangeTable::Reset(void)
{
rangeList.resize(0);
rangeMap.clear();
valid = true;
}
@ -216,11 +235,14 @@ bool trpgRangeTable::GetRange(int id,trpgRange &ret) const
if (!isValid())
return false;
if (id < 0 || id >= (int)rangeList.size())
if (id < 0)// || id >= rangeList.size())
return false;
ret = rangeList[id];
RangeMapType::const_iterator itr = rangeMap.find(id);
if(itr == rangeMap.end()) {
return false;
}
ret = itr->second;
return true;
}
@ -229,28 +251,39 @@ bool trpgRangeTable::SetRange(int id,trpgRange &inRange)
if (!isValid())
return false;
if (id < 0 || id >= (int)rangeList.size())
if (id < 0)// || id >= rangeList.size())
return false;
rangeList[id] = inRange;
rangeMap[id] = inRange;
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++) {
RangeMapType::iterator itr = rangeMap.begin();
for ( ; itr != rangeMap.end( ); itr++) {
if(itr->second==range)
return itr->first;
}
#if 0
for (int i=0;i<rangeList.size();i++) {
if (range == rangeList[i])
return i;
}
#endif
return AddRange(range);
}
@ -260,10 +293,11 @@ bool trpgRangeTable::Write(trpgWriteBuffer &buf)
return false;
buf.Begin(TRPGRANGETABLE);
buf.Add((int32)rangeList.size());
buf.Add((int32)rangeMap.size());
for (unsigned int i=0;i<rangeList.size();i++) {
trpgRange &range = rangeList[i];
RangeMapType::iterator itr = rangeMap.begin();
for ( ; itr != rangeMap.end( ); itr++) {
trpgRange &range = itr->second;
range.Write(buf);
}
@ -291,7 +325,7 @@ bool trpgRangeTable::Read(trpgReadBuffer &buf)
bool status = range.Read(buf);
buf.PopLimit();
if (!status) throw 1;
rangeList.push_back(range);
AddRange(range);
}
valid = true;
@ -307,9 +341,13 @@ bool trpgRangeTable::Read(trpgReadBuffer &buf)
trpgRangeTable & trpgRangeTable::operator = (const trpgRangeTable &inTab)
{
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++)
#if 0
for (int i=0;i<inTab.rangeList.size();i++)
rangeList.push_back(inTab.rangeList[i]);
#endif
return *this;
}

View File

@ -44,6 +44,11 @@ trpgr_Archive::~trpgr_Archive()
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
void trpgr_Archive::SetDirectory(const char *in_dir)
{
@ -71,24 +76,41 @@ bool trpgr_Archive::OpenFile(const char *name)
// Figure out the endianness from the magic number
trpgEndian cpuNess = trpg_cpu_byte_order();
if (magic == TRPG_MAGIC) {
if (magic == GetMagicNumber()) {
ness = cpuNess;
return true;
}
if (trpg_byteswap_int(magic) == TRPG_MAGIC) {
if (trpg_byteswap_int(magic) == GetMagicNumber()) {
if (cpuNess == LittleEndian)
ness = BigEndian;
else
ness = LittleEndian;
return true;
}
if (magic != TRPG_MAGIC)
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()
@ -101,9 +123,86 @@ void trpgr_Archive::CloseFile()
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;
@ -115,17 +214,20 @@ bool trpgr_Archive::ReadHeader()
// 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);
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
@ -151,6 +253,41 @@ bool trpgr_Archive::ReadHeader()
if (!parser.Parse(buf))
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
@ -166,7 +303,7 @@ bool trpgr_Archive::ReadHeader()
if (tileCache) delete tileCache;
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir);
tileCache = new trpgrAppFileCache(fullBase,"tpf");
tileCache = GetNewRAppFileCache(fullBase,"tpf");
}
valid = true;
@ -176,63 +313,114 @@ 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);
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)
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;
}
if(status)
{
trpgwAppAddress addr;
float zmin,zmax;
status = tileTable.GetTile(x,y,lod,addr,zmin,zmax);
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=NULL;
FILE *fp= 0;
try {
if (!(fp = fopen(filename,"rb"))) throw 1;
if (!(fp = fopen(filename,"rb"))) {
throw 1;
}
// Find the file end
if (fseek(fp,0,SEEK_END)) throw 1;
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;
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;
if (fread(data,pos,1,fp) != 1)
throw 1;
fclose(fp);
fp = NULL;
}
catch (...) {
if (fp)
fclose(fp);
return false;
}
} 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;
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);
if (!tf) return false;
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;
}
@ -245,7 +433,7 @@ const trpgMatTable *trpgr_Archive::GetMaterialTable() const
{
return &materialTable;
}
const trpgTexTable *trpgr_Archive::GetTexTable() const
trpgTexTable *trpgr_Archive::GetTexTable()
{
return &texTable;
}
@ -291,7 +479,7 @@ bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,
header.GetNumLods(numLod);
trpg2iPoint maxXY;
header.GetLodSize(lod,maxXY);
if (x >= (unsigned int)maxXY.x || y>= (unsigned int)maxXY.y)
if (static_cast<int>(x) >= maxXY.x || static_cast<int>(y)>= maxXY.y)
return false;
trpg3dPoint origin;
@ -319,10 +507,17 @@ bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,
*/
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)
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)
@ -350,7 +564,7 @@ bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
// 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;
if (!af->Read(data,addr.offset,0,size))
@ -373,7 +587,7 @@ bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,c
// 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;
@ -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,7 +647,8 @@ 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;
@ -445,8 +665,9 @@ bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,in
// 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;
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;
}
@ -491,7 +712,7 @@ bool trpgrImageHelper::GetNthImageMipLevelForLocalMat(int miplevel, const trpgLo
// 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);
trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row);
if (!af) return false;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
@ -518,7 +739,7 @@ bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pa
tex->GetName(name,nameLen);
nameLen = strlen(name);
if ((int)strlen(dir) + nameLen + 2 > pathLen)
if (static_cast<int>(strlen(dir)) + nameLen + 2 > pathLen)
return false;
sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);

View File

@ -29,7 +29,8 @@
Called when a given token is found.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Callback {
TX_EXDECL class TX_CLDECL trpgr_Callback
{
public:
virtual ~trpgr_Callback(void) { };
virtual void *Parse(trpgToken,trpgReadBuffer &) { return (void *)1; };
@ -39,7 +40,8 @@ public:
Stores callback info associated with a given token.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Token {
TX_EXDECL class TX_CLDECL trpgr_Token
{
public:
trpgr_Token(void);
trpgr_Token(int,trpgr_Callback *,bool destroy=true);
@ -55,7 +57,8 @@ public:
This executes callbacks
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Parser {
TX_EXDECL class TX_CLDECL trpgr_Parser
{
public:
trpgr_Parser(void);
virtual ~trpgr_Parser(void);
@ -64,6 +67,8 @@ 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
@ -90,9 +95,14 @@ private:
If you want to add additional ways to read textures, feel free
to subclass this object.
*/
TX_EXDECL class TX_CLDECL trpgrImageHelper {
class trpgwImageHelper;
TX_EXDECL class TX_CLDECL trpgrImageHelper
{
public:
trpgrImageHelper(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &);
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.
@ -146,6 +156,16 @@ public:
*/
virtual bool GetImagePath(const trpgTexture *,char *,int len);
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;
@ -153,6 +173,8 @@ protected:
const trpgTexTable *texTable;
trpgrAppFileCache *texCache;
trpgrAppFileCache *geotypCache;
bool separateGeoTyp;
};
/* Paging Archive (read version)
@ -160,7 +182,8 @@ protected:
and lets you parse from there.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable {
TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable
{
public:
trpgr_Archive(void);
virtual ~trpgr_Archive(void);
@ -169,12 +192,19 @@ public:
virtual bool OpenFile(const char *); // Open File
virtual void CloseFile(void);
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;
@ -189,6 +219,10 @@ public:
trpgEndian GetEndian(void) const;
char* getDir(void){return dir;};
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;
@ -219,7 +253,8 @@ class trpgSceneHelperDefault;
parser.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser {
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser
{
friend class trpgSceneHelperPush;
friend class trpgSceneHelperPop;
friend class trpgSceneHelperDefault;

View File

@ -54,6 +54,7 @@ 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);
else
@ -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;
}
@ -433,6 +434,9 @@ 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;
@ -451,6 +455,11 @@ 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;
@ -470,6 +479,11 @@ trpgrAppFile::~trpgrAppFile()
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)
@ -489,7 +503,7 @@ bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset)
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
len = trpg_byteswap_int(len);
if (len < 0) {
valid = false;
@ -503,7 +517,7 @@ bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset)
return false;
}
if (fread(data,sizeof(char),len,fp) != (unsigned int)len) {
if (fread(data,sizeof(char),len,fp) != (uint32)len) {
valid = false;
return false;
}
@ -536,7 +550,7 @@ bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSi
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
len = trpg_byteswap_int(len);
if (len < 0) {
valid = false;
@ -555,7 +569,7 @@ bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSi
// Read the raw data
// Note: What about byte swapping?
if (fread(data,sizeof(char),dataSize,fp) != (unsigned int)dataSize) {
if (fread(data,sizeof(char),dataSize,fp) != (uint32)dataSize) {
valid = false;
return false;
}
@ -570,6 +584,11 @@ bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSi
*/
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,7 +599,8 @@ trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noF
trpgrAppFileCache::~trpgrAppFileCache()
{
for (unsigned int i=0;i<files.size();i++) {
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;
@ -588,15 +608,27 @@ trpgrAppFileCache::~trpgrAppFileCache()
}
}
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) {
if ((files[i].id == id)&&
(files[i].col == col) &&
(files[i].row == row)) {
foundID = i;
break;
}
@ -605,9 +637,19 @@ trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id)
// Found it in cache, just return
if (foundID != -1) {
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
@ -625,11 +667,33 @@ trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id)
// Reclaim this one
OpenFile &of = files[oldID];
if (of.afile) delete of.afile;
if (of.afile)
delete of.afile;
char fileName[1024];
if(col==-1) {
sprintf(fileName,"%s_%d.%s",baseName,id,ext);
of.afile = new trpgrAppFile(ness,fileName);
}
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

@ -333,6 +333,30 @@ public:
protected:
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; }
@ -415,6 +439,7 @@ trpgSceneGraphParser::trpgSceneGraphParser()
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));

View File

@ -74,7 +74,7 @@ public:
virtual ~trpgReadGroupBase(void);
void AddChild(trpgReadNode *);
bool isGroupType(void) { return true; }
int GetNumChildren(void) { return children.size(); }
int GetNumChildren(void) { return int(children.size()); }
trpgReadNode *GetChild(int i) { return children[i]; }
trpgMBR GetMBR(void) const;
void unRefChild(int i);
@ -138,6 +138,19 @@ protected:
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}
TX_EXDECL class TX_CLDECL trpgReadBillboard : public trpgReadGroupBase {

View File

@ -122,7 +122,7 @@ short trpg_byteswap_short( short number )
**
** desc: byte-swaps an int.
*/
int trpg_byteswap_int( int number )
TX_CPPDECL int trpg_byteswap_int( int number )
{
int result;
@ -197,7 +197,7 @@ trpgllong trpg_byteswap_llong ( trpgllong number )
return result;
}
trpgEndian trpg_cpu_byte_order(void)
TX_CPPDECL trpgEndian trpg_cpu_byte_order(void)
{
static char big_endian_100[2] = { 0, 100 };

View File

@ -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

@ -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,6 +17,7 @@
#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
@ -33,6 +34,7 @@
// Constructor
trpgTileTable::trpgTileTable()
{
localBlock = false;
Reset();
}
@ -43,12 +45,14 @@ void trpgTileTable::Reset()
mode = External;
lodInfo.resize(0);
valid = true;
currentRow = -1;
currentCol = -1;
}
// Destructor
trpgTileTable::~trpgTileTable()
{
valid = false;
}
// Set functions
@ -64,13 +68,25 @@ void trpgTileTable::SetNumLod(int numLod)
lodInfo.resize(numLod);
}
void trpgTileTable::SetNumTiles(int nx,int ny,int lod)
{
if (nx <= 0 || ny <= 0 || lod < 0 || lod >= (int)lodInfo.size())
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 (mode == Local || mode == ExternalSaved) {
// If there's a pre-existing table, we need to preserve the entries
LodInfo oldLodInfo = lodInfo[lod];
@ -98,14 +114,20 @@ void trpgTileTable::SetNumTiles(int nx,int ny,int lod)
}
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)
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;
int loc = y*li.numX + x;
loc = y*li.numX + x;
}
li.addr[loc] = ref;
li.elev_min[loc] = zmin;
li.elev_max[loc] = zmax;
@ -130,14 +152,21 @@ bool trpgTileTable::GetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 &zm
{
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)
if (lod < 0 || lod >= static_cast<int>(lodInfo.size())) return false;
if (mode == External)
return false;
int loc = y*li.numX + x;
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];
@ -157,7 +186,7 @@ bool trpgTileTable::Write(trpgWriteBuffer &buf)
buf.Add(mode);
// Depending on the mode we'll have a lot or a little data
if (mode == Local) {
if (mode == Local || mode == ExternalSaved) {
// The lod sizing is redundant, but it's convenient here
int numLod = lodInfo.size();
buf.Add(numLod);
@ -165,6 +194,19 @@ bool trpgTileTable::Write(trpgWriteBuffer &buf)
// 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.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
@ -180,6 +222,7 @@ bool trpgTileTable::Write(trpgWriteBuffer &buf)
}
}
}
}
buf.End();
@ -199,31 +242,67 @@ bool trpgTileTable::Read(trpgReadBuffer &buf)
try {
int imode;
buf.Get(imode); mode = (TileMode)imode;
if (mode != External && mode != Local) throw 1;
if (mode == Local) {
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];
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);
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;
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];
buf.Get(ref.file);
buf.Get(ref.offset);
ref.file = file;
ref.offset = offset;
}
for (j=0;j<numTile;j++) {
buf.Get(li.elev_min[j]);
buf.Get(li.elev_max[j]);
float emin,emax;
buf.Get(emin);
buf.Get(emax);
li.elev_max[j] = emax;
li.elev_min[j] = emin;
}
}
}
}
@ -231,6 +310,7 @@ bool trpgTileTable::Read(trpgReadBuffer &buf)
valid = true;
}
catch (...) {
printf("Caught an exception\n");
return false;
}
@ -245,6 +325,8 @@ bool trpgTileTable::Read(trpgReadBuffer &buf)
// Constructor
trpgTileHeader::trpgTileHeader()
{
col = -1;
row = -1;
}
trpgTileHeader::~trpgTileHeader()
{
@ -255,18 +337,20 @@ void trpgTileHeader::Reset()
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())
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())
if (no < 0 || no >= static_cast<int>(modelList.size()))
return;
modelList[no] = id;
}
@ -310,7 +394,7 @@ bool trpgTileHeader::GetNumLocalMaterial(int32 &retNum) const
bool trpgTileHeader::GetLocalMaterial(int32 id,trpgLocalMaterial &retMat) const
{
if (id < 0 || id >= (int)locMats.size())
if (id < 0 || id >= static_cast<int>(locMats.size()))
return false;
retMat = locMats[id];
@ -334,7 +418,7 @@ bool trpgTileHeader::GetNumMaterial(int32 &no) const
}
bool trpgTileHeader::GetMaterial(int32 id,int32 &mat) const
{
if (!isValid() || id < 0 || id >= (int)matList.size())
if (!isValid() || id < 0 || id >= static_cast<int>(matList.size()))
return false;
mat = matList[id];
return true;
@ -347,7 +431,7 @@ bool trpgTileHeader::GetNumModel(int32 &no) const
}
bool trpgTileHeader::GetModel(int32 id,int32 &m) const
{
if (!isValid() || id < 0 || id >= (int)modelList.size())
if (!isValid() || id < 0 || id >= static_cast<int>(modelList.size()))
return false;
m = modelList[id];
return true;
@ -453,6 +537,12 @@ void * tileHeaderCB::Parse(trpgToken tok,trpgReadBuffer &buf)
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);
buf.PopLimit();
}
}

View File

@ -25,4 +25,3 @@
Instead, there's a Windows specific program that merges TerraPage archives in
the merge/ directory of this distribution.
*/

View File

@ -34,11 +34,23 @@
#include <trpage_read.h>
// Constructor
trpgwArchive::trpgwArchive(trpgEndian inNess,TileMode inTileMode,int inVersion)
trpgwArchive::trpgwArchive(trpgEndian inNess,trpgwArchive::TileMode inTileMode,int majorVer, int minorVer)
{
version = inVersion;
if (version != 1 && version != 2)
Init(inNess,inTileMode,majorVer, minorVer);
}
void trpgwArchive::Init(trpgEndian inNess, trpgwArchive::TileMode inTileMode,int majorVer, int minorVer)
{
minorVersion = minorVer;
majorVersion = majorVer;
if (majorVersion < 1 || majorVersion > TRPG_VERSION_MAJOR)
throw 1;
if(majorVersion == TRPG_VERSION_MAJOR)
{
if(minorVersion < 0 || minorVersion > TRPG_VERSION_MINOR)
throw 1;
}
fp = NULL;
strcpy(dir,".");
ness = inNess;
@ -53,10 +65,16 @@ trpgwArchive::trpgwArchive(trpgEndian inNess,TileMode inTileMode,int inVersion)
}
// Constructor for regenerate
trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne)
trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne, int majorVer, int minorVer)
{
Init(inDir,inFile,sw,ne, majorVer, minorVer);
}
void trpgwArchive::Init(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne, int majorVer, int minorVer)
{
maxTileFileLen = -1;
version = TRPG_VERSION_MAJOR;
majorVersion = majorVer;
minorVersion = minorVer;
fp = NULL;
strcpy(dir,inDir);
cpuNess = trpg_cpu_byte_order();
@ -65,15 +83,19 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint
isRegenerate = true;
errMess[0] = '\0';
// TODO: have a "setup from file" method for trpgwArchive
// Open a Read Archive to get the rest of the info we need
trpgr_Archive *inArch = new trpgr_Archive();
trpgr_Archive *inArch = this->GetArchiveReader();
inArch->SetDirectory(inDir);
if (!inArch->OpenFile(inFile)) {
if (!inArch->OpenFile(inFile))
{
delete inArch;
throw 1;
}
// Get the header (this is what we need)
if (!inArch->ReadHeader()) {
if (!inArch->ReadHeader())
{
delete inArch;
throw 1;
}
@ -81,16 +103,39 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint
ness = inArch->GetEndian();
const trpgHeader *inHeader = inArch->GetHeader();
// use the version in the archive instead.
inHeader->GetVersion(majorVersion,minorVersion);
// Expand the coverage
trpg2dPoint newSW,newNE;
trpg2dPoint oldSW,oldNE;
// Or not. Have to add in something to avoid recalculation
// when merging geocentric databases. We don't really support
// them, and everything goes to hell. So: hack is:
// if sw=ne, don't change anything.
// This will also help a little with MMB TXP merge speed.
bool extentsUnchanged=false;
inHeader->GetExtents(oldSW,oldNE);
// just checking for equality right now. Bad?
if ((sw==ne) || ((oldSW==sw) && (oldNE==ne)))
{
extentsUnchanged = true;
// set up passed-in SW and NE as well.
sw=newSW=oldSW;
ne=newNE=oldNE;
}
else
{
newSW.x = MIN(sw.x,oldSW.x);
newSW.y = MIN(sw.y,oldSW.y);
newNE.x = MAX(ne.x,oldNE.x);
newNE.y = MAX(ne.y,oldNE.y);
}
// Decide what the offset should be for new tiles
if (!extentsUnchanged)
{
trpg2dPoint blockSize;
inHeader->GetTileSize(0,blockSize);
@ -107,18 +152,20 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint
// Header can mostly stay the same
header = *inHeader;
// Update to the new MBR and tile grid sizes
header.SetExtents(newSW,newNE);
header.GetNumLods(numLod);
// Update to the new MBR and tile grid sizes
if (!extentsUnchanged) {
for (int i=0;i<numLod;i++) {
// Figure out the tile grid size
trpg2dPoint tileSize;
inHeader->GetTileSize(i,tileSize);
trpg2iPoint newTileExt;
newTileExt.x = (int)((newNE.x - newSW.x)/tileSize.x + 10e-5);
newTileExt.y = (int)((newNE.y - newSW.y)/tileSize.y + 10e-15);
newTileExt.x = int((newNE.x - newSW.x)/tileSize.x + 10e-5);
newTileExt.y = int((newNE.y - newSW.y)/tileSize.y + 10e-15);
header.SetLodSize(i,newTileExt);
}
}
// These tables we can copy straight over
matTable = *inArch->GetMaterialTable();
@ -131,11 +178,42 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint
supportStyleTable = *inArch->GetSupportStyleTable();
labelPropertyTable = *inArch->GetLabelPropertyTable();
// Need to resize the tile table
const trpgTileTable *oldTiles = inArch->GetTileTable();
// Need to resize the tile table (maybe)
// NOTE: Starting with version 2.1, the tile tables will contain only
// the lod 0 tiles
trpgTileTable::TileMode tileTableMode;
if (!extentsUnchanged) {
const trpgTileTable *oldTiles = inArch->GetTileTable();
oldTiles->GetMode(tileTableMode);
tileTable.SetMode(tileTableMode);
if(majorVersion == 2 && minorVersion >=1)
{
// Version 2.1. we store only lod 0, all other lod tiles are
// stored in the parent tile
tileTable.SetNumLod(0);
// Size the output tile table
trpg2iPoint tileSize;
header.GetLodSize(0,tileSize);
tileTable.SetNumTiles(tileSize.x, tileSize.y, 0);
// Copy over individual tiles
trpg2iPoint levelOffset;
levelOffset.x = addOffset.x;
levelOffset.y = addOffset.y;
trpg2iPoint oldTileSize;
inHeader->GetLodSize(0, oldTileSize);
for (int ix=0;ix<oldTileSize.x;ix++) {
for (int iy=0;iy<oldTileSize.y;iy++) {
trpgwAppAddress addr;
float zmin,zmax;
oldTiles->GetTile(ix, iy, 0,addr,zmin,zmax);
tileTable.SetTile(ix+addOffset.x, iy+addOffset.y ,0, addr, zmin, zmax);
}
}
}
else
{
tileTable.SetNumLod(numLod);
for (int lod=0;lod<numLod;lod++) {
// Size the output tile table
@ -158,9 +236,26 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint
}
}
}
}
} else {
tileTable = *inArch->GetTileTable();
tileTable.GetMode(tileTableMode);
}
// Continue to work in the mode the original database is in
tileMode = (tileTableMode == trpgTileTable::Local) ? TileLocal : TileExternal;
switch(tileTableMode)
{
case trpgTileTable::Local:
tileMode = TileLocal;
break;
case trpgTileTable::External:
tileMode = TileExternal;
break;
case trpgTileTable::ExternalSaved:
tileMode = TileExternalSaved;
break;
}
// That's it for the read archive
delete inArch;
@ -177,6 +272,12 @@ trpgwArchive::~trpgwArchive()
}
}
// WriteHeaderData
int32 trpgwArchive::WriteHeaderData(const char *dataPtr, int length, FILE* /*filehandle*/)
{
return fwrite(dataPtr,1,length,fp);
}
// IsValid()
// Verifies that our file is open
bool trpgwArchive::isValid() const
@ -369,13 +470,61 @@ bool trpgwArchive::CheckpointHeader()
we have all the relevant information collected during
the WriteTile calls.
*/
if(header.GetIsLocal()) {
int row = 0;
int col = 0;
header.GetBlocks(row,col);
tileTable.SetCurrentBlock(row,col,true);
}
if (tileMode == TileExternal) {
// External tiles are easy
tileTable.SetMode(trpgTileTable::External);
} else if( tileMode == TileExternalSaved) {
if(!isRegenerate && firstHeaderWrite)
{
// Set up the sizes
tileTable.SetMode(trpgTileTable::ExternalSaved);
tileTable.SetNumLod(1);
trpg2iPoint lodSize;
header.GetLodSize(0,lodSize);
tileTable.SetNumTiles(lodSize.x, lodSize.y, 0);
firstHeaderWrite = false;
}
// Now set the individual tile locations
for (unsigned int i=0;i<externalTiles.size();i++) {
TileFileEntry &te = externalTiles[i];
trpgwAppAddress addr;
addr.file = -1;
addr.offset = -1;
tileTable.SetTile(te.x,te.y,te.lod,addr,te.zmin,te.zmax);
}
externalTiles.clear();
} else {
if (!isRegenerate && firstHeaderWrite) {
// Local tiles require more work
tileTable.SetMode(trpgTileTable::Local);
if(majorVersion == 2 && minorVersion >= 1)
{
// Version 2.1, we store only lod 0 in the tile table
// Set up the sizes
tileTable.SetNumLod(1);
trpg2iPoint lodSize;
header.GetLodSize(0,lodSize);
tileTable.SetNumTiles(lodSize.x, lodSize.y, 0);
}
else
{
// Set up the sizes
int32 numLod;
header.GetNumLods(numLod);
@ -385,10 +534,15 @@ bool trpgwArchive::CheckpointHeader()
header.GetLodSize(i,lodSize);
tileTable.SetNumTiles(lodSize.x,lodSize.y,i);
}
}
firstHeaderWrite = false;
}
// Now set the individual tile locations
// Nothing special need to be done with version 2.1 since
// only tile with lod 0 will be found in the tileFiles container
for (unsigned int i=0;i<tileFiles.size();i++) {
TileFile &tf = tileFiles[i];
for (unsigned int j=0;j<tf.tiles.size();j++) {
@ -400,16 +554,19 @@ bool trpgwArchive::CheckpointHeader()
}
tf.tiles.clear();
}
}
// Write all the headers into a buffer
if (!header.Write(buf))
return false;
// Do the mat table and texture table
// These can be different depending on the version
switch (version) {
switch (majorVersion) {
case 1:
{
trpgMatTable1_0 matTable1_0(matTable);
@ -426,16 +583,7 @@ bool trpgwArchive::CheckpointHeader()
}
break;
case 2:
if (!matTable.Write(buf))
{
strcpy(errMess, "Error writing material table");
if(matTable.getErrMess())
{
strcat(errMess, ": ");
strcat(errMess, matTable.getErrMess());
return false;
}
}
if(!header.GetIsMaster()||texTable.isValid()) {
if(!texTable.Write(buf))
{
strcpy(errMess, "Error writing texture table");
@ -446,6 +594,20 @@ bool trpgwArchive::CheckpointHeader()
return false;
}
}
}
//These tables will not be populated if this is the master table.
if(!header.GetIsMaster()) {
if (!matTable.Write(buf))
{
strcpy(errMess, "Error writing material table");
if(matTable.getErrMess())
{
strcat(errMess, ": ");
strcat(errMess, matTable.getErrMess());
return false;
}
}
if(!modelTable.Write(buf) )
{
@ -457,6 +619,8 @@ bool trpgwArchive::CheckpointHeader()
return false;
}
}
}
//always write the tile table, even if we are a master
if(!tileTable.Write(buf))
{
strcpy(errMess, "Error writing tile table");
@ -467,6 +631,7 @@ bool trpgwArchive::CheckpointHeader()
return false;
}
}
if(!header.GetIsMaster()) {
if(!lightTable.Write(buf))
{
strcpy(errMess, "Error writing light table");
@ -517,12 +682,12 @@ bool trpgwArchive::CheckpointHeader()
return false;
}
}
}
break;
}
// Write the disk header
int32 magic = TRPG_MAGIC;
int32 magic = GetMagicNumber();
if (ness != cpuNess)
magic = trpg_byteswap_int(magic);
if (fwrite(&magic,sizeof(int32),1,fp) != 1)
@ -545,7 +710,7 @@ bool trpgwArchive::CheckpointHeader()
// Write the buffer
const char *data = buf.getData();
if (fwrite(data,sizeof(char),headLen,fp) != (unsigned int)headLen)
if (WriteHeaderData(data,headLen,fp) != headLen)
{
strcpy(errMess, "Could not write the buffer");
return false;
@ -564,6 +729,27 @@ bool trpgwArchive::CheckpointHeader()
return true;
}
/* Get a new appendable file.
*/
trpgwAppFile *trpgwArchive::GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse)
{
return new trpgwAppFile(inNess,fileName,reuse);
}
/* Get a new write image helper
*/
trpgwImageHelper *trpgwArchive::GetNewWImageHelper(trpgEndian ness,char *dir,trpgTexTable &inTexTable)
{
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 trpgwImageHelper(ness,dir,inTexTable,separateGeo);
}
/* Increment Tile File.
Close the current tile file (if any) and open the next one.
Also update the records we're keeping of which tiles went in
@ -583,7 +769,7 @@ bool trpgwArchive::IncrementTileFile()
// Open the next one
char filename[1024];
sprintf(filename,"%s" PATHSEPERATOR "tileFile_%d.tpf",dir,tileFileCount++);
tileFile = new trpgwAppFile(ness,filename);
tileFile = GetNewWAppFile(ness,filename,true);
if (!tileFile->isValid())
return false;
@ -612,7 +798,7 @@ bool trpgwArchive::DesignateTileFile(int id)
// Open a named on
char filename[1024];
sprintf(filename,"%s" PATHSEPERATOR "tileFile_%d.tpf",dir,id);
tileFile = new trpgwAppFile(ness,filename);
tileFile = GetNewWAppFile(ness,filename);
if (!tileFile->isValid())
return false;
@ -629,15 +815,18 @@ bool trpgwArchive::DesignateTileFile(int id)
appended together to the file.
*/
bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, float zmin, float zmax,
const trpgMemWriteBuffer *head,const trpgMemWriteBuffer *buf)
const trpgMemWriteBuffer *head,const trpgMemWriteBuffer *buf, int32& fileId, int32& fileOffset)
{
FILE *tfp=NULL;
if (!isValid())
return false;
fileId = -1;
fileOffset = -1;
// External tiles get their own individual files
if (tileMode == TileExternal) {
if (tileMode == TileExternal || tileMode == TileExternalSaved) {
// Make a new filename
char filename[1024];
// Note: Windows specific
@ -665,14 +854,29 @@ bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, flo
return false;
}
fclose(tfp);
// In version 2.1 and over we still add an entry to the tile table
// to save the zmin and zmax value.
if(tileMode == TileExternalSaved && lod == 0)
{
externalTiles.push_back(TileFileEntry());
TileFileEntry& tf = externalTiles.back();
tf.x = x;
tf.y = y;
tf.lod = lod;
tf.offset = -1;
tf.zmax = zmax;
tf.zmin = zmin;
}
} else {
// Local tiles get appended to a tile file
if (!tileFile) {
if (!IncrementTileFile())
return false;
} else {
}
// See if we've exceeded the maximum advised size for a tile file
if (maxTileFileLen > 0 && tileFile->GetLengthWritten() > maxTileFileLen)
while (maxTileFileLen > 0 && tileFile->GetLengthWritten() > maxTileFileLen) {
if (!IncrementTileFile())
return false;
}
@ -685,8 +889,19 @@ bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, flo
TileFileEntry te;
te.x = x; te.y = y; te.lod = lod;
te.zmin = zmin; te.zmax = zmax; te.offset = pos;
if(majorVersion == 2 && minorVersion >=1)
{
// Version 2.1, we need to keep track of lod 0 only
if(lod == 0)
tf.tiles.push_back(te);
}
else
tf.tiles.push_back(te);
fileOffset = pos;
fileId = tileFiles[tileFiles.size()-1].id;
}
return true;
}
@ -1152,12 +1367,19 @@ void trpgwGeomHelper::Optimize()
*************************
*/
trpgwImageHelper::trpgwImageHelper(trpgEndian inNess,char *inDir,trpgTexTable &inTable)
trpgwImageHelper::trpgwImageHelper(trpgEndian inNess,char *inDir,trpgTexTable &inTable,bool separateGeoTypical)
{
Init(inNess,inDir,inTable,separateGeoTypical);
}
void trpgwImageHelper::Init(trpgEndian inNess,char *inDir,trpgTexTable &inTable,bool separateGeoTypical)
{
ness = inNess;
strcpy(dir,inDir);
texTable = &inTable;
texFile = NULL;
geotypFile = NULL;
this->separateGeoTypical = separateGeoTypical;
maxTexFileLen = -1;
}
@ -1165,6 +1387,8 @@ trpgwImageHelper::~trpgwImageHelper()
{
if (texFile)
delete texFile;
if (geotypFile)
delete geotypFile;
}
bool trpgwImageHelper::AddExternal(char *name,int &texID,bool lookForExisting)
@ -1185,52 +1409,26 @@ void trpgwImageHelper::SetMaxTexFileLength(int len)
maxTexFileLen = len;
}
// doing this so people don't have to modify thier code, for both TXP users out there
bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,
bool isMipmap,char *data,int &texID)
{
int depth;
switch (type) {
case trpgTexture::trpg_INT8:
depth = 1;
break;
case trpgTexture::trpg_INTA8:
depth = 2;
break;
case trpgTexture::trpg_RGB8:
case trpgTexture::trpg_FXT1:
case trpgTexture::trpg_DXT1:
case trpgTexture::trpg_DXT3:
case trpgTexture::trpg_DXT5:
depth = 3;
break;
case trpgTexture::trpg_RGBA8:
depth = 4;
break;
default:
depth = -1;
break;
}
return AddLocal(name,type,sizeX,sizeY,depth,trpgTexture::trpg_RGBX_Neither,isMipmap,data,texID);
}
bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY, int sizeZ,
trpgTexture::ImageOrg org, bool isMipmap,char *data,int &texID)
bool isMipmap,char *data,int &texID,bool deferWrite)
{
// Set up the basic texture
trpgTexture tex;
if(texID!=-1)
tex.SetHandle(texID);
tex.SetName(name);
tex.SetImageMode(trpgTexture::Local);
tex.SetImageType(type);
int depth;
tex.GetImageDepth(depth);
tex.SetNumLayer(depth);
tex.SetImageSize(trpg2iPoint(sizeX,sizeY));
tex.SetNumLayer(sizeZ);
tex.SetImageOrganization(org);
tex.SetIsMipmap(isMipmap);
// Write the image out to disk
trpgwAppAddress addr;
if (!WriteToArchive(tex,data,addr))
if(!deferWrite)
if (!WriteToArchive(tex,data,addr,true))
return false;
// Now add the specifics to the texture table
@ -1240,76 +1438,87 @@ bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX
return true;
}
// doing this so people don't have to modify thier code, for both TXP users out there
bool trpgwImageHelper::ReplaceLocal(char *data,int &texID)
{
const trpgTexture *texRef=texTable->GetTextureRef(texID);
if (!texRef) return false;
// Write the image out to disk
trpgwAppAddress addr;
if (!WriteToArchive(*texRef,data,addr,true))
return false;
// Now add the specifics to the texture table
const_cast<trpgTexture *>(texRef)->SetImageAddr(addr);
return true;
}
bool trpgwImageHelper::AddTileLocal(char *name,trpgTexture::ImageType type, int sizeX, int sizeY,
bool isMipmap,char *data,int &texID,trpgwAppAddress &addr)
{
int depth;
switch (type) {
case trpgTexture::trpg_INT8:
depth = 1;
break;
case trpgTexture::trpg_INTA8:
depth = 2;
break;
case trpgTexture::trpg_RGB8:
case trpgTexture::trpg_FXT1:
case trpgTexture::trpg_DXT1:
case trpgTexture::trpg_DXT3:
case trpgTexture::trpg_DXT5:
depth = 3;
break;
case trpgTexture::trpg_RGBA8:
depth = 4;
break;
default:
depth = -1;
break;
}
return AddTileLocal(name,type,sizeX,sizeY,depth,trpgTexture::trpg_RGBX_Neither,isMipmap,data,texID,addr);
}
bool trpgwImageHelper::AddTileLocal(char *name,trpgTexture::ImageType type, int sizeX, int sizeY, int sizeZ,
trpgTexture::ImageOrg org, bool isMipmap,char *data,int &texID,trpgwAppAddress &addr)
{
// Set up the texture template and add to the table
trpgTexture tex;
if(texID!=-1)
tex.SetHandle(texID);
tex.SetName(name);
tex.SetImageMode(trpgTexture::Template);
tex.SetImageType(type);
int depth;
tex.GetImageDepth(depth);
tex.SetNumLayer(depth);
tex.SetImageSize(trpg2iPoint(sizeX,sizeY));
tex.SetNumLayer(sizeZ);
tex.SetImageOrganization(org);
tex.SetIsMipmap(isMipmap);
texID = texTable->FindAddTexture(tex);
// Write the specific data out to an archive (return the address)
if (!WriteToArchive(tex,data,addr))
if (!WriteToArchive(tex,data,addr,false))
return false;
return true;
}
/* Get new appendable file.
*/
trpgwAppFile* trpgwImageHelper::GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse) {
return new trpgwAppFile(inNess,fileName,reuse);
}
/* Increment Texture File.
Close the current texture file (if any) and open the next one.
*/
bool trpgwImageHelper::IncrementTextureFile()
trpgwAppFile * trpgwImageHelper::IncrementTextureFile(bool geotyp)
{
char filename[1024];
trpgwAppFile *thefile = texFile;
if(geotyp && separateGeoTypical) {
thefile = geotypFile;
sprintf(filename,"%s" PATHSEPERATOR "geotypFile_%d.txf",dir,static_cast<int>(geotypFileIDs.size()));
}
else {
sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,static_cast<int>(texFileIDs.size()));
}
// Closes the current texture file
if (texFile) delete texFile;
texFile = NULL;
if (thefile) delete thefile;
thefile = NULL;
// Open the next one
char filename[1024];
sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,static_cast<int>(texFileIDs.size()));
texFile = new trpgwAppFile(ness,filename);
if (!texFile->isValid())
return false;
thefile = GetNewWAppFile(ness,filename,true);
if (!thefile->isValid())
return NULL;
if(geotyp && separateGeoTypical) {
geotypFileIDs.push_back(geotypFileIDs.size());
geotypFile = thefile;
}
else {
texFileIDs.push_back(texFileIDs.size());
return true;
texFile = thefile;
}
return thefile;
}
// Flush current texture file (if any)
@ -1317,7 +1526,8 @@ bool trpgwImageHelper::Flush()
{
if (texFile)
texFile->Flush();
if (geotypFile)
geotypFile->Flush();
return true;
}
@ -1334,12 +1544,18 @@ bool trpgwImageHelper::DesignateTextureFile(int id)
// Open one with the given base name
char filename[1024];
sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,id);
texFile = new trpgwAppFile(ness,filename);
texFile = GetNewWAppFile(ness,filename);
if (!texFile->isValid())
return false;
texFileIDs.push_back(id);
sprintf(filename,"%s" PATHSEPERATOR "geotypFile_%d.txf",dir,id);
geotypFile = GetNewWAppFile(ness,filename);
if (!geotypFile->isValid())
return false;
geotypFileIDs.push_back(id);
return true;
}
@ -1347,32 +1563,42 @@ bool trpgwImageHelper::DesignateTextureFile(int id)
Write the given image data out to an appropriate archive and
return the address. This is used for Local and Tile Local textures.
*/
bool trpgwImageHelper::WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr)
bool trpgwImageHelper::WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr,bool geotyp)
{
trpg2iPoint size;
tex.GetImageSize(size);
int32 depth;
tex.GetImageDepth(depth);
trpgwAppFile *thefile = texFile;
if(geotyp && separateGeoTypical) {
thefile = geotypFile;
}
// Get a usable texture archive file
if (!texFile) {
if (!IncrementTextureFile())
if (!thefile) {
if (! (thefile=IncrementTextureFile(geotyp && separateGeoTypical)))
return false;
} else {
// Deal with maximum advised size for texture archive
if (maxTexFileLen > 0 && texFile->GetLengthWritten() > maxTexFileLen) {
if (!IncrementTextureFile())
return false;
}
}
while (maxTexFileLen > 0 && thefile->GetLengthWritten() > maxTexFileLen) {
if (!(thefile=IncrementTextureFile(geotyp && separateGeoTypical)))
return false;
}
// Get the current address
if(geotyp && separateGeoTypical) {
addr.file = geotypFileIDs[geotypFileIDs.size()-1];
}
else {
addr.file = texFileIDs[texFileIDs.size()-1];
addr.offset = static_cast<int32>(texFile->Pos());
}
addr.offset = (int32)thefile->Pos();
// Write the data out to the archive.
int totSize = tex.CalcTotalSize();
if (!texFile->Append(data,totSize))
if (!thefile->Append(data,totSize))
return false;
return true;

View File

@ -24,6 +24,7 @@
#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.
@ -153,7 +154,11 @@ protected:
*/
TX_EXDECL class TX_CLDECL trpgwImageHelper {
public:
trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &);
trpgwImageHelper() {;};
trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &,bool separateGeoTypical);
// construction is really here
virtual void Init(trpgEndian ness,char *dir,trpgTexTable &,bool separateGeoTypical);
virtual ~trpgwImageHelper(void);
// Adds an entry to the texture table for an external texture
@ -163,8 +168,14 @@ public:
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);
virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data,int &texID,bool deferWrite);
/* 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);
/* Write a Tile Local texture out to one of our texture archive files.
Also creates a texture template, if necessary.
@ -172,7 +183,6 @@ public:
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);
/* Sets the maximum advised length for a texture archive file.
Once the length is exceeded, the image write helper will move
@ -185,7 +195,7 @@ public:
the next texture file.
Note: This may create more files than we really need.
*/
virtual bool IncrementTextureFile(void);
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.
@ -195,15 +205,24 @@ public:
// Flush current texture output files
virtual bool Flush(void);
protected:
// 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 WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr,bool geotyp=false);
// Merge block textable into a master.
protected:
trpgEndian ness;
char dir[1024];
trpgTexTable *texTable;
std::vector<int> texFileIDs;
trpgwAppFile *texFile;
std::vector<int> geotypFileIDs;
trpgwAppFile *geotypFile;
bool separateGeoTypical;
int maxTexFileLen;
};
@ -215,12 +234,17 @@ protected:
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;
enum TileMode {TileLocal,TileExternal,TileExternalSaved};
// 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);
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 version=2);
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)
@ -262,13 +286,22 @@ public:
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 *);
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;
// Used to keep track of which tiles are in which file
class TileFileEntry {
public:
int x,y,lod; // Identifying info for tile
@ -281,14 +314,8 @@ public:
std::vector<TileFileEntry> tiles;
};
protected:
// Set if we're adding to an existing archive
bool isRegenerate;
// Used to keep track of which tiles are in which file
trpgEndian ness,cpuNess;
int version;
int majorVersion, minorVersion;
// Fed in from the outside
char dir[1024]; // Directory where we're doing all this
@ -315,6 +342,8 @@ protected:
std::vector<TileFile> tileFiles;
std::vector<TileFileEntry> externalTiles;
int maxTileFileLen;
// This offset is used when we're adding to an existing archive

View File

@ -277,6 +277,35 @@ void trpgMemWriteBuffer::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.
@ -301,17 +330,30 @@ void trpgMemWriteBuffer::End()
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)
{
Init(inNess,fileName,reuse);
}
void trpgwAppFile::Init(trpgEndian inNess,const char *fileName,bool reuse)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
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()
@ -343,15 +385,15 @@ bool trpgwAppFile::Append(const trpgMemWriteBuffer *buf1,const trpgMemWriteBuffe
// Write the data out
const char *data = buf1->getData();
int len = buf1->length();
if (fwrite(data,sizeof(char),len,fp) != (unsigned int)len) {
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) != (unsigned int)len) {
if (fwrite(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
@ -377,7 +419,7 @@ bool trpgwAppFile::Append(const char *data,int size)
}
// Write the data out
if (fwrite(data,sizeof(char),size,fp) != (unsigned int)size) {
if (fwrite(data,sizeof(char),size,fp) != (size_t)size) {
valid = false;
return false;
}