Merged changes from Nicklov Trajce and Boris Bralo.

This commit is contained in:
Robert Osfield
2003-07-23 13:34:48 +00:00
parent 7b2a0d0b06
commit 0c662e596c
46 changed files with 12403 additions and 9551 deletions

View File

@@ -122,6 +122,10 @@ SOURCE=..\..\..\src\osgPlugins\txp\trpage_header.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\txp\trpage_label.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\txp\trpage_light.cpp
# End Source File
# Begin Source File
@@ -134,6 +138,10 @@ SOURCE=..\..\..\src\osgPlugins\txp\trpage_material.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\txp\trpage_main.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\txp\trpage_model.cpp
# End Source File
# Begin Source File

View File

@@ -2,38 +2,40 @@ TOPDIR = ../../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
ReaderWriterTXP.cpp\
TerrapageNode.cpp\
IO_TerrapageNode.cpp\
TrPageArchive.cpp\
TrPageParser.cpp\
trpage_basic.cpp\
trpage_geom.cpp\
trpage_header.cpp\
trpage_tile.cpp\
trpage_readbuf.cpp\
trpage_rarchive.cpp\
trpage_writebuf.cpp\
trpage_warchive.cpp\
trpage_parse.cpp\
trpage_nodes.cpp\
trpage_model.cpp\
trpage_material.cpp\
trpage_swap.cpp\
trpage_range.cpp\
trpage_scene.cpp\
trpage_compat.cpp\
trpage_light.cpp\
trpage_pparse.cpp\
trpage_print.cpp\
trpage_managers.cpp\
trPagePageManager.cpp\
trpage_print_parse.cpp\
trpage_util.cpp\
IO_TerrapageNode.cpp\
ReaderWriterTXP.cpp\
TerrapageNode.cpp\
TrPageArchive.cpp\
TrPageParser.cpp\
trPagePageManager.cpp\
trpage_basic.cpp\
trpage_compat.cpp\
trpage_geom.cpp\
trpage_header.cpp\
trpage_label.cpp\
trpage_light.cpp\
trpage_main.cpp\
trpage_managers.cpp\
trpage_material.cpp\
trpage_model.cpp\
trpage_nodes.cpp\
trpage_parse.cpp\
trpage_pparse.cpp\
trpage_print.cpp\
trpage_print_parse.cpp\
trpage_range.cpp\
trpage_rarchive.cpp\
trpage_readbuf.cpp\
trpage_scene.cpp\
trpage_swap.cpp\
trpage_tile.cpp\
trpage_util.cpp\
trpage_warchive.cpp\
trpage_writebuf.cpp\
INC += -I$(THISDIR)
INC += -I$(THISDIR)
LIBS += $(OSG_LIBS) $(OTHER_LIBS)

View File

@@ -1,3 +1,4 @@
#include "ReaderWriterTXP.h"
#include <osg/Group>
#include <osg/Object>
#include <osg/Node>
@@ -8,7 +9,6 @@
#include <iostream>
#include "ReaderWriterTXP.h"
#include "TrPageArchive.h"
#include "TerrapageNode.h"

View File

