From Trajce Nikolov, port of TXP plugin across to a pure PagedLOD based

pager, with a little assistance from Robert Osfield.
This commit is contained in:
Robert Osfield
2003-12-22 06:27:17 +00:00
parent f1d8a584d8
commit 7a5053f81f
61 changed files with 13975 additions and 14305 deletions

View File

@@ -2,12 +2,14 @@ TOPDIR = ../../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
IO_TerrapageNode.cpp\
ReaderWriterTXP.cpp\
TerrapageNode.cpp\
TrPageArchive.cpp\
TrPageParser.cpp\
trPagePageManager.cpp\
TXPArchive.cpp\
TXPIO.cpp\
TXPNode.cpp\
TXPPageManager.cpp\
TXPTileNode.cpp\
TXPParser.cpp\
TXPSeamLOD.cpp\
trpage_basic.cpp\
trpage_compat.cpp\
trpage_geom.cpp\
@@ -34,7 +36,6 @@ CXXFILES =\
trpage_writebuf.cpp\
INC += -I$(THISDIR)
LIBS += -losgSim -losgText $(OSG_LIBS) $(OTHER_LIBS)

View File

@@ -1,57 +0,0 @@
#include "TerrapageNode.h"
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osg/ref_ptr>
#include <iostream>
bool TerrapageNode_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool TerrapageNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy TerrapageNode_Proxy
(
new txp::TerrapageNode,
"TerrapageNode",
"Object Node TerrapageNode",
TerrapageNode_readLocalData,
TerrapageNode_writeLocalData
);
bool TerrapageNode_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
txp::TerrapageNode &pager = static_cast<txp::TerrapageNode &>(obj);
bool itrAdvanced = false;
if (fr.matchSequence("databaseOptions %s"))
{
pager.setDatabaseOptions(fr[1].getStr());
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("databaseName %s"))
{
pager.setDatabaseName(fr[1].getStr());
pager.loadDatabase();
fr += 2;
itrAdvanced = true;
}
return itrAdvanced;
}
bool TerrapageNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
const txp::TerrapageNode &pager = static_cast<const txp::TerrapageNode &>(obj);
if (!pager.getDatabaseOptions().empty()) fw.indent() << "databaseOptions \"" << pager.getDatabaseOptions() << "\""<<std::endl;
if (!pager.getDatabaseName().empty()) fw.indent() << "databaseName \"" << pager.getDatabaseName() << "\"" << std::endl;
return true;
}

View File

@@ -1,42 +1,160 @@
#include "ReaderWriterTXP.h"
#include <osg/Group>
#include <osg/Object>
#include <osg/Node>
#include <osg/Notify>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <iostream>
#include "TrPageArchive.h"
#include "ReaderWriterTXP.h"
#include "TXPNode.h"
#include "TXPTileNode.h"
#include "TXPArchive.h"
#include "TerrapageNode.h"
#define ReaderWriterTXPERROR(s) osg::notify(osg::NOTICE) << "txp::ReaderWriterTXP::" << (s) << " error: "
using namespace txp;
using namespace osg;
int ReaderWriterTXP::_archiveId = 0;
osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options)
{
if( !acceptsExtension(osgDB::getFileExtension(fileName) ))
return ReadResult::FILE_NOT_HANDLED;
osg::ref_ptr<txp::TerrapageNode> pager = new TerrapageNode;
std::string name = osgDB::getSimpleFileName(fileName);
pager->setDatabaseName(fileName);
if (options)
// We load archive.txp
if (strncmp(name.c_str(),"archive",7)==0)
{
pager->setDatabaseOptions(options->getOptionString());
osg::ref_ptr<TXPNode> txpNode = new TXPNode;
txpNode->setArchiveName(fileName);
if (options)
{
txpNode->setOptions(options->getOptionString());
}
if (txpNode->loadArchive())
{
TXPArchive* archive = txpNode->getArchive();
if (archive) archive->setId(_archiveId++);
return txpNode.get();
}
else
{
return ReadResult::ERROR_IN_READING_FILE;
}
}
// We load tileLOD_XxY_ID.txp
if (strncmp(name.c_str(),"tile",4)==0)
{
int x,y,lod;
unsigned int id;
sscanf(name.c_str(),"tile%d_%dx%d_%d",&lod,&x,&y,&id);
TXPArchive* archive = getArchive(id,osgDB::getFilePath(fileName));
osg::ref_ptr<TXPTileNode> txpTileNode = new TXPTileNode;
txpTileNode->setArchive(archive);
if (txpTileNode->loadTile(x,y,lod))
{
//osg::notify(osg::NOTICE) << "Tile " << x << " " << y << " " << lod << " lodaded" << std::endl;
return txpTileNode.get();
}
else
return ReadResult::ERROR_IN_READING_FILE;
}
// We load subtilesLOD_XxY_ID.txp
if (strncmp(name.c_str(),"sub",3)==0)
{
int x,y,lod;
unsigned int id;
sscanf(name.c_str(),"subtiles%d_%dx%d_%d",&lod,&x,&y,&id);
TXPArchive* archive = getArchive(id,osgDB::getFilePath(fileName));
osg::ref_ptr<osg::Group> subtiles = new osg::Group;
for (int ix = 0; ix < 2; ix++)
for (int iy = 0; iy < 2; iy++)
{
int tileX = x*2+ix;
int tileY = y*2+iy;
int tileLOD = lod+1;
TXPTileNode* txpTileNode = new TXPTileNode;
txpTileNode->setArchive(archive);
if (txpTileNode->loadTile(tileX,tileY,tileLOD))
{
subtiles->addChild(txpTileNode);
}
}
//osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl;
return subtiles.get();
}
if (pager->loadDatabase())
{
return pager.get();
}
else
return ReadResult::ERROR_IN_READING_FILE;
return ReadResult::ERROR_IN_READING_FILE;
}
TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir)
{
TXPArchive* archive = NULL;
std::map< int,osg::ref_ptr<TXPArchive> >::iterator iter = _archives.find(id);
if (iter != _archives.end())
{
archive = iter->second.get();
}
if (archive == NULL)
{
#ifdef _WIN32
const char _PATHD = '\\';
#elif defined(macintosh)
const char _PATHD = ':';
#else
const char _PATHD = '/';
#endif
std::string archiveName = dir+_PATHD+"archive.txp";
archive = new TXPArchive;
if (archive->openFile(archiveName) == false)
{
ReaderWriterTXPERROR("getArchive()") << "failed to load archive: \"" << archiveName << "\"" << std::endl;
return NULL;
}
if (archive->loadMaterials() == false)
{
ReaderWriterTXPERROR("getArchive()") << "failed to load materials from archive: \"" << archiveName << "\"" << std::endl;
return NULL;
}
if (archive->loadModels() == false)
{
ReaderWriterTXPERROR("getArchive()") << "failed to load models from archive: \"" << archiveName << "\"" << std::endl;
return NULL;
}
if (archive->loadLightAttributes() == false)
{
ReaderWriterTXPERROR("getArchive()") << "failed to load light attributes from archive: \"" << archiveName << "\"" << std::endl;
return NULL;
}
archive->setId(id);
_archives[id] = archive;
}
return archive;
}
osgDB::RegisterReaderWriterProxy<ReaderWriterTXP> g_txpReaderWriterProxy;

View File

@@ -1,53 +1,37 @@
/*****************************************************************************
* Reader for Terrex TerraPage File format for OpenSceneGraph Library
*
* Copyright (C) 2002 Boris Bralo All Rights Reserved.
*
* based on code from Scene Graph Library:
* Copyright (C) Bryan Walsh All Rights Reserved.
* and Terrex
* Copyright Terrain Experts Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
#ifndef READER_WRITER_TXP_H
#define READER_WRITER_TXP_H
#ifndef __READERWRITER_TXP_H_
#define __READERWRITER_TXP_H_
#include "trpage_sys.h"
#include <osg/Object>
#include <osg/Node>
#include <osgDB/Registry>
#include <osgDB/FileNameUtils>
#include <osg/Referenced>
#include <map>
namespace txp
{
class TXPArchive;
class ReaderWriterTXP : public osgDB::ReaderWriter
{
public:
virtual const char* className() { return "TXP Reader/Writer"; }
class ReaderWriterTXP : public osgDB::ReaderWriter
{
public:
virtual const char* className() { return "TXP Reader/Writer"; }
virtual bool acceptsExtension(const std::string& extension)
{
return osgDB::equalCaseInsensitive(extension,"txp");
}
virtual bool acceptsExtension(const std::string& extension)
{
return osgDB::equalCaseInsensitive(extension,"txp");
}
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*);
virtual ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*);
};
protected:
TXPArchive *getArchive(int id, const std::string&);
std::map< int,osg::ref_ptr<TXPArchive> > _archives;
static int _archiveId;
};
} // namespace
#endif
#endif // __READERWRITER_TXP_H_

View File

@@ -0,0 +1,598 @@
#include <osg/Notify>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/AlphaFunc>
#include <osg/Group>
#include <osg/Image>
#include <osg/Texture2D>
#include <osg/Material>
#include <osg/TexEnv>
#include <osg/CullFace>
#include <osg/Light>
#include <osg/StateSet>
#include <osg/Point>
#include <osg/BlendFunc>
#include <osgDB/FileUtils>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgSim/Sector>
#include <osgSim/LightPoint>
#include <osgSim/LightPointNode>
#include <osgSim/BlinkSequence>
#include <iostream>
#include "TXPArchive.h"
#include "TXPParser.h"
using namespace txp;
#define TXPArchiveERROR(s) osg::notify(osg::NOTICE) << "txp::TXPArchive::" << (s) << " error: "
TXPArchive::TXPArchive():
trpgr_Archive(),
_id(-1),
_numLODs(0),
_swExtents(0.0,0.0),
_neExtents(0.0,0.0)
{
}
TXPArchive::~TXPArchive()
{
CloseFile();
}
bool TXPArchive::openFile(const std::string& archiveName)
{
std::string path = osgDB::getFilePath(archiveName);
std::string name = osgDB::getSimpleFileName(archiveName);
if(path.empty())
{
SetDirectory(".");
}
else
{
// push the path to the front of the list so that all subsequenct
// files get loaded relative to this if possible.
osgDB::getDataFilePathList().push_front(path);
SetDirectory(path.c_str());
}
if (!OpenFile(name.c_str()))
{
TXPArchiveERROR("openFile()") << "couldn't open archive: " << archiveName << std::endl;
return false;
}
if (!ReadHeader())
{
TXPArchiveERROR("openFile()") << "couldn't read header for archive: " << archiveName << std::endl;
return false;
}
const trpgHeader *header = GetHeader();
if (header)
{
header->GetNumLods(_numLODs);
header->GetExtents(_swExtents,_neExtents);
}
return true;
}
bool TXPArchive::loadMaterials()
{
trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable);
int numTextures;
texTable.GetNumTextures(numTextures);
_textures.resize(numTextures);
// these extra braces are workaroud for annoying bug in MSVC
// for( int i = ....) and i is visible outside the loop
{
for (int i=0; i < numTextures ; i++)
{
const trpgTexture *tex;
tex = texTable.GetTextureRef(i);
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if(mode == trpgTexture::External)
{
char texName[1024]; texName[0] = 0;
tex->GetName(texName,1023);
// Create a texture by name.
osg::ref_ptr<osg::Texture2D> osg_texture = new osg::Texture2D();
// Load Texture and Create Texture State
std::string filename = osgDB::getSimpleFileName(texName);
std::string path(getDir());
#ifdef _WIN32
const char _PATHD = '\\';
#elif defined(macintosh)
const char _PATHD = ':';
#else
const char _PATHD = '/';
#endif
if( path == "." )
path = "";
else
path += _PATHD ;
std::string theFile = path + filename ;
osg::Image* image = osgDB::readImageFile(theFile);
if (image)
{
osg_texture->setImage(image);
}
else
{
osg::notify(osg::WARN) << "TrPageArchive::LoadMaterials() error: "
<< "couldn't open image: " << filename << std::endl;
}
_textures[i] = osg_texture;
}
else if( mode == trpgTexture::Local )
{
_textures[i] = getLocalTexture(image_helper,tex);
}
else if( mode == trpgTexture::Template )
{
_textures[i] = 0L; //GetTemplateTexture(image_helper,0, tex);
}
else
{
_textures[i] = 0;
}
}
}
int numMaterials;
materialTable.GetNumMaterial(numMaterials);
{
_gstates.resize(numMaterials);
for (int i = 0; i < numMaterials; i++)
{
osg::StateSet* osg_state_set = new osg::StateSet;
const trpgMaterial *mat;
mat = materialTable.GetMaterialRef(0,i);
// Set texture
int numMatTex;
mat->GetNumTexture(numMatTex);
// TODO : multitextuting
// also note that multitexturing in terrapage can came from two sides
// - multiple textures per material, and multiple materials per geometry
// Note: Only in theory. The only type you'll encounter is multiple
// materials per polygon.
if( numMatTex )
{
osg::Material *osg_material = new osg::Material;
float64 alpha;
mat->GetAlpha(alpha);
trpgColor color;
mat->GetAmbient(color);
osg_material->setAmbient( osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
mat->GetDiffuse(color);
osg_material->setDiffuse(osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
mat->GetSpecular(color);
osg_material->setSpecular(osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
mat->GetEmission(color);
osg_material->setEmission(osg::Material::FRONT_AND_BACK ,
osg::Vec4(color.red, color.green, color.blue, alpha));
float64 shinines;
mat->GetShininess(shinines);
osg_material->setShininess(osg::Material::FRONT_AND_BACK , (float)shinines);
osg_material->setAlpha(osg::Material::FRONT_AND_BACK ,(float)alpha);
osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
if( alpha < 1.0f )
{
osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);
osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
int alphaFunc;
mat->GetAlphaFunc(alphaFunc);
if( alphaFunc>=GL_NEVER && alphaFunc<=GL_ALWAYS)
{
float64 ref;
mat->GetAlphaRef(ref);
osg::AlphaFunc *osg_alpha_func = new osg::AlphaFunc;
osg_alpha_func->setFunction((osg::AlphaFunc::ComparisonFunction)alphaFunc,(float)ref);
osg_state_set->setAttributeAndModes(osg_alpha_func, osg::StateAttribute::ON);
}
for (int ntex = 0; ntex < numMatTex; ntex ++ )
{
int texId;
trpgTextureEnv texEnv;
mat->GetTexture(ntex,texId,texEnv);
// Set up texture environment
osg::TexEnv *osg_texenv = new osg::TexEnv();
int32 te_mode;
texEnv.GetEnvMode(te_mode);
switch( te_mode )
{
case trpgTextureEnv::Alpha :
osg_texenv->setMode(osg::TexEnv::REPLACE);
break;
case trpgTextureEnv::Decal:
osg_texenv->setMode(osg::TexEnv::DECAL);
break;
case trpgTextureEnv::Blend :
osg_texenv->setMode(osg::TexEnv::BLEND);
break;
case trpgTextureEnv::Modulate :
osg_texenv->setMode(osg::TexEnv::MODULATE);
break;
}
osg_state_set->setTextureAttribute(ntex,osg_texenv);
int wrap_s, wrap_t;
texEnv.GetWrap(wrap_s, wrap_t);
osg::Texture2D* osg_texture = _textures[texId].get();
if(osg_texture)
{
osg_texture->setWrap(osg::Texture2D::WRAP_S, wrap_s == trpgTextureEnv::Repeat ? osg::Texture2D::REPEAT: osg::Texture2D::CLAMP );
osg_texture->setWrap(osg::Texture2D::WRAP_T, wrap_t == trpgTextureEnv::Repeat ? osg::Texture2D::REPEAT: osg::Texture2D::CLAMP );
// -----------
// Min filter
// -----------
int32 minFilter;
texEnv.GetMinFilter(minFilter);
switch (minFilter)
{
case trpgTextureEnv::Point:
case trpgTextureEnv::Nearest:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
break;
case trpgTextureEnv::Linear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
break;
case trpgTextureEnv::MipmapPoint:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_NEAREST);
break;
case trpgTextureEnv::MipmapLinear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_LINEAR);
break;
case trpgTextureEnv::MipmapBilinear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
break;
case trpgTextureEnv::MipmapTrilinear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR);
break;
default:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
break;
}
// -----------
// Mag filter
// -----------
int32 magFilter;
texEnv.GetMagFilter(magFilter);
switch (magFilter)
{
case trpgTextureEnv::Point:
case trpgTextureEnv::Nearest:
osg_texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
break;
case trpgTextureEnv::Linear:
default:
osg_texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
break;
}
// pass on to the stateset.
osg_state_set->setTextureAttributeAndModes(ntex,osg_texture, osg::StateAttribute::ON);
if(osg_texture->getImage() && osg_texture->getImage()->isImageTranslucent())
{
osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);
osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}
}
}
int cullMode;
mat->GetCullMode(cullMode);
// Culling mode in txp means opposite from osg i.e. Front-> show front face
if( cullMode != trpgMaterial::FrontAndBack)
{
osg::CullFace* cull_face = new osg::CullFace;
switch (cullMode)
{
case trpgMaterial::Front:
cull_face->setMode(osg::CullFace::BACK);
break;
case trpgMaterial::Back:
cull_face->setMode(osg::CullFace::FRONT);
break;
}
osg_state_set->setAttributeAndModes(cull_face, osg::StateAttribute::ON);
}
}
_gstates[i] = osg_state_set;
}
}
return true;
}
bool TXPArchive::loadModels()
{
int numModel;
modelTable.GetNumModels(numModel);
// Iterate over the models
for (int i=0; i< numModel; i++)
{
trpgModel *mod = modelTable.GetModelRef(i);
int type;
mod->GetType(type);
// Only dealing with external models currently
if (type == trpgModel::External)
{
char name[1024];
mod->GetName(name,1023);
// Load the model. It's probably not TerraPage
osg::Node *osg_model = osgDB::readNodeFile(name);
if (!osg_model)
{
osg::notify(osg::WARN) << "TrPageArchive::LoadModels() error: "
<< "failed to load model: "
<< name << std::endl;
}
// Do this even if it's NULL
_models.push_back(osg_model);
}
/*
else
{
trpgMemReadBuffer buf(GetEndian());
mod->Read(buf);
Group *osg_model = parse->ParseScene(buf, m_gstates , m_models);
m_models.push_back(osg_model);
}
*/
}
return true;
}
bool TXPArchive::loadLightAttributes()
{
int num;
lightTable.GetNumLightAttrs(num);
for ( int attr_num = 0; attr_num < num; attr_num++ )
{
trpgLightAttr* ref = const_cast<trpgLightAttr*>(lightTable.GetLightAttrRef(attr_num));
osgSim::LightPointNode* osgLight = new osgSim::LightPointNode();
osg::Point* osgPoint = new osg::Point();
osgSim::LightPoint lp ;
lp._on = true;
trpgColor col;
ref->GetFrontColor(col);
lp._color = osg::Vec4(col.red, col.green,col.blue, 1.0);
float64 inten;
ref->GetFrontIntensity(inten);
lp._intensity = inten;
trpgLightAttr::PerformerAttr perfAttr;
ref->GetPerformerAttr(perfAttr);
// point part
//osgPoint->setSize(perfAttr.actualSize);
osgPoint->setSize(5);
osgPoint->setMaxSize(perfAttr.maxPixelSize);
osgPoint->setMinSize(perfAttr.minPixelSize);
osgPoint->setFadeThresholdSize(perfAttr.transparentFallofExp);
//numbers that are going to appear are "experimental"
osgPoint->setDistanceAttenuation(osg::Vec3(0.0001, 0.0005, 0.00000025));
// osgPoint->setDistanceAttenuation(osg::Vec3(1.0, 0.0, 1.0));
osg::StateSet* stateSet = new osg::StateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON);
stateSet->setAttributeAndModes(osgPoint, osg::StateAttribute::ON );
stateSet->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::ON);
osgLight->setMaxPixelSize(perfAttr.maxPixelSize);
osgLight->setMinPixelSize(perfAttr.minPixelSize);
// float64 clamp;
// ref->GetPerformerTpClamp(clamp);
// osgLight->setMaxVisibleDistance2(clamp);
trpg3dPoint normal;
ref->GetNormal(normal);
// lp._radius = clamp;
trpgLightAttr::LightDirectionality direc;
ref->GetDirectionality(direc);
if( direc == trpgLightAttr::trpg_Unidirectional)
{
osgSim::AzimElevationSector* sec = new osgSim::AzimElevationSector();
float64 tmp;
ref->GetHLobeAngle(tmp);
float64 tmpfade;
ref->GetLobeFalloff(tmpfade);
sec->setAzimuthRange(-tmp/2.0,tmp/2.0,tmpfade);
ref->GetVLobeAngle(tmp);
sec->setElevationRange(0,tmp, tmpfade);
lp._sector = sec;
osgLight->addLightPoint(lp);
}
else if( direc == trpgLightAttr::trpg_Bidirectional )
{
osgSim::AzimElevationSector* front = new osgSim::AzimElevationSector();
float64 tmp;
ref->GetHLobeAngle(tmp);
float64 tmpfade;
ref->GetLobeFalloff(tmpfade);
front->setAzimuthRange(-tmp/2.0,tmp/2.0,tmpfade);
ref->GetVLobeAngle(tmp);
front->setElevationRange(0,tmp, tmpfade);
lp._sector = front;
osgLight->addLightPoint(lp);
osgSim::AzimElevationSector* back = new osgSim::AzimElevationSector();
back->setAzimuthRange(osg::PI-tmp/2.0,osg::PI+tmp/2.0,tmpfade);
back->setElevationRange(0,tmp, tmpfade);
lp._sector = back;
osgLight->addLightPoint(lp);
}
else{
osgLight->addLightPoint(lp);
}
addLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z));
}
return true;
}
void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att)
{
DefferedLightAttribute la;
la.lightPoint = lpn;
la.fallback = fallback;
la.attitude = att;
_lights.push_back(la);
}
bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info)
{
info.minRange = 0.0;
info.maxRange = 0.0;
info.radius = 0.f;
info.center.set(0.f,0.f,0.f);
info.bbox.set(0.f,0.f,0.f,0.f,0.f,0.f);
const trpgHeader *header = GetHeader();
const trpgTileTable *tileTable = GetTileTable();
if (header && tileTable)
{
header->GetLodRange(lod,info.maxRange);
header->GetLodRange(lod+1,info.minRange);
trpg2dPoint sw,ne;
header->GetExtents(sw,ne);
trpg2dPoint size;
header->GetTileSize(lod,size);
trpgwAppAddress addr;
float minz = 0.f;
float maxz = 0.f;
tileTable->GetTile(x,y,lod,addr,minz,maxz);
info.center.set(
sw.x+(x*size.x)+(size.x/2.f),
sw.y+(y*size.y)+(size.y/2.f),
(minz+maxz)/2.f
);
info.bbox.set(
osg::Vec3(
info.center.x()-(size.x/2.f),
info.center.y()-(size.y/2.f),
minz
),
osg::Vec3(
info.center.x()+(size.x/2.f),
info.center.y()+(size.y/2.f),
maxz
)
);
info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length();
return true;
}
return false;
}
osg::Group* TXPArchive::getTileContent(int x, int y, int lod)
{
if (_parser.get() == 0)
{
_parser = new TXPParser();
_parser->setArchive(this);
}
trpgMemReadBuffer buf(GetEndian());
if (!ReadTile(x,y,lod,buf))
{
return NULL;
}
osg::Group *tileGroup = _parser->parseScene(buf,_gstates,_models);
return tileGroup;
}
osg::PagedLOD* TXPArchive::getPagedLOD(int x, int y, int lod)
{
TileMap::iterator itr = _tileMap.find(TileTriple(x,y,lod));
if (itr!=_tileMap.end()) return itr->second.get();
else return 0;
}
void TXPArchive::insertPagedLOD(int x, int y, int lod, osg::PagedLOD* pagedLod)
{
_tileMap[TileTriple(x,y,lod)]=pagedLod;
}
void TXPArchive::removePagedLOD(int x, int y, int lod)
{
TileMap::iterator itr = _tileMap.find(TileTriple(x,y,lod));
if (itr!=_tileMap.end()) return _tileMap.erase(itr);
}
void TXPArchive::prunePagedLOD()
{
for(TileMap::iterator itr = _tileMap.begin();
itr!=_tileMap.end();
++itr)
{
if (itr->second.valid() && itr->second->referenceCount()==1)
{
TileMap::iterator eitr = itr;
--itr;
_tileMap.erase(eitr);
}
}
}

