diff --git a/src/osgPlugins/txp/Makefile b/src/osgPlugins/txp/Makefile index daff43c58..9b55991e7 100644 --- a/src/osgPlugins/txp/Makefile +++ b/src/osgPlugins/txp/Makefile @@ -4,22 +4,28 @@ SHELL = /bin/sh include $(OSGHOME)/Make/makedefs C++FILES = \ - ReaderWriterTXP.cpp\ - TrPageArchive.cpp\ - TrPageParser.cpp\ - trpage_basic.cpp\ - trpage_geom.cpp\ - trpage_header.cpp\ - trpage_tile.cpp\ - trpage_readbuf.cpp\ - trpage_rarchive.cpp\ - trpage_writebuf.cpp\ - trpage_warchive.cpp\ - trpage_parse.cpp\ - trpage_nodes.cpp\ - trpage_model.cpp\ - trpage_material.cpp\ - trpage_swap.cpp + ReaderWriterTXP.cpp\ + TrPageArchive.cpp\ + TrPageParser.cpp\ + trpage_basic.cpp\ + trpage_geom.cpp\ + trpage_header.cpp\ + trpage_tile.cpp\ + trpage_readbuf.cpp\ + trpage_rarchive.cpp\ + trpage_writebuf.cpp\ + trpage_warchive.cpp\ + trpage_parse.cpp\ + trpage_nodes.cpp\ + trpage_model.cpp\ + trpage_material.cpp\ + trpage_swap.cpp\ + trpage_range.cpp\ + trpage_scene.cpp\ + trpage_compat.cpp\ + trpage_light.cpp\ + trpage_pparse.cpp\ + trpage_print.cpp TARGET_BASENAME = osgdb_txp diff --git a/src/osgPlugins/txp/ReaderWriterTXP.cpp b/src/osgPlugins/txp/ReaderWriterTXP.cpp index 814de1d76..6dea20f01 100644 --- a/src/osgPlugins/txp/ReaderWriterTXP.cpp +++ b/src/osgPlugins/txp/ReaderWriterTXP.cpp @@ -45,8 +45,7 @@ public: notify(INFO) << "TXPFile::loadFile(): loading geometry" << std::endl; - ret = new Group; - ret->addChild(archive.LoadAllTiles()); + ret = archive.LoadAllTiles(); notify(INFO) << "TXPFile::loadFile(): loaded archive: " << foundname << std::endl; @@ -73,6 +72,9 @@ public: osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readObject(const std::string& fileName, const osgDB::ReaderWriter::Options*) { + if( !acceptsExtension(osgDB::getFileExtension(fileName) )) + return ReadResult::FILE_NOT_HANDLED; + TXPFile read; Object* obj = read.readObject(fileName); @@ -83,6 +85,9 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readObject(const std::string& f osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options*) { + if( !acceptsExtension(osgDB::getFileExtension(fileName) )) + return ReadResult::FILE_NOT_HANDLED; + TXPFile read; Node* node = read.readNode(fileName); if (node) return node; diff --git a/src/osgPlugins/txp/TrPageArchive.cpp b/src/osgPlugins/txp/TrPageArchive.cpp index f46c3abc9..756fd6626 100644 --- a/src/osgPlugins/txp/TrPageArchive.cpp +++ b/src/osgPlugins/txp/TrPageArchive.cpp @@ -89,7 +89,7 @@ void TrPageArchive::LoadMaterials() { for (int i=0; i < n_textures ; i++) { - trpgTexture *tex; + const trpgTexture *tex; tex = texTable.GetTextureRef(i); char texName[1024]; texName[0] = 0; tex->GetName(texName,1023); @@ -118,7 +118,7 @@ void TrPageArchive::LoadMaterials() { StateSet* osg_state_set = new StateSet; - trpgMaterial *mat; + const trpgMaterial *mat; mat = materialTable.GetMaterialRef(0,i); // Set texture int numMatTex; diff --git a/src/osgPlugins/txp/TrPageParser.cpp b/src/osgPlugins/txp/TrPageParser.cpp index 14cd0f8ee..b9c3248db 100644 --- a/src/osgPlugins/txp/TrPageParser.cpp +++ b/src/osgPlugins/txp/TrPageParser.cpp @@ -72,17 +72,13 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) geom.GetPrimType(primType); geom.GetNumPrims(numPrims); geom.GetNumVertex(numVert); - numVert /= 3; - geom.GetMaterial(0,matId); + bool local; + geom.GetMaterial(0,matId, local); geom.GetNumNormal(numNorm); - numNorm /= 3; Vec3* vertices = new Vec3[numVert]; // Get vertices - // it can be done this way because standard guaranties that vector is on - // continuous storage and vec3 is POD - geom.GetVertices((float32 *)vertices); - + geom.GetVertices(vertices); // Turn the trpgGeometry into something Performer can understand GeoSet *gset = 0L; @@ -103,7 +99,7 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) if (numNorm == numVert) { normals = new Vec3[numVert]; - geom.GetNormals((float32 *)normals); + geom.GetNormals(normals); } Geode *geode = new Geode(); diff --git a/src/osgPlugins/txp/trdll.h b/src/osgPlugins/txp/trdll.h index 3add60cb0..54e05feef 100644 --- a/src/osgPlugins/txp/trdll.h +++ b/src/osgPlugins/txp/trdll.h @@ -1,23 +1,22 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ /* 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 @@ -60,6 +59,7 @@ // #endif // #define TX_CPPDECL extern __declspec(dllimport) +#ifndef TX_CLDECL // Class declaration. Goes after "class" to handle DLL export in windows. #define TX_CLDECL // Goes before "class" to handle DLL export in windows @@ -69,7 +69,11 @@ // Exports a C function properly in a windows DLL #define TX_CDECL /* no-op */ // {secret} +#ifndef TXDUMMY_DLL_MAIN #define TXDUMMY_DLL_MAIN /* no-op */ +#endif +#endif + #else #define TX_CLDECL __declspec( dllexport ) #define TX_EXDECL @@ -83,11 +87,15 @@ // The following is a DLL Main function for DLLs that wouldn't otherwise // have one. It's needed to initialize the run time library. // This should appear once within every DLL + +// commented out by Boris Bralo for osg + +/* #ifndef TXDUMMY_DLL_MAIN #define TXDUMMY_DLL_MAIN \ extern "C" { \ BOOL WINAPI _CRT_INIT (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved); \ -BOOL APIENTRY DllMain (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved) \ +BOOL APIENTRY DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) \ { \ switch (dwReason) \ { \ @@ -106,8 +114,8 @@ BOOL APIENTRY DllMain (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved) \ return TRUE; \ } \ } - #endif +*/ #endif #ifndef txdll_h_ diff --git a/src/osgPlugins/txp/trpage_basic.cpp b/src/osgPlugins/txp/trpage_basic.cpp index be7250261..dee17e4c5 100644 --- a/src/osgPlugins/txp/trpage_basic.cpp +++ b/src/osgPlugins/txp/trpage_basic.cpp @@ -1,22 +1,21 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ /* trpage_basic.cpp - Methods for checkable base class. - */ + Methods for checkable base class. + */ #include #include @@ -24,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; } diff --git a/src/osgPlugins/txp/trpage_geom.cpp b/src/osgPlugins/txp/trpage_geom.cpp index 288263c03..08f072859 100644 --- a/src/osgPlugins/txp/trpage_geom.cpp +++ b/src/osgPlugins/txp/trpage_geom.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -28,7 +27,9 @@ #include "trpage_geom.h" #include "trpage_read.h" -#if defined(_WIN32) && !defined(__GNUC__) +#include + +#if defined(_WIN32) #define ALIGNMENT_WORKAROUND false #else #define ALIGNMENT_WORKAROUND true @@ -99,12 +100,12 @@ void trpgGeometry::SetNumMaterial(int no) materials.resize(no,-1); } -void trpgGeometry::SetMaterial(int which,int mat) +void trpgGeometry::SetMaterial(int which,int mat,bool isLocal) { if (which < 0 || which >= (int)materials.size()) return; - materials[which] = mat; + materials[which] = (isLocal ? -(mat+1) : mat); } void trpgGeometry::SetMaterials(int32 num,const int32 *mat) { @@ -318,10 +319,15 @@ bool trpgGeometry::GetNumMaterial(int &n) const n = materials.size(); return true; } -bool trpgGeometry::GetMaterial(int id,int32 &m) const +bool trpgGeometry::GetMaterial(int id,int32 &m,bool &isLocal) const { - if (!isValid() || id < 0 || id >= (int)materials.size()) return false; + isLocal = false; + if (!isValid() || id < 0 || id >= materials.size()) return false; m = materials[id]; + if (m < 0) { + m = -m - 1; + isLocal = true; + } return true; } bool trpgGeometry::GetNumVertex(int &v) const @@ -330,11 +336,12 @@ bool trpgGeometry::GetNumVertex(int &v) const int nvf = vertDataFloat.size(); int nvd = vertDataDouble.size(); v = MAX(nvf,nvd); + v = v / 3; return true; } bool trpgGeometry::GetVertices(float32 *v) const { - unsigned int i; + int i; if (!isValid()) return false; if (vertDataFloat.size() != 0) @@ -347,7 +354,7 @@ bool trpgGeometry::GetVertices(float32 *v) const } bool trpgGeometry::GetVertices(float64 *v) const { - unsigned int i; + int i; if (!isValid()) return false; if (vertDataFloat.size() != 0) @@ -358,11 +365,36 @@ bool trpgGeometry::GetVertices(float64 *v) const v[i] = vertDataDouble[i]; return true; } +bool trpgGeometry::GetVertices(osg::Vec3* v) const +{ + int i; + + if (!isValid()) return false; + if (vertDataFloat.size() != 0) + { + for (i=0;i= (int)vertDataFloat.size() && idMax >= (int)vertDataDouble.size())) + if (id < 0 || (idMax >= vertDataFloat.size() && idMax >= vertDataDouble.size())) return false; if (vertDataFloat.size() > vertDataDouble.size()) { pt.x = vertDataFloat[id]; @@ -382,11 +414,12 @@ bool trpgGeometry::GetNumNormal(int32 &n) const n = normDataFloat.size(); if (normDataDouble.size() != 0) n = normDataDouble.size(); + n = n / 3; return true; } bool trpgGeometry::GetNormals(float32 *v) const { - unsigned int i; + int i; if (!isValid()) return false; if (normDataFloat.size() != 0) @@ -399,7 +432,7 @@ bool trpgGeometry::GetNormals(float32 *v) const } bool trpgGeometry::GetNormals(float64 *v) const { - unsigned int i; + int i; if (!isValid()) return false; if (normDataFloat.size() != 0) @@ -410,40 +443,66 @@ bool trpgGeometry::GetNormals(float64 *v) const v[i] = normDataDouble[i]; return true; } + +bool trpgGeometry::GetNormals(osg::Vec3* v) const +{ + int i; + + if (!isValid()) return false; + if (normDataFloat.size() != 0) + { + for (i=0;i= (int)colors.size()) return false; + if (!isValid() || id < 0 || id >= colors.size()) return false; *ci = colors[id]; return true; } bool trpgGeometry::GetNumTexCoordSets(int &n) const { if (!isValid()) return false; - n = (int)texData.size(); + n = texData.size(); return true; } bool trpgGeometry::GetTexCoordSet(int id,trpgTexData *tx) const { - if (!isValid() || id < 0 || id >= (int)texData.size()) return false; + if (!isValid() || id < 0 || id >= texData.size()) return false; *tx = texData[id]; return true; } bool trpgGeometry::GetNumEdgeFlag(int &n) const { if (!isValid()) return false; - n = (int)edgeFlags.size(); + n = edgeFlags.size(); return true; } bool trpgGeometry::GetEdgeFlags(char *e) const { if (!isValid()) return false; - for (unsigned int i=0;i tileSize; - vector lodSizes; - vector lodRanges; + int numLods; + std::vector tileSize; + std::vector lodSizes; + std::vector lodRanges; }; /* The Texture Environment is used by the trpgMaterial to define texture - related parameters. A trpgTextureEnv is associated with each texture - used in a trpgMaterial. So, for example, if there are 2 textures in - a material, there will be two texture environments. - Most of these parameters come straight from the OpenGL specification. It's - best to consult that for an exact meaning. + related parameters. A trpgTextureEnv is associated with each texture + used in a trpgMaterial. So, for example, if there are 2 textures in + a material, there will be two texture environments. + Most of these parameters come straight from the OpenGL specification. It's + best to consult that for an exact meaning. - If you doing a TerraPage reader, expect to get a trpgTextureEnv when - dealing with trpgMaterial definitions. If you're doing a writer, you'll - need to build these in the course of building a trpgMaterial. - {group:Read/Write Classes} - */ + If you doing a TerraPage reader, expect to get a trpgTextureEnv when + dealing with trpgMaterial definitions. If you're doing a writer, you'll + need to build these in the course of building a trpgMaterial. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTextureEnv : public trpgReadWriteable { - friend class trpgMatTable; + friend class trpgMatTable; public: - trpgTextureEnv(void); - ~trpgTextureEnv(void); + trpgTextureEnv(void); + ~trpgTextureEnv(void); - // Environment mode values - enum {Alpha,Blend,Decal,Modulate}; - // Set the application mode for the texture. - void SetEnvMode(int); - // Values used by SetMinFilter and SetMagFilter - enum {Point, Linear, MipmapPoint, MipmapLinear, - MipmapBilinear, MipmapTrilinear, Nearest}; - // Set the Minification filter for a texture - void SetMinFilter(int); - // Set the Magnification filter for a texture - void SetMagFilter(int); + // Environment mode values + enum {Alpha,Blend,Decal,Modulate,AddDetail,ModulateDetail}; + // Set the application mode for the texture. + void SetEnvMode(int); + // Values used by SetMinFilter and SetMagFilter + enum {Point, Linear, MipmapPoint, MipmapLinear, + MipmapBilinear, MipmapTrilinear, Nearest}; + // Set the Minification filter for a texture + void SetMinFilter(int); + // Set the Magnification filter for a texture + void SetMagFilter(int); - // Values used by SetWrap - enum {Clamp,Repeat}; - // Set the texture wrapping for S and T, respectively - void SetWrap(int,int); - // Set the texture border color - void SetBorderColor(const trpgColor &); + // Values used by SetWrap + enum {Clamp,Repeat}; + // Set the texture wrapping for S and T, respectively + void SetWrap(int,int); + // Set the texture border color + void SetBorderColor(const trpgColor &); - /* The environment mode controls how the texture is applied. - It can take the following values: - Alpha - Used to change the alpha values on a polygon. - Blend - Blended with the polygont color - Decal - Doesn't take polygon color into account. - Modulate - See openGL spec for definition. - */ - bool GetEnvMode(int32 &) const; - /* The Minification and Magnification filters control how texture - mipmap levels are used. We support the values: Point, Linear, - MipmapPoint, MipmapLinear, - MipmapBilinear, MipmapTrilinear, Nearest - */ - bool GetMinFilter(int32 &) const; - // Get the magnification filter - bool GetMagFilter(int32 &) const; - /* Wrapping controls how textures are used near the edges. - There are two valid values: Clamp, Repeat. - */ - bool GetWrap(int &,int &) const; - /* This maps straight into the OpenGL definition of border color. */ - bool GetBorderColor(trpgColor &) const; + /* The environment mode controls how the texture is applied. + It can take the following values: + Alpha - Used to change the alpha values on a polygon. + Blend - Blended with the polygont color + Decal - Doesn't take polygon color into account. + Modulate - See openGL spec for definition. + */ + bool GetEnvMode(int32 &) const; + /* The Minification and Magnification filters control how texture + mipmap levels are used. We support the values: Point, Linear, + MipmapPoint, MipmapLinear, + MipmapBilinear, MipmapTrilinear, Nearest + */ + bool GetMinFilter(int32 &) const; + // Get the magnification filter + bool GetMagFilter(int32 &) const; + /* Wrapping controls how textures are used near the edges. + There are two valid values: Clamp, Repeat. + */ + bool GetWrap(int &,int &) const; + /* This maps straight into the OpenGL definition of border color. */ + bool GetBorderColor(trpgColor &) const; - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; protected: - int envMode; - int minFilter; - int magFilter; - int wrapS,wrapT; - trpgColor borderCol; + int envMode; + int minFilter; + int magFilter; + int wrapS,wrapT; + trpgColor borderCol; }; /* The material definition for TerraPage encompasses those things that have to - do with visual display that can be indexed and disassociated from the - polygons themselves. This covers things like color, texture, alpha - and a few more obscure ones. - Materials are indexed centrally in a trpgMatTable. + do with visual display that can be indexed and disassociated from the + polygons themselves. This covers things like color, texture, alpha + and a few more obscure ones. + Materials are indexed centrally in a trpgMatTable. - This material definition borrows heavily from the OpenGL specification. - Please refer to that for a good definition of all the fields. + This material definition borrows heavily from the OpenGL specification. + Please refer to that for a good definition of all the fields. - If you're doing a TerraPage reader you'll need to deal with these in two places. - First, is when you read the archive header and get a trpgMatTable back. You'll - want to translate them into your own internal representation and keep track of - the mapping. Later, when parsing trpgGeometry nodes, you'll run into them - again. This time they will be material indices into a trpgMatTable. At that - point you'll want to map these indices into your own material definition table. + If you're doing a TerraPage reader you'll need to deal with these in two places. + First, is when you read the archive header and get a trpgMatTable back. You'll + want to translate them into your own internal representation and keep track of + the mapping. Later, when parsing trpgGeometry nodes, you'll run into them + again. This time they will be material indices into a trpgMatTable. At that + point you'll want to map these indices into your own material definition table. - If you're doing a TerraPage writer you'll need to create one of these for every - unique material-like object you have. Since trpgMaterial objects are indexed - centrally in a TerraPage archive, you should take advantage of that and use - as few as possible. After defining one, you'll want to add it to a trpgMatTable - and keep track of the material index that returns. This will be the mapping from - your own internal material table (or whatever you've got) into the archive's - material table. A trpgMaterial sets up defaults that work pretty well, so just - fill in what you need to use. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer you'll need to create one of these for every + unique material-like object you have. Since trpgMaterial objects are indexed + centrally in a TerraPage archive, you should take advantage of that and use + as few as possible. After defining one, you'll want to add it to a trpgMatTable + and keep track of the material index that returns. This will be the mapping from + your own internal material table (or whatever you've got) into the archive's + material table. A trpgMaterial sets up defaults that work pretty well, so just + fill in what you need to use. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgMaterial : public trpgReadWriteable { - friend class trpgMatTable; + friend class trpgMatTable; public: - trpgMaterial(void); - ~trpgMaterial(void); - // Set base material color - void SetColor(const trpgColor &); - // Ambient color - void SetAmbient(const trpgColor &); - // Diffuse color (the most commonly used) - void SetDiffuse(const trpgColor &); - // Specular color used in lighting - void SetSpecular(const trpgColor &); - // Emissive color used in lighting - void SetEmission(const trpgColor &); - // Shininess used in lighting - void SetShininess(float64); + trpgMaterial(void); + ~trpgMaterial(void); + // Set base material color + void SetColor(const trpgColor &); + // Ambient color + void SetAmbient(const trpgColor &); + // Diffuse color (the most commonly used) + void SetDiffuse(const trpgColor &); + // Specular color used in lighting + void SetSpecular(const trpgColor &); + // Emissive color used in lighting + void SetEmission(const trpgColor &); + // Shininess used in lighting + void SetShininess(float64); - enum {Smooth,Flat}; - // Shading model - void SetShadeModel(int); - // Point size - void SetPointSize(float64); - // Line width - void SetLineWidth(float64); - enum {Front,Back,FrontAndBack}; - // Cull mode. See GetCullMode - void SetCullMode(int); - // None and Always appear to be defined on the SGI - // in such a way as to interfere with a local enum - // declaration within a class - enum {trNone,trAlways,Equal,GreaterThanOrEqual,GreaterThan, - LessThanOrEqual,LessThan,Never,NotEqual}; - // Alpha Function. See GetAlphaFunc - void SetAlphaFunc(int); - // Alpha Ref value. See GetAlphaRef - void SetAlphaRef(float64); - // Alpha value for any polygon using this material - void SetAlpha(float64); - // Generate normals automatically from geometry - void SetAutoNormal(bool); + enum {Smooth,Flat}; + // Shading model + void SetShadeModel(int); + // Point size + void SetPointSize(float64); + // Line width + void SetLineWidth(float64); + enum {Front,Back,FrontAndBack}; + // Cull mode. See GetCullMode + void SetCullMode(int); +#ifdef Always + // None and Always appear to be defined on the SGI + // in such a way as to interfere with a local enum + // declaration within a class + enum {trNone,trAlways,Equal,GreaterThanOrEqual,GreaterThan, + LessThanOrEqual,LessThan,Never,NotEqual}; +#else + enum {None,Always,Equal,GreaterThanOrEqual,GreaterThan, + LessThanOrEqual,LessThan,Never,NotEqual}; +#endif + // Alpha Function. See GetAlphaFunc + void SetAlphaFunc(int); + // Alpha Ref value. See GetAlphaRef + void SetAlphaRef(float64); + // Alpha value for any polygon using this material + void SetAlpha(float64); + // Generate normals automatically from geometry + void SetAutoNormal(bool); - /* Set the total number of textures used by this trpgMaterial. - This works with SetTexture. We recommend that you used - AddTexture instead of these two methods. */ - void SetNumTexture(int); - /* Works with SetNumTexture. - This method sets the texture ID and texture environment for the given - texture instance in this material. Use AddTexture instead, if you can. - */ - void SetTexture(int no,int id,const trpgTextureEnv &); - /* This method takes a texture ID that refers to a trpgTexTable and a - trpgTextureEnv which specifies the application information relating - to this texture instance. It returns the reference number (i.e. the - 3rd texture in this material, etc...) - */ - int AddTexture(int,const trpgTextureEnv &); + /* Set the total number of textures used by this trpgMaterial. + This works with SetTexture. We recommend that you used + AddTexture instead of these two methods. */ + void SetNumTexture(int); + /* Works with SetNumTexture. + This method sets the texture ID and texture environment for the given + texture instance in this material. Use AddTexture instead, if you can. + */ + void SetTexture(int no,int id,const trpgTextureEnv &); + /* This method takes a texture ID that refers to a trpgTexTable and a + trpgTextureEnv which specifies the application information relating + to this texture instance. It returns the reference number (i.e. the + 3rd texture in this material, etc...) + */ + int AddTexture(int,const trpgTextureEnv &); - // Number of tiles this material is used in - void SetNumTiles(int); - // Adds a count to the number of tiles this material is used in and returns that number - int AddTile(); + // Number of tiles this material is used in + void SetNumTiles(int); + // Adds a count to the number of tiles this material is used in and returns that number + int AddTile(void); - // Return the current color - bool GetColor(trpgColor &) const; - // Returns the ambient color - bool GetAmbient(trpgColor &) const; - // Returns the diffuse color (the most commonly used color) - bool GetDiffuse(trpgColor &) const; - // Specular color used for lighting - bool GetSpecular(trpgColor &) const; - // Emissive color used for lighting - bool GetEmission(trpgColor &) const; - // Shininess used for lighting - bool GetShininess(float64 &) const; + // Sets bump map status (color etc... isn't important) + void SetIsBumpMap(bool); - // The shading model can be either Smooth or Flat - bool GetShadeModel(int &) const; - // Point size - bool GetPointSize(float64 &) const; - // Line width - bool GetLineWidth(float64 &) const; - /* Cull mode determines whether geometry will be rejected if it's Front facing, Back - facing, or neither (FrontAndBack) - */ - bool GetCullMode(int &) const; - /* This controls what alpha values in a texture mean. It can take the values: - None,Always,Equal,GreaterThanOrEqual,GreaterThan, - LessThanOrEqual,LessThan,Never,NotEqual - */ - bool GetAlphaFunc(int &) const; - /* The Alpha Ref is a value used in some of the Alpha Functions */ - bool GetAlphaRef(float64 &) const; - // Whether or not to generate normals from geometry - bool GetAutoNormal(bool &) const; - // A single Alpha value that applies to any polygons using this material - bool GetAlpha(float64 &) const; - /* One of the useful things about TerraPage is that it contains enough information - to page textures & materials as well as terrain. This is part of that. - It returns the number of tiles this material is used in. The trpgTexture has - its own which is used for paging textures. You only want to pay attention to - this if you have some costly material definition in your hardware and so have - to swap them in and out. - */ - bool GetNumTile(int &) const; + // Return the current color + bool GetColor(trpgColor &) const; + // Returns the ambient color + bool GetAmbient(trpgColor &) const; + // Returns the diffuse color (the most commonly used color) + bool GetDiffuse(trpgColor &) const; + // Specular color used for lighting + bool GetSpecular(trpgColor &) const; + // Emissive color used for lighting + bool GetEmission(trpgColor &) const; + // Shininess used for lighting + bool GetShininess(float64 &) const; - /* There can be multiple textures per material. This returns the number. - The first is the base texture, so just use that if you can only do 1 texture per poly. - */ - bool GetNumTexture(int &) const; - /* TerraPage supports multiple textures per polygon. Some hardware can do this, - some can't. If you can support it, here's how this works. - This method returns the texture definition for the Nth texture used in this material. - That consists of a texture ID which points into a trpgTexTable and a trpgTextureEnv - which contains the texture application information. - Multiple materials can also appear per trpgGeometry, so be aware that there are - two ways to have multiple textures per polygon. - */ - bool GetTexture(int no,int &id,trpgTextureEnv &) const; + // The shading model can be either Smooth or Flat + bool GetShadeModel(int &) const; + // Point size + bool GetPointSize(float64 &) const; + // Line width + bool GetLineWidth(float64 &) const; + /* Cull mode determines whether geometry will be rejected if it's Front facing, Back + facing, or neither (FrontAndBack) + */ + bool GetCullMode(int &) const; + /* This controls what alpha values in a texture mean. It can take the values: + None,Always,Equal,GreaterThanOrEqual,GreaterThan, + LessThanOrEqual,LessThan,Never,NotEqual + */ + bool GetAlphaFunc(int &) const; + /* The Alpha Ref is a value used in some of the Alpha Functions */ + bool GetAlphaRef(float64 &) const; + // Whether or not to generate normals from geometry + bool GetAutoNormal(bool &) const; + // A single Alpha value that applies to any polygons using this material + bool GetAlpha(float64 &) const; + /* One of the useful things about TerraPage is that it contains enough information + to page textures & materials as well as terrain. This is part of that. + It returns the number of tiles this material is used in. The trpgTexture has + its own which is used for paging textures. You only want to pay attention to + this if you have some costly material definition in your hardware and so have + to swap them in and out. + */ + bool GetNumTile(int &) const; - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + /* There can be multiple textures per material. This returns the number. + The first is the base texture, so just use that if you can only do 1 texture per poly. + */ + bool GetNumTexture(int &) const; + /* TerraPage supports multiple textures per polygon. Some hardware can do this, + some can't. If you can support it, here's how this works. + This method returns the texture definition for the Nth texture used in this material. + That consists of a texture ID which points into a trpgTexTable and a trpgTextureEnv + which contains the texture application information. + Multiple materials can also appear per trpgGeometry, so be aware that there are + two ways to have multiple textures per polygon. + */ + bool GetTexture(int no,int &id,trpgTextureEnv &) const; - // Note: Need to do equality operator + // Return whether or not this material is a bump map + bool GetIsBumpMap(bool &) const; + + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Note: Need to do equality operator protected: - trpgColor color; - trpgColor ambient; - trpgColor diffuse; - trpgColor specular; - trpgColor emission; - float64 shininess; - int shadeModel; - float64 pointSize; - float64 lineWidth; - int cullMode; - int alphaFunc; - float64 alpha; - float64 alphaRef; - bool autoNormal; - int numTex; - int32 numTile; - vector texids; - vector texEnvs; + bool isBump; + trpgColor color; + trpgColor ambient; + trpgColor diffuse; + trpgColor specular; + trpgColor emission; + float64 shininess; + int shadeModel; + float64 pointSize; + float64 lineWidth; + int cullMode; + int alphaFunc; + float64 alpha; + float64 alphaRef; + bool autoNormal; + int numTex; + int32 numTile; + std::vector texids; + std::vector texEnvs; }; -/* There are two levels of materials to save space on disk. - The first level is a regular trpgMaterial. - The second level is a trpgShortMaterial which overrides texture. - This cuts down on header size for geospecific databases. - No one actually sees trpgShortMaterials. You interface with a regular - trpgMaterial. The trpgMatTable figures out when to use these and hides it. - {group:Read/Write Classes} - */ -class trpgShortMaterial { +/* The lights in TerraPage +*/ + +TX_EXDECL class TX_CLDECL trpgLightAttr : public trpgReadWriteable { public: - // Full trpgMaterial definition this one is based on - int32 baseMat; - // Currently the only thing a short material overrides is texture - vector texids; + // Default constructor + trpgLightAttr(void); + // Copy constructor + trpgLightAttr(const trpgLightAttr &); + // Destructor + ~trpgLightAttr(void); + + // Light Flags + enum { + // Light flags + trpg_Day = 0x0001, + trpg_Dusk = 0x0002, + trpg_Night = 0x0004, + trpg_Directional = 0x0008, + trpg_BackColor = 0x0010, + trpg_Reflective = 0x0020, + + // Animation flags + trpg_Flashing = 0x0100, + trpg_Rotating = 0x0200, + trpg_ClockWise = 0x0400, + trpg_AnimationMask =0x0f00, + + // Performer light flags + trpg_Perspective = 0x1000, + trpg_Fade = 0x2000, + trpg_ZBuffer = 0x4000, + trpg_FogPunch = 0x8000, + trpg_PerformerMask =0xf000 + } LightFlags; + + // Light Type + typedef enum { + trpg_Raster, + trpg_Calligraphic, + trpg_RASCAL + } LightType; + + // Light Directionality + typedef enum { + trpg_Omnidirectional, + trpg_Bidirectional, + trpg_Unidirectional + } LightDirectionality; + + // Light Quality + typedef enum { + trpg_Off, + trpg_Low, + trpg_Medium, + trpg_High, + trpg_Undefined + } LightQuality; + + // Struct for Performer Lights + typedef struct PerformerAttr { + PerformerAttr() : flags(0),minPixelSize(0),maxPixelSize(0),actualSize(0), + transparentPixelSize(0),transparentFallofExp(0),transparentScale(0), + transparentClamp(0),fogScale(0) {}; + int32 flags; + float64 minPixelSize; + float64 maxPixelSize; + float64 actualSize; + float64 transparentPixelSize; + float64 transparentFallofExp; + float64 transparentScale; + float64 transparentClamp; + float64 fogScale; + }; + + // Struct for Animated Lights + typedef struct AnimationAttr { + AnimationAttr() : period(0),phaseDelay(0),timeOn(0),vector(trpg3dPoint(0,0,0)),flags(0) {}; + float64 period; + float64 phaseDelay; + float64 timeOn; + trpg3dPoint vector; + int32 flags; + }; + + // Struct for Calligraphic Lights + typedef struct CalligraphicAttr { + CalligraphicAttr() : drawOrder(0),minDefocus(0),maxDefocus(0) {} ; + int32 drawOrder; + float64 minDefocus; + float64 maxDefocus; + }; + + // Setters + // Set Type + void SetType( trpgLightAttr::LightType ); + + // Set Directionality + void SetDirectionality( trpgLightAttr::LightDirectionality ); + + // Set Front Color + void SetFrontColor( trpgColor ); + + // Set Front Intensity + void SetFrontIntensity( float64 ); + + // Set Back Color + void SetBackColor( trpgColor ); + + // Set Back Intensity + void SetBackIntensity( float64 ); + + // Set Normal + void SetNormal( trpg3dPoint ); + + // Set SMC + void SetSMC( int32 ); + + // Set FID + void SetFID( int32 ); + + // Set Flags + void SetFlags( int32 ); + + // Set Horizontal Lobe Angle + void SetHLobeAngle( float64 ); + + // Set Vertical Lobe Angle + void SetVLobeAngle( float64 ); + + // Set Lobe Roll Angle + void SetLobeRollAngle( float64 ); + + // Set Lobe Falloff + void SetLobeFalloff( float64 ); + + // Set Ambient Intensity + void SetAmbient( float64 ); + + // Set Quality + void SetQuality( trpgLightAttr::LightQuality ); + + // Set RASCAL Significance + void SetRascalSignificance( float64 ); + + // Set Random Intensity + void SetRandomIntensity( trpgLightAttr::LightQuality ); + + // Set the attributes for Calligraphics Lights + void SetCalligraphicAttr( trpgLightAttr::CalligraphicAttr& ); + + // Set Calligraphic Draw Order + void SetCalligraphicDrawOrder( int32 ); + + // Set Calligraphic Minimum Defocus + void SetCalligraphicMinDefocus( float64 ); + + // Set Calligraphic Maximum Defocus + void SetCalligraphicMaxDefocus( float64 ); + + // Set the attributes for Performer Lights + void SetPerformerAttr( trpgLightAttr::PerformerAttr& ); + + // Set the flags for Perfromer Lights + void SetPerformerFlags( int32 ); + + // Set the minimum pixel size for Performer Lights + void SetPerformerMinPixelSize( float64 ); + + // Set the maximum pixel size for Performer Lights + void SetPerformerMaxPixelSize( float64 ); + + // Set the actual size for Performer Lights + void SetPerformerActualSize( float64 ); + + // Set the transparent pixel size for Performer Lights + void SetPerformerTpPixelSize( float64 ); + + // Set the transparent Falloff exponent for Performer Lights + void SetPerformerTpFalloffExp( float64 ); + + // Set the transparent scale for Performer Lights + void SetPerformerTpScale( float64 ); + + // Set the transparent clamp for Performer Lights + void SetPerformerTpClamp( float64 ); + + // Set the fog scale for Performer Lights + void SetPerformerFogScale( float64 ); + + // Set the attributes for animated lights + void SetAnimationAttr( trpgLightAttr::AnimationAttr& ); + + // Set the animation period for animated lights + void SetAnimationPeriod( float64 ); + + // Set the animation phase delay for animated lights + void SetAnimationPhaseDelay( float64 ); + + // Set the time on for animated lights + void SetAnimationTimeOn( float64 ); + + // Set the animation vector for animated lights + void SetAnimationVector( trpg3dPoint ); + + // Set the flags for animated lights + void SetAnimationFlags( int32 ); + + // Getters + // See the comments for the Setters + void GetType( trpgLightAttr::LightType& ); + void GetDirectionality( trpgLightAttr::LightDirectionality& ); + void GetFrontColor( trpgColor& ); + void GetFrontIntensity( float64& ); + void GetBackColor( trpgColor& ); + void GetBackIntensity( float64& ); + void GetNormal( trpg3dPoint& ); + void GetSMC( int32& ); + void GetFID( int32& ); + void GetFlags( int32& ); + void GetHLobeAngle( float64& ); + void GetVLobeAngle( float64& ); + void GetLobeRollAngle( float64& ); + void GetLobeFalloff( float64& ); + void GetAmbient( float64& ); + void GetQuality( trpgLightAttr::LightQuality& ); + void GetRascalSignificance( float64& ); + void GetRandomIntensity( trpgLightAttr::LightQuality& ); + void GetCalligraphicAttr( trpgLightAttr::CalligraphicAttr& ); + void GetCalligraphicDrawOrder( int32& ); + void GetCalligraphicMinDefocus( float64& ); + void GetCalligraphicMaxDefocus( float64& ); + void GetPerformerAttr( trpgLightAttr::PerformerAttr& ); + void GetPerformerFlags( int32& ); + void GetPerformerMinPixelSize( float64& ); + void GetPerformerMaxPixelSize( float64& ); + void GetPerformerActualSize( float64& ); + void GetPerformerTpPixelSize( float64& ); + void GetPerformerTpFalloffExp( float64& ); + void GetPerformerTpScale( float64& ); + void GetPerformerTpClamp( float64& ); + void GetPerformerFogScale( float64& ); + void GetAnimationAttr( trpgLightAttr::AnimationAttr& ); + void GetAnimationPeriod( float64& ); + void GetAnimationPhaseDelay( float64& ); + void GetAnimationTimeOn( float64& ); + void GetAnimationVector( trpg3dPoint& ); + void GetAnimationFlags( int32& ); + + // operators + trpgLightAttr& operator = (const trpgLightAttr&); + bool operator == (const trpgLightAttr&); + bool operator != (const trpgLightAttr&); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Validity check + bool isValid(void) const; + + // Resets the contents back to empty + void Reset(void); + +protected: + struct DataSet { + LightType type; + LightDirectionality directionality; + trpgColor frontColor; + float64 frontIntensity; + trpgColor backColor; + float64 backIntensity; + trpg3dPoint normal; + int32 smc; + int32 fid; + int32 flags; + float64 horizontalLobeAngle; + float64 verticalLobeAngle; + float64 lobeRollAngle; + float64 lobeFalloff; + float64 ambientIntensity; + LightQuality quality; + LightQuality randomIntensity; + float64 rascalSignificance; + CalligraphicAttr calligraphicAttr; + PerformerAttr performerAttr; + AnimationAttr animationAttr; + } data; +}; + +TX_EXDECL class TX_CLDECL trpgLight : public trpgReadWriteable { +public: + // Default constructor + trpgLight(void); + // Copy constructor + trpgLight(const trpgLight &); + // Destructor + ~trpgLight(void); + + // Set the index pointing into the Light Table + void SetAttrIndex(int); + + // Add a new location this light is located at + void AddVertex(trpg3dPoint); + + // Returns the number of locations, this light is located at + void GetNumVertices(uint32 &) const; + + // Returns the location at a given index + bool GetVertex(uint32, trpg3dPoint &) const; + + // Returns the whole list of vertices + bool GetVertices(trpg3dPoint *) const; + bool GetVertices(float64 *) const; + bool GetVertices(float32 *) const; + +// Returns the index of the Light Attributes in the Light Table + void GetAttrIndex(int &) const; + + // Validity check + bool isValid(void) const; + + // Resets the contents back to empty + void Reset(void); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // operator + trpgLight& operator = (const trpgLight &); + +protected: + // Here we store the light locations + std::vector lightPoints; + int index; +}; + +TX_EXDECL class TX_CLDECL trpgLightTable : public trpgReadWriteable { +public: + // Default constructor + trpgLightTable(void); + + // Copy constructor + trpgLightTable(const trpgLightTable &); + + // Destructor + ~trpgLightTable(void); + + // Adds the given light attrib to the table and increments the total light attrib count. + int AddLightAttr(const trpgLightAttr&); + + /* This is the same as AddLightAttr except that it searches for a matching light attrib + first. This is convenient for writers who aren't keeping track of their + own light attrib internally. + */ + int FindAddLightAttr(const trpgLightAttr&); + + // Returns the number of light attrib in this table + bool GetNumLightAttrs(int &) const; + + // Returns a pointer to a light attrib from a given index + const trpgLightAttr* GetLightAttrRef(int) const; + + // Validity check + bool isValid(void) const; + + // Resets the contents back to empty + void Reset(void); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // operator + trpgLightTable & operator = (const trpgLightTable &); + +protected: + // Here we store the light attributes + std::vector lightList; + +}; + +/* Range Info + These classes live within the trpgRangeTable. They encapsulate range + information that ties trpgLod nodes together. Their purpose is to provide + data to the run-time system about the relative priorities of classes of + features. See the trpgRangeTable for a complete explanation. + */ +TX_EXDECL class TX_CLDECL trpgRange : public trpgReadWriteable { +public: + trpgRange(void); + ~trpgRange(void); + + // Copy constructor + trpgRange(const trpgRange &); + + // Set the name and subName (can be NULL) + void SetCategory(char *cat,char *subCat); + + /* Get the name and subName + Name should be the major category (e.g. "trees") + SubName should be the minor category (e.g. "big trees") + */ + void GetCategory(char *cat,int maxCatLen,char *subCat,int maxSubCatLen) const; + + // Set the lod info + void SetLodInfo(double in,double out); + + // Get the lod info (this will be duplicated in the trpgLod node) + // However, you may want to change these values yourself during a run + void GetLodInfo(double &in,double &out) const; + + // Set the priority + void SetPriority(int); + + /* Get the priority. + Priority is a hint to the run-time system as to the relative importance + of range limited features. Features with lower priorities should be + sacrified before those with higher priorities. + */ + void GetPriority(int &) const; + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Reset back to a clean state + void Reset(void); + + // Equality operator + bool operator == (const trpgRange &) const; + + // Assignment operator + trpgRange & operator = (const trpgRange &); + +protected: + double inLod,outLod; + char *category; + char *subCategory; + int priority; +}; + +/* The Range Table is new to 2.0. The goal is to provide information about + certain classes of features within a TerraPage database. It's intended + to solve the following problem. + + Let's say that you have an Image Generator that must draw a given TerraPage + database at 60Hz. However, it's only hitting 30Hz reliably. Often, some + feature set (e.g. bushes) must be sacrified in order to reach the target frame rate. + Determining which features can be throttled back can often be very difficult. + Scaling all of the LODs will often work, but it's not very elegant. It's + not selective (you may lose important features as well as unimportant ones) + and it doesn't easily let turn whole feature sets off. + + If you do want to selectively turn features on and off or throttle them + back, you can do so based on node names within the LODs. This can work, however + you've got the additional overhead of traversing the tree looking for LODs + and trying to figure out what the names mean. The range table is intended + to make this task easier. + + Each trpgLod can (but isn't required to) have an index into the Range Table. + That index will point to a trpgRange that contains global information + about that class of LODs. This includes the in/out information already contained + within the LOD as well as global info. The global information includes a category + and sub-category as well as an integer priority. The category data is there to + allow run-time systems to tell users what they're dropping (or allow them to pick). + The priority is there to tell systems what to get rid of first (according to the + user who build the TerraPage archive). + + Priorities are relative to each other within the Range Table. There can be + duplicates and there may be holes in the numbering. + + {group:Read/Write Classes} + */ +TX_EXDECL class TX_CLDECL trpgRangeTable : public trpgReadWriteable { +public: + trpgRangeTable(void); + ~trpgRangeTable(void); + + // Get the given range info + bool GetRange(int id,trpgRange &) const; + + // Set the range info for the given ID + bool SetRange(int id,trpgRange &); + + // Add a new range and return the ID + int AddRange(trpgRange &); + + // Find a matching range and return it or add a new one if needed + int FindAddRange(trpgRange &); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Resets the contents back to empty + void Reset(void); + + // Assignment operator + trpgRangeTable & operator = (const trpgRangeTable &); + +protected: + std::vector rangeList; }; /* All materials are centrally indexed in TerraPage. There is one material - table per archive. All trpgGeometry nodes point to that material table (with indices) - for their trpgMaterial definitions. + table per archive. All trpgGeometry nodes point to that material table (with indices) + for their trpgMaterial definitions. - The material table has one wrinkle. It is divided up into sub-tables or channels. - Each sub-table has the same number of materials, so there will be NxM trpgMaterial - structures in a trpgMatTable. The sub-tables are intended for use in simple sensor - simulations. For example, the base table (0) is the purely visual, out the window - representation. The next table (1) might the Infra-Red version. It's up to the run-time - system to switch between these two. TerraPage simply provides the means for keeping - track of it. + The material table has one wrinkle. It is divided up into sub-tables or channels. + Each sub-table has the same number of materials, so there will be NxM trpgMaterial + structures in a trpgMatTable. The sub-tables are intended for use in simple sensor + simulations. For example, the base table (0) is the purely visual, out the window + representation. The next table (1) might the Infra-Red version. It's up to the run-time + system to switch between these two. TerraPage simply provides the means for keeping + track of it. - If you're doing a TerraPage reader you'll get a trpgMatTable from the trpgr_Archive. - This is your central index for materials. If you can handle the multiple channels/sub-tables - then you can access those as you need. If you can't, just use 0 for the sub-table index where appropriate. - - If you're doing a TerraPage writer you'll need to build up a trpgMatTable to pass to - trpgwArchive. If you're only doing a single sub-table (i.e. visible materials only) - just use AddMaterial and add them as you go. The trpgMaterial object you build up - for a given material are copied when you call the add function. So you can have a single - trpgMaterial, modify just a few fields and call AddMaterial repeatedly. - {group:Read/Write Classes} - */ + If you're doing a TerraPage reader you'll get a trpgMatTable from the trpgr_Archive. + This is your central index for materials. If you can handle the multiple channels/sub-tables + then you can access those as you need. If you can't, just use 0 for the sub-table index where appropriate. + + If you're doing a TerraPage writer you'll need to build up a trpgMatTable to pass to + trpgwArchive. If you're only doing a single sub-table (i.e. visible materials only) + just use AddMaterial and add them as you go. The trpgMaterial object you build up + for a given material are copied when you call the add function. So you can have a single + trpgMaterial, modify just a few fields and call AddMaterial repeatedly. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgMatTable : public trpgReadWriteable { public: - trpgMatTable(void); - ~trpgMatTable(void); - /* If you intend to have more than one material sub-table you'll - need to set this first before doing anything else. - */ - void SetNumTable(int); - /* This sets the total number of materials. Each sub-table will - have this many of its own materials. If you call this function - you can't use AddMaterial. - */ - void SetNumMaterial(int); - /* Sets a material definition for the given sub-table material ID - combination. If you only have one sub-table you can use - AddMaterial instead. - The two argument version assumes subTable = 0 - */ - void SetMaterial(int subTable,int mat,const trpgMaterial &); - void SetMaterial(int,const trpgMaterial &); + trpgMatTable(void); + ~trpgMatTable(void); + /* If you intend to have more than one material sub-table you'll + need to set this first before doing anything else. + */ + void SetNumTable(int); + /* This sets the total number of materials. Each sub-table will + have this many of its own materials. If you call this function + you can't use AddMaterial. + */ + void SetNumMaterial(int); + /* Sets a material definition for the given sub-table material ID + combination. If you only have one sub-table you can use + AddMaterial instead. + The two argument version assumes subTable = 0 + */ + void SetMaterial(int subTable,int mat,const trpgMaterial &); + void SetMaterial(int,const trpgMaterial &); + + /* This function should be used if you only have a single material sub-table. + It searches for a matching material and then adds a new one if it doesn't + find a match. The new (or old) ID is returned. + */ + int AddMaterial(const trpgMaterial &); - /* This function should be used if you only have a single material sub-table. - It increases the number of total materials and returns the last material - ID to you. - */ - int AddMaterial(const trpgMaterial &); + /* Return the number of sub-tables. This will, most commonly, be 1. + Any value more than 1 means the archive has alternate material definitions + (think IR or Radar versions). + */ + bool GetNumTable(int &) const; + /* The number of materials per sub-table. Each sub-table has the same number + of materials. So there will be N x M number of materials total, but you'll + only see M of them at any given time. + */ + bool GetNumMaterial(int &) const; - /* Return the number of sub-tables. This will, most commonly, be 1. - Any value more than 1 means the archive has alternate material definitions - (think IR or Radar versions). - */ - bool GetNumTable(int &) const; - /* The number of materials per sub-table. Each sub-table has the same number - of materials. So there will be N x M number of materials total, but you'll - only see M of them at any given time. - */ - bool GetNumMaterial(int &) const; + /* Returns the material definition for the given subTable and the given material + ID. The most common subTable will be 0 (visual). The material ID comes + from the value(s) in trpgGeometry. + */ + bool GetMaterial(int subTable,int matID,trpgMaterial &) const; - /* Returns the material definition for the given subTable and the given material - ID. The most common subTable will be 0 (visual). The material ID comes - from the value(s) in trpgGeometry. - */ - bool GetMaterial(int subTable,int matID,trpgMaterial &) const; + /* This is a convenience method for getting a reference to a trpgMaterial object. + The reason you might want to do this is if you don't want to create a full + trpgMaterial object to pass to GetMaterial. + The returned value is only valid until the next GetMaterialRef call. + */ + const trpgMaterial *GetMaterialRef(int,int) const; - /* This is a convenience method for getting a reference to a trpgMaterial object. - The reason you might want to do this is if you don't want to create a full - trpgMaterial object to pass to GetMaterial. - The returned value is only valid until the next GetMaterialRef call. - */ - trpgMaterial *GetMaterialRef(int,int); + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); protected: - int numTable; - int numMat; - vector baseMats; - vector matTables; - trpgMaterial matRef; + int numTable; + int numMat; + std::vector matTables; }; /* This class holds the texture definition TerraPage uses. Textures are a little - different than other TerraPage objects for the following reason: they aren't - stored in the archive. Instead they're stored individually on disk in your - favorite image format. We don't constrain what that format is, although SGI - format (.rgb) is always the safest in this industry. + different than other TerraPage objects for the following reason: they aren't + stored in the archive. Instead they're stored individually on disk in your + favorite image format. We don't constrain what that format is, although SGI + format (.rgb) is always the safest in this industry. - Texture objects are really just references to these on-disk textures. As such, - they're pretty simple. They just consist of a filename. These trpgTexture - objects will be indexed in a trpgTexTable. The indices you get from trpgMaterial - objects point to trpgTexture objects through that table. trpgMaterial objects - should be the only things that have texture indices. + Texture objects are really just references to these on-disk textures. As such, + they're pretty simple. They just consist of a filename. These trpgTexture + objects will be indexed in a trpgTexTable. The indices you get from trpgMaterial + objects point to trpgTexture objects through that table. trpgMaterial objects + should be the only things that have texture indices. - If you're doing a TerraPage reader textures are pretty simple to read in. There - are two ways to do it. First, if you're not doing texture paging, simply read - them all in, using the trpgTexTable to figure out where they all are. If you - are doing texture paging (highly recommended) then you'll need to call GetNumTile - to figure out how many tiles a texture is used in. If it's 1, then this is probably - a geospecific textures and ought to be paged. If it's more than 1, then it's a - geotypical texture (i.e. a tree or road) and should be loaded in at the beginning. + If you're doing a TerraPage reader textures are pretty simple to read in. There + are two ways to do it. First, if you're not doing texture paging, simply read + them all in, using the trpgTexTable to figure out where they all are. If you + are doing texture paging (highly recommended) then you'll need to call GetNumTile + to figure out how many tiles a texture is used in. If it's 1, then this is probably + a geospecific textures and ought to be paged. If it's more than 1, then it's a + geotypical texture (i.e. a tree or road) and should be loaded in at the beginning. - If you're doing a TerraPage writer you'll need to be creating trpgTexture objects - as you go and adding them to your central trpgTexTable. If you want to support - texture paging set the numTile count to 1 for the geospecific textures and more - than 1 for everything else. There are utility functions for keeping track of all - of this. It's best to use those. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer you'll need to be creating trpgTexture objects + as you go and adding them to your central trpgTexTable. If you want to support + texture paging set the numTile count to 1 for the geospecific textures and more + than 1 for everything else. There are utility functions for keeping track of all + of this. It's best to use those. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTexture : public trpgReadWriteable { public: - trpgTexture(void); - trpgTexture(const trpgTexture &); - ~trpgTexture(void); + trpgTexture(void); + trpgTexture(const trpgTexture &); + ~trpgTexture(void); - // Set the texture name. - void SetName(const char *); - /* This is the texture name. You pass in a string of a pre-defined length - and it returns the texture name in that. */ - bool GetName(char *retStr,int strLen) const; + /* This enum is used to determine where the image is. + External - Stored in an external file, just like TerraPage 1.x. + Local - Stored in one of the archive files. The type and size will be here. + Use trpgrImageHelper to fetch the image, either initially or later. + Global - This image is really large and parts of it will be referenced + later within individual tiles. Use the trpgrImageHelper class + to reference the various parts of the image. Don't load it yourself. + Template - This isn't an image at all. It's here to represent a class of + images with a certain size and type. You'll encounter inline materials + (for pageable textures) in the tiles which make use of this template. + If you use trpgrImageHelper to fetch those textures, you don't need to + do anything with this texture. + */ + typedef enum {External,Local,Global,Template} ImageMode; - /* Sets the number of tiles this texture is used in. This hint is used by - readers to determine texture pageability. */ - void SetNumTile(int); - /* Instead of calling SetNumTile after you've built a database, you can call - AddTile as you encounter each texture reference (per tile). */ - void AddTile(); + /* These are the types of images TerraPage can support for Local and Template + image modes (see ImageMode). If the image is External or Global, anything + is fair game, but these are the only types TerraPage can store itself. + */ + typedef enum { + trpg_RGB8, + trpg_RGBA8, + trpg_INT8, + trpg_INTA8, + trpg_FXT1, + trpg_Filler, // This is not a texture format. It's here to keep the numbering consistent + trpg_RGBX, // MCM + trpg_Unknown, + trpg_DDS, + trpg_DXT1, + trpg_DXT3, + trpg_DXT5 + } ImageType; - /* This tells you the number of tiles this texture is used in. You can - use this to do texture paging (if you can support it). It's a pretty - general meachanism and will work for large scale geospecific terrain textures - as well as things like specific building pictures. */ - bool GetNumTile(int &) const; + // How the image bit planes are organized + typedef enum {} ImageOrg; - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Set the texture name. + void SetName(const char *); + /* This is the texture name. You pass in a string of a pre-defined length + and it returns the texture name in that. */ + bool GetName(char *retStr,int strLen) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + /* Sets the number of tiles this texture is used in. This hint is used by + readers to determine texture pageability. */ + void SetNumTile(int); + /* Instead of calling SetNumTile after you've built a database, you can call + AddTile as you encounter each texture reference (per tile). */ + void AddTile(void); - trpgTexture & operator = (const trpgTexture &); - int operator == (const trpgTexture &) const; + /* This tells you the number of tiles this texture is used in. You can + use this to do texture paging (if you can support it). It's a pretty + general meachanism and will work for large scale geospecific terrain textures + as well as things like specific building pictures. + When GetImageMode returns Global, expect this value to always be 1. For + Template texture, it will be set to the total number of uses of the template + (which should be fairly large). + */ + bool GetNumTile(int &) const; + + // Retrieve the image mode for this texture. See ImageMode for details. + bool GetImageMode(ImageMode &) const; + + // Retrieve the image type for this texture. See ImageType for details. + // This method is only used if ImageMode is Local or Template + bool GetImageType(ImageType &) const; + + // Find out how the bit planes are organized. Only important for some types + // of images + bool GetImageOrganization(ImageOrg &) const; + + // Retrieve the size of this image. Valid only for Local and Template textures. + bool GetImageSize(trpg2iPoint &) const; + + // Get the location of a Local image + bool GetImageAddr(trpgwAppAddress &) const; + + // Figure out the image depth from the type + bool GetImageDepth(int32 &depth) const; + + // Determine whether this image (must be Local or Template) has all its mipmaps + bool GetIsMipmap(bool &) const; + + // Set the image mode of this texture. Used by writers only. + void SetImageMode(ImageMode); + + // Set the image type of this texture. See GetImageType for details. + void SetImageType(ImageType); + + // Sets a constant the dictates bit plane organization. Not used for all image + // types + void SetImageOrganization(ImageOrg); + + // Set the image size of this texture. See GetImageSize for details + void SetImageSize(const trpg2iPoint &); + + // Set the image location (For Local images only) + void SetImageAddr(const trpgwAppAddress &); + + // Set whether or not this is a full set of mipmaps + void SetIsMipmap(bool); + + // Set the storage sizes for all mipmap levels +// void SetStorageSizes(vector &); + + // Get the storage sizes for all mipmap levels. +// bool GetStorageSizes(const vector *) const; + + // Set the number of mipmap levels + void SetNumMipmap(int); + + // Set the number of layers used in an RGBX image + void SetNumLayer(int); + + // Get the number of layers used in an RGBX image. RGBX images are typically for + // sensors and contain arbitrary data which is not visual. + bool GetNumLayer(int &) const; + + /* Utility to figure out the number of mipmap levels this image would have. + Only really necessary for Local or Template images. + */ + int32 CalcNumMipmaps() const; + + // Calculate the total size of this texture + int32 CalcTotalSize() const; + + // Returns the size of a given mip level + int32 MipLevelSize(int miplevel); + + // Returns the offset of the mip level in the whole texture data buffer + int32 MipLevelOffset(int miplevel); + + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + trpgTexture & operator = (const trpgTexture &); + int operator == (const trpgTexture &) const; protected: - char *name; - int useCount; + // Mode for this texture. See ImageMode for details + ImageMode mode; + + // Type of texture (only valid if ImageMode is Local or Template) + ImageType type; + + // Organize of image bit planes + ImageOrg org; + + // The name really only has meaning for External or Global textures + char *name; + int useCount; + + // The size values are used only if this is a Local or Template image + int sizeX,sizeY; + + // Whether or not there are mipmap levels + bool isMipmap; + + // Number of mipmap levels, 0 if not present + int numMipMap; + + // Number of layers (for RGBX) + int numLayer; + + // Sizes of each level. This is important for compressed textures in particular, + // which may have random sizes. Used only for Local textures. + std::vector storageSize; + + // Offset of each level + std::vector levelOffset; + + // Address is used only for Local textures + trpgwAppAddress addr; + + // calculate the mip level sizes + void CalcMipLevelSizes(); }; /* The texture table keeps track of all the textures in a TerraPage archive. - All textures are indexed centrally here. The indices in trpgMaterial objects - point into a trpgTexTable. Although the trpgMatTable potentially has several - sub-tables for different representations (visual, IR, etc..), the trpgTexTable - is not affected by that. All textures, no matter what their use, are indexed - together here. + All textures are indexed centrally here. The indices in trpgMaterial objects + point into a trpgTexTable. Although the trpgMatTable potentially has several + sub-tables for different representations (visual, IR, etc..), the trpgTexTable + is not affected by that. All textures, no matter what their use, are indexed + together here. - If you're doing a TerraPage reader you'll get a trpgTexTable back from your - trpgr_Archive. You'll then want to iterate over the trpgTexture objects and - load in the ones used in more than one tile. If you can do texture paging - you should leave the ones only used in 1 tile alone initially. You may also - want to set up a mapping from texture indices here into whatever your own texture - repository is. The texture indices in trpgMaterial objects refer to the listing - here. + If you're doing a TerraPage reader you'll get a trpgTexTable back from your + trpgr_Archive. You'll then want to iterate over the trpgTexture objects and + load in the ones used in more than one tile. If you can do texture paging + you should leave the ones only used in 1 tile alone initially. You may also + want to set up a mapping from texture indices here into whatever your own texture + repository is. The texture indices in trpgMaterial objects refer to the listing + here. - If you're doing a TerraPage writer you'll want to create one of these and add - textures as you go. Textures are copied in when you call AddTexture or SetTexture - so you can reused the trpgTexture object you put together to pass in. The texture - index returned by AddTexture should be used in the trpgMaterial you'll need to build. - Textures don't live in isolation and must be applied to geometry through a trpgMaterial. - After the trpgTexTable is built it will get passed to a trpgwArchive for writing. That - can be done right before you close the archive. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer you'll want to create one of these and add + textures as you go. Textures are copied in when you call AddTexture or SetTexture + so you can reused the trpgTexture object you put together to pass in. The texture + index returned by AddTexture should be used in the trpgMaterial you'll need to build. + Textures don't live in isolation and must be applied to geometry through a trpgMaterial. + After the trpgTexTable is built it will get passed to a trpgwArchive for writing. That + can be done right before you close the archive. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTexTable : public trpgReadWriteable { public: - trpgTexTable(void); - trpgTexTable(const trpgTexTable &); - ~trpgTexTable(void); + trpgTexTable(void); + trpgTexTable(const trpgTexTable &); + ~trpgTexTable(void); - /* Sets the total number of textures in this table. This is used in - combination with SetTexture. If you can, you should use AddTexture - and FindAddTexture instead. - */ - void SetNumTextures(int); - /* Adds the given texture to the table and increments the total texture - count. If you use this, you should not use SetNumTextures and SetTexture. - */ - int AddTexture(const trpgTexture &); - /* This is the same as AddTexture except that it searches for a matching texture - first. This is convenient for writers who aren't keeping track of their - own textures internally. - */ - int FindAddTexture(const trpgTexture &); - /* This sets the given texture ID to be the trpgTexture passed in. It's used - in combination with SetNumTextures. Use AddTexture or FindAddTexture instead - if you can. - */ - void SetTexture(int texID,const trpgTexture &); + /* Sets the total number of textures in this table. This is used in + combination with SetTexture. If you can, you should use AddTexture + and FindAddTexture instead. + */ + void SetNumTextures(int); + /* Adds the given texture to the table and increments the total texture + count. If you use this, you should not use SetNumTextures and SetTexture. + */ + int AddTexture(const trpgTexture &); + /* This is the same as AddTexture except that it searches for a matching texture + first. This is convenient for writers who aren't keeping track of their + own textures internally. + */ + int FindAddTexture(const trpgTexture &); + /* This sets the given texture ID to be the trpgTexture passed in. It's used + in combination with SetNumTextures. Use AddTexture or FindAddTexture instead + if you can. + */ + void SetTexture(int texID,const trpgTexture &); - // Returns the number of textures in this table - bool GetNumTextures(int &) const; - // This returns the trpgTexture corresponding to the given ID (from a trpgMaterial) - bool GetTexture(int texID,trpgTexture &) const; - /* Does the same thing as GetTexture only it returns a pointer instead. - You would use this if you don't want a new trpgTexture created for you. - Assume the value it returns is only good until the next GetTextureRef call. - */ - trpgTexture *GetTextureRef(int); + // Returns the number of textures in this table + bool GetNumTextures(int &) const; + // This returns the trpgTexture corresponding to the given ID (from a trpgMaterial) + bool GetTexture(int texID,trpgTexture &) const; + /* Does the same thing as GetTexture only it returns a pointer instead. + You would use this if you don't want a new trpgTexture created for you. + Assume the value it returns is only good until the next GetTextureRef call. + */ + const trpgTexture *GetTextureRef(int) const; - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; - trpgTexTable & operator = (const trpgTexTable &); + + trpgTexTable & operator = (const trpgTexTable &); protected: - vector texList; + std::vector texList; }; /* Models are basically just references in TerraPage. This class just points - to a model from somewhere else. There are two places it can point. (1) It - can point externally to a model in some arbitrary format (OpenFlight(tm) is - a popular one). (2) It can also point to a model within the TerraPage archive. - The first case is much like trpgTexture objects are treated. That is, the actual - thing itself is on disk somewhere corresponding to a file name. The second case is - more like tile terrain geometry. In that case there is scene node type data (LODs, - groups, geometry, etc...) associated with it. + to a model from somewhere else. There are two places it can point. (1) It + can point externally to a model in some arbitrary format (OpenFlight(tm) is + a popular one). (2) It can also point to a model within the TerraPage archive. + The first case is much like trpgTexture objects are treated. That is, the actual + thing itself is on disk somewhere corresponding to a file name. The second case is + more like tile terrain geometry. In that case there is scene node type data (LODs, + groups, geometry, etc...) associated with it. - trpgModel objects live within a trpgModelTable. They are indexed there and refered - to by trpgModelRef objects. Those model references are the only things that explicitly - use trpgModel objects. + trpgModel objects live within a trpgModelTable. They are indexed there and refered + to by trpgModelRef objects. Those model references are the only things that explicitly + use trpgModel objects. - If you're doing a TerraPage reader you'll need to take into account whether the - model is external or internal. If it's external you'll need to read the given file - and convert it to your own representation. If it's internal you've probably already - got the code for dealing with terrain tiles, which is essentially the same thing. - Models can be paged, if you're so inclined. They have tile reference counts just - like trpgTexture objects. If numTile == 1 then page it, if > 1 then don't. + If you're doing a TerraPage reader you'll need to take into account whether the + model is external or internal. If it's external you'll need to read the given file + and convert it to your own representation. If it's internal you've probably already + got the code for dealing with terrain tiles, which is essentially the same thing. + Models can be paged, if you're so inclined. They have tile reference counts just + like trpgTexture objects. If numTile == 1 then page it, if > 1 then don't. - If you're doing a TerraPage writer you'll want to build up a trpgModelTable of these - as you encounter them. If your models are external in some other format then setting - up a trpgModel is pretty easy. If you want to do internal models, the support is not - quite there yet. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer you'll want to build up a trpgModelTable of these + as you encounter them. If your models are external in some other format then setting + up a trpgModel is pretty easy. If you want to do internal models, the support is not + quite there yet. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgModel : public trpgReadWriteable { public: - trpgModel(void); - trpgModel(const trpgModel &); - ~trpgModel(void); - enum {Local,External}; - // Sets the name of the external model file and sets this model to External type. - void SetName(const char *); - // Sets the on-disk reference to an internal model and sets this model to Internal type. - void SetReference(trpgDiskRef); - /* Models are reference counted (per-tile). It's up to the writer to set this - value. */ - void SetNumTiles(int); - /* TerraPage writers can use AddTile (starts at 0) every time they use this model - in a tile. Note that this is not for every instance within a tile. So if - you use a model 40 times within a tile, you call AddTile once. - This is used instead of SetNumTiles. */ - void AddTile(); + trpgModel(void); + trpgModel(const trpgModel &); + ~trpgModel(void); + enum {Local,External}; + // Sets the name of the external model file and sets this model to External type. + void SetName(const char *); + // Sets the on-disk reference to an internal model and sets this model to Internal type. + void SetReference(trpgDiskRef); + /* Models are reference counted (per-tile). It's up to the writer to set this + value. */ + void SetNumTiles(int); + /* TerraPage writers can use AddTile (starts at 0) every time they use this model + in a tile. Note that this is not for every instance within a tile. So if + you use a model 40 times within a tile, you call AddTile once. + This is used instead of SetNumTiles. */ + void AddTile(void); - /* Returns the type (Local or External) of this model */ - bool GetType(int &); - /* If the model is external, this returns the file name of that model. - You pass in a string and a length and it copies the filename into that. */ - bool GetName(char *ret,int strLen) const; - /* If the model is internal, this returns the disk reference to it. - At some future data you'll be able to simply read these out of an archive. */ - bool GetReference(trpgDiskRef &) const; - /* Models are reference counted, like trpgTexture objects. You can use this - value to determine whether or not you should page models. - */ - bool GetNumTiles(int &) const; + /* Returns the type (Local or External) of this model */ + bool GetType(int &); + /* If the model is external, this returns the file name of that model. + You pass in a string and a length and it copies the filename into that. */ + bool GetName(char *ret,int strLen) const; + /* If the model is internal, this returns the disk reference to it. + At some future data you'll be able to simply read these out of an archive. */ + bool GetReference(trpgDiskRef &) const; + /* Models are reference counted, like trpgTexture objects. You can use this + value to determine whether or not you should page models. + */ + bool GetNumTiles(int &) const; - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; - trpgModel & operator = (const trpgModel &); - int operator == (const trpgModel &) const; + + trpgModel & operator = (const trpgModel &); + int operator == (const trpgModel &) const; protected: - int type; - char *name; - trpgDiskRef diskRef; - int useCount; + int type; + char *name; + trpgDiskRef diskRef; + int useCount; }; /* Models (trpgModel) are indexed together in a model table. There is one - model table per TerraPage archive. It holds the canonical list of models - for the entire database. It's pretty simple. Just a list of models, really. - the trpgModel object holds the real information. + model table per TerraPage archive. It holds the canonical list of models + for the entire database. It's pretty simple. Just a list of models, really. + the trpgModel object holds the real information. - If you're doing a TerraPage reader you'll get one of these from a trpgr_Archive. - You'll want to iterate over the models in it and figure out which ones to page, - if you're doing model paging. If not, then you can just read them all in - at initialization time and index them as need per-tile. + If you're doing a TerraPage reader you'll get one of these from a trpgr_Archive. + You'll want to iterate over the models in it and figure out which ones to page, + if you're doing model paging. If not, then you can just read them all in + at initialization time and index them as need per-tile. - If you're doing a TerraPage writer you'll build one of these up for the entire - database as you go. Just call AddModel every time you finish a model definition. - The finished table will be passed to trpgwArchive at the end. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer you'll build one of these up for the entire + database as you go. Just call AddModel every time you finish a model definition. + The finished table will be passed to trpgwArchive at the end. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgModelTable : public trpgReadWriteable { public: - trpgModelTable(void); - ~trpgModelTable(void); + trpgModelTable(void); + ~trpgModelTable(void); - /* Set the total number of models in the table. Use this in conjunction - with SetModel. If you can, use AddModel isntead of either of these. - */ - void SetNumModels(int); - /* Add the given model to the table. Makes a copy of the model you pass in - and returns the new model ID which you'll need to reference in trpgModelRef. - */ - int AddModel(const trpgModel &); - /* Sets the model definition corresponding to the given ID. Use this in conjunction - with SetNumModels. */ - void SetModel(int,const trpgModel &); + /* Set the total number of models in the table. Use this in conjunction + with SetModel. If you can, use AddModel isntead of either of these. + */ + void SetNumModels(int); + /* Add the given model to the table. Makes a copy of the model you pass in + and returns the new model ID which you'll need to reference in trpgModelRef. + */ + int AddModel(const trpgModel &); + /* Look for a given model. If it's not there, add it. */ + int FindAddModel(const trpgModel &); + /* Sets the model definition corresponding to the given ID. Use this in conjunction + with SetNumModels. */ + void SetModel(int,const trpgModel &); - // Returns the number of models in this table - bool GetNumModels(int &) const; - /* Returns the Nth model. trpgModelRef objects point into this table - and that is where the model ID comes from. */ - bool GetModel(int modID,trpgModel &) const; + // Returns the number of models in this table + bool GetNumModels(int &) const; + /* Returns the Nth model. trpgModelRef objects point into this table + and that is where the model ID comes from. */ + bool GetModel(int modID,trpgModel &) const; - /* The same as GetModel only it returns a pointer to the trpgModel instead. - Use this if you don't want to create a copy of the model. - The result is only good until the next GetModelRef call. - */ - trpgModel *GetModelRef(int); + /* The same as GetModel only it returns a pointer to the trpgModel instead. + Use this if you don't want to create a copy of the model. + The result is only good until the next GetModelRef call. + */ + trpgModel *GetModelRef(int); - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; protected: - vector models; + std::vector models; }; /* The tile table keeps track of tile locations within a TerraPage archive. - At the present time archives are broken out into multiple files. When - it becomes possible to combine an archive into a single file then this - object will become important. For now, you can safely ignore it.. - {group:Read/Write Classes} - */ + Tiles can be stored either externally (as individual files) or locally + (grouped together into bigger files). The details are hidden from the + reader completely and the writer in most cases. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTileTable : public trpgReadWriteable { public: - trpgTileTable(void); - ~trpgTileTable(void); - enum {Local,External}; - void SetNumTiles(int,int); - void SetNumTiles(int,int,int); - void SetBaseName(const char *); - void SetTile(int,int,int,trpgDiskRef); - void SetTile(int,int,trpgDiskRef); - void SetCenter(int,int,int,const trpg3dPoint &); - void SetCenter(int,int,const trpg3dPoint &); + // Tiles can be stored individually (External) or in grouped files (Local) + typedef enum {Local,External} TileMode; - bool GetNumTiles(int &,int &,int &) const; - // Local or external tiles - bool GetType(int &) const; - bool GetBaseName(char *,int len) const; - // Get the disk reference (local) - bool GetTile(int,int,int,trpgDiskRef &) const; - // Generate the file name (external) - bool GetTile(int,int,int,char *,int len) const; - bool GetCenter(int,int,int,trpg3dPoint &) const; + trpgTileTable(void); + ~trpgTileTable(void); + // Set the tile storage mode: external or local + void SetMode(TileMode); + // Set the total number of LODs + void SetNumLod(int numLod); + // Set the number of tiles in each dimenion for each terrain LOD + // This must agree with trpgHeader + void SetNumTiles(int numX,int numY,int lod); + // Set the external address of a given tile as well as its Z value + void SetTile(int x,int y,int lod,trpgwAppAddress &,float32 min,float32 max); - const char *GetBaseName(void) const; + // Local or external tiles + bool GetMode(TileMode &) const; + // Get the disk reference (local) + bool GetTile(int x,int y,int lod,trpgwAppAddress &,float32 &min,float32 &max) const; - // Validity check - bool isValid(void) const; - // Reads this class from a read buffer - void Reset(void); + // Validity check + bool isValid(void) const; + // Reads this class from a read buffer + void Reset(void); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); protected: - int type; - int numLod,numX,numY; - vector lodSizes; + TileMode mode; -// vector tiles; -// vector center; + class LodInfo { + public: + int numX,numY; + // Tile addresses into external Appendable files + std::vector addr; + // Elevation of the midpoint of each tile + // This is used for calculating bounding boxes + std::vector elev_min; + std::vector elev_max; + }; + std::vector lodInfo; +}; - char *baseName; +/* Local materials are new to TerraPage 2.0. + The idea is that for pageable one-time textures it makes more sense + to define them in the tiles. This keeps the size of Texture and + Material tables down in the header. It also lets us make use of + Global textures by grabbing subimages. + You'll encounter these in a tile right after the tile header. They'll + be referenced by ID in trpgGeometry nodes within that tile. They + can represent a sub-image of a Global texture or a whole Local texture. + In either case, you can pass this class to trpgrTextureHelper and let + it get the image data for you. + */ +TX_EXDECL class TX_CLDECL trpgLocalMaterial : public trpgReadWriteable { +public: + trpgLocalMaterial(void); + ~trpgLocalMaterial(void); + + // Set the base material for this local material + void SetBaseMaterial(int32 matSubTable,int32 matID); + + /* Get the base material for this local material. Base materials + define the colors, specularity, texture environments, and in + general everything not having to do with the texture image itself. + In effect you're using the base material as your material definition and + the local material is just telling you what part of the image to use. + By convention, there should only be one global image used in any given + trpgMaterial and it should be at texture index 0 (within that trpgMaterial). + If you want to use multiple pageable textures per polygon, you can do + that with multiple materials per trpgGeometry node. Doing it any + other way makes my head hurt (actually the thought of multiple, pageable + textures per polygon makes my head hurt in general). + */ + bool GetBaseMaterial(int32 &matSubTable,int32 &matID) const; + + class SubImageInfo { + public: + int32 sx,sy; // Source (sx,sy) in pixels + int32 ex,ey; // Source (ex,ey) in pixels + int32 destWidth,destHeight; // Size of destination image (in pixels) + }; + + // Set the sub image info (only for writers) + void SetSubImageInfo(const SubImageInfo &); + + /* Get the sub image info. This is valid only for Global images + (you can check what a given Local Material is by looking at the + base material's texture). + */ + bool GetSubImageInfo(SubImageInfo &) const; + + // Set the address info (only for writers) + void SetAddr(const trpgwAppAddress &); + + /* Get the address (location in an archive) for an image. + This is valid for Local images only. You can determine what + a Local Material refers to by looking in its base material's texture. + */ + bool GetAddr(trpgwAppAddress &) const; + + // Set the storage sizes for all mipmap levels +// bool SetStorageSizes(vector &); + + // Get the storage sizes for all mipmap levels. +// bool GetStorageSizes(const vector *) const; + + // Validity check + bool isValid(void) const; + // Reads this class from a read buffer + void Reset(void); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + +protected: + int32 baseMatTable,baseMat; + // These are valid for Global images + int32 sx,sy,ex,ey,destWidth,destHeight; + // Storage sizes for each mipmap level. Important for compressed textures. +// vector storageSize; + // This is valid only for Tile Local images + trpgwAppAddress addr; }; /* The tile header is one of the more interesting parts of TerraPage. Basically, - it's a list of all the materials and models used in a tile. Tile headers are - stuck at the beginning of terrain tiles to give you this information. They - can be read separately, in theory, although no one is doing that at present. + it's a list of all the materials, local material and models used in a tile. Tile headers are + stuck at the beginning of terrain tiles to give you this information. They + can be read separately, in theory, although no one is doing that at present. - If you're doing a TerraPage reader you will encounter one of these first thing - when you parse a terrain tile. If you're doing texture paging you'll want to get - the list of material IDs, consult those materials and compile a list of texture - IDs that you need loaded in. You can then load those textures in (if necessary) - and go from there. If you're paging models, you can do something similar with - the model list. In theory, the trpgTileHeader is not required for every tile. - If you don't encounter one when reading a tile you'd better assume that everything - needs to be loaded (i.e. texture/model paging is not supported). + If you're doing a TerraPage reader you will encounter one of these first thing + when you parse a terrain tile. These are here to aid texture and model paging. + Texture paging is the most common and there are now two ways of doing it. The + simpler one (supported in version 1.0) is as follows. Textures are indexed at + the beginning of a TerraPage archive (in a trpgTexTable) and when listed in the + trpgTileHeader for a tile must be loaded in for use. You can tell the pageable + textures from the non-pageable ones by looking at the tile reference count in + the trpgTexture object. - If you're doing a TerraPage writer you will need to construct one of these for - each tile that you build (remember that tiles are per-terrain LOD). You'll want - to call AddMaterial for every material that you use in a tile and AddModel - for every model. You can call these methods multiple times and it will keep track - of whether you've already added a model or material. The tile header will then - be passed to trpgwArchive along with the tile geometry and written to disk. - {group:Read/Write Classes} - */ + The second way of doing texture paging (in version 2.0) is more complex, but + much more powerful. One of the big problems we encountered with v1.0 was the + enormous proliferation of texture files. In addition, much information was + duplicated between the different terrain resolutions. Lastly, we (TERREX) have + had a lot of success with wavelet compressed image pyramids for solving quite a + few interesting problems. This second approach to texture paging makes use of + what we've learned from all of this. The idea is that instead of having lots of + little textures, we have a small number of very large images which can support + extraction at any resolution. In this way we re-use information between terrain + levels of detail and we cut down on our disk usage, both in terms of number of + files as well as data size. + + To implement this scheme we added the trpgLocalMaterial object. trpgTexture + objects tell you if they are global images (e.g. parts are pageable). If they + are, then they can be used in a trpgLocalMaterial. These objects define the + sub-image (extents and a resolution) for a texture/material that can be used + within this tile (and only within this tile). The trpgLocalMaterial objects + reside within the trpgTileHeader and should be filled out (e.g. the sub-images + paged) as soon as the trpgTileHeader is parsed because you'll be needing them + in trpgGeometry nodes to follow. + + If you want to page models, you can do so by looking at the list of model IDs + used in a tile. + + If you're doing a TerraPage writer you will need to construct one of these for + each tile that you build (remember that tiles are per-terrain LOD). You'll want + to call AddMaterial for every material that you use in a tile and AddModel + for every model. You can call these methods multiple times and it will keep track + of whether you've already added a model or material. The tile header will then + be passed to trpgwArchive along with the tile geometry and written to disk. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTileHeader : public trpgReadWriteable { public: - trpgTileHeader(void); - ~trpgTileHeader(void); - /* Add the given material reference to this tile if it's not already there. - The ID passed in refers to a trpgMatTable. */ - void AddMaterial(int); - /* Add the given model reference to this tile if it's not already there. - The ID passed in refers to a trpgModelTable. */ - void AddModel(int); - // {secret} - void SetDate(int32); + trpgTileHeader(void); + ~trpgTileHeader(void); + /* Add the given material reference to this tile if it's not already there. + The ID passed in refers to a trpgMatTable. */ + void AddMaterial(int); + /* Add the given model reference to this tile if it's not already there. + The ID passed in refers to a trpgModelTable. */ + void AddModel(int); + /* Add the given local material to the list of local materials in this tile. + Local materials are used to page sub-pieces of very large images and + are referenced by trpgGeometry nodes (in their material indices) within + a given tile. Local materials can't be referenced across tiles. + */ + void AddLocalMaterial(trpgLocalMaterial &); + // {secret} + void SetDate(int32); + /* Set the given material reference to the given value. + It's easier to use AddMaterial(), if possible. + */ + void SetMaterial(int no,int id); + /* Set the given model reference (in this tile) to the given value + It's easier to use AddModel(), if possible. + */ + void SetModel(int no,int id); - void SetMaterial(int no,int id); - void SetModel(int no,int id); + // Returns the number of materials used in this tile + bool GetNumMaterial(int32 &) const; + /* Return the material ID of the Nth material reference. + The ID returned points into a trpgMatTable. */ + bool GetMaterial(int32 nth,int32 &matID) const; + // This is the number of models used in this tile + bool GetNumModel(int32 &) const; + /* Gets the model ID of the Nth model reference. + The ID returned points into a trpgModelTable. */ + bool GetModel(int32 nth,int32 &modID) const; + // Returns the number of local materials in this tile + bool GetNumLocalMaterial(int32 &) const; + /* Return the given local material. Local materials are used + to page sub-pieces of extremely large images. The Local Material + list within a tile is distinct from the list of materials used within + a tile. Local materials will be referenced by trpgGeometry nodes within + a given tile. + */ + bool GetLocalMaterial(int32 nth,trpgLocalMaterial &locMat) const; + /* Return a pointer to the list of locally defined materials. + See GetLocalMaterial for an explantion of local materials. + */ + const std::vector *GetLocalMaterialList(void) const; + // {secret} + bool GetDate(int32 &) const; - // Returns the number of materials used in this tile - bool GetNumMaterial(int32 &) const; - /* Return the material ID of the Nth material reference. - The ID returned points into a trpgMatTable. */ - bool GetMaterial(int32 nth,int32 &matID) const; - // This is the number of models used in this tile - bool GetNumModel(int32 &) const; - /* Gets the model ID of the Nth model reference. - The ID returned points into a trpgModelTable. */ - bool GetModel(int32 nth,int32 &modID) const; - // {secret} - bool GetDate(int32 &) const; + // Validity check + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); - // Validity check - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); protected: - vector matList; - vector modelList; - int date; + std::vector matList; + std::vector modelList; + std::vector locMats; + // {secret} + int date; }; /* The color info structure is used by the trpgGeometry class to store - per vertex (or per primitive) color information. It can be read directly - by the user (all its data is public). This structure is returned by - trpgGeometry::GetColorSet(). - {group:Read/Write Classes} - */ + per vertex (or per primitive) color information. It can be read directly + by the user (all its data is public). This structure is returned by + trpgGeometry::GetColorSet(). + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgColorInfo { public: - trpgColorInfo(void); - ~trpgColorInfo(void); + trpgColorInfo(void); + ~trpgColorInfo(void); - /* This is a trpgGeometry::ColorType - */ - int type; - /* This refers to how the colors in the data array are used. - It can take the values "Overall", "PerPrim" or "PerVertex". - */ - int bind; - /* The list of colors. There will be one total (bind=Overall), one per - primitive (bind=PerPrim), or one per vertex (bind=PerVertex). - */ - vector data; - /* Resets the structure to a default state. - */ - void Reset(void); + /* This is a trpgGeometry::ColorType + */ + int type; + /* This refers to how the colors in the data array are used. + It can take the values "Overall", "PerPrim" or "PerVertex". + */ + int bind; + /* The list of colors. There will be one total (bind=Overall), one per + primitive (bind=PerPrim), or one per vertex (bind=PerVertex). + */ + std::vector data; + /* Resets the structure to a default state. + */ + void Reset(void); + + // Print out debugging info + bool Print(trpgPrintBuffer &) const; }; /* This class represents a group of texture coordinates applied to a trpgGeometry - class. It is returned by trpgGeometry::GetTexCoordSet. TerraPage supports - multiple materials per polygon. The way we implement this is as multiple - materials on a trpgGeometry node. The first material with be the "primary" - and additional ones will be secondary and so on. - To support this, we need multiple sets of texture coordinates. That's what - this structure is used for. - {group:Read/Write Classes} - */ + class. It is returned by trpgGeometry::GetTexCoordSet. TerraPage supports + multiple materials per polygon. The way we implement this is as multiple + materials on a trpgGeometry node. The first material with be the "primary" + and additional ones will be secondary and so on. + To support this, we need multiple sets of texture coordinates. That's what + this structure is used for. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTexData { public: - trpgTexData(void); - ~trpgTexData(void); - // This should always be set to PerVertex - int bind; - /* List of texture coordinates in 32 bit floating point. - There should be one per vertex. Either this or doubleData will be - set, but never both. - */ - vector floatData; - /* List of texture coordinates in 64 bit floating point. - There should be one per vertex. Either this or floatData will be - set, but never both. - */ - vector doubleData; - /* Initialize the texture coordinate data set with floating point or double values. - num should correspond to the correct bind. */ - void set(int num,int bind,const float32 *); - void set(int num,int bind,const float64 *); - /* Resets the structure to a default state. - */ - void Reset(void); + trpgTexData(void); + ~trpgTexData(void); + // This should always be set to PerVertex + int bind; + /* List of texture coordinates in 32 bit floating point. + There should be one per vertex. Either this or doubleData will be + set, but never both. + */ + std::vector floatData; + /* List of texture coordinates in 64 bit floating point. + There should be one per vertex. Either this or floatData will be + set, but never both. + */ + std::vector doubleData; + /* Initialize the texture coordinate data set with floating point or double values. + num should correspond to the correct bind. */ + void set(int num,int bind,const float32 *); + void set(int num,int bind,const float64 *); + /* Resets the structure to a default state. + */ + void Reset(void); + + // Print out debugging info + bool Print(trpgPrintBuffer &) const; }; /* The trpgGeometry class represents a low level geometry node within the - TerraPage "scene graph". This is where the triangles (or quads, polygons, etc...) - are actually kept. If you're writing a TerraPage reader, you'll encounter a - lot of these nodes. If you're doing a writer, you'll need to construct them. - You can use a trpgwGeomHelper to aid you in this process. - We use data arrays to store lists of vertices, colors, texture coordinates, and - normals. These data arrays correspond pretty closely to the respective OpenGL - equivalents. + TerraPage "scene graph". This is where the triangles (or quads, polygons, etc...) + are actually kept. If you're writing a TerraPage reader, you'll encounter a + lot of these nodes. If you're doing a writer, you'll need to construct them. + You can use a trpgwGeomHelper to aid you in this process. + We use data arrays to store lists of vertices, colors, texture coordinates, and + normals. These data arrays correspond pretty closely to the respective OpenGL + equivalents. - In general, you'll want to do a GetPrimType() to figure out what primitive - type (PrimType) a given node is holding. It will typically be TriStrips, - TriFans, or Triangles, but all the other types are valid as well. - The next step is to get the vertices via a GetVertices() call and then get - the normals and texture coordinates (via GetNormals() and GetTexCoordSet() calls). - To get the material information call GetNumMaterial() (if you can support more - than one texture per polygon) and then GetMaterial() for each material. If you - only support one material/texture per polygon then just do one GetMaterial() all. - There's always guaranteed to be at least one material. + In general, you'll want to do a GetPrimType() to figure out what primitive + type (PrimType) a given node is holding. It will typically be TriStrips, + TriFans, or Triangles, but all the other types are valid as well. + The next step is to get the vertices via a GetVertices() call and then get + the normals and texture coordinates (via GetNormals() and GetTexCoordSet() calls). + To get the material information call GetNumMaterial() (if you can support more + than one texture per polygon) and then GetMaterial() for each material. If you + only support one material/texture per polygon then just do one GetMaterial() all. + There's always guaranteed to be at least one material. - It's a good idea to review the OpenGL specification for triangle arrays and - such before diving into this structure. - {group:Read/Write Classes} - */ + It's a good idea to review the OpenGL specification for triangle arrays and + such before diving into this structure. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgGeometry : public trpgReadWriteable { public: - trpgGeometry(void); - ~trpgGeometry(void); - typedef enum {Points,LineStrips,LineLoops,Lines,Polygons,TriStrips, - TriFans,Triangles,QuadStrips,Quads} PrimType; - // Set the primitive type for the geometry node - void SetPrimType(PrimType type); - /* Some primitive types require lengths. These include TriStrips and - TriFans, but not Triangles, for example. */ - void SetPrimLengths(int,const int *); - /* Add a primitive length on to the end of the current primLength array. - Use this if you're adding geometry one vertex at a time. - */ - void AddPrimLength(int); - /* This just increments the number of primitives in the structure. Use this - if you're adding geometry one vertex at a time for a Triangle array, for example. - */ - void AddPrim(); - /* Set the total number of primitives. You would use this only when the PrimType - does not require primitive lengths (e.g. Triangles, but not TriStrips). Use - SetPrimLengths() or AddPrimLength() in that case. - */ - void SetNumPrims(int); // Only when there are no primitive lengths - /* This function sets the total number of materials applied to this group - of geometry. If you're only using one material, trpgGeometry defaults to - 1, so you can just do a SetMaterial() and ignore this. - */ - void SetNumMaterial(int); - /* Set the given material instance (in this trpgGeometry node) to the given - material ID. The material ID is an index into a trpgMatTable. You would - need to do a SetNumMaterial() call first, before any number of SetMaterial() - calls if there is more than one material. If there is only one material, - you can do a single SetMaterial(0,MatID) call. - */ - void SetMaterial(int which,int matID); - /* This is the same as repeated SetMaterial() calls. - */ - void SetMaterials(int32 numMat,const int32 *matIDs); - /* This adds the given material ID to the end of the material list. - You can use this instead of SetNumMaterial() and SetMaterial(). - */ - int AddMaterial(int matID); + trpgGeometry(void); + ~trpgGeometry(void); + typedef enum {Points,LineStrips,LineLoops,Lines,Polygons,TriStrips, + TriFans,Triangles,QuadStrips,Quads} PrimType; + // Set the primitive type for the geometry node + void SetPrimType(PrimType type); + /* Some primitive types require lengths. These include TriStrips and + TriFans, but not Triangles, for example. */ + void SetPrimLengths(int,const int *); + /* Add a primitive length on to the end of the current primLength array. + Use this if you're adding geometry one vertex at a time. + */ + void AddPrimLength(int); + /* This just increments the number of primitives in the structure. Use this + if you're adding geometry one vertex at a time for a Triangle array, for example. + */ + void AddPrim(void); + /* Set the total number of primitives. You would use this only when the PrimType + does not require primitive lengths (e.g. Triangles, but not TriStrips). Use + SetPrimLengths() or AddPrimLength() in that case. + */ + void SetNumPrims(int); // Only when there are no primitive lengths + /* This function sets the total number of materials applied to this group + of geometry. If you're only using one material, trpgGeometry defaults to + 1, so you can just do a SetMaterial() and ignore this. + */ + void SetNumMaterial(int); + /* Set the given material instance (in this trpgGeometry node) to the given + material ID. The material ID is an index into a trpgMatTable. You would + need to do a SetNumMaterial() call first, before any number of SetMaterial() + calls if there is more than one material. If there is only one material, + you can do a single SetMaterial(0,MatID) call. + Negative materials IDs denote local material definitions (e.g. parts of + a larger, paged image). They will always be returned as positive by + GetMaterial, however you must set them as negative so that GetMaterial + can set its isLocal bit on return. + */ + void SetMaterial(int which,int matID,bool isLocal=false); + /* This is the same as repeated SetMaterial() calls. + */ + void SetMaterials(int32 numMat,const int32 *matIDs); + /* This adds the given material ID to the end of the material list. + You can use this instead of SetNumMaterial() and SetMaterial(). + */ + int AddMaterial(int matID); - // These are primitive types used within the trpgGeometry structure. - enum {VertexFloat,VertexDouble,NormalFloat,NormalDouble, - Color,TextureFloat,TextureDouble,EdgeFlag}; + // These are primitive types used within the trpgGeometry structure. + enum {VertexFloat,VertexDouble,NormalFloat,NormalDouble, + Color,TextureFloat,TextureDouble,EdgeFlag}; - /* Used to tell some of the trpgGeometry methods what kind of - data they're getting */ - typedef enum {FloatData,DoubleData} DataType; + /* Used to tell some of the trpgGeometry methods what kind of + data they're getting */ + typedef enum {FloatData,DoubleData} DataType; - /* The SetVertices() methods will set either 32 or 64 bit floating - point vertex arrays within the trpgGeometry structure. - The num passed in is the number of vertices, not the number of individual - floats or doubles (as with GetNumVertex). - */ - void SetVertices(int num,const float32 *); - void SetVertices(int num,const float64 *); - /* This method will add a vertex to the end of the appropriate data array - (either float or double, but never both). You would use this method - if you were building up a trpgGeometry structure vertex by vertex. - */ - void AddVertex(DataType type,trpg3dPoint &); - /* Binding type used by colors, normals, and textures (just PerPrim). - */ - typedef enum {Overall,PerPrim,PerVertex} BindType; - /* The SetNormals() methods will set either the 32 or 64 bit floating - point normal arrays within the trpgGeometry structure. - The num of normals is determined by the bind type. You should - either set the 32 or 64 bit floating point arrays, but not both. - num is the number of individual normals, not float values, unlike - the GetNumNormal() call. - */ - void SetNormals(int num,BindType bind,const float32 *); - void SetNormals(int num,BindType bind,const float64 *); - /* This method is used to add normals one by one of the given type. - You would use this if you were adding geometry one vertex at a time - in conjuntion with AddVertex(). - */ - void AddNormal(DataType type,trpg3dPoint &); - /* This constant is used to select the type of a color array - passed to SetColors(). - */ - typedef enum {Ambient,Diffuse,Specular,Emission} ColorType; - /* This method sets an array of color structures for a trpgGeometry node. - The num should correspond to the bind type. You can set as many of - these color arrays as you like, they're simply stored in an array for - later use. - */ - void SetColors(int num,ColorType type,BindType bind,const trpgColor *); - /* The SetTexCoords() methods set a list of texture coordinates. This - essentially builds a trpgTexData class and pushes it onto the current - list of texture coordinate sets. Choose the appropriate method based - on 32 or 64 bit floating point values. num should be the number of - texture coordinates, not the number of floats passed in. + /* The SetVertices() methods will set either 32 or 64 bit floating + point vertex arrays within the trpgGeometry structure. + The num passed in is the number of vertices, not the number of individual + floats or doubles (as with GetNumVertex). + */ + void SetVertices(int num,const float32 *); + void SetVertices(int num,const float64 *); + /* This method will add a vertex to the end of the appropriate data array + (either float or double, but never both). You would use this method + if you were building up a trpgGeometry structure vertex by vertex. + */ + void AddVertex(DataType type,trpg3dPoint &); + /* Binding type used by colors, normals, and textures (just PerPrim). + */ + typedef enum {Overall,PerPrim,PerVertex} BindType; + /* The SetNormals() methods will set either the 32 or 64 bit floating + point normal arrays within the trpgGeometry structure. + The num of normals is determined by the bind type. You should + either set the 32 or 64 bit floating point arrays, but not both. + num is the number of individual normals, not float values, unlike + the GetNumNormal() call. + */ + void SetNormals(int num,BindType bind,const float32 *); + void SetNormals(int num,BindType bind,const float64 *); + /* This method is used to add normals one by one of the given type. + You would use this if you were adding geometry one vertex at a time + in conjuntion with AddVertex(). + */ + void AddNormal(DataType type,trpg3dPoint &); + /* This constant is used to select the type of a color array + passed to SetColors(). + */ + typedef enum {Ambient,Diffuse,Specular,Emission} ColorType; + /* This method sets an array of color structures for a trpgGeometry node. + The num should correspond to the bind type. You can set as many of + these color arrays as you like, they're simply stored in an array for + later use. + */ + void SetColors(int num,ColorType type,BindType bind,const trpgColor *); + /* The SetTexCoords() methods set a list of texture coordinates. This + essentially builds a trpgTexData class and pushes it onto the current + list of texture coordinate sets. Choose the appropriate method based + on 32 or 64 bit floating point values. num should be the number of + texture coordinates, not the number of floats passed in. - bind should be PerPrim in all cases. - */ - void SetTexCoords(int num,BindType bind,const float32 *); - void SetTexCoords(int num,BindType bind,const float64 *); - /* This is the same as SetTexCoords(0,bind,NULL) */ - void AddTexCoords(BindType bind); - /* This method adds a texture coordinate to array 0. You would use - this if you were adding vertices one at a time. - */ - void AddTexCoord(DataType type,trpg2dPoint &); - /* Edge flags are used by some primitives in OpenGL. We don't typically - use them, but they can be read and written with TerraPage. - */ - void SetEdgeFlags(int num,const char *); + bind should be PerPrim in all cases. + */ + void SetTexCoords(int num,BindType bind,const float32 *); + void SetTexCoords(int num,BindType bind,const float64 *); + /* This is the same as SetTexCoords(0,bind,NULL) */ + void AddTexCoords(BindType bind); + /* This method adds a texture coordinate to array 0. You would use + this if you were adding vertices one at a time. + */ + void AddTexCoord(DataType type,trpg2dPoint &); + /* Edge flags are used by some primitives in OpenGL. We don't typically + use them, but they can be read and written with TerraPage. + */ + void SetEdgeFlags(int num,const char *); - /* Returns the primitive type for this trpgGeometry structure. - */ - bool GetPrimType(PrimType &type) const; - /* Number of primitives in this structure. Primitives are things - like a single triangle, a triangle strip or fan. Some primitives - require a primitive length array. - */ - bool GetNumPrims(int &num) const; - /* This returns the primitive length array. Some primitive types, like - TriStrips or TriFans (but not Triangles) require a primitive length - array to tell you how to break up the vertex/normal/texture/color - arrays into individual primitives. The array you pass in must be - of a certain length (returned by GetNumPrims()) and will only be - valid for some primitive types. - */ - bool GetPrimLengths(int *lenArray) const; - /* TerraPage supports multiple materials per geometry set. This method - tells you how many are applied to this structure. There will always - be at least one. - */ - bool GetNumMaterial(int &num) const; - /* Returns the material ID for a material instance. num is the - nth material instance. matId is an index into a trpgMatTable. - */ - bool GetMaterial(int num,int32 &matID) const; - /* This returns 3 * num_vertex. The function returns the length - of the vertex array, which is, unfortunately, 3 times the number - of vertices. This is a bug, but isn't likely to be fixed any time - soon. For now, just divide this number by 3. - */ - bool GetNumVertex(int &num) const; - /* The GetVertices() methods return a list of vertices in the given - form (32 or 64 bit floating point). These functions will convert to - the appropriate format, just ask for the one you need. - The length of the vertex array is determined by GetNumVertex(), which - returns 3* the number of vertices. - */ - bool GetVertices(float32 *) const; - bool GetVertices(float64 *) const; - /* This method lets you get an individual vertex. The number of vertices - can be determined by GetNumVertex()/3. - */ - bool GetVertex(int id,trpg3dPoint &) const; - /* GetNumNormal() returns the number of normals * 3. See GetNumVertex() - for an explanation of why. - */ - bool GetNumNormal(int &num) const; - /* Much, like GetVertices(), these methods will copy the contents of - the normal array into the array passed in. They will convert the - contents to the appropriate format (32 or 64 bit floating point). - The length of the input array can be determined by GetNumNormal(). - */ - bool GetNormals(float32 *) const; - bool GetNormals(float64 *) const; - /* This returns the number of color sets in the trpgGeometry structure. - There can be one color set per ColorType. - */ - bool GetNumColorSets(int &num) const; - /* You pass a trpgColorInfo into this method and it will fill it out + /* Returns the primitive type for this trpgGeometry structure. + */ + bool GetPrimType(PrimType &type) const; + /* Number of primitives in this structure. Primitives are things + like a single triangle, a triangle strip or fan. Some primitives + require a primitive length array. + */ + bool GetNumPrims(int &num) const; + /* This returns the primitive length array. Some primitive types, like + TriStrips or TriFans (but not Triangles) require a primitive length + array to tell you how to break up the vertex/normal/texture/color + arrays into individual primitives. The array you pass in must be + of a certain length (returned by GetNumPrims()) and will only be + valid for some primitive types. + */ + bool GetPrimLengths(int *lenArray) const; + /* TerraPage supports multiple materials per geometry set. This method + tells you how many are applied to this structure. There will always + be at least one. + */ + bool GetNumMaterial(int &num) const; + /* Returns the material ID for a material instance. num is the + nth material instance. matId is an index into a trpgMatTable. + isLocal is true if the given material is local to this tile. + Local materials are only used to page small pieces of a larger image. + */ + bool GetMaterial(int num,int32 &matID,bool &isLocal) const; + /* This returns num_vertex. The function returns the length + of the vertex array dived by 3, which is the total number of + vertices. + */ + bool GetNumVertex(int &num) const; + /* The GetVertices() methods return a list of vertices in the given + form (32 or 64 bit floating point). These functions will convert to + the appropriate format, just ask for the one you need. + The length of the vertex array is determined by GetNumVertex(), which + returns 3* the number of vertices. + */ + bool GetVertices(float32 *) const; + bool GetVertices(float64 *) const; - */ - bool GetColorSet(int id,trpgColorInfo *) const; - bool GetNumTexCoordSets(int &) const; - bool GetTexCoordSet(int id,trpgTexData *) const; - bool GetNumEdgeFlag(int &num) const; - bool GetEdgeFlags(char *) const; + bool GetVertices(osg::Vec3*) const; + /* This method lets you get an individual vertex. The number of vertices + can be determined by GetNumVertex()/3. + */ + bool GetVertex(int id,trpg3dPoint &) const; + /* GetNumNormal() returns the number of normals. See GetNumVertex() + for an explanation of why. + */ + bool GetNumNormal(int &num) const; + /* Much, like GetVertices(), these methods will copy the contents of + the normal array into the array passed in. They will convert the + contents to the appropriate format (32 or 64 bit floating point). + The length of the input array can be determined by GetNumNormal(). + */ + bool GetNormals(float32 *) const; + bool GetNormals(float64 *) const; + bool GetNormals(osg::Vec3*) const; + /* This returns the number of color sets in the trpgGeometry structure. + There can be one color set per ColorType. Color sets are either + per vertex, per primitive, or per geometry unit (i.e. only one) + arrays of color data. + */ + bool GetNumColorSets(int &num) const; + /* This method fills out the trpgColorInfo class that you pass in. + The number of color sets is determined by GetNumColorSets and + the structure you passed can be reused (to save memory). + */ + bool GetColorSet(int id,trpgColorInfo *) const; + /* Returns the number of texture coordinate sets. There could (and + should) be one texture coordinate set per material applied to this + geometry. Tex Coord sets can be retrieved with GetTexCoordSet. + */ + bool GetNumTexCoordSets(int &) const; + /* This method returns the texture coordinate set specified by the given + index. GetNumTexCoordSets determines the total number of texture + coordinate sets. + */ + bool GetTexCoordSet(int id,trpgTexData *) const; + /* Returns the number of edge flags in this geometry node. + Edge flags are used on certain primitive types, but are rather rare. + */ + bool GetNumEdgeFlag(int &num) const; + /* This returns the edge flags for the current set of primitives. + */ + bool GetEdgeFlags(char *) const; - // Returns true if the trpgGeometry structure is valid - bool isValid(void) const; - // Resets the contents back to empty - void Reset(void); + // Returns true if the trpgGeometry structure is valid + bool isValid(void) const; + // Resets the contents back to empty + void Reset(void); - // Write self to a buffer - bool Write(trpgWriteBuffer &); - // Read self from a buffer. Check isValid() afterwards - bool Read(trpgReadBuffer &); + // Write self to a buffer + bool Write(trpgWriteBuffer &); + // Read self from a buffer. Check isValid() afterwards + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; protected: - int primType; - int numPrim; - vector primLength; - vector materials; - vector vertDataFloat; - vector vertDataDouble; - int normBind; - vector normDataFloat; - vector normDataDouble; - vector colors; - vector texData; - vector edgeFlags; + int primType; + int numPrim; + std::vector primLength; + std::vector materials; + std::vector vertDataFloat; + std::vector vertDataDouble; + int normBind; + std::vector normDataFloat; + std::vector normDataDouble; + std::vector colors; + std::vector texData; + std::vector edgeFlags; }; /* This is a standard Group that you might see in any reasonable - scene graph. It holds a number of children. TerraPage isn't - actually a scene graph, it just represents one. That means that there - are no pointers to children here. Instead you'll encounter this group - while reading a terrain tile or model. That tells you to create a group - (or whatever you call it) in your own system and get read to dump child - trees into it. A push will follow this object, then the children (however - deep they may be) then a pop. + scene graph. It holds a number of children. TerraPage isn't + actually a scene graph, it just represents one. That means that there + are no pointers to children here. Instead you'll encounter this group + while reading a terrain tile or model. That tells you to create a group + (or whatever you call it) in your own system and get read to dump child + trees into it. A push will follow this object, then the children (however + deep they may be) then a pop. - All groups have IDs. These IDs are unique among groups and group-like things - (i.e. LODs) and are used to hook trpgAttach geometry into a scene graph hierachy - as you page in higher terrain levels of detail. + All groups have IDs. These IDs are unique among groups and group-like things + (i.e. LODs) and are used to hook trpgAttach geometry into a scene graph hierachy + as you page in higher terrain levels of detail. - If you're doing a TerraPage reader, the group tells you to put together - your generic container in a scene graph and get read for the push/children/pop. - The NumChild field should tell you how many children will follow, but a writer - can easily forget to put it, so be wary. You'll also want to look at the group - ID and build a mapping from that ID (look at the max group ID in trpgHeader) to - your own group structure. A trpgAttach is allowed to page itself into any group. + If you're doing a TerraPage reader, the group tells you to put together + your generic container in a scene graph and get read for the push/children/pop. + The NumChild field should tell you how many children will follow, but a writer + can easily forget to put it, so be wary. You'll also want to look at the group + ID and build a mapping from that ID (look at the max group ID in trpgHeader) to + your own group structure. A trpgAttach is allowed to page itself into any group. - If you're doing a TerraPage writer you'll create one of these, fill out the - numChild hint, the group ID and then write it. You'll then write a Push, then - the children hierarchies (which can be anything) followed by a Pop. You'll want - to keep track of the group ID you assigned in case one of the children is a - pageable chunk of terrain hierarchy. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer you'll create one of these, fill out the + numChild hint, the group ID and then write it. You'll then write a Push, then + the children hierarchies (which can be anything) followed by a Pop. You'll want + to keep track of the group ID you assigned in case one of the children is a + pageable chunk of terrain hierarchy. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgGroup : public trpgReadWriteable { public: - trpgGroup(void); - ~trpgGroup(void); - // Resets the contents back to empty - virtual void Reset(void); + trpgGroup(void); + virtual ~trpgGroup(void); + // Resets the contents back to empty + virtual void Reset(void); - /* Set the total number of children this group will have */ - virtual void SetNumChild(int); - // Starting from 0, increments the number of children - virtual int AddChild(void); - /* The writer is supposed to set this value to the number of - children. */ - virtual bool GetNumChild(int &) const; + /* Set the total number of children this group will have */ + virtual void SetNumChild(int); + // Starting from 0, increments the number of children + virtual int AddChild(void); + /* The writer is supposed to set this value to the number of + children. */ + virtual bool GetNumChild(int &) const; - /* Set the group ID */ - virtual void SetID(int); - // Returns the group ID - virtual bool GetID(int &) const; + /* Set the group ID */ + virtual void SetID(int); + // Returns the group ID + virtual bool GetID(int &) const; - // Validity check - virtual bool isValid(void) const; - // Writes this class to a write buffer - virtual bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + /* Set the group name */ + void SetName(const char* ); + // Returns the group name + const char* GetName(void) const; + + // Validity check + virtual bool isValid(void) const; + // Writes this class to a write buffer + virtual bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; protected: - int id; - int numChild; + int id; + int numChild; + char* name; }; /* Structurally, an attach is just like a trpgGroup. It does everything a group - does, plus a little bit more. The attach node is how TerraPage does terrain - database paging across LODs. + does, plus a little bit more. The attach node is how TerraPage does terrain + database paging across LODs. - In TerraPage we don't enfoced a terrain LOD structure. Let's say you built - your database as a quad-tree. That is, there is one root tile per block, - 4 children, each of which has 4 of its own children etc... That would imply - a certain structure (4 children per tile until you reach the bottom). That would - also lock you into a database scheme (quad-tree). However, let's assume that - someone else wanted to do replacement LOD for their terrain. That scheme works - by having one child per tile. If you want to support both of these then you're - asking the reader to do a lot of thinking and you can pretty much assume that the - one you don't test won't work. We decided to avoid all that by coming up with a - generic scene graph paging scheme. It's a little more painfull, but once you deal - with it you get whatever weird scheme the writer is using for free without having to - think about it. + In TerraPage we don't enfoced a terrain LOD structure. Let's say you built + your database as a quad-tree. That is, there is one root tile per block, + 4 children, each of which has 4 of its own children etc... That would imply + a certain structure (4 children per tile until you reach the bottom). That would + also lock you into a database scheme (quad-tree). However, let's assume that + someone else wanted to do replacement LOD for their terrain. That scheme works + by having one child per tile. If you want to support both of these then you're + asking the reader to do a lot of thinking and you can pretty much assume that the + one you don't test won't work. We decided to avoid all that by coming up with a + generic scene graph paging scheme. It's a little more painfull, but once you deal + with it you get whatever weird scheme the writer is using for free without having to + think about it. - Here's how it works. Each trpgGroup and group-like structure (trpgLod for example) - has a unique group ID. You can have one trpgAttach at the start of a given terrain - tile. That trpgAttach can point to any group within the scene graph (with a group ID). - Level of detail for the terrain is controlled by trpgLod nodes as if everything was - loaded in all the time. That is, you'll see the same thing no matter whether every node - is loaded into memory or just the nearby ones. The theoretical scene graph structure - is the same no matter what. It's the ranges in your trpgHeader that tell you when - things ought to be loaded in, but the actual display logic is contained within the trpgLod - objects. It sounds complicated and it is... for the writer. But for the reader it's - really simple. + Here's how it works. Each trpgGroup and group-like structure (trpgLod for example) + has a unique group ID. You can have one trpgAttach at the start of a given terrain + tile. That trpgAttach can point to any group within the scene graph (with a group ID). + Level of detail for the terrain is controlled by trpgLod nodes as if everything was + loaded in all the time. That is, you'll see the same thing no matter whether every node + is loaded into memory or just the nearby ones. The theoretical scene graph structure + is the same no matter what. It's the ranges in your trpgHeader that tell you when + things ought to be loaded in, but the actual display logic is contained within the trpgLod + objects. It sounds complicated and it is... for the writer. But for the reader it's + really simple. - If you're doing a TerraPage reader all you'll need to do is keep a mapping from group - ID's to your own internal scene graph node representation. Then when a trpgAttach shows - up you can turn it into your own group-like thing and stuff it and its children into - the scene graph. When it wanders out of range (the trpgHeader tells you that for a given - terrain LOD) you simply delete it. If you out-run your paging you've got two options: - (1) Display holes. That's what will happen when the LOD above a given tile trpgAttach - turns on without the children in memory; or (2) Don't switch LODs that don't have all - their children loaded in yet. Be aware that a trpgAttach inherits from trpgGroup and - so can have trpgAttach children. So don't absorb the trpgAttach even though it's extra - hierarchy. Also, don't make any assumptions that there is really terrain in a given - tile. The writer may have chosen to page buildings or trees. You never know and there's - no reason to assume. + If you're doing a TerraPage reader all you'll need to do is keep a mapping from group + ID's to your own internal scene graph node representation. Then when a trpgAttach shows + up you can turn it into your own group-like thing and stuff it and its children into + the scene graph. When it wanders out of range (the trpgHeader tells you that for a given + terrain LOD) you simply delete it. If you out-run your paging you've got two options: + (1) Display holes. That's what will happen when the LOD above a given tile trpgAttach + turns on without the children in memory; or (2) Don't switch LODs that don't have all + their children loaded in yet. Be aware that a trpgAttach inherits from trpgGroup and + so can have trpgAttach children. So don't absorb the trpgAttach even though it's extra + hierarchy. Also, don't make any assumptions that there is really terrain in a given + tile. The writer may have chosen to page buildings or trees. You never know and there's + no reason to assume. - If you're doing a TerraPage writer this is slightly more complex than writing a normal - format, depending on the structure of your internal scene graph. If you don't want - to write more than one pageable terrain LOD you can just ignore trpgAttach nodes. This - doesn't mean you can only have one terrain LOD, it only means they won't be pageable. - If you do want to fully support it, what you'll need to - do is give all your groups (or whatever will become groups) unique IDs, keeping in mind - to update the trpgHeader max group ID as you go. Start at the lowest terrain lod. This - one doesn't need to have a trpgAttach node since it's at the top. Traverse toward - the higher lods. When you hit one, spit out a trpgAttach, giving it the group ID of - the trpgGroup directly above it. Then treat the node you just created as a trpgGroup - (i.e. do its children as normal). You will also need to keep the trpgTileHeader for - each tile around. It's best to index these by (x,y,lod) index. You'll need to build - that tile header up *just for this tile geometry*. That means you have to stop adding - material/model references when you start defining the next tile. Depending on how you - write out your scene graph it may make sense to keep a stack of trpgTileHeader and - trpgMemWriteBuffer objects around indexed by tile (x,y,lod). + If you're doing a TerraPage writer this is slightly more complex than writing a normal + format, depending on the structure of your internal scene graph. If you don't want + to write more than one pageable terrain LOD you can just ignore trpgAttach nodes. This + doesn't mean you can only have one terrain LOD, it only means they won't be pageable. + If you do want to fully support it, what you'll need to + do is give all your groups (or whatever will become groups) unique IDs, keeping in mind + to update the trpgHeader max group ID as you go. Start at the lowest terrain lod. This + one doesn't need to have a trpgAttach node since it's at the top. Traverse toward + the higher lods. When you hit one, spit out a trpgAttach, giving it the group ID of + the trpgGroup directly above it. Then treat the node you just created as a trpgGroup + (i.e. do its children as normal). You will also need to keep the trpgTileHeader for + each tile around. It's best to index these by (x,y,lod) index. You'll need to build + that tile header up *just for this tile geometry*. That means you have to stop adding + material/model references when you start defining the next tile. Depending on how you + write out your scene graph it may make sense to keep a stack of trpgTileHeader and + trpgMemWriteBuffer objects around indexed by tile (x,y,lod). - {group:Read/Write Classes} - */ + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgAttach : public trpgGroup { public: - trpgAttach(void); - ~trpgAttach(void); - // Resets the contents back to empty - void Reset(void); + trpgAttach(void); + ~trpgAttach(void); + // Resets the contents back to empty + void Reset(void); - // Set the parent of the group/LOD/whatever to attach to when loaded in - void SetParentID(int); - // Retrieve the parent ID we'll need to attach this thing into the scene graph - bool GetParentID(int &) const; + // Set the parent of the group/LOD/whatever to attach to when loaded in + void SetParentID(int); + // Retrieve the parent ID we'll need to attach this thing into the scene graph + bool GetParentID(int &) const; - /* The writer is supposed to set this value to a unique position with relation - to its parent group. */ - void SetChildPos(int); - /* The child position is a hint as to which child this is in its parent group. - That is, if there are 3 children, of which this is one, then it could be - at child position 0, 1, or 3 in its parent. You can safely ignore this if - you want to just this node to its parent's list of children. */ - bool GetChildPos(int &) const; + /* The writer is supposed to set this value to a unique position with relation + to its parent group. */ + void SetChildPos(int); + /* The child position is a hint as to which child this is in its parent group. + That is, if there are 3 children, of which this is one, then it could be + at child position 0, 1, or 3 in its parent. You can safely ignore this if + you want to just this node to its parent's list of children. */ + bool GetChildPos(int &) const; - // Validity check - virtual bool isValid(void) const; - // Writes this class to a write buffer - virtual bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + // Validity check + bool isValid(void) const; + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; protected: - int parentID,childPos; + int parentID,childPos; }; /* The billboard inherits from the standard trpgGroup. It tells the reader that - everything underneath this node is supposed to be treated like a stamp or billboard - (depending on your terminology). That means it's supposed to be rotated towards - the eye point in some way. There are no restrictions on the number, depth, or type - of children. In theory you could have another billboard as a child, although we have - no idea what that should look like. + everything underneath this node is supposed to be treated like a stamp or billboard + (depending on your terminology). That means it's supposed to be rotated towards + the eye point in some way. There are no restrictions on the number, depth, or type + of children. In theory you could have another billboard as a child, although we have + no idea what that should look like. - If you're doing a TerraPage reader treat everything underneath this group as rotatable. - Pay attention to the Type in particular. There's a shorthand for rotating a bunch - of objects that is a little confusing. + If you're doing a TerraPage reader treat everything underneath this group as rotatable. + Pay attention to the Type in particular. There's a shorthand for rotating a bunch + of objects that is a little confusing. - If you're doing a TerraPage write this is pretty simple. For the standard tree example - use one of these with one or more trpgGeometry children. - {group:Read/Write Classes} - */ + If you're doing a TerraPage write this is pretty simple. For the standard tree example + use one of these with one or more trpgGeometry children. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgBillboard : public trpgGroup { public: - trpgBillboard(void); - ~trpgBillboard(void); - enum {Individual,Group}; - // Set the type. See GetType for details. - void SetType(int); - // Set the center. - void SetCenter(const trpg3dPoint &); - enum {Axial,World,Eye}; - // Set the rotation mode. - void SetMode(int); - // Set the rotation axis if mode == Axial - void SetAxis(const trpg3dPoint &); + trpgBillboard(void); + ~trpgBillboard(void); + enum {Individual,Group}; + // Set the type. See GetType for details. + void SetType(int); + // Set the center. + void SetCenter(const trpg3dPoint &); + enum {Axial,World,Eye}; + // Set the rotation mode. + void SetMode(int); + // Set the rotation axis if mode == Axial + void SetAxis(const trpg3dPoint &); - /* The type controls how the billboard node relates to its children. There - are two modes: (1) Group - This is the obvious one. Everything below - this node rotates around the center in the way specified by GetMode. (2) Individual - This - is a little weirder. Basically, it's here for trees. It's assumed that - there will be one or more trpgGeometry nodes below this node. Each single - primitive is supposed to rotate "seperately". That is, you must take into - account the unique center of each one and rotate it around that. If you have - some optimization scheme where you can deal with groups of billboards (ala Performer) - it is valid to do so in the Individual case. */ - bool GetType(int &) const; - /* Center of the thing to be rotated. For Group this does the obvious thing. - For Individual it should be the center of the group of things you want to rotate. - This has no use if you're going to rotate each primitive seperately, but if you've - got some sort of optimized scheme for doing so (ala Performer) this information is useful. - */ - bool GetCenter(trpg3dPoint &) const; - /* The mode will be one of: (1) Axial - rotate around the Axis. This is the normal - one for tree. (2) Eye - Always rotate toward the eye point. (3) world. - */ - bool GetMode(int &) const; - /* The axis used when GetMode returns Axial. */ - bool GetAxis(trpg3dPoint &) const; + /* The type controls how the billboard node relates to its children. There + are two modes: (1) Group - This is the obvious one. Everything below + this node rotates around the center in the way specified by GetMode. (2) Individual - This + is a little weirder. Basically, it's here for trees. It's assumed that + there will be one or more trpgGeometry nodes below this node. Each single + primitive is supposed to rotate "seperately". That is, you must take into + account the unique center of each one and rotate it around that. If you have + some optimization scheme where you can deal with groups of billboards (ala Performer) + it is valid to do so in the Individual case. */ + bool GetType(int &) const; + /* Center of the thing to be rotated. For Group this does the obvious thing. + For Individual it should be the center of the group of things you want to rotate. + This has no use if you're going to rotate each primitive seperately, but if you've + got some sort of optimized scheme for doing so (ala Performer) this information is useful. + */ + bool GetCenter(trpg3dPoint &) const; + /* The mode will be one of: (1) Axial - rotate around the Axis. This is the normal + one for tree. (2) Eye - Always rotate toward the eye point. (3) world. + */ + bool GetMode(int &) const; + /* The axis used when GetMode returns Axial. */ + bool GetAxis(trpg3dPoint &) const; - // Resets the contents back to empty - void Reset(void); + // Resets the contents back to empty + void Reset(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; protected: - int type; - int mode; - trpg3dPoint center; - trpg3dPoint axis; + int type; + int mode; + trpg3dPoint center; + trpg3dPoint axis; }; /* TerraPage level of detail nodes are pretty simple. Even though they don't inherit from trpgGroup, - they have many of the same calls and act, structurally at least, in much the same way. These - act as a switch. When the user's eye point is within a distance then the children of this - node should be turned on for display. Otherwise, the children will be invisible. + they have many of the same calls and act, structurally at least, in much the same way. These + act as a switch. When the user's eye point is within a distance then the children of this + node should be turned on for display. Otherwise, the children will be invisible. A simple on/off test for a TerraPage lod might look like this: - If ( in < dist < out || out < dist < in) then + If ( in < dist < out || out < dist < in) then Turn children on else Turn children off. - There is also a transition width can be used to fade LODs in and out around - the transition zones. Keep in mind that these LODs are binary. Children - are either on or off (in the process of being turned off). The position of - a child doesn't have any special meaning with respect to range. + There is also a transition width can be used to fade LODs in and out around + the transition zones. Keep in mind that these LODs are binary. Children + are either on or off (in the process of being turned off). The position of + a child doesn't have any special meaning with respect to range. - If you're doing a TerraPage reader you'll need to turn this into your own LOD - structure. Keep in mind that trpgAttach nodes can and do attach to trpgLod - nodes. If you have a general purpose LOD in your scene graph this should be - pretty easy. However, you must have implemented the concept of LOD center and - you definitely should *not* recalculate the LOD center yourself based on the - center of child geometry. They may not be the same. In fact, many terrain - LOD schemes depend on them not being the same. + If you're doing a TerraPage reader you'll need to turn this into your own LOD + structure. Keep in mind that trpgAttach nodes can and do attach to trpgLod + nodes. If you have a general purpose LOD in your scene graph this should be + pretty easy. However, you must have implemented the concept of LOD center and + you definitely should *not* recalculate the LOD center yourself based on the + center of child geometry. They may not be the same. In fact, many terrain + LOD schemes depend on them not being the same. - If you're doing a TerraPage writer you'll need to use these both for geometry - that you want to disappear at certain distances (e.g. trees, houses, etc..), but - also terrain. Any terrain LOD scheme you implement must use these to drop out - polygons in the distance. You'll need to set the center and in/out/width info. - Otherwise it's like a group. + If you're doing a TerraPage writer you'll need to use these both for geometry + that you want to disappear at certain distances (e.g. trees, houses, etc..), but + also terrain. Any terrain LOD scheme you implement must use these to drop out + polygons in the distance. You'll need to set the center and in/out/width info. + Otherwise it's like a group. - {group:Read/Write Classes} - */ + In TerraPage 2.0 we added the Range Index field. This field is here to help + run-time systems gracefully degrade visual fidelity. The trpgLod node still acts + like a normal LOD and you can safely ignore the range index field. If, however, + you want to use it, please read the documention on the trpgRangeTable for further + information. + + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgLod : public trpgReadWriteable { public: - trpgLod(void); - ~trpgLod(void); - // Set the calculated center - void SetCenter(const trpg3dPoint &); - // Set the number of children hint - void SetNumChild(int); - // Set the LOD information - void SetLOD(double in,double out,double width); + trpgLod(void); + ~trpgLod(void); + // Set the calculated center + void SetCenter(const trpg3dPoint &); + // Set the number of children hint + void SetNumChild(int); + // Set the LOD information + void SetLOD(double in,double out,double width); - // Center of this LOD. Distance from the viewer is calculated from this. - bool GetCenter(trpg3dPoint &) const; - // Number of children hint. - bool GetNumChild(int &) const; - // LOD specific information. in and out can be switched. width is - // the transition range for doing fading. - bool GetLOD(double &in,double &out,double &width) const; + // Center of this LOD. Distance from the viewer is calculated from this. + bool GetCenter(trpg3dPoint &) const; + // Number of children hint. + bool GetNumChild(int &) const; + // LOD specific information. in and out can be switched. width is + // the transition range for doing fading. + bool GetLOD(double &in,double &out,double &width) const; - // Set the group ID - virtual void SetID(int); + // Set the group ID + void SetID(int); - // Group IDs are used here the same way as in trpgGroup - virtual bool GetID(int &) const; + // Group IDs are used here the same way as in trpgGroup + bool GetID(int &) const; - // Resets the contents back to empty - void Reset(void); + /* Set the lod name */ + void SetName(const char* ); + // Returns the lod name + const char* GetName(void) const; + + // Set the range Index + void SetRangeIndex(int ri); + // Get the range index + bool GetRangeIndex(int &ri) const; + + // Resets the contents back to empty + void Reset(void); + + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); protected: - int numRange; - double switchIn,switchOut,width; - trpg3dPoint center; - int id; + int numRange; + double switchIn,switchOut,width; + trpg3dPoint center; + int id; + char* name; + int rangeIndex; }; /* Layers are used to draw subface geometry. That is, geometry that is - coplanar. This object should be treated just like a group otherwise. - Its existence implies the layering effect. There is no other associated - information. + coplanar. This object should be treated just like a group otherwise. + Its existence implies the layering effect. There is no other associated + information. - If you're doing a TerraPage reader you should assume that each child, - starting at 0 should be draw one after the other using whatever subfacing - scheme you support. There are no restrictions on what the children may - be, but we strongly recommend that writers keep this simple. Keep in - mind that trpgAttach nodes can legally appear as children. If you can pull - it off this has a rather nice effect (think strips on runways). If not, - don't sweat it. + If you're doing a TerraPage reader you should assume that each child, + starting at 0 should be draw one after the other using whatever subfacing + scheme you support. There are no restrictions on what the children may + be, but we strongly recommend that writers keep this simple. Keep in + mind that trpgAttach nodes can legally appear as children. If you can pull + it off this has a rather nice effect (think strips on runways). If not, + don't sweat it. - If you're doing a TerraPage writer, this is fairly simple. Obey the ordering - contraints and try to keep this simple. Ideally that would mean just a few - trpgGeometry nodes below this node. Also keep in mind that layering works - very poorly on most OpenGL systems. - {group:Read/Write Classes} - */ + If you're doing a TerraPage writer, this is fairly simple. Obey the ordering + contraints and try to keep this simple. Ideally that would mean just a few + trpgGeometry nodes below this node. Also keep in mind that layering works + very poorly on most OpenGL systems. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgLayer : public trpgGroup { public: - trpgLayer(void); - ~trpgLayer(void); - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); - // Resets the contents back to empty - void Reset(void); + trpgLayer(void); + ~trpgLayer(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Resets the contents back to empty + void Reset(void); protected: }; /* This is pretty much a standard 4x4 static transform. It has a matrix - which controls where its children wind up in 3D. Otherwise it acts just - like a trpgGroup. - {group:Read/Write Classes} - */ + which controls where its children wind up in 3D. Otherwise it acts just + like a trpgGroup. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgTransform : public trpgGroup { public: - trpgTransform(void); - ~trpgTransform(void); + trpgTransform(void); + ~trpgTransform(void); - // Set the 4x4 matrix - void SetMatrix(const float64 *); + // Set the 4x4 matrix + void SetMatrix(const float64 *); - // Get the 4x4 matrix - bool GetMatrix(float64 *) const; + // Get the 4x4 matrix + bool GetMatrix(float64 *) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); - // Resets the contents back to empty - void Reset(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Resets the contents back to empty + void Reset(void); protected: - float64 m[4][4]; + float64 m[4][4]; }; /* TerraPage treats model references pretty much like instances. Models - are organized centrally in a trpgModelTable. This class simply points - into there with a model ID. There is also a 4x4 matrix (ala trpgTransform) - which moves the model to its final location. + are organized centrally in a trpgModelTable. This class simply points + into there with a model ID. There is also a 4x4 matrix (ala trpgTransform) + which moves the model to its final location. - If you're doing a TerraPage reader you should already have dealt with the - trpgModelTable by this point. Presumably you've got a mapping from model IDs - to small scene graphs in your own representation. This can be treated just like - an instance into one of those. + If you're doing a TerraPage reader you should already have dealt with the + trpgModelTable by this point. Presumably you've got a mapping from model IDs + to small scene graphs in your own representation. This can be treated just like + an instance into one of those. - If you're doing a TerraPage writer this is pretty simple. When you encounter - a model (external reference) add it to your trpgModelTable and stuff the resulting - model ID into one of these. Stick that trpgModelRef into your tile data stream. - You'll need to fill out the matrix to scale/translate/rotate it as well. - The model is assumed to be spatially within the tile it's written into. That isn't - enforced, though. + If you're doing a TerraPage writer this is pretty simple. When you encounter + a model (external reference) add it to your trpgModelTable and stuff the resulting + model ID into one of these. Stick that trpgModelRef into your tile data stream. + You'll need to fill out the matrix to scale/translate/rotate it as well. + The model is assumed to be spatially within the tile it's written into. That isn't + enforced, though. - {group:Read/Write Classes} - */ + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgModelRef : public trpgReadWriteable { public: - trpgModelRef(void); - ~trpgModelRef(void); - // Set the model ID. Must come from a trpgModelTable - void SetModel(int); - // Set the 4x4 rotate/translate/scale matrix - void SetMatrix(const float64 *); + trpgModelRef(void); + ~trpgModelRef(void); + // Set the model ID. Must come from a trpgModelTable + void SetModel(int); + // Set the 4x4 rotate/translate/scale matrix + void SetMatrix(const float64 *); - // Model ID pointing into a trpgModelTable - bool GetModel(int32 &) const; - // Positional matrix. Works just like a trpgTransform. - bool GetMatrix(float64 *) const; + // Model ID pointing into a trpgModelTable + bool GetModel(int32 &) const; + // Positional matrix. Works just like a trpgTransform. + bool GetMatrix(float64 *) const; - // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); - // Reads this class from a read buffer - bool Read(trpgReadBuffer &); - // Resets the contents back to empty - void Reset(void); + // Writes this class to a write buffer + bool Write(trpgWriteBuffer &); + // Reads this class from a read buffer + bool Read(trpgReadBuffer &); + // Prints this class to a print buffer + bool Print(trpgPrintBuffer &) const; + + // Resets the contents back to empty + void Reset(void); protected: - int modelRef; - float64 m[4][4]; + int modelRef; + float64 m[4][4]; }; #endif diff --git a/src/osgPlugins/txp/trpage_header.cpp b/src/osgPlugins/txp/trpage_header.cpp index b2f927390..2f63f1568 100644 --- a/src/osgPlugins/txp/trpage_header.cpp +++ b/src/osgPlugins/txp/trpage_header.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,22 +18,22 @@ #include /* 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() { @@ -43,143 +42,143 @@ trpgHeader::~trpgHeader() // Validity check bool trpgHeader::isValid() const { - if (numLods <= 0) - return false; - if (sw.x == ne.x && sw.y == ne.y) - return false; + if (numLods <= 0) + return false; + if (sw.x == ne.x && sw.y == ne.y) + 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; } // 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 || (unsigned int)id >= tileSize.size()) return; - tileSize[id] = pt; + if (id < 0 || id >= tileSize.size()) return; + tileSize[id] = pt; } void trpgHeader::SetOrigin(const trpg3dPoint &pt) { - origin = pt; + origin = pt; } void trpgHeader::SetExtents(const trpg2dPoint &in_sw,const trpg2dPoint &in_ne) { - sw = in_sw; - ne = in_ne; + sw = in_sw; + ne = in_ne; } void trpgHeader::SetTileOriginType(trpgTileType type) { - tileType = type; + tileType = type; } void trpgHeader::SetNumLods(int no) { - if (no < 0) return; - numLods = no; + if (no < 0) return; + numLods = no; - lodSizes.resize(no); - lodRanges.resize(no); + lodSizes.resize(no); + lodRanges.resize(no); } void trpgHeader::SetLodSize(int no,const trpg2iPoint &pt) { - if (no < 0 || no >= numLods) - return; + if (no < 0 || no >= numLods) + return; - lodSizes[no] = pt; + lodSizes[no] = pt; } void trpgHeader::SetLodSize(const trpg2iPoint *pt) { - for (int i=0;i= numLods) - return; + if (no < 0 || no >= numLods) + return; - lodRanges[no] = r; + lodRanges[no] = r; } void trpgHeader::SetLodRange(const float64 *r) { - for (int i=0;i= tileSize.size()) return false; - pt = tileSize[id]; - return true; + if (!isValid()) return false; + if (id < 0 || id >= tileSize.size()) return false; + pt = tileSize[id]; + return true; } bool trpgHeader::GetOrigin(trpg3dPoint &pt) const { - if (!isValid()) return false; - pt = origin; - return true; + if (!isValid()) return false; + pt = origin; + return true; } bool trpgHeader::GetTileOriginType(trpgTileType &type) const { - if (!isValid()) return false; - type = tileType; - return true; + if (!isValid()) return false; + type = tileType; + return true; } bool trpgHeader::GetNumLods(int32 &no) const { - if (!isValid()) return false; - no = numLods; - return true; + if (!isValid()) return false; + no = numLods; + return true; } bool trpgHeader::GetLodSize(int32 id,trpg2iPoint &pt) const { - if (!isValid() || (id < 0 || id >= numLods)) return false; - pt = lodSizes[id]; - return true; + if (!isValid() || (id < 0 || id >= numLods)) return false; + pt = lodSizes[id]; + return true; } bool trpgHeader::GetLodRange(int32 id,float64 &range) const { - if (!isValid() || (id < 0 || id >= numLods)) return false; - range = lodRanges[id]; - return true; + if (!isValid() || (id < 0 || id >= numLods)) return false; + range = lodRanges[id]; + return true; } bool trpgHeader::GetExtents(trpg2dPoint &osw,trpg2dPoint &one) const { - if (!isValid()) return false; - osw = sw; - one = ne; - return true; + if (!isValid()) return false; + osw = sw; + one = ne; + return true; } bool trpgHeader::GetMaxGroupID(int &id) const { - id = maxGroupID; - return true; + id = maxGroupID; + return true; } // Read in the header bool trpgHeader::Read(trpgReadBuffer &buf) { - uint8 i8; - trpgToken tok; - bool status; - int32 len; + uint8 i8; + trpgToken tok; + bool status; + int32 len; - try { - buf.Get(verMajor); - buf.Get(verMinor); - buf.Get(dbVerMajor); - buf.Get(dbVerMinor); - buf.Get(origin); - buf.Get(sw); - buf.Get(ne); - buf.Get(i8); tileType = (trpgTileType)i8; - buf.Get(numLods); - if (numLods < 0) throw 1; + try { + buf.Get(verMajor); + buf.Get(verMinor); + buf.Get(dbVerMajor); + buf.Get(dbVerMinor); + buf.Get(origin); + buf.Get(sw); + buf.Get(ne); + buf.Get(i8); tileType = (trpgTileType)i8; + buf.Get(numLods); + if (numLods < 0) throw 1; - // Read in the LOD range info - buf.GetToken(tok,len); - if (tok != TRPGHEAD_LODINFO) throw 1; - buf.PushLimit(len); - status = ReadLodInfo(buf); - buf.PopLimit(); - if (!status) throw 1; + // Read in the LOD range info + buf.GetToken(tok,len); + if (tok != TRPGHEAD_LODINFO) throw 1; + buf.PushLimit(len); + status = ReadLodInfo(buf); + buf.PopLimit(); + if (!status) throw 1; - // Added after the first version - 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 lengths; + virtual void append(unsigned int,const char *); + virtual void set(unsigned int pos,unsigned int len,const char *); + int curLen; + int totLen; + char *data; + std::vector lengths; }; /* This is a virtual base class for reading data from a device. - The device implementation is left as an excercise to the sub class. - This class contains methods for getting data that must be filled in - as well as helper methods that call those. - {group:Low Level I/O} - */ + The device implementation is left as an excercise to the sub class. + This class contains methods for getting data that must be filled in + as well as helper methods that call those. + {group:Low Level I/O} + */ TX_EXDECL class TX_CLDECL trpgReadBuffer { public: - virtual ~trpgReadBuffer(void) { }; - /* The Get methods are utility routines that all call the GetData method. - Only that method need be filled in by a subclass. */ - virtual bool Get(int32 &); - virtual bool Get(int64 &); - virtual bool Get(char *,int); - virtual bool Get(float32 &); - virtual bool Get(float64 &); + virtual ~trpgReadBuffer(void) { }; + /* The Get methods are utility routines that all call the GetData method. + Only that method need be filled in by a subclass. */ + virtual bool Get(int32 &); + virtual bool Get(int64 &); + virtual bool Get(char *,int); + virtual bool Get(float32 &); + virtual bool Get(float64 &); #if (bool != int32) - virtual bool Get(bool &); + virtual bool Get(bool &); #endif - virtual bool Get(uint8 &); + virtual bool Get(uint8 &); #if (trpgDiskRef != int64) - virtual bool Get(trpgDiskRef &); + virtual bool Get(trpgDiskRef &); #endif - virtual bool Get(trpgToken &); + virtual bool Get(trpgToken &); - /* These methods return references to arrays of data of the given types. - These are all utility routines and depend upon GetDataRef. */ - virtual bool GetArray(int,float32 **); - virtual bool GetArray(int,float64 **); - virtual bool GetArray(int,int32 **); - virtual bool GetArray(int,trpgColor **); - virtual bool GetArray(int,char **); + /* These methods return references to arrays of data of the given types. + These are all utility routines and depend upon GetDataRef. */ + virtual bool GetArray(int,float32 **); + virtual bool GetArray(int,float64 **); + virtual bool GetArray(int,int32 **); + virtual bool GetArray(int,trpgColor **); + virtual bool GetArray(int,char **); - virtual bool Get(trpg2iPoint &); - virtual bool Get(trpg2dPoint &); - virtual bool Get(trpg3dPoint &); - virtual bool Get(trpgColor &); - virtual bool GetToken(trpgToken &,int32 &); + virtual bool Get(trpg2iPoint &); + virtual bool Get(trpg2dPoint &); + virtual bool Get(trpg3dPoint &); + virtual bool Get(trpgColor &); + virtual bool GetToken(trpgToken &,int32 &); - /* Force the buffer to only allow the next N bytes to be read. - The limits are stack based. That is, this limit is the current one - until it's popped off the stack. Then it reverts to the previous one. - Any bytes read in the mean time count against all limits. */ - virtual void PushLimit(int); - /* Revert to the limit before this one. Typically this would happen when - a tokenized object has been read. */ - virtual void PopLimit(void); - /* Skip to the end of the current limit. This is done by a parser when - reading a tokenized object from the buffer to make sure that the next - object can be safely read even if the current one wasn't. */ - virtual bool SkipToLimit(void); + /* Force the buffer to only allow the next N bytes to be read. + The limits are stack based. That is, this limit is the current one + until it's popped off the stack. Then it reverts to the previous one. + Any bytes read in the mean time count against all limits. */ + virtual void PushLimit(int); + /* Revert to the limit before this one. Typically this would happen when + a tokenized object has been read. */ + virtual void PopLimit(void); + /* Skip to the end of the current limit. This is done by a parser when + reading a tokenized object from the buffer to make sure that the next + object can be safely read even if the current one wasn't. */ + virtual bool SkipToLimit(void); - // Buffer is empty - virtual bool isEmpty(void) = 0; + // Buffer is empty + virtual bool isEmpty(void) = 0; protected: - trpgEndian ness; // Endianness of the source we're reading - trpgEndian cpuNess; // Endiannees of the CPU - /* Virtual raw data retrieval function that must be implemented by a subclass. - It must return a given number of bytes in the array passed in. */ - virtual bool GetData(char *,int)=0; - /* Virtual raw data reference retrieval function. The difference between - this method and GetData is that this is supposed to return a pointer - to a given amount of bytes. This assumes some sort of memory caching - mechanism in the subclass. */ - virtual bool GetDataRef(char **,int)=0; - /* This virtual method must be filled in by the subclass so that SkipToLimit - will work correctly. */ - virtual bool Skip(int) = 0; - /* A utility function for subclasses to use to see if they would exceed an - outside imposed limit by reading the given number of bytes. */ - virtual bool TestLimit(int); - /* Utility function that must be called after a successfull read to update - the outside imposed read limits. */ - virtual void UpdateLimits(int); - vector limits; + trpgEndian ness; // Endianness of the source we're reading + trpgEndian cpuNess; // Endiannees of the CPU + /* Virtual raw data retrieval function that must be implemented by a subclass. + It must return a given number of bytes in the array passed in. */ + virtual bool GetData(char *,int)=0; + /* Virtual raw data reference retrieval function. The difference between + this method and GetData is that this is supposed to return a pointer + to a given amount of bytes. This assumes some sort of memory caching + mechanism in the subclass. */ + virtual bool GetDataRef(char **,int)=0; + /* This virtual method must be filled in by the subclass so that SkipToLimit + will work correctly. */ + virtual bool Skip(int) = 0; + /* A utility function for subclasses to use to see if they would exceed an + outside imposed limit by reading the given number of bytes. */ + virtual bool TestLimit(int); + /* Utility function that must be called after a successfull read to update + the outside imposed read limits. */ + virtual void UpdateLimits(int); + std::vector limits; }; /* This class implements a read buffer that uses a chunk of memory. - Typically, raw data will be dumped into this class, then it will be - passed to a parser for object based reading. - {group:Low Level I/O} - */ + Typically, raw data will be dumped into this class, then it will be + passed to a parser for object based reading. + {group:Low Level I/O} + */ TX_EXDECL class TX_CLDECL trpgMemReadBuffer : public trpgReadBuffer { public: - // Memory read buffers must be initialized with an endianness - trpgMemReadBuffer(trpgEndian); - ~trpgMemReadBuffer(void); + // Memory read buffers must be initialized with an endianness + trpgMemReadBuffer(trpgEndian); + ~trpgMemReadBuffer(void); // Return true if we're out of data - bool isEmpty(void); - // Sets the size of this read buffer. - void SetLength(int); - /* Return a pointer to the raw data cache for this object. Data will - be dumped straight into here (from disk, for example) and then parsed - by something that takes a trpgReadBuffer as input. */ - char *GetDataPtr(void); + bool isEmpty(void); + // Sets the size of this read buffer. + void SetLength(int); + /* Return a pointer to the raw data cache for this object. Data will + be dumped straight into here (from disk, for example) and then parsed + by something that takes a trpgReadBuffer as input. */ + char *GetDataPtr(void); protected: - bool GetData(char *,int); // Retrieve the given amount of data - bool GetDataRef(char **,int); // Retrieve a pointer to the given array - bool Skip(int); // Skip over the given amount - int len; // Data Length - int totLen; // Total allocated length - int pos; // Current position - char *data; + bool GetData(char *,int); // Retrieve the given amount of data + bool GetDataRef(char **,int); // Retrieve a pointer to the given array + bool Skip(int); // Skip over the given amount + int len; // Data Length + int totLen; // Total allocated length + int pos; // Current position + char *data; }; /* A Checkable is purely a base class used by other classes that - need validity checks associated with them. By default, the - checkable will return false for isValid unless the valid flag is set. - */ + need validity checks associated with them. By default, the + checkable will return false for isValid unless the valid flag is set. + */ TX_EXDECL class TX_CLDECL trpgCheckable { public: - trpgCheckable(void); - virtual ~trpgCheckable(void); - // Returns the state of the valid flag, or can be overriden by a subclass to do a more complex check. - bool isValid(void) const; + trpgCheckable(void); + virtual ~trpgCheckable(void); + // Returns the state of the valid flag, or can be overriden by a subclass to do a more complex check. + bool isValid(void) const; protected: - /* Set this flag to true if your checkable structure doesn't have a complex - check it needs to do. */ - bool valid; + /* Set this flag to true if your checkable structure doesn't have a complex + check it needs to do. */ + bool valid; }; +class trpgPrintBuffer; /* The Read/Writeable is a class that knows how to read itself from a trpgReadBuffer and write itself to a trpgWriteBuffer. This includes all the node and header - data in TerraPage. These classes are intended as marshalling points for reading - and writing data, not as data containers in and of themselves. If you find - yourself keeping a lot of classes derived from trpgReadWriteable around, you're - probably misusing them. + data in TerraPage. These classes are intended as marshalling points for reading + and writing data, not as data containers in and of themselves. If you find + yourself keeping a lot of classes derived from trpgReadWriteable around, you're + probably misusing them. - The classes derived from this one will have a lot of methods that begin with - "Set", "Get", and "Add". These will almost always return a bool value. This - is used to indicate whether the given call succeeded. In the case of "Set" and "Add" calls - this should always work if it possibly can. An out of range index might make it - fail, for example. "Get" calls will always fail if the object you're getting from - is not valid. Be sure to do an isValid check as soon as you've read or filled out - one of these objects. - {group:Read/Write Classes} - */ + The classes derived from this one will have a lot of methods that begin with + "Set", "Get", and "Add". These will almost always return a bool value. This + is used to indicate whether the given call succeeded. In the case of "Set" and "Add" calls + this should always work if it possibly can. An out of range index might make it + fail, for example. "Get" calls will always fail if the object you're getting from + is not valid. Be sure to do an isValid check as soon as you've read or filled out + one of these objects. + {group:Read/Write Classes} + */ TX_EXDECL class TX_CLDECL trpgReadWriteable : public trpgCheckable { public: - /* The Write method is a virtual that must be filled in by the subclass. - It takes a trpgWriteBuffer and should return true on success. */ - virtual bool Write(trpgWriteBuffer &) = 0; - /* The Read method should be overriden by a subclass. It should read - the contents of the given trpgReadBuffer up to the current limit - into itself. It must return true on success. */ - virtual bool Read(trpgReadBuffer &) { return false;}; - /* Every read/writeable must be able to reset itself to a pristine state - so that, for example, multiple objects of the same type can be read into - it, one after the other. */ - virtual void Reset(void) = 0; + /* The Write method is a virtual that must be filled in by the subclass. + It takes a trpgWriteBuffer and should return true on success. */ + virtual bool Write(trpgWriteBuffer &) = 0; + /* The Read method should be overriden by a subclass. It should read + the contents of the given trpgReadBuffer up to the current limit + into itself. It must return true on success. */ + virtual bool Read(trpgReadBuffer &) { return false;}; + /* Every read/writeable must be able to reset itself to a pristine state + so that, for example, multiple objects of the same type can be read into + it, one after the other. */ + virtual void Reset(void) = 0; + /* The print method is optional. If it's not there, it won't do anything. + */ + virtual bool Print(trpgPrintBuffer &) const { return true; } protected: }; +/* Pointer into a trpgwAppFile. The full name of the file + is based on the context (e.g. texture vs. tile) + {group:Archive Writing} + */ +TX_EXDECL class TX_CLDECL trpgwAppAddress { +public: + // Which file + int32 file; + // Offset within the file + // Note: This is not a 64 bit value + int32 offset; +}; + +/* Archive File. + This class represents an appendable file archive used for + consolidating tiles and textures. + {group:Archive Writing} + */ +TX_EXDECL class TX_CLDECL trpgwAppFile { +public: + trpgwAppFile(trpgEndian,const char *); + virtual ~trpgwAppFile(void); + virtual bool Append(const trpgMemWriteBuffer *,const trpgMemWriteBuffer *); + virtual bool Append(const char *,int size); + virtual int64 Pos(void) const; + virtual int GetLengthWritten(); + + bool isValid(void) const; +protected: + bool valid; + trpgEndian ness,cpuNess; + FILE *fp; + int lengthSoFar; +}; + +/* Archive File - Read version. + This class represents an appendable file archive from the + read perspective. This is the same type of file written by + trpgwAppFile. + */ +TX_EXDECL class TX_CLDECL trpgrAppFile { +public: + trpgrAppFile(trpgEndian,const char *); + virtual ~trpgrAppFile(void); + virtual bool Read(trpgMemReadBuffer *,int32 offset); + virtual bool Read(char *data,int32 offset,int32 dataSize); + + bool isValid(void) const; +protected: + bool valid; + trpgEndian ness,cpuNess; + FILE *fp; +}; + +/* Archive File Cache. + This class keeps + */ +TX_EXDECL class TX_CLDECL trpgrAppFileCache { +public: + trpgrAppFileCache(const char *prefix,const char *ext,int noFiles=32); + ~trpgrAppFileCache(void); + trpgrAppFile *GetFile(trpgEndian ness,int id); +protected: + // Prefix name and extension + char baseName[1024],ext[20]; + + class OpenFile { + public: + OpenFile(void); + int id; // ID of open file + trpgrAppFile *afile; + int lastUsed; // When the file was last accessed + }; + + std::vector files; + int timeCount; // Incremented for every access +}; + #endif diff --git a/src/osgPlugins/txp/trpage_material.cpp b/src/osgPlugins/txp/trpage_material.cpp index 150777d18..ff5e64ef5 100644 --- a/src/osgPlugins/txp/trpage_material.cpp +++ b/src/osgPlugins/txp/trpage_material.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,22 +18,22 @@ #include /* trpage_material.cpp - This source file contains the methods for trpgMatTable, trpgTextureEnv, - trpgMaterial, and trpgTexTable. - You should only modify this code if you want to add data to these classes. - */ + This source file contains the methods for trpgMatTable, trpgTextureEnv, + trpgMaterial, and trpgTexTable. + You should only modify this code if you want to add data to these classes. + */ #include "trpage_geom.h" #include "trpage_read.h" /* Write Material Table class - Keeps track of the materials that have been added. - */ + Keeps track of the materials that have been added. + */ // Constructor trpgMatTable::trpgMatTable() { - numTable = numMat = 0; + numTable = numMat = 0; } trpgMatTable::~trpgMatTable() { @@ -43,276 +42,211 @@ trpgMatTable::~trpgMatTable() // Reset function void trpgMatTable::Reset() { - numTable = 0; - numMat = 0; - baseMats.resize(0); - matTables.resize(0); + numTable = 0; + numMat = 0; + matTables.resize(0); } // Validity check bool trpgMatTable::isValid() const { - if (numTable <= 0 || numMat <= 0) - return false; + if (numTable <= 0 || numMat <= 0) + return false; - for (unsigned int i=0;i= numTable) - return; - if (nm < 0 || nm >= numMat) - return; -#ifdef FIX - tables[nt*numMat+nm] = mat; -#endif + if (nt < 0 || nt >= numTable) + return; + if (nm < 0 || nm >= numMat) + return; + + matTables[nt*numMat+nm] = mat; } void trpgMatTable::SetMaterial(int nm,const trpgMaterial &mat) { - if (nm < 0 || nm >= numMat) - return; + if (nm < 0 || nm >= numMat) + return; -#ifdef FIX - for (int i=0;i= baseMats.size()) - baseMats.push_back(cmat); + // Look for a matching base material minus the textures + trpgMaterial cmat = mat; + int baseMat; + for (baseMat = 0;baseMat < matTables.size();baseMat++) { + trpgMaterial &bm = matTables[baseMat]; + // Compare structures + if (CEQ(cmat.color,bm.color) && CEQ(cmat.ambient,bm.ambient) && + CEQ(cmat.diffuse,bm.diffuse) && CEQ(cmat.specular,bm.specular) && + CEQ(cmat.emission,bm.emission) && cmat.shininess == bm.shininess && + cmat.shadeModel == bm.shadeModel && cmat.pointSize == bm.pointSize && + cmat.lineWidth == bm.lineWidth && cmat.cullMode == bm.cullMode && + cmat.alphaFunc == bm.alphaFunc && cmat.alphaRef == bm.alphaRef && + cmat.autoNormal == bm.autoNormal && cmat.texEnvs.size() == bm.texEnvs.size()) { + // Test the texture envs + bool isSame=true; + int i; + for (i=0;i= matTables.size()) { + matTables.push_back(cmat); + numMat++; + } else + // Found it. Just return this ID. + return baseMat; - // Add a short material - trpgShortMaterial smat; - smat.baseMat = baseMat; - smat.texids = mat.texids; - matTables.push_back(smat); - - numMat++; - - return numMat-1; + return numMat-1; } // Write out material table bool trpgMatTable::Write(trpgWriteBuffer &buf) { - int i,j; + int i; - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPGMATTABLE2); + buf.Begin(TRPGMATTABLE); - // Total number of materials - buf.Add((int32)numTable); - buf.Add((int32)numMat); + // Total number of materials + buf.Add((int32)numTable); + buf.Add((int32)numMat); - // Dump the short table in first - // These are small materials. They reference the base materials - buf.Begin(TRPGSHORTMATTABLE); - for (i=0;i= numTable || nm < 0 || nm >= numMat) - return false; - const trpgShortMaterial *smat = &matTables[nt*numMat+nm]; - mat = baseMats[smat->baseMat]; - // Now do the overrides for the short material - mat.texids = smat->texids; - - return true; + if (!isValid()) return false; + if (nt < 0 || nt >= numTable || nm < 0 || nm >= numMat) + return false; + mat = matTables[nt*numMat+nm]; + + return true; } -trpgMaterial *trpgMatTable::GetMaterialRef(int nt,int nm) +const trpgMaterial *trpgMatTable::GetMaterialRef(int nt,int nm) const { - if (nt < 0 || nt >= numTable || nm < 0 || nm >= numMat) - return 0; - GetMaterial(nt,nm,matRef); - return &matRef; + if (nt < 0 || nt >= numTable || nm < 0 || nm >= numMat) + return false; + return const_cast(&matTables[nt*numMat+nm]); } -// This parses both MATTABLE and MATTABLE2 + bool trpgMatTable::Read(trpgReadBuffer &buf) { - trpgMaterial mat; - trpgToken matTok; - int32 len; - bool status; - int i,j,k; + trpgMaterial mat; + trpgToken matTok; + int32 len; + bool status; + int i,j; - 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; + // Read the materials + matTables.resize(numTable*numMat); + for (i=0;iSetEnvMode(envMode); - break; - case TRPGMAT_TXENV_FILTER: - buf.Get(minFilter); - buf.Get(magFilter); - tenv->SetMinFilter(minFilter); - tenv->SetMagFilter(magFilter); - break; - case TRPGMAT_TXENV_WRAP: - buf.Get(wrapS); - buf.Get(wrapT); - tenv->SetWrap(wrapS,wrapT); - break; - case TRPGMAT_TXENV_BORDER: - buf.Get(borderCol); - tenv->SetBorderColor(borderCol); - break; - default: - // Don't know this token. Skip - break; - } - } - catch (...) { - return NULL; - } + try { + switch (tok) { + case TRPGMAT_TXENV_MODE: + buf.Get(envMode); + tenv->SetEnvMode(envMode); + break; + case TRPGMAT_TXENV_FILTER: + buf.Get(minFilter); + buf.Get(magFilter); + tenv->SetMinFilter(minFilter); + tenv->SetMagFilter(magFilter); + break; + case TRPGMAT_TXENV_WRAP: + buf.Get(wrapS); + buf.Get(wrapT); + tenv->SetWrap(wrapS,wrapT); + break; + case TRPGMAT_TXENV_BORDER: + buf.Get(borderCol); + tenv->SetBorderColor(borderCol); + break; + default: + // Don't know this token. Skip + break; + } + } + catch (...) { + return NULL; + } - return tenv; + return tenv; } bool trpgTextureEnv::Read(trpgReadBuffer &buf) { - trpgr_Parser parse; - textureEnvCB teCb; + trpgr_Parser parse; + textureEnvCB teCb; - // Texture environment is a bunch of tokens in random order - // Interface to it with a parser - teCb.tenv = this; - parse.AddCallback(TRPGMAT_TXENV_MODE,&teCb,false); - parse.AddCallback(TRPGMAT_TXENV_FILTER,&teCb,false); - parse.AddCallback(TRPGMAT_TXENV_WRAP,&teCb,false); - parse.AddCallback(TRPGMAT_TXENV_BORDER,&teCb,false); - parse.Parse(buf); + // Texture environment is a bunch of tokens in random order + // Interface to it with a parser + teCb.tenv = this; + parse.AddCallback(TRPGMAT_TXENV_MODE,&teCb,false); + parse.AddCallback(TRPGMAT_TXENV_FILTER,&teCb,false); + parse.AddCallback(TRPGMAT_TXENV_WRAP,&teCb,false); + parse.AddCallback(TRPGMAT_TXENV_BORDER,&teCb,false); + parse.Parse(buf); - return isValid(); + return isValid(); } /* Write Material class - Material representation. - */ + Material representation. + */ // Constructor trpgMaterial::trpgMaterial() { - Reset(); + Reset(); } trpgMaterial::~trpgMaterial() { @@ -507,553 +441,960 @@ trpgMaterial::~trpgMaterial() // Reset function void trpgMaterial::Reset() { - color = trpgColor(1,1,1); - ambient = trpgColor(0,0,0); - diffuse = trpgColor(1,1,1); - specular = trpgColor(0,0,0); - emission = trpgColor(0,0,0); - shininess = 0; - shadeModel = Smooth; - pointSize = 1; - lineWidth = 1; - cullMode = Back; - alphaFunc = GreaterThan; - alphaRef = 0; - alpha = 1.0; - autoNormal = false; - numTex = 0; - texids.resize(0); - texEnvs.resize(0); - numTile = 0; + color = trpgColor(1,1,1); + ambient = trpgColor(0,0,0); + diffuse = trpgColor(1,1,1); + specular = trpgColor(0,0,0); + emission = trpgColor(0,0,0); + shininess = 0; + shadeModel = Smooth; + pointSize = 1; + lineWidth = 1; + cullMode = Back; + alphaFunc = GreaterThan; + alphaRef = 0; + alpha = 1.0; + autoNormal = false; + numTex = 0; + texids.resize(0); + texEnvs.resize(0); + numTile = 0; + isBump = false; } // Validity check bool trpgMaterial::isValid() const { - // Only thing we really care about is texture - if (numTex < 0) - return false; + // Only thing we really care about is texture + if (numTex < 0) + return false; - for (int i=0;i= texids.size()) - return; + if (no < 0 || (unsigned int)no >= texids.size()) + return; - texids[no] = id; - texEnvs[no] = env; + texids[no] = id; + texEnvs[no] = env; } int trpgMaterial::AddTexture(int id,const trpgTextureEnv &env) { - texids.push_back(id); - texEnvs.push_back(env); - numTex++; + texids.push_back(id); + texEnvs.push_back(env); + numTex++; - return numTex-1; + return numTex-1; } void trpgMaterial::SetNumTiles(int no) { - numTile = no; + numTile = no; } int trpgMaterial::AddTile() { - return(++numTile); + return(++numTile); +} +void trpgMaterial::SetIsBumpMap(bool val) +{ + isBump = val; } // Write to buffer bool trpgMaterial::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPGMATERIAL); + buf.Begin(TRPGMATERIAL); - // Bundle the basic material parameters together - buf.Begin(TRPGMAT_BASIC); - buf.Add(color); - buf.Add(ambient); - buf.Add(diffuse); - buf.Add(specular); - buf.Add(emission); - buf.Add(shininess); - buf.Add(numTile); - buf.End(); + // Bundle the basic material parameters together + buf.Begin(TRPGMAT_BASIC); + buf.Add(color); + buf.Add(ambient); + buf.Add(diffuse); + buf.Add(specular); + buf.Add(emission); + buf.Add(shininess); + buf.Add(numTile); + buf.End(); - // Most everything else is a single token. - // This is inefficient, but expandable - buf.Begin(TRPGMAT_SHADE); - buf.Add(shadeModel); - buf.End(); + // Most everything else is a single token. + // This is inefficient, but expandable + buf.Begin(TRPGMAT_SHADE); + buf.Add(shadeModel); + buf.End(); - buf.Begin(TRPGMAT_SIZES); - buf.Add(pointSize); - buf.Add(lineWidth); - buf.End(); + buf.Begin(TRPGMAT_SIZES); + buf.Add(pointSize); + buf.Add(lineWidth); + buf.End(); - buf.Begin(TRPGMAT_CULL); - buf.Add(cullMode); - buf.End(); + buf.Begin(TRPGMAT_CULL); + buf.Add(cullMode); + buf.End(); - buf.Begin(TRPGMAT_ALPHA); - buf.Add(alphaFunc); - buf.Add(alphaRef); - buf.Add(alpha); - buf.End(); + buf.Begin(TRPGMAT_ALPHA); + buf.Add(alphaFunc); + buf.Add(alphaRef); + buf.Add(alpha); + buf.End(); - buf.Begin(TRPGMAT_NORMAL); - buf.Add(autoNormal); - buf.End(); + buf.Begin(TRPGMAT_NORMAL); + buf.Add(autoNormal); + buf.End(); - buf.Begin(TRPGMAT_TEXTURE); - buf.Add(numTex); - for (int i=0;i= numTex) - return false; - id = texids[no]; - te = texEnvs[no]; - return true; + if (!isValid() || no < 0 || no >= numTex) + return false; + id = texids[no]; + te = texEnvs[no]; + return true; } bool trpgMaterial::GetNumTile(int &no) const { - if (!isValid()) return false; - no = numTile; - return true; + if (!isValid()) return false; + no = numTile; + return true; +} +bool trpgMaterial::GetIsBumpMap(bool &ret) const +{ + if (!isValid()) return false; + ret = isBump; + return true; } /* Material CB - Used to parse tokens for a material. - */ + Used to parse tokens for a material. + */ class materialCB : public trpgr_Callback { public: - void * Parse(trpgToken,trpgReadBuffer &); - trpgMaterial *mat; + void * Parse(trpgToken,trpgReadBuffer &); + trpgMaterial *mat; }; void * materialCB::Parse(trpgToken tok,trpgReadBuffer &buf) { - trpgColor color; - float64 shininess; - int shadeModel; - float64 size; - int cullMode; - int alphaFunc; - float64 alphaRef,alpha; - bool autoNormal; - int numTex,texId; - trpgToken envTok; - trpgTextureEnv texEnv; - int32 len,numtile; - bool status; - int i; + trpgColor color; + float64 shininess; + int shadeModel; + float64 size; + int cullMode; + int alphaFunc; + float64 alphaRef,alpha; + bool autoNormal; + int numTex,texId; + trpgToken envTok; + trpgTextureEnv texEnv; + int32 len,numtile; + bool status; + int i; - try { - switch (tok) { - case TRPGMAT_BASIC: - buf.Get(color); - mat->SetColor(color); - buf.Get(color); - mat->SetAmbient(color); - buf.Get(color); - mat->SetDiffuse(color); - buf.Get(color); - mat->SetSpecular(color); - buf.Get(color); - mat->SetEmission(color); - buf.Get(shininess); - mat->SetShininess(shininess); - buf.Get(numtile); - mat->SetNumTiles(numtile); - break; - case TRPGMAT_SHADE: - buf.Get(shadeModel); - mat->SetShadeModel(shadeModel); - break; - case TRPGMAT_SIZES: - buf.Get(size); - mat->SetPointSize(size); - buf.Get(size); - mat->SetLineWidth(size); - break; - case TRPGMAT_CULL: - buf.Get(cullMode); - mat->SetCullMode(cullMode); - break; - case TRPGMAT_ALPHA: - buf.Get(alphaFunc); - buf.Get(alphaRef); - buf.Get(alpha); - mat->SetAlphaFunc(alphaFunc); - mat->SetAlphaRef(alphaRef); - mat->SetAlpha(alpha); - break; - case TRPGMAT_NORMAL: - { - int tmp; - buf.Get(tmp); - if (tmp) - autoNormal = true; - else - autoNormal = false; - mat->SetAutoNormal(autoNormal); - } - break; - case TRPGMAT_TEXTURE: - buf.Get(numTex); - for (i=0;iSetColor(color); + buf.Get(color); + mat->SetAmbient(color); + buf.Get(color); + mat->SetDiffuse(color); + buf.Get(color); + mat->SetSpecular(color); + buf.Get(color); + mat->SetEmission(color); + buf.Get(shininess); + mat->SetShininess(shininess); + buf.Get(numtile); + mat->SetNumTiles(numtile); + break; + case TRPGMAT_SHADE: + buf.Get(shadeModel); + mat->SetShadeModel(shadeModel); + break; + case TRPGMAT_SIZES: + buf.Get(size); + mat->SetPointSize(size); + buf.Get(size); + mat->SetLineWidth(size); + break; + case TRPGMAT_CULL: + buf.Get(cullMode); + mat->SetCullMode(cullMode); + break; + case TRPGMAT_ALPHA: + buf.Get(alphaFunc); + buf.Get(alphaRef); + buf.Get(alpha); + mat->SetAlphaFunc(alphaFunc); + mat->SetAlphaRef(alphaRef); + mat->SetAlpha(alpha); + break; + case TRPGMAT_NORMAL: + { + int tmp; + buf.Get(tmp); + if (tmp) + autoNormal = true; + else + autoNormal = false; + mat->SetAutoNormal(autoNormal); + } + break; + case TRPGMAT_TEXTURE: + buf.Get(numTex); + for (i=0;iAddTexture(texId,texEnv); - } - break; - default: - break; - } - } - catch (...) { - return NULL; - } + mat->AddTexture(texId,texEnv); + } + break; + case TRPGMAT_BUMP: + { + int tmp; + buf.Get(tmp); + bool isBump = (tmp) ? true : false; + mat->SetIsBumpMap(isBump); + } + default: + break; + } + } + catch (...) { + return NULL; + } - return mat; + return mat; } bool trpgMaterial::Read(trpgReadBuffer &buf) { - trpgr_Parser parse; - materialCB matCb; + trpgr_Parser parse; + materialCB matCb; - // Material is just a bunch of unordered tokens. - // Interface to it with a generic parser - matCb.mat = this; - parse.AddCallback(TRPGMAT_BASIC,&matCb,false); - parse.AddCallback(TRPGMAT_SHADE,&matCb,false); - parse.AddCallback(TRPGMAT_SIZES,&matCb,false); - parse.AddCallback(TRPGMAT_CULL,&matCb,false); - parse.AddCallback(TRPGMAT_ALPHA,&matCb,false); - parse.AddCallback(TRPGMAT_NORMAL,&matCb,false); - parse.AddCallback(TRPGMAT_TEXTURE,&matCb,false); - parse.Parse(buf); + // Material is just a bunch of unordered tokens. + // Interface to it with a generic parser + matCb.mat = this; + parse.AddCallback(TRPGMAT_BASIC,&matCb,false); + parse.AddCallback(TRPGMAT_SHADE,&matCb,false); + parse.AddCallback(TRPGMAT_SIZES,&matCb,false); + parse.AddCallback(TRPGMAT_CULL,&matCb,false); + parse.AddCallback(TRPGMAT_ALPHA,&matCb,false); + parse.AddCallback(TRPGMAT_NORMAL,&matCb,false); + parse.AddCallback(TRPGMAT_TEXTURE,&matCb,false); + parse.AddCallback(TRPGMAT_BUMP,&matCb,false); + parse.Parse(buf); - return isValid(); + return isValid(); } /* Texture - Really just a container for a texture name and use count. - The use count is used for paging. - */ + Really just a container for a texture name and use count. + The use count is used for paging. + */ // Constructor trpgTexture::trpgTexture() { - name = NULL; - useCount = 0; + mode = External; + type = trpg_Unknown; + name = NULL; + useCount = 0; + sizeX = sizeY = -1; + addr.file = 0; + addr.offset = 0; + isMipmap = false; } // Copy construction trpgTexture::trpgTexture(const trpgTexture &in) { - name = NULL; - useCount = 0; - *this = in; + mode = in.mode; + type = in.type; + name = NULL; + SetName(in.name); + useCount = in.useCount; + sizeX = in.sizeX; sizeY = in.sizeY; + addr.file = in.addr.file; + addr.offset = in.addr.offset; + isMipmap = in.isMipmap; } // Destruction trpgTexture::~trpgTexture() { - Reset(); + Reset(); } // Reset void trpgTexture::Reset() { - if (name) - delete name; - name = NULL; - useCount = 0; + mode = External; + type = trpg_Unknown; + if (name) + delete [] name; + name = NULL; + useCount = 0; + sizeX = sizeY = -1; + addr.file = 0; + addr.offset = 0; + isMipmap = false; + storageSize.clear(); + levelOffset.clear(); } // Valid if we've got a name bool trpgTexture::isValid() const { - if (name) - return true; + switch (mode) { + case External: + return (name != NULL); + break; + case Local: + return (type != trpg_Unknown && sizeX != -1 && sizeY != -1); + break; + case Global: + return (type != trpg_Unknown); + break; + case Template: + return (type != trpg_Unknown && sizeX != -1 && sizeY != -1); + break; + default: + return false; + } - return false; + return false; } // Set Name void trpgTexture::SetName(const char *inName) { - if (name) - delete name; - if (!inName || strlen(inName) < 1) - return; + if (name) + delete [] name; + name = NULL; - name = new char[strlen(inName)+1]; - strcpy(name,inName); + if (!inName) + return; + + name = new char[strlen(inName)+1]; + strcpy(name,inName); } // Get Name bool trpgTexture::GetName(char *outName,int outLen) const { - if (!isValid()) return false; + if (!isValid()) return false; - int len = (name) ? strlen(name) : 0; - strncpy(outName,name,MIN(len,outLen)+1); + int len = (name) ? strlen(name) : 0; + strncpy(outName,name,MIN(len,outLen)+1); - return true; + return true; +} + +void trpgTexture::SetImageMode(ImageMode inMode) +{ + mode = inMode; +} +bool trpgTexture::GetImageMode(ImageMode &outMode) const +{ + outMode = mode; + + return true; +} +void trpgTexture::SetImageType(ImageType inType) +{ + type = inType; +} +bool trpgTexture::GetImageType(ImageType &outType) const +{ + outType = type; + + return true; +} +void trpgTexture::SetImageSize(const trpg2iPoint &inSize) +{ + sizeX = inSize.x; + sizeY = inSize.y; +} +bool trpgTexture::GetImageSize(trpg2iPoint &outSize) const +{ + if (mode != Local && mode != Template) + return false; + outSize.x = sizeX; + outSize.y = sizeY; + + return true; +} +void trpgTexture::SetIsMipmap(bool val) +{ + isMipmap = val; +} +bool trpgTexture::GetIsMipmap(bool &ret) const +{ + ret = isMipmap; + return true; +} +bool trpgTexture::GetImageAddr(trpgwAppAddress &outAddr) const +{ + if (mode != Local) + return false; + + outAddr = addr; + + return true; +} +void trpgTexture::SetImageAddr(const trpgwAppAddress &inAddr) +{ + addr = inAddr; +} +bool trpgTexture::GetImageDepth(int32 &depth) const +{ + switch (type) { + case trpg_RGB8: + depth = 3; + break; + case trpg_RGBA8: + depth = 4; + break; + case trpg_INT8: + depth = 1; + break; + case trpg_INTA8: + depth = 2; + break; + case trpg_FXT1: + depth = 3; + break; + case trpg_RGBX: + depth = numLayer; + break; + case trpg_DXT1: + depth = 3; + break; + case trpg_DXT3: + depth = 3; + break; + case trpg_DXT5: + depth = 3; + break; + default: + depth = -1; + break; + } + + return true; } // Use count management void trpgTexture::SetNumTile(int num) { - useCount = num; + useCount = num; } void trpgTexture::AddTile() { - useCount++; + useCount++; } bool trpgTexture::GetNumTile(int &num) const { - if (!isValid()) return false; - num = useCount; - return true; + if (!isValid()) return false; + num = useCount; + return true; } // Copy operator trpgTexture &trpgTexture::operator = (const trpgTexture &in) { - SetName(in.name); - useCount = in.useCount; + mode = in.mode; + type = in.type; - return *this; + if (in.name) + SetName(in.name); + + useCount = in.useCount; + + sizeX = in.sizeX; + sizeY = in.sizeY; + isMipmap = in.isMipmap; + addr = in.addr; + + return *this; } // Equality operator int trpgTexture::operator == (const trpgTexture &in) const { - if (!in.name && !name) - return 1; - if (!in.name || !name) - return 0; - return (!strcmp(in.name,name)); + if (mode != in.mode) + return 0; + + switch (mode) { + case External: + if (!in.name && !name) + return 1; + if (!in.name || !name) + return 0; + return (!strcmp(in.name,name)); + break; + case Local: + if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY && + isMipmap == in.isMipmap && + addr.file == in.addr.file && addr.offset == in.addr.offset) + return 1; + break; + case Global: + case Template: + if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY && + isMipmap == in.isMipmap) + return 1; + } + + return 0; } +// Utility functions + +int32 trpgTexture::CalcNumMipmaps() const +{ + // We're going to assume these are powers of two. + // If not, then the writer's a moron. + + // :))) The comment line above made me really loughing, Steve. - Nick + int bval = MAX(sizeX,sizeY); + + // Now look for the highest bit + int p2; + for (p2=0;p2<32;p2++) + if ((1<> 3; + + if (x > 1) x /= 2; + if (y > 1) y /= 2; + } + + return totSize; + } + }; + + // Figure out the total data size, including mipmaps if necessary + int32 depth; + GetImageDepth(depth); + totSize = sizeX * sizeY * depth; + + // Do mipmaps if they're there + if (isMipmap) { + trpg2iPoint size(sizeX,sizeY); + int maxSize = MAX(size.x,size.y); + while (maxSize > 1) { + size.x = size.x >> 1; size.x = MAX(1,size.x); + size.y = size.y >> 1; size.y = MAX(1,size.y); + maxSize = maxSize >> 1; + + totSize += size.x*size.y*depth; + } + } + + return totSize; +} + +// Calculate the size of a given mip level +int32 trpgTexture::MipLevelSize(int miplevel) +{ + + if ( miplevel > 0 && miplevel < CalcNumMipmaps() ) { + if ( !storageSize.size() ) + CalcMipLevelSizes(); + return storageSize[miplevel]; + } + + return 0; +} + +int32 trpgTexture::MipLevelOffset(int miplevel) +{ + if ( miplevel > 0 && miplevel < CalcNumMipmaps() ) { + if ( !levelOffset.size() ) + CalcMipLevelSizes(); + return levelOffset[miplevel]; + } + + return 0; +} + + // Write function bool trpgTexture::Write(trpgWriteBuffer &buf) { - if (!isValid()) return false; + if (!isValid()) return false; - buf.Add(name); - buf.Add(useCount); + buf.Begin(TRPGTEXTURE); - return true; + buf.Add(name); + buf.Add(useCount); + // New in 2.0 from here down + buf.Add((unsigned char)mode); + buf.Add((unsigned char)type); + buf.Add(sizeX); + buf.Add(sizeY); + buf.Add(addr.file); + buf.Add(addr.offset); + buf.Add(isMipmap); + + buf.End(); + + return true; } // Read function bool trpgTexture::Read(trpgReadBuffer &buf) { - char texName[1024]; + char texName[1024]; - try { - buf.Get(texName,1023); - SetName(texName); - buf.Get(useCount); - } - catch (...) { - return false; - } + try { + buf.Get(texName,1023); + SetName(texName); + buf.Get(useCount); - if (!isValid()) return false; - return true; + mode = External; + // New in 2.0 from here down + unsigned char bval; + buf.Get(bval); mode = (trpgTexture::ImageMode)bval; + buf.Get(bval); type = (trpgTexture::ImageType)bval; + buf.Get(sizeX); + buf.Get(sizeY); + buf.Get(addr.file); + buf.Get(addr.offset); + int ival; + buf.Get(ival); + isMipmap = (ival) ? true : false; + } + catch (...) { + return false; + } + + if (!isValid()) return false; + + // calculate the mip level sizes + CalcMipLevelSizes(); + + return true; +} + +void trpgTexture::CalcMipLevelSizes() +{ + int num_miplevels = CalcNumMipmaps(); + int level_size = 0; + int level_offset = 0; + int block_size = 0; + int pixel_size = 0; + + switch (type) { + case trpg_DXT1: + block_size = 8; + break; + case trpg_DXT3: + case trpg_DXT5: + block_size = 16; + break; + case trpg_RGB8: + pixel_size = 3; + break; + case trpg_RGBA8: + pixel_size = 4; + break; + case trpg_INT8: + pixel_size = 1; + break; + case trpg_INTA8: + pixel_size = 2; + break; + } + + levelOffset.clear(); + storageSize.clear(); + + levelOffset.push_back(level_offset); + + if ( block_size ) { // DXT compressed + int num_x_blocks = ((sizeX/4)+(sizeX%4?1:0)); + int num_y_blocks = ((sizeY/4)+(sizeY%4?1:0)); + + level_size = num_x_blocks * num_y_blocks * block_size; + storageSize.push_back(level_size); + + for ( int i = 1; i < num_miplevels; i++ ) { + level_offset += level_size; + levelOffset.push_back(level_offset); + + num_x_blocks /= 2; + num_y_blocks /= 2; + num_x_blocks = MAX(1,num_x_blocks); + num_y_blocks = MAX(1,num_y_blocks); + + level_size = num_x_blocks * num_y_blocks * block_size; + storageSize.push_back(level_size); + } + } + else { + int x_size = sizeX; + int y_size = sizeY; + + level_size = x_size * y_size * pixel_size; + storageSize.push_back(level_size); + for ( int i = 1; i < num_miplevels; i++ ) { + level_offset += level_size; + levelOffset.push_back(level_offset); + + x_size /= 2; + y_size /= 2; + x_size = MAX(1,x_size); + y_size = MAX(1,y_size); + + level_size = x_size * y_size * pixel_size; + storageSize.push_back(level_size); + } + } } /* Texture Table - Just a list of texture names so we can index. - */ + Just a list of texture names so we can index. + */ // Constructor trpgTexTable::trpgTexTable() @@ -1061,124 +1402,287 @@ trpgTexTable::trpgTexTable() } trpgTexTable::trpgTexTable(const trpgTexTable &in) { - *this = in; + *this = in; } // Reset function void trpgTexTable::Reset() { - texList.resize(0); + texList.resize(0); } // Destructor trpgTexTable::~trpgTexTable() { - Reset(); + Reset(); } // Validity check bool trpgTexTable::isValid() const { - for (unsigned int i=0;i= (int)texList.size()) - return; + if (id < 0 || (unsigned int)id >= texList.size()) + return; - texList[id] = inTex; + texList[id] = inTex; } // Copy operator trpgTexTable &trpgTexTable::operator = (const trpgTexTable &in) { - for (unsigned int i=0;i= (int)texList.size()) return false; + if (!isValid()) return false; + if (id < 0 || id >= texList.size()) return false; - ret = texList[id]; - return true; + ret = texList[id]; + return true; } -trpgTexture *trpgTexTable::GetTextureRef(int id) +const trpgTexture *trpgTexTable::GetTextureRef(int id) const { - if (id < 0 || id >= (int)texList.size()) return NULL; - return &texList[id]; + if (id < 0 || id >= texList.size()) return NULL; + return &texList[id]; } bool trpgTexTable::Read(trpgReadBuffer &buf) { - int32 numTex; - trpgTexture tex; + int32 numTex; + trpgToken texTok; + int32 len; - try { - buf.Get(numTex); - for (int i=0;i *inSizes) +{ + storageSize.resize(inSizes->size()); + for (int i=0;isize();i++) + storageSize[i] = (*inSizes)[i]; + + return true; +}*/ + +/*bool trpgLocalMaterial::GetStorageSizes(const vector *retSize) +{ + if (!isValid()) return false; + + retSize = storageSize; + return true; +}*/ + +bool trpgLocalMaterial::isValid() const +{ + if (baseMat < 0) return false; + + return true; +} + +// Write method + +bool trpgLocalMaterial::Write(trpgWriteBuffer &buf) +{ + if (!isValid()) + return false; + + buf.Begin(TRPGLOCALMATERIAL); + + // Write the data + buf.Add(baseMatTable); + buf.Add(baseMat); + buf.Add(sx); + buf.Add(sy); + buf.Add(ex); + buf.Add(ey); + buf.Add(destWidth); + buf.Add(destHeight); + buf.Add(addr.file); + buf.Add(addr.offset); + + buf.End(); + + return true; +} + +// Read method + +bool trpgLocalMaterial::Read(trpgReadBuffer &buf) +{ + try { + buf.Get(baseMatTable); + buf.Get(baseMat); + buf.Get(sx); + buf.Get(sy); + buf.Get(ex); + buf.Get(ey); + buf.Get(destWidth); + buf.Get(destHeight); + buf.Get(addr.file); + buf.Get(addr.offset); + } + catch (...) { + return false; + } + + return isValid(); +} + diff --git a/src/osgPlugins/txp/trpage_model.cpp b/src/osgPlugins/txp/trpage_model.cpp index 726e7bdbc..2a7a6f038 100644 --- a/src/osgPlugins/txp/trpage_model.cpp +++ b/src/osgPlugins/txp/trpage_model.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,199 +18,199 @@ #include /* 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) { - name = NULL; - type = External; - *this = in; + name = NULL; + type = External; + *this = in; } // Reset function void trpgModel::Reset() { - if (name) - delete name; - name = NULL; - useCount = 0; + if (name) + delete [] name; + name = NULL; + useCount = 0; } trpgModel::~trpgModel() { - Reset(); + Reset(); } // Set functions void trpgModel::SetName(const char *nm) { - if (name) - delete name; + if (name) + delete [] name; - name = new char[(nm ? strlen(nm) : 0)+1]; - strcpy(name,nm); + name = new char[(nm ? strlen(nm) : 0)+1]; + strcpy(name,nm); - type = External; + type = External; } void trpgModel::SetReference(trpgDiskRef pos) { - if (name) - delete name; + if (name) + delete [] name; - diskRef = pos; + diskRef = pos; - type = Local; + type = Local; } void trpgModel::SetNumTiles(int num) { - useCount = num; + useCount = num; } void trpgModel::AddTile() { - useCount++; + useCount++; } // Validity check bool trpgModel::isValid() const { - if (type == External && !name) - return false; + if (type == External && !name) + 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() @@ -224,102 +223,110 @@ 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()) - return false; - model = models[id]; - return true; + if (!isValid() || id < 0 || id >= models.size()) + return false; + model = models[id]; + return true; } trpgModel *trpgModelTable::GetModelRef(int id) { - if (id < 0 || (unsigned int)id >= models.size()) - return NULL; - return &models[id]; + if (id < 0 || id >= models.size()) + return NULL; + return &models[id]; } bool trpgModelTable::Read(trpgReadBuffer &buf) { - int32 numModel; - trpgModel model; - trpgToken tok; - int32 len; - bool status; + int32 numModel; + trpgModel model; + trpgToken tok; + int32 len; + bool status; - try { - buf.Get(numModel); - for (int i=0;i /* trpage_nodes.cpp - The methods for all the hierarchy nodes (e.g. groups, transforms, etc...) - is here. - You should only need to modify this if you want to add something to one - of these classes. - */ + The methods for all the hierarchy nodes (e.g. groups, transforms, etc...) + is here. + You should only need to modify this if you want to add something to one + of these classes. + */ #include "trpage_geom.h" #include "trpage_read.h" /* Write Group - Basic group. - */ + Basic group. + */ // Constructor trpgGroup::trpgGroup() { - Reset(); + name = 0; + Reset(); + } trpgGroup::~trpgGroup() { + Reset(); } // Reset void trpgGroup::Reset() { - numChild = 0; - id = -1; + numChild = 0; + id = -1; + if ( name ) { + delete [] name; + name = 0; + } } // Set functions void trpgGroup::SetNumChild(int no) { - numChild = no; + numChild = no; } int trpgGroup::AddChild() { - numChild++; - return numChild-1; + numChild++; + return numChild-1; } void trpgGroup::SetID(int inID) { - id = inID; + id = inID; +} + +void trpgGroup::SetName(const char* newname ) +{ + if ( name ) { + delete [] name; + name = 0; + } + if ( strlen(newname) ) { + name = new char[strlen(newname)+1]; + strcpy(name,newname); + } } // Get methods +const char* trpgGroup::GetName(void) const +{ + return name; +} + bool trpgGroup::GetNumChild(int &n) const { - if (!isValid()) return false; - n = numChild; - return true; + if (!isValid()) return false; + n = numChild; + return true; } bool trpgGroup::GetID(int &inID) const { - if (!isValid()) return false; - inID = id; - return true; + if (!isValid()) return false; + inID = id; + return true; } // Validity check bool trpgGroup::isValid() const { - if (numChild <= 0) return false; - if (id < 0) return false; + if (numChild <= 0) return false; + if (id < 0) return false; - return true; + return true; } // Write group bool trpgGroup::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPG_GROUP); - buf.Add(numChild); - buf.Add(id); - buf.End(); + buf.Begin(TRPG_GROUP); + buf.Add(numChild); + buf.Add(id); - return true; + if ( name && strlen(name) ) { + buf.Add(name); + } + + buf.End(); + + return true; } // Read group bool trpgGroup::Read(trpgReadBuffer &buf) { - try { - buf.Get(numChild); - if (numChild < 0) throw 1; - buf.Get(id); - if (id < 0) throw 1; - } - catch (...) { - return false; - } + try { + buf.Get(numChild); + if (numChild < 0) throw 1; + buf.Get(id); + if (id < 0) throw 1; + if ( !buf.isEmpty() ) { + char nm[1024] = {0}; + buf.Get(nm,1024); + SetName(nm); + } - return isValid(); + } + catch (...) { + return false; + } + + return isValid(); } /* Write Billboard - Represents rotational billboarded geometry. - */ + Represents rotational billboarded geometry. + */ // Constructor trpgBillboard::trpgBillboard() { - Reset(); + name = 0; + Reset(); } trpgBillboard::~trpgBillboard() { + Reset(); } // Reset function void trpgBillboard::Reset() { - id = -1; - mode = Axial; - type = Group; - axis = trpg3dPoint(0,0,1); - center = trpg3dPoint(0,0,0); - numChild = 0; + id = -1; + mode = Axial; + type = Group; + axis = trpg3dPoint(0,0,1); + center = trpg3dPoint(0,0,0); + numChild = 0; + if ( name ) { + delete [] name; + name = 0; + } } // Set functions void trpgBillboard::SetCenter(const trpg3dPoint &pt) { - center = pt; - valid = true; + center = pt; + valid = true; } void trpgBillboard::SetMode(int m) { - mode = m; + mode = m; } void trpgBillboard::SetAxis(const trpg3dPoint &pt) { - axis = pt; + axis = pt; } void trpgBillboard::SetType(int t) { - type = t; + type = t; } // Get methods bool trpgBillboard::GetCenter(trpg3dPoint &pt) const { - if (!isValid()) return false; - pt = center; - return true; + if (!isValid()) return false; + pt = center; + return true; } bool trpgBillboard::GetMode(int &m) const { - if (!isValid()) return false; - m = mode; - return true; + if (!isValid()) return false; + m = mode; + return true; } bool trpgBillboard::GetAxis(trpg3dPoint &pt) const { - if (!isValid()) return false; - pt = axis; - return true; + if (!isValid()) return false; + pt = axis; + return true; } bool trpgBillboard::GetType(int &t) const { - if (!isValid()) return false; - t = type; - return true; + if (!isValid()) return false; + t = type; + return true; } // Write billboard bool trpgBillboard::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPG_BILLBOARD); - buf.Add(numChild); - buf.Add(id); - buf.Add((uint8)type); - buf.Add((uint8)mode); - buf.Add(center); - buf.Add(axis); - buf.End(); + buf.Begin(TRPG_BILLBOARD); + buf.Add(numChild); + buf.Add(id); + buf.Add((uint8)type); + buf.Add((uint8)mode); + buf.Add(center); + buf.Add(axis); - return true; + if ( name && strlen(name) ) { + buf.Add(name); + } + buf.End(); + + return true; } // Read billboard bool trpgBillboard::Read(trpgReadBuffer &buf) { - uint8 uChar; + uint8 uChar; - try { - buf.Get(numChild); - buf.Get(id); - buf.Get(uChar); type = uChar; - buf.Get(uChar); mode = uChar; - buf.Get(center); - buf.Get(axis); - } - catch (...) { - return false; - } + try { + buf.Get(numChild); + buf.Get(id); + buf.Get(uChar); type = uChar; + buf.Get(uChar); mode = uChar; + buf.Get(center); + buf.Get(axis); + if ( !buf.isEmpty() ) { + char nm[1024] = {0}; + buf.Get(nm,1024); + SetName(nm); + } + } + catch (...) { + return false; + } - return isValid(); + return isValid(); } /* Write Level of Detail - Represents LOD information. - */ + Represents LOD information. + */ // Constructor trpgLod::trpgLod() { - Reset(); + name = 0; + Reset(); } trpgLod::~trpgLod() { + Reset(); } // Reset function void trpgLod::Reset() { - id = -1; - numRange = 0; - center = trpg3dPoint(0,0,0); - switchIn = switchOut = width = 0; - valid = true; + id = -1; + numRange = 0; + center = trpg3dPoint(0,0,0); + switchIn = switchOut = width = 0; + rangeIndex = -1; + valid = true; + if ( name ) { + delete [] name; + name = 0; + } } // Set functions void trpgLod::SetCenter(const trpg3dPoint &pt) { - center = pt; - valid = true; + center = pt; + valid = true; } void trpgLod::SetNumChild(int no) { - if (no < 0) - return; + if (no < 0) + return; - numRange = no; + numRange = no; } void trpgLod::SetLOD(double in,double out,double wid) { - switchIn = in; - switchOut = out; - width = wid; + switchIn = in; + switchOut = out; + width = wid; } void trpgLod::SetID(int inID) { - id = inID; + id = inID; +} + +void trpgLod::SetName(const char* newname ) +{ + if ( name ) { + delete [] name; + name = 0; + } + if ( strlen(newname) ) { + name = new char[strlen(newname)+1]; + strcpy(name,newname); + } +} + +void trpgLod::SetRangeIndex(int ri) +{ + rangeIndex = ri; +} + +// Get methods +const char* trpgLod::GetName(void) const +{ + return name; } // Get functions bool trpgLod::GetCenter(trpg3dPoint &pt) const { - if (!isValid()) return false; - pt = center; - return true; + if (!isValid()) return false; + pt = center; + return true; } bool trpgLod::GetNumChild(int &n) const { - if (!isValid()) return false; - n = numRange; - return true; + if (!isValid()) return false; + n = numRange; + return true; } bool trpgLod::GetLOD(double &in,double &out,double &wid) const { - if (!isValid()) return false; - in = switchIn; - out = switchOut; - wid = width; - return true; + if (!isValid()) return false; + in = switchIn; + out = switchOut; + wid = width; + return true; } bool trpgLod::GetID(int &outID) const { - if (!isValid()) return false; - outID = id; - return true; + if (!isValid()) return false; + outID = id; + return true; +} +bool trpgLod::GetRangeIndex(int &ri) const +{ + if (!isValid()) return false; + + ri = rangeIndex; + + return true; } // Write out LOD bool trpgLod::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPG_LOD); - buf.Add(id); - buf.Add(numRange); - buf.Add(center); - buf.Add(switchIn); - buf.Add(switchOut); - buf.Add(width); - buf.End(); + buf.Begin(TRPG_LOD); + buf.Add(id); + buf.Add(numRange); + buf.Add(center); + buf.Add(switchIn); + buf.Add(switchOut); + buf.Add(width); - return true; + if ( name && strlen(name) ) { + buf.Add(name); + } else + buf.Add(""); + + + buf.End(); + + return true; } // Read in LOD bool trpgLod::Read(trpgReadBuffer &buf) { - try { - buf.Get(id); - buf.Get(numRange); - if (numRange < 0) throw 1; - buf.Get(center); - buf.Get(switchIn); - buf.Get(switchOut); - buf.Get(width); - } - catch (...) { - return false; - } + try { + buf.Get(id); + buf.Get(numRange); + if (numRange < 0) throw 1; + buf.Get(center); + buf.Get(switchIn); + buf.Get(switchOut); + buf.Get(width); + if ( !buf.isEmpty() ) { + char nm[1024] = {0}; + buf.Get(nm,1024); + if (*nm) + SetName(nm); + // Look for a range index + if (!buf.isEmpty()) + buf.Get(rangeIndex); + } + } + catch (...) { + return false; + } - return isValid(); + return isValid(); } /* Write Layer - A layer is just a group with a different opcode. - */ + A layer is just a group with a different opcode. + */ // Constructor trpgLayer::trpgLayer() { + name = 0; } trpgLayer::~trpgLayer() { + Reset(); } // Write it bool trpgLayer::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPG_LAYER); - buf.Add(numChild); - buf.Add(id); - buf.End(); + buf.Begin(TRPG_LAYER); + buf.Add(numChild); + buf.Add(id); - return true; + if ( name && strlen(name) ) { + buf.Add(name); + } + + buf.End(); + + return true; } // Read layer bool trpgLayer::Read(trpgReadBuffer &buf) { - try { - buf.Get(numChild); - if (numChild < 0) throw 1; - buf.Get(id); - if (id < 0) throw 1; - } - catch (...) { - return false; - } + try { + buf.Get(numChild); + if (numChild < 0) throw 1; + buf.Get(id); + if (id < 0) throw 1; + if ( !buf.isEmpty() ) { + char nm[1024] = {0}; + buf.Get(nm,1024); + SetName(nm); + } + } + catch (...) { + return false; + } - return isValid(); + return isValid(); } // Reset function void trpgLayer::Reset() { - numChild = 0; + numChild = 0; + if ( name ) { + delete [] name; + name = 0; + } } /* Write Transform - Matrix defining the transform with children. - */ + Matrix defining the transform with children. + */ // Constructor trpgTransform::trpgTransform() { - Reset(); + name = 0; + Reset(); } trpgTransform::~trpgTransform() { + Reset(); } // Reset function void trpgTransform::Reset() { - id = -1; - // Note: Is this row major or column major? - m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0; - m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0; - m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0; - m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; + id = -1; + // Note: Is this row major or column major? + m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0; + m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0; + m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0; + m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; + + if ( name ) { + delete [] name; + name = 0; + } } // Set functions void trpgTransform::SetMatrix(const float64 *im) { - m[0][0] = im[4*0+0]; m[0][1] = im[4*0+1]; m[0][2] = im[4*0+2]; m[0][3] = im[4*0+3]; - m[1][0] = im[4*1+0]; m[1][1] = im[4*1+1]; m[1][2] = im[4*1+2]; m[1][3] = im[4*1+3]; - m[2][0] = im[4*2+0]; m[2][1] = im[4*2+1]; m[2][2] = im[4*2+2]; m[2][3] = im[4*2+3]; - m[3][0] = im[4*3+0]; m[3][1] = im[4*3+1]; m[3][2] = im[4*3+2]; m[3][3] = im[4*3+3]; + m[0][0] = im[4*0+0]; m[0][1] = im[4*0+1]; m[0][2] = im[4*0+2]; m[0][3] = im[4*0+3]; + m[1][0] = im[4*1+0]; m[1][1] = im[4*1+1]; m[1][2] = im[4*1+2]; m[1][3] = im[4*1+3]; + m[2][0] = im[4*2+0]; m[2][1] = im[4*2+1]; m[2][2] = im[4*2+2]; m[2][3] = im[4*2+3]; + m[3][0] = im[4*3+0]; m[3][1] = im[4*3+1]; m[3][2] = im[4*3+2]; m[3][3] = im[4*3+3]; } // Get methods bool trpgTransform::GetMatrix(float64 *rm) const { - if (!isValid()) return false; - for (int i=0;i<4;i++) - for (int j=0;j<4;j++) - // Note: is this right? - rm[i*4+j] = m[i][j]; - return true; + if (!isValid()) return false; + for (int i=0;i<4;i++) + for (int j=0;j<4;j++) + // Note: is this right? + rm[i*4+j] = m[i][j]; + return true; } // Write transform bool trpgTransform::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPG_TRANSFORM); - buf.Add(numChild); - buf.Add(id); - for (int i=0;i<4;i++) - for (int j=0;j<4;j++) - buf.Add(m[i][j]); - buf.End(); + buf.Begin(TRPG_TRANSFORM); + buf.Add(numChild); + buf.Add(id); + for (int i=0;i<4;i++) + for (int j=0;j<4;j++) + buf.Add(m[i][j]); - return true; + if ( name && strlen(name) ) { + buf.Add(name); + } + buf.End(); + + return true; } // Read transform bool trpgTransform::Read(trpgReadBuffer &buf) { - try { - buf.Get(numChild); - buf.Get(id); - if (numChild < 0) throw 1; - for (int i=0;i<4;i++) - for (int j=0;j<4;j++) - buf.Get(m[i][j]); - } - catch (...) { - return false; - } + try { + buf.Get(numChild); + buf.Get(id); + if (numChild < 0) throw 1; + for (int i=0;i<4;i++) + for (int j=0;j<4;j++) + buf.Get(m[i][j]); + if ( !buf.isEmpty() ) { + char nm[1024] = {0}; + buf.Get(nm,1024); + SetName(nm); + } + } + catch (...) { + return false; + } - return isValid(); + return isValid(); } /* Model Reference - This is just a matrix transform and a model ID. - */ + This is just a matrix transform and a model ID. + */ // Constructor trpgModelRef::trpgModelRef() { - Reset(); + Reset(); } trpgModelRef::~trpgModelRef() { @@ -479,162 +614,178 @@ trpgModelRef::~trpgModelRef() // Reset function void trpgModelRef::Reset() { - m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0; - m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0; - m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0; - m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; - modelRef = -1; + m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0; + m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0; + m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0; + m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; + modelRef = -1; } // Set functions void trpgModelRef::SetModel(int id) { - modelRef = id; - valid = true; + modelRef = id; + valid = true; } void trpgModelRef::SetMatrix(const float64 *im) { - m[0][0] = im[4*0+0]; m[0][1] = im[4*0+1]; m[0][2] = im[4*0+2]; m[0][3] = im[4*0+3]; - m[1][0] = im[4*1+0]; m[1][1] = im[4*1+1]; m[1][2] = im[4*1+2]; m[1][3] = im[4*1+3]; - m[2][0] = im[4*2+0]; m[2][1] = im[4*2+1]; m[2][2] = im[4*2+2]; m[2][3] = im[4*2+3]; - m[3][0] = im[4*3+0]; m[3][1] = im[4*3+1]; m[3][2] = im[4*3+2]; m[3][3] = im[4*3+3]; + m[0][0] = im[4*0+0]; m[0][1] = im[4*0+1]; m[0][2] = im[4*0+2]; m[0][3] = im[4*0+3]; + m[1][0] = im[4*1+0]; m[1][1] = im[4*1+1]; m[1][2] = im[4*1+2]; m[1][3] = im[4*1+3]; + m[2][0] = im[4*2+0]; m[2][1] = im[4*2+1]; m[2][2] = im[4*2+2]; m[2][3] = im[4*2+3]; + m[3][0] = im[4*3+0]; m[3][1] = im[4*3+1]; m[3][2] = im[4*3+2]; m[3][3] = im[4*3+3]; } // Get methods bool trpgModelRef::GetModel(int32 &mod) const { - if (!isValid()) return false; - mod = modelRef; - return true; + if (!isValid()) return false; + mod = modelRef; + return true; } bool trpgModelRef::GetMatrix(float64 *rm) const { - if (!isValid()) return false; - for (int i=0;i<4;i++) - for (int j=0;j<4;j++) - // Note: is this right? - rm[i*4+j] = m[i][j]; - return true; + if (!isValid()) return false; + for (int i=0;i<4;i++) + for (int j=0;j<4;j++) + // Note: is this right? + rm[i*4+j] = m[i][j]; + return true; } // Write model reference bool trpgModelRef::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; - - buf.Begin(TRPG_MODELREF); - buf.Add(modelRef); - for (int i=0;i<4;i++) - for (int j=0;j<4;j++) - buf.Add(m[i][j]); - buf.End(); + if (!isValid()) + return false; + + buf.Begin(TRPG_MODELREF); + buf.Add(modelRef); + for (int i=0;i<4;i++) + for (int j=0;j<4;j++) + buf.Add(m[i][j]); + buf.End(); - return true; + return true; } // Read model reference bool trpgModelRef::Read(trpgReadBuffer &buf) { - try { - buf.Get(modelRef); - if (modelRef < 0) throw 1; - for (int i=0;i<4;i++) - for (int j=0;j<4;j++) - buf.Get(m[i][j]); - } - catch (...) { - return false; - } + try { + buf.Get(modelRef); + if (modelRef < 0) throw 1; + for (int i=0;i<4;i++) + for (int j=0;j<4;j++) + buf.Get(m[i][j]); + } + catch (...) { + return false; + } - valid = true; - return isValid(); + valid = true; + return isValid(); } /* Attach Node - You'll find one of these in each tile, except for the lowest LOD. - It's basically a group with some extra info that tells you where to attach it. - The ID corresponds to the one in Group and LOD. - */ + You'll find one of these in each tile, except for the lowest LOD. + It's basically a group with some extra info that tells you where to attach it. + The ID corresponds to the one in Group and LOD. + */ // Constructor trpgAttach::trpgAttach() { - Reset(); + name = 0; + Reset(); } trpgAttach::~trpgAttach() { + Reset(); } // Reset void trpgAttach::Reset() { - parentID = -1; - childPos = -1; + parentID = -1; + childPos = -1; + if ( name ) { + delete [] name; + name = 0; + } } // Parent ID is the node this one gets attached to void trpgAttach::SetParentID(int id) { - parentID = id; + parentID = id; } bool trpgAttach::GetParentID(int &id) const { - if (!isValid()) return false; - id = parentID; - return false; + if (!isValid()) return false; + id = parentID; + return true; } // Child Position is a unique number of parent // It could be used as an array index, for example void trpgAttach::SetChildPos(int id) { - childPos = id; + childPos = id; } bool trpgAttach::GetChildPos(int &id) const { - if (!isValid()) return false; - id = childPos; - return false; + if (!isValid()) return false; + id = childPos; + return true; } // Validity check bool trpgAttach::isValid() const { - if (parentID < 0 || childPos < 0) return false; - return true; + if (parentID < 0 || childPos < 0) return false; + return true; } // Write Attach node bool trpgAttach::Write(trpgWriteBuffer &buf) { - if (!isValid()) return false; + if (!isValid()) return false; - buf.Begin(TRPG_ATTACH); - buf.Add(numChild); - buf.Add(id); - buf.Add(parentID); - buf.Add(childPos); - buf.End(); + buf.Begin(TRPG_ATTACH); + buf.Add(numChild); + buf.Add(id); + buf.Add(parentID); + buf.Add(childPos); - return true; + if ( name && strlen(name) ) { + buf.Add(name); + } + + buf.End(); + + return true; } // Read Attach node bool trpgAttach::Read(trpgReadBuffer &buf) { - try { - buf.Get(numChild); - buf.Get(id); - if (id < 0) throw 1; - buf.Get(parentID); - if (parentID < 0) throw 1; - buf.Get(childPos); - if (childPos < 0) throw 1; - } - catch (...) { - return false; - } + try { + buf.Get(numChild); + buf.Get(id); + if (id < 0) throw 1; + buf.Get(parentID); + if (parentID < 0) throw 1; + buf.Get(childPos); + if (childPos < 0) throw 1; + if ( !buf.isEmpty() ) { + char nm[1024] = {0}; + buf.Get(nm,1024); + SetName(nm); + } + } + catch (...) { + return false; + } - return true; + return true; } diff --git a/src/osgPlugins/txp/trpage_parse.cpp b/src/osgPlugins/txp/trpage_parse.cpp index 28e67b991..cfcc6068d 100644 --- a/src/osgPlugins/txp/trpage_parse.cpp +++ b/src/osgPlugins/txp/trpage_parse.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -171,10 +170,14 @@ bool trpgr_Parser::Parse(trpgReadBuffer &buf) // Call our token handler for this one try { - trpgr_Token *tcb = &tokenMap[tok]; + 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); @@ -259,8 +262,7 @@ trpgSceneParser::trpgSceneParser() // Register for default SetDefaultCallback(new trpgSceneHelperDefault(this)); -}; - +} trpgSceneParser::~trpgSceneParser() { -}; +} diff --git a/src/osgPlugins/txp/trpage_rarchive.cpp b/src/osgPlugins/txp/trpage_rarchive.cpp index 48340ad41..fe1c9e561 100644 --- a/src/osgPlugins/txp/trpage_rarchive.cpp +++ b/src/osgPlugins/txp/trpage_rarchive.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,222 +18,472 @@ #include /* 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" // Constructor trpgr_Archive::trpgr_Archive() { - fp = NULL; - ness = LittleEndian; - strcpy(dir,"."); + fp = NULL; + ness = LittleEndian; + strcpy(dir,"."); + tileCache = NULL; } // Destructor trpgr_Archive::~trpgr_Archive() { - if (fp) - fclose(fp); - fp = NULL; + 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/%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 (fp) + fclose(fp); + fp = NULL; + if (tileCache) + delete tileCache; + tileCache = NULL; } // Read Header // Run through the rest of the header information bool trpgr_Archive::ReadHeader() { - if (!fp || headerRead) - return false; + int ret; - headerRead = true; + if (!fp || headerRead) + return false; - // Eat some bytes -// char stuff[20]; -// if (fread(stuff,1,20,fp) != 20) return false; + headerRead = true; -// if (fread(stuff,1,sizeof(trpgllong),fp) != sizeof(trpgllong)) 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; - // 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 (fread(data,1,headLen,fp) != (unsigned int)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 - // Set up a parser - // Catch the tables we need for the archive - trpgr_Parser parser; - parser.AddCallback(TRPGHEADER,&header); - parser.AddCallback(TRPGMATTABLE,&materialTable); - parser.AddCallback(TRPGMATTABLE2,&materialTable); // Added 11-14-98 - parser.AddCallback(TRPGTEXTABLE,&texTable); - parser.AddCallback(TRPGMODELTABLE,&modelTable); - parser.AddCallback(TRPGTILETABLE,&tileTable); + // 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; - valid = true; + // 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; - return true; + // 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; + + 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 < 0 ||*/ (int)lod >= numLods) return false; - trpg2iPoint lodSize; - header.GetLodSize(lod,lodSize); - if (/*x < 0 ||*/ (int)x >= lodSize.x || /*y < 0 ||*/ (int)y >= lodSize.y) return false; + // Reality check the address + int32 numLods; + header.GetNumLods(numLods); + if (lod >= numLods) return false; + trpg2iPoint lodSize; + header.GetLodSize(lod,lodSize); + if (x >= lodSize.x || y >= lodSize.y) return false; - // Figure out the file name - // Note: This assumes External tiles - const char *base = tileTable.GetBaseName(); - char filename[1024]; - sprintf(filename,"%s/%s/tile_%d_%d_%d.tpt",dir,base,x,y,lod); + trpgTileTable::TileMode tileMode; + tileTable.GetMode(tileMode); - // 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; - } + 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); - return true; + // 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 tile + if (!tf->Read(&buf,addr.offset)) + return false; + } + + 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; +} +const trpgRangeTable *trpgr_Archive::GetRangeTable() const +{ + return &rangeTable; } trpgEndian trpgr_Archive::GetEndian() const { - return ness; + return ness; } // Utility MBR routine -bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg2dPoint &ll,trpg2dPoint &ur) const +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 < 0 ||*/ (int)x>= maxXY.x || /*y < 0 ||*/ (int)y>= maxXY.y) - return false; + if (!header.isValid()) + return false; + int32 numLod; + header.GetNumLods(numLod); + trpg2iPoint maxXY; + header.GetLodSize(lod,maxXY); + if (x >= maxXY.x || y>= maxXY.y) + return false; - trpg3dPoint origin; - header.GetOrigin(origin); - trpg2dPoint size; - header.GetTileSize(lod,size); + trpg3dPoint origin; + header.GetOrigin(origin); + trpg2dPoint size; + header.GetTileSize(lod,size); - ll.x = origin.x + size.x*x; - ll.y = origin.y + size.y*y; - ur.x = origin.x + size.x*(x+1); - ur.y = origin.y + size.y*(y+1); + ll.x = origin.x + size.x*x; + ll.y = origin.y + size.y*y; + ur.x = origin.x + size.x*(x+1); + ur.y = origin.y + size.y*(y+1); - return true; + // 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; +} + +/* ***************** + Read Image Helper + ***************** + */ + +trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir, + const trpgMatTable &inMatTable,const trpgTexTable &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"); +} + +trpgrImageHelper::~trpgrImageHelper() +{ + 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; + + // Fetch data data + trpgwAppAddress addr; + tex->GetImageAddr(addr); + trpgrAppFile *af = texCache->GetFile(ness,addr.file); + if (!af) + return false; + if (!af->Read(data,addr.offset,size)) + return false; + + return true; +} + +bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,char *data,int32 dataSize) +{ + 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; + + // Fetch data data + trpgwAppAddress addr; + tex->GetImageAddr(addr); + trpgrAppFile *af = texCache->GetFile(ness,addr.file); + if (!af) + return false; + + int level_offset = (const_cast(tex))->MipLevelOffset(miplevel); + if (!af->Read(data,addr.offset+level_offset,dataSize)) + return false; + + return true; +} + + +bool trpgrImageHelper::GetImageInfoForLocalMat(const trpgLocalMaterial *locMat, + const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize) +{ + // Get the base material for the Local Material + int32 matSubTable,matID; + locMat->GetBaseMaterial(matSubTable,matID); + const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID); + if (!mat) return false; + + // 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(); + + *retTex = tex; + *retMat = mat; + return true; +} + +bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize) +{ + if (!locMat->isValid()) return false; + + const trpgMaterial *mat; + const trpgTexture *tex; + int totSize; + if (!GetImageInfoForLocalMat(locMat,&mat,&tex,totSize)) + return false; + + // Determine the type + trpgTexture::ImageMode imageMode; + tex->GetImageMode(imageMode); + switch (imageMode) { + case trpgTexture::Template: + { + // Read the image data out of the Local image (in an archive somewhere) + trpgwAppAddress addr; + locMat->GetAddr(addr); + trpgrAppFile *af = texCache->GetFile(ness,addr.file); + if (!af) return false; + if (!af->Read(data,addr.offset,dataSize)) + return false; + } + break; + case trpgTexture::Global: + // Note: Not dealing with Global textures yet + return false; + break; + default: + // This is not a valid Local Material + return false; + }; + + return true; +} + +bool trpgrImageHelper::GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize) +{ + if (!locMat->isValid()) return false; + + const trpgMaterial *mat; + const trpgTexture *tex; + int totSize; + if (!GetImageInfoForLocalMat(locMat,&mat,&tex,totSize)) + 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; + locMat->GetAddr(addr); + trpgrAppFile *af = texCache->GetFile(ness,addr.file); + if (!af) return false; + + int level_offset = (const_cast(tex))->MipLevelOffset(miplevel); + if (!af->Read(data,addr.offset+level_offset,dataSize)) + return false; + } + break; + case trpgTexture::Global: + // Note: Not dealing with Global textures yet + return false; + break; + default: + // This is not a valid Local Material + return false; + }; + + return true; +} + +bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pathLen) +{ + char name[1024]; + int nameLen=1024; + tex->GetName(name,nameLen); + nameLen = strlen(name); + + if (strlen(dir) + nameLen + 2 > pathLen) + return false; + + sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name); + + return true; } diff --git a/src/osgPlugins/txp/trpage_read.h b/src/osgPlugins/txp/trpage_read.h index 4e54918c1..a28f8a004 100644 --- a/src/osgPlugins/txp/trpage_read.h +++ b/src/osgPlugins/txp/trpage_read.h @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -75,15 +74,73 @@ protected: private: // Note: Just how slow is a map<> anyway? // This usage is self-contained and could be replaced with an array -#if defined(_WIN32) && !defined(__GNUC__) - typedef map tok_map; +#if defined(_WIN32) + typedef std::map tok_map; #else - typedef map > tok_map; + typedef std::map > tok_map; #endif 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. + */ +TX_EXDECL class TX_CLDECL trpgrImageHelper { +public: + 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 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); + + /* 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 the one above, just fetch single mip levels + */ + virtual bool GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize); + + /* Determine the full path of the image in the given + trpgTexture class. + Only useful for External images. + */ + virtual bool GetImagePath(const trpgTexture *,char *,int len); + +protected: + char dir[1024]; + trpgEndian ness; + const trpgMatTable *matTable; + const trpgTexTable *texTable; + + trpgrAppFileCache *texCache; +}; + /* Paging Archive (read version) This just reads the first bits of the file (and the header) and lets you parse from there. @@ -106,13 +163,15 @@ public: 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; - // Utility routine to calculate the MBR of a given point + // Utility routine to calculate the MBR of a given tile virtual bool trpgGetTileMBR(uint32 x,uint32 y,uint32 lod, - trpg2dPoint &ll,trpg2dPoint &ur) const; + trpg3dPoint &ll,trpg3dPoint &ur) const; - trpgEndian GetEndian() const; - char* getDir(){return dir;}; + trpgEndian GetEndian(void) const; + char* getDir(void){return dir;}; protected: bool headerRead; trpgEndian ness; @@ -125,6 +184,10 @@ protected: trpgTexTable texTable; trpgModelTable modelTable; trpgTileTable tileTable; + trpgLightTable lightTable; + trpgRangeTable rangeTable; + + trpgrAppFileCache *tileCache; }; class trpgSceneHelperPush; @@ -149,7 +212,7 @@ protected: virtual bool EndChildren(void *) { return true;}; // List of objects whose children we're working on - vector parents; + std::vector parents; }; #endif diff --git a/src/osgPlugins/txp/trpage_readbuf.cpp b/src/osgPlugins/txp/trpage_readbuf.cpp index 4a5fad8f8..1e5760204 100644 --- a/src/osgPlugins/txp/trpage_readbuf.cpp +++ b/src/osgPlugins/txp/trpage_readbuf.cpp @@ -1,34 +1,32 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ - #include #include #include #include /* 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" @@ -41,243 +39,243 @@ // Basic get functions bool trpgReadBuffer::Get(int32 &ret) { - int32 val; + int32 val; - if (!GetData((char *)&val,sizeof(int32))) return false; - if (ness != cpuNess) - ret = trpg_byteswap_int(val); - else - ret = val; + if (!GetData((char *)&val,sizeof(int32))) return false; + if (ness != cpuNess) + ret = trpg_byteswap_int(val); + else + ret = val; - return true; + return true; } bool trpgReadBuffer::Get(int64 &ret) { - int64 val; + int64 val; - if (!GetData((char *)&val,sizeof(int64))) return false; - if (ness != cpuNess) - ret = trpg_byteswap_llong(val); - else - ret = val; + if (!GetData((char *)&val,sizeof(int64))) return false; + if (ness != cpuNess) + ret = trpg_byteswap_long(val); + else + ret = val; - return true; + return true; } bool trpgReadBuffer::Get(char *ret,int retLen) { - int32 len; + int32 len; - // Get the length first - if (!Get(len)) return false; + // Get the length first + if (!Get(len)) return false; - // Read what we can - int rlen = MIN(len,retLen-1); - if (!GetData(ret,rlen)) return false; - ret[rlen] = 0; + // Read what we can + int rlen = MIN(len,retLen-1); + if (!GetData(ret,rlen)) return false; + ret[rlen] = 0; - // Skip the rest - if (!Skip(rlen-len)) return false; + // Skip the rest + if (!Skip(rlen-len)) return false; - return true; + return true; } bool trpgReadBuffer::Get(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 0) - limits.resize(len-1); + if (len > 0) + limits.resize(len-1); } // Skip To Limit @@ -285,34 +283,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[i]) - return false; + for (int i=0;i 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= len) - return true; + if (pos >= len) + return true; - // Also test the limits - for (unsigned int i=0;i 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 + */ + +trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName) +{ + valid = false; + ness = inNess; + cpuNess = trpg_cpu_byte_order(); + + if (!(fp = fopen(fileName,"rb"))) + return; + + valid = true; +} + +trpgrAppFile::~trpgrAppFile() +{ + if (fp) + fclose(fp); + + 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; + + // 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; + } + + // Byteswap if necessary + if (ness != cpuNess) + trpg_byteswap_int(len); + + if (len < 0) { + valid = false; + return false; + } + + buf->SetLength(len); + char *data = buf->GetDataPtr(); + if (!data) { + valid = false; + return false; + } + + if (fread(data,sizeof(char),len,fp) != len) { + valid = false; + return false; + } + + 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. + */ +bool trpgrAppFile::Read(char *data,int32 offset,int32 dataSize) +{ + if (!valid) return false; + + // Seek to the right place + int result; + if ((result = fseek(fp,offset,SEEK_SET))) { + valid = false; + return false; + } + + // Read the 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); + + if (len < 0) { + valid = false; + return false; + } + // It's all right to read less than the whol data block + if (dataSize > len) + return false; + + // Read the raw data + // Note: What about byte swapping? + if (fread(data,sizeof(char),dataSize,fp) != dataSize) { + valid = false; + return false; + } + + return true; +} + +/* App File Cache + This class manages a group of appendable files with + the same base name and extension. It will keep a certain + number of them open to facilitate caching. + */ + +trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noFiles) +{ + strcpy(baseName,inPre); + strcpy(ext,inExt); + + files.resize(noFiles); + timeCount = 0; +} + +trpgrAppFileCache::~trpgrAppFileCache() +{ + for (unsigned int i=0;i /* 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 -#include +#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= (int)children.size()) - return; - children[id] = NULL; + if (id < 0 || id >= children.size()) + return; + children[id] = NULL; } // Unref all the children (they've probably been moved elsewhere) void trpgReadGroupBase::unRefChildren() { - for (unsigned int i=0;i(&mbr); - trpgMBR kmbr; - // Ask the kids - for (unsigned int i=0;iGetMBR(); - cmbr->Union(kmbr); - } - return *cmbr; - } + if (mbr.isValid()) + return mbr; + else { + // Calculate and cache a new MBR + trpgMBR *cmbr = const_cast(&mbr); + trpgMBR kmbr; + // Ask the kids + for (int i=0;iGetMBR(); + 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(&mbr); + trpgMBR *pmbr = const_cast(&mbr); - int numVert,i; - trpg3dPoint pt; - data.GetNumVertex(numVert); - numVert /= 3; - for (i=0;iAddPoint(pt); - } + int numVert,i; + trpg3dPoint pt; + data.GetNumVertex(numVert); + numVert /= 3; + for (i=0;iAddPoint(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 @@ -469,87 +468,87 @@ 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 when the parser hits a pop. +/* This is called whent he parser hits a pop. We'll want to look on the parent list (in trpgSceneParser) for the parent above the current one. If there isn't one, we'll just stick things in our top group. */ -bool trpgSceneGraphParser::EndChildren(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()); - trpg2dPoint 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; } diff --git a/src/osgPlugins/txp/trpage_scene.h b/src/osgPlugins/txp/trpage_scene.h index b62805bfb..fbb33b6a4 100644 --- a/src/osgPlugins/txp/trpage_scene.h +++ b/src/osgPlugins/txp/trpage_scene.h @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -36,13 +35,13 @@ TX_EXDECL class TX_CLDECL trpgMBR { public: trpgMBR(void); ~trpgMBR(void) { }; - bool isValid() const; - void Reset(); + 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() const; - trpg3dPoint GetUR() 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; @@ -59,10 +58,10 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadNode { public: - virtual ~trpgReadNode() { }; - virtual bool isGroupType() = 0; - virtual int GetType() { return type; } - virtual trpgMBR GetMBR() 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; }; @@ -72,18 +71,18 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadGroupBase : public trpgReadNode { public: - virtual ~trpgReadGroupBase(); + virtual ~trpgReadGroupBase(void); void AddChild(trpgReadNode *); - bool isGroupType() { return true; } - int GetNumChildren() { return children.size(); } + bool isGroupType(void) { return true; } + int GetNumChildren(void) { return children.size(); } trpgReadNode *GetChild(int i) { return children[i]; } - trpgMBR GetMBR() const; + trpgMBR GetMBR(void) const; void unRefChild(int i); - void unRefChildren(); + void unRefChildren(void); protected: trpgMBR mbr; - void DeleteChildren(); - vector children; + void DeleteChildren(void); + std::vector children; }; // Read Geometry @@ -91,11 +90,11 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadGeometry : public trpgReadNode { public: - trpgReadGeometry() { type = TRPG_GEOMETRY; } - ~trpgReadGeometry() { }; - bool isGroupType() { return false; } - trpgGeometry *GetData() { return &data; } - trpgMBR GetMBR() 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; @@ -106,11 +105,11 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadTileHeader : public trpgReadNode { public: - trpgReadTileHeader() { type = TRPGTILEHEADER; } - ~trpgReadTileHeader() { }; - bool isGroupType() { return false; } - trpgTileHeader *GetData() { return &data; } - trpgMBR GetMBR() 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; }; @@ -120,9 +119,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadGroup : public trpgReadGroupBase { public: - trpgReadGroup() { type = TRPG_GROUP; } - ~trpgReadGroup() { }; - trpgGroup *GetData() { return &data; } + trpgReadGroup(void) { type = TRPG_GROUP; } + ~trpgReadGroup(void) { }; + trpgGroup *GetData(void) { return &data; } protected: trpgGroup data; }; @@ -132,9 +131,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadAttach : public trpgReadGroupBase { public: - trpgReadAttach() { type = TRPG_ATTACH; } - ~trpgReadAttach() { }; - trpgAttach *GetData() { return &data; } + trpgReadAttach(void) { type = TRPG_ATTACH; } + ~trpgReadAttach(void) { }; + trpgAttach *GetData(void) { return &data; } protected: trpgAttach data; }; @@ -143,9 +142,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadBillboard : public trpgReadGroupBase { public: - trpgReadBillboard() { type = TRPG_BILLBOARD; } - ~trpgReadBillboard() { }; - trpgBillboard *GetData() { return &data; } + trpgReadBillboard(void) { type = TRPG_BILLBOARD; } + ~trpgReadBillboard(void) { }; + trpgBillboard *GetData(void) { return &data; } protected: trpgBillboard data; }; @@ -154,9 +153,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadLod : public trpgReadGroupBase { public: - trpgReadLod() { type = TRPG_LOD; } - ~trpgReadLod() { }; - trpgLod *GetData() { return &data; } + trpgReadLod(void) { type = TRPG_LOD; } + ~trpgReadLod(void) { }; + trpgLod *GetData(void) { return &data; } protected: trpgLod data; }; @@ -165,9 +164,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadLayer : public trpgReadGroupBase { public: - trpgReadLayer() { type = TRPG_LAYER; } - ~trpgReadLayer() { }; - trpgLayer *GetData() { return &data; } + trpgReadLayer(void) { type = TRPG_LAYER; } + ~trpgReadLayer(void) { }; + trpgLayer *GetData(void) { return &data; } protected: trpgLayer data; }; @@ -176,9 +175,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadTransform : public trpgReadGroupBase { public: - trpgReadTransform() { type = TRPG_TRANSFORM; } - ~trpgReadTransform() { }; - trpgTransform *GetData() { return &data; } + trpgReadTransform(void) { type = TRPG_TRANSFORM; } + ~trpgReadTransform(void) { }; + trpgTransform *GetData(void) { return &data; } protected: trpgTransform data; }; @@ -187,9 +186,9 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadModelRef : public trpgReadGroupBase { public: - trpgReadModelRef() { type = TRPG_MODELREF; } - ~trpgReadModelRef() { }; - trpgModelRef *GetData() { return &data; } + trpgReadModelRef(void) { type = TRPG_MODELREF; } + ~trpgReadModelRef(void) { }; + trpgModelRef *GetData(void) { return &data; } protected: trpgModelRef data; }; @@ -204,21 +203,21 @@ protected: // {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgSceneGraphParser : public trpgSceneParser { public: -#if defined(_WIN32) && !defined(__GNUC__) - typedef map GroupMap; +#if defined(_WIN32) + typedef std::map GroupMap; #else - typedef map > GroupMap; + typedef std::map > GroupMap; #endif - trpgSceneGraphParser(); - ~trpgSceneGraphParser() { }; + trpgSceneGraphParser(void); + virtual ~trpgSceneGraphParser(void) { }; // Call this instead of Parse() // Deleting it is your responsibility trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &); - trpgReadGroupBase *GetCurrTop(); // Get the current parent object - trpgReadTileHeader *GetTileHeaderRef(); + trpgReadGroupBase *GetCurrTop(void); // Get the current parent object + trpgReadTileHeader *GetTileHeaderRef(void); // For use by the helpers only - GroupMap *GetGroupMap(); + GroupMap *GetGroupMap(void); protected: bool StartChildren(void *); bool EndChildren(void *); diff --git a/src/osgPlugins/txp/trpage_swap.cpp b/src/osgPlugins/txp/trpage_swap.cpp index dd541bf1a..3c25dd8f4 100644 --- a/src/osgPlugins/txp/trpage_swap.cpp +++ b/src/osgPlugins/txp/trpage_swap.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -18,15 +17,15 @@ #include /* 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 ) { @@ -39,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 ) { @@ -56,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 ) { @@ -77,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 ) { @@ -106,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; } diff --git a/src/osgPlugins/txp/trpage_swap.h b/src/osgPlugins/txp/trpage_swap.h index 1e2dd4f28..a42e84aaf 100644 --- a/src/osgPlugins/txp/trpage_swap.h +++ b/src/osgPlugins/txp/trpage_swap.h @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -18,7 +17,7 @@ #define trpage_swap_h_ /* trpage_swap.h - Byte swapping utility functions. + Byte swapping utility functions. */ #include "trpage_sys.h" @@ -30,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 ); diff --git a/src/osgPlugins/txp/trpage_sys.h b/src/osgPlugins/txp/trpage_sys.h index 29c22364f..e1a637676 100644 --- a/src/osgPlugins/txp/trpage_sys.h +++ b/src/osgPlugins/txp/trpage_sys.h @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -21,7 +20,15 @@ #ifndef trpage_sys_h_ #define trpage_sys_h_ -#if defined(_WIN32) && !defined(__CYGWIN__) +#ifndef PATHSEPERATOR +#ifdef macintosh +#define PATHSEPERATOR ":" +#else +#define PATHSEPERATOR "/" +#endif +#endif + +#if defined(_WIN32) /* ********************* System Specific Section. This is currently set up for win32. @@ -39,19 +46,10 @@ #define TRPGDELETEFILE(file) DeleteFile((file)) #ifndef int64 - // 64 bit long value. Need this for really big files. -// #ifdef __CYGWIN__ -// typedef long long int64; -// #else - typedef __int64 int64; -// #endif +// 64 bit long value. Need this for really big files. +typedef __int64 int64; #endif -#ifdef __MINGW32__ -#include -#endif - - #else // Unix #include @@ -59,38 +57,8 @@ // Delete a file #define TRPGDELETEFILE(file) remove((file)) -//#ifndef int64 -//typedef long long int64; -//#endif - -#if defined(sgi) && defined(unix) -# include -typedef __int64_t int64; - -#elif defined(sun) && defined(unix) && (defined(SUN551) || defined(SUN56)) -// NOTE: SUN56 and SUN551 is assumed to be defined in our makefiles. -#include -typedef longlong_t int64; - -#elif defined(sun) && defined(unix) -// This should work on SunOS 5.7 and later. -#include -typedef int64_t int64; - -#elif defined(linux) -#include -typedef int64_t int64; -//typedef long long int int64; - -#elif defined(__ghs__) && defined(__LL_Is_64) +#ifndef int64 typedef long long int64; - -#elif defined(__CYGWIN__) -typedef long long int64; -#include - -#else -typedef int int64; // DON'T KNOW WHAT TO DO #endif #endif @@ -118,27 +86,19 @@ typedef double float64; #include #endif -#if defined(WIN32) || defined(_WIN32) || defined(vxw) || (defined(sgi) && defined(_STANDARD_C_PLUS_PLUS)) || (defined(__GNUC__) && (__GNUC__>=2) && (__GNUC_MINOR__>=91)) +#if defined(_WIN32) #include #include -namespace std {} -using namespace std; #else #include #include #endif -//#if defined(_WIN32) -//#include -//#include -//#else -//#include -//#include -//#endif - -//#if defined(_WIN32) // PJM -//using namespace std; -//#endif +#if defined(_WIN32) // PJM +// Had to take this out because of an iostream conflict +// Now referencing everything by std:: +// using namespace std; +#endif // We use long longs for addresses within a paging file typedef int64 trpgllong; diff --git a/src/osgPlugins/txp/trpage_tile.cpp b/src/osgPlugins/txp/trpage_tile.cpp index 4fc5dca69..588ca46a5 100644 --- a/src/osgPlugins/txp/trpage_tile.cpp +++ b/src/osgPlugins/txp/trpage_tile.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,222 +18,229 @@ #include /* 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() { -// numX = numY = numLod = 0; - numLod = 0; - baseName = NULL; - type = External; + Reset(); } // Reset function void trpgTileTable::Reset() { - if (baseName) - delete baseName; -// center.resize(0); -// tiles.resize(0); -// numX = numY; - numLod = 0; - baseName = NULL; - type = External; + mode = External; + lodInfo.resize(0); + valid = true; } // Destructor trpgTileTable::~trpgTileTable() { - Reset(); + valid = false; } // Set functions -void trpgTileTable::SetNumTiles(int nx,int ny) -{ - if (nx <= 0 || ny <= 0) - return; - SetNumTiles(nx,ny,1); -} -void trpgTileTable::SetNumTiles(int nx,int ny,int nl) +void trpgTileTable::SetMode(TileMode inMode) { - if (nx <= 0 || ny <= 0 || nl <= 0 || nl >= numLod) - return; - - lodSizes[nl] = trpg2iPoint(nx,ny); - -// tiles.resize(nx*ny*nl,0); -} -void trpgTileTable::SetTile(int nx,int ny,int nl,trpgDiskRef ref) -{ - if (nx < 0 || nx >= numX || - ny < 0 || ny >= numY || - nl < 0 || nl >= numLod) - return; - - type = Local; - -// tiles[nl*(numX*numY)+ny*numX+nx] = ref; -} -void trpgTileTable::SetTile(int nx,int ny,trpgDiskRef ref) -{ - SetTile(nx,ny,0,ref); -} -void trpgTileTable::SetBaseName(const char *name) -{ - if (baseName) - delete baseName; - - baseName = new char[(name ? strlen(name) : 0)+1]; - strcpy(baseName,name); - type = External; -} -void trpgTileTable::SetCenter(int nx,int ny,int nl,const trpg3dPoint &pt) -{ - if (nx < 0 || nx >= numX || - ny < 0 || ny >= numY || - nl < 0 || nl >= numLod) - return; - -// center[nl*(numX*numY)+ny*numX+nx] = pt; -} -void trpgTileTable::SetCenter(int nx,int ny,const trpg3dPoint &pt) -{ - SetCenter(nx,ny,0,pt); + Reset(); + mode = inMode; } -// Need the basename when writing an archive -const char *trpgTileTable::GetBaseName() const +void trpgTileTable::SetNumLod(int numLod) { - return baseName; + lodInfo.resize(numLod); +} + +void trpgTileTable::SetNumTiles(int nx,int ny,int lod) +{ + if (nx <= 0 || ny <= 0 || lod < 0 || lod >= lodInfo.size()) + return; + + // Got a table we need to maintain + if (mode == Local) { + // If there's a pre-existing table, we need to preserve the entries + LodInfo oldLodInfo = lodInfo[lod]; + + LodInfo &li = lodInfo[lod]; + li.numX = nx; li.numY = ny; + int numTile = li.numX*li.numY; + li.addr.resize(numTile); + li.elev_min.resize(numTile); + li.elev_max.resize(numTile); + + // Copy pre-existing data if it's there + if (oldLodInfo.addr.size() > 0) { + for (int x=0;x= 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; } -// Validity check bool trpgTileTable::isValid() const { -// if (numX == 0 || numY == 0 || numLod == 0) -// return false; + return valid; +} - return true; +// Get methods + +bool trpgTileTable::GetMode(TileMode &outMode) const +{ + if (!isValid()) return false; + + 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 (lod < 0 || lod >= lodInfo.size()) return false; + if (mode != Local) + return false; + const LodInfo &li = lodInfo[lod]; + if (x < 0 || x >= li.numX || y < 0 || y >= li.numY) + return false; + + int loc = y*li.numX + x; + ref = li.addr[loc]; + zmin = li.elev_min[loc]; + zmax = li.elev_max[loc]; + + return true; } // Write tile table bool trpgTileTable::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPGTILETABLE); -#if 0 - numTiles = tiles.size(); - buf.Add(numX); - buf.Add(numY); - buf.Add(numLod); - for (unsigned int i=0;i= numX || y < 0 || y >= numY || - lod < 0 || lod >= numLod) - return false; -// pt = center[lod*(numX*numY)+y*numX+x]; - return true; -} bool trpgTileTable::Read(trpgReadBuffer &buf) { - // trpg3dPoint pt; - char tmpStr[1024]; + valid = false; - try { - type = External; // Note: Read this in -#if 0 - buf.Get(numX); - buf.Get(numY); - buf.Get(numLod); - if (numTiles < 0) throw 1; - for (int i=0;i= (int)matList.size()) - return; - matList[no] = id; + if (no < 0 || no >= matList.size()) + return; + matList[no] = id; } void trpgTileHeader::SetModel(int no,int id) { - if (no < 0 || no >= (int)modelList.size()) - return; - modelList[no] = id; + if (no < 0 || no >= modelList.size()) + return; + modelList[no] = id; } // Set functions void trpgTileHeader::AddMaterial(int id) { - // Look for it first - for (unsigned int i=0;i= locMats.size()) + return false; + + retMat = locMats[id]; + + return true; +} + +const std::vector *trpgTileHeader::GetLocalMaterialList() const +{ + if (!isValid()) return NULL; + + return &locMats; } // Get methods bool trpgTileHeader::GetNumMaterial(int32 &no) const { - if (!isValid()) return false; - no = (int32)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 >= (int32)matList.size()) - return false; - mat = matList[id]; - return true; + if (!isValid() || id < 0 || id >= matList.size()) + return false; + mat = matList[id]; + return true; } bool trpgTileHeader::GetNumModel(int32 &no) const { - if (!isValid()) return false; - no = modelList.size(); - return true; + if (!isValid()) return false; + no = modelList.size(); + return true; } bool trpgTileHeader::GetModel(int32 id,int32 &m) const { - if (!isValid() || id < 0 || id >= (int32)modelList.size()) - return false; - m = modelList[id]; - return true; + if (!isValid() || id < 0 || id >= modelList.size()) + return false; + m = modelList[id]; + return true; } bool trpgTileHeader::GetDate(int32 &d) const { - if (!isValid()) return false; - d = date; - return true; + if (!isValid()) return false; + d = date; + return true; } // Validity check bool trpgTileHeader::isValid() const { - return true; + return true; } // Write to a buffer bool trpgTileHeader::Write(trpgWriteBuffer &buf) { - unsigned int i; + unsigned int i; - if (!isValid()) - return false; + if (!isValid()) + return false; + for (i=0;iAddMaterial(id); - } - break; - case TRPG_TILE_MODELLIST: - buf.Get(no); - if (no < 0) throw 1; - for (i=0;iAddModel(id); - } - break; - case TRPG_TILE_DATE: - buf.Get(date); - head->SetDate(date); - 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;iAddModel(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 *locMats; + locMats = const_cast *> (head->GetLocalMaterialList()); + locMats->resize(numLocMat); + for (i=0;i /* trpage_warchive.cpp - This source file contains the implementations of trpgwArchive and trpgwGeomHelper. - The Write Archive is used to write TerraPage archives. All its important methods - are virtual, so you shouldn't need to modify any of this code. Simply subclass - and override. - The Geometry Helper is a class that's used to sort out polygons and build - trpgGeometry objects, containing triangle strips and fans out of them. The one - contained here is fairly simple, but all its important methods are virtual. So - again, subclass and override if you need to change them. - */ + This source file contains the implementations of trpgwArchive and trpgwGeomHelper. + The Write Archive is used to write TerraPage archives. All its important methods + are virtual, so you shouldn't need to modify any of this code. Simply subclass + and override. + The Geometry Helper is a class that's used to sort out polygons and build + trpgGeometry objects, containing triangle strips and fans out of them. The one + contained here is fairly simple, but all its important methods are virtual. So + again, subclass and override if you need to change them. + */ #include "trpage_geom.h" #include "trpage_write.h" +#include "trpage_compat.h" +#include "trpage_read.h" // Constructor -trpgwArchive::trpgwArchive(trpgEndian inNess) +trpgwArchive::trpgwArchive(trpgEndian inNess,TileMode inTileMode,int inVersion) { - fp = NULL; - // Note: only doing external tiles - tileTable.SetBaseName("."); - strcpy(dir,"."); - ness = inNess; - cpuNess = trpg_cpu_byte_order(); + version = inVersion; + if (version != 1 && version != 2) + throw 1; + fp = NULL; + strcpy(dir,"."); + ness = inNess; + tileMode = inTileMode; + cpuNess = trpg_cpu_byte_order(); + tileFile = NULL; + tileFileCount = 0; + isRegenerate = false; + maxTileFileLen = -1; } -void trpgwArchive::init(trpgEndian inNess) + +// Constructor for regenerate +trpgwArchive::trpgwArchive(char *inDir,char *inFile) { - ness = inNess; + maxTileFileLen = -1; + version = TRPG_VERSION_MAJOR; + fp = NULL; + strcpy(dir,inDir); + cpuNess = trpg_cpu_byte_order(); + tileFile = NULL; + tileFileCount = 0; + isRegenerate = true; + + // Open a Read Archive to get the rest of the info we need + trpgr_Archive *inArch = new trpgr_Archive(); + inArch->SetDirectory(inDir); + if (!inArch->OpenFile(inFile)) { + delete inArch; + throw 1; + } + // Get the header (this is what we need) + if (!inArch->ReadHeader()) { + delete inArch; + throw 1; + } + + ness = inArch->GetEndian(); + + // Copy the header tables + header = *inArch->GetHeader(); + matTable = *inArch->GetMaterialTable(); + texTable = *inArch->GetTexTable(); + modelTable = *inArch->GetModelTable(); + tileTable = *inArch->GetTileTable(); + lightTable = *inArch->GetLightTable(); + rangeTable = *inArch->GetRangeTable(); + + trpgTileTable::TileMode inMode; + tileTable.GetMode(inMode); + tileMode = (inMode == trpgTileTable::Local) ? TileLocal : TileExternal; + + // That's it for the read archive + delete inArch; } // Destructor trpgwArchive::~trpgwArchive() { - if (fp) - fclose(fp); + if (fp) + fclose(fp); + if (tileFile) { + delete tileFile; + tileFile = NULL; + } } // IsValid() // Verifies that our file is open bool trpgwArchive::isValid() const { - if (!fp) - return false; + if (!fp) + return false; - return true; + return true; +} + +// Set the maximum advised size for a tile file + +void trpgwArchive::SetMaxTileFileLength(int max) +{ + maxTileFileLen = max; } /* Set Functions - These just copy tables and the header from the input. - If these aren't set, then empty ones are written. - */ + These just copy tables and the header from the input. + If these aren't set, then empty ones are written. + */ bool trpgwArchive::SetHeader(const trpgHeader &head) { - header = head; - return true; + header = head; + return true; } bool trpgwArchive::SetMaterialTable(const trpgMatTable &mat) { - matTable = mat; - return true; + matTable = mat; + return true; } bool trpgwArchive::SetTextureTable(const trpgTexTable &tex) { - texTable = tex; - return true; + texTable = tex; + return true; } bool trpgwArchive::SetModelTable(const trpgModelTable &models) { - modelTable = models; - return true; + modelTable = models; + return true; +} +bool trpgwArchive::SetLightTable(const trpgLightTable &lights) +{ + lightTable = lights; + return true; +} +bool trpgwArchive::SetRangeTable(const trpgRangeTable &ranges) +{ + rangeTable = ranges; + return true; +} + +/* Get Methods + Used in regenerate. + */ +trpgHeader *trpgwArchive::GetHeader() +{ + return &header; +} +trpgMatTable *trpgwArchive::GetMatTable() +{ + return &matTable; +} +trpgTexTable *trpgwArchive::GetTextureTable() +{ + return &texTable; +} +trpgModelTable *trpgwArchive::GetModelTable() +{ + return &modelTable; +} +trpgLightTable *trpgwArchive::GetLightTable() +{ + return &lightTable; +} +trpgRangeTable *trpgwArchive::GetRangeTable() +{ + return &rangeTable; } // OpenFile // Same as above, only gets a basename as well bool trpgwArchive::OpenFile(const char *in_dir,const char *name) { - char filename[1024]; + char filename[1024]; - strncpy(dir,in_dir,1023); + strncpy(dir,in_dir,1023); - sprintf(filename,"%s/%s",dir,name); + sprintf(filename,"%s" PATHSEPERATOR "%s",dir,name); - if (!(fp = fopen(filename,"wb"))) - return false; + if (!(fp = fopen(filename,"wb"))) + return false; - return true; + return true; } // CloseFile // Close the open file void trpgwArchive::CloseFile() { - if (fp) - fclose(fp); + if (fp) + fclose(fp); - fp = NULL; + fp = NULL; } /* WriteHeader - For now everything is external, so the header is written last. - The order is this: - Header - Material table - Texture References - Model References - [Future: - Tile Address Table - Model Address Table] - */ + For now everything is external, so the header is written last. + The order is this: + Header + Material table + Texture References + Model References + [Future: + Tile Address Table + Model Address Table] + */ bool trpgwArchive::WriteHeader() { - trpgMemWriteBuffer buf(ness); + trpgMemWriteBuffer buf(ness); - if (!isValid()) - return false; - - // Write all the headers into a buffer - if (!header.Write(buf) || - !matTable.Write(buf) || - !texTable.Write(buf) || - !modelTable.Write(buf) || - !tileTable.Write(buf)) + if (!isValid()) return false; - // Write the disk header - int32 magic = TRPG_MAGIC; - if (ness != cpuNess) - magic = trpg_byteswap_int(magic); - if (fwrite(&magic,sizeof(int32),1,fp) != 1) - return false; + if (!header.isValid()) + return false; - // Write the header length - int32 headerSize = buf.length(); - int headLen = headerSize; - if (ness != cpuNess) - headerSize = trpg_byteswap_int(headerSize); - if (fwrite(&headerSize,1,sizeof(int32),fp) != sizeof(int32)) return false; + // This will close the appendable files + if (tileFile) { + delete tileFile; + tileFile = NULL; + } - // Write the buffer - const char *data = buf.getData(); + /* Build a Tile Table + We need to build one from scratch here. However, + we have all the relevant information collected during + the WriteTile calls. + */ + if (tileMode == TileExternal) { + // External tiles are easy + tileTable.SetMode(trpgTileTable::External); + } else { + if (!isRegenerate) { + // Local tiles require more work + tileTable.SetMode(trpgTileTable::Local); + // Set up the sizes + int32 numLod; + header.GetNumLods(numLod); + tileTable.SetNumLod(numLod); + for (unsigned int i=0;iisValid()) + return false; - // Make a new filename - char filename[1024]; - // Note: Windows specific - sprintf(filename,"%s/%s/tile_%d_%d_%d.tpt",dir,base,x,y,lod); - if (!(tfp = fopen(filename,"wb"))) - return false; + // Add another TileFiles entry + tileFiles.resize(tileFiles.size()+1); + tileFiles[tileFiles.size()-1].id = tileFiles.size()-1; - // Write the header first - int len; - const char *data; - if (head) { - data = head->getData(); - len = head->length(); - if (fwrite(data,sizeof(char),len,tfp) != (unsigned int)len) { - fclose(tfp); - return false; - } - } - - // Write the buffer out - data = buf->getData(); - len = buf->length(); - if (fwrite(data,sizeof(char),len,tfp) != (unsigned int)len) { - fclose(tfp); - return false; - } - fclose(tfp); - - // Note: Should be updating the center in the tile table - // Also, last updated date - return true; + return true; } -/* DeleteTile - Delete the given tile. - Note: This is system specific. - */ -bool trpgwArchive::DeleteTile(unsigned int x,unsigned int y,unsigned int lod) +/* Designate Tile File + Close the current tile file (if any) and open one with the + given base name. This is used for regenerate. + */ +bool trpgwArchive::DesignateTileFile(int id) { - if (!isValid()) return false; + if (tileMode != TileLocal) + return false; - const char *base = tileTable.GetBaseName(); - if (!base) return false; + // Close the current tile file + if (tileFile) delete tileFile; - // Note: windows specific - char filename[1024]; - sprintf(filename,"%s\\tile_%d_%d_%d.tpt",base,x,y,lod); - TRPGDELETEFILE(filename); + // Open a named on + char filename[1024]; + sprintf(filename,"%s" PATHSEPERATOR "tileFile_%d.tpf",dir,id); + tileFile = new trpgwAppFile(ness,filename); + if (!tileFile->isValid()) + return false; - return true; + // Add another TileFiles entry + tileFiles.resize(tileFiles.size()+1); + tileFiles[tileFiles.size()-1].id = id; + + return true; +} + +/* WriteTile. + Write the given tile (x,y,lod) in the appropriate mode (Local or External). + The tile header is given separately from the rest of the tile, but they are + appended together to the file. + */ +bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, float zmin, float zmax, + const trpgMemWriteBuffer *head,const trpgMemWriteBuffer *buf) +{ + FILE *tfp=NULL; + + if (!isValid()) + return false; + + // External tiles get their own individual files + if (tileMode == TileExternal) { + // Make a new filename + char filename[1024]; + // Note: Windows specific + sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod); + if (!(tfp = fopen(filename,"wb"))) + return false; + + // Write the header first + int len; + const char *data; + if (head) { + data = head->getData(); + len = head->length(); + if (fwrite(data,sizeof(char),len,tfp) != len) { + fclose(tfp); + return false; + } + } + + // Write the buffer out + data = buf->getData(); + len = buf->length(); + if (fwrite(data,sizeof(char),len,tfp) != len) { + fclose(tfp); + return false; + } + fclose(tfp); + } else { + // Local tiles get appended to a tile file + if (!tileFile) { + if (!IncrementTileFile()) + return false; + } else { + // See if we've exceeded the maximum advised size for a tile file + if (maxTileFileLen > 0 && tileFile->GetLengthWritten() > maxTileFileLen) + if (!IncrementTileFile()) + return false; + } + + int32 pos = tileFile->Pos(); + if (!tileFile->Append(head,buf)) + return false; + // Keep track of the fact that this went here + TileFile &tf = tileFiles[tileFiles.size()-1]; + TileFileEntry te; + te.x = x; te.y = y; te.lod = lod; + te.zmin = zmin; te.zmax = zmax; te.offset = pos; + tf.tiles.push_back(te); + } + + return true; } /* **************** - Geometry Stats - Used by the Geometry Helper - **************** - */ + Geometry Stats + Used by the Geometry Helper + **************** + */ trpgwGeomStats::trpgwGeomStats() { - totalTri = totalStripTri = totalFanTri = totalBagTri = 0; - for (int i=0;i<15;i++) { - stripStat[i] = fanStat[i] = 0; - } - stripGeom = fanGeom = bagGeom = 0; - stateChanges = 0; - numStrip = numFan = 0; - totalQuad = 0; + totalTri = totalStripTri = totalFanTri = totalBagTri = 0; + for (int i=0;i<15;i++) { + stripStat[i] = fanStat[i] = 0; + } + stripGeom = fanGeom = bagGeom = 0; + stateChanges = 0; + numStrip = numFan = 0; + totalQuad = 0; } trpgwGeomStats::~trpgwGeomStats() { } /* **************** - Geometry Helper - Here, since it's used with a write archive. - **************** - */ + Geometry Helper + Here, since it's used with a write archive. + **************** + */ trpgwGeomHelper::trpgwGeomHelper() { - buf = NULL; - mode = trpgGeometry::Triangles; + buf = NULL; + mode = trpgGeometry::Triangles; } trpgwGeomHelper::~trpgwGeomHelper() { } void trpgwGeomHelper::SetMode(int m) { - if (m == trpgGeometry::Triangles || m == trpgGeometry::Quads) - mode = m; + if (m == trpgGeometry::Triangles || m == trpgGeometry::Quads) + mode = m; } trpgwGeomHelper::trpgwGeomHelper(trpgWriteBuffer *ibuf, int dtype) { - init(ibuf,dtype); + init(ibuf,dtype); } void trpgwGeomHelper::init(trpgWriteBuffer *ibuf,int dtype) { - buf = ibuf; - dataType = dtype; + buf = ibuf; + dataType = dtype; + zmin = 1e12; + zmax = -1e12; } // Reset back to a clean state (except for the buffer) void trpgwGeomHelper::Reset() { - ResetTri(); - ResetPolygon(); + ResetTri(); + ResetPolygon(); + zmin = 1e12; + zmax = -1e12; } // Reset triangle arrays (usually after a flush) void trpgwGeomHelper::ResetTri() { - strips.Reset(); - fans.Reset(); - bags.Reset(); + strips.Reset(); + fans.Reset(); + bags.Reset(); - tex.resize(0); - norm.resize(0); - vert.resize(0); + tex.resize(0); + norm.resize(0); + vert.resize(0); } // Start a polygon definition void trpgwGeomHelper::StartPolygon() { - ResetPolygon(); + ResetPolygon(); } // Finish a polygon definition void trpgwGeomHelper::EndPolygon() { - // See if we can add it to the current triangle arrays - if (vert.size() && (matTri != matPoly)) { - // Couldn't flush geometry and move on - FlushGeom(); - } + // See if we can add it to the current triangle arrays + if (vert.size() && (matTri != matPoly)) { + // Couldn't flush geometry and move on + FlushGeom(); + } - // Turn the polygon into triangles - // Note: Only dealing with convex here - matTri = matPoly; + // Turn the polygon into triangles + // Note: Only dealing with convex here + matTri = matPoly; - switch (mode) { - case trpgGeometry::Triangles: - { - int num = polyVert.size() - 2; - int id1,id2; - for (int i=0;i 1) { - id1 = i+2; id2 = i+1; - } + id1 = i+1; + id2 = i+2; + if (num > 1) { + id1 = i+2; id2 = i+1; + } #else - id1 = i+1; - id2 = i+2; + id1 = i+1; + id2 = i+2; #endif - // Define the triangle - vert.push_back(polyVert[0]); - vert.push_back(polyVert[id1]); - vert.push_back(polyVert[id2]); + // Define the triangle + vert.push_back(polyVert[0]); + vert.push_back(polyVert[id1]); + vert.push_back(polyVert[id2]); - norm.push_back(polyNorm[0]); - norm.push_back(polyNorm[id1]); - norm.push_back(polyNorm[id2]); + norm.push_back(polyNorm[0]); + norm.push_back(polyNorm[id1]); + norm.push_back(polyNorm[id2]); - tex.push_back(polyTex[0]); - tex.push_back(polyTex[id1]); - tex.push_back(polyTex[id2]); - } - } - break; - case trpgGeometry::Quads: - { - int num = polyVert.size(); - if (polyVert.size() == 4) { - for (int i=0;iGetEndian() != trpg_cpu_byte_order()) @@ -430,222 +663,381 @@ void trpgwGeomHelper::AddVertex(trpg3dPoint &pt) tmpVert.x = trpg_byteswap_8bytes_to_double ((char *)&pt.x); tmpVert.y = trpg_byteswap_8bytes_to_double ((char *)&pt.y); tmpVert.z = trpg_byteswap_8bytes_to_double ((char *)&pt.z); - polyVert.push_back(tmpVert); + polyVert.push_back(tmpVert); } else #endif - polyVert.push_back(pt); + polyVert.push_back(pt); + + // Update min/max + zmin = MIN(pt.z,zmin); + zmax = MAX(pt.z,zmax); } // Flush the current set of geometry and move on void trpgwGeomHelper::FlushGeom() { - bool hadGeom = false; + bool hadGeom = false; - switch (mode) { - case trpgGeometry::Triangles: - { - Optimize(); + switch (mode) { + case trpgGeometry::Triangles: + { + Optimize(); - // Write only if we've got something - int numPrim; - if (strips.GetNumPrims(numPrim) && numPrim) { - strips.Write(*buf); - stats.stripGeom++; - hadGeom = true; - } - if (fans.GetNumPrims(numPrim) && numPrim) { - fans.Write(*buf); - stats.fanGeom++; - hadGeom = true; - } - if (bags.GetNumPrims(numPrim) && numPrim) { - bags.Write(*buf); - stats.bagGeom++; - hadGeom = true; - } - } - break; - case trpgGeometry::Quads: - { - int numVert = vert.size(); - // Make sure we've got quads - if (numVert % 4 == 0) { - int dtype = (dataType == UseDouble ? trpgGeometry::DoubleData : trpgGeometry::FloatData); - // Just dump the quads into single geometry node - trpgGeometry quads; - quads.SetPrimType(trpgGeometry::Quads); - quads.AddTexCoords(trpgGeometry::PerVertex); - for (int i=0;iFindAddTexture(tex); + + return (texID != -1); +} + +void trpgwImageHelper::SetMaxTexFileLength(int len) +{ + maxTexFileLen = len; +} + +bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY, + bool isMipmap,char *data,int &texID) +{ + // Set up the basic texture + trpgTexture tex; + tex.SetName(name); + tex.SetImageMode(trpgTexture::Local); + tex.SetImageType(type); + tex.SetImageSize(trpg2iPoint(sizeX,sizeY)); + tex.SetIsMipmap(isMipmap); + + // Write the image out to disk + trpgwAppAddress addr; + if (!WriteToArchive(tex,data,addr)) + return false; + + // Now add the specifics to the texture table + tex.SetImageAddr(addr); + texID = texTable->AddTexture(tex); + + return true; +} + +bool trpgwImageHelper::AddTileLocal(char *name,trpgTexture::ImageType type, + int sizeX,int sizeY,bool isMipmap,char *data,int &texID,trpgwAppAddress &addr) +{ + // Set up the texture template and add to the table + trpgTexture tex; + tex.SetName(name); + tex.SetImageMode(trpgTexture::Template); + tex.SetImageType(type); + tex.SetImageSize(trpg2iPoint(sizeX,sizeY)); + tex.SetIsMipmap(isMipmap); + texID = texTable->FindAddTexture(tex); + + // Write the specific data out to an archive (return the address) + if (!WriteToArchive(tex,data,addr)) + return false; + + return true; +} + +/* Increment Texture File. + Close the current texture file (if any) and open the next one. + */ +bool trpgwImageHelper::IncrementTextureFile() +{ + // Closes the current texture file + if (texFile) delete texFile; + texFile = NULL; + + // Open the next one + char filename[1024]; + sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,texFileIDs.size()); + texFile = new trpgwAppFile(ness,filename); + if (!texFile->isValid()) + return false; + + texFileIDs.push_back(texFileIDs.size()); + + return true; +} + +/* Designate Texture File + Close the curren texture file (if any) and open one with the given + base name. + */ +bool trpgwImageHelper::DesignateTextureFile(int id) +{ + // Close the current texture file + if (texFile) delete texFile; + texFile = NULL; + + // Open one with the given base name + char filename[1024]; + sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,id); + texFile = new trpgwAppFile(ness,filename); + if (!texFile->isValid()) + return false; + + texFileIDs.push_back(id); + + return true; +} + +/* Write To Archive. + Write the given image data out to an appropriate archive and + return the address. This is used for Local and Tile Local textures. + */ +bool trpgwImageHelper::WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr) +{ + trpg2iPoint size; + tex.GetImageSize(size); + int32 depth; + tex.GetImageDepth(depth); + + // Get a usable texture archive file + if (!texFile) { + if (!IncrementTextureFile()) + return false; + } else { + // Deal with maximum advised size for texture archive + if (maxTexFileLen > 0 && texFile->GetLengthWritten() > maxTexFileLen) { + if (!IncrementTextureFile()) + return false; + } + } + + // Get the current address + addr.file = texFileIDs[texFileIDs.size()-1]; + addr.offset = texFile->Pos(); + + // Write the data out to the archive. + int totSize = tex.CalcTotalSize(); + if (!texFile->Append(data,totSize)) + return false; + + return true; } diff --git a/src/osgPlugins/txp/trpage_write.h b/src/osgPlugins/txp/trpage_write.h index db7199d14..8ca1f8397 100644 --- a/src/osgPlugins/txp/trpage_write.h +++ b/src/osgPlugins/txp/trpage_write.h @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,173 +18,283 @@ #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++; } + // Helper functions + inline void AddStripStat(int val) { stripStat[MIN(14,val)]++; totalStripTri += val; totalTri += val; numStrip++;} + inline void AddFanStat(int val) { fanStat[MIN(14,val)]++; totalFanTri += val; totalTri += val; numFan++;} + inline void AddBagStat(int val) { totalBagTri += val; totalTri += val;} + inline void AddQuadStat(int val) { totalQuad++; } }; /* Geometry Helper - Collects up geometry and tries to form triangle strips, fans, - and groups of triangles. - Right now this looks for a very careful ordering. If that ordering - isn't there you won't get useful tristrips or fans. You can, however - use this class as a starting point and build something more akin - to the geometry builder in Performer. - {group:Archive Writing} + Collects up geometry and tries to form triangle strips, fans, + and groups of triangles. + Right now this looks for a very careful ordering. If that ordering + isn't there you won't get useful tristrips or fans. You can, however + use this class as a starting point and build something more akin + to the geometry builder in Performer. + {group:Archive Writing} */ TX_EXDECL class TX_CLDECL trpgwGeomHelper { public: - trpgwGeomHelper(void); - virtual ~trpgwGeomHelper(void); - enum {UseDouble,UseFloat}; - trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble); - void init(trpgWriteBuffer *,int dataType=UseDouble); - virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default) - virtual void Reset(); - // Start/End polygon definition - virtual void StartPolygon(); - virtual void EndPolygon(); - virtual void ResetPolygon(); // If you change your mind about the current poly - // Set the current state - // Note: Currently you *must* set all of these - virtual void SetColor(trpgColor &); - virtual void SetTexCoord(trpg2dPoint &); - virtual void SetNormal(trpg3dPoint &); - virtual void SetMaterial(int32); - // Pull the state info together and add a vertex - virtual void AddVertex(trpg3dPoint &); + trpgwGeomHelper(void); + virtual ~trpgwGeomHelper(void); + enum {UseDouble,UseFloat}; + trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble); + void init(trpgWriteBuffer *,int dataType=UseDouble); + virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default) + virtual void Reset(void); + // Start/End polygon definition + virtual void StartPolygon(void); + virtual void EndPolygon(void); + virtual void ResetPolygon(void); // If you change your mind about the current poly + // Set the current state + // Note: Currently you *must* set all of these + virtual void SetColor(trpgColor &); + virtual void SetTexCoord(trpg2dPoint &); + virtual void SetNormal(trpg3dPoint &); + virtual void SetMaterial(int32); + // Pull the state info together and add a vertex + virtual void AddVertex(trpg3dPoint &); - // Dump whatever we're doing and move on - virtual void FlushGeom(); + // Dump whatever we're doing and move on + virtual void FlushGeom(void); - // Get statistics for whatever we built - trpgwGeomStats *GetStats() { return &stats; } + // 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; } 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(); + /* 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(); + // Reset Triangle arrays + virtual void ResetTri(void); - // Collections of geometry - trpgGeometry strips,fans,bags; + // Collections of geometry + trpgGeometry strips,fans,bags; - // Temporary data arrays for triangles/quads - int32 matTri; - vector tex; - vector norm,vert; - // Data arrays for a polygon - int32 matPoly; - vector polyTex; - vector polyNorm,polyVert; - // Single points - trpg2dPoint tmpTex; - trpg3dPoint tmpNorm; - trpgColor tmpCol; + // Temporary data arrays for triangles/quads + int32 matTri; + std::vector tex; + std::vector norm,vert; + // Data arrays for a polygon + int32 matPoly; + std::vector polyTex; + std::vector polyNorm,polyVert; + // Single points + 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; +}; + +/* 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). + */ +TX_EXDECL class TX_CLDECL trpgwImageHelper { +public: + trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &); + virtual ~trpgwImageHelper(void); + + // Adds an entry to the texture table for an external texture + virtual bool AddExternal(char *name,int &texID); + + /* Adds an entry to the texture table for 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); + + /* 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); + + /* 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); + + /* Close the current texture file and go on to one with the + given base name. This is used for regenerate. + */ + virtual bool DesignateTextureFile(int); + +protected: + // 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 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: - trpgwArchive(trpgEndian ness=LittleEndian); - void init(trpgEndian); - virtual ~trpgwArchive(void); + // Tiles can be stored as individual files (External) or grouped together (Local) + typedef enum {TileLocal,TileExternal} TileMode; - // 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 &); + // Add data to an existing archive + trpgwArchive(char *baseDir,char *name); + // Start an archive from scratch. + trpgwArchive(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int version=2); + virtual ~trpgwArchive(void); - // Note: For now, everything is external -// enum {Local,External}; -// virtual bool SetModelMode(int); -// virtual bool SetTileMode(int); + // 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); - // Write functions. - // For now, the header is written last. - virtual bool OpenFile(const char *,const char *); - virtual void CloseFile(void); -// virtual bool OpenFile(const char *); - virtual bool WriteHeader(void); - virtual bool WriteTile(unsigned int,unsigned int,unsigned int,const trpgMemWriteBuffer *,const trpgMemWriteBuffer *); - virtual bool DeleteTile(unsigned int,unsigned int,unsigned int); -// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &); + // 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 &); - bool isValid(void) const; - char* getDir(){return dir;}; + // 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 bool IncrementTileFile(void); + virtual bool DesignateTileFile(int); + + // Write functions. + // For now, the header is written last. + + virtual bool OpenFile(const char *,const char *); + virtual void CloseFile(void); + virtual bool WriteHeader(void); + virtual bool WriteTile(unsigned int,unsigned int,unsigned int,float zmin,float zmax, + const trpgMemWriteBuffer *,const trpgMemWriteBuffer *); +// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &); + + bool isValid(void) const; + char* getDir(void){return dir;}; protected: - trpgEndian ness,cpuNess; - // Fed in from the outside - char dir[1024]; // Directory where we're doing all this - trpgHeader header; - trpgMatTable matTable; - trpgTexTable texTable; - trpgModelTable modelTable; + // Set if we're adding to an existing archive + bool isRegenerate; - // Used by this class only - trpgTileTable tileTable; -// int modelMode,tileMode; - FILE *fp; + // Used to keep track of which tiles are in which file + class TileFileEntry { + public: + int x,y,lod; // Identifying info for tile + float zmin,zmax; + uint32 offset; // Offset into file + }; + class TileFile { + public: + int id; + std::vector tiles; + }; + + trpgEndian ness,cpuNess; + int version; + // Fed in from the outside + char dir[1024]; // Directory where we're doing all this + + // These are passed in + + trpgHeader header; + trpgMatTable matTable; + trpgTexTable texTable; + trpgModelTable modelTable; + trpgLightTable lightTable; + trpgRangeTable rangeTable; + + trpgTileTable tileTable; + + int numX,numY,numLod; + TileMode tileMode; + + trpgwAppFile *tileFile; + int tileFileCount; + + std::vector tileFiles; + + int maxTileFileLen; + + FILE *fp; }; #endif diff --git a/src/osgPlugins/txp/trpage_writebuf.cpp b/src/osgPlugins/txp/trpage_writebuf.cpp index 6f6e46b14..76b184c05 100644 --- a/src/osgPlugins/txp/trpage_writebuf.cpp +++ b/src/osgPlugins/txp/trpage_writebuf.cpp @@ -1,16 +1,15 @@ /* ************************ Copyright Terrain Experts Inc. Terrain Experts Inc (TERREX) reserves all rights to this source code - unless otherwise specified in writing by the Chief Operating Officer - of TERREX. + unless otherwise specified in writing by the President of TERREX. This copyright may be updated in the future, in which case that version supercedes this one. ------------------- Terrex Experts Inc. - 84 West Santa Clara St., Suite 380 - San Jose, CA 95113 + 4400 East Broadway #314 + Tucson, AZ 85711 info@terrex.com - Tel: (408) 293-9977 + Tel: (520) 323-7990 ************************ */ @@ -19,16 +18,16 @@ #include /* 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" @@ -40,152 +39,152 @@ // Constructor trpgMemWriteBuffer::trpgMemWriteBuffer(trpgEndian in_ness) { - ness = in_ness; - cpuNess = trpg_cpu_byte_order(); - data = NULL; - curLen = totLen = 0; + ness = in_ness; + cpuNess = trpg_cpu_byte_order(); + data = NULL; + curLen = totLen = 0; } // Destructor trpgMemWriteBuffer::~trpgMemWriteBuffer() { - if (data) - delete data; - data = NULL; + if (data) + delete [] data; + data = NULL; } /* Length() - Return the length of the given buffer. - */ + Return the length of the given buffer. + */ int trpgMemWriteBuffer::length() const { - return curLen; + return curLen; } /* getData() - Return a pointer to the memory buffer. - */ + Return a pointer to the memory buffer. + */ const char *trpgMemWriteBuffer::getData() const { - return data; + return data; } /* Length() - Set the maximum buffer length. - */ + Set the maximum buffer length. + */ void trpgMemWriteBuffer::setLength(unsigned int len) { - if ((int)len > totLen) { - char *old_data = data; - int oldLen = totLen; - totLen = 2*len; - data = new char[totLen]; + if ((int)len > totLen) { + char *old_data = data; + int oldLen = totLen; + totLen = 2*len; + data = new char[totLen]; - if (old_data) { - memcpy(data,old_data,oldLen); - delete old_data; - } - } + if (old_data) { + memcpy(data,old_data,oldLen); + delete [] old_data; + } + } } /* append() - Append the given data to our buffer. - */ + Append the given data to our buffer. + */ void trpgMemWriteBuffer::append(unsigned int len,const char *val) { - if (len == 0) return; - setLength(curLen+len); - memcpy(&data[curLen],val,len); - curLen += len; + if (len == 0) return; + setLength(curLen+len); + memcpy(&data[curLen],val,len); + curLen += len; } /* set() - Set a specific portion of the buffer to a given value. - */ + Set a specific portion of the buffer to a given value. + */ void trpgMemWriteBuffer::set(unsigned int pos,unsigned int len,const char *val) { - if (len == 0) return; - if (pos+len > (unsigned int)curLen) return; + if (len == 0) return; + if (pos+len > (unsigned int)curLen) return; - memcpy(&data[pos],val,len); + memcpy(&data[pos],val,len); } /* --- replacement virtual functions --- */ /* Reset() - Drop whatever's being stored. - */ + Drop whatever's being stored. + */ void trpgMemWriteBuffer::Reset() { - curLen = 0; + curLen = 0; } // Add(Int32) void trpgMemWriteBuffer::Add(int32 val) { - if (ness != cpuNess) - val = trpg_byteswap_int(val); - append(sizeof(int32),(const char *)&val); + if (ness != cpuNess) + val = trpg_byteswap_int(val); + append(sizeof(int32),(const char *)&val); } // Add(int64) void trpgMemWriteBuffer::Add(int64 val) { - if (ness != cpuNess) - val = trpg_byteswap_llong(val); - append(sizeof(int64),(const char *)&val); + if (ness != cpuNess) + val = trpg_byteswap_long(val); + append(sizeof(int64),(const char *)&val); } // Add(string) // [len] [value...] void trpgMemWriteBuffer::Add(const char *val) { - int32 len = (val ? strlen(val) : 0),vlen = len; - if (ness != cpuNess) - vlen = trpg_byteswap_int(vlen); - append(sizeof(int32),(const char *)&len); - 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(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 @@ -193,94 +192,200 @@ 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); } /* 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. + */ + +trpgwAppFile::trpgwAppFile(trpgEndian inNess,const char *fileName) +{ + valid = false; + ness = inNess; + cpuNess = trpg_cpu_byte_order(); + + if (!(fp = fopen(fileName,"wb"))) + return; + + lengthSoFar = 0; + valid = true; +} + +trpgwAppFile::~trpgwAppFile() +{ + if (fp) + fclose(fp); + valid = false; +} + +// Return the amount of data written so far (in total) +int trpgwAppFile::GetLengthWritten() +{ + return lengthSoFar; +} + +// Append the given buffer to our appendable file +bool trpgwAppFile::Append(const trpgMemWriteBuffer *buf1,const trpgMemWriteBuffer *buf2) +{ + if (!isValid()) return false; + + // 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 data out + const char *data = buf1->getData(); + int len = buf1->length(); + if (fwrite(data,sizeof(char),len,fp) != len) { + valid = false; + return false; + } + if (buf2) { + data = buf2->getData(); + len = buf2->length(); + if (fwrite(data,sizeof(char),len,fp) != len) { + valid = false; + return false; + } + } + + lengthSoFar += totLen; + + return true; +} + +// Append the given raw data to our appendable file +bool trpgwAppFile::Append(const char *data,int size) +{ + if (!isValid()) 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) != size) { + valid = false; + return false; + } + + lengthSoFar += size; + + 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); + + return pos; +} + +// Validity check +bool trpgwAppFile::isValid() const +{ + return valid; }