@@ -1,5 +1,4 @@
#include "TerrapageNode.h"
#include <osg/Notify>
using namespace osg;
@@ -28,7 +27,6 @@ TerrapageNode::~TerrapageNode()
{
// will the page manger delete the archive?
delete _pageManager;
_pageManager = 0L;
}
void TerrapageNode::traverse(osg::NodeVisitor& nv)
@@ -121,7 +119,6 @@ bool TerrapageNode::loadDatabase()
addChild(node);
} else {
_pageManager = new OSGPageManager(txpArchive);
if (threadMode!=OSGPageManager::ThreadNone)

View File

@@ -3,10 +3,11 @@
#ifndef TERRAPAGENODE_H
#define TERRAPAGENODE_H
#include "trPagePageManager.h"
#include <osg/Node>
#include <osg/BoundingBox>
#include "trPagePageManager.h"
namespace txp
{

View File

@@ -155,20 +155,25 @@ void TrPageArchive::LoadMaterials()
path += _PATHD ;
std::string theFile = path + filename ;
ref_ptr<Image> image = osgDB::readImageFile(theFile);
if (image.valid())
Image* image = osgDB::readImageFile(theFile);
if (image)
{
osg_texture->setImage(image.get());
osg_texture->setImage(image);
}
else
{
notify(WARN) << "TrPageArchive::LoadMaterials() error: "
<< "couldn't open image: " << filename << std::endl;
}
m_textures[i] = osg_texture;
}
else if( mode == trpgTexture::Local )
{
m_textures[i] = GetLocalTexture(image_helper,0, tex);
m_textures[i] = GetLocalTexture(image_helper,tex);
}
else if( mode == trpgTexture::Template )
{
m_textures[i] = GetLocalTexture(image_helper,0, tex);
m_textures[i] = 0L; //GetTemplateTexture(image_helper,0, tex);
}
else
{
@@ -436,7 +441,7 @@ Group* TrPageArchive::LoadTile(Group *rootNode,
{
int x,y,lod;
tile->GetTileLoc(x,y,lod);
std::vector<osg::Group *> *groupList = parse->GetGroupList();
std::vector<GeodeGroup *> *groupList = parse->GetGroupList();
// Fetch the tile data (but don't parse it)
if (!ReadTile(x,y,lod,buf))
@@ -497,6 +502,7 @@ Group* TrPageArchive::LoadAllTiles()
int32 numLod;
head->GetNumLods(numLod);
// Iterate over the LODs. Lower res LODs must be loaded
// first, otherwise there's nothing to hook the higher res
// LODs into.
@@ -504,7 +510,7 @@ Group* TrPageArchive::LoadAllTiles()
// The group list is used to map parent IDs to pfGroup nodes
//std::vector<Group *> groupList;
std::vector<Group *> *groupList = parse->GetGroupList();
std::vector<GeodeGroup *> *groupList = parse->GetGroupList();
for (int nl=0;nl<numLod;nl++)
{

View File

@@ -88,6 +88,11 @@ namespace txp
// Calculate the center
void GetCenter(osg::Vec3 &center);
osg::Texture2D* getGlobalTexture(int id)
{
return m_textures[id].get();
}
protected:
/// This class does most of the actual parsing.
std::auto_ptr<TrPageParser> parse;

View File

@@ -20,6 +20,7 @@
*
*****************************************************************************/
#include "trpage_sys.h"
#include <osg/AlphaFunc>
#include <osg/Group>
#include <osg/Material>
@@ -33,15 +34,11 @@
#include <osg/CullFace>
#include <osg/Light>
#include <osg/Notify>
#include <osg/PolygonOffset>
#include "TrPageParser.h"
#include "TrPageArchive.h"
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
*/
#include <algorithm>
using namespace txp;
@@ -49,7 +46,86 @@ using namespace osg;
using std::vector;
using std::string;
Texture2D* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMaterial* locmat, const trpgTexture* tex)
//----------------------------------------------------------------------------
// Check if the node is billboard
namespace {
bool is_billboard (Node* node)
{
if (node && (node!=(Node*)1) && (strcmp(node->className(),"GeodeGroup") == 0))
{
GeodeGroup* group = static_cast<GeodeGroup*>(node);
return (group->getNumChildren() && (strcmp(group->getChild(0)->className(),"Billboard") == 0));
}
return false;
};
void check_format(trpgTexture::ImageType type, int depth, GLenum& internalFormat, GLenum& pixelFormat, GLenum&)
{
switch(type)
{
case trpgTexture::trpg_RGB8:
internalFormat = GL_RGB;
pixelFormat = GL_RGB;
break;
case trpgTexture::trpg_RGBA8:
internalFormat = GL_RGBA;
pixelFormat = GL_RGBA;
break;
case trpgTexture::trpg_INT8:
internalFormat = GL_LUMINANCE;
pixelFormat = GL_LUMINANCE;
break;
case trpgTexture::trpg_INTA8:
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)
{
internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
pixelFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
}
else
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
}
break;
case trpgTexture::trpg_DXT3:
if(depth == 3)
{
// not supported.
}
else
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
}
break;
case trpgTexture::trpg_DXT5:
if(depth == 3)
{
// not supported.
}
else
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
break;
}
}
}
//----------------------------------------------------------------------------
// Get a template texture via the image helper
Texture2D* txp::GetLocalTexture(trpgrImageHelper& image_helper, const trpgTexture* tex)
{
Texture2D* osg_texture= 0L;
@@ -64,65 +140,7 @@ Texture2D* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMateria
GLenum pixelFormat = (GLenum)-1;
GLenum dataType = GL_UNSIGNED_BYTE;
switch(type)
{
case trpgTexture::trpg_RGB8:
internalFormat = GL_RGB;
pixelFormat = GL_RGB;
break;
case trpgTexture::trpg_RGBA8:
internalFormat = GL_RGBA;
pixelFormat = GL_RGBA;
break;
case trpgTexture::trpg_INT8:
internalFormat = GL_LUMINANCE;
pixelFormat = GL_LUMINANCE;
break;
case trpgTexture::trpg_INTA8:
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:
case trpgTexture::trpg_DDS:
break;
case trpgTexture::trpg_DXT1:
if(depth == 3)
{
internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
pixelFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
}
else
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
}
break;
case trpgTexture::trpg_DXT3:
if(depth == 3)
{
// not supported.
}
else
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
}
break;
case trpgTexture::trpg_DXT5:
if(depth == 3)
{
// not supported.
}
else
{
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
break;
}
check_format(type,depth,internalFormat , pixelFormat , dataType);
if(pixelFormat!=(GLenum)-1)
{
@@ -141,11 +159,76 @@ Texture2D* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMateria
int32 size = s.x*s.y*depth;
// int32 size = const_cast<trpgTexture*>(tex)->MipLevelSize(1) ;
data = new char [size];
image_helper.GetLocalGL(tex,data,size);
image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
(unsigned char*)data,osg::Image::USE_NEW_DELETE);
}
else
{
int32 size = tex->CalcTotalSize();
trpgTexture* tmp_tex = const_cast<trpgTexture*>(tex);
if(locmat)
image_helper.GetImageForLocalMat(locmat,data,size);
else
image_helper.GetLocalGL(tex,data,size);
data = new char [size];
image_helper.GetLocalGL(tex,data,size);
// Load entire texture including mipmaps
image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
(unsigned char*)data,
osg::Image::USE_NEW_DELETE);
// now set mipmap data (offsets into image raw data)
Image::MipmapDataType mipmaps;
// number of offsets in osg is one less than num_mipmaps
// because it's assumed that first offset iz 0
mipmaps.resize(num_mipmaps-1);
for( int k = 1 ; k < num_mipmaps;k++ )
{
mipmaps[k-1] = tmp_tex->MipLevelOffset(k);
}
image->setMipmapData(mipmaps);
}
osg_texture->setImage(image);
}
return osg_texture;
}
//----------------------------------------------------------------------------
// Get a locale texture via the image helper
Texture2D* txp::GetTemplateTexture(trpgrImageHelper& image_helper, trpgLocalMaterial* locmat, const trpgTexture* tex, int index)
{
Texture2D* osg_texture= 0L;
trpg2iPoint s;
tex->GetImageSize(s);
int32 depth;
tex->GetImageDepth(depth);
trpgTexture::ImageType type;
tex->GetImageType(type);
GLenum internalFormat = (GLenum)-1;
GLenum pixelFormat = (GLenum)-1;
GLenum dataType = GL_UNSIGNED_BYTE;
check_format(type,depth,internalFormat , pixelFormat , dataType);
if(pixelFormat!=(GLenum)-1)
{
osg_texture = new Texture2D();
Image* image = new Image;
char* data = 0L;
bool bMipmap;
tex->GetIsMipmap(bMipmap);
int32 num_mipmaps = bMipmap ? tex->CalcNumMipmaps() : 1; // this is currently line 130
// osg::Image do their own mipmaps
if(num_mipmaps <= 1)
{
int32 size = s.x*s.y*depth;
// int32 size = const_cast<trpgTexture*>(tex)->MipLevelSize(1) ;
data = new char [size];
image_helper.GetNthImageForLocalMat(locmat,index, data,size);
image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
(unsigned char*)data,osg::Image::USE_NEW_DELETE);
@@ -157,10 +240,7 @@ Texture2D* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMateria
data = new char [size];
if(locmat)
image_helper.GetImageForLocalMat(locmat,data,size);
else
image_helper.GetLocalGL(tex,data,size);
image_helper.GetNthImageForLocalMat(locmat,index, data,size);
// Load entire texture including mipmaps
image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
@@ -180,29 +260,74 @@ Texture2D* txp::GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMateria
}
// // AAAARRRGH! TOOK ME 2 DAYS TO FIGURE IT OUT
// // EVERY IMAGE HAS TO HAVE UNIQUE NAME FOR OPTIMIZER NOT TO OPTIMIZE IT OFF
// //
// static int unique = 0;
// char unique_name[256];
// sprintf(unique_name,"TXP_TEX_UNIQUE%d",unique++);
//
// image->setFileName(unique_name);
osg_texture->setImage(image);
}
return osg_texture;
}
//----------------------------------------------------------------------------
//
// Group Reader Class
//
//----------------------------------------------------------------------------
// Apply transformation on geometry
class TransformFunctor : public osg::Drawable::AttributeFunctor
{
public:
osg::Matrix _m;
osg::Matrix _im;
TransformFunctor(const osg::Matrix& m)
{
_m = m;
_im.invert(_m);
}
virtual ~TransformFunctor() {}
virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
{
if (type == osg::Drawable::VERTICES)
{
osg::Vec3* end = begin+count;
for (osg::Vec3* itr=begin;itr<end;++itr)
{
(*itr) = (*itr)*_m;
}
}
else if (type == osg::Drawable::NORMALS)
{
osg::Vec3* end = begin+count;
for (osg::Vec3* itr=begin;itr<end;++itr)
{
// note post mult by inverse for normals.
(*itr) = osg::Matrix::transform3x3(_im,(*itr));
(*itr).normalize();
}
}
}
inline void SetMatrix(const osg::Matrix& m)
{
_m = m;
_im.invert(_m);
}
};
//----------------------------------------------------------------------------
geomRead::geomRead(TrPageParser *in_parse)
{
parse = in_parse;
}
//----------------------------------------------------------------------------
geomRead::~geomRead()
{
}
//----------------------------------------------------------------------------
void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgGeometry geom;
@@ -222,8 +347,8 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
geom.GetMaterial(0,matId, local);
geom.GetNumNormal(numNorm);
Vec3Array* vertices = new Vec3Array(numVert);
// Get vertices
Vec3Array* vertices = new Vec3Array(numVert);
geom.GetVertices((float *)&(vertices->front()));
// Turn the trpgGeometry into something Performer can understand
@@ -246,15 +371,15 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
}
}
}
// The normals
Vec3Array* normals = 0L;
if (numNorm == numVert)
{
normals = new Vec3Array(numVert);
geom.GetNormals(&(normals->front()));
geom.GetNormals((float*)&(normals->front()));
}
Geode *geode = new Geode();
// Set up the primitive type
switch (primType)
{
@@ -264,6 +389,12 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
geometry->addPrimitiveSet(new DrawArrays(PrimitiveSet::TRIANGLES,0,numPrims*3));
}
break;
case trpgGeometry::Quads:
{
geometry = new Geometry;
geometry->addPrimitiveSet(new DrawArrays(PrimitiveSet::QUADS,0,numPrims*4));
}
break;
case trpgGeometry::TriStrips:
{
// Need primitive lengths too
@@ -331,7 +462,8 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Add it to the current parent group
Group *top = parse->GetCurrTop();
GeodeGroup *top = parse->GetCurrTop();
Geode *geode = top->GetGeode();
if (geometry)
{
// added this set use display list off since terrapage will
@@ -359,17 +491,86 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
geometry->setTexCoordArray( texno, tex_coords[texno]);
}
geometry->setStateSet(sset.get());
geode->addDrawable(geometry);
top->addChild(geode);
if ( is_billboard(top) )
{
geometry->setStateSet(sset.get());
Billboard *billboard = static_cast<Billboard*>(top->getChild(0));
switch (parse->getBillboardType()) {
case trpgBillboard::Individual:
{
// compute center of billboard geometry
const BoundingBox& bbox = geometry->getBound();
Vec3 center ((bbox._min + bbox._max) * 0.5f);
// make billboard geometry coordinates relative to computed center
Matrix matrix;
matrix.makeTranslate(-center[0], -center[1], -center[2]);
TransformFunctor tf(matrix);
geometry->accept(tf);
geometry->dirtyBound();
billboard->addDrawable(geometry);
billboard->setPos(0, center);
}
break;
case trpgBillboard::Group:
{
Vec3 center(parse->getBillboardCenter());
// make billboard geometry coordinates relative to specified center
Matrix matrix;
matrix.makeTranslate(-center[0], -center[1], -center[2]);
TransformFunctor tf(matrix);
geometry->accept(tf);
geometry->dirtyBound();
billboard->addDrawable(geometry);
billboard->setPos(0, center);
}
break;
default:
billboard->addDrawable(geometry);
notify(WARN) << "TerraPage loader: fell through case: " << __FILE__ << " " << __LINE__ << ".\n";
break;
}
}
else
{
// if this is part of the layer we turn the PolygonOffset on
if ( (parse->GetCurrLayer() == top) && geode->getNumDrawables() )
{
StateSet* poStateSet = new StateSet;
PolygonOffset* polyoffset = new PolygonOffset;
poStateSet->merge(*sset.get());
polyoffset->setFactor(-1.0f*geode->getNumDrawables());
polyoffset->setUnits(-20.0f*geode->getNumDrawables());
poStateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);
geometry->setStateSet(poStateSet);
}
else
{
geometry->setStateSet(sset.get());
}
geode->addDrawable(geometry);
}
}
return (void *) 1;
}
//----------------------------------------------------------------------------
//
// Group Reader Class
//
//----------------------------------------------------------------------------
groupRead::groupRead(TrPageParser *in_parse)
{
@@ -383,11 +584,37 @@ void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
if (!group.Read(buf))
return NULL;
// Create a new Performer group
Group *osg_Group = new Group();
GeodeGroup* osg_Group = new GeodeGroup();
// Dump this group into the hierarchy
Group *top = parse->GetCurrTop();
if (top)
top->addChild(osg_Group);
parse->AddIntoSceneGraph(osg_Group);
// Register the group for attachements
int32 id;
group.GetID(id);
parse->AddToGroupList(id,osg_Group);
return (void *) osg_Group;
}
//----------------------------------------------------------------------------
//
// Layer Reader Class
//
//----------------------------------------------------------------------------
layerRead::layerRead(TrPageParser *in_parse)
{
parse = in_parse;
}
//----------------------------------------------------------------------------
void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
trpgLayer group;
if (!group.Read(buf))
return NULL;
// Create a new Performer group
Layer* osg_Group = new Layer();
// Dump this group into the hierarchy
parse->AddIntoSceneGraph(osg_Group);
// Register for attachements
int32 id;
group.GetID(id);
parse->AddToGroupList(id,osg_Group);
@@ -398,6 +625,7 @@ void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
//
// Attach Reader Class
//
//----------------------------------------------------------------------------
attachRead::attachRead(TrPageParser *in_parse)
{
parse = in_parse;
@@ -410,11 +638,10 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
if (!group.Read(buf))
return NULL;
// Create a new Performer group
Group *osg_Group = new Group();
GeodeGroup* osg_Group = new GeodeGroup();
// Dump this group into the hierarchy
Group *top = parse->GetCurrTop();
if (top)
top->addChild(osg_Group);
parse->AddIntoSceneGraph(osg_Group);
// Register for attachements
int32 id;
group.GetID(id);
parse->AddToGroupList(id,osg_Group);
@@ -429,6 +656,7 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
//
// Billboard Reader Class
//
//----------------------------------------------------------------------------
billboardRead::billboardRead(TrPageParser *in_parse)
{
parse = in_parse;
@@ -437,37 +665,61 @@ billboardRead::billboardRead(TrPageParser *in_parse)
//----------------------------------------------------------------------------
void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
{
// Read in the txp billboard
trpgBillboard bill;
if (!bill.Read(buf))
return NULL;
Group* osg_Group = new Group;
int type;
bill.GetType(type);
// Note: Must deal with the billboard type here
if( type == trpgBillboard::Group )
{
// Create a new Performer group
Billboard* bl = new Billboard();
int m;
bill.GetMode(m);
if( m == trpgBillboard::Eye)
bl->setMode(Billboard::POINT_ROT_EYE);
else if(m == trpgBillboard::World )
bl->setMode(Billboard::POINT_ROT_WORLD);
else if(m == trpgBillboard::Axial )
{
trpg3dPoint p;
bill.GetAxis(p);
bl->setAxis(Vec3(p.x, p.y, p.z));
bl->setMode(Billboard::AXIAL_ROT);
}
osg_Group->addChild(bl);
}
// Create a group with a geometry beneath for the billboard
GeodeGroup* osg_Group = new GeodeGroup();
if (parse->inBillboard()) {
// we don't allow anything under a billboard except geometry
notify(WARN) << "TerraPage loader: can only have geometry nodes beneath a billboard.\n";
}
else
{
int type, mode;
trpg3dPoint center, axis;
if (bill.GetType(type) && bill.GetMode(mode) && bill.GetCenter(center) && bill.GetAxis(axis)) {
Billboard* billboard = new Billboard();
osg_Group->SetGeode(billboard);
// save this state for processing of the geometry node(s)
parse->setBillboardType(type);
parse->setBillboardCenter(center);
// set the axis
// NOTE: Needs update, when the billboard implementation for
// arbitrary axis is ready
// billboard->setAxis(Vec3(axis.x, axis.y, axis.z));
billboard->setAxis(Vec3(0.0f,0.0,1.0f) );
billboard->setNormal(Vec3(0.0f,-1.0,0.0f));
// the mode
switch (mode) {
case trpgBillboard::Axial:
billboard->setMode(Billboard::AXIAL_ROT);
break;
case trpgBillboard::World:
billboard->setMode(Billboard::POINT_ROT_WORLD);
break;
case trpgBillboard::Eye:
billboard->setMode(Billboard::POINT_ROT_EYE);
break;
default:
notify(WARN) << "TerraPage loader: Unknown billboard type.\n";
notify(WARN) << "TerraPage loader: fell through case: " << __FILE__ << " " << __LINE__ << ".\n";
break;
}
}
}
// Dump this group into the hierarchy
Group *top = parse->GetCurrTop();
if (top)
top->addChild(osg_Group);
parse->AddIntoSceneGraph(osg_Group);
// Register
int32 id;
bill.GetID(id);
parse->AddToGroupList(id,osg_Group);
@@ -479,6 +731,7 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
//
// LOD Reader Class
//
//----------------------------------------------------------------------------
lodRead::lodRead (TrPageParser *in_parse)
{
parse = in_parse;
@@ -496,10 +749,10 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
double in,out,width;
lod.GetLOD(in,out,width);
double minRange = MIN(in,out);
double maxRange = MAX(in,out);
double maxRange = MAX(in,out+width);
// Create a new Performer LOD
LOD *osg_Lod = new LOD();
LOD* osg_Lod = new LOD();
Vec3 osg_Center;
osg_Center[0] = center.x; osg_Center[1] = center.y; osg_Center[2] = center.z;
osg_Lod->setCenter(osg_Center);
@@ -507,13 +760,12 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Our LODs are binary so we need to add a group under this LOD and attach stuff
// to that instead of the LOD
Group *osg_LodG = new Group();
GeodeGroup *osg_LodG = new GeodeGroup();
osg_Lod->addChild(osg_LodG);
// Dump this group into the hierarchy
Group *top = parse->GetCurrTop();
if (top)
top->addChild(osg_Lod);
parse->AddIntoSceneGraph(osg_Lod);
// Register for attachements
int32 id;
lod.GetID(id);
// Add the sub-group to the group list, not the LOD
@@ -525,6 +777,7 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
//
// Model Reference Reader Class
//
//----------------------------------------------------------------------------
modelRefRead::modelRefRead(TrPageParser *in_parse)
{
parse = in_parse;
@@ -573,6 +826,7 @@ void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
//
// Tile Header Reader Class
//
//----------------------------------------------------------------------------
tileHeaderRead::tileHeaderRead(TrPageParser *in_parse)
{
parse = in_parse;
@@ -598,6 +852,9 @@ TrPageParser::TrPageParser(TrPageArchive* parent)
parent_ = parent;
currTop = NULL;
top = NULL;
layerDepth = 0;
currLayer = NULL;
in_billboard = false;
// Register the readers
AddCallback(TRPG_GEOMETRY,new geomRead(this));
@@ -606,6 +863,7 @@ TrPageParser::TrPageParser(TrPageArchive* parent)
AddCallback(TRPG_BILLBOARD,new billboardRead(this));
AddCallback(TRPG_LOD,new lodRead(this));
AddCallback(TRPG_MODELREF,new modelRefRead(this));
AddCallback(TRPG_LAYER,new layerRead(this));
AddCallback(TRPGTILEHEADER,new tileHeaderRead(this));
}
@@ -628,7 +886,7 @@ trpgTileHeader *TrPageParser::GetTileHeaderRef()
// scene graph.
Group *TrPageParser::ParseScene(trpgReadBuffer &buf,vector<ref_ptr<StateSet> > &in_mat,vector<ref_ptr<Node> > &in_model)
{
top = currTop = new Group();
top = currTop = new GeodeGroup();
materials = &in_mat;
local_materials.clear();
models = &in_model;
@@ -647,6 +905,8 @@ Group *TrPageParser::ParseScene(trpgReadBuffer &buf,vector<ref_ptr<StateSet> > &
return ret;
}
//----------------------------------------------------------------------------
// Read local materials
void TrPageParser::LoadLocalMaterials()
{
// new to 2.0 LOCAL materials
@@ -673,56 +933,79 @@ void TrPageParser::LoadLocalMaterials()
const trpgTexture *tex;
int32 size;
image_helper.GetImageInfoForLocalMat(&locmat,&mat,&tex,size);
image_helper.GetImageInfoForLocalMat(&locmat, &mat,&tex,size);
int texId;
trpgTextureEnv texEnv;
mat->GetTexture(0,texId,texEnv);
int num_tex;
mat->GetNumTexture(num_tex);
for (int texNo = 0 ; texNo < num_tex; ++texNo)
{
int texId;
trpgTextureEnv texEnv;
mat->GetTexture(texNo,texId,texEnv);
// Set up texture environment
TexEnv *osg_texenv = new TexEnv();
int32 te_mode;
texEnv.GetEnvMode(te_mode);
switch( te_mode )
{
case trpgTextureEnv::Alpha :
osg_texenv->setMode(TexEnv::REPLACE);
break;
case trpgTextureEnv::Decal:
osg_texenv->setMode(TexEnv::DECAL);
break;
case trpgTextureEnv::Blend :
osg_texenv->setMode(TexEnv::BLEND);
break;
case trpgTextureEnv::Modulate :
osg_texenv->setMode(TexEnv::MODULATE);
// Set up texture environment
TexEnv *osg_texenv = new TexEnv();
int32 te_mode;
texEnv.GetEnvMode(te_mode);
switch( te_mode )
{
case trpgTextureEnv::Alpha :
osg_texenv->setMode(TexEnv::REPLACE);
break;
case trpgTextureEnv::Decal:
osg_texenv->setMode(TexEnv::DECAL);
break;
case trpgTextureEnv::Blend :
osg_texenv->setMode(TexEnv::BLEND);
break;
case trpgTextureEnv::Modulate :
osg_texenv->setMode(TexEnv::MODULATE);
break;
}
osg_state_set->setTextureAttribute(texNo,osg_texenv);
image_helper.GetNthImageInfoForLocalMat(&locmat, texNo, &mat,&tex,size);
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
Texture2D* osg_texture = 0L;
if(mode == trpgTexture::Template)
osg_texture = GetTemplateTexture(image_helper,&locmat, tex, texNo);
else if(mode == trpgTexture::Local)
osg_texture = GetLocalTexture(image_helper,tex);
else if(mode == trpgTexture::Global)
osg_texture = parent_->getGlobalTexture(texId);
if(osg_texture)
{
if(osg_texture->getImage())
{
GLenum gltype = osg_texture->getImage()->getPixelFormat();
if( gltype == GL_RGBA || gltype == GL_LUMINANCE_ALPHA )
{
osg_state_set->setMode(GL_BLEND,StateAttribute::ON);
osg_state_set->setRenderingHint(StateSet::TRANSPARENT_BIN);
}
}
else
{
notify(WARN) << "No image\n";
}
osg_state_set->setTextureAttributeAndModes(texNo,osg_texture, StateAttribute::ON);
int wrap_s, wrap_t;
texEnv.GetWrap(wrap_s, wrap_t);
osg_texture->setWrap(Texture2D::WRAP_S, wrap_s == trpgTextureEnv::Repeat ? Texture2D::REPEAT: Texture2D::CLAMP );
osg_texture->setWrap(Texture2D::WRAP_T, wrap_t == trpgTextureEnv::Repeat ? Texture2D::REPEAT: Texture2D::CLAMP );
}
else
{
notify(WARN) << "No texture\n";
}
}
osg_state_set->setTextureAttribute(0,osg_texenv);
Texture2D* osg_texture = GetLocalTexture(image_helper,&locmat, tex);
if(osg_texture)
{
if(osg_texture->getImage())
{
GLenum gltype = osg_texture->getImage()->getPixelFormat();
if( gltype == GL_RGBA || gltype == GL_LUMINANCE_ALPHA )
{
osg_state_set->setMode(GL_BLEND,StateAttribute::ON);
osg_state_set->setRenderingHint(StateSet::TRANSPARENT_BIN);
}
}
osg_state_set->setTextureAttributeAndModes(0,osg_texture, StateAttribute::ON);
int wrap_s, wrap_t;
texEnv.GetWrap(wrap_s, wrap_t);
osg_texture->setWrap(Texture2D::WRAP_S, wrap_s == trpgTextureEnv::Repeat ? Texture2D::REPEAT: Texture2D::CLAMP );
osg_texture->setWrap(Texture2D::WRAP_T, wrap_t == trpgTextureEnv::Repeat ? Texture2D::REPEAT: Texture2D::CLAMP );
}
Material *osg_material = new Material;
Material *osg_material = new Material;
float64 alpha;
mat->GetAlpha(alpha);
@@ -799,9 +1082,30 @@ void TrPageParser::LoadLocalMaterials()
// We'll want to make the node it's handing us the "top" node
bool TrPageParser::StartChildren(void *in_node)
{
Group *node = (Group *)in_node;
currTop = node;
// Make a node
GeodeGroup *node = (GeodeGroup *)in_node;
// If we are under layer we need to drop all groups. Then
// the current parent is still the layer node
if (layerDepth==0)
{
// Set it as current parent
currTop = node;
}
//
// track whether we are under a billboard in the scene graph
//
if (is_billboard(currTop))
in_billboard = true;
// Chek if it's layer
if (node && (in_node != (void*)1) && (strcasecmp(node->className(),"Layer") == 0))
{
if (layerDepth==0)
currLayer = (Layer*)node;
layerDepth++;
}
return true;
}
@@ -811,25 +1115,57 @@ bool TrPageParser::StartChildren(void *in_node)
// We'll want to look on the parent list (in trpgSceneParser)
// for the parent above the current one.
// If there isn't one, we'll just stick things in our top group.
bool TrPageParser::EndChildren(void * /* in_node */)
bool TrPageParser::EndChildren(void *in_node)
{
// Get the parent above the current one
int pos = parents.size()-2;
if (pos < 0)
{
// Nothing above the current one. Fall back on our top group
currTop = top;
}
else
{
currTop = (Group *)parents[pos];
}
// Chek if it's layer
osg::Node* node = (osg::Node*)in_node;
if (node && (in_node != (void*)1) && (strcasecmp(node->className(),"Layer") == 0))
{
if (layerDepth > 0)
layerDepth--;
else
{
notify(WARN) << "Layer depth < 0 ???\n";
}
if (layerDepth==0)
{
currLayer = NULL;
for (unsigned int i = 0; i < deadNodes.size(); i++)
{
osg::ref_ptr<Node> deadNode = deadNodes[i];
}
deadNodes.clear();
}
}
//
// track whether we are under a billboard in the scene graph
//
if (is_billboard(static_cast<Billboard*>(in_node)))
in_billboard = false;
// if we are under layer all the groups are dropped out, so no need to do this
if (layerDepth==0)
{
// Get the parent above the current one
int pos = parents.size()-2;
if (pos < 0)
{
// Nothing above the current one. Fall back on our top group
currTop = top;
}
else
{
currTop = (GeodeGroup *)parents[pos];
}
}
return true;
}
//----------------------------------------------------------------------------
// Return the current top node
Group *TrPageParser::GetCurrTop()
GeodeGroup *TrPageParser::GetCurrTop()
{
if (currTop)
{
@@ -843,10 +1179,14 @@ Group *TrPageParser::GetCurrTop()
//----------------------------------------------------------------------------
// Add the given pfGroup to the group list at position ID
bool TrPageParser::AddToGroupList(int ID,Group *group)
bool TrPageParser::AddToGroupList(int ID,GeodeGroup *group)
{
// Note: check bounds
groupList[ID] = group;
// we dont do this if we are under layer
if (layerDepth==0)
{
// Note: check bounds
groupList[ID] = group;
}
return true;
}
@@ -862,3 +1202,27 @@ void TrPageParser::SetMaxGroupID(int maxGroupID)
for (int i=0;i<maxGroupID;i++)
groupList.push_back(NULL);
}
//----------------------------------------------------------------------------
// Use this to add nodes into the scenegraph
void TrPageParser::AddIntoSceneGraph(osg::Node* node)
{
// chek first if we are under some layer
if (layerDepth)
{
deadNodes.push_back(node);
}
else
{
Group *top = GetCurrTop();
if (top)
top->addChild(node);
}
}
//----------------------------------------------------------------------------
// Return the current layer node (also used during parsing)
Layer *TrPageParser::GetCurrLayer()
{
return currLayer;
}

View File

@@ -29,6 +29,7 @@
#include <osg/ref_ptr>
#include <osg/Texture2D>
#include <osg/Group>
#include <osg/Geode>
#include <osg/StateSet>
#include <vector>
#include "trpage_read.h"
@@ -44,14 +45,74 @@ namespace txp
int id;
} GroupIDInfo;
// This is group that will has geode node
// It is better since all the geometry children will be
// added into one Geode node as drawables, then having one
// geode node per child
// Means, instad of having
// Group
// +-----------
// | |
// Geode Geode
// | |
// Drawable Drawable
// we will have
// Group
// |
// Geode
// +-----------
// | |
// Drawable Drawable
// nick@terrex.com
class GeodeGroup : public osg::Group
{
protected:
osg::Geode* _geode;
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);
osg::Geode* GetGeode()
{
if (!_geode)
{
_geode = new osg::Geode();
addChild(_geode);
}
return _geode;
};
void SetGeode(osg::Geode* geode)
{
if ( _geode )
{
// I assume ref_ptr will destroy it
removeChild(_geode);
}
_geode = geode;
addChild(_geode);
}
};
// same as above, we need this to identify the node as Layer node
class Layer : public GeodeGroup
{
public:
Layer() : GeodeGroup() {};
Layer(const Layer& lr,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
: GeodeGroup(lr, copyop) {};
META_Node(txp, Layer);
};
class TrPageParser : public trpgSceneParser
{
public:
TrPageParser(TrPageArchive* parent);
~TrPageParser();
// Scene parser
osg::Group *ParseScene(trpgReadBuffer & buf,
std::vector<osg::ref_ptr<osg::StateSet> > & materials_,
std::vector<osg::ref_ptr<osg::StateSet> > & materials_,
std::vector<osg::ref_ptr<osg::Node> > & node );
// Return the parent of a recently parsed tile
@@ -61,46 +122,124 @@ namespace txp
trpgTileHeader *GetTileHeaderRef();
// Return the current top node (used during parsing)
osg::Group *GetCurrTop();
GeodeGroup *GetCurrTop();
// Return the current layer node (also used during parsing)
Layer *GetCurrLayer();
// Return the current material list (passed in to ParseScene())
std::vector<osg::ref_ptr<osg::StateSet> >* GetMaterials() { return materials; }
// new to TerraPage 2.0 - local materials
std::vector<osg::ref_ptr<osg::StateSet> >* GetLocalMaterials() { return &local_materials; }
std::vector<osg::ref_ptr<osg::Node> >* GetModels() { return models; }
// Add the Group to the current group list
bool AddToGroupList(int id,osg::Group *);
bool AddToGroupList(int id,GeodeGroup*);
// Use this to add nodes into the scenegraph
void AddIntoSceneGraph(osg::Node* node);
// Return the group list
std::vector< osg::Group *> *GetGroupList() { return &groupList; }
std::vector< GeodeGroup *> *GetGroupList() { return &groupList; }
/// TXP 2.0 - local materials
void LoadLocalMaterials();
// Initialize the group list
void SetMaxGroupID(int maxGroupID);
// Methods for tracking whether we are under a billboard in the scene graph
bool inBillboard() const { return in_billboard; }
void setBillboardType(int type) { billboard_type = type; }
int getBillboardType() { return billboard_type; }
void setBillboardCenter(trpg3dPoint center) { billboard_center = center; }
osg::Vec3 getBillboardCenter() { return osg::Vec3(billboard_center.x, billboard_center.y, billboard_center.z); }
protected:
// Called on start children
bool StartChildren(void *);
// Called on end children
bool EndChildren(void *);
protected:
TrPageArchive* parent_;
osg::Group *currTop; // Current parent group
osg::Group *top; // Top group
trpgTileHeader tileHead; // Dump tile header here
TrPageArchive* parent_; // The archive
GeodeGroup *currTop; // Current parent group
GeodeGroup *top; // Top group
trpgTileHeader tileHead; // Dump tile header here
// If there was an attach node, this is
// the tile's parent ID. -1 otherwise
int parentID;
std::vector<osg::ref_ptr<osg::StateSet> >* materials;
std::vector<osg::ref_ptr<osg::StateSet> > local_materials;
std::vector<osg::Group *> groupList;
std::vector<osg::ref_ptr<osg::Node> >* models;
int parentID;
// Materials
std::vector<osg::ref_ptr<osg::StateSet> >* materials;
// Local materials
std::vector<osg::ref_ptr<osg::StateSet> > local_materials;
// Group list. Probably needed for keepinh tracks of the IDs (?)
std::vector<GeodeGroup *> groupList;
// Model list
std::vector<osg::ref_ptr<osg::Node> >* models;
// track whether we are under a billboard in the scene graph
bool in_billboard;
int billboard_type;
trpg3dPoint billboard_center;
// Keeps track how deep are we into the layer subtree
int layerDepth;
// The current layer we are processing nodes below
Layer* currLayer;
// Nodes that are part of the label subtree and will never get
// into the sceen graph.
// Consider this subtree
// Layer0
// +-------------------
// | |
// Group0(layer0) Group4(layer1)
// | |
// Group1 Geometry3(for layer1)
// +---------------
// | |
// Geometry0 Layer1
// +---------------
// | |
// Group2 Group3
// | |
// Geometry1 Geometry2
//
// The idea is to have all the geometries below Layer0 into one Geode
// and set the right PolygonOffset. That means the rest of the nodes will go away
// One problem that can occur is, if there is trpgAttach existing that attach something
// to a trpgGroup from the Layer0 subtree ( or LODs - but I dont think any writer will do
// produce such an archive ). The right way to do this probably is by using
// targettable bin numbers, but I was not able to make it work
// Here's Layer0 in osg representation
// Layer0 (it's GeodeGroup, it has it's own Geode)
// |
// Geode
// +-----------------------------------
// | | | |
// Geometry0 Geometry1 Geometry2 Geometry3
//
// Geometry1-3 will have PolygonState truned on
// p.s. I have no archive at present to test this against. Usualy, the layers are
// coming out of TerraVista in such a tree as follows:
// Layer
// +---------------
// | |
// Group(layer0) Group(layer1)
// | |
// Geometry Geometry
// It is tested on this kind of archive and it works.
// nick@terrex.com
std::vector<osg::Node*> deadNodes;
};
osg::Texture2D* GetLocalTexture(trpgrImageHelper& image_helper, trpgLocalMaterial* locmat, const trpgTexture* tex);
// Gets local texture via the image helper
osg::Texture2D* GetLocalTexture(trpgrImageHelper& image_helper, const trpgTexture* tex);
osg::Texture2D* GetTemplateTexture(trpgrImageHelper& image_helper, trpgLocalMaterial* locmat, const trpgTexture* tex, int index=0);
//! callback functions for various scene graph elements
//----------------------------------------------------------------------------
class geomRead : public trpgr_Callback {
public:
geomRead(TrPageParser *in_parse);
@@ -163,6 +302,15 @@ namespace txp
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class layerRead: public trpgr_Callback {
public:
layerRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
} // namespace txp
#endif

View File

@@ -1,36 +1,32 @@
#ifndef WAIT_BLOCK_H
#define WAIT_BLOCK_H
#if !defined(WIN32) || defined(__CYGWIN__)
#include <pthread.h>
#include <OpenThreads/Condition>
namespace osgTXP {
struct WaitBlock{
pthread_mutex_t mut;
pthread_cond_t cond;
OpenThreads::Mutex mut;
OpenThreads::Condition cond;
WaitBlock()
{
pthread_mutex_init( &mut, 0L );
pthread_cond_init( &cond, 0L );
}
void wait()
{
pthread_mutex_lock( &mut );
pthread_cond_wait( &cond, &mut);
pthread_mutex_unlock(&mut);
mut.lock();
cond.wait(&mut);
mut.unlock();
}
void release()
{
pthread_mutex_lock( &mut );
pthread_cond_broadcast( &cond );
pthread_mutex_unlock( &mut );
// mut.lock();
cond.broadcast();
// mut.unlock();
}
};
}
#endif
#endif

View File

@@ -1,18 +1,6 @@
#include <stdlib.h>
#include <stdio.h>
#if defined(__CYGWIN__)
#include <windows.h>
#include <unistd.h>
#include <pthread.h>
#elif defined(_WIN32)
#include <windows.h>
#include <conio.h>
#else
#include <unistd.h>
#include <pthread.h>
#endif
#include "TrPageArchive.h"
#include "trPagePageManager.h"
#include "trpage_print.h"
@@ -21,8 +9,6 @@
#include <osg/Object>
#include <osg/Node>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/Texture>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
@@ -32,6 +18,12 @@
using namespace txp;
using namespace osg;
#if defined(WIN32)
#define sleep(x) Sleep((x))
#else
#define sleep(x) usleep((x)*1000)
#endif
OSGPageManager::OSGPageManager(TrPageArchive *in_arch,trpgPageManager *in_pageManage)
{
archive = in_arch;
@@ -40,7 +32,8 @@ OSGPageManager::OSGPageManager(TrPageArchive *in_arch,trpgPageManager *in_pageMa
if (!in_arch)
throw 1;
if (pageManage)
if (pageManage)
pageManageOurs = false;
else {
pageManage = new trpgPageManager();
@@ -117,69 +110,22 @@ bool OSGPageManager::UpdateNoThread(osg::Group *rootNode,double locX,double locY
// Mutex lock function
// --- Either thread ---
void osgLockMutex(ThreadMutex &mtx)
struct osgGuard
{
#if defined (_WIN32)
WaitForSingleObject( mtx, INFINITE);
#else
pthread_mutex_lock( &mtx );
#endif
}
ThreadMutex& _mtx;
osgGuard(ThreadMutex &mtx):_mtx(mtx){
_mtx.lock();
}
~osgGuard(){
_mtx.unlock();
}
};
// Mutex unlock function
// --- Either thread ---
void osgUnLockMutex(ThreadMutex &mtx)
void PagingThread::run()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
ReleaseMutex(mtx);
#else
pthread_mutex_unlock( &mtx );
#endif
pager->ThreadLoop(this);
}
// Wait for Event
// --- Either thread (only used in paging thread) ---
void osgWaitEvent(ThreadEvent &ev)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
WaitForSingleObject( ev, INFINITE);
#else
ev.wait();
#endif
}
// Set Event (i.e. notify the other thread something's up)
// --- Either thread (only used in main thread) ---
void osgSetEvent(ThreadEvent &ev)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
SetEvent(ev);
#else
ev.release();
#endif
}
// Windows specific thread function.
// This just fires up our own loop
// --- Paging Thread ---
#if defined(_WIN32) && !defined(__CYGWIN__)
DWORD WINAPI ThreadFunc( LPVOID lpParam )
{
OSGPageManager *myPager = (OSGPageManager *)lpParam;
myPager->ThreadLoop();
return 0;
}
#else // Pthreads, cause Pthreads is a POSIX standard and is EVERYWHERE else
void *ThreadFunc( void *data )
{
OSGPageManager *myPager = static_cast<OSGPageManager *>(data);
myPager->ThreadLoop();
return 0L;
}
#endif
/* Start Thread
This initialized
--- Main Thread ---
@@ -188,174 +134,152 @@ bool OSGPageManager::StartThread(ThreadMode mode,ThreadID &newThread)
{
positionValid = false;
#if defined(_WIN32) && !defined(__CYGWIN__)
// Create the event we'll use to wake up the pager thread when the location changes
locationChangeEvent = CreateEvent(NULL,false,false,"Location Change Event");
// Create the mutexes we'll need later
changeListMutex = CreateMutex(NULL,false,"Change List Mutex");
locationMutex = CreateMutex(NULL,false,"Location Mutex");
{
// Create the thread
DWORD dwThreadId=0;
LPVOID dwThrdParam = (LPVOID) this;
threadID = newThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunc, // thread function
dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
}
// Note: Should be optional
// Set the priority low so this is only called when the other thread is idle
// if (!SetThreadPriority(newThread,THREAD_PRIORITY_IDLE))
// fprintf(stderr,"Couldn't set paging thread priority.\n");
// Was successfull
if (newThread != NULL)
threadMode = mode;
#else
//locationChangeEvent is self-initialized.
pthread_mutex_init( &changeListMutex, 0L );
pthread_mutex_init( &locationMutex, 0L );
threadMode = mode;
if( pthread_create( &newThread, 0L, ThreadFunc, (void *)this ) != 0 )
threadMode = ThreadNone;
threadID = newThread;
#endif
pagingThread.pager = this;
pagingThread.startThread();
newThread = pagingThread.getThreadId();
return threadMode != ThreadNone;
}
/* End Thread
Note: Do this
*/
bool OSGPageManager::EndThread()
{
cancel = true;
// claer the path for thred loop to finish
osgSetEvent(locationChangeEvent);
#ifdef _WIN32
DWORD res = STILL_ACTIVE;
while(res==STILL_ACTIVE){
GetExitCodeThread(threadID,&res);
Sleep(100);
}
#else
// Need a handle to the thread ID here.
pthread_join( threadID, 0 );
#endif
// locationChangeEvent.release();
pagingThread.cancel();
return true;
}
void OSGPageManager::LoadOneTile(trpgManagedTile* tile)
{
osg::Group* tileGroup;
osg::Group* parentNode ;
int x,y,lod;
tile->GetTileLoc(x,y,lod);
tileGroup = archive->LoadTile(NULL,pageManage,tile,&parentNode);
if (tileGroup)
{
#ifdef USE_THREADLOOP_DELETE
// Make an extra reference to it because we want it back for deletion
// RO, commenting out as we don't want to do delete here, we want it to happen in the merge thread.
tileGroup->ref();
#endif
// we only put tiles with NULL parent to merge list
// others are referenced when added as a child
osgGuard g(changeListMutex);
if(parentNode)
parentNode->addChild(tileGroup) ;
else
toMerge.push_back( tileGroup) ;
//toMergeParent.push_back(parentNode );
}
else
{
osg::notify(WARN) << "Failed to load tile (" << x << y << lod << ")" << std::endl ;
}
}
/* Thread Loop
This method is the main loop for the pager when it's
working in its own thread.
--- Paging Thread ---
*/
bool OSGPageManager::ThreadLoop()
bool OSGPageManager::ThreadLoop(PagingThread* t)
{
// Note: Only works for free running thread
if (threadMode != ThreadFree)
throw 1;
bool pagingActive = false;
cancel = false;
std::vector<osg::Group *> unhook;
std::vector <osg::Group *> nextDelete;
while (!cancel) {
/* Here's how we do it:
Wait for position change
Update manager w/ position
Form delete list
Load tile (if needed)
Add tile to merge list
*/
bool pagingActive = false;
while (!t->testCancel()) {
/* Here's how we do it:
Wait for position change
Update manager w/ position
Form delete list
Load tile (if needed)
Add tile to merge list
*/
// Position has already changed or we'll wait for it to do so
osgWaitEvent(locationChangeEvent);
// locationChangeEvent.wait();
double myLocX,myLocY;
{
osgLockMutex(locationMutex);
osgGuard g(locationMutex);
myLocX = locX;
myLocY = locY;
osgUnLockMutex(locationMutex);
positionValid = false;
}
// Pass the new location on to page manager
int x,y,lod;
trpg2dPoint loc;
loc.x = myLocX;
loc.y = myLocY;
if (pageManage->SetLocation(loc) || pagingActive) {
if (pageManage->SetLocation(loc) ) {
// If there were changes, process them
// Form the delete list first
trpgManagedTile *tile=NULL;
std::vector<osg::Group *> unhook;
unhook.clear();
while ((tile = pageManage->GetNextUnload())) {
unhook.push_back((Group *)(tile->GetLocalData()));
pageManage->AckUnload();
tile->GetTileLoc(x,y,lod);
unhook.push_back((Group *)(tile->GetLocalData()));
pageManage->AckUnload();
}
// Tell the main thread to unhook tiles
// and get the groups to delete as well.
std::vector <osg::Group *> nextDelete;
nextDelete.clear();
{
osgLockMutex(changeListMutex);
osgGuard g(changeListMutex);
// Add to the unhook list
for (unsigned int ti=0;ti<unhook.size();ti++)
toUnhook.push_back(unhook[ti]);
for(unsigned int kk = 0; kk < unhook.size();kk++)
{
toUnhook.push_back(unhook[kk]);
}
// Also get the list of deletions while we're here
#ifdef USE_THREADLOOP_DELETE
nextDelete = toDelete;
toDelete.clear();
// use the stl Luke :-) swap is constant time operation that do a = b; b.clear()
// if a is empty which is our case
nextDelete.swap(toDelete);
// toDelete.clear();
#endif
osgUnLockMutex(changeListMutex);
}
#ifdef USE_THREADLOOP_DELETE
// Unreference whatever we're supposed to delete
for (unsigned int gi=0;gi<nextDelete.size();gi++)
nextDelete[gi]->unref();
// Unreference whatever we're supposed to delete
for (unsigned int gi=0;gi<nextDelete.size();gi++)
{
if( nextDelete[gi] )
nextDelete[gi]->unref();
}
#endif
// Now do a single load
while( (tile = pageManage->GetNextLoad()) ) // Sasa's new code - more frame drops, but less missing tiles.
//if( (tile = pageManage->GetNextLoad()) ) // original code (0.9.4 and before) - less frame drops, more missing tiles.
{
osg::Group *tileGroup=NULL;
pagingActive = false;
osg::Group *parentNode = NULL;
tileGroup = archive->LoadTile(NULL,pageManage,tile,&parentNode);
pageManage->AckLoad();
if (tileGroup) {
#ifdef USE_THREADLOOP_DELETE
// Make an extra reference to it because we want it back for deletion
// RO, commenting out as we don't want to do delete here, we want it to happen in the merge thread.
tileGroup->ref();
#endif
}
else
{
int x,y,lod;
tile->GetTileLoc(x,y,lod);
fprintf(stderr,"Failed to load tile (%d,%d,%d)\n",x,y,lod);
}
// Now add this tile to the merge list
if (tileGroup) {
osgLockMutex(changeListMutex);
toMerge.push_back(tileGroup);
toMergeParent.push_back(parentNode);
osgUnLockMutex(changeListMutex);
}
// We're not necessarily done paging, we're just handing control back
// It's likely we'll be back here
pagingActive = true;
}
}
}
while((tile = pageManage->GetNextLoad()))
{
tile->GetTileLoc(x,y,lod);
osg::notify(WARN) << "Tile to load :" << x << ' ' << y << ' ' << lod << std::endl;
osg::notify(WARN) << "Position :" << loc.x << ' ' << loc.y << std::endl;
LoadOneTile(tile);
// Now add this tile to the merge list
pageManage->AckLoad();
}
}
else
sleep(10);
}
return true;
}
@@ -367,81 +291,19 @@ bool OSGPageManager::ThreadLoop()
void OSGPageManager::UpdatePositionThread(double inLocX,double inLocY)
{
// Update the position
{
if(!positionValid)
{
// Get the location mutex
osgLockMutex(locationMutex);
osgGuard g(locationMutex);
positionValid = true;
locX = inLocX-originX;
locY = inLocY-originY;
osgUnLockMutex(locationMutex);
}
// Notify the paging thread there's been a position update
osgSetEvent(locationChangeEvent);
// locationChangeEvent.release();
}
class ReleaseTexturesAndDrawablesVisitor : public osg::NodeVisitor
{
public:
ReleaseTexturesAndDrawablesVisitor():
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
{
}
virtual void apply(osg::Node& node)
{
apply(node.getStateSet());
traverse(node);
}
virtual void apply(osg::Geode& geode)
{
apply(geode.getStateSet());
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
apply(geode.getDrawable(i));
}
traverse(geode);
}
inline void apply(osg::StateSet* stateset)
{
if (stateset)
{
// search for the existance of any texture object attributes
bool foundTextureState = false;
osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList();
for(osg::StateSet::TextureAttributeList::iterator itr=tal.begin();
itr!=tal.end() && !foundTextureState;
++itr)
{
osg::StateSet::AttributeList& al = *itr;
osg::StateSet::AttributeList::iterator alitr = al.find(osg::StateAttribute::TEXTURE);
if (alitr!=al.end())
{
// found texture, so place it in the texture list.
osg::Texture* texture = static_cast<osg::Texture*>(alitr->second.first.get());
texture->dirtyTextureObject();
}
}
}
}
inline void apply(osg::Drawable* drawable)
{
apply(drawable->getStateSet());
if (drawable->getUseDisplayList() || drawable->getUseVertexBufferObjects())
{
drawable->dirtyDisplayList();
}
}
};
/* Merge Updates
Merge in the new tiles and unhook the ones we'll be deleting.
Actually, we'll hand these back to the paging thread for deletion.
@@ -450,46 +312,43 @@ public:
bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode)
{
std::vector<osg::Group *> mergeList;
std::vector<osg::Group *> mergeParentList;
std::vector<osg::Group *> unhookList;
// Make local copies of the merge and unhook lists
{
osgLockMutex(changeListMutex);
mergeList = toMerge;
mergeParentList = toMergeParent;
unhookList = toUnhook;
toMerge.clear();
toMergeParent.clear();
toUnhook.clear();
osgUnLockMutex(changeListMutex);
}
osgGuard g(changeListMutex);
// use the stl Luke :-) swap is constant time operation that do a = b; b.clear()
// if a is empty which is our case
mergeList.swap(toMerge);
unhookList.swap(toUnhook);
// toMerge.clear();
// toMergeParent.clear();
// toUnhook.clear();
}
// Do the unhooking first
for (unsigned int ui=0;ui<unhookList.size();ui++) {
osg::Group *unhookMe = unhookList[ui];
// better safe than sorry
if(!unhookMe ) continue;
// Look for its parent(s)
// Only expecting one, but it doesn't matter
const osg::Node::ParentList &parents = unhookMe->getParents();
for (unsigned int pi=0;pi<parents.size();pi++) {
osg::Group *parent = parents[pi];
parent->removeChild(unhookMe);
if(parent != rootNode)
parent->removeChild(unhookMe);
}
}
#ifdef USE_THREADLOOP_DELETE
// Put the unhooked things on the list to delete
{
ReleaseTexturesAndDrawablesVisitor rtadv;
osgLockMutex(changeListMutex);
for (unsigned int di=0;di<unhookList.size();di++)
{
toDelete.push_back(unhookList[di]);
unhookList[di]->accept(rtadv);
}
osgUnLockMutex(changeListMutex);
osgGuard g(changeListMutex);
for (unsigned int i = 0; i < unhookList.size();i++)
toDelete.push_back(unhookList[i]);
}
#endif
@@ -497,13 +356,15 @@ bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode)
{
for (unsigned int mi=0;mi<mergeList.size();mi++) {
osg::Group *mergeMe = mergeList[mi];
osg::Group *parent = mergeParentList[mi];
if (parent)
parent->addChild(mergeMe);
else
rootNode->addChild(mergeMe);
// NO need for that - we only put tiles with NULL parent to merge list
// osg::Group *parent = mergeParentList[mi];
// if (parent)
// parent->addChild(mergeMe);
// else
rootNode->addChild(mergeMe);
}
}
return true;
}

View File

@@ -17,16 +17,13 @@
#ifndef _TRPAGEMANAGER_H_
#define _TRPAGEMANAGER_H_
#include <string>
#if defined(__CYGWIN__) || !defined(WIN32)
#include <pthread.h>
#endif
#include <osg/Group>
#include <osg/Object>
#include <osg/Node>
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
#include "trpage_geom.h"
#include "trpage_read.h"
#include "trpage_write.h"
@@ -35,6 +32,8 @@
#include "WaitBlock.h"
#include "TrPageArchive.h"
#include <string>
// Dec 2002, Robert Osfield -> comment out now, as we actually do want to delete in the main thread
// as the deletion of the display and texture object isn't thread safe.
// Jan 2002, Robert osfield -> comment back in now, as I've changed the way the
@@ -42,7 +41,7 @@
// in theory its still not thread safe, but a point swap should be much faster
// and less likely to encounter a race condition on the static caches of display
// and texture object lists.
#define USE_THREADLOOP_DELETE
// #define USE_THREADLOOP_DELETE
namespace txp
{
@@ -50,22 +49,31 @@ namespace txp
Fill this in for your specific platform.
Should be water ID you use for threads.
*/
#if defined(_WIN32) && !defined(__CYGWIN__)
typedef HANDLE ThreadID;
typedef HANDLE ThreadMutex;
typedef HANDLE ThreadEvent;
#else
typedef pthread_t ThreadID;
typedef pthread_mutex_t ThreadMutex;
typedef int ThreadID;
typedef OpenThreads::Mutex ThreadMutex;
typedef osgTXP::WaitBlock ThreadEvent;
#endif
class OSGPageManager;
class PagingThread: public OpenThreads::Thread{
public:
typedef OpenThreads::Thread super;
PagingThread():pager(NULL)
{
}
virtual void run();
OSGPageManager *pager;
private:
volatile bool canceled;
};
/* OSG Page Manager
This class handles the paging into
*/
class OSGPageManager {
class OSGPageManager{
public:
/* Need a group to put things under and the archive to page.
/* Need a group to put things under and the archive to page.
Also, optionally, a Page Manager (if you've made changes
to the default one).
*/
@@ -112,7 +120,12 @@ namespace txp
// Called by the thread start function
// Don't call this yourself
bool ThreadLoop();
bool ThreadLoop(PagingThread* t);
// Load One tile
// @param tile managed tile
// @return tileGroup osg::Group representing managed tile
void LoadOneTile(trpgManagedTile* tile);
protected:
// Page Manager we'll use is ours (i.e. delete it at the end)
@@ -128,7 +141,7 @@ namespace txp
// ID of created thread and whether it's valid
ThreadMode threadMode;
ThreadID threadID;
PagingThread pagingThread;
// Used to notify the paging thread when the location changes
ThreadEvent locationChangeEvent;
@@ -142,17 +155,17 @@ namespace txp
ThreadMutex changeListMutex;
// Merge list is filled in by the paging thread.
std::vector<osg::Group *> toMerge;
std::vector<osg::Group *> toMergeParent;
// no need for that
// std::vector<osg::Group *> toMergeParent;
// Unhook list is filled in by the paging thread
std::vector<osg::Group *> toUnhook;
volatile bool cancel;
#ifdef USE_THREADLOOP_DELETE
// Main thread moves groups to the delete list as soon as they are unhooked
std::vector<osg::Group *> toDelete;
#endif
};
};
#endif

View File

@@ -14,9 +14,9 @@
*/
/* trdll.h
Windows Only
Windows Only
This header file defines the declaration macros for DLLs.
This header file defines the declaration macros for DLLs.
*/
// Export/import declaration for classes and functions
@@ -87,15 +87,11 @@
// The following is a DLL Main function for DLLs that wouldn't otherwise
// have one. It's needed to initialize the run time library.
// This should appear once within every DLL
// commented out by Boris Bralo for osg
/*
#ifndef TXDUMMY_DLL_MAIN
#define TXDUMMY_DLL_MAIN \
extern "C" { \
BOOL WINAPI _CRT_INIT (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved); \
BOOL APIENTRY DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) \
BOOL APIENTRY DllMain (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved) \
{ \
switch (dwReason) \
{ \
@@ -114,8 +110,8 @@ BOOL APIENTRY DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) \
return TRUE; \
} \
}
#endif
*/
#endif
#ifndef txdll_h_

View File

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

View File

@@ -24,19 +24,19 @@
*/
#include "trpage_geom.h"
#include "trpage_read.h"
#include "trpage_compat.h"
#include <trpage_geom.h>
#include <trpage_read.h>
#include <trpage_compat.h>
/* Old short Material definition from 1.0.
{secret}
*/
class trpgShortMaterial {
public:
// Full trpgMaterial definition this one is based on
int baseMat;
// Currently the only thing a short material overrides is texture
std::vector<int> texids;
// Full trpgMaterial definition this one is based on
int baseMat;
// Currently the only thing a short material overrides is texture
std::vector<int> texids;
};
trpgMatTable1_0::trpgMatTable1_0(const trpgMatTable &inTbl)
@@ -46,85 +46,84 @@ trpgMatTable1_0::trpgMatTable1_0(const trpgMatTable &inTbl)
bool trpgMatTable1_0::Read(trpgReadBuffer &buf)
{
trpgMaterial mat;
trpgToken matTok;
int32 len;
bool status;
int i,j,k;
trpgMaterial mat;
trpgToken matTok;
int32 len;
bool status;
int i,j,k;
std::vector<trpgShortMaterial> shortTable;
std::vector<trpgMaterial> baseMats;
std::vector<trpgShortMaterial> shortTable;
std::vector<trpgMaterial> baseMats;
try {
buf.Get(numTable);
buf.Get(numMat);
if (numTable <= 0 || numMat < 0) throw 1;
try {
buf.Get(numTable);
buf.Get(numMat);
if (numTable <= 0 || numMat < 0) throw 1;
// Short material tables are always full size
shortTable.resize(numTable*numMat);
// Short material tables are always full size
shortTable.resize(numTable*numMat);
// Look for short material table
buf.GetToken(matTok,len);
if (matTok == TRPGSHORTMATTABLE) {
int32 numTex,texId;
buf.PushLimit(len);
for (i=0;i<numTable;i++)
for (j=0;j<numMat;j++) {
trpgShortMaterial &smat = shortTable[i*numMat+j];
buf.Get(smat.baseMat);
buf.Get(numTex);
for (k=0;k<numTex;k++) {
buf.Get(texId);
smat.texids.push_back(texId);
}
}
buf.PopLimit();
// Look for short material table
buf.GetToken(matTok,len);
if (matTok == TRPGSHORTMATTABLE) {
int32 numTex,texId;
buf.PushLimit(len);
for (i=0;i<numTable;i++)
for (j=0;j<numMat;j++) {
trpgShortMaterial &smat = shortTable[i*numMat+j];
buf.Get(smat.baseMat);
buf.Get(numTex);
for (k=0;k<numTex;k++) {
buf.Get(texId);
smat.texids.push_back(texId);
}
}
buf.PopLimit();
// Now read the base materials
int32 numBaseMat;
buf.Get(numBaseMat);
if (numBaseMat < 0) throw 1;
baseMats.resize(numBaseMat);
for (i=0;i<numBaseMat;i++) {
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
mat.Reset();
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
baseMats[i] = mat;
}
}
}
catch (...) {
return false;
}
// Now read the base materials
int32 numBaseMat;
buf.Get(numBaseMat);
if (numBaseMat < 0) throw 1;
baseMats.resize(numBaseMat);
for (i=0;i<numBaseMat;i++) {
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
mat.Reset();
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
baseMats[i] = mat;
}
}
}
catch (...) {
return false;
}
// Now convert to the new style material table
for (i=0;i<static_cast<int>(shortTable.size());i++)
{
trpgShortMaterial &shortMat = shortTable[i];
trpgMaterial &baseMat = baseMats[shortMat.baseMat];
matTables.push_back(baseMat);
trpgMaterial &newMat = matTables[matTables.size()-1];
newMat.SetNumTexture(shortMat.texids.size());
for (unsigned j=0;j<shortMat.texids.size();j++) {
int texId;
trpgTextureEnv texEnv;
baseMat.GetTexture(j,texId,texEnv);
newMat.SetTexture(j,shortMat.texids[j],texEnv);
}
}
// Now convert to the new style material table
for (i=0;i<shortTable.size();i++) {
trpgShortMaterial &shortMat = shortTable[i];
trpgMaterial &baseMat = baseMats[shortMat.baseMat];
matTables.push_back(baseMat);
trpgMaterial &newMat = matTables[matTables.size()-1];
newMat.SetNumTexture(shortMat.texids.size());
for (j=0;j<shortMat.texids.size();j++) {
int texId;
trpgTextureEnv texEnv;
baseMat.GetTexture(j,texId,texEnv);
newMat.SetTexture(j,shortMat.texids[j],texEnv);
}
}
valid = true;
return true;
valid = true;
return true;
}
bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
return false;
// Create one short material for every material
std::vector<trpgShortMaterial> shortMats;
@@ -132,21 +131,20 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
// Iterate over the existing materials
int i;
for (i=0;i<numTable*numMat;i++)
{
trpgMaterial &mat = matTables[i];
// Fill in the short material
trpgShortMaterial &sMat = shortMats[i];
int numTex;
mat.GetNumTexture(numTex);
for (int j=0;j<numTex;j++)
{
int texId;
trpgTextureEnv texEnv;
mat.GetTexture(j,texId,texEnv);
sMat.texids.push_back(texId);
sMat.baseMat = i;
}
for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = matTables[i];
// Fill in the short material
trpgShortMaterial &sMat = shortMats[i];
sMat.baseMat = 0;
int numTex;
mat.GetNumTexture(numTex);
for (int j=0;j<numTex;j++) {
int texId;
trpgTextureEnv texEnv;
mat.GetTexture(j,texId,texEnv);
sMat.texids.push_back(texId);
sMat.baseMat = i;
}
}
// Write the 1.0 material table
@@ -156,23 +154,23 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
// Write the short materials
buf.Begin(TRPGSHORTMATTABLE);
for (i=0;i<static_cast<int>(shortMats.size());i++)
{
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
for (unsigned int j=0;j<sMat.texids.size();j++)
buf.Add(sMat.texids[j]);
for (i=0;i<shortMats.size();i++) {
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
int j;
for (j=0;j<sMat.texids.size();j++)
buf.Add(sMat.texids[j]);
}
buf.End();
// Write the regular materials
buf.Add(numTable*numMat);
for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = matTables[i];
// This will be bigger than the old 1.0 material, but it doesn't matter since
// the new stuff is on the end.
mat.Write(buf);
trpgMaterial &mat = matTables[i];
// This will be bigger than the old 1.0 material, but it doesn't matter since
// the new stuff is on the end.
mat.Write(buf);
}
// Close Mat Table
@@ -190,26 +188,26 @@ trpgTexture1_0 trpgTexture1_0::operator = (const trpgTexture &inTex)
bool trpgTexture1_0::Read(trpgReadBuffer &buf)
{
mode = External;
mode = External;
try {
char texName[1024];
buf.Get(texName,1023);
SetName(texName);
buf.Get(useCount);
}
catch (...) {
return false;
}
try {
char texName[1024];
buf.Get(texName,1023);
SetName(texName);
buf.Get(useCount);
}
catch (...) {
return false;
}
return true;
return true;
}
bool trpgTexture1_0::Write(trpgWriteBuffer &buf)
{
// Can only deal with external textures in 1.0
if (mode != External)
return false;
return false;
// Write the name and use count
buf.Add(name);
@@ -225,48 +223,48 @@ trpgTexTable1_0::trpgTexTable1_0(const trpgTexTable &inTbl)
bool trpgTexTable1_0::Read(trpgReadBuffer &buf)
{
int32 numTex;
int32 numTex;
try {
buf.Get(numTex);
texList.resize(numTex);
for (int i=0;i<numTex;i++) {
trpgTexture1_0 tex1_0;
tex1_0.Read(buf);
texList[i] = tex1_0;
}
}
catch (...) {
return false;
}
try {
buf.Get(numTex);
texList.resize(numTex);
for (unsigned int i=0;i<numTex;i++) {
trpgTexture1_0 tex1_0;
tex1_0.Read(buf);
texList[i] = tex1_0;
}
}
catch (...) {
return false;
}
valid = true;
return true;
valid = true;
return true;
}
bool trpgTexTable1_0::Write(trpgWriteBuffer &buf)
{
int32 numTex;
int32 numTex;
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGTEXTABLE);
numTex = texList.size();
buf.Add(numTex);
for (unsigned int i=0;i<texList.size();i++) {
trpgTexture1_0 tex1_0;
tex1_0 = texList[i];
if (!tex1_0.Write(buf))
return false;
}
buf.End();
buf.Begin(TRPGTEXTABLE);
numTex = texList.size();
buf.Add(numTex);
for (unsigned int i=0;i<texList.size();i++) {
trpgTexture1_0 tex1_0;
tex1_0 = texList[i];
if (!tex1_0.Write(buf))
return false;
}
buf.End();
return true;
return true;
}
trpgTileTable1_0::trpgTileTable1_0(const trpgTileTable &)
trpgTileTable1_0::trpgTileTable1_0(const trpgTileTable &inTable)
{
// Nothing to copy for now
}
@@ -274,12 +272,12 @@ trpgTileTable1_0::trpgTileTable1_0(const trpgTileTable &)
bool trpgTileTable1_0::Write(trpgWriteBuffer &buf)
{
try {
buf.Begin(TRPGTILETABLE);
buf.Add("");
buf.End();
buf.Begin(TRPGTILETABLE);
buf.Add("");
buf.End();
}
catch (...) {
return false;
return false;
}
return true;

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,978 @@
/* ************************
Copyright Terrain Experts Inc.
Terrain Experts Inc (TERREX) reserves all rights to this source code
unless otherwise specified in writing by the President of TERREX.
This copyright may be updated in the future, in which case that version
supercedes this one.
-------------------
Terrex Experts Inc.
4400 East Broadway #314
Tucson, AZ 85711
info@terrex.com
Tel: (520) 323-7990
************************
*/
/* trpage_label.cpp
Methods for the trpgLable object and its associated support structure
including trpgTextStyle and trpgTextStyleTable.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <trpage_geom.h>
#include <trpage_read.h>
// *************** Text Style implementation
trpgTextStyle::trpgTextStyle(void)
{
Reset();
}
trpgTextStyle::~trpgTextStyle(void)
{
}
void trpgTextStyle::Reset(void)
{
font = "";
bold = italic = underline = false;
characterSize = float32(0.0042333333333); // 12 point in meter
matId = -1;
}
void trpgTextStyle::SetMaterial(int inMatId)
{
matId = inMatId;
}
int trpgTextStyle::GetMaterial(void) const
{
return matId;
}
void trpgTextStyle::SetFont(std::string &inFont)
{
font = inFont;
}
const std::string *trpgTextStyle::GetFont(void) const
{
return &font;
}
void trpgTextStyle::SetBold(bool inBold)
{
bold = inBold;
}
bool trpgTextStyle::GetBold(void) const
{
return bold;
}
void trpgTextStyle::SetItalic(bool inItalic)
{
italic = inItalic;
}
bool trpgTextStyle::GetItalic(void) const
{
return italic;
}
void trpgTextStyle::SetUnderline(bool inUnder)
{
underline = inUnder;
}
bool trpgTextStyle::GetUnderline(void) const
{
return underline;
}
void trpgTextStyle::SetCharacterSize(float32 inSize)
{
characterSize = inSize;
}
float32 trpgTextStyle::GetCharacterSize(void) const
{
return characterSize;
}
// Write method
bool trpgTextStyle::Write(trpgWriteBuffer &buf)
{
buf.Begin(TRPG_TEXT_STYLE);
buf.Begin(TRPG_TEXT_STYLE_BASIC);
buf.Add(font);
buf.Add(bold);
buf.Add(italic);
buf.Add(underline);
buf.Add(characterSize);
buf.Add(matId);
buf.End();
buf.End();
return true;
}
// TextStyle CB
// Used to parse tokens from the text style structure.
// If we do it this way it's easier to expand later.
class textStyleCB : public trpgr_Callback {
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgTextStyle *style;
};
void * textStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
std::string sVal;
int iVal;
float32 fVal;
try {
switch (tok) {
case TRPG_TEXT_STYLE_BASIC:
buf.Get(sVal);
style->SetFont(sVal);
buf.Get(iVal);
style->SetBold((iVal ? true : false));
buf.Get(iVal);
style->SetItalic((iVal ? true : false));
buf.Get(iVal);
style->SetUnderline((iVal ? true : false));
buf.Get(fVal);
style->SetCharacterSize(fVal);
buf.Get(iVal);
style->SetMaterial(iVal);
break;
default:
break;
}
}
catch (...) {
return NULL;
}
return style;
}
// Read from a buffer
bool trpgTextStyle::Read(trpgReadBuffer &buf)
{
Reset();
trpgr_Parser parse;
textStyleCB textStyleCb;
textStyleCb.style = this;
parse.AddCallback(TRPG_TEXT_STYLE_BASIC,&textStyleCb,false);
parse.Parse(buf);
return isValid();
}
bool trpgTextStyle::isValid(void) const
{
// Need to have a font designation at least
if (font.size() > 0)
return true;
return false;
}
bool trpgTextStyle::operator == (const trpgTextStyle& in) const
{
if (font.compare(in.font) != 0)
return false;
if (bold != in.bold ||
italic != in.italic ||
underline != in.underline)
return false;
if(fabs(double(characterSize - in.characterSize)) > 0.0001)
return false;
if (matId != in.matId)
return false;
return true;
}
// ******************* Text Style Table implementation
trpgTextStyleTable::trpgTextStyleTable()
{
Reset();
}
trpgTextStyleTable::~trpgTextStyleTable()
{
}
void trpgTextStyleTable::Reset()
{
styles.resize(0);
}
bool trpgTextStyleTable::isValid() const
{
for (int i=0;i<styles.size();i++)
if (!styles[i].isValid())
return false;
return true;
}
int trpgTextStyleTable::AddStyle(const trpgTextStyle &style)
{
styles.push_back(style);
return styles.size() -1;
}
int trpgTextStyleTable::FindAddStyle(const trpgTextStyle &style)
{
for (int i=0;i<styles.size();i++)
if (styles[i] == style)
return i;
return AddStyle(style);
}
int trpgTextStyleTable::GetNumStyle() const
{
return styles.size();
}
const trpgTextStyle *trpgTextStyleTable::GetStyleRef(int id) const
{
if (id < 0 || id >= styles.size())
return NULL;
return &styles[id];
}
bool trpgTextStyleTable::Write(trpgWriteBuffer &buf)
{
int i;
if (!isValid())
return false;
buf.Begin(TRPG_TEXT_STYLE_TABLE);
// Number of styles
int numStyle = styles.size();
buf.Add((int32)numStyle);
// Write the styles
for (i=0;i<styles.size();i++)
styles[i].Write(buf);
buf.End();
return true;
}
bool trpgTextStyleTable::Read(trpgReadBuffer &buf)
{
trpgTextStyle style;
trpgToken styleTok;
int32 len;
bool status;
int numStyle;
int i;
Reset();
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;
buf.PushLimit(len);
style.Reset();
status = style.Read(buf);
buf.PopLimit();
if (!status) throw 1;
styles[i] = style;
}
}
catch (...) {
return false;
}
return isValid();
}
// *************** Support Style implementation
trpgSupportStyle::trpgSupportStyle(void)
{
Reset();
}
trpgSupportStyle::~trpgSupportStyle(void)
{
}
void trpgSupportStyle::Reset(void)
{
type = Line;
matId = -1;
}
void trpgSupportStyle::SetType(SupportType s)
{
type = s;
}
trpgSupportStyle::SupportType trpgSupportStyle::GetType() const
{
return type;
}
void trpgSupportStyle::SetMaterial(int inMatId)
{
matId = inMatId;
}
int trpgSupportStyle::GetMaterial(void) const
{
return matId;
}
// Write method
bool trpgSupportStyle::Write(trpgWriteBuffer &buf)
{
buf.Begin(TRPG_SUPPORT_STYLE);
buf.Begin(TRPG_SUPPORT_STYLE_BASIC);
buf.Add(type);
buf.Add(matId);
buf.End();
buf.End();
return true;
}
// 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 {
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgSupportStyle *style;
};
void * supportStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
int iVal;
try {
switch (tok) {
case TRPG_SUPPORT_STYLE_BASIC:
buf.Get(iVal);
style->SetType(trpgSupportStyle::SupportType(iVal));
buf.Get(iVal);
style->SetMaterial(iVal);
break;
default:
break;
}
}
catch (...) {
return NULL;
}
return style;
}
// Read from a buffer
bool trpgSupportStyle::Read(trpgReadBuffer &buf)
{
Reset();
trpgr_Parser parse;
supportStyleCB supportStyleCb;
supportStyleCb.style = this;
parse.AddCallback(TRPG_SUPPORT_STYLE_BASIC,&supportStyleCb,false);
parse.Parse(buf);
return isValid();
}
bool trpgSupportStyle::isValid(void) const
{
return true;
}
bool trpgSupportStyle::operator == (const trpgSupportStyle& in) const
{
if (type != in.type || matId != in.matId)
return false;
return true;
}
// ******************* Support Style Table implementation
trpgSupportStyleTable::trpgSupportStyleTable()
{
Reset();
}
trpgSupportStyleTable::~trpgSupportStyleTable()
{
}
void trpgSupportStyleTable::Reset()
{
styles.resize(0);
}
bool trpgSupportStyleTable::isValid() const
{
for (int i=0;i<styles.size();i++)
if (!styles[i].isValid())
return false;
return true;
}
int trpgSupportStyleTable::AddStyle(const trpgSupportStyle &style)
{
styles.push_back(style);
return styles.size() -1;
}
int trpgSupportStyleTable::FindAddStyle(const trpgSupportStyle &style)
{
for (int i=0;i<styles.size();i++)
if (styles[i] == style)
return i;
return AddStyle(style);
}
int trpgSupportStyleTable::GetNumStyle() const
{
return styles.size();
}
const trpgSupportStyle *trpgSupportStyleTable::GetStyleRef(int id) const
{
if (id < 0 || id >= styles.size())
return NULL;
return &styles[id];
}
bool trpgSupportStyleTable::Write(trpgWriteBuffer &buf)
{
int i;
if (!isValid())
return false;
buf.Begin(TRPG_SUPPORT_STYLE_TABLE);
// Number of styles
int numStyle = styles.size();
buf.Add((int32)numStyle);
// Write the styles
for (i=0;i<styles.size();i++)
styles[i].Write(buf);
buf.End();
return true;
}
bool trpgSupportStyleTable::Read(trpgReadBuffer &buf)
{
trpgSupportStyle style;
trpgToken styleTok;
int32 len;
bool status;
int numStyle;
int i;
Reset();
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_SUPPORT_STYLE) throw 1;
buf.PushLimit(len);
style.Reset();
status = style.Read(buf);
buf.PopLimit();
if (!status) throw 1;
styles[i] = style;
}
}
catch (...) {
return false;
}
return isValid();
}
// *************** Label ppoperty implementation
trpgLabelProperty::trpgLabelProperty(void)
{
Reset();
}
trpgLabelProperty::~trpgLabelProperty(void)
{
}
void trpgLabelProperty::Reset(void)
{
fontId = -1;
supportId = -1;
type = VertBillboard;
}
void trpgLabelProperty::SetType(LabelType inType)
{
type = inType;
}
trpgLabelProperty::LabelType trpgLabelProperty::GetType() const
{
return type;
}
void trpgLabelProperty::SetFontStyle(int id)
{
fontId = id;
}
int trpgLabelProperty::GetFontStyle() const
{
return fontId;
}
void trpgLabelProperty::SetSupport(int id)
{
supportId = id;
}
int trpgLabelProperty::GetSupport(void) const
{
return supportId;
}
// Write method
bool trpgLabelProperty::Write(trpgWriteBuffer &buf)
{
buf.Begin(TRPG_LABEL_PROPERTY);
buf.Begin(TRPG_LABEL_PROPERTY_BASIC);
buf.Add(fontId);
buf.Add(supportId);
buf.Add(type);
buf.End();
buf.End();
return true;
}
// 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 {
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgLabelProperty *property;
};
void * labelPropertyCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
int iVal;
try {
int ival;
switch (tok) {
case TRPG_LABEL_PROPERTY_BASIC:
buf.Get(iVal);
property->SetFontStyle(iVal);
buf.Get(iVal);
property->SetSupport(iVal);
buf.Get(ival);
property->SetType(trpgLabelProperty::LabelType(ival));
break;
default:
break;
}
}
catch (...) {
return NULL;
}
return property;
}
// Read from a buffer
bool trpgLabelProperty::Read(trpgReadBuffer &buf)
{
Reset();
trpgr_Parser parse;
labelPropertyCB labelPropertyCb;
labelPropertyCb.property = this;
parse.AddCallback(TRPG_LABEL_PROPERTY_BASIC,&labelPropertyCb,false);
parse.Parse(buf);
return isValid();
}
bool trpgLabelProperty::isValid(void) const
{
return supportId != -1 && fontId != -1 && type >=0 && type < MaxLabelType;
}
bool trpgLabelProperty::operator == (const trpgLabelProperty& in)const
{
if (fontId != in.fontId || supportId != in.supportId || type != in.type)
return false;
return true;
}
// ******************* Label Property Table implementation
trpgLabelPropertyTable::trpgLabelPropertyTable()
{
Reset();
}
trpgLabelPropertyTable::~trpgLabelPropertyTable()
{
}
void trpgLabelPropertyTable::Reset()
{
properties.resize(0);
}
bool trpgLabelPropertyTable::isValid() const
{
for (int i=0;i<properties.size();i++)
if (!properties[i].isValid())
return false;
return true;
}
int trpgLabelPropertyTable::AddProperty(const trpgLabelProperty &property)
{
properties.push_back(property);
return properties.size() -1;
}
int trpgLabelPropertyTable::FindAddProperty(const trpgLabelProperty& property)
{
for (int i=0;i<properties.size();i++)
if (properties[i] == property)
return i;
return AddProperty(property);
}
int trpgLabelPropertyTable::GetNumProperty() const
{
return properties.size();
}
const trpgLabelProperty *trpgLabelPropertyTable::GetPropertyRef(int id) const
{
if (id < 0 || id >= properties.size())
return NULL;
return &properties[id];
}
bool trpgLabelPropertyTable::Write(trpgWriteBuffer &buf)
{
int i;
if (!isValid())
return false;
buf.Begin(TRPG_LABEL_PROPERTY_TABLE);
// Number of styles
int numProperty = properties.size();
buf.Add((int32)numProperty);
// Write the properties
for (i=0;i<properties.size();i++)
properties[i].Write(buf);
buf.End();
return true;
}
bool trpgLabelPropertyTable::Read(trpgReadBuffer &buf)
{
trpgLabelProperty property;
trpgToken propertyTok;
int32 len;
bool status;
int numProperty;
int i;
Reset();
try {
buf.Get(numProperty);
if (numProperty < 0)
throw 1;
properties.resize(numProperty);
for (i=0;i<numProperty;i++) {
buf.GetToken(propertyTok,len);
if (propertyTok != TRPG_LABEL_PROPERTY) throw 1;
buf.PushLimit(len);
property.Reset();
status = property.Read(buf);
buf.PopLimit();
if (!status) throw 1;
properties[i] = property;
}
}
catch (...) {
return false;
}
return isValid();
}
// ****************** Label implementation
trpgLabel::trpgLabel()
{
Reset();
}
trpgLabel::~trpgLabel()
{
}
void trpgLabel::Reset()
{
propertyId = -1;
text = "";
alignment = Left;
tabSize = 8;
scale = 1.0;
thickness = 0.0;
desc = "";
url = "";
location.x = 0;
location.y = 0;
location.z = 0;
supports.resize(0);
}
bool trpgLabel::isValid() const
{
if (text.empty() || propertyId == -1)
return false;
return true;
}
void trpgLabel::SetProperty(int id)
{
propertyId = id;
}
int trpgLabel::GetProperty() const
{
return propertyId;
}
void trpgLabel::SetText(const std::string &inText)
{
text = inText;
}
const std::string *trpgLabel::GetText() const
{
return &text;
}
void trpgLabel::SetAlignment(AlignmentType inType)
{
alignment = inType;
}
trpgLabel::AlignmentType trpgLabel::GetAlignment() const
{
return alignment;
}
void trpgLabel::SetTab(int size)
{
tabSize = size;
}
int trpgLabel::GetTab(void) const
{
return tabSize;
}
void trpgLabel::SetScale(float32 inScale)
{
scale = inScale;
}
float32 trpgLabel::GetScale(void) const
{
return scale;
}
void trpgLabel::SetThickness(float32 inThickness)
{
thickness = inThickness;
}
float32 trpgLabel::GetThickness(void) const
{
return thickness;
}
void trpgLabel::SetDesc(const std::string &inText)
{
desc = inText;
}
const std::string *trpgLabel::GetDesc() const
{
return &desc;
}
void trpgLabel::SetURL(const std::string &inText)
{
url = inText;
}
const std::string *trpgLabel::GetURL() const
{
return &url;
}
void trpgLabel::SetLocation(const trpg3dPoint &pt)
{
location = pt;
}
const trpg3dPoint& trpgLabel::GetLocation() const
{
return location;
}
void trpgLabel::AddSupport(const trpg3dPoint &pt)
{
supports.push_back(pt);
}
const std::vector<trpg3dPoint> *trpgLabel::GetSupports() const
{
return &supports;
}
bool trpgLabel::Write(trpgWriteBuffer &buf)
{
int i;
buf.Begin(TRPG_LABEL);
buf.Add(propertyId);
buf.Add(text);
buf.Add(alignment);
buf.Add(tabSize);
buf.Add(scale);
buf.Add(thickness);
buf.Add(desc);
buf.Add(url);
buf.Add(location);
buf.Add((int)supports.size());
for (i=0;i<supports.size();i++)
buf.Add(supports[i]);
buf.End();
return true;
}
bool trpgLabel::Read(trpgReadBuffer &buf)
{
int numSupport,i;
trpg3dPoint support;
int iVal;
try {
buf.Get(iVal);
propertyId = iVal;
buf.Get(text);
buf.Get(iVal);
alignment = (AlignmentType)iVal;
buf.Get(tabSize);
buf.Get(scale);
buf.Get(thickness);
buf.Get(desc);
buf.Get(url);
buf.Get(location);
buf.Get(numSupport);
if (numSupport < 0) throw 1;
for (i=0;i<numSupport;i++) {
buf.Get(support);
supports.push_back(support);
}
}
catch (...) {
return false;
}
return isValid();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,23 @@
/* ************************
Copyright Terrain Experts Inc.
Terrain Experts Inc (TERREX) reserves all rights to this source code
unless otherwise specified in writing by the Chief Operating Officer
of TERREX.
unless otherwise specified in writing by the President of TERREX.
This copyright may be updated in the future, in which case that version
supercedes this one.
-------------------
Terrex Experts Inc.
84 West Santa Clara St., Suite 380
San Jose, CA 95113
4400 East Broadway #314
Tucson, AZ 85711
info@terrex.com
Tel: (408) 293-9977
Tel: (520) 323-7990
************************
*/
/* trpage_main.cpp
This file is here to provide a DLL Main.
Note: #ifdef this out on non-windows machines
*/
#if defined(_WIN32) || defined(__CYGWIN__)
This file is here to provide a DLL Main.
Note: #ifdef this out on non-windows machines
*/
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
@@ -26,6 +25,6 @@
#include <stdlib.h>
#include <stdio.h>
#include "trdll.h"
#include <trdll.h>
TXDUMMY_DLL_MAIN

View File

@@ -17,11 +17,11 @@
#include <stdio.h>
#include <string.h>
#include "trpage_sys.h"
#include "trpage_geom.h"
#include "trpage_read.h"
#include "trpage_print.h"
#include "trpage_managers.h"
#include <trpage_sys.h>
#include <trpage_geom.h>
#include <trpage_read.h>
#include <trpage_print.h>
#include <trpage_managers.h>
/* Managed Tile class.
Check the header file for details.
@@ -38,7 +38,7 @@ trpgManagedTile::trpgManagedTile()
void trpgManagedTile::Reset()
{
// Null out the local material data
for (int i=0;i<int(localMatData.size());i++)
for (int i=0;i<localMatData.size();i++)
localMatData[i] = NULL;
groupIDs.resize(0);
@@ -102,7 +102,7 @@ const trpgLocalMaterial *trpgManagedTile::GetLocMaterial(int id) const
const std::vector<trpgLocalMaterial> *matList;
matList = tileHead.GetLocalMaterialList();
if (id <0 || id >= int(matList->size()))
if (id <0 || id >= matList->size())
return NULL;
return &(*matList)[id];
@@ -120,7 +120,7 @@ void *trpgManagedTile::GetLocalData() const
bool trpgManagedTile::SetMatData(int id,void *info)
{
if (id < 0 || id >= int(localMatData.size()))
if (id < 0 || id >= localMatData.size())
return false;
localMatData[id] = info;
@@ -130,7 +130,7 @@ bool trpgManagedTile::SetMatData(int id,void *info)
void *trpgManagedTile::GetMatData(int id) const
{
if (id < 0 || id >= int(localMatData.size()))
if (id < 0 || id >= localMatData.size())
return NULL;
return localMatData[id];
@@ -174,19 +174,19 @@ void trpgPageManager::LodPageInfo::Clean()
{
// Clean up managed tile structures
int i;
for (i=0;i<int(load.size());i++)
for (i=0;i<load.size();i++)
if (load[i])
delete load[i];
load.resize(0);
for (i=0;i<int(unload.size());i++)
for (i=0;i<unload.size();i++)
if (unload[i])
delete unload[i];
unload.resize(0);
for (i=0;i<int(current.size());i++)
for (i=0;i<current.size();i++)
if (current[i])
delete current[i];
current.resize(0);
for (i=0;i<int(freeList.size());i++)
for (i=0;i<freeList.size();i++)
delete freeList[i];
freeList.resize(0);
activeLoad = false;
@@ -329,12 +329,12 @@ bool trpgPageManager::LodPageInfo::Stop()
{
// Empty the load list
int i;
for (i=0;i<int(load.size());i++)
for (i=0;i<load.size();i++)
freeList.push_back(load[i]);
load.resize(0);
// Move the current tiles to the unload list
for (i=0;i<int(current.size());i++)
for (i=0;i<current.size();i++)
if (current[i])
unload.push_back(current[i]);
current.resize(0);
@@ -362,7 +362,7 @@ void trpgPageManager::LodPageInfo::Update()
out of range. Take them off the load list.
*/
int i;
for (i=0;i<int(load.size());i++) {
for (i=0;i<load.size();i++) {
if (load[i] && !isWithin(load[i],sw,ne)) {
freeList.push_back(load[i]);
load[i] = NULL;
@@ -373,7 +373,7 @@ void trpgPageManager::LodPageInfo::Update()
Some of the tiles we were planning on unloading may now
be in view again. Move them back to current.
*/
for (i=0;i<int(unload.size());i++) {
for (i=0;i<unload.size();i++) {
if (unload[i] && isWithin(unload[i],sw,ne)) {
current.push_back(unload[i]);
unload[i] = NULL;
@@ -389,7 +389,7 @@ void trpgPageManager::LodPageInfo::Update()
// Look for tiles to page out
// Move them to the unload list
for (i=0;i<int(current.size());i++) {
for (i=0;i<current.size();i++) {
if (current[i] && !isWithin(current[i],sw,ne)) {
unload.push_back(current[i]);
current[i] = NULL;
@@ -397,7 +397,7 @@ void trpgPageManager::LodPageInfo::Update()
}
// Clean the NULLs out of the current list
int curPos = 0;
for (i=0;i<int(current.size());i++) {
for (i=0;i<current.size();i++) {
if (current[i]) {
current[curPos] = current[i];
curPos++;
@@ -411,8 +411,8 @@ void trpgPageManager::LodPageInfo::Update()
int dx,dy;
dx = ne.x - sw.x+1; dy = ne.y - sw.y+1;
tmpCurrent.resize(dx*dy);
for (i=0;i<int(tmpCurrent.size());i++) tmpCurrent[i] = false;
for (i=0;i<int(current.size());i++) {
for (i=0;i<tmpCurrent.size();i++) tmpCurrent[i] = false;
for (i=0;i<current.size();i++) {
trpgManagedTile *tile = current[i];
if (tile) {
int tileX,tileY,tileLod;
@@ -455,21 +455,21 @@ void trpgPageManager::LodPageInfo::Print(trpgPrintBuffer &buf)
sprintf(line,"Loads: (activeLoad = %s)",(activeLoad ? "yes" : "no")); buf.prnLine(line);
buf.IncreaseIndent();
for (i=0;i<int(load.size());i++)
for (i=0;i<load.size();i++)
if (load[i])
load[i]->Print(buf);
buf.DecreaseIndent();
sprintf(line,"Unloads: (activeUnload = %s)",(activeUnload ? "yes" : "no")); buf.prnLine(line);
buf.IncreaseIndent();
for (i=0;i<int(unload.size());i++)
for (i=0;i<unload.size();i++)
if (unload[i])
unload[i]->Print(buf);
buf.DecreaseIndent();
buf.prnLine("Currently loaded:");
buf.IncreaseIndent();
for (i=0;i<int(current.size());i++)
for (i=0;i<current.size();i++)
if (current[i])
current[i]->Print(buf);
buf.DecreaseIndent();
@@ -538,7 +538,7 @@ bool trpgPageManager::SetLocation(trpg2dPoint &pt)
// Call each terrain LOD and let if figure out if something
// has changed.
bool change = false;
for (int i=0;i<int(pageInfo.size());i++) {
for (int i=0;i<pageInfo.size();i++) {
if (pageInfo[i].SetLocation(pt))
change = true;
}
@@ -555,7 +555,7 @@ trpgManagedTile *trpgPageManager::GetNextLoad()
// Look for anything that needs loaded
// Start with lowest LOD, work up to highest
trpgManagedTile *tile = NULL;
for (int i=0;i<int(pageInfo.size());i++) {
for (int i=0;i<pageInfo.size();i++) {
LodPageInfo &info = pageInfo[i];
if ((tile = info.GetNextLoad()))
break;
@@ -632,7 +632,7 @@ void trpgPageManager::AckUnload()
// Remove this tile's group IDs from the map
const std::vector<int> *groupIDs = lastTile->GetGroupIDs();
int i;
for (i=0;i<int(groupIDs->size());i++) {
for (i=0;i<groupIDs->size();i++) {
ManageGroupMap::iterator p = groupMap.find((*groupIDs)[i]);
if (p != groupMap.end())
groupMap.erase(p);
@@ -648,7 +648,7 @@ bool trpgPageManager::Stop()
{
bool res=false;
int i;
for (i=0;i<int(pageInfo.size());i++)
for (i=0;i<pageInfo.size();i++)
res |= pageInfo[i].Stop();
lastLoad = None;
@@ -663,7 +663,7 @@ void trpgPageManager::Print(trpgPrintBuffer &buf)
buf.prnLine("Terrain LODs:");
int i;
for (i=0;i<int(pageInfo.size());i++) {
for (i=0;i<pageInfo.size();i++) {
sprintf(line,"----Terrain lod %d---",i); buf.prnLine(line);
buf.IncreaseIndent();
pageInfo[i].Print(buf);

File diff suppressed because it is too large Load Diff

View File

@@ -18,199 +18,202 @@
#include <string.h>
/* trpage_mode.cpp
This source file contains the methods trpgModel and trpgModelTable.
You should only modify this code if you want to add data to these classes.
*/
This source file contains the methods trpgModel and trpgModelTable.
You should only modify this code if you want to add data to these classes.
*/
#include "trpage_geom.h"
#include "trpage_read.h"
#include <trpage_geom.h>
#include <trpage_read.h>
/* Write Model class
Represents a model reference.
*/
Represents a model reference.
*/
trpgModel::trpgModel()
{
name = NULL;
type = External;
useCount = 0;
name = NULL;
type = External;
useCount = 0;
}
trpgModel::trpgModel(const trpgModel &in):trpgReadWriteable()
trpgModel::trpgModel(const trpgModel &in)
{
name = NULL;
type = External;
*this = in;
name = NULL;
type = External;
*this = in;
}
// Reset function
void trpgModel::Reset()
{
if (name)
delete [] name;
name = NULL;
useCount = 0;
if (name)
delete [] name;
name = NULL;
useCount = 0;
}
trpgModel::~trpgModel()
{
Reset();
Reset();
}
// Set functions
void trpgModel::SetName(const char *nm)
{
if (name)
delete [] name;
if (name)
delete [] name;
name = new char[(nm ? strlen(nm) : 0)+1];
strcpy(name,nm);
name = new char[(nm ? strlen(nm) : 0)+1];
strcpy(name,nm);
type = External;
type = External;
}
void trpgModel::SetReference(trpgDiskRef pos)
{
if (name)
delete [] name;
if (name)
delete [] name;
diskRef = pos;
diskRef = pos;
type = Local;
type = Local;
}
void trpgModel::SetNumTiles(int num)
{
useCount = num;
useCount = num;
}
void trpgModel::AddTile()
{
useCount++;
useCount++;
}
// Validity check
bool trpgModel::isValid() const
{
if (type == External && !name)
return false;
if (type == External && !name)
{
strcpy(errMess, "Model is external with no name");
return false;
}
return true;
return true;
}
// Copy from one to another
trpgModel& trpgModel::operator = (const trpgModel &in)
{
if (name) {
delete [] name;
name = NULL;
}
if (name) {
delete [] name;
name = NULL;
}
type = in.type;
if (in.name)
SetName(in.name);
diskRef = in.diskRef;
useCount = in.useCount;
type = in.type;
if (in.name)
SetName(in.name);
diskRef = in.diskRef;
useCount = in.useCount;
return *this;
return *this;
}
// Compare two models
int trpgModel::operator == (const trpgModel &in) const
{
if (type != in.type)
return 0;
if (type != in.type)
return 0;
switch (type) {
case Local:
if (diskRef == in.diskRef)
return 1;
else
return 0;
break;
case External:
if (!name && !in.name)
return 1;
if (!name || !in.name)
return 0;
if (strcmp(name,in.name))
return 0;
break;
}
switch (type) {
case Local:
if (diskRef == in.diskRef)
return 1;
else
return 0;
break;
case External:
if (!name && !in.name)
return 1;
if (!name || !in.name)
return 0;
if (strcmp(name,in.name))
return 0;
break;
}
return 1;
return 1;
}
// Write a model reference out
bool trpgModel::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGMODELREF);
buf.Add(type);
if (name)
buf.Add(name);
else
buf.Add(diskRef);
buf.Add(useCount);
buf.Begin(TRPGMODELREF);
buf.Add(type);
if (name)
buf.Add(name);
else
buf.Add(diskRef);
buf.Add(useCount);
buf.End();
buf.End();
return true;
return true;
}
/* *******************
Model Read Methods
*******************
*/
/* *******************
Model Read Methods
*******************
*/
// Get methods
bool trpgModel::GetType(int &t)
{
if (!isValid()) return false;
t = type;
return true;
if (!isValid()) return false;
t = type;
return true;
}
bool trpgModel::GetName(char *str,int strLen) const
{
if (!isValid() || type != External) return false;
int len = (name ? strlen(name) : 0);
strncpy(str,name,MIN(len,strLen)+1);
return true;
if (!isValid() || type != External) return false;
int len = (name ? strlen(name) : 0);
strncpy(str,name,MIN(len,strLen)+1);
return true;
}
bool trpgModel::GetNumTiles(int &ret) const
{
if (!isValid()) return false;
if (!isValid()) return false;
ret = useCount;
return true;
ret = useCount;
return true;
}
bool trpgModel::GetReference(trpgDiskRef &ref) const
{
if (!isValid() || type != Local) return false;
ref = diskRef;
return true;
if (!isValid() || type != Local) return false;
ref = diskRef;
return true;
}
bool trpgModel::Read(trpgReadBuffer &buf)
{
char tmpName[1024];
char tmpName[1024];
try {
buf.Get(type);
if (type == Local)
buf.Get(diskRef);
else {
buf.Get(tmpName,1023);
SetName(tmpName);
}
buf.Get(useCount);
}
catch(...) {
return false;
}
try {
buf.Get(type);
if (type == Local)
buf.Get(diskRef);
else {
buf.Get(tmpName,1023);
SetName(tmpName);
}
buf.Get(useCount);
}
catch(...) {
return false;
}
return isValid();
return isValid();
}
/* Write Model Reference table
Groups of models for the entire file.
*/
Groups of models for the entire file.
*/
// Constructor
trpgModelTable::trpgModelTable()
@@ -223,32 +226,32 @@ trpgModelTable::~trpgModelTable()
// Reset function
void trpgModelTable::Reset()
{
models.resize(0);
models.resize(0);
}
// Set functions
void trpgModelTable::SetNumModels(int no)
{
models.resize(no);
models.resize(no);
}
void trpgModelTable::SetModel(int id,const trpgModel &mod)
{
if (id < 0 || static_cast<unsigned int>(id) >= models.size())
return;
if (id < 0 || (unsigned int)id >= models.size())
return;
models[id] = mod;
models[id] = mod;
}
int trpgModelTable::AddModel(const trpgModel &mod)
{
models.push_back(mod);
models.push_back(mod);
return models.size()-1;
return models.size()-1;
}
int trpgModelTable::FindAddModel(const trpgModel &mod)
{
for (unsigned int i=0;i<models.size();i++)
if (models[i] == mod)
return i;
if (models[i] == mod)
return i;
return AddModel(mod);
}
@@ -256,77 +259,85 @@ int trpgModelTable::FindAddModel(const trpgModel &mod)
// Validity check
bool trpgModelTable::isValid() const
{
for (unsigned int i=0;i<models.size();i++)
if (!models[i].isValid())
return false;
for (unsigned int i=0;i<models.size();i++)
{
if (!models[i].isValid())
{
if(models[i].getErrMess())
strcpy(errMess, models[i].getErrMess());
return false;
}
}
return true;
return true;
}
// Write out the model table
bool trpgModelTable::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)models.size());
for (unsigned int i=0;i<models.size();i++)
models[i].Write(buf);
buf.End();
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)models.size());
for (unsigned int i=0;i<models.size();i++)
models[i].Write(buf);
buf.End();
return true;
return true;
}
/* ***************
Model Table Read methods
***************
*/
/* ***************
Model Table Read methods
***************
*/
// Get methods
bool trpgModelTable::GetNumModels(int &nm) const
{
if (!isValid()) return false;
nm = models.size();
return true;
if (!isValid()) return false;
nm = models.size();
return true;
}
bool trpgModelTable::GetModel(int id,trpgModel &model) const
{
if (!isValid() || id < 0 || static_cast<unsigned int>(id) >= models.size())
return false;
model = models[id];
return true;
if (!isValid() || id < 0 || id >= models.size())
return false;
model = models[id];
return true;
}
trpgModel *trpgModelTable::GetModelRef(int id)
{
if (id < 0 || static_cast<unsigned int>(id) >= models.size())
return NULL;
return &models[id];
if (id < 0 || id >= models.size())
return NULL;
return &models[id];
}
bool trpgModelTable::Read(trpgReadBuffer &buf)
{
int32 numModel;
trpgModel model;
trpgToken tok;
int32 len;
bool status;
int32 numModel;
trpgModel model;
trpgToken tok;
int32 len;
bool status;
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
buf.GetToken(tok,len);
if (tok != TRPGMODELREF) throw 1;
buf.PushLimit(len);
status = model.Read(buf);
buf.PopLimit();
if (!status) throw 1;
models.push_back(model);
}
}
catch (...) {
return false;
}
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
buf.GetToken(tok,len);
if (tok != TRPGMODELREF) throw 1;
buf.PushLimit(len);
status = model.Read(buf);
buf.PopLimit();
if (!status) throw 1;
models.push_back(model);
}
}
catch (...) {
return false;
}
return isValid();
return isValid();
}

File diff suppressed because it is too large Load Diff

View File

@@ -17,62 +17,62 @@
#include <stdio.h>
/* trpage_parse.cpp
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
trpgr_Parser is the main class. It parses the basic structure of paging archive
data out of Read Buffers. You should not need to change this.
If you want to parse data out of a different structure instead, look at
subclassing trpgReadBuffer and replacing its virtual methods. That's what
trpgMemReadBuffer is doing.
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
trpgr_Parser is the main class. It parses the basic structure of paging archive
data out of Read Buffers. You should not need to change this.
If you want to parse data out of a different structure instead, look at
subclassing trpgReadBuffer and replacing its virtual methods. That's what
trpgMemReadBuffer is doing.
This file also contains the implementation of trpgSceneParser().
That class implements a set of callbacks for handling the Pushes and Pops
in an archive. You fill in the Start/EndChildren callbacks and register
for the rest of the tokens that you want.
*/
That class implements a set of callbacks for handling the Pushes and Pops
in an archive. You fill in the Start/EndChildren callbacks and register
for the rest of the tokens that you want.
*/
#include "trpage_read.h"
#include <trpage_read.h>
/* ***************************
Paging token callback structure
Paging token callback structure
***************************
*/
trpgr_Token::trpgr_Token()
{
cb = NULL;
destroy = true;
cb = NULL;
destroy = true;
}
trpgr_Token::~trpgr_Token()
{
}
trpgr_Token::trpgr_Token(int in_tok,trpgr_Callback *in_cb,bool in_dest)
{
init(in_tok,in_cb,in_dest);
init(in_tok,in_cb,in_dest);
}
void trpgr_Token::init(int in_tok,trpgr_Callback *in_cb,bool in_dest)
{
Token = in_tok;
cb = in_cb;
destroy = in_dest;
Token = in_tok;
cb = in_cb;
destroy = in_dest;
}
// Destruct
// Destroy our callback if appropriate
void trpgr_Token::Destruct()
{
if (cb && destroy)
delete cb;
cb = NULL;
destroy = true;
if (cb && destroy)
delete cb;
cb = NULL;
destroy = true;
}
/* ***************************
Paging parser implementation.
Paging parser implementation.
***************************
*/
// Constructor
trpgr_Parser::trpgr_Parser()
{
lastObject = NULL;
lastObject = NULL;
}
trpgr_Parser::~trpgr_Parser()
{
@@ -81,63 +81,63 @@ trpgr_Parser::~trpgr_Parser()
// Validity check
bool trpgr_Parser::isValid() const
{
return true;
return true;
}
// Add Callback
// Make the given callback object current for the given token.
void trpgr_Parser::AddCallback(trpgToken tok,trpgr_Callback *cb,bool in_dest)
{
RemoveCallback(tok);
RemoveCallback(tok);
tokenMap[tok] = trpgr_Token(tok,cb,in_dest);
tokenMap[tok] = trpgr_Token(tok,cb,in_dest);
}
// Callback used as writeable wrapper
class WriteWrapper : public trpgr_Callback {
public:
WriteWrapper(trpgReadWriteable *in_wr) { wr = in_wr; };
void *Parse(trpgToken,trpgReadBuffer &buf) {
if (wr->Read(buf))
return wr;
else
return NULL;
}
WriteWrapper(trpgReadWriteable *in_wr) { wr = in_wr; };
void *Parse(trpgToken,trpgReadBuffer &buf) {
if (wr->Read(buf))
return wr;
else
return NULL;
}
protected:
trpgReadWriteable *wr;
trpgReadWriteable *wr;
};
// Add Callback (writeable)
// Build a wrapper around a trpgWriteable so it can read itself
void trpgr_Parser::AddCallback(trpgToken tok,trpgReadWriteable *wr)
{
AddCallback(tok,new WriteWrapper(wr),true);
AddCallback(tok,new WriteWrapper(wr),true);
}
// Remove Callback
void trpgr_Parser::RemoveCallback(trpgToken tok)
{
tokenMap.erase(tok);
tokenMap.erase(tok);
}
// Set Default Callback
// This gets called for all tokens we don't understand
void trpgr_Parser::SetDefaultCallback(trpgr_Callback *cb,bool in_dest)
{
defCb.Destruct();
defCb.init(-1,cb,in_dest);
defCb.Destruct();
defCb.init(-1,cb,in_dest);
}
/* Token Is Valid
Checks if something *could be* a token.
Doesn't necessarily mean that it is.
*/
Checks if something *could be* a token.
Doesn't necessarily mean that it is.
*/
bool trpgr_Parser::TokenIsValid(trpgToken tok)
{
if (tok < 0)
return false;
if (tok < 0)
return false;
return true;
return true;
}
/* Parse Buffer
@@ -147,97 +147,97 @@ bool trpgr_Parser::TokenIsValid(trpgToken tok)
*/
bool trpgr_Parser::Parse(trpgReadBuffer &buf)
{
bool ret = true;
bool ret = true;
try {
while (!buf.isEmpty()) {
/* We're expecting the following
Token (int32)
Length (int32)
Data (variable)
*/
trpgToken tok;
int32 len;
if (!buf.Get(tok)) throw 1;
// Push and Pop are special - no data
if (tok != TRPG_PUSH && tok != TRPG_POP) {
if (!buf.Get(len)) throw 1;
if (!TokenIsValid(tok)) throw 1;
if (len < 0) throw 1;
// Limit what we're reading to the length of this
buf.PushLimit(len);
}
try {
while (!buf.isEmpty()) {
/* We're expecting the following
Token (int32)
Length (int32)
Data (variable)
*/
trpgToken tok;
int32 len;
if (!buf.Get(tok)) throw 1;
// Push and Pop are special - no data
if (tok != TRPG_PUSH && tok != TRPG_POP) {
if (!buf.Get(len)) throw 1;
if (!TokenIsValid(tok)) throw 1;
if (len < 0) throw 1;
// Limit what we're reading to the length of this
buf.PushLimit(len);
}
// Call our token handler for this one
try {
const trpgr_Token *tcb = NULL;
tok_map::const_iterator p = tokenMap.find(tok);
if (p != tokenMap.end())
tcb = &(*p).second;
if (!tcb)
// No such token, call the default
tcb = &defCb;
// Call our token handler for this one
try {
const trpgr_Token *tcb = NULL;
tok_map::const_iterator p = tokenMap.find(tok);
if (p != tokenMap.end())
tcb = &(*p).second;
if (!tcb)
// No such token, call the default
tcb = &defCb;
// Run the callback
if (tcb->cb) {
void *ret = tcb->cb->Parse(tok,buf);
// Note: Do something with the return value
lastObject = ret;
}
}
catch (...) {
// Don't want to screw up the limit stack
}
// No limit to worry about with push and pop
if (tok != TRPG_PUSH && tok != TRPG_POP) {
buf.SkipToLimit();
buf.PopLimit();
}
}
}
catch (...) {
// Failed to parse.
ret = false;
}
// Run the callback
if (tcb->cb) {
void *ret = tcb->cb->Parse(tok,buf);
// Note: Do something with the return value
lastObject = ret;
}
}
catch (...) {
// Don't want to screw up the limit stack
}
// No limit to worry about with push and pop
if (tok != TRPG_PUSH && tok != TRPG_POP) {
buf.SkipToLimit();
buf.PopLimit();
}
}
}
catch (...) {
// Failed to parse.
ret = false;
}
return ret;
return ret;
}
/* ****************
Scene Parser
****************
*/
/* ****************
Scene Parser
****************
*/
// Helper - callback for Push
class trpgSceneHelperPush : public trpgr_Callback {
public:
trpgSceneHelperPush(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken ,trpgReadBuffer &) {
// Call the start children callback
parse->StartChildren(parse->lastObject);
parse->parents.push_back(parse->lastObject);
return (void *)1;
}
trpgSceneHelperPush(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
// Call the start children callback
parse->StartChildren(parse->lastObject);
parse->parents.push_back(parse->lastObject);
return (void *)1;
}
protected:
trpgSceneParser *parse;
trpgSceneParser *parse;
};
// Helper - callback for Pop
class trpgSceneHelperPop : public trpgr_Callback {
public:
trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken ,trpgReadBuffer &) {
// Make sure we don't have an extra pop
if (parse->parents.size() == 0)
// Note: let someone know about the extra pop
return NULL;
// Call the end children callback
int len = parse->parents.size();
parse->EndChildren(parse->parents[len-1]);
parse->parents.resize(len-1);
return (void *)1;
}
trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
// Make sure we don't have an extra pop
if (parse->parents.size() == 0)
// Note: let someone know about the extra pop
return NULL;
// Call the end children callback
int len = parse->parents.size();
parse->EndChildren(parse->parents[len-1]);
parse->parents.resize(len-1);
return (void *)1;
}
protected:
trpgSceneParser *parse;
trpgSceneParser *parse;
};
// Helper - default callback
@@ -245,23 +245,23 @@ protected:
// Note: Need to use this fact above
class trpgSceneHelperDefault : public trpgr_Callback {
public:
trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken ,trpgReadBuffer &) {
// Absorb it quietly
return (void *)1;
}
trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken tok,trpgReadBuffer &buf) {
// Absorb it quietly
return (void *)1;
}
protected:
trpgSceneParser *parse;
trpgSceneParser *parse;
};
trpgSceneParser::trpgSceneParser()
{
// Register for Push and Pop
AddCallback(TRPG_PUSH,new trpgSceneHelperPush(this));
AddCallback(TRPG_POP,new trpgSceneHelperPop(this));
// Register for Push and Pop
AddCallback(TRPG_PUSH,new trpgSceneHelperPush(this));
AddCallback(TRPG_POP,new trpgSceneHelperPop(this));
// Register for default
SetDefaultCallback(new trpgSceneHelperDefault(this));
// Register for default
SetDefaultCallback(new trpgSceneHelperDefault(this));
}
trpgSceneParser::~trpgSceneParser()
{

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -16,83 +16,90 @@
#ifndef trpage_print_h_
#define trpage_print_h_
#include "trpage_read.h"
#include <trpage_read.h>
/* Print Buffer for TerraPage. Subclasses of this object
are used to print out to stdout or disk (or whatever).
You won't create one of these directly, instead you'll create
something which inherits from it.
are used to print out to stdout or disk (or whatever).
You won't create one of these directly, instead you'll create
something which inherits from it.
*/
TX_EXDECL class TX_CLDECL trpgPrintBuffer {
public:
trpgPrintBuffer(void);
virtual ~trpgPrintBuffer(void) { };
trpgPrintBuffer(void);
virtual ~trpgPrintBuffer(void) { };
// Check if print buffer is valid
virtual bool isValid(void) { return true; }
// Check if print buffer is valid
virtual bool isValid(void) { return true; }
// The main print function. Subclasses must fill this in.
virtual bool prnLine(char *str=NULL)=0;
// The main print function. Subclasses must fill this in.
virtual bool prnLine(char *str=NULL)=0;
// This increases the current indentation by the amount given (defaults to one)
virtual void IncreaseIndent(int amount=1);
// Decreases the current indentation by the amount given (defaults to one)
virtual void DecreaseIndent(int amount=1);
// This increases the current indentation by the amount given (defaults to one)
virtual void IncreaseIndent(int amount=1);
// Decreases the current indentation by the amount given (defaults to one)
virtual void DecreaseIndent(int amount=1);
protected:
void updateIndent(void);
int curIndent;
char indentStr[200];
void updateIndent(void);
int curIndent;
char indentStr[200];
};
/* File print buffer for TerraPage. The file print buffer writes
debugging output to a file.
debugging output to a file.
*/
TX_EXDECL class TX_CLDECL trpgFilePrintBuffer : public trpgPrintBuffer {
public:
// This class can be constructed with either a FILE pointer or a file name
trpgFilePrintBuffer(FILE *);
trpgFilePrintBuffer(char *);
~trpgFilePrintBuffer(void);
// This class can be constructed with either a FILE pointer or a file name
trpgFilePrintBuffer(FILE *);
trpgFilePrintBuffer(char *);
~trpgFilePrintBuffer(void);
// Check if file print buffer is valid (i.e. if file was opened)
bool isValid(void) { return valid; };
// Check if file print buffer is valid (i.e. if file was opened)
bool isValid(void) { return valid; };
// For a file printer buffer, this writes a string out to a file
bool prnLine(char *str = NULL);
// For a file printer buffer, this writes a string out to a file
bool prnLine(char *str = NULL);
protected:
bool valid;
bool isMine;
FILE *fp;
bool valid;
bool isMine;
FILE *fp;
};
/* The Print Graph Parser is a scene graph parser that
prints out the scene graph as it goes. It's simpler
than the scene example in trpage_scene.cpp since it
isn't trying to build up a working scene graph.
prints out the scene graph as it goes. It's simpler
than the scene example in trpage_scene.cpp since it
isn't trying to build up a working scene graph.
*/
TX_EXDECL class TX_CLDECL trpgPrintGraphParser : public trpgSceneParser {
public:
trpgPrintGraphParser(trpgPrintBuffer *);
virtual ~trpgPrintGraphParser(void) { };
trpgPrintGraphParser(trpgr_Archive *,trpgrImageHelper *,trpgPrintBuffer *);
virtual ~trpgPrintGraphParser(void) { };
/* 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 {
public:
ReadHelper(trpgPrintBuffer *inBuf) {pBuf = inBuf;};
void *Parse(trpgToken,trpgReadBuffer &buf);
protected:
trpgPrintBuffer *pBuf;
};
/* 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 {
public:
ReadHelper(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf) {pBuf = inBuf; parse = inPG;};
void *Parse(trpgToken,trpgReadBuffer &buf);
protected:
trpgPrintBuffer *pBuf;
trpgPrintGraphParser *parse;
};
// Fetch the archive associated with this print
trpgr_Archive *GetArchive() {return archive; };
trpgrImageHelper *GetImageHelp() {return imageHelp; };
protected:
bool StartChildren(void *);
bool EndChildren(void *);
bool StartChildren(void *);
bool EndChildren(void *);
trpgPrintBuffer *printBuf;
trpgPrintBuffer *printBuf;
trpgr_Archive *archive;
trpgrImageHelper *imageHelp;
};
// Print utitility for while archive

View File

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

View File

@@ -18,283 +18,299 @@
#include <string.h>
/* trpage_rarchive.cpp
This source file implements the methods for a trpgr_Archive.
The Read Archive is used to read a paging archive from disk.
*/
This source file implements the methods for a trpgr_Archive.
The Read Archive is used to read a paging archive from disk.
*/
#include "trpage_read.h"
#include "trpage_compat.h"
#include <trpage_read.h>
#include <trpage_compat.h>
// Constructor
trpgr_Archive::trpgr_Archive()
{
fp = NULL;
ness = LittleEndian;
strcpy(dir,".");
tileCache = NULL;
fp = NULL;
ness = LittleEndian;
strcpy(dir,".");
tileCache = NULL;
}
// Destructor
trpgr_Archive::~trpgr_Archive()
{
if (fp)
fclose(fp);
fp = NULL;
if (tileCache)
delete tileCache;
if (fp)
fclose(fp);
fp = NULL;
if (tileCache)
delete tileCache;
}
// Set the directory where the archive is
void trpgr_Archive::SetDirectory(const char *in_dir)
{
strncpy(dir,in_dir,1024);
strncpy(dir,in_dir,1024);
}
// Open File
// Open the given file and look for the file specific info
bool trpgr_Archive::OpenFile(const char *name)
{
char file[1024];
sprintf(file,"%s" PATHSEPARATOR "%s",dir,name);
char file[1024];
sprintf(file,"%s" PATHSEPERATOR "%s",dir,name);
CloseFile();
CloseFile();
if (!(fp = fopen(file,"rb")))
return false;
if (!(fp = fopen(file,"rb")))
return false;
// Look for a magic # and endianness
int32 magic;
if (fread(&magic,sizeof(int32),1,fp) != 1)
return false;
// Look for a magic # and endianness
int32 magic;
if (fread(&magic,sizeof(int32),1,fp) != 1)
return false;
headerRead = false;
headerRead = false;
// Figure out the endianness from the magic number
trpgEndian cpuNess = trpg_cpu_byte_order();
if (magic == TRPG_MAGIC) {
ness = cpuNess;
return true;
}
if (trpg_byteswap_int(magic) == TRPG_MAGIC) {
if (cpuNess == LittleEndian)
ness = BigEndian;
else
ness = LittleEndian;
return true;
}
if (magic != TRPG_MAGIC)
return false;
// Figure out the endianness from the magic number
trpgEndian cpuNess = trpg_cpu_byte_order();
if (magic == TRPG_MAGIC) {
ness = cpuNess;
return true;
}
if (trpg_byteswap_int(magic) == TRPG_MAGIC) {
if (cpuNess == LittleEndian)
ness = BigEndian;
else
ness = LittleEndian;
return true;
}
if (magic != TRPG_MAGIC)
return false;
// Not one of our files
return false;
// Not one of our files
return false;
}
// Close File
// Close the currently open file
void trpgr_Archive::CloseFile()
{
if (fp)
fclose(fp);
fp = NULL;
if (tileCache)
delete tileCache;
tileCache = NULL;
if (fp)
fclose(fp);
fp = NULL;
if (tileCache)
delete tileCache;
tileCache = NULL;
}
// Read Header
// Run through the rest of the header information
bool trpgr_Archive::ReadHeader()
{
if (!fp || headerRead)
return false;
int ret;
headerRead = true;
if (!fp || headerRead)
return false;
// 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 (ness != cpuNess)
headerSize = trpg_byteswap_int(headerSize);
int headLen = headerSize;
if (headLen < 0) return false;
headerRead = true;
// Read in the header whole
trpgMemReadBuffer buf(ness);
buf.SetLength(headLen);
char *data = buf.GetDataPtr();
if (fread(data,1,headLen,fp) != static_cast<unsigned int>(headLen)) return false;
// 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 (ness != cpuNess)
headerSize = trpg_byteswap_int(headerSize);
int headLen = headerSize;
if (headLen < 0) return false;
// Set up a parser
// Catch the tables we need for the archive
trpgMatTable1_0 oldMatTable;
trpgTexTable1_0 oldTexTable;
trpgr_Parser parser;
parser.AddCallback(TRPGHEADER,&header);
parser.AddCallback(TRPGMATTABLE,&materialTable); // Went back to oldest style for 2.0
parser.AddCallback(TRPGMATTABLE2,&oldMatTable); // Added 11-14-98 (1.0 material table)
parser.AddCallback(TRPGTEXTABLE,&oldTexTable);
parser.AddCallback(TRPGTEXTABLE2,&texTable); // Added for 2.0
parser.AddCallback(TRPGMODELTABLE,&modelTable);
parser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0
parser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0
// 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;
// Don't read the tile table for v1.0 archives
// It's only really used for 2.0 archives
parser.AddCallback(TRPGTILETABLE2,&tileTable);
// Set up a parser
// Catch the tables we need for the archive
trpgMatTable1_0 oldMatTable;
trpgTexTable1_0 oldTexTable;
trpgr_Parser parser;
parser.AddCallback(TRPGHEADER,&header);
parser.AddCallback(TRPGMATTABLE,&materialTable); // Went back to oldest style for 2.0
parser.AddCallback(TRPGMATTABLE2,&oldMatTable); // Added 11-14-98 (1.0 material table)
parser.AddCallback(TRPGTEXTABLE,&oldTexTable);
parser.AddCallback(TRPGTEXTABLE2,&texTable); // Added for 2.0
parser.AddCallback(TRPGMODELTABLE,&modelTable);
parser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0
parser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0
parser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1
parser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable);
parser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable);
// Don't read the tile table for v1.0 archives
// It's only really used for 2.0 archives
parser.AddCallback(TRPGTILETABLE2,&tileTable);
// Parse the buffer
if (!parser.Parse(buf))
return false;
// Parse the buffer
if (!parser.Parse(buf))
return false;
// 1.0 Compatibility
// If we see an older style material table, convert it to the new style
// This isn't terribly memory efficient, but it does work
if (oldMatTable.isValid())
materialTable = oldMatTable;
if (oldTexTable.isValid())
texTable = oldTexTable;
// 1.0 Compatibility
// If we see an older style material table, convert it to the new style
// This isn't terribly memory efficient, but it does work
if (oldMatTable.isValid())
materialTable = oldMatTable;
if (oldTexTable.isValid())
texTable = oldTexTable;
// Set up a tile cache, if needed
trpgTileTable::TileMode tileMode;
tileTable.GetMode(tileMode);
if (tileMode == trpgTileTable::Local) {
if (tileCache) delete tileCache;
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPARATOR "tileFile",dir);
tileCache = new trpgrAppFileCache(fullBase,"tpf");
}
// Set up a tile cache, if needed
trpgTileTable::TileMode tileMode;
tileTable.GetMode(tileMode);
if (tileMode == trpgTileTable::Local) {
if (tileCache) delete tileCache;
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPERATOR "tileFile",dir);
tileCache = new trpgrAppFileCache(fullBase,"tpf");
}
valid = true;
valid = true;
return true;
return true;
}
// Read Tile
// Read a tile into a read buffer
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 >= static_cast<unsigned int>(numLods)) return false;
trpg2iPoint lodSize;
header.GetLodSize(lod,lodSize);
if (x >= static_cast<unsigned int>(lodSize.x) || y >= static_cast<unsigned int>(lodSize.y)) return false;
// Reality check the address
int32 numLods;
header.GetNumLods(numLods);
if (lod >= numLods) return false;
trpg2iPoint lodSize;
header.GetLodSize(lod,lodSize);
if (x >= lodSize.x || y >= lodSize.y) return false;
trpgTileTable::TileMode tileMode;
tileTable.GetMode(tileMode);
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" PATHSEPARATOR "tile_%d_%d_%d.tpt",dir,x,y,lod);
if (tileMode == trpgTileTable::External) {
// Figure out the file name
// Note: This assumes External tiles
char filename[1024];
sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod);
// Open the file and read the contents
FILE *fp=NULL;
try {
if (!(fp = fopen(filename,"rb"))) throw 1;
// Find the file end
if (fseek(fp,0,SEEK_END)) throw 1;
// Note: This means tile is capped at 2 gigs
long pos = ftell(fp);
if (fseek(fp,0,SEEK_SET)) throw 1;
// Now we know the size. Read the whole file
buf.SetLength(pos);
char *data = buf.GetDataPtr();
if (fread(data,pos,1,fp) != 1) throw 1;
fclose(fp); fp = NULL;
}
catch (...) {
if (fp)
fclose(fp);
return false;
}
} 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;
// Open the file and read the contents
FILE *fp=NULL;
try {
if (!(fp = fopen(filename,"rb"))) throw 1;
// Find the file end
if (fseek(fp,0,SEEK_END)) throw 1;
// Note: This means tile is capped at 2 gigs
long pos = ftell(fp);
if (fseek(fp,0,SEEK_SET)) throw 1;
// Now we know the size. Read the whole file
buf.SetLength(pos);
char *data = buf.GetDataPtr();
if (fread(data,pos,1,fp) != 1) throw 1;
fclose(fp); fp = NULL;
}
catch (...) {
if (fp)
fclose(fp);
return false;
}
} 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;
// Fetch the appendable file from the cache
trpgrAppFile *tf = tileCache->GetFile(ness,addr.file);
if (!tf) return false;
// Fetch the appendable file from the cache
trpgrAppFile *tf = tileCache->GetFile(ness,addr.file);
if (!tf) return false;
// Fetch the tile
if (!tf->Read(&buf,addr.offset))
return false;
}
// Fetch the tile
if (!tf->Read(&buf,addr.offset))
return false;
}
return true;
return true;
}
// Get methods
const trpgHeader *trpgr_Archive::GetHeader() const
{
return &header;
return &header;
}
const trpgMatTable *trpgr_Archive::GetMaterialTable() const
{
return &materialTable;
return &materialTable;
}
const trpgTexTable *trpgr_Archive::GetTexTable() const
{
return &texTable;
return &texTable;
}
const trpgModelTable *trpgr_Archive::GetModelTable() const
{
return &modelTable;
return &modelTable;
}
const trpgTileTable *trpgr_Archive::GetTileTable() const
{
return &tileTable;
return &tileTable;
}
const trpgLightTable *trpgr_Archive::GetLightTable() const
{
return &lightTable;
return &lightTable;
}
const trpgRangeTable *trpgr_Archive::GetRangeTable() const
{
return &rangeTable;
return &rangeTable;
}
const trpgTextStyleTable *trpgr_Archive::GetTextStyleTable() const
{
return &textStyleTable;
}
const trpgSupportStyleTable *trpgr_Archive::GetSupportStyleTable() const
{
return &supportStyleTable;
}
const trpgLabelPropertyTable *trpgr_Archive::GetLabelPropertyTable() const
{
return &labelPropertyTable;
}
trpgEndian trpgr_Archive::GetEndian() const
{
return ness;
return ness;
}
// Utility MBR routine
bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,trpg3dPoint &ur) const
{
if (!header.isValid())
return false;
int32 numLod;
header.GetNumLods(numLod);
trpg2iPoint maxXY;
header.GetLodSize(lod,maxXY);
if (x >= static_cast<unsigned int>(maxXY.x) || y>= static_cast<unsigned int>(maxXY.y))
return false;
if (!header.isValid())
return false;
int32 numLod;
header.GetNumLods(numLod);
trpg2iPoint maxXY;
header.GetLodSize(lod,maxXY);
if (x >= maxXY.x || y>= maxXY.y)
return false;
trpg3dPoint origin;
header.GetOrigin(origin);
trpg2dPoint size;
header.GetTileSize(lod,size);
trpg3dPoint origin;
header.GetOrigin(origin);
trpg2dPoint size;
header.GetTileSize(lod,size);
ll.x = origin.x + size.x*x;
ll.y = origin.y + size.y*y;
ur.x = origin.x + size.x*(x+1);
ur.y = origin.y + size.y*(y+1);
ll.x = origin.x + size.x*x;
ll.y = origin.y + size.y*y;
ur.x = origin.x + size.x*(x+1);
ur.y = origin.y + size.y*(y+1);
// If the tiles are local, we should have Z information
trpgwAppAddress addr;
float elev_min=0.0,elev_max=0.0;
tileTable.GetTile(x,y,lod,addr,elev_min,elev_max);
ll.z = elev_min; ur.z = elev_max;
// If the tiles are local, we should have Z information
trpgwAppAddress addr;
float elev_min=0.0,elev_max=0.0;
tileTable.GetTile(x,y,lod,addr,elev_min,elev_max);
ll.z = elev_min; ur.z = elev_max;
return true;
return true;
}
/* *****************
@@ -303,185 +319,209 @@ 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)
{
ness = inNess;
strcpy(dir,inDir);
matTable = &inMatTable;
texTable = &inTexTable;
ness = inNess;
strcpy(dir,inDir);
matTable = &inMatTable;
texTable = &inTexTable;
// Set up the texture cache
// It doesn't do anything until it's called anyway
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPARATOR "texFile",dir);
texCache = new trpgrAppFileCache(fullBase,"txf");
// Set up the texture cache
// It doesn't do anything until it's called anyway
char fullBase[1024];
sprintf(fullBase,"%s" PATHSEPERATOR "texFile",dir);
texCache = new trpgrAppFileCache(fullBase,"txf");
}
trpgrImageHelper::~trpgrImageHelper()
{
if (texCache)
delete texCache;
if (texCache)
delete texCache;
}
bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size)
{
// Make sure the texture is Local
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if (mode != trpgTexture::Local)
return false;
// Make sure the texture is Local
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if (mode != trpgTexture::Local)
return false;
// Fetch data data
trpgwAppAddress addr;
tex->GetImageAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af)
return false;
if (!af->Read(data,addr.offset,size))
return false;
// Fetch data data
trpgwAppAddress addr;
tex->GetImageAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af)
return false;
if (!af->Read(data,addr.offset,0,size))
return false;
return true;
return true;
}
bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,char *data,int32 dataSize)
{
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
// Make sure the texture is Local
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if (mode != trpgTexture::Local)
return false;
// Make sure the texture is Local
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if (mode != trpgTexture::Local)
return false;
// Fetch data data
trpgwAppAddress addr;
tex->GetImageAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af)
return false;
// Fetch data data
trpgwAppAddress addr;
tex->GetImageAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af)
return false;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset+level_offset,dataSize))
return false;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset,level_offset,dataSize))
return false;
return true;
return true;
}
bool trpgrImageHelper::GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
{
// Get the base material for the Local Material
int32 matSubTable,matID;
locMat->GetBaseMaterial(matSubTable,matID);
const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID);
if (!mat) return false;
return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize);
}
// Now get the texture (always the first one)
trpgTextureEnv texEnv;
int32 texID;
if (!mat->GetTexture(0,texID,texEnv)) return false;
const trpgTexture *tex = texTable->GetTextureRef(texID);
if (!tex) return false;
bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
{
// Get the base material for the Local Material
int32 matSubTable,matID;
locMat->GetBaseMaterial(matSubTable,matID);
// For right now, force the subtable number to match the index.
// 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 (index>0) matSubTable=index; // otherwise, leave it alone - could be nonzero
const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID);
if (!mat) return false;
totSize = tex->CalcTotalSize();
// Now get the texture (always the first one)
trpgTextureEnv texEnv;
int32 texID;
if (!mat->GetTexture(0,texID,texEnv)) return false;
const trpgTexture *tex = texTable->GetTextureRef(texID);
if (!tex) return false;
*retTex = tex;
*retMat = mat;
return true;
totSize = tex->CalcTotalSize();
*retTex = tex;
*retMat = mat;
return true;
}
bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize)
{
if (!locMat->isValid()) return false;
return GetNthImageForLocalMat(locMat, 0, data, dataSize);
}
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetImageInfoForLocalMat(locMat,&mat,&tex,totSize))
return false;
bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,int index, char *data,int dataSize)
{
if (!locMat->isValid()) return false;
// Determine the type
trpgTexture::ImageMode imageMode;
tex->GetImageMode(imageMode);
switch (imageMode) {
case trpgTexture::Template:
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
locMat->GetAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af) return false;
if (!af->Read(data,addr.offset,dataSize))
return false;
}
break;
case trpgTexture::Global:
// Note: Not dealing with Global textures yet
return false;
break;
default:
// This is not a valid Local Material
return false;
};
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
return true;
// Determine the type
trpgTexture::ImageMode imageMode;
tex->GetImageMode(imageMode);
switch (imageMode) {
case trpgTexture::Template:
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
if (!locMat->GetNthAddr(index,addr)) return false;
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af) return false;
if (!af->Read(data,addr.offset,0,dataSize))
return false;
}
break;
case trpgTexture::Global:
// Note: Not dealing with Global textures yet
return false;
break;
default:
// This is not a valid Local Material
return false;
};
return true;
}
bool trpgrImageHelper::GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize)
{
if (!locMat->isValid()) return false;
return GetNthImageMipLevelForLocalMat(miplevel, locMat, 0, data, dataSize);
}
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetImageInfoForLocalMat(locMat,&mat,&tex,totSize))
return false;
bool trpgrImageHelper::GetNthImageMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat, int index, char *data,int dataSize)
{
if (index>0) return false; // not yet, folks, if ever. index>1 means sensors for now.
if (!locMat->isValid()) return false;
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
// Determine the type
trpgTexture::ImageMode imageMode;
tex->GetImageMode(imageMode);
switch (imageMode) {
case trpgTexture::Template:
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
locMat->GetAddr(addr);
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af) return false;
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset+level_offset,dataSize))
return false;
}
break;
case trpgTexture::Global:
// Note: Not dealing with Global textures yet
return false;
break;
default:
// This is not a valid Local Material
return false;
};
// Determine the type
trpgTexture::ImageMode imageMode;
tex->GetImageMode(imageMode);
switch (imageMode) {
case trpgTexture::Template:
{
// Read the image data out of the Local image (in an archive somewhere)
trpgwAppAddress addr;
if (!locMat->GetNthAddr(index,addr)) return false;
trpgrAppFile *af = texCache->GetFile(ness,addr.file);
if (!af) return false;
return true;
int level_offset = (const_cast<trpgTexture*>(tex))->MipLevelOffset(miplevel);
if (!af->Read(data,addr.offset,level_offset,dataSize))
return false;
}
break;
case trpgTexture::Global:
// Note: Not dealing with Global textures yet
return false;
break;
default:
// This is not a valid Local Material
return false;
};
return true;
}
bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pathLen)
{
char name[1024];
int nameLen=1024;
tex->GetName(name,nameLen);
nameLen = strlen(name);
char name[1024];
int nameLen=1024;
tex->GetName(name,nameLen);
nameLen = strlen(name);
if (strlen(dir) + nameLen + 2 > static_cast<unsigned int>(pathLen))
return false;
if (strlen(dir) + nameLen + 2 > pathLen)
return false;
sprintf(fullPath,"%s" PATHSEPARATOR "%s",dir,name);
sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);
return true;
return true;
}

View File

@@ -18,201 +18,221 @@
#define _txpage_read_h_
/* txpage_read.h
Classes used to represent read objects for paging files.
*/
Classes used to represent read objects for paging files.
*/
#include "trpage_sys.h"
#include <trpage_sys.h>
#include "trpage_geom.h"
#include <trpage_geom.h>
/* Callback base class
Called when a given token is found.
{group:Archive Reading}
*/
Called when a given token is found.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Callback {
public:
virtual ~trpgr_Callback(void) { };
virtual void *Parse(trpgToken,trpgReadBuffer &) { return (void *)1; };
virtual ~trpgr_Callback(void) { };
virtual void *Parse(trpgToken,trpgReadBuffer &) { return (void *)1; };
};
/* Paging Token
Stores callback info associated with a given token.
{group:Archive Reading}
*/
Stores callback info associated with a given token.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Token {
public:
trpgr_Token(void);
trpgr_Token(int,trpgr_Callback *,bool destroy=true);
~trpgr_Token(void);
void init(int,trpgr_Callback *,bool destroy=true);
int Token; // Constant token value
trpgr_Callback *cb; // Callback when we hit this token
bool destroy; // Should we call delete on the callback or not
void Destruct(void); // Not quite like delete
trpgr_Token(void);
trpgr_Token(int,trpgr_Callback *,bool destroy=true);
~trpgr_Token(void);
void init(int,trpgr_Callback *,bool destroy=true);
int Token; // Constant token value
trpgr_Callback *cb; // Callback when we hit this token
bool destroy; // Should we call delete on the callback or not
void Destruct(void); // Not quite like delete
};
/* Parse class for paging data structures.
This executes callbacks
{group:Archive Reading}
*/
This executes callbacks
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Parser {
public:
trpgr_Parser(void);
virtual ~trpgr_Parser(void);
bool isValid(void) const;
trpgr_Parser(void);
virtual ~trpgr_Parser(void);
bool isValid(void) const;
// Add and remove token callbacks
virtual void AddCallback(trpgToken,trpgr_Callback *,bool destroy = true);
virtual void AddCallback(trpgToken,trpgReadWriteable *);
virtual void RemoveCallback(trpgToken);
virtual void SetDefaultCallback(trpgr_Callback *,bool destroy = true);
// Parse a read buffer
virtual bool Parse(trpgReadBuffer &);
virtual bool TokenIsValid(trpgToken); // Check token validity
// Add and remove token callbacks
virtual void AddCallback(trpgToken,trpgr_Callback *,bool destroy = true);
virtual void AddCallback(trpgToken,trpgReadWriteable *);
virtual void RemoveCallback(trpgToken);
virtual void SetDefaultCallback(trpgr_Callback *,bool destroy = true);
// Parse a read buffer
virtual bool Parse(trpgReadBuffer &);
virtual bool TokenIsValid(trpgToken); // Check token validity
protected:
void *lastObject;
void *lastObject;
private:
// Note: Just how slow is a map<> anyway?
// This usage is self-contained and could be replaced with an array
#if defined(_WIN32) && !defined(__CYGWIN__)
typedef std::map<trpgToken,trpgr_Token> tok_map;
// Note: Just how slow is a map<> anyway?
// This usage is self-contained and could be replaced with an array
#if defined(_WIN32)
typedef std::map<trpgToken,trpgr_Token> tok_map;
#else
typedef std::map<trpgToken,trpgr_Token,std::less<trpgToken> > tok_map;
typedef std::map<trpgToken,trpgr_Token,std::less<trpgToken> > tok_map;
#endif
tok_map tokenMap;
trpgr_Token defCb; // Call this when no others are called
tok_map tokenMap;
trpgr_Token defCb; // Call this when no others are called
};
/* Image Read Helper.
Used to help read Local and Tile Local textures into
memory (in OpenGL format). You're on your own for External
textures.
If you want to add additional ways to read textures, feel free
to subclass this object.
Used to help read Local and Tile Local textures into
memory (in OpenGL format). You're on your own for External
textures.
If you want to add additional ways to read textures, feel free
to subclass this object.
*/
TX_EXDECL class TX_CLDECL trpgrImageHelper {
public:
trpgrImageHelper(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &);
virtual ~trpgrImageHelper(void);
trpgrImageHelper(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &);
virtual ~trpgrImageHelper(void);
/* Fetch the bytes for the given texture.
This is only valid for Local textures.
*/
virtual bool GetLocalGL(const trpgTexture *,char *data,int32 dataSize);
/* Fetch the bytes for the given texture.
This is only valid for Local textures.
*/
virtual bool GetLocalGL(const trpgTexture *,char *data,int32 dataSize);
/* Fetch the bytes for the given mip level of a given texture.
This is only valid for Local textures.
*/
virtual bool GetMipLevelLocalGL(int miplevel, const trpgTexture *,char *data,int32 dataSize);
/* Fetch the bytes for the given mip level of a given texture.
This is only valid for Local textures.
*/
virtual bool GetMipLevelLocalGL(int miplevel, const trpgTexture *,char *data,int32 dataSize);
/* Do the lookups to figure out the correct material
and Template (or Local) texture for a given Local Material.
You'll need this for sizes (among other things).
This routine also calculates the total size, including mipmaps if they're there.
*/
virtual bool GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
/* Do the lookups to figure out the correct material
and Template (or Local) texture for a given Local Material.
You'll need this for sizes (among other things).
This routine also calculates the total size, including mipmaps if they're there.
*/
virtual bool GetImageInfoForLocalMat(const trpgLocalMaterial *locMat,
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
/* Fetch the bytes for the given Local Material (and
associated texture). This is for Tile Local and
Global textures.
Data is a pre-allocated buffer for the data and
dataSize is the size of that buffer.
*/
virtual bool GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize);
/* Same as above, but gets info for nth image associated with this local material
*/
virtual bool GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
const trpgMaterial **retMat,const trpgTexture **retTex,
int &totSize);
/* Same as the one above, just fetch single mip levels
*/
virtual bool GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize);
/* Fetch the bytes for the given Local Material (and
associated texture). This is for Tile Local and
Global textures.
Data is a pre-allocated buffer for the data and
dataSize is the size of that buffer.
*/
virtual bool GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize);
/* Determine the full path of the image in the given
trpgTexture class.
Only useful for External images.
*/
virtual bool GetImagePath(const trpgTexture *,char *,int len);
/* Same as above, but gets nth image associated with this local material
*/
virtual bool GetNthImageForLocalMat(const trpgLocalMaterial *locMat, int index, char *data,int dataSize);
/* Same as the one above, just fetch single mip levels
*/
virtual bool GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize);
/* Get mip levels for one of multiple images
*/
virtual bool GetNthImageMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat, int index, char *data,int dataSize);
/* Determine the full path of the image in the given
trpgTexture class.
Only useful for External images.
*/
virtual bool GetImagePath(const trpgTexture *,char *,int len);
protected:
char dir[1024];
trpgEndian ness;
const trpgMatTable *matTable;
const trpgTexTable *texTable;
char dir[1024];
trpgEndian ness;
const trpgMatTable *matTable;
const trpgTexTable *texTable;
trpgrAppFileCache *texCache;
trpgrAppFileCache *texCache;
};
/* Paging Archive (read version)
This just reads the first bits of the file (and the header)
and lets you parse from there.
{group:Archive Reading}
*/
This just reads the first bits of the file (and the header)
and lets you parse from there.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable {
public:
trpgr_Archive(void);
virtual ~trpgr_Archive(void);
trpgr_Archive(void);
virtual ~trpgr_Archive(void);
virtual void SetDirectory(const char *);
virtual bool OpenFile(const char *); // Open File
virtual void CloseFile(void);
virtual bool ReadHeader(void); // Read header (materials, tile table. etc..)
virtual bool ReadTile(uint32 x, uint32 y, uint32 lod,trpgMemReadBuffer &);
virtual void SetDirectory(const char *);
virtual bool OpenFile(const char *); // Open File
virtual void CloseFile(void);
virtual bool ReadHeader(void); // Read header (materials, tile table. etc..)
virtual bool ReadTile(uint32 x, uint32 y, uint32 lod,trpgMemReadBuffer &);
// Get access to header info
virtual const trpgHeader *GetHeader(void) const;
virtual const trpgMatTable *GetMaterialTable(void) const;
virtual const trpgTexTable *GetTexTable(void) const;
virtual const trpgModelTable *GetModelTable(void) const;
virtual const trpgTileTable *GetTileTable(void) const;
virtual const trpgLightTable *GetLightTable(void) const;
virtual const trpgRangeTable *GetRangeTable(void) const;
// Get access to header info
virtual const trpgHeader *GetHeader(void) const;
virtual const trpgMatTable *GetMaterialTable(void) const;
virtual const trpgTexTable *GetTexTable(void) const;
virtual const trpgModelTable *GetModelTable(void) const;
virtual const trpgTileTable *GetTileTable(void) const;
virtual const trpgLightTable *GetLightTable(void) const;
virtual const trpgRangeTable *GetRangeTable(void) const;
virtual const trpgLabelPropertyTable *GetLabelPropertyTable() const;
virtual const trpgTextStyleTable *GetTextStyleTable() const;
virtual const trpgSupportStyleTable *GetSupportStyleTable() const;
// Utility routine to calculate the MBR of a given tile
virtual bool trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,
trpg3dPoint &ll,trpg3dPoint &ur) const;
// Utility routine to calculate the MBR of a given tile
virtual bool trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,
trpg3dPoint &ll,trpg3dPoint &ur) const;
trpgEndian GetEndian(void) const;
char* getDir(void){return dir;};
trpgEndian GetEndian(void) const;
char* getDir(void){return dir;};
protected:
bool headerRead;
trpgEndian ness;
FILE *fp;
int fid;
// Header info
char dir[1024];
trpgHeader header;
trpgMatTable materialTable;
trpgTexTable texTable;
trpgModelTable modelTable;
trpgTileTable tileTable;
trpgLightTable lightTable;
trpgRangeTable rangeTable;
bool headerRead;
trpgEndian ness;
FILE *fp;
int fid;
// Header info
char dir[1024];
trpgHeader header;
trpgMatTable materialTable;
trpgTexTable texTable;
trpgModelTable modelTable;
trpgTileTable tileTable;
trpgLightTable lightTable;
trpgRangeTable rangeTable;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
trpgrAppFileCache *tileCache;
trpgrAppFileCache *tileCache;
};
class trpgSceneHelperPush;
class trpgSceneHelperPop;
class trpgSceneHelperDefault;
/* Scene Parser
This class assists in parsing a scene graph structure (tiles and models).
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
parser.
{group:Archive Reading}
*/
This class assists in parsing a scene graph structure (tiles and models).
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
parser.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser {
friend class trpgSceneHelperPush;
friend class trpgSceneHelperPop;
friend class trpgSceneHelperDefault;
friend class trpgSceneHelperPush;
friend class trpgSceneHelperPop;
friend class trpgSceneHelperDefault;
public:
trpgSceneParser(void);
virtual ~trpgSceneParser(void);
trpgSceneParser(void);
virtual ~trpgSceneParser(void);
protected:
// Start defining children for the given object
virtual bool StartChildren(void *) { return true;};
virtual bool EndChildren(void *) { return true;};
// Start defining children for the given object
virtual bool StartChildren(void *) { return true;};
virtual bool EndChildren(void *) { return true;};
// List of objects whose children we're working on
std::vector<void *> parents;
// List of objects whose children we're working on
std::vector<void *> parents;
};
#endif

View File

@@ -18,18 +18,18 @@
#include <math.h>
/* trpage_readbuf.cpp
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
#include "trpage_io.h"
#include "trpage_swap.h"
#include <trpage_io.h>
#include <trpage_swap.h>
/* **********************
Read buffer base class functions
@@ -39,243 +39,263 @@
// Basic get functions
bool trpgReadBuffer::Get(int32 &ret)
{
int32 val;
int32 val;
if (!GetData((char *)&val,sizeof(int32))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_int(val);
else
ret = val;
if (!GetData((char *)&val,sizeof(int32))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_int(val);
else
ret = val;
return true;
return true;
}
bool trpgReadBuffer::Get(int64 &ret)
{
int64 val;
int64 val;
if (!GetData((char *)&val,sizeof(int64))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_llong(val);
else
ret = val;
if (!GetData((char *)&val,sizeof(int64))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_long(val);
else
ret = val;
return true;
return true;
}
bool trpgReadBuffer::Get(char *ret,int retLen)
{
int32 len;
int32 len;
// Get the length first
if (!Get(len)) return false;
// Get the length first
if (!Get(len)) return false;
// Read what we can
int rlen = MIN(len,retLen-1);
if (!GetData(ret,rlen)) return false;
ret[rlen] = 0;
// Read what we can
int rlen = MIN(len,retLen-1);
if (!GetData(ret,rlen)) return false;
ret[rlen] = 0;
// Skip the rest
if (!Skip(rlen-len)) return false;
// Skip the rest
if (!Skip(rlen-len)) return false;
return true;
return true;
}
bool trpgReadBuffer::Get(std::string &str)
{
int32 len;
// Get the length first
if (!Get(len)) return false;
if (len < 0)
return false;
// Note: Should fix this
char *tmpStr = new char[len+1];
// Read it
if (!GetData(tmpStr,len)) return false;
tmpStr[len] = 0;
str = tmpStr;
return true;
}
bool trpgReadBuffer::Get(float32 &ret)
{
char cval[4];
char cval[4];
if (!GetData(cval,sizeof(float32))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,4);
else
ret = trpg_byteswap_4bytes_to_float(cval);
}
catch (...) {
}
if (!GetData(cval,sizeof(float32))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,4);
else
ret = trpg_byteswap_4bytes_to_float(cval);
}
catch (...) {
}
return true;
return true;
}
bool trpgReadBuffer::Get(float64 &ret)
{
char cval[8];
char cval[8];
if (!GetData(cval,sizeof(float64))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,8);
else
ret = trpg_byteswap_8bytes_to_double(cval);
}
catch (...) {
}
if (!GetData(cval,sizeof(float64))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,8);
else
ret = trpg_byteswap_8bytes_to_double(cval);
}
catch (...) {
}
return true;
return true;
}
bool trpgReadBuffer::Get(uint8 &ret)
{
uint8 val;
uint8 val;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = val;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = val;
return true;
return true;
}
#if (bool != int32)
//#if (bool != int32)
bool trpgReadBuffer::Get(bool &ret)
{
uint8 val;
uint8 val;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = (val == 0) ? false : true;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = (val == 0) ? false : true;
return true;
return true;
}
#endif
//#endif
#if (trpgDiskRef != int64)
bool trpgReadBuffer::Get(trpgDiskRef &ret)
{
trpgDiskRef val;
trpgDiskRef val;
if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_llong(val);
if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_llong(val);
return true;
return true;
}
#endif
bool trpgReadBuffer::Get(trpgToken &ret)
{
trpgToken val;
trpgToken val;
if (!GetData((char *)&val,sizeof(trpgToken))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_short(val);
if (!GetData((char *)&val,sizeof(trpgToken))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_short(val);
return true;
return true;
}
// Array Get functions
bool trpgReadBuffer::GetArray(int len,float32 **arr)
{
if (!GetDataRef((char **)arr,sizeof(float32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
if (!GetDataRef((char **)arr,sizeof(float32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
return true;
}
bool trpgReadBuffer::GetArray(int len,float64 **arr)
{
if (!GetDataRef((char **)arr,sizeof(float64)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_eight(ptr,ptr);
}
return true;
if (!GetDataRef((char **)arr,sizeof(float64)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_eight(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,int32 **arr)
{
if (!GetDataRef((char **)arr,sizeof(int32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
if (!GetDataRef((char **)arr,sizeof(int32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,trpgColor **arr)
{
if (!GetDataRef((char **)arr,sizeof(trpgColor)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_four(ptr,ptr);
}
return true;
if (!GetDataRef((char **)arr,sizeof(trpgColor)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_four(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,char **arr)
{
return GetDataRef((char **)arr,sizeof(char)*len);
return GetDataRef((char **)arr,sizeof(char)*len);
}
// Utility Get functions - Just call the others
bool trpgReadBuffer::Get(trpg2iPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
}
bool trpgReadBuffer::Get(trpg2dPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
}
bool trpgReadBuffer::Get(trpg3dPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y) || !Get(pt.z))
return false;
return true;
if (!Get(pt.x) || !Get(pt.y) || !Get(pt.z))
return false;
return true;
}
bool trpgReadBuffer::Get(trpgColor &color)
{
if (!Get(color.red) || !Get(color.green) || !Get(color.blue))
return false;
return true;
if (!Get(color.red) || !Get(color.green) || !Get(color.blue))
return false;
return true;
}
// Get both a token and it's length, since that's fairly common
bool trpgReadBuffer::GetToken(trpgToken &tok,int32 &len)
{
if (!Get(tok) || !Get(len))
return false;
if (!Get(tok) || !Get(len))
return false;
return true;
return true;
}
/* Limit Handling functions
These impose arbitrary lenght limits on the read buffer.
This keeps us from reading pased a token group and parsing
random data within an archive.
*/
These impose arbitrary lenght limits on the read buffer.
This keeps us from reading pased a token group and parsing
random data within an archive.
*/
// Push Limit
// Add another limit to the top of the stack
void trpgReadBuffer::PushLimit(int limit)
{
limits.push_back(limit);
limits.push_back(limit);
}
// Pop Limit
// Remove the current limit from the stack
void trpgReadBuffer::PopLimit()
{
int len = limits.size();
int len = limits.size();
if (len > 0)
limits.resize(len-1);
if (len > 0)
limits.resize(len-1);
}
// Skip To Limit
@@ -283,34 +303,34 @@ void trpgReadBuffer::PopLimit()
// This happens when we bag the rest of the current token
bool trpgReadBuffer::SkipToLimit()
{
int len=0;
int len=0;
if (limits.size() != 0)
len = limits[limits.size()-1];
if (limits.size() != 0)
len = limits[limits.size()-1];
if (len > 0)
return Skip(len);
if (len > 0)
return Skip(len);
return true;
return true;
}
// Test Limit
// See if the next read is going to blow the limits
bool trpgReadBuffer::TestLimit(int len)
{
for (unsigned int i=0;i<limits.size();i++)
if (len > limits[i])
return false;
for (int i=0;i<limits.size();i++)
if (len > limits[i])
return false;
return true;
return true;
}
// Update Limits
// We just read a few bytes. Update the limits
void trpgReadBuffer::UpdateLimits(int len)
{
for (unsigned int i=0;i<limits.size();i++)
limits[i] -= len;
for (int i=0;i<limits.size();i++)
limits[i] -= len;
}
/* *************************
@@ -319,112 +339,112 @@ void trpgReadBuffer::UpdateLimits(int len)
*/
trpgMemReadBuffer::trpgMemReadBuffer(trpgEndian in_ness)
{
data = NULL;
len = totLen = pos = 0;
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
data = NULL;
len = totLen = pos = 0;
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
}
trpgMemReadBuffer::~trpgMemReadBuffer()
{
if (data)
delete [] data;
if (data)
delete [] data;
}
// Empty check
bool trpgMemReadBuffer::isEmpty()
{
if (!data) return true;
if (!data) return true;
if (pos >= len)
return true;
if (pos >= len)
return true;
// Also test the limits
for (unsigned int i=0;i<limits.size();i++)
if (limits[i] == 0) return true;
// Also test the limits
for (int i=0;i<limits.size();i++)
if (limits[i] == 0) return true;
return false;
return false;
}
// Set Length
// Allocate the given space
void trpgMemReadBuffer::SetLength(int newLen)
{
if (newLen > totLen) {
if (data)
delete [] data;
data = new char[newLen];
totLen = newLen;
}
len = newLen;
pos = 0;
if (newLen > totLen) {
if (data)
delete [] data;
data = new char[newLen];
totLen = newLen;
}
len = newLen;
pos = 0;
}
// Get Data Ptr
// Return a pointer to our data so it can be written to
char *trpgMemReadBuffer::GetDataPtr()
{
return data;
return data;
}
// Get Data
// Protected method for actually retrieving a piece of data
bool trpgMemReadBuffer::GetData(char *ret,int rlen)
{
if (rlen < 0)
return false;
if (rlen < 0)
return false;
// Test against limits imposed from without
if (!TestLimit(rlen)) throw 1;
// Test against limits imposed from without
if (!TestLimit(rlen)) throw 1;
// See if we've actually got the data
if (pos+rlen > len) throw 1;
// See if we've actually got the data
if (pos+rlen > len) throw 1;
// Copy into the return buffer
memcpy(ret,&data[pos],rlen);
// Copy into the return buffer
memcpy(ret,&data[pos],rlen);
// Update any limits we might have
UpdateLimits(rlen);
// Update any limits we might have
UpdateLimits(rlen);
pos += rlen;
pos += rlen;
return true;
return true;
}
// Get Reference to Data
// Protected method that retrieves a reference to the given amoutn of data
bool trpgMemReadBuffer::GetDataRef(char **ret,int rlen)
{
if (rlen < 0) return false;
if (rlen < 0) return false;
// Test against limits
if (!TestLimit(rlen)) throw 1;
if (pos + rlen > len) throw 1;
// Test against limits
if (!TestLimit(rlen)) throw 1;
if (pos + rlen > len) throw 1;
// Set up reference
*ret = &data[pos];
// Set up reference
*ret = &data[pos];
UpdateLimits(rlen);
pos += rlen;
UpdateLimits(rlen);
pos += rlen;
return true;
return true;
}
// Skip
// Same as read except we're not, uh, reading
bool trpgMemReadBuffer::Skip(int rlen)
{
if (rlen < 0)
return false;
if (rlen < 0)
return false;
// Test against limits
if (!TestLimit(rlen)) return false;
if (pos + rlen > len) return false;
// Test against limits
if (!TestLimit(rlen)) return false;
if (pos + rlen > len) return false;
UpdateLimits(rlen);
UpdateLimits(rlen);
pos += rlen;
pos += rlen;
return true;
return true;
}
/* Appendable File read class
@@ -432,185 +452,195 @@ bool trpgMemReadBuffer::Skip(int rlen)
trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
if (!(fp = fopen(fileName,"rb")))
return;
if (!(fp = fopen(fileName,"rb")))
return;
valid = true;
valid = true;
}
trpgrAppFile::~trpgrAppFile()
{
if (fp)
fclose(fp);
if (fp)
fclose(fp);
valid = false;
valid = false;
}
// Read a section of data from the given file
// and dump it into the given buffer
bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset)
{
if (!valid) return false;
if (!valid) return false;
// Seek to the right location
if (fseek(fp,offset,SEEK_SET))
return false;
// Seek to the right location
if (fseek(fp,offset,SEEK_SET))
return false;
// Read a length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Read a length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Byteswap if necessary
if (ness != cpuNess)
len = trpg_byteswap_int(len);
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
if (len < 0) {
valid = false;
return false;
}
if (len < 0) {
valid = false;
return false;
}
buf->SetLength(len);
char *data = buf->GetDataPtr();
if (!data) {
valid = false;
return false;
}
buf->SetLength(len);
char *data = buf->GetDataPtr();
if (!data) {
valid = false;
return false;
}
if (fread(data,sizeof(char),len,fp) != static_cast<unsigned int>(len)) {
valid = false;
return false;
}
if (fread(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
return true;
return true;
}
/* Read a section of data from the given file
and dump it into the given memory. Sanity
check the length against the size of the memory
passed into dataSize.
check the length against the size of the memory
passed into dataSize.
*/
bool trpgrAppFile::Read(char *data,int32 offset,uint32 dataSize)
bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSize)
{
if (!valid) return false;
if (!valid) return false;
// Seek to the right place
if (fseek(fp,offset,SEEK_SET)) {
valid = false;
return false;
}
// Seek to the right place
int result;
if ((result = fseek(fp,baseOffset,SEEK_SET))) {
valid = false;
return false;
}
// Read the length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Read the total object length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Byteswap if necessary
if (ness != cpuNess)
len = trpg_byteswap_int(len);
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
if (len < 0) {
valid = false;
return false;
}
// It's all right to read less than the whol data block
if (dataSize > static_cast<unsigned int>(len))
return false;
if (len < 0) {
valid = false;
return false;
}
// Read the raw data
// Note: What about byte swapping?
if (fread(data,sizeof(char),dataSize,fp) != dataSize) {
valid = false;
return false;
}
// It's all right to read less than the whole data block
if (objOffset+dataSize > len)
return false;
return true;
// Skip to the object offset
if (fseek(fp,objOffset,SEEK_CUR)) {
valid = false;
return false;
}
// Read the raw data
// Note: What about byte swapping?
if (fread(data,sizeof(char),dataSize,fp) != dataSize) {
valid = false;
return false;
}
return true;
}
/* App File Cache
This class manages a group of appendable files with
the same base name and extension. It will keep a certain
number of them open to facilitate caching.
This class manages a group of appendable files with
the same base name and extension. It will keep a certain
number of them open to facilitate caching.
*/
trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noFiles)
{
strcpy(baseName,inPre);
strcpy(ext,inExt);
strcpy(baseName,inPre);
strcpy(ext,inExt);
files.resize(noFiles);
timeCount = 0;
files.resize(noFiles);
timeCount = 0;
}
trpgrAppFileCache::~trpgrAppFileCache()
{
for (unsigned int i=0;i<files.size();i++) {
if (files[i].afile) {
delete files[i].afile;
files[i].afile = NULL;
}
}
for (unsigned int i=0;i<files.size();i++) {
if (files[i].afile) {
delete files[i].afile;
files[i].afile = NULL;
}
}
}
/*
*/
trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id)
{
// Look for it already here
int foundID = -1;
unsigned int i;
for (i=0;i<files.size();i++) {
if (files[i].id == id) {
foundID = i;
}
}
// Look for it already here
int foundID = -1;
unsigned int i;
for (i=0;i<files.size();i++) {
if (files[i].id == id) {
foundID = i;
break;
}
}
// Found it in cache, just return
if (foundID != -1) {
OpenFile &of = files[foundID];
of.lastUsed = timeCount;
return of.afile;
}
// Found it in cache, just return
if (foundID != -1) {
OpenFile &of = files[foundID];
of.lastUsed = timeCount;
return of.afile;
}
// Didn't find it. Need to reclaim one
// Look for the oldest used
int oldTime=-1,oldID=-1;
for (i=0;i<files.size();i++) {
OpenFile &of = files[i];
if (!of.afile || (of.lastUsed < oldTime)) {
oldID = i;
oldTime = of.lastUsed;
if (!of.afile)
break;
}
}
// Didn't find it. Need to reclaim one
// Look for the oldest used
int oldTime=-1,oldID=-1;
for (i=0;i<files.size();i++) {
OpenFile &of = files[i];
if (!of.afile || (oldTime == -1) || (of.lastUsed < oldTime)) {
oldID = i;
oldTime = of.lastUsed;
if (!of.afile)
break;
}
}
// Reclaim this one
OpenFile &of = files[oldID];
if (of.afile) delete of.afile;
char fileName[1024];
sprintf(fileName,"%s_%d.%s",baseName,id,ext);
of.afile = new trpgrAppFile(ness,fileName);
of.id = id;
of.lastUsed = timeCount;
timeCount++;
// Reclaim this one
OpenFile &of = files[oldID];
if (of.afile) delete of.afile;
char fileName[1024];
sprintf(fileName,"%s_%d.%s",baseName,id,ext);
of.afile = new trpgrAppFile(ness,fileName);
of.id = id;
of.lastUsed = timeCount;
return of.afile;
timeCount++;
return of.afile;
}
// Constructor for OpenFile class
trpgrAppFileCache::OpenFile::OpenFile()
{
afile = NULL;
lastUsed = 0;
id = -1;
afile = NULL;
lastUsed = 0;
id = -1;
}