View File

@@ -0,0 +1,149 @@
#ifndef __TXPARCHIVE_H_
#define __TXPARCHIVE_H_
#include "trpage_sys.h"
#include "trpage_read.h"
#include <osg/Referenced>
#include <osg/BoundingBox>
#include <osg/Texture2D>
#include <osg/StateSet>
#include <osg/Node>
#include <osg/PagedLOD>
#include <osgSim/LightPointNode>
namespace txp
{
// this one handles different placement of light direction in osg and terrapage
struct DefferedLightAttribute
{
// light point at (0,0,0) looking in (0,0,0) direction
osg::ref_ptr<osgSim::LightPointNode> lightPoint;
osg::ref_ptr<osg::StateSet> fallback;
osg::Vec3 attitude;
};
class TXPParser;
class TXPArchive : public trpgr_Archive, public osg::Referenced
{
public:
// Constructor
TXPArchive();
// Opens the archive file and reads the header
bool openFile(const std::string& archiveName);
// Load the materials from the archve
bool loadMaterials();
// Load the models from the archive
bool loadModels();
// Load the light attribs from the archive
bool loadLightAttributes();
// Add light attrib
void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude);
// Get light attrib
inline DefferedLightAttribute& getLightAttribute(unsigned int i) { return _lights[i]; };
// Gets some informations for a given tile
struct TileInfo
{
osg::Vec3 center;
double minRange;
double maxRange;
float radius;
osg::BoundingBox bbox;
};
bool getTileInfo(int x, int y, int lod, TileInfo& info);
// Set/Get the archive id
inline void setId(int id) { _id = id; }
inline const int& getId() const { return _id; }
// Returns the number of LODs for this archive
inline const int& getNumLODs() const { return _numLODs; }
// Returns the extents of the archive
inline void getExtents(osg::BoundingBox& extents)
{
extents.set(_swExtents.x,_swExtents.y,0.0f,_neExtents.x,_neExtents.y,0.0f);
}
// Returns the origin of the archive
inline void getOrigin(double& x, double& y) { x=_swExtents.x; y=_swExtents.y; }
inline osg::Texture2D* getGlobalTexture(int id) { return _textures[id].get(); }
osg::Group* getTileContent(int x, int y, int lod);
osg::PagedLOD* getPagedLOD(int x, int y, int lod);
void insertPagedLOD(int x, int y, int lod, osg::PagedLOD* pagedLod);
void removePagedLOD(int x, int y, int lod);
void prunePagedLOD();
protected:
// Destructor
virtual ~TXPArchive();
// Id of the archive
int _id;
// Number of the LODs
int _numLODs;
// Archive extents
trpg2dPoint _swExtents;
trpg2dPoint _neExtents;
// Terra Page Parser
osg::ref_ptr<TXPParser> _parser;
// Textures
std::vector< osg::ref_ptr<osg::Texture2D> > _textures;
// States
std::vector< osg::ref_ptr<osg::StateSet> > _gstates;
// Models
std::vector< osg::ref_ptr<osg::Node> > _models;
// Light attributes vector
std::vector<DefferedLightAttribute> _lights;
struct TileTriple
{
TileTriple(int ax, int ay, int alod):
x(ax),y(ay),lod(alod) {}
int x,y,lod;
bool operator < (const TileTriple& rhs) const
{
if (x<rhs.x) return true;
if (x>rhs.x) return false;
if (y<rhs.y) return true;
if (y>rhs.y) return false;
if (lod<rhs.lod) return true;
if (lod>rhs.lod) return false;
return false;
}
};
typedef std::map< TileTriple, osg::ref_ptr<osg::PagedLOD> > TileMap;
TileMap _tileMap;
};
} // namespace
#endif // __TXPARCHIVE_H_

View File

@@ -0,0 +1,76 @@
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/WriteFile>
#include <osg/ref_ptr>
#include <iostream>
#include "TXPNode.h"
bool TXPNode_readLocalData(osg::Object &obj, osgDB::Input &fr);
bool TXPNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
osgDB::RegisterDotOsgWrapperProxy TXPNode_Proxy
(
new txp::TXPNode,
"TXPNode",
"Object Node TXPNode",
TXPNode_readLocalData,
TXPNode_writeLocalData
);
bool TXPNode_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
txp::TXPNode &txpNode = static_cast<txp::TXPNode &>(obj);
bool itrAdvanced = false;
if (fr.matchSequence("databaseOptions %s"))
{
txpNode.setOptions(fr[1].getStr());
fr += 2;
itrAdvanced = true;
}
if (fr.matchSequence("databaseName %s"))
{
txpNode.setArchiveName(fr[1].getStr());
txpNode.loadArchive();
fr += 2;
itrAdvanced = true;
}
return itrAdvanced;
}
class Dump2Osg : public osg::NodeVisitor
{
public:
Dump2Osg(osgDB::Output &fw) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _fw(fw) {};
virtual void apply(osg::Node& node)
{
_fw.writeObject(node);
osg::NodeVisitor::apply(node);
}
osgDB::Output &_fw;
};
bool TXPNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
const txp::TXPNode &txpNode = static_cast<const txp::TXPNode&>(obj);
if (!txpNode.getOptions().empty()) fw.indent() << "databaseOptions \"" << txpNode.getOptions() << "\""<<std::endl;
if (!txpNode.getArchiveName().empty()) fw.indent() << "archive name\"" << txpNode.getArchiveName() << "\"" << std::endl;
osg::Group* grp = const_cast<osg::Group*>(txpNode.asGroup());
Dump2Osg wrt(fw);
grp->accept(wrt);
return true;
}

View File

