Merged changes from Nicklov Trajce and Boris Bralo.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
#ifndef TERRAPAGENODE_H
|
||||
#define TERRAPAGENODE_H
|
||||
|
||||
#include "trPagePageManager.h"
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/BoundingBox>
|
||||
|
||||
#include "trPagePageManager.h"
|
||||
|
||||
namespace txp
|
||||
{
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -88,6 +88,11 @@ namespace txp
|
||||
// Calculate the center
|
||||
void GetCenter(osg::Vec3 ¢er);
|
||||
|
||||
osg::Texture2D* getGlobalTexture(int id)
|
||||
{
|
||||
return m_textures[id].get();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// This class does most of the actual parsing.
|
||||
std::auto_ptr<TrPageParser> parse;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
978
src/osgPlugins/txp/trpage_label.cpp
Normal file
978
src/osgPlugins/txp/trpage_label.cpp
Normal 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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user