View File

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

View File

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

View File

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

View File

@@ -17,19 +17,19 @@
#define trpage_swap_h_
/* trpage_swap.h
Byte swapping utility functions.
Byte swapping utility functions.
*/
#include "trpage_sys.h"
#include <trpage_sys.h>
#include "trpage_io.h"
#include <trpage_io.h>
// Byte swap and return a short
// {group:Byte Ordering Utilities}
short trpg_byteswap_short( short number );
// Byte swap and return an integer
// {group:Byte Ordering Utilities}
int trpg_byteswap_int( int number );
int trpg_byteswap_int( int number );
// Byte swap and return a long
// {group:Byte Ordering Utilities}
long trpg_byteswap_long( long number );

View File

@@ -14,53 +14,41 @@
*/
/* trpage_sys.h
System specific declarations.
*/
System specific declarations.
*/
#ifndef trpage_sys_h_
#define trpage_sys_h_
#ifndef PATHSEPARATOR
#ifndef PATHSEPERATOR
#ifdef macintosh
#define PATHSEPARATOR ":"
#define PATHSEPERATOR ":"
#else
#define PATHSEPARATOR "/"
#define PATHSEPERATOR "/"
#endif
#endif
#if defined(_WIN32)
/* *********************
System Specific Section.
This is currently set up for win32.
*********************
*/
/* *********************
System Specific Section.
This is currently set up for win32.
*********************
*/
#include <windows.h>
#include <stdio.h>
#if !defined(__GNUC__)
// Microsoft Developer warnings that annoy me
#pragma warning ( disable : 4251)
#pragma warning ( disable : 4275)
#pragma warning ( disable : 4786)
#endif
// Somewhat system independent file deletion macro
#ifdef __CYGWIN__
# define TRPGDELETEFILE(file) remove((file))
#else
# define TRPGDELETEFILE(file) DeleteFile((file))
#endif
#define TRPGDELETEFILE(file) DeleteFile((file))
#ifndef int64
// 64 bit long value. Need this for really big files.
#ifdef __GNUC__
typedef long long int64;
#else
typedef __int64 int64;
// 64 bit long value. Need this for really big files.
typedef __int64 int64;
#endif
#endif
#else // Unix
@@ -100,6 +88,7 @@ typedef double float64;
#include <vector>
#include <map>
#include <string>
#if defined(_WIN32) // PJM
// Had to take this out because of an iostream conflict
@@ -112,7 +101,7 @@ typedef int64 trpgllong;
// These are used to export classes from a DLL
// Definitely Windows specific
#include "trpage_ident.h"
#include "trdll.h"
#include <trpage_ident.h>
#include <trdll.h>
#endif

View File

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

View File

@@ -13,7 +13,7 @@
************************
*/
#include "trpage_util.h"
#include <trpage_util.h>
/* trpage_util.cpp
This source file implements various utility routines for paging archive

View File

@@ -20,14 +20,13 @@
#ifndef trpage_util_h_
#define trpage_util_h_
#include <stdlib.h>
#include "trpage_read.h"
#include "trpage_write.h"
#include "trpage_scene.h"
#include <trpage_read.h>
#include <trpage_write.h>
#include <trpage_scene.h>
TX_EXDECL class TX_CLDECL trpgUtil {
public:
enum {DoReport = 1<<0,DoCopy = 1<<1, DoTileOpt = 1<<2};
int merge(trpgr_Archive &inArch1,trpgr_Archive &inArch2,trpgwArchive &outArch, int flags = 0);
};
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

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

View File

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