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:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_
|
||||
|
||||
598
src/osgPlugins/txp/TXPArchive.cpp
Normal file
598
src/osgPlugins/txp/TXPArchive.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
149
src/osgPlugins/txp/TXPArchive.h
Normal file
149
src/osgPlugins/txp/TXPArchive.h
Normal 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_
|
||||
76
src/osgPlugins/txp/TXPIO.cpp
Normal file
76
src/osgPlugins/txp/TXPIO.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
226
src/osgPlugins/txp/TXPNode.cpp
Normal file
226
src/osgPlugins/txp/TXPNode.cpp
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
66
src/osgPlugins/txp/TXPNode.h
Normal file
66
src/osgPlugins/txp/TXPNode.h
Normal 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_
|
||||
11
src/osgPlugins/txp/TXPPageManager.cpp
Normal file
11
src/osgPlugins/txp/TXPPageManager.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "TXPPageManager.h"
|
||||
using namespace txp;
|
||||
|
||||
TXPPageManager::TXPPageManager():
|
||||
trpgPageManager()
|
||||
{
|
||||
}
|
||||
|
||||
TXPPageManager::~TXPPageManager()
|
||||
{
|
||||
}
|
||||
24
src/osgPlugins/txp/TXPPageManager.h
Normal file
24
src/osgPlugins/txp/TXPPageManager.h
Normal 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_
|
||||
1241
src/osgPlugins/txp/TXPParser.cpp
Normal file
1241
src/osgPlugins/txp/TXPParser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
271
src/osgPlugins/txp/TXPParser.h
Normal file
271
src/osgPlugins/txp/TXPParser.h
Normal 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_
|
||||
69
src/osgPlugins/txp/TXPSeamLOD.cpp
Normal file
69
src/osgPlugins/txp/TXPSeamLOD.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
57
src/osgPlugins/txp/TXPSeamLOD.h
Normal file
57
src/osgPlugins/txp/TXPSeamLOD.h
Normal 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
|
||||
216
src/osgPlugins/txp/TXPTileNode.cpp
Normal file
216
src/osgPlugins/txp/TXPTileNode.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
34
src/osgPlugins/txp/TXPTileNode.h
Normal file
34
src/osgPlugins/txp/TXPTileNode.h
Normal 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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ¢er)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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 ¢er);
|
||||
|
||||
osg::Texture2D* getGlobalTexture(int id)
|
||||
{
|
||||
return m_textures[id].get();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// This class does most of the actual parsing.
|
||||
std::auto_ptr<TrPageParser> parse;
|
||||
// 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
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -34,13 +34,13 @@ public:
|
||||
trpgMatTable1_0(const trpgMatTable &);
|
||||
|
||||
/* This read method overrides the one from trpgMatTable and knows
|
||||
how to read the old school material tables.
|
||||
how to read the old school material tables.
|
||||
*/
|
||||
bool Read(trpgReadBuffer &);
|
||||
bool Read(trpgReadBuffer &);
|
||||
/* This write method can write a 2.0 material table as 1.0
|
||||
style for backward compatibility.
|
||||
style for backward compatibility.
|
||||
*/
|
||||
bool Write(trpgWriteBuffer &);
|
||||
bool Write(trpgWriteBuffer &);
|
||||
protected:
|
||||
};
|
||||
|
||||
@@ -56,13 +56,13 @@ public:
|
||||
trpgTexTable1_0(const trpgTexTable &);
|
||||
|
||||
/* This read method overrides the one from trpgTexTable and
|
||||
knows how to read the old style texture table.
|
||||
knows how to read the old style texture table.
|
||||
*/
|
||||
bool Read(trpgReadBuffer &);
|
||||
bool Read(trpgReadBuffer &);
|
||||
/* The write method can write a 2.0 texture table as 1.0
|
||||
style for backward compatibility.
|
||||
style for backward compatibility.
|
||||
*/
|
||||
bool Write(trpgWriteBuffer &);
|
||||
bool Write(trpgWriteBuffer &);
|
||||
protected:
|
||||
};
|
||||
|
||||
@@ -76,9 +76,9 @@ public:
|
||||
trpgTexture1_0 operator = (const trpgTexture &);
|
||||
|
||||
// Knows how to read old style textures
|
||||
bool Read(trpgReadBuffer &);
|
||||
bool Read(trpgReadBuffer &);
|
||||
// Can write old style textures
|
||||
bool Write(trpgWriteBuffer &);
|
||||
bool Write(trpgWriteBuffer &);
|
||||
protected:
|
||||
};
|
||||
|
||||
@@ -90,7 +90,7 @@ class trpgTileTable1_0 : public trpgTileTable {
|
||||
public:
|
||||
trpgTileTable1_0(const trpgTileTable &);
|
||||
// Can write old style tile table
|
||||
bool Write(trpgWriteBuffer &);
|
||||
bool Write(trpgWriteBuffer &);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -18,22 +18,22 @@
|
||||
#include <string.h>
|
||||
|
||||
/* trpage_header.cpp
|
||||
Source for trpgHeader methods.
|
||||
The only reason to change this is if you want to add something
|
||||
to the header definition.
|
||||
*/
|
||||
Source for trpgHeader methods.
|
||||
The only reason to change this is if you want to add something
|
||||
to the header definition.
|
||||
*/
|
||||
|
||||
#include <trpage_geom.h>
|
||||
#include <trpage_read.h>
|
||||
|
||||
/* 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
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user