@@ -0,0 +1,226 @@
#include <osg/Notify>
#include <osg/BoundingBox>
#include <osg/PagedLOD>
#include <iostream>
#include <vector>
#include <algorithm>
#include "TXPNode.h"
using namespace txp;
#define TXPNodeERROR(s) osg::notify(osg::NOTICE) << "txp::TXPNode::" << (s) << " error: "
TXPNode::TXPNode():
osg::Group(),
_originX(0.0),
_originY(0.0)
{
setNumChildrenRequiringUpdateTraversal(1);
}
TXPNode::TXPNode(const TXPNode& txpNode,const osg::CopyOp& copyop):
osg::Group(txpNode,copyop),
_originX(txpNode._originX),
_originY(txpNode._originY)
{
setNumChildrenRequiringUpdateTraversal(1);
}
TXPNode::~TXPNode()
{
}
TXPArchive* TXPNode::getArchive()
{
return _archive.get();
}
void TXPNode::traverse(osg::NodeVisitor& nv)
{
switch(nv.getVisitorType())
{
case osg::NodeVisitor::CULL_VISITOR:
updateEye(nv);
break;
case osg::NodeVisitor::UPDATE_VISITOR:
updateSceneGraph();
break;
default:
break;
}
osg::Group::traverse(nv);
}
bool TXPNode::computeBound() const
{
if (getNumChildren() == 0)
{
_bsphere.init();
_bsphere.expandBy(_extents);
_bsphere_computed = true;
return true;
}
return osg::Group::computeBound();
}
void TXPNode::setArchiveName(const std::string& archiveName)
{
_archiveName = archiveName;
}
void TXPNode::setOptions(const std::string& options)
{
_options = options;
}
const std::string& TXPNode::getOptions() const
{
return _options;
}
const std::string& TXPNode::getArchiveName() const
{
return _archiveName;
}
bool TXPNode::loadArchive()
{
if (_archive.get())
{
TXPNodeERROR("loadArchive()") << "archive already open" << std::endl;
return false;
}
_archive = new TXPArchive;
if (_archive->openFile(_archiveName) == false)
{
TXPNodeERROR("loadArchive()") << "failed to load archive: \"" << _archiveName << "\"" << std::endl;
return false;
}
if (_archive->loadMaterials() == false)
{
TXPNodeERROR("loadArchive()") << "failed to load materials from archive: \"" << _archiveName << "\"" << std::endl;
return false;
}
if (_archive->loadModels() == false)
{
TXPNodeERROR("loadArchive()") << "failed to load models from archive: \"" << _archiveName << "\"" << std::endl;
return false;
}
if (_archive->loadLightAttributes() == false)
{
TXPNodeERROR("loadArchive()") << "failed to load light attributes from archive: \"" << _archiveName << "\"" << std::endl;
return false;
}
_archive->getOrigin(_originX,_originY);
_archive->getExtents(_extents);
int32 numLod;
_archive->GetHeader()->GetNumLods(numLod);
trpg2iPoint tileSize;
_archive->GetHeader()->GetLodSize(0,tileSize);
_pageManager = new TXPPageManager;
_pageManager->Init(_archive.get());
return true;
}
void TXPNode::updateEye(osg::NodeVisitor& nv)
{
trpg2dPoint loc;
loc.x = nv.getEyePoint().x() - _originX;
loc.y = nv.getEyePoint().y() - _originY;
if (_pageManager->SetLocation(loc))
{
trpgManagedTile *tile=NULL;
while((tile = _pageManager->GetNextUnload()))
{
int x,y,lod;
tile->GetTileLoc(x,y,lod);
if (lod == 0)
{
osg::Node* node = (osg::Node*)(tile->GetLocalData());
_nodesToRemove.push_back(node);
//osg::notify(osg::NOTICE) << "Tile unload: " << x << " " << y << " " << lod << std::endl;
}
_pageManager->AckUnload();
}
while ((tile = _pageManager->GetNextLoad()))
{
int x,y,lod;
tile->GetTileLoc(x,y,lod);
if (lod==0)
{
osg::Node* node = addPagedLODTile(x,y,lod);
tile->SetLocalData(node);
//osg::notify(osg::NOTICE) << "Tile load: " << x << " " << y << " " << lod << std::endl;
}
_pageManager->AckLoad();
}
}
}
osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod)
{
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\tile%d_%dx%d_%d.txp",_archive->getDir(),lod,x,y,_archive->getId());
TXPArchive::TileInfo info;
_archive->getTileInfo(x,y,lod,info);
osg::PagedLOD* pagedLOD = new osg::PagedLOD;
pagedLOD->setFileName(0,pagedLODfile);
pagedLOD->setRange(0,0.0,info.maxRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
_nodesToAdd.push_back(pagedLOD);
_archive->insertPagedLOD(x,y,lod,pagedLOD);
return pagedLOD;
}
void TXPNode::updateSceneGraph()
{
if (!_nodesToRemove.empty())
{
for (unsigned int i = 0; i < _nodesToRemove.size(); i++)
{
removeChild(_nodesToRemove[i]);
}
_nodesToRemove.clear();
}
if (!_nodesToAdd.empty())
{
for (unsigned int i = 0; i < _nodesToAdd.size(); i++)
{
addChild(_nodesToAdd[i]);
}
_nodesToAdd.clear();
}
_archive->prunePagedLOD();
}

View File

@@ -0,0 +1,66 @@
#ifndef __TXPNODE_H_
#define __TXPNODE_H_
#include <osg/Group>
#include <osg/NodeVisitor>
#include <osg/NodeCallback>
#include <osg/ref_ptr>
#include "TXPArchive.h"
#include "TXPPageManager.h"
namespace txp
{
class TXPNode : public osg::Group
{
public:
TXPNode();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
TXPNode(const TXPNode&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Node(txp, TXPNode);
virtual void traverse(osg::NodeVisitor& nv);
void setArchiveName(const std::string& archiveName);
void setOptions(const std::string& options);
const std::string& getOptions() const;
const std::string& getArchiveName() const;
bool loadArchive();
TXPArchive* getArchive();
protected:
virtual ~TXPNode();
virtual bool computeBound() const;
void updateEye(osg::NodeVisitor& nv);
void updateSceneGraph();
osg::Node* addPagedLODTile(int x, int y, int lod);
std::string _archiveName;
std::string _options;
osg::ref_ptr<TXPArchive> _archive;
osg::ref_ptr<TXPPageManager> _pageManager;
double _originX;
double _originY;
osg::BoundingBox _extents;
std::vector<osg::Node*> _nodesToAdd;
std::vector<osg::Node*> _nodesToRemove;
};
} // namespace
#endif // __TXPNODE_H_

View File

@@ -0,0 +1,11 @@
#include "TXPPageManager.h"
using namespace txp;
TXPPageManager::TXPPageManager():
trpgPageManager()
{
}
TXPPageManager::~TXPPageManager()
{
}

View File

@@ -0,0 +1,24 @@
#ifndef __TXPPAGEMANAGER_H_
#define __TXPPAGEMANAGER_H_
#include "trpage_sys.h"
#include "trpage_read.h"
#include "trpage_managers.h"
#include <osg/Referenced>
namespace txp
{
class TXPPageManager : public trpgPageManager, public osg::Referenced
{
public:
TXPPageManager();
protected:
virtual ~TXPPageManager();
};
} // namespace
#endif // __TXPPAGEMANAGER_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
#ifndef __TXPPARSER_H_
#define __TXPPARSER_H_
#include <osg/Referenced>
#include <osg/Texture2D>
#include <osg/StateSet>
#include <osg/Node>
#include <stack>
#include "trpage_read.h"
namespace txp
{
// 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);
// 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
class GeodeGroup : public osg::Group
{
public:
GeodeGroup() : osg::Group(), _geode(NULL) {};
GeodeGroup(const GeodeGroup& gg,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
osg::Group(gg, copyop), _geode(gg._geode) {};
META_Node(txp, GeodeGroup);
osg::Geode* getGeode()
{
if (_geode == 0)
{
_geode = new osg::Geode();
addChild(_geode);
}
return _geode;
}
protected:
osg::Geode* _geode;
};
class TXPArchive;
struct DefferedLightAttribute;
class TXPParser : public trpgSceneParser, public osg::Referenced
{
public:
TXPParser();
// Sets the archive to be parsed
inline void setArchive(TXPArchive* archive) { _archive = archive; }
// Scene parser
osg::Group *parseScene(
trpgReadBuffer &buf,
std::vector<osg::ref_ptr<osg::StateSet> > &materials,
std::vector<osg::ref_ptr<osg::Node> > &models);
// Returns the current Top Group
inline osg::Group* getCurrTop() { return _currentTop ? _currentTop : _root.get(); }
// Sets the group as potentional tile group
inline void setPotentionalTileGroup(osg::Group* grp) { _tileGroups[grp] = 1; }
// Return the current material list (passed in to ParseScene())
inline 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 &_localMaterials; }
// Load local materials
void loadLocalMaterials();
// Return the current model list
std::vector<osg::ref_ptr<osg::Node> >* getModels() { return _models; }
// Return a reference to the tile header (after a tile has been read)
inline trpgTileHeader *getTileHeaderRef() { return &_tileHeader; }
// Returns true if we are under billboard subgraph
inline const bool underBillboardSubgraph() const { return _underBillboardSubgraph; }
// Sets if we are under billboard subgraph
inline void setUnderBillboardSubgraph(bool b) { _underBillboardSubgraph = b; }
// TXP Billboard info
struct TXPBillboardInfo
{
int type;
int mode;
trpg3dPoint center;
trpg3dPoint axis;
};
// Sets info for the last billboard parsed
inline void setLastBillboardInfo(TXPBillboardInfo& info) { _lastBillboardInfo = info; }
// Gets info for the last billboard parsed
inline void getLastBillboardInfo(TXPBillboardInfo& info) { info = _lastBillboardInfo; }
// Gets light attrib
DefferedLightAttribute& getLightAttribute(int ix);
// Returns if we are under layer subgraph
inline const bool underLayerSubgraph() const { return _underLayerSubgraph; }
// Sets if we are under layer subgraph
inline void setUnderLayerSubgraph(bool b) {_underLayerSubgraph = b; }
// Set the current layer geode
inline void setLayerGeode(osg::Geode* layer) { _layerGeode = layer; }
// Returns the current layer geode
inline osg::Geode* getLayerGeode() const { return _layerGeode; }
protected:
virtual ~TXPParser();
// Removes any empty groups and LODs
void removeEmptyGroups();
// Called on start children
bool StartChildren(void *);
// Called on end children
bool EndChildren(void *);
// THE archive
TXPArchive *_archive;
// Current parent
osg::Group* _currentTop;
// The root of the til
osg::ref_ptr<osg::Group> _root;
// Parents list
std::stack<osg::Group*> _parents;
// Potentional Tile groups
std::map<osg::Group*,int> _tileGroups;
// Replace the tile lod to regular group
void replaceTileLod(osg::Group*);
// Materials
std::vector<osg::ref_ptr<osg::StateSet> >* _materials;
// Local materials
std::vector<osg::ref_ptr<osg::StateSet> > _localMaterials;
// Model list
std::vector<osg::ref_ptr<osg::Node> >* _models;
// Tile header
trpgTileHeader _tileHeader;
// true if we are under billboard subgraph
bool _underBillboardSubgraph;
// Number of levels below the billboard node
int _numBillboardLevels;
// Last billboard we parsed
TXPBillboardInfo _lastBillboardInfo;
// true if we are under layer subgraph
bool _underLayerSubgraph;
// Numbers of levels below layer subgraph
int _numLayerLevels;
// Our Layer Geode
osg::Geode* _layerGeode;
// TEMP
osg::Geode* createBoundingBox(int x,int y, int lod);
};
//! callback functions for various scene graph elements
//----------------------------------------------------------------------------
class geomRead : public trpgr_Callback {
public:
geomRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class groupRead : public trpgr_Callback {
public:
groupRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class lodRead : public trpgr_Callback {
public:
lodRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class tileHeaderRead : public trpgr_Callback {
public:
tileHeaderRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class modelRefRead : public trpgr_Callback {
public:
modelRefRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class billboardRead : public trpgr_Callback {
public:
billboardRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class lightRead: public trpgr_Callback {
public:
lightRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
//----------------------------------------------------------------------------
class layerRead: public trpgr_Callback {
public:
layerRead(TXPParser *in_parse) : _parse(in_parse) {};
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TXPParser *_parse;
};
} // namespace
#endif // __TXPPARSER_H_

View File

@@ -0,0 +1,69 @@
#include "TXPSeamLOD.h"
#include "TXPArchive.h"
#include "TXPTileNode.h"
using namespace txp;
TXPSeamLOD::TXPSeamLOD() :
Group()
{
_neighbourTileX =
_neighbourTileY =
_neighbourTileLOD = -1;
_tileRef = 0;
_txpNode = 0;
_archive = 0;
}
TXPSeamLOD::TXPSeamLOD(int x, int y, int lod, const osg::Vec3& center, float dmin, float dmid, float dmax) :
Group()
{
_neighbourTileX = x;
_neighbourTileY = y;
_neighbourTileLOD = lod;
_center = center;
_min = dmin;
_mid = dmid;
_max = dmax;
_txpNode = 0;
_tileRef = 0;
_archive = 0;
}
TXPSeamLOD::TXPSeamLOD(const TXPSeamLOD& ttg,const osg::CopyOp& copyop) :
Group(ttg,copyop)
{
_neighbourTileX = ttg._neighbourTileX;
_neighbourTileY = ttg._neighbourTileY;
_neighbourTileLOD = ttg._neighbourTileLOD;
_tileRef = ttg._tileRef;
_archive = ttg._archive;
}
void TXPSeamLOD::traverse(osg::NodeVisitor& nv)
{
if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR && _children.size()==2)
{
float distance = nv.getDistanceToEyePoint(_center,true);
if (distance<_mid)
{
// cap the lod's that can be used to what is available in the adjacent PagedLOD.
osg::PagedLOD* pagedLOD = _archive->getPagedLOD(_neighbourTileX,_neighbourTileY, _neighbourTileLOD);
if (pagedLOD && pagedLOD->getNumChildren()>1) getChild(1)->accept(nv);
else getChild(0)->accept(nv);
}
else
{
getChild(0)->accept(nv);
}
}
else
{
Group::traverse(nv);
}
}

View File

@@ -0,0 +1,57 @@
#ifndef TXPSeamLOD_H
#define TXPSeamLOD_H
#include <osg/LOD>
#include <map>
#include <string>
#include "TXPTileNode.h"
#include "TXPArchive.h"
namespace txp
{
class TXPSeamLOD : public osg::Group
{
public:
TXPSeamLOD();
TXPSeamLOD(int x, int y, int lod, const osg::Vec3& center, float dmin, float dmid, float dmax);
TXPSeamLOD(const TXPSeamLOD&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Node(txp, TXPSeamLOD);
virtual void traverse(osg::NodeVisitor& nv);
void setTileRef(bool* b)
{
_tileRef = b;
}
void setTxpNode(TXPTileNode* txpNode) { _txpNode = txpNode; }
TXPTileNode* getTxpNode() const { return _txpNode; }
void setArchive(TXPArchive* ar) { _archive = ar; }
protected:
int _neighbourTileX;
int _neighbourTileY;
int _neighbourTileLOD;
osg::Vec3 _center;
float _min;
float _mid;
float _max;
bool* _tileRef;
TXPTileNode* _txpNode;
TXPArchive* _archive;
};
}
#endif

View File

@@ -0,0 +1,216 @@
#include <osg/PagedLOD>
#include "TXPTileNode.h"
#include "TXPArchive.h"
#include "TXPSeamLOD.h"
using namespace txp;
class PrintVisitor : public osg::NodeVisitor
{
public:
PrintVisitor():NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN)
{
_indent = 0;
_step = 4;
}
inline void moveIn() { _indent += _step; }
inline void moveOut() { _indent -= _step; }
inline void writeIndent()
{
for(int i=0;i<_indent;++i) std::cout << " ";
}
virtual void apply(osg::Node& node)
{
moveIn();
writeIndent(); std::cout << node.className() <<std::endl;
traverse(node);
moveOut();
}
virtual void apply(osg::Geode& node) { apply((osg::Node&)node); }
virtual void apply(osg::Billboard& node) { apply((osg::Geode&)node); }
virtual void apply(osg::LightSource& node) { apply((osg::Group&)node); }
virtual void apply(osg::ClipNode& node) { apply((osg::Group&)node); }
virtual void apply(osg::Group& node) { apply((osg::Node&)node); }
virtual void apply(osg::Transform& node) { apply((osg::Group&)node); }
virtual void apply(osg::Projection& node) { apply((osg::Group&)node); }
virtual void apply(osg::Switch& node) { apply((osg::Group&)node); }
virtual void apply(osg::LOD& lod)
{
moveIn();
writeIndent(); std::cout << lod.className() <<std::endl;
writeIndent(); std::cout << "center="<<lod.getCenter()<<std::endl;
for(unsigned int i=0;i<lod.getNumChildren();++i)
{
writeIndent(); std::cout << "child min="<<lod.getMinRange(i)<<" max="<<lod.getMaxRange(i)<<std::endl;
lod.getChild(i)->accept(*this);
}
moveOut();
}
virtual void apply(osg::Impostor& node) { apply((osg::LOD&)node); }
protected:
int _indent;
int _step;
};
TXPTileNode::TXPTileNode():
osg::Group(),
_archive(0)
{
}
TXPTileNode::TXPTileNode(const TXPTileNode& tn,const osg::CopyOp& copyop):
osg::Group(tn,copyop),
_archive(tn._archive)
{
}
TXPTileNode::~TXPTileNode()
{
}
void TXPTileNode::setArchive(TXPArchive* archive)
{
_archive = archive;
}
osg::Node* TXPTileNode::seamReplacement(osg::Node* child,int x, int y, int level, TXPArchive::TileInfo& info)
{
osg::Group* group = child->asGroup();
if (group)
{
if (group->getNumChildren()==2)
{
osg::LOD* lod1 = dynamic_cast<osg::LOD*>(group->getChild(0));
osg::LOD* lod2 = dynamic_cast<osg::LOD*>(group->getChild(1));
if (lod1 && lod1->getNumChildren()==1 &&
lod2 && lod2->getNumChildren()==1)
{
osg::Vec3 delta = lod1->getCenter()-info.center;
if (fabs(delta.x())>fabs(delta.y()))
{
if (delta.x()<0.0)
{
// west tile
--x;
}
else
{
// east tile
x++;
}
}
else
{
if (delta.y()<0.0)
{
// south tile
--y;
}
else
{
// north tile
++y;
}
}
TXPSeamLOD* seam = new TXPSeamLOD(x,y,level,lod1->getCenter(),lod2->getMinRange(0),lod2->getMaxRange(0),lod1->getMaxRange(0));
seam->setArchive(_archive);
seam->addChild(lod1->getChild(0));
seam->addChild(lod2->getChild(0));
return seam;
}
}
}
return child;
}
bool TXPTileNode::loadTile(int x, int y, int lod)
{
if (_archive == 0) return false;
TXPArchive::TileInfo info;
bool validTile = _archive->getTileInfo(x,y,lod,info);
int numLods = _archive->getNumLODs();
if (validTile)
{
osg::Group* tileGroup = _archive->getTileContent(x,y,lod);
// if group has only one child, then simply use its child.
while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())
{
tileGroup = tileGroup->getChild(0)->asGroup();
}
if (tileGroup->getNumChildren()==5)
{
// candidate for being a Tile with seams.
// std::cout<<"------- Seams candidate ------ "<<std::endl;
// std::cout<<" info.center = "<<info.center<<std::endl;
// PrintVisitor pv;
// tileGroup->accept(pv);
for(unsigned int i=1;i<tileGroup->getNumChildren();++i)
{
osg::Node* child = tileGroup->getChild(i);
osg::Node* replacement = seamReplacement(child,x,y,lod,info);
if (child!=replacement)
{
tileGroup->replaceChild(child,replacement);
}
}
}
if (lod < (numLods-1))
{
char pagedLODfile[1024];
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
_archive->getDir(),
lod,
x,
y,
_archive->getId()
);
osg::PagedLOD* pagedLOD = new osg::PagedLOD;
// not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
pagedLOD->addChild(tileGroup,info.minRange,osg::maximum(info.maxRange,1e7));
pagedLOD->setFileName(1,pagedLODfile);
pagedLOD->setRange(1,0,info.minRange);
pagedLOD->setCenter(info.center);
pagedLOD->setRadius(info.radius);
pagedLOD->setNumChildrenThatCannotBeExpired(1);
_archive->insertPagedLOD(x,y,lod,pagedLOD);
addChild(pagedLOD);
}
else
{
addChild(tileGroup);
}
return true;
}
return false;
}

View File

@@ -0,0 +1,34 @@
#ifndef __TXPTILENODE_H_
#define __TXPTILENODE_H_
#include <osg/Group>
#include "TXPArchive.h"
namespace txp
{
class TXPArchive;
class TXPTileNode : public osg::Group
{
public:
TXPTileNode();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
TXPTileNode(const TXPTileNode&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Node(txp, TXPTileNode);
void setArchive(TXPArchive* archive);
bool loadTile(int x, int y, int lod);
osg::Node* seamReplacement(osg::Node* child,int x, int y, int level, TXPArchive::TileInfo& info);
protected:
virtual ~TXPTileNode();
TXPArchive* _archive;
};
} // namespace
#endif // __TXPTILENODE_H_

View File

@@ -1,246 +0,0 @@
#include "TerrapageNode.h"
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
using namespace osg;
namespace txp
{
osg::ref_ptr<TrPageArchive> TerrapageNode::_archive = NULL;
TerrapageNode::TerrapageNode():
_pageManager(0)
{
setNumChildrenRequiringUpdateTraversal(1);
_dbLoaded = false;
}
TerrapageNode::TerrapageNode(const TerrapageNode& pager,const osg::CopyOp&):
osg::Group(),
_databaseDimensions(pager._databaseDimensions),
_databaseName(pager._databaseName),
_databaseOptions(pager._databaseOptions),
_pageManager(0),
_lastRecordEyePoint(pager._lastRecordEyePoint)
{
setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
_dbLoaded = pager._dbLoaded;
}
TerrapageNode::~TerrapageNode()
{
// will the page manger delete the archive?
delete _pageManager;
}
void TerrapageNode::traverse(osg::NodeVisitor& nv)
{
if (_pageManager)
{
if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
{
updateSceneGraph();
}
else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
{
updateEyePoint(nv.getEyePoint());
}
}
Group::traverse(nv);
}
bool TerrapageNode::loadDatabase()
{
std::string name = osgDB::getSimpleFileName(_databaseName);
// Here we load subtiles for a tile
if (strncmp(name.c_str(),"subtiles",8)==0)
{
std::string path = osgDB::getFilePath(_databaseName);
_databaseName = path+"\\archive.txp";
int lod;
int x;
int y;
sscanf(name.c_str(),"subtiles%d_%dx%d",&lod,&x,&y);
float64 range;
TerrapageNode::_archive->GetHeader()->GetLodRange(lod+1,range);
trpg2dPoint tileSize;
TerrapageNode::_archive->GetHeader()->GetTileSize(lod+1,tileSize);
trpg2dPoint sw;
trpg2dPoint ne;
TerrapageNode::_archive->GetHeader()->GetExtents(sw,ne);
for (int ix = 0; ix < 2; ix++)
for (int iy = 0; iy < 2; iy++)
{
int tileX = x*2+ix;
int tileY = y*2+iy;
int tileLOD = lod+1;
int parentID;
addChild(TerrapageNode::_archive->LoadTile(tileX,tileY,tileLOD,parentID));
}
//std::cout << "subtiles paged in: " << x << " " << y << " " << lod << std::endl;
return true;
}
// Open the TXP database
TrPageArchive *txpArchive = new TrPageArchive();
if (!txpArchive->OpenFile(_databaseName.c_str()))
{
osg::notify(osg::WARN)<<"Couldn't load TerraPage archive "<<_databaseName<<std::endl;
return false;
}
// Note: Should be checking the return values
txpArchive->LoadMaterials();
// Note: Should be checking the return values
txpArchive->LoadModels();
// Note: Should be checking the return values
txpArchive->LoadLightAttributes();
if (TerrapageNode::_archive == NULL)
{
TerrapageNode::_archive = new TrPageArchive();
if (!TerrapageNode::_archive->OpenFile(_databaseName.c_str()))
{
osg::notify(osg::WARN)<<"Couldn't load interanal TerraPage archive "<<_databaseName<<std::endl;
TerrapageNode::_archive = NULL;
return false;
}
TerrapageNode::_archive->LoadMaterials();
TerrapageNode::_archive->LoadModels();
TerrapageNode::_archive->LoadLightAttributes();
}
// get the exents of the archive
const trpgHeader *head = txpArchive->GetHeader();
trpg2dPoint sw,ne;
head->GetExtents(sw,ne);
_databaseDimensions.set(sw.x,sw.y,0.0f,
ne.x,ne.y,0.0f);
// set up the options.
bool loadAll=false;
OSGPageManager::ThreadMode threadMode = OSGPageManager::ThreadFree;
if (!_databaseOptions.empty())
{
if (_databaseOptions.find("LoadAll")!=std::string::npos)
{
loadAll = true;
osg::notify(osg::INFO)<<"TerraPage archive : LoadAll selected"<<std::endl;
}
if (_databaseOptions.find("ThreadNone")!=std::string::npos)
{
threadMode = OSGPageManager::ThreadNone;
osg::notify(osg::INFO)<<"TerraPage archive : ThreadNone selected"<<std::endl;
}
if (_databaseOptions.find("ThreadFree")!=std::string::npos)
{
threadMode = OSGPageManager::ThreadFree;
osg::notify(osg::INFO)<<"TerraPage archive : ThreadFree selected"<<std::endl;
}
if (_databaseOptions.find("ThreadSync")!=std::string::npos)
{
threadMode = OSGPageManager::ThreadSync;
osg::notify(osg::INFO)<<"TerraPage archive : ThreadSync selected"<<std::endl;
}
}
if (loadAll)
{
// Load the whole scenegraph
osg::Node* node = txpArchive->LoadAllTiles();
if (!node) {
osg::notify(osg::WARN)<<"Couldn't load whole TerraPage archive "<<_databaseName<<std::endl;
return false;
}
// need to think about ref counting these..
delete txpArchive;
// add the loaded database into the scenegraph.
addChild(node);
} else {
_pageManager = new OSGPageManager(txpArchive);
if (threadMode!=OSGPageManager::ThreadNone)
{
ThreadID newThread;
_pageManager->StartThread(threadMode,newThread);
}
}
_dbLoaded = true;
return true;
}
void TerrapageNode::updateSceneGraph()
{
if (_pageManager)
{ _bsphere_computed = true;
if (_pageManager->GetThreadMode() == OSGPageManager::ThreadNone)
{
// we're in non-thread mode, load in the given number of tiles (maximum).
int numTile = 1;
_pageManager->UpdateNoThread(this,_lastRecordEyePoint.x(),_lastRecordEyePoint.y(),numTile);
}
else
{
// we're in ThreadFree mode, merge in whatever may be ready.
_pageManager->MergeUpdateThread(this);
}
}
}
void TerrapageNode::updateEyePoint(const osg::Vec3& eyepoint) const
{
if (_pageManager && (_pageManager->GetThreadMode() != OSGPageManager::ThreadNone))
{
_pageManager->UpdatePositionThread(eyepoint.x(),eyepoint.y());
}
_lastRecordEyePoint = eyepoint;
}
bool TerrapageNode::computeBound() const
{
if (_databaseDimensions.valid())
{
_bsphere.init();
_bsphere.expandBy(_databaseDimensions);
_bsphere_computed = true;
return true;
}
else
{
return Group::computeBound();
}
}
} // namespace txp

View File

@@ -1,64 +0,0 @@
//C++ header.
#ifndef TERRAPAGENODE_H
#define TERRAPAGENODE_H
#include "trPagePageManager.h"
#include <osg/Node>
#include <osg/BoundingBox>
namespace txp
{
class TrPageArchive;
class TerrapageNode : public osg::Group
{
public:
TerrapageNode();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
TerrapageNode(const TerrapageNode&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
META_Node(txp, TerrapageNode);
virtual void traverse(osg::NodeVisitor& nv);
bool loadDatabase();
void setDatabaseName(const std::string& name) { _databaseName = name; }
const std::string& getDatabaseName() const { return _databaseName; }
void setDatabaseOptions(const std::string& name) { _databaseOptions = name; }
const std::string& getDatabaseOptions() const { return _databaseOptions; }
void setDatabaseDimensions(const osg::BoundingBox& box) { _databaseDimensions = box; }
const osg::BoundingBox& getDatabaseDimensions() const { return _databaseDimensions; }
virtual void updateSceneGraph();
virtual void updateEyePoint(const osg::Vec3& eyepoint) const;
protected:
virtual ~TerrapageNode();
virtual bool computeBound() const;
osg::BoundingBox _databaseDimensions;
std::string _databaseName;
std::string _databaseOptions;
OSGPageManager* _pageManager;
mutable osg::Vec3 _lastRecordEyePoint;
static osg::ref_ptr<TrPageArchive> _archive;
bool _dbLoaded;
};
} // namespace txp
#endif

View File

@@ -1,665 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "TrPageArchive.h"
#include "TrPageParser.h"
#include <osg/AlphaFunc>
#include <osg/Group>
#include <osg/Image>
#include <osg/Texture2D>
#include <osg/Material>
#include <osg/TexEnv>
#include <osg/CullFace>
#include <osg/Light>
#include <osg/StateSet>
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <iostream>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/FileNameUtils>
#include <osgSim/Sector>
#include <osgSim/LightPoint>
#include <osgSim/LightPointNode>
#include <osgSim/BlinkSequence>
#include <osg/Point>
#include <osg/BlendFunc>
#include "trpage_geom.h"
#include "trpage_read.h"
#include "trpage_write.h"
#include "trpage_scene.h"
#include "trpage_managers.h"
using namespace txp;
using namespace osg;
// disable 'this' used in base pointer initilialization..
#if defined(WIN32) && !defined(__GNUC__)
#pragma warning( disable : 4355 )
#endif
TrPageArchive::TrPageArchive()
: trpgr_Archive()
, parse(new TrPageParser(this))
, buf(GetEndian())
{
}
TrPageArchive::~TrPageArchive()
{
}
bool TrPageArchive::OpenFile(const char* file)
{
m_alternate_path = osgDB::getFilePath(file);
std::string name = osgDB::getSimpleFileName(file);
if(m_alternate_path.empty())
SetDirectory(".");
else
{
// push the path to the front of the list so that all subsequenct
// files get loaded relative to this if possible.
osgDB::getDataFilePathList().push_front(m_alternate_path);
SetDirectory(m_alternate_path.c_str());
}
if (!trpgr_Archive::OpenFile(name.c_str()))
{
notify(WARN) << "TrPageArchive::OpenFile() error: "
<< "couldn't open archive: " << file << std::endl;
return false;
}
if (!ReadHeader())
{
notify(WARN) << "TrPageArchive::OpenFile() error: "
<< "couldn't read header for archive: " << file
<< std::endl;
return false;
}
// Set the max group ID here because it won't change
const trpgHeader *head = GetHeader();
int maxID;
head->GetMaxGroupID(maxID);
parse->SetMaxGroupID(maxID);
return true;
}
/* Calculate the center of the database (including Z)
*/
void TrPageArchive::GetCenter(Vec3 &center)
{
trpg2dPoint sw,ne;
const trpgHeader *head = GetHeader();
const trpgTileTable *tileTable = GetTileTable();
head->GetExtents(sw,ne);
trpg2dPoint tileSize;
head->GetTileSize(0,tileSize);
center[0] = (ne.x+sw.x)/2.0;
center[1] = (ne.y+sw.y)/2.0;
trpg2iPoint loc;
loc.x = int((center[0]-sw.x)/tileSize.x);
loc.y = int((center[1]-sw.y)/tileSize.y);
trpgwAppAddress foo;
float zmin,zmax;
tileTable->GetTile(loc.x, loc.y,0,foo,zmin,zmax);
center[2] = (zmin+zmax)/2.0;
}
// load textures and materials
// TODO : multitexturing
void TrPageArchive::LoadMaterials()
{
trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable);
int n_textures;
texTable.GetNumTextures(n_textures);
m_textures.resize(n_textures);
// these extra braces are workaroud for annoying bug in MSVC
// for( int i = ....) and i is visible outside the loop
{
for (int i=0; i < n_textures ; i++)
{
const trpgTexture *tex;
tex = texTable.GetTextureRef(i);
trpgTexture::ImageMode mode;
tex->GetImageMode(mode);
if(mode == trpgTexture::External)
{
char texName[1024]; texName[0] = 0;
tex->GetName(texName,1023);
// Create a texture by name.
ref_ptr<Texture2D> osg_texture = new Texture2D();
// Load Texture and Create Texture State
std::string filename = osgDB::getSimpleFileName(texName);
std::string path(getDir());
#ifdef _WIN32
const char _PATHD = '\\';
#elif defined(macintosh)
const char _PATHD = ':';
#else
const char _PATHD = '/';
#endif
if( path == "." )
path = "";
else
path += _PATHD ;
std::string theFile = path + filename ;
Image* image = osgDB::readImageFile(theFile);
if (image)
{
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,tex);
}
else if( mode == trpgTexture::Template )
{
m_textures[i] = 0L; //GetTemplateTexture(image_helper,0, tex);
}
else
{
m_textures[i] = 0;
}
}
}
int n_materials;
materialTable.GetNumMaterial(n_materials);
{
m_gstates.resize(n_materials);
for (int i = 0; i < n_materials; i++)
{
StateSet* osg_state_set = new StateSet;
const trpgMaterial *mat;
mat = materialTable.GetMaterialRef(0,i);
// Set texture
int numMatTex;
mat->GetNumTexture(numMatTex);
// TODO : multitextuting
// also note that multitexturing in terrapage can came from two sides
// - multiple textures per material, and multiple materials per geometry
// Note: Only in theory. The only type you'll encounter is multiple
// materials per polygon.
if( numMatTex )
{
Material *osg_material = new Material;
float64 alpha;
mat->GetAlpha(alpha);
trpgColor color;
mat->GetAmbient(color);
osg_material->setAmbient( Material::FRONT_AND_BACK ,
Vec4(color.red, color.green, color.blue, alpha));
mat->GetDiffuse(color);
osg_material->setDiffuse(Material::FRONT_AND_BACK ,
Vec4(color.red, color.green, color.blue, alpha));
mat->GetSpecular(color);
osg_material->setSpecular(Material::FRONT_AND_BACK ,
Vec4(color.red, color.green, color.blue, alpha));
mat->GetEmission(color);
osg_material->setEmission(Material::FRONT_AND_BACK ,
Vec4(color.red, color.green, color.blue, alpha));
float64 shinines;
mat->GetShininess(shinines);
osg_material->setShininess(Material::FRONT_AND_BACK , (float)shinines);
osg_material->setAlpha(Material::FRONT_AND_BACK ,(float)alpha);
osg_state_set->setAttributeAndModes(osg_material, StateAttribute::ON);
if( alpha < 1.0f )
{
osg_state_set->setMode(GL_BLEND,StateAttribute::ON);
osg_state_set->setRenderingHint(StateSet::TRANSPARENT_BIN);
}
int alphaFunc;
mat->GetAlphaFunc(alphaFunc);
if( alphaFunc>=GL_NEVER && alphaFunc<=GL_ALWAYS)
{
float64 ref;
mat->GetAlphaRef(ref);
AlphaFunc *osg_alpha_func = new AlphaFunc;
osg_alpha_func->setFunction((AlphaFunc::ComparisonFunction)alphaFunc,(float)ref);
osg_state_set->setAttributeAndModes(osg_alpha_func, StateAttribute::ON);
}
for (int ntex = 0; ntex < numMatTex; ntex ++ )
{
int texId;
trpgTextureEnv texEnv;
mat->GetTexture(ntex,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);
break;
}
osg_state_set->setTextureAttribute(ntex,osg_texenv);
int wrap_s, wrap_t;
texEnv.GetWrap(wrap_s, wrap_t);
Texture2D* osg_texture = m_textures[texId].get();
if(osg_texture)
{
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 );
// -----------
// Min filter
// -----------
int32 minFilter;
texEnv.GetMinFilter(minFilter);
switch (minFilter)
{
case trpgTextureEnv::Point:
case trpgTextureEnv::Nearest:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::NEAREST);
break;
case trpgTextureEnv::Linear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::LINEAR);
break;
case trpgTextureEnv::MipmapPoint:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::NEAREST_MIPMAP_NEAREST);
break;
case trpgTextureEnv::MipmapLinear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::NEAREST_MIPMAP_LINEAR);
break;
case trpgTextureEnv::MipmapBilinear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::LINEAR_MIPMAP_NEAREST);
break;
case trpgTextureEnv::MipmapTrilinear:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::LINEAR_MIPMAP_LINEAR);
break;
default:
osg_texture->setFilter(osg::Texture2D::MIN_FILTER, Texture2D::LINEAR);
break;
}
// -----------
// Mag filter
// -----------
int32 magFilter;
texEnv.GetMagFilter(magFilter);
switch (magFilter)
{
case trpgTextureEnv::Point:
case trpgTextureEnv::Nearest:
osg_texture->setFilter(osg::Texture2D::MAG_FILTER,Texture2D::NEAREST);
break;
case trpgTextureEnv::Linear:
default:
osg_texture->setFilter(osg::Texture2D::MAG_FILTER, Texture2D::LINEAR);
break;
}
// pass on to the stateset.
osg_state_set->setTextureAttributeAndModes(ntex,osg_texture, StateAttribute::ON);
if(osg_texture->getImage() && osg_texture->getImage()->isImageTranslucent())
{
osg_state_set->setMode(GL_BLEND,StateAttribute::ON);
osg_state_set->setRenderingHint(StateSet::TRANSPARENT_BIN);
}
}
}
int cullMode;
mat->GetCullMode(cullMode);
// Culling mode in txp means opposite from osg i.e. Front-> show front face
if( cullMode != trpgMaterial::FrontAndBack)
{
CullFace* cull_face = new CullFace;
switch (cullMode)
{
case trpgMaterial::Front:
cull_face->setMode(CullFace::BACK);
break;
case trpgMaterial::Back:
cull_face->setMode(CullFace::FRONT);
break;
}
osg_state_set->setAttributeAndModes(cull_face, StateAttribute::ON);
}
}
m_gstates[i] = osg_state_set;
}
}
}
void TrPageArchive::LoadLightAttributes()
{
int num;
lightTable.GetNumLightAttrs(num);
for ( int attr_num = 0; attr_num < num; attr_num++ ){
trpgLightAttr* ref = const_cast<trpgLightAttr*>(lightTable.GetLightAttrRef(attr_num));
osgSim::LightPointNode* osgLight = new osgSim::LightPointNode();
osg::Point* osgPoint = new osg::Point();
osgSim::LightPoint lp ;
lp._on = true;
trpgColor col;
ref->GetFrontColor(col);
lp._color = osg::Vec4(col.red, col.green,col.blue, 1.0);
float64 inten;
ref->GetFrontIntensity(inten);
lp._intensity = inten;
trpgLightAttr::PerformerAttr perfAttr;
ref->GetPerformerAttr(perfAttr);
// point part
osgPoint->setSize(perfAttr.actualSize);
osgPoint->setMaxSize(perfAttr.maxPixelSize);
osgPoint->setMinSize(perfAttr.minPixelSize);
osgPoint->setFadeThresholdSize(perfAttr.transparentFallofExp);
//numbers that are going to appear are "experimental"
osgPoint->setDistanceAttenuation(osg::Vec3(0.0001, 0.0005, 0.00000025));
// osgPoint->setDistanceAttenuation(osg::Vec3(1.0, 0.0, 1.0));
osg::StateSet* stateSet = new osg::StateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON);
stateSet->setAttributeAndModes(osgPoint, osg::StateAttribute::ON );
stateSet->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::ON);
osgLight->setMaxPixelSize(perfAttr.maxPixelSize);
osgLight->setMinPixelSize(perfAttr.minPixelSize);
// float64 clamp;
// ref->GetPerformerTpClamp(clamp);
// osgLight->setMaxVisibleDistance2(clamp);
trpg3dPoint normal;
ref->GetNormal(normal);
// lp._radius = clamp;
trpgLightAttr::LightDirectionality direc;
ref->GetDirectionality(direc);
if( direc == trpgLightAttr::trpg_Unidirectional){
osgSim::AzimElevationSector* sec = new osgSim::AzimElevationSector();
float64 tmp;
ref->GetHLobeAngle(tmp);
float64 tmpfade;
ref->GetLobeFalloff(tmpfade);
sec->setAzimuthRange(-tmp/2.0,tmp/2.0,tmpfade);
ref->GetVLobeAngle(tmp);
sec->setElevationRange(0,tmp, tmpfade);
lp._sector = sec;
osgLight->addLightPoint(lp);
}
else if( direc == trpgLightAttr::trpg_Bidirectional ){
osgSim::AzimElevationSector* front = new osgSim::AzimElevationSector();
float64 tmp;
ref->GetHLobeAngle(tmp);
float64 tmpfade;
ref->GetLobeFalloff(tmpfade);
front->setAzimuthRange(-tmp/2.0,tmp/2.0,tmpfade);
ref->GetVLobeAngle(tmp);
front->setElevationRange(0,tmp, tmpfade);
lp._sector = front;
osgLight->addLightPoint(lp);
osgSim::AzimElevationSector* back = new osgSim::AzimElevationSector();
back->setAzimuthRange(osg::PI-tmp/2.0,osg::PI+tmp/2.0,tmpfade);
back->setElevationRange(0,tmp, tmpfade);
lp._sector = back;
osgLight->addLightPoint(lp);
}
else{
osgLight->addLightPoint(lp);
}
AddLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z));
}
}
void TrPageArchive::AddLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att)
{
DefferedLightAttribute la;
la.lightPoint = lpn;
la.fallback = fallback;
la.attitude = att;
lightAttrTable.push_back(la);
}
bool TrPageArchive::LoadModels()
{
int numModel;
modelTable.GetNumModels(numModel);
// Iterate over the models
for (int i=0; i< numModel; i++)
{
trpgModel *mod = modelTable.GetModelRef(i);
int type;
mod->GetType(type);
// Only dealing with external models currently
if (type == trpgModel::External)
{
char name[1024];
mod->GetName(name,1023);
// Load the model. It's probably not TerraPage
Node *osg_model = osgDB::readNodeFile(name);
if (!osg_model)
{
notify(WARN) << "TrPageArchive::LoadModels() error: "
<< "failed to load model: "
<< name << std::endl;
}
// Do this even if it's NULL
m_models.push_back(osg_model);
}
/*
else
{
trpgMemReadBuffer buf(GetEndian());
mod->Read(buf);
Group *osg_model = parse->ParseScene(buf, m_gstates , m_models);
m_models.push_back(osg_model);
}
*/
}
return true;
}
// Group* TrPageArchive::LoadTile(int x,int y,int lod,int &parentID,vector<GroupIDInfo> **groupList)
Group* TrPageArchive::LoadTile(int x,int y,int lod,int &parentID)
{
trpgMemReadBuffer buf(GetEndian());
// Read the tile data in, but don't parse it
if (!ReadTile(x,y,lod,buf))
return NULL;
parse->SetTile(x,y,lod);
Group *tile = parse->ParseScene(buf, m_gstates , m_models);
if (tile)
{
parentID = parse->GetParentID();
// This is where you would page in textures and models
}
// Also return the list of IDs and their groups we read in for this tile
// *groupList = parse->GetGroupList();
// That's it
return tile;
}
// Group* TrPageArchive::LoadTile(Group *rootNode,trpgPageManager *pageManage,trpgManagedTile *tile,vector<)
Group* TrPageArchive::LoadTile(Group *rootNode,
trpgPageManager * /*pageManage*/,
trpgManagedTile *tile,osg::Group **parentNode)
{
int x,y,lod;
tile->GetTileLoc(x,y,lod);
std::vector<GeodeGroup *> *groupList = parse->GetGroupList();
// Fetch the tile data (but don't parse it)
if (!ReadTile(x,y,lod,buf))
return NULL;
// Now parse it
parse->SetTile(x,y,lod);
Group *gTile = parse->ParseScene(buf, m_gstates, m_models);
if (gTile && rootNode) {
// Hook it into its parent
int parentID = parse->GetParentID();
if (parentID >= 0) {
(*groupList)[parentID]->addChild(gTile);
} else
rootNode->addChild(gTile);
// Note: Need to page in the textures
// They're being forced in during the parse right now
}
if (parentNode) {
int parentID = parse->GetParentID();
if (parentID >= 0)
*parentNode = (*groupList)[parentID];
else
*parentNode = rootNode;
}
// Add the tile to the local data in the managed tile
tile->SetLocalData(gTile);
return gTile;
}
bool TrPageArchive::UnLoadTile(trpgPageManager * /*pageManage*/,
trpgManagedTile *tile)
{
// The local tile data will have the group we need
Group *gTile = (Group *)tile->GetLocalData();
if (gTile) {
// Remove it from the parent list
// We're only expecting on parent
const Group::ParentList &pList = gTile->getParents();
if (pList.size() != 1)
return false;
pList[0]->removeChild(gTile);
} else
return false;
return true;
}
//----------------------------------------------------------------------------
Group* TrPageArchive::LoadAllTiles()
{
// Size information comes out of the header
const trpgHeader *head = GetHeader();
// Create one group as the top
Group *topGroup = new Group;
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.
trpg2iPoint tileSize;
// The group list is used to map parent IDs to pfGroup nodes
//std::vector<Group *> groupList;
std::vector<GeodeGroup *> *groupList = parse->GetGroupList();
for (int nl=0;nl<numLod;nl++)
{
// The number of tiles in X and Y changes per LOD
head->GetLodSize(nl,tileSize);
for (int x=0; x < tileSize.x; x++)
{
for (int y=0; y < tileSize.y; y++)
{
int parentID;
Group *tile = LoadTile(x,y,nl,parentID);
if (!tile)
{
notify(WARN)<< "TrPageArchive::LoadAllTiles error: "
<< "failed to load tile ("
<< x << "," << y << "," << nl << ")"
<< std::endl;
}
else
{
if (parentID == -1)
{
// Get added to the top level node
topGroup->addChild(tile);
}
else
{
// Added below some other node
(*groupList)[parentID]->addChild(tile);
}
}
}
}
}
return topGroup;
}

View File

@@ -1,128 +0,0 @@
/* **************************************************************************
* OpenSceneGraph loader for Terrapage format database
* by Boris Bralo 2002
*
* based on/modifed sgl (Scene Graph Library) loader by Bryan Walsh
*
* This loader is based on/modified from Terrain Experts Performer Loader,
* and was ported to SGL by Bryan Walsh / bryanw at earthlink dot net
*
* That loader is redistributed under the terms listed on Terrain Experts
* website (www.terrex.com/www/pages/technology/technologypage.htm)
*
* "TerraPage is provided as an Open Source format for use by anyone...
* We supply the TerraPage C++ source code free of charge. Anyone
* can use it and redistribute it as needed (including our competitors).
* We do, however, ask that you keep the TERREX copyrights intact."
*
* Copyright Terrain Experts Inc. 1999.
* All Rights Reserved.
*
*****************************************************************************/
#ifndef _TRPAGEARCHIVE_H_
#define _TRPAGEARCHIVE_H_
#include "trpage_sys.h"
#include "trpage_read.h"
#include "trpage_managers.h"
#include "TrPageParser.h"
#include <osgSim/LightPointNode>
#include <string>
#include <vector>
#include <memory> // for auto_ptr
namespace txp
{
// this one handles different placement of light direction in osg and terrapage
struct DefferedLightAttribute{
// light point at (0,0,0) looking in (0,0,0) direction
osg::ref_ptr<osgSim::LightPointNode> lightPoint;
osg::ref_ptr<osg::StateSet> fallback;
osg::Vec3 attitude;
};
/// main class for loading terrapage archives
class TrPageArchive : public trpgr_Archive, public osg::Referenced
{
public:
TrPageArchive();
~TrPageArchive();
// open archive file
virtual bool OpenFile(const char* file);
/// Load and create textures and materials
void LoadMaterials();
/// Load and create models, usualy OpenFlight models
bool LoadModels();
void LoadLightAttributes();
void AddLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude);
DefferedLightAttribute& GetLightAttribute(unsigned int i) {
return lightAttrTable[i];
};
/** Load a TXP tile and
@param x Tile location input - x dimension.
@param y Tile location input - y dimension.
@param lod Tile LOD level input.
@return The parent ID of this tile to let you hook it into the scene
graph.
x, y dimensions are not coordinates, they are tile numbers. For example,
for combination 10, 1 and lod number 2 terrapage opens file tile_10_1_2.tpt
in directory of the archive. This is THE method which shoud be used once
paging is implemented.
*/
osg::Group *LoadTile(int x,int y,int lod,int &parent);
/* This version is used during the paging and takes a Managed Tile
instead of location. These are used to keep track of what to
page in and out.
*/
osg::Group *LoadTile(osg::Group *rootNode,trpgPageManager *,trpgManagedTile *,osg::Group **parentNode=NULL);
/* Unload Tile
This is called to get rid of a tile from the scenegraph
*/
bool UnLoadTile(trpgPageManager *,trpgManagedTile *);
/** Load all the tiles . No paging.
@return The parent of the complete scene graph.
*/
osg::Group *LoadAllTiles();
// Calculate the center
void GetCenter(osg::Vec3 &center);
osg::Texture2D* getGlobalTexture(int id)
{
return m_textures[id].get();
}
protected:
/// This class does most of the actual parsing.
std::auto_ptr<TrPageParser> parse;
// Texture, material, and model lists.
std::vector< osg::ref_ptr<osg::Texture2D> > m_textures;
std::vector< osg::ref_ptr<osg::StateSet> > m_gstates;
std::vector< osg::ref_ptr<osg::Node> > m_models;
// light attributes vector
std::vector<DefferedLightAttribute> lightAttrTable;
std::string m_alternate_path;
trpgMemReadBuffer buf;
};
}; // end namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,360 +0,0 @@
/* **************************************************************************
* OpenSceneGraph loader for Terrapage format database
* by Boris Bralo 2002
*
* based on/modifed sgl (Scene Graph Library) loader by Bryan Walsh
*
* This loader is based on/modified from Terrain Experts Performer Loader,
* and was ported to SGL by Bryan Walsh / bryanw at earthlink dot net
*
* That loader is redistributed under the terms listed on Terrain Experts
* website (www.terrex.com/www/pages/technology/technologypage.htm)
*
* "TerraPage is provided as an Open Source format for use by anyone...
* We supply the TerraPage C++ source code free of charge. Anyone
* can use it and redistribute it as needed (including our competitors).
* We do, however, ask that you keep the TERREX copyrights intact."
*
* Copyright Terrain Experts Inc. 1999.
* All Rights Reserved.
*
*****************************************************************************/
#ifndef _TRPAGEPARSER_H_
#define _TRPAGEPARSER_H_
#include <osg/Vec3>
#include <osg/Vec2>
#include <osg/StateSet>
#include <osg/ref_ptr>
#include <osg/Texture2D>
#include <osg/Group>
#include <osg/Geode>
#include <osg/StateSet>
#include <vector>
#include "trpage_read.h"
namespace txp
{
class TrPageArchive;
struct DefferedLightAttribute;
// Group ID Info
// Used to keep track of which groups are which IDs for parents
typedef struct {
osg::Group *group;
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::Node> > & node );
// Return the parent of a recently parsed tile
int GetParentID() { return parentID; }
void SetParentID(int id) { parentID = id; }
// Return a reference to the tile header (after a tile has been read)
trpgTileHeader *GetTileHeaderRef();
// Return the current top node (used during parsing)
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,GeodeGroup*);
// Use this to add nodes into the scenegraph
void AddIntoSceneGraph(osg::Node* node);
// Return the group list
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); }
DefferedLightAttribute& GetLightAttribute(int attr_index);
// Sets the info about the tile that is being parsed
inline void SetTile(int x, int y, int lod)
{
_tileX = x; _tileY = y; _tileLOD = lod;
}
// Sets a group as potentinal PagedLOD - see below
inline void SetPotentionalPagedLOD(osg::Group* group)
{
_pagedLods[group] = 1;
}
protected:
// Called on start children
bool StartChildren(void *);
// Called on end children
bool EndChildren(void *);
// LOD parents
// These will help us to find the "LOD Bridges" in the scene graph. "LOD Bridge" is a
// group that holds two LOD nodes: one is the parent of the "current" LOD implementation of
// a tile, the other is parent of the quad of the higher-res LOD implementation of the same
// tile - it has four higher-res tiles. After a tile is loaded, we replace the "LOD bridge"
// with PagedLOD node
// nick@terrex.com
std::map<osg::Group*,int> _pagedLods;
// Converts to PagedLOD
// If the given group is "LOD Bridge" this method will convert it into appropriate PagedLOD
void ConvertToPagedLOD(osg::Group* group);
// Current tile that is being loaded
int _tileX;
int _tileY;
int _tileLOD;
double _tileRange;
protected:
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;
// 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;
};
// 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);
~geomRead();
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser *parse;
};
//----------------------------------------------------------------------------
class groupRead : public trpgr_Callback {
public:
groupRead(TrPageParser *in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser *parse;
};
//----------------------------------------------------------------------------
class attachRead : public trpgr_Callback {
public:
attachRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class billboardRead : public trpgr_Callback {
public:
billboardRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class lodRead : public trpgr_Callback {
public:
lodRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class modelRefRead : public trpgr_Callback {
public:
modelRefRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class tileHeaderRead : public trpgr_Callback {
public:
tileHeaderRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class layerRead: public trpgr_Callback {
public:
layerRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
//----------------------------------------------------------------------------
class lightRead: public trpgr_Callback {
public:
lightRead(TrPageParser*in_parse);
void *Parse(trpgToken tok,trpgReadBuffer &buf);
protected:
TrPageParser*parse;
};
} // namespace txp
#endif

View File

@@ -1,32 +0,0 @@
#ifndef WAIT_BLOCK_H
#define WAIT_BLOCK_H
#include <OpenThreads/Condition>
namespace osgTXP {
struct WaitBlock{
OpenThreads::Mutex mut;
OpenThreads::Condition cond;
WaitBlock()
{
}
void wait()
{
mut.lock();
cond.wait(&mut);
mut.unlock();
}
void release()
{
// mut.lock();
cond.broadcast();
// mut.unlock();
}
};
}
#endif

View File

@@ -1,393 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include "TrPageArchive.h"
#include "trPagePageManager.h"
#include "trpage_print.h"
#include <osg/Group>
#include <osg/Object>
#include <osg/Node>
#include <osg/Notify>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgDB/DatabasePager>
#include <iostream>
using namespace txp;
using namespace osg;
OSGPageManager::OSGPageManager(TrPageArchive *in_arch,trpgPageManager *in_pageManage)
{
archive = in_arch;
pageManage = in_pageManage;
if (!in_arch)
throw 1;
if (pageManage)
pageManageOurs = false;
else {
pageManage = new trpgPageManager();
pageManage->SetPageDistFactor(1.2);
pageManage->Init(archive);
pageManageOurs = true;
}
// Location info we'll need later
const trpgHeader *head = archive->GetHeader();
trpg2dPoint sw,ne;
head->GetExtents(sw,ne);
originX = sw.x;
originY = sw.y;
threadMode = ThreadNone;
}
OSGPageManager::~OSGPageManager()
{
if (threadMode != ThreadNone)
EndThread();
if (pageManageOurs)
delete pageManage;
pageManage = NULL;
}
/* Update
Bring the paging up to date based on the given location.
The location is in TerraPage's coordinate system, but must
still be adjusted to the SW corner.
*/
bool OSGPageManager::UpdateNoThread(osg::Group *rootNode,double locX,double locY,int numTile)
{
// Adjust to TerraPage coordinates
double lx = locX-originX;
double ly = locY-originY;
/* Do that paging thing:
- Tell the manager the new location
- Iterate over the unloads
- Iterate over the loads
*/
trpg2dPoint loc;
loc.x = lx;
loc.y = ly;
if (pageManage->SetLocation(loc)) {
// printf("Location (%f,%f) resulted in changes.",loc.x,loc.y);
// trpgFilePrintBuffer printBuf(stdout);
// pageManage->Print(printBuf);
}
// Do the unloads
trpgManagedTile *tile=NULL;
while ((tile = pageManage->GetNextUnload())) {
archive->UnLoadTile(pageManage,tile);
pageManage->AckUnload();
};
// Decide how many loads to do per frame
int loadCount=0;
// Do the loads
while ((tile = pageManage->GetNextLoad())) {
archive->LoadTile(rootNode,pageManage,tile);
pageManage->AckLoad();
loadCount++;
if (numTile > 0 && loadCount >= numTile)
break;
};
return true;
}
// Mutex lock function
// --- Either thread ---
struct osgGuard
{
ThreadMutex& _mtx;
osgGuard(ThreadMutex &mtx):_mtx(mtx){
_mtx.lock();
}
~osgGuard(){
_mtx.unlock();
}
};
void PagingThread::run()
{
// need to set the texture object manager to be able to reuse textures
// by keeping deleted texture objects around for 10 seconds after being deleted.
osg::Texture::getTextureObjectManager()->setExpiryDelay(10.0f);
pager->ThreadLoop(this);
}
/* Start Thread
This initialized
--- Main Thread ---
*/
bool OSGPageManager::StartThread(ThreadMode mode,ThreadID &newThread)
{
positionValid = false;
//locationChangeEvent is self-initialized.
threadMode = mode;
pagingThread.pager = this;
pagingThread.startThread();
newThread = pagingThread.getThreadId();
return threadMode != ThreadNone;
}
/* End Thread
Note: Do this
*/
bool OSGPageManager::EndThread()
{
// locationChangeEvent.release();
if( pagingThread.isRunning() )
{
pagingThread.cancel();
//pagingThread.join();
// then wait for the the thread to stop running.
while(pagingThread.isRunning())
{
osg::notify(osg::INFO)<<"Waiting for TXP pager thread to cancel"<<std::endl;
OpenThreads::Thread::YieldCurrentThread();
}
}
return true;
}
void OSGPageManager::LoadOneTile(trpgManagedTile* tile)
{
osg::Group* tileGroup = 0;
osg::Group* parentNode = 0;
int x,y,lod;
tile->GetTileLoc(x,y,lod);
tileGroup = archive->LoadTile(NULL,pageManage,tile,&parentNode);
if (tileGroup)
{
osgGuard g(changeListMutex);
if(parentNode)
toMerge.push_back(MergePair(parentNode,tileGroup)) ;
else
toMerge.push_back(MergePair(0,tileGroup)) ;
}
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(PagingThread* t)
{
// Note: Only works for free running thread
if (threadMode != ThreadFree)
throw 1;
//std::cout<<"OSGPageManager::ThreadLoop()"<<std::endl;
std::vector<osg::Group *> unhook;
std::vector < osg::ref_ptr<osg::Group> > nextDelete;
//bool pagingActive = false;
do
{
/* 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
// locationChangeEvent.wait();
double myLocX,myLocY;
{
osgGuard g(locationMutex);
myLocX = locX;
myLocY = locY;
positionValid = false;
}
// Pass the new location on to page manager
int x,y,lod;
trpg2dPoint loc;
loc.x = myLocX;
loc.y = myLocY;
//std::cout<<"location "<<myLocX<<" "<<myLocY<<std::endl;
if (pageManage->SetLocation(loc) ) {
// If there were changes, process them
// Form the delete list first
trpgManagedTile *tile=NULL;
unhook.clear();
while ((tile = pageManage->GetNextUnload())) {
tile->GetTileLoc(x,y,lod);
unhook.push_back((Group *)(tile->GetLocalData()));
pageManage->AckUnload();
}
//nextDelete.clear();
{
// Add to the unhook list
for(unsigned int kk = 0; kk < unhook.size();kk++)
{
osgGuard g(changeListMutex);
toUnhook.push_back(unhook[kk]);
}
// Also get the list of deletions while we're here
// use the stl Luke :-) swap is constant time operation that do a = b; b.clear()
// if a is empty which is our case
osgGuard g(changeListMutex);
nextDelete.swap(toDelete);
}
// unref the delete list.
nextDelete.clear();
// Now do a single load
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;
if (lod==0) LoadOneTile(tile);
// Now add this tile to the merge list
pageManage->AckLoad();
//OpenThreads::Thread::YieldCurrentThread();
}
}
else
{
OpenThreads::Thread::YieldCurrentThread();
}
} while (!t->testCancel());
return true;
}
/* Update Position Thread
This method updates the location for the paging thread to use.
--- Main Thread ---
*/
void OSGPageManager::UpdatePositionThread(double inLocX,double inLocY)
{
// Update the position
if(!positionValid)
{
// Get the location mutex
osgGuard g(locationMutex);
positionValid = true;
locX = inLocX-originX;
locY = inLocY-originY;
}
// Notify the paging thread there's been a position update
// locationChangeEvent.release();
}
/* 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.
--- Main Thread ---
*/
bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode)
{
std::vector<MergePair> mergeList;
std::vector<osg::ref_ptr<osg::Group> > unhookList;
// Make local copies of the merge and unhook lists
{
// use the stl Luke :-) swap is constant time operation that do a = b; b.clear()
// if a is empty which is our case
//if (changeListMutex.trylock()==0)
{
osgGuard g(changeListMutex);
mergeList.swap(toMerge);
unhookList.swap(toUnhook);
}
}
// visitor to go through unhooked subgraphs to release texture objects
// and display lists.
osgDB::DatabasePager::ReleaseTexturesAndDrawablesVisitor rtadv;
// Do the unhooking first
for (unsigned int ui=0;ui<unhookList.size();ui++)
{
osg::Group *unhookMe = unhookList[ui].get();
// better safe than sorry
if(!unhookMe ) continue;
// relase textre objects and display lists in subgraph.
unhookMe->accept(rtadv);
// 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];
//if(parent != rootNode)
{
//std::cout<<"removing "<<unhookMe<<" from "<<parent<<std::endl;
parent->removeChild(unhookMe);
}
}
}
// Append the unhooked things on to the list to delete
{
osgGuard g(changeListMutex);
for (unsigned int i = 0; i < unhookList.size();i++)
{
toDelete.push_back(unhookList[i]);
}
}
// Do the merging last
{
for (unsigned int mi=0;mi<mergeList.size();mi++)
{
osg::Group *parent = mergeList[mi].first.get();
osg::Group *mergeMe = mergeList[mi].second.get();
if (parent)
parent->addChild(mergeMe);
else
rootNode->addChild(mergeMe);
}
}
return true;
}

View File

@@ -1,158 +0,0 @@
/* **************************************************************************
* OpenSceneGraph loader for Terrapage format database
*
* That loader is redistributed under the terms listed on Terrain Experts
* website (www.terrex.com/www/pages/technology/technologypage.htm)
*
* "TerraPage is provided as an Open Source format for use by anyone...
* We supply the TerraPage C++ source code free of charge. Anyone
* can use it and redistribute it as needed (including our competitors).
* We do, however, ask that you keep the TERREX copyrights intact."
*
* Copyright Terrain Experts Inc. 1999.
* All Rights Reserved.
*
*****************************************************************************/
#ifndef _TRPAGEMANAGER_H_
#define _TRPAGEMANAGER_H_
#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"
#include "trpage_scene.h"
#include "trpage_managers.h"
#include "WaitBlock.h"
#include "TrPageArchive.h"
#include <string>
namespace txp
{
/* Thread Identifier
Fill this in for your specific platform.
Should be water ID you use for threads.
*/
typedef int ThreadID;
typedef OpenThreads::Mutex ThreadMutex;
typedef osgTXP::WaitBlock ThreadEvent;
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{
public:
/* 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).
*/
OSGPageManager(TrPageArchive *,trpgPageManager *pageManage = NULL);
~OSGPageManager();
/* Unthreaded update
Update viewer position and load a maximum of numTile before
returning.
Also unloads everything that needs it.
Don't call this in threaded mode.
*/
bool UpdateNoThread(osg::Group *,double locX,double locY,int numTile=-1);
/* Thread routines
The thread will run in and around this object. It can
run in one of two modes:
ThreadFree -
ThreadSync -
*/
typedef enum {ThreadNone,ThreadFree,ThreadSync} ThreadMode;
// Retrieve the current threading mode
ThreadMode GetThreadMode() { return threadMode; }
// ----- Main thread routines -----
// ----- Only call these from the main thread ----
// Create a new thread in the given mode.
bool StartThread(ThreadMode,ThreadID &newThread);
/* If we're in ThreadFree mode, merge everything the paging
thread has read in up to this point into the main scenegraph.
*/
bool MergeUpdateThread(osg::Group *);
// Shut down the current paging thread.
bool EndThread();
// Update the viewer position
void UpdatePositionThread(double locX,double locY);
// ----- Paging Thread Routines ----
// ----- Only call these from the paging thread ----
// Called by the thread start function
// Don't call this yourself
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)
bool pageManageOurs;
trpgPageManager *pageManage;
// Archive to page from
TrPageArchive *archive;
// Database origin
double originX,originY;
/* Thread specific data.
*/
// ID of created thread and whether it's valid
ThreadMode threadMode;
PagingThread pagingThread;
// Used to notify the paging thread when the location changes
ThreadEvent locationChangeEvent;
// Lock for the location and location itself
ThreadMutex locationMutex;
bool positionValid;
double locX,locY;
// Lock for the change lists (merge, unhook, delete)
ThreadMutex changeListMutex;
// Merge list is filled in by the paging thread.
typedef std::pair< osg::ref_ptr<osg::Group> , osg::ref_ptr<osg::Group> > MergePair;
std::vector< MergePair > toMerge;
std::vector< osg::ref_ptr<osg::Group> > toUnhook;
// Main thread moves groups to the delete list as soon as they are unhooked
std::vector< osg::ref_ptr<osg::Group> > toDelete;
};
};
#endif

View File

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

View File

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

View File

@@ -33,10 +33,10 @@
*/
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,84 +46,84 @@ trpgMatTable1_0::trpgMatTable1_0(const trpgMatTable &inTbl)
bool trpgMatTable1_0::Read(trpgReadBuffer &buf)
{
trpgMaterial mat;
trpgToken matTok;
int32 len;
bool status;
unsigned int i,j,k;
trpgMaterial mat;
trpgToken matTok;
int32 len;
bool status;
unsigned 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<(unsigned int)numTable;i++)
for (j=0;j<(unsigned int)numMat;j++) {
trpgShortMaterial &smat = shortTable[i*numMat+j];
buf.Get(smat.baseMat);
buf.Get(numTex);
for (k=0;k<(unsigned int)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<(unsigned int)numTable;i++)
for (j=0;j<(unsigned int)numMat;j++) {
trpgShortMaterial &smat = shortTable[i*numMat+j];
buf.Get(smat.baseMat);
buf.Get(numTex);
for (k=0;k<(unsigned int)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<(unsigned int)numBaseMat;i++) {
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
mat.Reset();
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
baseMats[i] = mat;
}
}
}
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<(unsigned int)numBaseMat;i++) {
buf.GetToken(matTok,len);
if (matTok != TRPGMATERIAL) throw 1;
buf.PushLimit(len);
mat.Reset();
status = mat.Read(buf);
buf.PopLimit();
if (!status) throw 1;
baseMats[i] = mat;
}
}
}
catch (...) {
return false;
}
// Now convert to the new style material table
for (i=0;i<shortTable.size();i++) {
trpgShortMaterial &shortMat = shortTable[i];
trpgMaterial &baseMat = baseMats[shortMat.baseMat];
matTables.push_back(baseMat);
trpgMaterial &newMat = matTables[matTables.size()-1];
newMat.SetNumTexture(shortMat.texids.size());
for (j=0;j<shortMat.texids.size();j++) {
int texId;
trpgTextureEnv texEnv;
baseMat.GetTexture(j,texId,texEnv);
newMat.SetTexture(j,shortMat.texids[j],texEnv);
}
}
// 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,19 +132,19 @@ 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];
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;
}
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
@@ -155,22 +155,22 @@ bool trpgMatTable1_0::Write(trpgWriteBuffer &buf)
// Write the short materials
buf.Begin(TRPGSHORTMATTABLE);
for (i=0;i<(int)shortMats.size();i++) {
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
unsigned int j;
for (j=0;j<sMat.texids.size();j++)
buf.Add(sMat.texids[j]);
trpgShortMaterial &sMat = shortMats[i];
buf.Add(sMat.baseMat);
buf.Add((int)(sMat.texids.size()));
unsigned int j;
for (j=0;j<sMat.texids.size();j++)
buf.Add(sMat.texids[j]);
}
buf.End();
// Write the regular materials
buf.Add(numTable*numMat);
for (i=0;i<numTable*numMat;i++) {
trpgMaterial &mat = matTables[i];
// This will be bigger than the old 1.0 material, but it doesn't matter since
// the new stuff is on the end.
mat.Write(buf);
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
@@ -188,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);
@@ -223,44 +223,44 @@ 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 (unsigned int i=0;i<(unsigned int)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<(unsigned int)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;
}
@@ -272,12 +272,12 @@ trpgTileTable1_0::trpgTileTable1_0(const trpgTileTable& /*inTable*/)
bool trpgTileTable1_0::Write(trpgWriteBuffer &buf)
{
try {
buf.Begin(TRPGTILETABLE);
buf.Add("");
buf.End();
buf.Begin(TRPGTILETABLE);
buf.Add("");
buf.End();
}
catch (...) {
return false;
return false;
}
return true;

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -24,77 +24,77 @@
#include <trpage_managers.h>
/* Managed Tile class.
Check the header file for details.
Check the header file for details.
*/
trpgManagedTile::trpgManagedTile()
{
isLoaded = false;
x = y = -1;
lod = -1;
localData = NULL;
isLoaded = false;
x = y = -1;
lod = -1;
localData = NULL;
}
void trpgManagedTile::Reset()
{
// Null out the local material data
for (unsigned int i=0;i<localMatData.size();i++)
localMatData[i] = NULL;
groupIDs.resize(0);
// Null out the local material data
for (unsigned int i=0;i<localMatData.size();i++)
localMatData[i] = NULL;
groupIDs.resize(0);
isLoaded = false;
x = y = -1;
lod = -1;
localData = NULL;
isLoaded = false;
x = y = -1;
lod = -1;
localData = NULL;
}
bool trpgManagedTile::ParseTileHeader(trpgReadBuffer &buf)
{
isLoaded = false;
if (!tileHead.Read(buf))
return false;
isLoaded = false;
if (!tileHead.Read(buf))
return false;
int numLoc;
tileHead.GetNumLocalMaterial(numLoc);
localMatData.resize(numLoc);
int numLoc;
tileHead.GetNumLocalMaterial(numLoc);
localMatData.resize(numLoc);
// The tile considers itself loaded with just
// the header. This isn't true as far as the paging
// manager is concerned.
isLoaded = true;
return true;
// The tile considers itself loaded with just
// the header. This isn't true as far as the paging
// manager is concerned.
isLoaded = true;
return true;
}
bool trpgManagedTile::IsLoaded()
{
return isLoaded;
return isLoaded;
}
bool trpgManagedTile::SetTileLoc(int inX,int inY,int inLod)
{
x = inX; y = inY;
if (inLod < 0)
return false;
lod = inLod;
x = inX; y = inY;
if (inLod < 0)
return false;
lod = inLod;
return true;
return true;
}
bool trpgManagedTile::GetTileLoc(int &retx,int &rety,int &retLod)
{
retx = x; rety = y; retLod = lod;
retx = x; rety = y; retLod = lod;
return true;
return true;
}
const trpgTileHeader *trpgManagedTile::GetTileHead()
{
return &tileHead;
return &tileHead;
}
const std::vector<trpgLocalMaterial> *trpgManagedTile::GetLocMatList() const
{
return tileHead.GetLocalMaterialList();
return tileHead.GetLocalMaterialList();
}
const trpgLocalMaterial *trpgManagedTile::GetLocMaterial(int id) const
@@ -103,7 +103,7 @@ const trpgLocalMaterial *trpgManagedTile::GetLocMaterial(int id) const
matList = tileHead.GetLocalMaterialList();
if (id <0 || id >= (int)matList->size())
return NULL;
return NULL;
return &(*matList)[id];
}
@@ -120,20 +120,20 @@ void *trpgManagedTile::GetLocalData() const
bool trpgManagedTile::SetMatData(int id,void *info)
{
if (id < 0 || id >= (int)localMatData.size())
return false;
if (id < 0 || id >= (int)localMatData.size())
return false;
localMatData[id] = info;
localMatData[id] = info;
return true;
return true;
}
void *trpgManagedTile::GetMatData(int id) const
{
if (id < 0 || id >= (int)localMatData.size())
return NULL;
if (id < 0 || id >= (int)localMatData.size())
return NULL;
return localMatData[id];
return localMatData[id];
}
void trpgManagedTile::AddGroupID(int id)
@@ -154,83 +154,83 @@ void trpgManagedTile::Print(trpgPrintBuffer &buf)
}
/* Page Manager LOD Page Info class.
Used by the page manager to keep track of paging information
for a single terrain LOD. See the header file for details.
Used by the page manager to keep track of paging information
for a single terrain LOD. See the header file for details.
*/
trpgPageManager::LodPageInfo::LodPageInfo()
{
valid = false;
pageDist = 0.0;
cell.x = cell.y = -100;
valid = false;
pageDist = 0.0;
cell.x = cell.y = -100;
}
trpgPageManager::LodPageInfo::~LodPageInfo()
{
Clean();
Clean();
}
void trpgPageManager::LodPageInfo::Clean()
{
// Clean up managed tile structures
// Clean up managed tile structures
unsigned int i;
for (i=0;i<load.size();i++)
if (load[i])
delete load[i];
load.resize(0);
for (i=0;i<unload.size();i++)
if (unload[i])
delete unload[i];
unload.resize(0);
for (i=0;i<current.size();i++)
if (current[i])
delete current[i];
current.resize(0);
for (i=0;i<freeList.size();i++)
delete freeList[i];
freeList.resize(0);
activeLoad = false;
activeUnload = false;
for (i=0;i<load.size();i++)
if (load[i])
delete load[i];
load.resize(0);
for (i=0;i<unload.size();i++)
if (unload[i])
delete unload[i];
unload.resize(0);
for (i=0;i<current.size();i++)
if (current[i])
delete current[i];
current.resize(0);
for (i=0;i<freeList.size();i++)
delete freeList[i];
freeList.resize(0);
activeLoad = false;
activeUnload = false;
}
bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, double scale)
{
Clean();
Clean();
lod = myLod;
// In theory we could have a negative scale, but I don't
// really want to deal with that.
if (scale < 0) scale = 0.0;
lod = myLod;
// In theory we could have a negative scale, but I don't
// really want to deal with that.
if (scale < 0) scale = 0.0;
// Need some size and shape info about our terrain LOD
const trpgHeader *head = archive->GetHeader();
head->GetTileSize(lod,cellSize);
head->GetLodRange(lod,pageDist);
head->GetLodSize(lod,lodSize);
pageDist *= scale;
// Need some size and shape info about our terrain LOD
const trpgHeader *head = archive->GetHeader();
head->GetTileSize(lod,cellSize);
head->GetLodRange(lod,pageDist);
head->GetLodSize(lod,lodSize);
pageDist *= scale;
// Area of interest size (in cells)
aoiSize.x = (int)(pageDist/cellSize.x);
aoiSize.y = (int)(pageDist/cellSize.y);
// Area of interest size (in cells)
aoiSize.x = (int)(pageDist/cellSize.x);
aoiSize.y = (int)(pageDist/cellSize.y);
/* Make a guess as to how many tiles we might have loaded
in at any given time. Give ourselves 15% extra room.
From the area of interest in cells, we can guess the max
number of tiles (aka cells) we'll have loaded in at once.
Note that the AOI size is only ahead, so it must be doubled.
*/
maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1));
/* Make a guess as to how many tiles we might have loaded
in at any given time. Give ourselves 15% extra room.
From the area of interest in cells, we can guess the max
number of tiles (aka cells) we'll have loaded in at once.
Note that the AOI size is only ahead, so it must be doubled.
*/
maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1));
// Allocate 'em
for (int i=0;i<maxNumTiles;i++) {
trpgManagedTile *tile = new trpgManagedTile();
freeList.push_back(tile);
}
// Allocate 'em
for (int i=0;i<maxNumTiles;i++) {
trpgManagedTile *tile = new trpgManagedTile();
freeList.push_back(tile);
}
// We still don't have a position yet
valid = true;
// We still don't have a position yet
valid = true;
return true;
return true;
}
bool trpgPageManager::LodPageInfo::SetLocation(trpg2dPoint &loc)
@@ -248,7 +248,7 @@ bool trpgPageManager::LodPageInfo::SetLocation(trpg2dPoint &loc)
// Nothing to page. Done.
if (newCell.x == cell.x && newCell.y == cell.y)
return false;
return false;
// Cell has changed. Update.
cell = newCell;
@@ -262,15 +262,15 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextLoad()
{
// Can only load one tile at a time
if (activeLoad)
return NULL;
return NULL;
// Clear any NULLs at the beginning
while (load.size() && !load[0])
load.pop_front();
load.pop_front();
if (load.size() > 0) {
activeLoad = true;
return load[0];
activeLoad = true;
return load[0];
}
return NULL;
@@ -279,8 +279,8 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextLoad()
void trpgPageManager::LodPageInfo::AckLoad()
{
if (activeLoad) {
current.push_back(load[0]);
load.pop_front();
current.push_back(load[0]);
load.pop_front();
}
activeLoad = false;
}
@@ -289,15 +289,15 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextUnload()
{
// Can only unload one tile at a time
if (activeUnload)
return NULL;
return NULL;
// Clear any NULLs at the beginning
while (unload.size() && !unload[0])
unload.pop_front();
unload.pop_front();
if (unload.size() > 0) {
activeUnload = true;
return unload[0];
activeUnload = true;
return unload[0];
}
return NULL;
@@ -306,10 +306,10 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextUnload()
void trpgPageManager::LodPageInfo::AckUnload()
{
if (activeUnload) {
trpgManagedTile *tile = unload[0];
tile->Reset();
freeList.push_back(tile);
unload.pop_front();
trpgManagedTile *tile = unload[0];
tile->Reset();
freeList.push_back(tile);
unload.pop_front();
}
activeUnload = false;
}
@@ -319,8 +319,8 @@ bool trpgPageManager::LodPageInfo::isWithin(trpgManagedTile *tile,trpg2iPoint &s
int tileX,tileY,tileLod;
tile->GetTileLoc(tileX,tileY,tileLod);
if (tileX >= sw.x && tileX <= ne.x &&
tileY >= sw.y && tileY <= ne.y)
return true;
tileY >= sw.y && tileY <= ne.y)
return true;
return false;
}
@@ -330,13 +330,13 @@ bool trpgPageManager::LodPageInfo::Stop()
// Empty the load list
unsigned int i;
for (i=0;i<load.size();i++)
freeList.push_back(load[i]);
freeList.push_back(load[i]);
load.resize(0);
// Move the current tiles to the unload list
for (i=0;i<current.size();i++)
if (current[i])
unload.push_back(current[i]);
if (current[i])
unload.push_back(current[i]);
current.resize(0);
return (unload.size() > 0);
@@ -354,54 +354,54 @@ void trpgPageManager::LodPageInfo::Update()
// in cell coordinates
sw.x = cell.x - aoiSize.x; sw.y = cell.y - aoiSize.y;
ne.x = cell.x + aoiSize.x; ne.y = cell.y + aoiSize.y;
sw.x = MAX(0,sw.x); sw.y = MAX(0,sw.y);
sw.x = MAX(0,sw.x); sw.y = MAX(0,sw.y);
ne.x = MIN(lodSize.x-1,ne.x); ne.y = MIN(lodSize.y-1,ne.y);
/* Load list -
Some of the tiles we're supposed to load may now be
out of range. Take them off the load list.
Some of the tiles we're supposed to load may now be
out of range. Take them off the load list.
*/
unsigned int i;
for (i=0;i<load.size();i++) {
if (load[i] && !isWithin(load[i],sw,ne)) {
freeList.push_back(load[i]);
load[i] = NULL;
}
if (load[i] && !isWithin(load[i],sw,ne)) {
freeList.push_back(load[i]);
load[i] = NULL;
}
}
/* Unload list -
Some of the tiles we were planning on unloading may now
be in view again. Move them back to current.
Some of the tiles we were planning on unloading may now
be in view again. Move them back to current.
*/
for (i=0;i<unload.size();i++) {
if (unload[i] && isWithin(unload[i],sw,ne)) {
current.push_back(unload[i]);
unload[i] = NULL;
}
if (unload[i] && isWithin(unload[i],sw,ne)) {
current.push_back(unload[i]);
unload[i] = NULL;
}
}
/* Current list -
We need to figure out a few things here.
1) What's in the current list that should be paged out.
2) What's already paged, sorted into tmpCurrent.
3) What's missing from tmpCurrent and should be paged in.
We need to figure out a few things here.
1) What's in the current list that should be paged out.
2) What's already paged, sorted into tmpCurrent.
3) What's missing from tmpCurrent and should be paged in.
*/
// Look for tiles to page out
// Move them to the unload list
for (i=0;i<current.size();i++) {
if (current[i] && !isWithin(current[i],sw,ne)) {
unload.push_back(current[i]);
current[i] = NULL;
}
if (current[i] && !isWithin(current[i],sw,ne)) {
unload.push_back(current[i]);
current[i] = NULL;
}
}
// Clean the NULLs out of the current list
int curPos = 0;
for (i=0;i<current.size();i++) {
if (current[i]) {
current[curPos] = current[i];
curPos++;
}
if (current[i]) {
current[curPos] = current[i];
curPos++;
}
}
current.resize(curPos);
@@ -413,30 +413,30 @@ void trpgPageManager::LodPageInfo::Update()
tmpCurrent.resize(dx*dy);
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;
tile->GetTileLoc(tileX,tileY,tileLod);
tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true;
}
trpgManagedTile *tile = current[i];
if (tile) {
int tileX,tileY,tileLod;
tile->GetTileLoc(tileX,tileY,tileLod);
tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true;
}
}
// Now figure out which ones are missing and add them
// to the load list
for (int x=0;x<dx;x++) {
for (int y=0;y<dy;y++) {
if (!tmpCurrent[y*dx + x]) {
// Allocate a new tile
trpgManagedTile *tile = NULL;
if (freeList.size() > 0) {
tile = freeList[0];
freeList.pop_front();
} else
tile = new trpgManagedTile();
tile->SetTileLoc(x+sw.x,y+sw.y,lod);
load.push_back(tile);
}
}
for (int y=0;y<dy;y++) {
if (!tmpCurrent[y*dx + x]) {
// Allocate a new tile
trpgManagedTile *tile = NULL;
if (freeList.size() > 0) {
tile = freeList[0];
freeList.pop_front();
} else
tile = new trpgManagedTile();
tile->SetTileLoc(x+sw.x,y+sw.y,lod);
load.push_back(tile);
}
}
}
// That's it. All the rest is handled by the caller
@@ -456,22 +456,22 @@ void trpgPageManager::LodPageInfo::Print(trpgPrintBuffer &buf)
sprintf(line,"Loads: (activeLoad = %s)",(activeLoad ? "yes" : "no")); buf.prnLine(line);
buf.IncreaseIndent();
for (i=0;i<load.size();i++)
if (load[i])
load[i]->Print(buf);
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<unload.size();i++)
if (unload[i])
unload[i]->Print(buf);
if (unload[i])
unload[i]->Print(buf);
buf.DecreaseIndent();
buf.prnLine("Currently loaded:");
buf.IncreaseIndent();
for (i=0;i<current.size();i++)
if (current[i])
current[i]->Print(buf);
if (current[i])
current[i]->Print(buf);
buf.DecreaseIndent();
sprintf(line,"Free list size = %d",freeList.size()); buf.prnLine(line);
@@ -513,7 +513,7 @@ void trpgPageManager::Init(trpgr_Archive *inArch)
valid = true;
pageInfo.resize(numLod);
for (int i=0;i<numLod;i++) {
pageInfo[i].Init(archive,i,scale);
pageInfo[i].Init(archive,i,scale);
}
}
@@ -521,7 +521,7 @@ bool trpgPageManager::SetPageDistFactor(double inFact)
{
// A scaling factor less than 1 will break the archive display.
if (inFact <= 1.0)
return false;
return false;
scale = inFact;
@@ -532,15 +532,15 @@ bool trpgPageManager::SetLocation(trpg2dPoint &pt)
{
// Do a basic sanity check
if (!valid || (pagePt.x == pt.x && pagePt.y == pt.y))
return false;
return false;
pagePt = pt;
// Call each terrain LOD and let if figure out if something
// has changed.
bool change = false;
for (unsigned int i=0;i<pageInfo.size();i++) {
if (pageInfo[i].SetLocation(pt))
change = true;
if (pageInfo[i].SetLocation(pt))
change = true;
}
return change;
@@ -550,22 +550,22 @@ trpgManagedTile *trpgPageManager::GetNextLoad()
{
// If we're already doing something, let them know about it
if (lastLoad != None)
throw 1;
throw 1;
// Look for anything that needs loaded
// Start with lowest LOD, work up to highest
trpgManagedTile *tile = NULL;
for (unsigned int i=0;i<pageInfo.size();i++) {
LodPageInfo &info = pageInfo[i];
if ((tile = info.GetNextLoad()))
break;
LodPageInfo &info = pageInfo[i];
if ((tile = info.GetNextLoad()))
break;
}
// Found one. Now the user has to load it.
if (tile) {
lastLoad = Load;
lastTile = tile;
lastLod = tile->lod;
lastLoad = Load;
lastTile = tile;
lastLod = tile->lod;
}
return tile;
@@ -575,7 +575,7 @@ void trpgPageManager::AckLoad()
{
// If we're not in the middle of a load, register our displeasure
if (lastLoad != Load)
throw 1;
throw 1;
LodPageInfo &info = pageInfo[lastLod];
info.AckLoad();
@@ -593,7 +593,7 @@ void *trpgPageManager::GetGroupData(int groupID)
{
ManageGroupMap::const_iterator p = groupMap.find(groupID);
if (p != groupMap.end())
return (*p).second;
return (*p).second;
return NULL;
}
@@ -602,22 +602,22 @@ trpgManagedTile *trpgPageManager::GetNextUnload()
{
// If we're already doing something, let them know about it
if (lastLoad != None)
throw 1;
throw 1;
// Look for anything that needs unloaded
// Start with highest LOD, work down to lowest
trpgManagedTile *tile = NULL;
for (int i=pageInfo.size()-1;i>=0;i--) {
LodPageInfo &info = pageInfo[i];
if ((tile = info.GetNextUnload()))
break;
LodPageInfo &info = pageInfo[i];
if ((tile = info.GetNextUnload()))
break;
}
// Found one. Now the user has to unload it.
if (tile) {
lastLoad = Unload;
lastTile = tile;
lastLod = tile->lod;
lastLoad = Unload;
lastTile = tile;
lastLod = tile->lod;
}
return tile;
@@ -627,14 +627,14 @@ void trpgPageManager::AckUnload()
{
// If we're not in the middle of an unload, let 'em know.
if (lastLoad != Unload)
throw 1;
throw 1;
// Remove this tile's group IDs from the map
const std::vector<int> *groupIDs = lastTile->GetGroupIDs();
for (unsigned int i=0;i<groupIDs->size();i++) {
ManageGroupMap::iterator p = groupMap.find((*groupIDs)[i]);
if (p != groupMap.end())
groupMap.erase(p);
ManageGroupMap::iterator p = groupMap.find((*groupIDs)[i]);
if (p != groupMap.end())
groupMap.erase(p);
}
LodPageInfo &info = pageInfo[lastLod];
@@ -647,7 +647,7 @@ bool trpgPageManager::Stop()
{
bool res=false;
for (unsigned int i=0;i<pageInfo.size();i++)
res |= pageInfo[i].Stop();
res |= pageInfo[i].Stop();
lastLoad = None;
@@ -661,10 +661,10 @@ void trpgPageManager::Print(trpgPrintBuffer &buf)
buf.prnLine("Terrain LODs:");
for (unsigned int i=0;i<pageInfo.size();i++) {
sprintf(line,"----Terrain lod %d---",i); buf.prnLine(line);
sprintf(line,"----Terrain lod %d---",i); buf.prnLine(line);
buf.IncreaseIndent();
pageInfo[i].Print(buf);
buf.DecreaseIndent();
pageInfo[i].Print(buf);
buf.DecreaseIndent();
}
}
@@ -689,7 +689,7 @@ void trpgPageManageTester::Init(trpgPrintBuffer *pBuf,trpgPageManager *pMan,trpg
printBuf = pBuf;
if (!archive->isValid())
throw 1;
throw 1;
// Start up the paging manager
manager->Init(archive);
@@ -698,11 +698,11 @@ void trpgPageManageTester::Init(trpgPrintBuffer *pBuf,trpgPageManager *pMan,trpg
void trpgPageManageTester::RandomTest(int num,int seed)
{
if (!manager || !archive || !printBuf)
throw 1;
throw 1;
// Seed the random number generator so we can replicate runs
if (seed != -1)
srand(seed);
srand(seed);
// Need the extents
trpg2dPoint ll,ur,lod0Size;
@@ -718,20 +718,20 @@ void trpgPageManageTester::RandomTest(int num,int seed)
int i;
char line[1024];
for (i=0;i<num;i++) {
// Generate a point
double randNum1 = rand()/(double)RAND_MAX;
double randNum2 = rand()/(double)RAND_MAX;
trpg2dPoint pt;
pt.x = (ur.x - ll.x)*randNum1;
pt.y = (ur.y - ll.y)*randNum2;
// Generate a point
double randNum1 = rand()/(double)RAND_MAX;
double randNum2 = rand()/(double)RAND_MAX;
trpg2dPoint pt;
pt.x = (ur.x - ll.x)*randNum1;
pt.y = (ur.y - ll.y)*randNum2;
// Jump to the point
bool changes = manager->SetLocation(pt);
sprintf(line,"Jumped to (%f,%f). Tiles to load/unload = %s",pt.x,pt.y,
(changes ? "yes" : "no")); printBuf->prnLine(line);
// Jump to the point
bool changes = manager->SetLocation(pt);
sprintf(line,"Jumped to (%f,%f). Tiles to load/unload = %s",pt.x,pt.y,
(changes ? "yes" : "no")); printBuf->prnLine(line);
// Process the results
ProcessChanges();
// Process the results
ProcessChanges();
}
// Ask the page manager for its final status
@@ -745,7 +745,7 @@ void trpgPageManageTester::Fly_LL_to_UR(double dist)
char line[1024];
if (!manager || !archive || !printBuf)
throw 1;
throw 1;
// Need the extents
trpg2dPoint ll,ur,lod0Size;
@@ -761,15 +761,15 @@ void trpgPageManageTester::Fly_LL_to_UR(double dist)
// Fly the path
trpg2dPoint loc; loc = ll;
do {
loc.x += dist; loc.y += dist;
loc.x += dist; loc.y += dist;
// Jump to next point
bool changes = manager->SetLocation(loc);
sprintf(line,"Moved to (%f,%f). Tiles to load/unload = %s",loc.x,loc.y,
(changes ? "yes" : "no")); printBuf->prnLine(line);
// Jump to next point
bool changes = manager->SetLocation(loc);
sprintf(line,"Moved to (%f,%f). Tiles to load/unload = %s",loc.x,loc.y,
(changes ? "yes" : "no")); printBuf->prnLine(line);
// Process new location
ProcessChanges();
// Process new location
ProcessChanges();
} while (loc.x < ur.x && loc.y < ur.y);
// Ask the page manager for its final status
@@ -788,9 +788,9 @@ void trpgPageManageTester::ProcessChanges()
printBuf->prnLine("Tiles to unload:");
printBuf->IncreaseIndent();
while ((unloadTile = manager->GetNextUnload())) {
unloadTile->GetTileLoc(x,y,lod);
sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line);
manager->AckUnload();
unloadTile->GetTileLoc(x,y,lod);
sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line);
manager->AckUnload();
}
printBuf->DecreaseIndent();
@@ -799,9 +799,9 @@ void trpgPageManageTester::ProcessChanges()
printBuf->prnLine("Tiles to load:");
printBuf->IncreaseIndent();
while ((loadTile = manager->GetNextLoad())) {
loadTile->GetTileLoc(x,y,lod);
sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line);
manager->AckLoad();
loadTile->GetTileLoc(x,y,lod);
sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line);
manager->AckLoad();
}
printBuf->DecreaseIndent();
}

View File

@@ -19,327 +19,327 @@
#include <deque>
/* This file contains class definitions for managers
that help you keep track of data related to
paging. For instance, which tiles to load
in at any given time and what textures you need
to read for a given tile.
that help you keep track of data related to
paging. For instance, which tiles to load
in at any given time and what textures you need
to read for a given tile.
*/
class trpgPageManager;
/* Managed Tiles are used by the trpgPageManager to keep
track of which tiles are loaded and what textures (and
models) they need loaded into memory with them.
track of which tiles are loaded and what textures (and
models) they need loaded into memory with them.
*/
TX_EXDECL class TX_CLDECL trpgManagedTile {
friend class trpgPageManager;
public:
trpgManagedTile(void);
trpgManagedTile(void);
// Called to clear any info out of this tile
void Reset(void);
// Called to clear any info out of this tile
void Reset(void);
/* Call this when you hit a tile header in your own
Scene parser callback. The managed tile
can then keep track of which textures and models
go with this tile.
*/
bool ParseTileHeader(trpgReadBuffer &);
/* Call this when you hit a tile header in your own
Scene parser callback. The managed tile
can then keep track of which textures and models
go with this tile.
*/
bool ParseTileHeader(trpgReadBuffer &);
// Check if the tile is loaded (e.g. the header read in)
bool IsLoaded(void);
// Check if the tile is loaded (e.g. the header read in)
bool IsLoaded(void);
/* Set the tile location. This resets any internal
state we may be keeping.
*/
bool SetTileLoc(int x,int y,int lod);
/* Set the tile location. This resets any internal
state we may be keeping.
*/
bool SetTileLoc(int x,int y,int lod);
// Get the tile location
bool GetTileLoc(int &x,int &y,int &lod);
// Get the tile location
bool GetTileLoc(int &x,int &y,int &lod);
// Return a pointer to the tile header
const trpgTileHeader *GetTileHead(void);
// Return a pointer to the tile header
const trpgTileHeader *GetTileHead(void);
/* Return a pointer to the list of locally defined
materials. As soon as the tile header is read by
ParseTileHeader (which you call) you'll want to get
this list and load the pageable textures. You can
use SetMatData to keep track of our internal texture
structures.
*/
const std::vector<trpgLocalMaterial> *GetLocMatList(void) const;
/* Return a pointer to the list of locally defined
materials. As soon as the tile header is read by
ParseTileHeader (which you call) you'll want to get
this list and load the pageable textures. You can
use SetMatData to keep track of our internal texture
structures.
*/
const std::vector<trpgLocalMaterial> *GetLocMatList(void) const;
/* Returns a pointer to a single local material, if within
the valid range of local materials for this tile.
*/
const trpgLocalMaterial *GetLocMaterial(int id) const;
/* Returns a pointer to a single local material, if within
the valid range of local materials for this tile.
*/
const trpgLocalMaterial *GetLocMaterial(int id) const;
/* Set Local Data for managed tile. The local data would
probably be a pointer to the top of the scene graph you're
using to represent just this tile.
*/
void SetLocalData(void *);
/* Set Local Data for managed tile. The local data would
probably be a pointer to the top of the scene graph you're
using to represent just this tile.
*/
void SetLocalData(void *);
/* Returns the local data you set with SetLocalData.
*/
void *GetLocalData(void) const;
/* Returns the local data you set with SetLocalData.
*/
void *GetLocalData(void) const;
/* Associates a void * with one of the materials referenced
within this tile. The idea here is that you'll want
to load the texture for a given local material and then
pass your own internal texture structure into here as
a void *. That way, the trpgPageManager will keep track
of which textures you should unload when this tile goes
out of range.
*/
bool SetMatData(int id,void *);
/* Associates a void * with one of the materials referenced
within this tile. The idea here is that you'll want
to load the texture for a given local material and then
pass your own internal texture structure into here as
a void *. That way, the trpgPageManager will keep track
of which textures you should unload when this tile goes
out of range.
*/
bool SetMatData(int id,void *);
/* Gets the void * data you associated with a given local
material index. See SetMatData for more information.
*/
void *GetMatData(int id) const;
/* Gets the void * data you associated with a given local
material index. See SetMatData for more information.
*/
void *GetMatData(int id) const;
/* Add Group ID to this tile. This is called by the page
manager to keep track of which group IDs belong to this tile.
We use this information to NULL out the appropriate positions
in the group map help by the page manager.
*/
void AddGroupID(int id);
/* Add Group ID to this tile. This is called by the page
manager to keep track of which group IDs belong to this tile.
We use this information to NULL out the appropriate positions
in the group map help by the page manager.
*/
void AddGroupID(int id);
/* Retrieve the list of group IDs for this tile.
*/
const std::vector<int> *GetGroupIDs(void) const;
/* Retrieve the list of group IDs for this tile.
*/
const std::vector<int> *GetGroupIDs(void) const;
/* Print the current status and information about this managed
Tile.
*/
void Print(trpgPrintBuffer &);
/* Print the current status and information about this managed
Tile.
*/
void Print(trpgPrintBuffer &);
protected:
// Set if a tile is currently loaded
bool isLoaded;
// Tile location info
int x,y,lod;
// Tile Header associated with this tile
trpgTileHeader tileHead;
// Data to keep associated with each individual local material index
std::vector<void *> localMatData;
// Used to keep track of group IDs in this tile
std::vector<int> groupIDs;
// Local data (probably the top of the local scene graph)
void *localData;
// Set if a tile is currently loaded
bool isLoaded;
// Tile location info
int x,y,lod;
// Tile Header associated with this tile
trpgTileHeader tileHead;
// Data to keep associated with each individual local material index
std::vector<void *> localMatData;
// Used to keep track of group IDs in this tile
std::vector<int> groupIDs;
// Local data (probably the top of the local scene graph)
void *localData;
// Note: Should do models too if anyone wanted them.
// Note: Should do models too if anyone wanted them.
};
/* The Page Manager is a helper class that can be used
to keep track of: (1) which tiles need to be loaded
into memory for a given viewer position, (2) which tiles
are currently loaded and (3) which tiles need to be unloaded
when the viewer position moves. The tile list this
class generates is guaranteed to be in the right order
for loading. You would use this class if you're implementing
a TerraPage reader for your visual run-time system.
to keep track of: (1) which tiles need to be loaded
into memory for a given viewer position, (2) which tiles
are currently loaded and (3) which tiles need to be unloaded
when the viewer position moves. The tile list this
class generates is guaranteed to be in the right order
for loading. You would use this class if you're implementing
a TerraPage reader for your visual run-time system.
*/
TX_EXDECL class TX_CLDECL trpgPageManager {
public:
trpgPageManager(void);
virtual ~trpgPageManager(void);
trpgPageManager(void);
virtual ~trpgPageManager(void);
// Initialize with an archive
virtual void Init(trpgr_Archive *);
// Initialize with an archive
virtual void Init(trpgr_Archive *);
/* Set Paging Distance
This is the extra distance outside the visible range
we want to page. The defaults will be valid. You would
set this if you want to pull tiles in earlier. Be sure
to call it before you call Init(), however.
*/
virtual bool SetPageDistFactor(double);
/* Set Paging Distance
This is the extra distance outside the visible range
we want to page. The defaults will be valid. You would
set this if you want to pull tiles in earlier. Be sure
to call it before you call Init(), however.
*/
virtual bool SetPageDistFactor(double);
/* Updates the current location for paging purposes.
Returns true if any load or unloads need to happen.
*/
virtual bool SetLocation(trpg2dPoint &);
/* Updates the current location for paging purposes.
Returns true if any load or unloads need to happen.
*/
virtual bool SetLocation(trpg2dPoint &);
/* Get next tile to load.
The paging manager is keeping track of which tiles
need to be loaded and in what order. This method
returns a pointer to the next one. The user is
expected to call AckLoad() after the tile is loaded.
*/
virtual trpgManagedTile *GetNextLoad(void);
/* Acknowledge Tile Load.
This method should be called when a tile has been
loaded by the caller. This method is used in conjunction
with GetNextLoad().
*/
virtual void AckLoad(void);
/* Get next tile to load.
The paging manager is keeping track of which tiles
need to be loaded and in what order. This method
returns a pointer to the next one. The user is
expected to call AckLoad() after the tile is loaded.
*/
virtual trpgManagedTile *GetNextLoad(void);
/* Acknowledge Tile Load.
This method should be called when a tile has been
loaded by the caller. This method is used in conjunction
with GetNextLoad().
*/
virtual void AckLoad(void);
/* Add Group ID to map.
This should be called when the user encounters a group-like
object while processing the scene graph data from a tile.
The groupId is given by TerraPage and the data should be
the corresponding group object that the user creates in
their own scenegraph toolkit. This information can then
be retrieved later by GetGroupData().
*/
virtual void AddGroupID(trpgManagedTile *,int groupID,void *data);
/* Add Group ID to map.
This should be called when the user encounters a group-like
object while processing the scene graph data from a tile.
The groupId is given by TerraPage and the data should be
the corresponding group object that the user creates in
their own scenegraph toolkit. This information can then
be retrieved later by GetGroupData().
*/
virtual void AddGroupID(trpgManagedTile *,int groupID,void *data);
/* Get Group Data fetches the data cached by the user and
associated with the given groupID. This would be used in
conjunction with trpgAttach nodes to implement geometry paging.
*/
virtual void *GetGroupData(int groupID);
/* Get Group Data fetches the data cached by the user and
associated with the given groupID. This would be used in
conjunction with trpgAttach nodes to implement geometry paging.
*/
virtual void *GetGroupData(int groupID);
/* Get next tile to unload.
The paging manager keeps track of which tiles need
to be unloaded based on a change of location. It's
best if you unload tiles before loading them, but
that's really up to you.
*/
virtual trpgManagedTile *GetNextUnload(void);
/* Acknowledge a tile unload.
You should call this after you've "unloaded" a tile
and all its associated textures.
*/
virtual void AckUnload(void);
/* Get next tile to unload.
The paging manager keeps track of which tiles need
to be unloaded based on a change of location. It's
best if you unload tiles before loading them, but
that's really up to you.
*/
virtual trpgManagedTile *GetNextUnload(void);
/* Acknowledge a tile unload.
You should call this after you've "unloaded" a tile
and all its associated textures.
*/
virtual void AckUnload(void);
/* Stop paging entirely. Call this right before you want to
shut down paging. Everything active will wind up on the
unload lists. Then you can unload those tiles and move on.
*/
virtual bool Stop(void);
/* Stop paging entirely. Call this right before you want to
shut down paging. Everything active will wind up on the
unload lists. Then you can unload those tiles and move on.
*/
virtual bool Stop(void);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
protected:
trpgr_Archive *archive;
trpgr_Archive *archive;
// Center of paging
trpg2dPoint pagePt;
// Center of paging
trpg2dPoint pagePt;
/* Information associated with each terrain level of
detail as related to paging.
*/
class LodPageInfo {
friend class trpgPageManager;
public:
LodPageInfo(void);
virtual ~LodPageInfo(void);
/* Information associated with each terrain level of
detail as related to paging.
*/
class LodPageInfo {
friend class trpgPageManager;
public:
LodPageInfo(void);
virtual ~LodPageInfo(void);
/* Initializes the class with its current LOD.
It figures out all the rest.
*/
virtual bool Init(trpgr_Archive *, int myLod, double scale);
/* Initializes the class with its current LOD.
It figures out all the rest.
*/
virtual bool Init(trpgr_Archive *, int myLod, double scale);
/* Reset the location. This forces a recalculation
of what to load and unload if the cell has changed
or if this is the first SetLocation.
The location passed in must be relative to the southwest
corner of the TerraPage archive.
*/
virtual bool SetLocation(trpg2dPoint &);
/* Reset the location. This forces a recalculation
of what to load and unload if the cell has changed
or if this is the first SetLocation.
The location passed in must be relative to the southwest
corner of the TerraPage archive.
*/
virtual bool SetLocation(trpg2dPoint &);
// Return the next tile to load for this terrain lod
virtual trpgManagedTile *GetNextLoad(void);
// Acknowledge the load. Move the active tile to the
// loaded list.
virtual void AckLoad(void);
// Return the next tile to unload for this terrain lod
virtual trpgManagedTile *GetNextUnload(void);
// Acknowledge the unload. Move the active tile to the
// free list.
virtual void AckUnload(void);
// Called to stop paging. Everything active is dumped on
// the unload list.
virtual bool Stop(void);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
protected:
virtual void Clean(void);
virtual void Update(void);
// Return the next tile to load for this terrain lod
virtual trpgManagedTile *GetNextLoad(void);
// Acknowledge the load. Move the active tile to the
// loaded list.
virtual void AckLoad(void);
// Return the next tile to unload for this terrain lod
virtual trpgManagedTile *GetNextUnload(void);
// Acknowledge the unload. Move the active tile to the
// free list.
virtual void AckUnload(void);
// Called to stop paging. Everything active is dumped on
// the unload list.
virtual bool Stop(void);
// Print current status and content information
virtual void Print(trpgPrintBuffer &);
protected:
virtual void Clean(void);
virtual void Update(void);
// Check if the given tile is within the area we care about
bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne);
// Check if the given tile is within the area we care about
bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne);
bool valid;
bool valid;
// Terrain LOD we're responsible for
int lod;
// Terrain LOD we're responsible for
int lod;
/* Adjusted (e.g. paranoid) distance outward from
which to page this terrain LOD. This takes into
account the distance in the header as well as
any factor the user may have added.
*/
double pageDist;
/* Adjusted (e.g. paranoid) distance outward from
which to page this terrain LOD. This takes into
account the distance in the header as well as
any factor the user may have added.
*/
double pageDist;
/* Max tiles we could have loaded in at any given time.
This is just a guess because it's up to the user
to load (and, more importantly) unload.
*/
int maxNumTiles;
/* Max tiles we could have loaded in at any given time.
This is just a guess because it's up to the user
to load (and, more importantly) unload.
*/
int maxNumTiles;
// Size of a single cell. Copied from the archive.
trpg2dPoint cellSize;
// Size of a single cell. Copied from the archive.
trpg2dPoint cellSize;
// Number of tiles (cells) in each direction
trpg2iPoint lodSize;
// Number of tiles (cells) in each direction
trpg2iPoint lodSize;
/* Area of interest size in cells
This is a linear distance "ahead" of the center cell.
*/
trpg2iPoint aoiSize;
/* Area of interest size in cells
This is a linear distance "ahead" of the center cell.
*/
trpg2iPoint aoiSize;
/* Our effective paging location sits at the middle
of this cell. We don't recalculate unless the
cell changes. */
trpg2iPoint cell;
/* Our effective paging location sits at the middle
of this cell. We don't recalculate unless the
cell changes. */
trpg2iPoint cell;
// List of tiles to load
std::deque<trpgManagedTile *> load;
// List of tiles to unload
std::deque<trpgManagedTile *> unload;
// List of currently loaded tiles
std::deque<trpgManagedTile *> current;
// List of tiles to load
std::deque<trpgManagedTile *> load;
// List of tiles to unload
std::deque<trpgManagedTile *> unload;
// List of currently loaded tiles
std::deque<trpgManagedTile *> current;
// Used by Update. Here because we want to avoid memory allocs, if possible.
std::vector<bool> tmpCurrent;
// Used by Update. Here because we want to avoid memory allocs, if possible.
std::vector<bool> tmpCurrent;
// Set if a load is in progress
// Load w/o ACK
bool activeLoad;
// Set if an unload is in progress
// Unload w/o ACK
bool activeUnload;
// Set if a load is in progress
// Load w/o ACK
bool activeLoad;
// Set if an unload is in progress
// Unload w/o ACK
bool activeUnload;
// List of tile pointers we can reuse
std::deque<trpgManagedTile *> freeList;
};
// List of tile pointers we can reuse
std::deque<trpgManagedTile *> freeList;
};
// Per terrain lod paging information
std::vector<LodPageInfo> pageInfo;
// Per terrain lod paging information
std::vector<LodPageInfo> pageInfo;
// Enumerated type for lastLoad
typedef enum {Load,Unload,None} LoadType;
/* Information about what the pending load/unload operation
is. It's up to the user to complete and acknowledge it.
*/
LoadType lastLoad;
// LOD for the pending load/unload requested operation
int lastLod;
// Tile to be loaded/unloaded
trpgManagedTile *lastTile;
// Enumerated type for lastLoad
typedef enum {Load,Unload,None} LoadType;
/* Information about what the pending load/unload operation
is. It's up to the user to complete and acknowledge it.
*/
LoadType lastLoad;
// LOD for the pending load/unload requested operation
int lastLod;
// Tile to be loaded/unloaded
trpgManagedTile *lastTile;
// Optional scaling factor
double scale;
// Optional scaling factor
double scale;
// Mapping from group IDs to user defined data
typedef std::map<int,void *> ManageGroupMap;
ManageGroupMap groupMap;
// Mapping from group IDs to user defined data
typedef std::map<int,void *> ManageGroupMap;
ManageGroupMap groupMap;
bool valid;
bool valid;
};
/* Page Manager Tester. This class tests a given paging manager
@@ -347,28 +347,28 @@ protected:
*/
TX_EXDECL class TX_CLDECL trpgPageManageTester {
public:
trpgPageManageTester();
virtual ~trpgPageManageTester();
trpgPageManageTester();
virtual ~trpgPageManageTester();
/* Initialize the tester with a paging manager
and an archive.
*/
void Init(trpgPrintBuffer *,trpgPageManager *,trpgr_Archive *);
/* Initialize the tester with a paging manager
and an archive.
*/
void Init(trpgPrintBuffer *,trpgPageManager *,trpgr_Archive *);
/* Feeds the paging manager coordinates starting from
the lower left to upper right of the database in the
given increment.
*/
void Fly_LL_to_UR(double dist=100.0);
/* Feeds the paging manager coordinates starting from
the lower left to upper right of the database in the
given increment.
*/
void Fly_LL_to_UR(double dist=100.0);
/* Jumps around randomly within the archive loading and
unloading as needed.
*/
void RandomTest(int no=100,int seed=-1);
/* Jumps around randomly within the archive loading and
unloading as needed.
*/
void RandomTest(int no=100,int seed=-1);
protected:
// Does the work of "load" and "unloading"
void ProcessChanges();
// Does the work of "load" and "unloading"
void ProcessChanges();
trpgPageManager *manager;
trpgr_Archive *archive;

File diff suppressed because it is too large Load Diff

View File

@@ -18,203 +18,203 @@
#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>
/* 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(in)
trpgReadWriteable(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)
{
strcpy(errMess, "Model is external with no name");
return false;
}
if (type == External && !name)
{
strcpy(errMess, "Model is external with no name");
return false;
}
return true;
return true;
}
// Copy from one to another
trpgModel& trpgModel::operator = (const trpgModel &in)
{
if (name) {
delete [] name;
name = NULL;
}
if (name) {
delete [] name;
name = NULL;
}
type = in.type;
if (in.name)
SetName(in.name);
diskRef = in.diskRef;
useCount = in.useCount;
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()
@@ -227,32 +227,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 || (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);
}
@@ -260,17 +260,17 @@ 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())
{
if(models[i].getErrMess())
strcpy(errMess, models[i].getErrMess());
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;
}
@@ -278,67 +278,67 @@ bool trpgModelTable::isValid() const
// Write out the model table
bool trpgModelTable::Write(trpgWriteBuffer &buf)
{
if (!isValid())
return false;
if (!isValid())
return false;
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)models.size());
for (unsigned int i=0;i<models.size();i++)
models[i].Write(buf);
buf.End();
buf.Begin(TRPGMODELTABLE);
buf.Add((int32)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 || id >= (int)models.size())
return false;
model = models[id];
return true;
if (!isValid() || id < 0 || id >= (int)models.size())
return false;
model = models[id];
return true;
}
trpgModel *trpgModelTable::GetModelRef(int id)
{
if (id < 0 || id >= (int)models.size())
return NULL;
return &models[id];
if (id < 0 || id >= (int)models.size())
return NULL;
return &models[id];
}
bool trpgModelTable::Read(trpgReadBuffer &buf)
{
int32 numModel;
trpgModel model;
trpgToken tok;
int32 len;
bool status;
int32 numModel;
trpgModel model;
trpgToken tok;
int32 len;
bool status;
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
buf.GetToken(tok,len);
if (tok != TRPGMODELREF) throw 1;
buf.PushLimit(len);
status = model.Read(buf);
buf.PopLimit();
if (!status) throw 1;
models.push_back(model);
}
}
catch (...) {
return false;
}
try {
buf.Get(numModel);
for (int i=0;i<numModel;i++) {
buf.GetToken(tok,len);
if (tok != TRPGMODELREF) throw 1;
buf.PushLimit(len);
status = model.Read(buf);
buf.PopLimit();
if (!status) throw 1;
models.push_back(model);
}
}
catch (...) {
return false;
}
return isValid();
return isValid();
}

File diff suppressed because it is too large Load Diff

View File

@@ -17,62 +17,62 @@
#include <stdio.h>
/* trpage_parse.cpp
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
trpgr_Parser is the main class. It parses the basic structure of paging archive
data out of Read Buffers. You should not need to change this.
If you want to parse data out of a different structure instead, look at
subclassing trpgReadBuffer and replacing its virtual methods. That's what
trpgMemReadBuffer is doing.
This source file contains methods for the trpgr_Parser and trpgr_Token classes.
trpgr_Parser is the main class. It parses the basic structure of paging archive
data out of Read Buffers. You should not need to change this.
If you want to parse data out of a different structure instead, look at
subclassing trpgReadBuffer and replacing its virtual methods. That's what
trpgMemReadBuffer is doing.
This file also contains the implementation of trpgSceneParser().
That class implements a set of callbacks for handling the Pushes and Pops
in an archive. You fill in the Start/EndChildren callbacks and register
for the rest of the tokens that you want.
*/
That class implements a set of callbacks for handling the Pushes and Pops
in an archive. You fill in the Start/EndChildren callbacks and register
for the rest of the tokens that you want.
*/
#include <trpage_read.h>
/* ***************************
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 /*tok*/,trpgReadBuffer& /*buf*/) {
// Call the start children callback
parse->StartChildren(parse->lastObject);
parse->parents.push_back(parse->lastObject);
return (void *)1;
}
trpgSceneHelperPush(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Call the start children callback
parse->StartChildren(parse->lastObject);
parse->parents.push_back(parse->lastObject);
return (void *)1;
}
protected:
trpgSceneParser *parse;
trpgSceneParser *parse;
};
// Helper - callback for Pop
class trpgSceneHelperPop : public trpgr_Callback {
public:
trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Make sure we don't have an extra pop
if (parse->parents.size() == 0)
// Note: let someone know about the extra pop
return NULL;
// Call the end children callback
int len = parse->parents.size();
parse->EndChildren(parse->parents[len-1]);
parse->parents.resize(len-1);
return (void *)1;
}
trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; };
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Make sure we don't have an extra pop
if (parse->parents.size() == 0)
// Note: let someone know about the extra pop
return NULL;
// Call the end children callback
int len = parse->parents.size();
parse->EndChildren(parse->parents[len-1]);
parse->parents.resize(len-1);
return (void *)1;
}
protected:
trpgSceneParser *parse;
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 /*tok*/,trpgReadBuffer& /*buf*/) {
// Absorb it quietly
return (void *)1;
}
trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; }
void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) {
// Absorb it quietly
return (void *)1;
}
protected:
trpgSceneParser *parse;
trpgSceneParser *parse;
};
trpgSceneParser::trpgSceneParser()
{
// Register for Push and Pop
AddCallback(TRPG_PUSH,new trpgSceneHelperPush(this));
AddCallback(TRPG_POP,new trpgSceneHelperPop(this));
// Register for Push and Pop
AddCallback(TRPG_PUSH,new trpgSceneHelperPush(this));
AddCallback(TRPG_POP,new trpgSceneHelperPop(this));
// Register for default
SetDefaultCallback(new trpgSceneHelperDefault(this));
// Register for default
SetDefaultCallback(new trpgSceneHelperDefault(this));
}
trpgSceneParser::~trpgSceneParser()
{

View File

@@ -18,183 +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>
/* Set up the callbacks for the scene graph parser.
In our case this is just one read helper with
a switch statement.
In our case this is just one read helper with
a switch statement.
*/
trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelper *inImg,trpgPrintBuffer *inBuf)
{
printBuf = inBuf;
archive = inArch;
imageHelp = inImg;
printBuf = inBuf;
archive = inArch;
imageHelp = inImg;
// Register the readers
AddCallback(TRPG_GEOMETRY,new ReadHelper(this,printBuf));
AddCallback(TRPG_GROUP,new ReadHelper(this,printBuf));
AddCallback(TRPG_ATTACH,new ReadHelper(this,printBuf));
AddCallback(TRPG_BILLBOARD,new ReadHelper(this,printBuf));
AddCallback(TRPG_LOD,new ReadHelper(this,printBuf));
AddCallback(TRPG_TRANSFORM,new ReadHelper(this,printBuf));
AddCallback(TRPG_MODELREF,new ReadHelper(this,printBuf));
AddCallback(TRPG_LAYER,new ReadHelper(this,printBuf));
AddCallback(TRPG_LIGHT,new ReadHelper(this,printBuf));
AddCallback(TRPG_LABEL,new ReadHelper(this,printBuf));
AddCallback(TRPGTILEHEADER,new ReadHelper(this,printBuf));
// Register the readers
AddCallback(TRPG_GEOMETRY,new ReadHelper(this,printBuf));
AddCallback(TRPG_GROUP,new ReadHelper(this,printBuf));
AddCallback(TRPG_ATTACH,new ReadHelper(this,printBuf));
AddCallback(TRPG_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;
trpgTileHeader *tileHead = 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 TRPG_LABEL:
obj = new trpgLabel();
break;
switch (tok) {
case TRPG_GEOMETRY:
obj = new trpgGeometry();
break;
case TRPG_GROUP:
obj = new trpgGroup();
break;
case TRPG_ATTACH:
obj = new trpgAttach();
break;
case TRPG_BILLBOARD:
obj = new trpgBillboard();
break;
case TRPG_LOD:
obj = new trpgLod();
break;
case TRPG_TRANSFORM:
obj = new trpgTransform();
break;
case TRPG_MODELREF:
obj = new trpgModelRef();
break;
case TRPG_LAYER:
obj = new trpgLayer();
break;
case TRPG_LIGHT:
obj = new trpgLight();
break;
case TRPG_LABEL:
obj = new trpgLabel();
break;
case TRPGTILEHEADER:
obj = tileHead = new trpgTileHeader();
break;
};
case TRPGTILEHEADER:
obj = tileHead = new trpgTileHeader();
break;
};
if (obj) {
if (obj->Read(buf))
obj->Print(*pBuf);
// For the tile header, do a little more work
if (tok == TRPGTILEHEADER) {
int numMat;
tileHead->GetNumLocalMaterial(numMat);
for (int i=0;i<numMat;i++) {
trpgLocalMaterial locMat;
tileHead->GetLocalMaterial(i,locMat);
const trpgMaterial *baseMat;
const trpgTexture *baseTex;
int totSize;
trpgrImageHelper *imageHelp = parse->GetImageHelp();
int numImages=1;
locMat.GetNumLocals(numImages);
for (int imgN=0;imgN<numImages;imgN++) {
// read all the images for each local material
imageHelp->GetNthImageInfoForLocalMat(&locMat,imgN,&baseMat,&baseTex,totSize);
if (obj) {
if (obj->Read(buf))
obj->Print(*pBuf);
// For the tile header, do a little more work
if (tok == TRPGTILEHEADER) {
int numMat;
tileHead->GetNumLocalMaterial(numMat);
for (int i=0;i<numMat;i++) {
trpgLocalMaterial locMat;
tileHead->GetLocalMaterial(i,locMat);
const trpgMaterial *baseMat;
const trpgTexture *baseTex;
int totSize;
trpgrImageHelper *imageHelp = parse->GetImageHelp();
int numImages=1;
locMat.GetNumLocals(numImages);
for (int imgN=0;imgN<numImages;imgN++) {
// read all the images for each local material
imageHelp->GetNthImageInfoForLocalMat(&locMat,imgN,&baseMat,&baseTex,totSize);
// Fetch the whole image
{
char *pixels = new char[totSize];
bool failed = false;
try {
failed = !imageHelp->GetNthImageForLocalMat(&locMat,imgN,pixels,totSize);
}
catch (...) {
failed = true;
}
if (failed) {
fprintf(stderr,"Failed to read local image %d from local material %d.\n",imgN,i);
} else
fprintf(stderr,"Read local image %d from local material %d successfully.\n",imgN,i);
delete [] pixels;
}
// Fetch the whole image
{
char *pixels = new char[totSize];
bool failed = false;
try {
failed = !imageHelp->GetNthImageForLocalMat(&locMat,imgN,pixels,totSize);
}
catch (...) {
failed = true;
}
if (failed) {
fprintf(stderr,"Failed to read local image %d from local material %d.\n",imgN,i);
} else
fprintf(stderr,"Read local image %d from local material %d successfully.\n",imgN,i);
delete [] pixels;
}
// Fetch the individual mipmap levels
{
int numMipmap;
bool hasMipmap;
baseTex->GetIsMipmap(hasMipmap);
numMipmap = hasMipmap ? baseTex->CalcNumMipmaps() : 0;
for (int j=1;j<numMipmap;j++) {
//int mipOffset = (const_cast<trpgTexture *>(baseTex))->MipLevelOffset(j);
int mipSize = (const_cast<trpgTexture *>(baseTex))->MipLevelSize(j);
if (mipSize) {
char *pixels = new char[mipSize];
bool failed = false;
try {
failed = !imageHelp->GetNthImageMipLevelForLocalMat(j,&locMat,imgN,pixels,mipSize);
}
catch (...) {
failed = true;
}
if (failed)
fprintf(stderr,"Failed to read mipmap level %d for local image %d from local material %d.\n",j,imgN,i);
else
fprintf(stderr,"Read mipmap level %d for local image %d from local material %d.\n",j,imgN,i);
delete [] pixels;
}
}
}
}
}
}
// Fetch the individual mipmap levels
{
int numMipmap;
bool hasMipmap;
baseTex->GetIsMipmap(hasMipmap);
numMipmap = hasMipmap ? baseTex->CalcNumMipmaps() : 0;
for (int j=1;j<numMipmap;j++) {
//int mipOffset = (const_cast<trpgTexture *>(baseTex))->MipLevelOffset(j);
int mipSize = (const_cast<trpgTexture *>(baseTex))->MipLevelSize(j);
if (mipSize) {
char *pixels = new char[mipSize];
bool failed = false;
try {
failed = !imageHelp->GetNthImageMipLevelForLocalMat(j,&locMat,imgN,pixels,mipSize);
}
catch (...) {
failed = true;
}
if (failed)
fprintf(stderr,"Failed to read mipmap level %d for local image %d from local material %d.\n",j,imgN,i);
else
fprintf(stderr,"Read mipmap level %d for local image %d from local material %d.\n",j,imgN,i);
delete [] pixels;
}
}
}
}
}
}
delete obj;
}
delete obj;
}
// Need to return non-zero. Otherwise it's interpreted as an error
return (void *)1;
// Need to return non-zero. Otherwise it's interpreted as an error
return (void *)1;
}
// The following routine is not compiled if there's no _splitpath
#ifdef _splitpath
/* This is a convenience function to print out the contents
of an entire TerraPage archive.
of an entire TerraPage archive.
There are two versions of this function. The first takes
a file name and the second an opened archive where the header
@@ -202,88 +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);
archive->GetTextStyleTable()->Print(pBuf);
archive->GetSupportStyleTable()->Print(pBuf);
archive->GetLabelPropertyTable()->Print(pBuf);
pBuf.prnLine();
// Print out the header portion
archive->GetHeader()->Print(pBuf);
archive->GetMaterialTable()->Print(pBuf);
archive->GetTexTable()->Print(pBuf);
archive->GetModelTable()->Print(pBuf);
archive->GetTileTable()->Print(pBuf);
archive->GetLightTable()->Print(pBuf);
archive->GetRangeTable()->Print(pBuf);
archive->GetTextStyleTable()->Print(pBuf);
archive->GetSupportStyleTable()->Print(pBuf);
archive->GetLabelPropertyTable()->Print(pBuf);
pBuf.prnLine();
// Read the local images and do the math for the templates
// Read the local images and do the math for the templates
// Now do the tiles
if (!archive->isValid()) return false;
// Now do the tiles
if (!archive->isValid()) return false;
// Parser that prints out a tile scene graph
trpgrImageHelper imageHelp(archive->GetEndian(),archive->getDir(),*archive->GetMaterialTable(),
*archive->GetTexTable());
trpgPrintGraphParser parser(archive,&imageHelp,&pBuf);
// Parser that prints out a tile scene graph
trpgrImageHelper imageHelp(archive->GetEndian(),archive->getDir(),*archive->GetMaterialTable(),
*archive->GetTexTable());
trpgPrintGraphParser parser(archive,&imageHelp,&pBuf);
pBuf.prnLine("====Tile Data====");
int nl,x,y;
trpgMemReadBuffer buf(archive->GetEndian());
// Iterate over the terrain lods
int numLod;
archive->GetHeader()->GetNumLods(numLod);
trpg2iPoint tileSize;
for (nl=0;nl<numLod;nl++) {
archive->GetHeader()->GetLodSize(nl,tileSize);
// Iterate over the tiles
for (x=tileSize.x-1;x>=0;x--)
for (y=0;y<tileSize.y;y++) {
sprintf(ls,"Tile (lod) (x,y) = (%d) (%d,%d)",nl,x,y);
pBuf.prnLine(ls);
if (archive->ReadTile(x,y,nl,buf)) {
if (flags & TRPGPRN_BODY) {
pBuf.IncreaseIndent();
// Parse it (also prints it
parser.Parse(buf);
pBuf.DecreaseIndent();
}
} else
pBuf.prnLine(" Couldn't read tile.");
}
}
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;
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,87 +19,87 @@
#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(trpgr_Archive *,trpgrImageHelper *,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(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf) {pBuf = inBuf; parse = inPG;};
void *Parse(trpgToken,trpgReadBuffer &buf);
protected:
trpgPrintBuffer *pBuf;
trpgPrintGraphParser *parse;
};
/* 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; };
// 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;
trpgr_Archive *archive;
trpgrImageHelper *imageHelp;
trpgPrintBuffer *printBuf;
trpgr_Archive *archive;
trpgrImageHelper *imageHelp;
};
// Print utitility for while archive

View File

@@ -14,9 +14,9 @@
*/
/* trpage_range.cpp
Methods for the Range Table. Consult trpg_geom.h for details
on what this is and how it works.
*/
Methods for the Range Table. Consult trpg_geom.h for details
on what this is and how it works.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -26,290 +26,290 @@
#include <trpage_read.h>
/* *******************
Range Methods
Range Methods
*******************
*/
trpgRange::trpgRange(void)
{
category = NULL;
subCategory = NULL;
Reset();
category = NULL;
subCategory = NULL;
Reset();
}
trpgRange::~trpgRange(void)
{
Reset();
Reset();
}
trpgRange::trpgRange(const trpgRange &in):
trpgReadWriteable(in)
trpgReadWriteable(in)
{
category = NULL;
subCategory = NULL;
*this = in;
category = NULL;
subCategory = NULL;
*this = in;
}
void trpgRange::Reset(void)
{
errMess[0] = '\0';
if (category)
delete [] category;
category = NULL;
if (subCategory)
delete [] subCategory;
subCategory = NULL;
errMess[0] = '\0';
if (category)
delete [] category;
category = NULL;
if (subCategory)
delete [] subCategory;
subCategory = NULL;
inLod = outLod = 0.0;
priority = 0;
inLod = outLod = 0.0;
priority = 0;
}
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 >= (int)rangeList.size())
return false;
if (id < 0 || id >= (int)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 >= (int)rangeList.size())
return false;
if (id < 0 || id >= (int)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 (unsigned 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 (unsigned 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;
trpgToken tok;
int32 len;
valid = false;
int32 numRange;
trpgToken tok;
int32 len;
valid = false;
try {
buf.Get(numRange);
if (numRange < 0) throw 1;
for (int i=0;i<numRange;i++) {
// Read in the individual range
buf.GetToken(tok,len);
if (tok != TRPG_RANGE) throw 1;
buf.PushLimit(len);
trpgRange range;
bool status = range.Read(buf);
buf.PopLimit();
if (!status) throw 1;
rangeList.push_back(range);
}
try {
buf.Get(numRange);
if (numRange < 0) throw 1;
for (int i=0;i<numRange;i++) {
// Read in the individual range
buf.GetToken(tok,len);
if (tok != TRPG_RANGE) throw 1;
buf.PushLimit(len);
trpgRange range;
bool status = range.Read(buf);
buf.PopLimit();
if (!status) throw 1;
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(inTab.rangeList[i]);
for (unsigned int i=0;i<inTab.rangeList.size();i++)
rangeList.push_back(inTab.rangeList[i]);
return *this;
return *this;
}

View File

@@ -18,9 +18,9 @@
#include <string.h>
/* trpage_rarchive.cpp
This source file implements the methods for a trpgr_Archive.
The Read Archive is used to read a paging archive from disk.
*/
This source file implements the methods for a trpgr_Archive.
The Read Archive is used to read a paging archive from disk.
*/
#include <trpage_read.h>
#include <trpage_compat.h>
@@ -28,289 +28,289 @@
// 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" PATHSEPERATOR "%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()
{
int ret;
int ret;
if (!fp || headerRead)
return false;
if (!fp || headerRead)
return false;
headerRead = true;
headerRead = true;
// Next int64 should be the header size
trpgEndian cpuNess = trpg_cpu_byte_order();
int32 headerSize;
if (fread(&headerSize,sizeof(int32),1,fp) != 1) return false;
if (ness != cpuNess)
headerSize = trpg_byteswap_int(headerSize);
int headLen = headerSize;
if (headLen < 0) 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;
// 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;
// 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;
// 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);
// 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" PATHSEPERATOR "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 >= (unsigned int)numLods) return false;
trpg2iPoint lodSize;
header.GetLodSize(lod,lodSize);
if (x >= (unsigned int)lodSize.x || y >= (unsigned int)lodSize.y) return false;
// Reality check the address
int32 numLods;
header.GetNumLods(numLods);
if (lod >= (unsigned int)numLods) return false;
trpg2iPoint lodSize;
header.GetLodSize(lod,lodSize);
if (x >= (unsigned int)lodSize.x || y >= (unsigned int)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" PATHSEPERATOR "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;
return &textStyleTable;
}
const trpgSupportStyleTable *trpgr_Archive::GetSupportStyleTable() const
{
return &supportStyleTable;
return &supportStyleTable;
}
const trpgLabelPropertyTable *trpgr_Archive::GetLabelPropertyTable() const
{
return &labelPropertyTable;
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 >= (unsigned int)maxXY.x || y>= (unsigned int)maxXY.y)
return false;
if (!header.isValid())
return false;
int32 numLod;
header.GetNumLods(numLod);
trpg2iPoint maxXY;
header.GetLodSize(lod,maxXY);
if (x >= (unsigned int)maxXY.x || y>= (unsigned int)maxXY.y)
return false;
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;
}
/* *****************
@@ -319,209 +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" PATHSEPERATOR "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,0,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)
{
return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize);
return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize);
}
bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index,
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize)
{
// Get the base material for the Local Material
int32 matSubTable,matID;
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;
// 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;
// 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;
// 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;
totSize = tex->CalcTotalSize();
totSize = tex->CalcTotalSize();
*retTex = tex;
*retMat = mat;
return true;
*retTex = tex;
*retMat = mat;
return true;
}
bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize)
{
return GetNthImageForLocalMat(locMat, 0, data, dataSize);
return GetNthImageForLocalMat(locMat, 0, data, dataSize);
}
bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,int index, char *data,int dataSize)
{
if (!locMat->isValid()) return false;
if (!locMat->isValid()) return false;
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
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;
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;
};
// 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;
return true;
}
bool trpgrImageHelper::GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize)
{
return GetNthImageMipLevelForLocalMat(miplevel, locMat, 0, data, dataSize);
return GetNthImageMipLevelForLocalMat(miplevel, locMat, 0, data, dataSize);
}
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 (index>0) return false; // not yet, folks, if ever. index>1 means sensors for now.
if (!locMat->isValid()) return false;
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
const trpgMaterial *mat;
const trpgTexture *tex;
int totSize;
if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize))
return false;
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
return false;
if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 )
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;
// 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;
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;
};
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;
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 ((int)strlen(dir) + nameLen + 2 > pathLen)
return false;
if ((int)strlen(dir) + nameLen + 2 > pathLen)
return false;
sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);
sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name);
return true;
return true;
}

View File

@@ -18,221 +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_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
// 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;
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);
/* 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 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);
/* 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);
/* 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 nth image associated with this local material
*/
virtual bool GetNthImageForLocalMat(const trpgLocalMaterial *locMat, int index, char *data,int dataSize);
/* 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);
/* 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);
/* 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);
/* 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;
virtual const trpgLabelPropertyTable *GetLabelPropertyTable() const;
virtual const trpgTextStyleTable *GetTextStyleTable() const;
virtual const trpgSupportStyleTable *GetSupportStyleTable() 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;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
bool headerRead;
trpgEndian ness;
FILE *fp;
int fid;
// Header info
char dir[1024];
trpgHeader header;
trpgMatTable materialTable;
trpgTexTable texTable;
trpgModelTable modelTable;
trpgTileTable tileTable;
trpgLightTable lightTable;
trpgRangeTable rangeTable;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
trpgrAppFileCache *tileCache;
trpgrAppFileCache *tileCache;
};
class trpgSceneHelperPush;
class trpgSceneHelperPop;
class trpgSceneHelperDefault;
/* Scene Parser
This class assists in parsing a scene graph structure (tiles and models).
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
parser.
{group:Archive Reading}
*/
This class assists in parsing a scene graph structure (tiles and models).
To use it, do an archive ReadTile and pass the resulting Read Buffer to this
parser.
{group:Archive Reading}
*/
TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser {
friend class trpgSceneHelperPush;
friend class trpgSceneHelperPop;
friend class trpgSceneHelperDefault;
friend class trpgSceneHelperPush;
friend class trpgSceneHelperPop;
friend class trpgSceneHelperDefault;
public:
trpgSceneParser(void);
virtual ~trpgSceneParser(void);
trpgSceneParser(void);
virtual ~trpgSceneParser(void);
protected:
// Start defining children for the given object
virtual bool StartChildren(void *) { return true;};
virtual bool EndChildren(void *) { return true;};
// Start defining children for the given object
virtual bool StartChildren(void *) { return true;};
virtual bool EndChildren(void *) { return true;};
// List of objects whose children we're working on
std::vector<void *> parents;
// List of objects whose children we're working on
std::vector<void *> parents;
};
#endif

View File

@@ -18,15 +18,15 @@
#include <math.h>
/* trpage_readbuf.cpp
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
#include <trpage_io.h>
#include <trpage_swap.h>
@@ -39,263 +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_llong(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;
int32 len;
// Get the length first
if (!Get(len)) return false;
// Get the length first
if (!Get(len)) return false;
if (len < 0)
return false;
// Note: Should fix this
char *tmpStr = new char[len+1];
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;
// Read it
if (!GetData(tmpStr,len)) return false;
tmpStr[len] = 0;
str = tmpStr;
str = tmpStr;
return true;
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)
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
#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
@@ -303,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 (unsigned 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 (unsigned int i=0;i<limits.size();i++)
limits[i] -= len;
}
/* *************************
@@ -339,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 (unsigned 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
@@ -452,195 +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)
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) != (unsigned int)len) {
valid = false;
return false;
}
if (fread(data,sizeof(char),len,fp) != (unsigned int)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 baseOffset,int32 objOffset,int32 dataSize)
{
if (!valid) return false;
if (!valid) return false;
// Seek to the right place
int result;
if ((result = fseek(fp,baseOffset,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 total object 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)
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;
}
// It's all right to read less than the whole data block
if (objOffset+dataSize > len)
return false;
// It's all right to read less than the whole data block
if (objOffset+dataSize > len)
return false;
// Skip to the object offset
if (fseek(fp,objOffset,SEEK_CUR)) {
valid = false;
return false;
}
// 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) != (unsigned int)dataSize) {
valid = false;
return false;
}
// Read the raw data
// Note: What about byte swapping?
if (fread(data,sizeof(char),dataSize,fp) != (unsigned int)dataSize) {
valid = false;
return false;
}
return true;
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;
break;
}
}
// 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 || (oldTime == -1) || (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;
// 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++;
timeCount++;
return of.afile;
return of.afile;
}
// Constructor for OpenFile class
trpgrAppFileCache::OpenFile::OpenFile()
{
afile = NULL;
lastUsed = 0;
id = -1;
afile = NULL;
lastUsed = 0;
id = -1;
}

View File

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

View File

@@ -18,221 +18,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>
/*
{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)
typedef std::map<int,trpgReadGroupBase *> GroupMap;
typedef std::map<int,trpgReadGroupBase *> GroupMap;
#else
typedef std::map<int,trpgReadGroupBase *,std::less<int> > GroupMap;
typedef std::map<int,trpgReadGroupBase *,std::less<int> > GroupMap;
#endif
trpgSceneGraphParser(void);
virtual ~trpgSceneGraphParser(void) { };
// Call this instead of Parse()
// Deleting it is your responsibility
trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &);
trpgReadGroupBase *GetCurrTop(void); // Get the current parent object
trpgReadTileHeader *GetTileHeaderRef(void);
trpgSceneGraphParser(void);
virtual ~trpgSceneGraphParser(void) { };
// Call this instead of Parse()
// Deleting it is your responsibility
trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &);
trpgReadGroupBase *GetCurrTop(void); // Get the current parent object
trpgReadTileHeader *GetTileHeaderRef(void);
// For use by the helpers only
GroupMap *GetGroupMap(void);
// For use by the helpers only
GroupMap *GetGroupMap(void);
protected:
bool StartChildren(void *);
bool EndChildren(void *);
trpgReadNode *currTop; // Current parent group
trpgReadNode *top; // Top of everything
GroupMap *gmap;
trpgReadTileHeader tileHead; // Tile header gets read into here
bool StartChildren(void *);
bool EndChildren(void *);
trpgReadNode *currTop; // Current parent group
trpgReadNode *top; // Top of everything
GroupMap *gmap;
trpgReadTileHeader tileHead; // Tile header gets read into here
};
/* Test Archive
Utility function that loads and tests all tiles.
The only reason you'd want to call this is to test a TerraPage archive
you'd written.
*/
// {group:Demonstration Scene Graph}
Utility function that loads and tests all tiles.
The only reason you'd want to call this is to test a TerraPage archive
you'd written.
*/
// {group:Demonstration Scene Graph}
TX_CPPDECL bool trpgTestArchive(trpgr_Archive &);
#endif

View File

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

View File

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

View File

@@ -14,8 +14,8 @@
*/
/* trpage_sys.h
System specific declarations.
*/
System specific declarations.
*/
#ifndef trpage_sys_h_
#define trpage_sys_h_
@@ -29,11 +29,11 @@
#endif
#if defined(_WIN32)
/* *********************
System Specific Section.
This is currently set up for win32.
*********************
*/
/* *********************
System Specific Section.
This is currently set up for win32.
*********************
*/
#include <windows.h>

View File

@@ -18,230 +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>
/* 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()
{
errMess[0] = '\0';
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 || lod >= (int)lodInfo.size())
return;
if (nx <= 0 || ny <= 0 || lod < 0 || lod >= (int)lodInfo.size())
return;
// Got a table we need to maintain
if (mode == Local) {
// If there's a pre-existing table, we need to preserve the entries
LodInfo oldLodInfo = lodInfo[lod];
// Got a table we need to maintain
if (mode == Local) {
// If there's a pre-existing table, we need to preserve the entries
LodInfo oldLodInfo = lodInfo[lod];
LodInfo &li = lodInfo[lod];
li.numX = nx; li.numY = ny;
int numTile = li.numX*li.numY;
li.addr.resize(numTile);
li.elev_min.resize(numTile,0.0);
li.elev_max.resize(numTile,0.0);
LodInfo &li = lodInfo[lod];
li.numX = nx; li.numY = ny;
int numTile = li.numX*li.numY;
li.addr.resize(numTile);
li.elev_min.resize(numTile,0.0);
li.elev_max.resize(numTile,0.0);
// Copy pre-existing data if it's there
if (oldLodInfo.addr.size() > 0) {
for (int x=0;x<oldLodInfo.numX;x++) {
for (int y=0;y<oldLodInfo.numY;y++) {
int oldLoc = y*oldLodInfo.numX + x;
int newLoc = y*li.numX + x;
li.addr[newLoc] = oldLodInfo.addr[oldLoc];
li.elev_min[newLoc] = oldLodInfo.elev_min[oldLoc];
li.elev_max[newLoc] = oldLodInfo.elev_max[oldLoc];
}
}
}
}
valid = true;
// Copy pre-existing data if it's there
if (oldLodInfo.addr.size() > 0) {
for (int x=0;x<oldLodInfo.numX;x++) {
for (int y=0;y<oldLodInfo.numY;y++) {
int oldLoc = y*oldLodInfo.numX + x;
int newLoc = y*li.numX + x;
li.addr[newLoc] = oldLodInfo.addr[oldLoc];
li.elev_min[newLoc] = oldLodInfo.elev_min[oldLoc];
li.elev_max[newLoc] = oldLodInfo.elev_max[oldLoc];
}
}
}
}
valid = true;
}
void trpgTileTable::SetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 zmin,float32 zmax)
{
if (lod < 0 || lod >= (int)lodInfo.size()) return;
if (mode != Local)
return;
LodInfo &li = lodInfo[lod];
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return;
if (lod < 0 || lod >= (int)lodInfo.size()) return;
if (mode != Local)
return;
LodInfo &li = lodInfo[lod];
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return;
int loc = y*li.numX + x;
li.addr[loc] = ref;
li.elev_min[loc] = zmin;
li.elev_max[loc] = zmax;
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 || lod >= (int)lodInfo.size()) return false;
if (mode != Local)
return false;
const LodInfo &li = lodInfo[lod];
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return false;
if (lod < 0 || lod >= (int)lodInfo.size()) return false;
if (mode != Local)
return false;
const LodInfo &li = lodInfo[lod];
if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
return false;
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 (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 (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]);
}
}
}
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()
{
@@ -252,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 || no >= (int)matList.size())
return;
matList[no] = id;
if (no < 0 || no >= (int)matList.size())
return;
matList[no] = id;
}
void trpgTileHeader::SetModel(int no,int id)
{
if (no < 0 || no >= (int)modelList.size())
return;
modelList[no] = id;
if (no < 0 || no >= (int)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 (unsigned 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 (unsigned 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
@@ -311,7 +311,7 @@ bool trpgTileHeader::GetNumLocalMaterial(int32 &retNum) const
bool trpgTileHeader::GetLocalMaterial(int32 id,trpgLocalMaterial &retMat) const
{
if (id < 0 || id >= (int)locMats.size())
return false;
return false;
retMat = locMats[id];
@@ -328,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 || id >= (int)matList.size())
return false;
mat = matList[id];
return true;
if (!isValid() || id < 0 || id >= (int)matList.size())
return false;
mat = matList[id];
return true;
}
bool trpgTileHeader::GetNumModel(int32 &no) const
{
if (!isValid()) return false;
no = modelList.size();
return true;
if (!isValid()) return false;
no = modelList.size();
return true;
}
bool trpgTileHeader::GetModel(int32 id,int32 &m) const
{
if (!isValid() || id < 0 || id >= (int)modelList.size())
return false;
m = modelList[id];
return true;
if (!isValid() || id < 0 || id >= (int)modelList.size())
return false;
m = modelList[id];
return true;
}
bool trpgTileHeader::GetDate(int32 &d) const
{
if (!isValid()) return false;
d = date;
return true;
if (!isValid()) return false;
d = date;
return true;
}
// Validity check
bool trpgTileHeader::isValid() const
{
return true;
return true;
}
// Write to a buffer
bool trpgTileHeader::Write(trpgWriteBuffer &buf)
{
unsigned int i;
unsigned int i;
if (!isValid())
return false;
for (i=0;i<locMats.size();i++)
if (!locMats[i].isValid())
return false;
if (!isValid())
return false;
for (i=0;i<locMats.size();i++)
if (!locMats[i].isValid())
return false;
buf.Begin(TRPGTILEHEADER);
buf.Begin(TRPGTILEHEADER);
buf.Begin(TRPG_TILE_MATLIST);
buf.Add((int32)matList.size());
for (i=0;i<matList.size();i++)
buf.Add(matList[i]);
buf.End();
buf.Begin(TRPG_TILE_MODELLIST);
buf.Add((int32)modelList.size());
for (i=0;i<modelList.size();i++)
buf.Add(modelList[i]);
buf.End();
buf.Begin(TRPG_TILE_DATE);
buf.Add(date);
buf.End();
buf.Begin(TRPG_TILE_LOCMATLIST);
buf.Add((int32)locMats.size());
for (i=0;i<locMats.size();i++)
locMats[i].Write(buf);
buf.End();
buf.Begin(TRPG_TILE_MATLIST);
buf.Add((int32)matList.size());
for (i=0;i<matList.size();i++)
buf.Add(matList[i]);
buf.End();
buf.Begin(TRPG_TILE_MODELLIST);
buf.Add((int32)modelList.size());
for (i=0;i<modelList.size();i++)
buf.Add(modelList[i]);
buf.End();
buf.Begin(TRPG_TILE_DATE);
buf.Add(date);
buf.End();
buf.Begin(TRPG_TILE_LOCMATLIST);
buf.Add((int32)locMats.size());
for (i=0;i<locMats.size();i++)
locMats[i].Write(buf);
buf.End();
buf.End();
buf.End();
return true;
return true;
}
// Tile Header CB
@@ -407,81 +407,81 @@ bool trpgTileHeader::Write(trpgWriteBuffer &buf)
// We want the tile header to be expandable, so be careful here
class tileHeaderCB : public trpgr_Callback {
public:
void * Parse(trpgToken,trpgReadBuffer &);
trpgTileHeader *head;
void * Parse(trpgToken,trpgReadBuffer &);
trpgTileHeader *head;
};
void * tileHeaderCB::Parse(trpgToken tok,trpgReadBuffer &buf)
{
int32 no,id,date,i;
int32 no,id,date,i;
try {
switch (tok) {
case TRPG_TILE_MATLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i = 0;i < no; i++) {
buf.Get(id);
head->AddMaterial(id);
}
break;
case TRPG_TILE_MODELLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i=0;i<no;i++) {
buf.Get(id);
head->AddModel(id);
}
break;
case TRPG_TILE_DATE:
buf.Get(date);
head->SetDate(date);
break;
case TRPG_TILE_LOCMATLIST:
{
int32 numLocMat;
buf.Get(numLocMat);
if (numLocMat < 0) throw 1;
std::vector<trpgLocalMaterial> *locMats;
locMats = const_cast<std::vector<trpgLocalMaterial> *> (head->GetLocalMaterialList());
locMats->resize(numLocMat);
for (i=0;i<numLocMat;i++) {
trpgToken matTok;
int32 len;
buf.GetToken(matTok,len);
if (matTok != TRPGLOCALMATERIAL) throw 1;
buf.PushLimit(len);
trpgLocalMaterial &locMat = (*locMats)[i];
locMat.Read(buf);
buf.PopLimit();
}
}
break;
default:
// Don't care
break;
}
}
catch (...) {
return NULL;
}
try {
switch (tok) {
case TRPG_TILE_MATLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i = 0;i < no; i++) {
buf.Get(id);
head->AddMaterial(id);
}
break;
case TRPG_TILE_MODELLIST:
buf.Get(no);
if (no < 0) throw 1;
for (i=0;i<no;i++) {
buf.Get(id);
head->AddModel(id);
}
break;
case TRPG_TILE_DATE:
buf.Get(date);
head->SetDate(date);
break;
case TRPG_TILE_LOCMATLIST:
{
int32 numLocMat;
buf.Get(numLocMat);
if (numLocMat < 0) throw 1;
std::vector<trpgLocalMaterial> *locMats;
locMats = const_cast<std::vector<trpgLocalMaterial> *> (head->GetLocalMaterialList());
locMats->resize(numLocMat);
for (i=0;i<numLocMat;i++) {
trpgToken matTok;
int32 len;
buf.GetToken(matTok,len);
if (matTok != TRPGLOCALMATERIAL) throw 1;
buf.PushLimit(len);
trpgLocalMaterial &locMat = (*locMats)[i];
locMat.Read(buf);
buf.PopLimit();
}
}
break;
default:
// Don't care
break;
}
}
catch (...) {
return NULL;
}
return head;
return head;
}
// Read tile header
bool trpgTileHeader::Read(trpgReadBuffer &buf)
{
tileHeaderCB tcb;
trpgr_Parser parse;
tileHeaderCB tcb;
trpgr_Parser parse;
tcb.head = this;
parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_DATE,&tcb,false);
// New for 2.0
parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false);
parse.Parse(buf);
tcb.head = this;
parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false);
parse.AddCallback(TRPG_TILE_DATE,&tcb,false);
// New for 2.0
parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false);
parse.Parse(buf);
return isValid();
return isValid();
}

View File

@@ -16,8 +16,8 @@
#include <trpage_util.h>
/* trpage_util.cpp
This source file implements various utility routines for paging archive
*/
This source file implements various utility routines for paging archive
*/
/* The merge routine used to be in here.
However, merge isn't actually general enough to be part of the library.

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -18,313 +18,313 @@
#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>
/* 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 += val; }
// Helper functions
inline void AddStripStat(int val) { stripStat[MIN(14,val)]++; totalStripTri += val; totalTri += val; numStrip++;}
inline void AddFanStat(int val) { fanStat[MIN(14,val)]++; totalFanTri += val; totalTri += val; numFan++;}
inline void AddBagStat(int val) { totalBagTri += val; totalTri += val;}
inline void AddQuadStat(int val) { totalQuad += val; }
};
/* Geometry Helper
Collects up geometry and tries to form triangle strips, fans,
and groups of triangles.
Right now this looks for a very careful ordering. If that ordering
isn't there you won't get useful tristrips or fans. You can, however
use this class as a starting point and build something more akin
to the geometry builder in Performer.
{group:Archive Writing}
Collects up geometry and tries to form triangle strips, fans,
and groups of triangles.
Right now this looks for a very careful ordering. If that ordering
isn't there you won't get useful tristrips or fans. You can, however
use this class as a starting point and build something more akin
to the geometry builder in Performer.
{group:Archive Writing}
*/
TX_EXDECL class TX_CLDECL trpgwGeomHelper {
public:
trpgwGeomHelper(void);
virtual ~trpgwGeomHelper(void);
enum {UseDouble,UseFloat};
trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble);
void init(trpgWriteBuffer *,int dataType=UseDouble);
virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default)
virtual void Reset(void);
// Start/End polygon definition
virtual void StartPolygon(void);
virtual void EndPolygon(void);
virtual void ResetPolygon(void); // If you change your mind about the current poly
// Set the current state
// Note: Currently you *must* set all of these
virtual void SetColor(trpgColor &);
virtual void SetTexCoord(trpg2dPoint &);
virtual void AddTexCoord(trpg2dPoint &); // for multiple textures
virtual void SetNormal(trpg3dPoint &);
virtual void SetMaterial(int32);
virtual void AddMaterial(int32); // for multiple textures
// Pull the state info together and add a vertex
virtual void AddVertex(trpg3dPoint &);
trpgwGeomHelper(void);
virtual ~trpgwGeomHelper(void);
enum {UseDouble,UseFloat};
trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble);
void init(trpgWriteBuffer *,int dataType=UseDouble);
virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default)
virtual void Reset(void);
// Start/End polygon definition
virtual void StartPolygon(void);
virtual void EndPolygon(void);
virtual void ResetPolygon(void); // If you change your mind about the current poly
// Set the current state
// Note: Currently you *must* set all of these
virtual void SetColor(trpgColor &);
virtual void SetTexCoord(trpg2dPoint &);
virtual void AddTexCoord(trpg2dPoint &); // for multiple textures
virtual void SetNormal(trpg3dPoint &);
virtual void SetMaterial(int32);
virtual void AddMaterial(int32); // for multiple textures
// Pull the state info together and add a vertex
virtual void AddVertex(trpg3dPoint &);
// Dump whatever we're doing and move on
virtual void FlushGeom(void);
// Dump whatever we're doing and move on
virtual void FlushGeom(void);
// Get the Min and Max Z values
virtual void GetZMinMax(double &min,double &max);
// Get the Min and Max Z values
virtual void GetZMinMax(double &min,double &max);
// Get statistics for whatever we built
trpgwGeomStats *GetStats(void) { return &stats; }
// Get statistics for whatever we built
trpgwGeomStats *GetStats(void) { return &stats; }
protected:
int mode;
int dataType;
trpgWriteBuffer *buf;
int mode;
int dataType;
trpgWriteBuffer *buf;
/* Builds strips and fans from the triangle array.
We (TERREX) are assuming a certain ordering in our vertex array
because we do this optimization elsewhere. This won't work well
for anyone else. What you will need to do if you want good
performance is to implement a more generic form of this method.
All you should have to do is override Optimize(). You've
got the triangle arrays and a guarantee that the triangles
have the same material. All you really need is a decent fan/strip
algorithm.
*/
virtual void Optimize(void);
/* Builds strips and fans from the triangle array.
We (TERREX) are assuming a certain ordering in our vertex array
because we do this optimization elsewhere. This won't work well
for anyone else. What you will need to do if you want good
performance is to implement a more generic form of this method.
All you should have to do is override Optimize(). You've
got the triangle arrays and a guarantee that the triangles
have the same material. All you really need is a decent fan/strip
algorithm.
*/
virtual void Optimize(void);
// Reset Triangle arrays
virtual void ResetTri(void);
// Reset Triangle arrays
virtual void ResetTri(void);
// Collections of geometry
trpgGeometry strips,fans,bags;
// Collections of geometry
trpgGeometry strips,fans,bags;
// Temporary data arrays for triangles/quads
std::vector<int32> matTri;
std::vector<trpg2dPoint> tex;
std::vector<trpg3dPoint> norm,vert;
// Data arrays for a polygon
std::vector<int32> matPoly;
std::vector<trpg2dPoint> polyTex;
std::vector<trpg3dPoint> polyNorm,polyVert;
// Single points
std::vector<trpg2dPoint> tmpTex;
trpg3dPoint tmpNorm;
trpgColor tmpCol;
// Temporary data arrays for triangles/quads
std::vector<int32> matTri;
std::vector<trpg2dPoint> tex;
std::vector<trpg3dPoint> norm,vert;
// Data arrays for a polygon
std::vector<int32> matPoly;
std::vector<trpg2dPoint> polyTex;
std::vector<trpg3dPoint> polyNorm,polyVert;
// Single points
std::vector<trpg2dPoint> tmpTex;
trpg3dPoint tmpNorm;
trpgColor tmpCol;
// Geometry status built up as we go
trpgwGeomStats stats;
// Geometry status built up as we go
trpgwGeomStats stats;
// Keeps track of min and max z values
double zmin,zmax;
// Keeps track of min and max z values
double zmin,zmax;
};
/* Image Write Helper.
Used to manage textures being added to a TerraPage archive.
It can write Local and Tile Local textures and also manages
the names of External textures (but you have to write those yourself).
Used to manage textures being added to a TerraPage archive.
It can write Local and Tile Local textures and also manages
the names of External textures (but you have to write those yourself).
*/
TX_EXDECL class TX_CLDECL trpgwImageHelper {
public:
trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &);
virtual ~trpgwImageHelper(void);
trpgwImageHelper(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,bool lookForExisting=true);
// 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);
virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,int sizeZ,trpgTexture::ImageOrg org,bool isMipmap,char *data,int &texID);
/* Adds an entry to the texture table for 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);
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);
/* 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);
// 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,trpg2dPoint &ll,trpg2dPoint &ur);
// 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 &);
virtual bool SetLabelPropertyTable(const trpgLabelPropertyTable &);
virtual bool SetSupportStyleTable(const trpgSupportStyleTable &);
virtual bool SetTextStyleTable(const trpgTextStyleTable &);
// Set functions. Have to fill all these out before writing
virtual bool SetHeader(const trpgHeader &);
virtual bool SetMaterialTable(const trpgMatTable &);
virtual bool SetTextureTable(const trpgTexTable &);
virtual bool SetModelTable(const trpgModelTable &);
virtual bool SetLightTable(const trpgLightTable &);
virtual bool SetRangeTable(const trpgRangeTable &);
virtual bool SetLabelPropertyTable(const trpgLabelPropertyTable &);
virtual bool SetSupportStyleTable(const trpgSupportStyleTable &);
virtual bool SetTextStyleTable(const trpgTextStyleTable &);
// Get functions. If we're doing a regenerate we need to get at these
virtual trpgHeader *GetHeader();
virtual trpgMatTable *GetMatTable();
virtual trpgTexTable *GetTextureTable();
virtual trpgModelTable *GetModelTable();
virtual trpgLightTable *GetLightTable();
virtual trpgRangeTable *GetRangeTable();
virtual trpgLabelPropertyTable *GetLabelPropertyTable();
virtual trpgTextStyleTable *GetTextStyleTable();
virtual trpgSupportStyleTable *GetSupportStyleTable();
// Get functions. If we're doing a regenerate we need to get at these
virtual trpgHeader *GetHeader();
virtual trpgMatTable *GetMatTable();
virtual trpgTexTable *GetTextureTable();
virtual trpgModelTable *GetModelTable();
virtual trpgLightTable *GetLightTable();
virtual trpgRangeTable *GetRangeTable();
virtual trpgLabelPropertyTable *GetLabelPropertyTable();
virtual trpgTextStyleTable *GetTextStyleTable();
virtual trpgSupportStyleTable *GetSupportStyleTable();
virtual bool IncrementTileFile(void);
virtual bool DesignateTileFile(int);
virtual bool IncrementTileFile(void);
virtual bool DesignateTileFile(int);
// Write functions.
// For now, the header is written last.
// Write functions.
// For now, the header is written last.
virtual bool OpenFile(const char *,const char *);
virtual void CloseFile(void);
virtual bool WriteHeader(void);
virtual bool CheckpointHeader(void);
virtual bool WriteTile(unsigned int,unsigned int,unsigned int,float zmin,float zmax,
const trpgMemWriteBuffer *,const trpgMemWriteBuffer *);
// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &);
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;};
bool isValid(void) const;
const char *getErrMess() const;
char* getDir(void){return dir;};
class TileFileEntry {
public:
int x,y,lod; // Identifying info for tile
float zmin,zmax;
int32 offset; // Offset into file
};
class TileFile {
public:
int id;
std::vector<TileFileEntry> tiles;
};
class TileFileEntry {
public:
int x,y,lod; // Identifying info for tile
float zmin,zmax;
int32 offset; // Offset into file
};
class TileFile {
public:
int id;
std::vector<TileFileEntry> tiles;
};
protected:
// Set if we're adding to an existing archive
bool isRegenerate;
// Set if we're adding to an existing archive
bool isRegenerate;
// Used to keep track of which tiles are in which file
// Used to keep track of which tiles are in which file
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;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
trpgHeader header;
trpgMatTable matTable;
trpgTexTable texTable;
trpgModelTable modelTable;
trpgLightTable lightTable;
trpgRangeTable rangeTable;
trpgTextStyleTable textStyleTable;
trpgSupportStyleTable supportStyleTable;
trpgLabelPropertyTable labelPropertyTable;
trpgTileTable tileTable;
trpgTileTable tileTable;
int numX,numY,numLod;
TileMode tileMode;
int numX,numY,numLod;
TileMode tileMode;
trpgwAppFile *tileFile;
int tileFileCount;
trpgwAppFile *tileFile;
int tileFileCount;
std::vector<TileFile> tileFiles;
std::vector<TileFile> tileFiles;
int maxTileFileLen;
int maxTileFileLen;
// This offset is used when we're adding to an existing archive
trpg2iPoint addOffset;
// This offset is used when we're adding to an existing archive
trpg2iPoint addOffset;
FILE *fp;
FILE *fp;
bool firstHeaderWrite;
bool firstHeaderWrite;
mutable char errMess[512];
mutable char errMess[512];
};
#endif

View File

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