From 261f4a3b1c38b577f051a8b7c60a7cd4c7b7ff8e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 27 Jun 2006 10:07:42 +0000 Subject: [PATCH] From Terrex and Andrew Sampsom and Don Tidrow and Robert Osfield, email comments from Andew Sampson, "I've contacted Terrex, and obtained the 2.2 version of their trpage library. The library included a fork of OSG 0.9.8's txp plugin, modified to load 2.1+ txp DBs. I've done the work of incorporating the changes made to OSG's txp plugin since 0.9.8 into Terrex's fork. The forked version is now up-to-date with the changes made to OSG 0.9.9 and 1.0. Terrex made a lot of changes (especially differences in whitespace), so the diff between the forked version and OSG 1.0's txp plugin is yucky. I did my best, but keep in mind that this is the result of a 4-way merge (kinda... terrex-0.9.8, stock-0.9.8, stock-0.9.9, stock-1.0). I really want to see this forked version merged back into the main OSG branch. The new features offered by this version of the plugin (2.1+ support, variable LOD support, bug fixes) are worth the trouble." -- Don Tidrow then took this code and added his work. -- Robert Osfield then fixed all the warnings that abound in the trpage code base. --- src/osgPlugins/txp/ReaderWriterTXP.cpp | 669 ++++- src/osgPlugins/txp/ReaderWriterTXP.h | 8 +- src/osgPlugins/txp/TXPArchive.cpp | 503 ++-- src/osgPlugins/txp/TXPArchive.h | 307 ++- src/osgPlugins/txp/TXPIO.cpp | 9 +- src/osgPlugins/txp/TXPNode.cpp | 73 +- src/osgPlugins/txp/TXPNode.h | 30 +- src/osgPlugins/txp/TXPPagedLOD.cpp | 12 +- src/osgPlugins/txp/TXPPagedLOD.h | 1 + src/osgPlugins/txp/TXPParser.cpp | 739 +++--- src/osgPlugins/txp/TXPParser.h | 116 +- src/osgPlugins/txp/TXPSeamLOD.cpp | 1 + src/osgPlugins/txp/TXPSeamLOD.h | 4 + src/osgPlugins/txp/TileMapper.cpp | 100 +- src/osgPlugins/txp/TileMapper.h | 14 +- src/osgPlugins/txp/trdll.h | 4 +- src/osgPlugins/txp/trpage_basic.cpp | 18 +- src/osgPlugins/txp/trpage_compat.cpp | 223 +- src/osgPlugins/txp/trpage_compat.h | 22 +- src/osgPlugins/txp/trpage_geom.cpp | 957 ++++--- src/osgPlugins/txp/trpage_geom.h | 3255 +++++++++++++----------- src/osgPlugins/txp/trpage_header.cpp | 364 +-- src/osgPlugins/txp/trpage_io.h | 827 +++--- src/osgPlugins/txp/trpage_label.cpp | 245 +- src/osgPlugins/txp/trpage_light.cpp | 1080 ++++---- src/osgPlugins/txp/trpage_main.cpp | 6 +- src/osgPlugins/txp/trpage_managers.cpp | 783 ++++-- src/osgPlugins/txp/trpage_managers.h | 514 ++-- src/osgPlugins/txp/trpage_material.cpp | 1358 +++++----- src/osgPlugins/txp/trpage_model.cpp | 481 ++-- src/osgPlugins/txp/trpage_nodes.cpp | 456 ++-- src/osgPlugins/txp/trpage_parse.cpp | 230 +- src/osgPlugins/txp/trpage_pparse.cpp | 550 ++-- src/osgPlugins/txp/trpage_print.cpp | 356 ++- src/osgPlugins/txp/trpage_print.h | 91 +- src/osgPlugins/txp/trpage_range.cpp | 364 +-- src/osgPlugins/txp/trpage_rarchive.cpp | 503 +++- src/osgPlugins/txp/trpage_read.h | 179 +- src/osgPlugins/txp/trpage_readbuf.cpp | 320 ++- src/osgPlugins/txp/trpage_scene.cpp | 719 +++--- src/osgPlugins/txp/trpage_scene.h | 257 +- src/osgPlugins/txp/trpage_swap.cpp | 102 +- src/osgPlugins/txp/trpage_swap.h | 6 +- src/osgPlugins/txp/trpage_sys.h | 24 +- src/osgPlugins/txp/trpage_tile.cpp | 636 +++-- src/osgPlugins/txp/trpage_util.cpp | 5 +- src/osgPlugins/txp/trpage_util.h | 8 +- src/osgPlugins/txp/trpage_warchive.cpp | 1088 ++++---- src/osgPlugins/txp/trpage_write.h | 485 ++-- src/osgPlugins/txp/trpage_writebuf.cpp | 410 +-- 50 files changed, 11399 insertions(+), 8113 deletions(-) diff --git a/src/osgPlugins/txp/ReaderWriterTXP.cpp b/src/osgPlugins/txp/ReaderWriterTXP.cpp index 4d9d24a93..f125ef803 100644 --- a/src/osgPlugins/txp/ReaderWriterTXP.cpp +++ b/src/osgPlugins/txp/ReaderWriterTXP.cpp @@ -3,9 +3,12 @@ #include #include #include +#include #include #include +#include #include +#include #include "ReaderWriterTXP.h" #include "TXPNode.h" @@ -16,6 +19,13 @@ #define ReaderWriterTXPERROR(s) osg::notify(osg::NOTICE) << "txp::ReaderWriterTXP::" << (s) << " error: " + + +namespace +{ + char gbuf[2048]; +} + using namespace txp; int ReaderWriterTXP::_archiveId = 0; @@ -29,7 +39,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin if (strncmp(name.c_str(),"archive",7)==0) { std::string fileName = osgDB::findDataFile( file, options ); - if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + if ( fileName.empty() ) + return ReadResult::FILE_NOT_FOUND; osg::ref_ptr txpNode = new TXPNode; txpNode->setArchiveName(fileName); @@ -45,7 +56,8 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin { int id = _archiveId++; archive->setId(id); - txpNode->setArchive(getArchive(id,osgDB::getFilePath(fileName))); +// txpNode->setArchive(getArchive(id,osgDB::getFilePath(fileName))); + getArchive(id,osgDB::getFilePath(fileName)); } return txpNode.get(); } @@ -56,35 +68,92 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin } // We load tileLOD_XxY_ID.txp - if (strncmp(name.c_str(),"tile",4)==0) + else if (strncmp(name.c_str(),"tile",4)==0) { int x,y,lod; unsigned int id; sscanf(name.c_str(),"tile%d_%dx%d_%d",&lod,&x,&y,&id); TXPArchive* archive = getArchive(id,osgDB::getFilePath(file)); + // The way this is done a 'tile' should only be created for lod 0 only, + // something is wrong if this is no the case + if(lod != 0) + { + ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "paged 'tile' should be at lod 0" << std::endl; + return ReadResult::ERROR_IN_READING_FILE; + } + + trpgEndian endian = archive->GetEndian(); + archive->ReadSubArchive( 0, 0, endian); + archive->ReadSubArchive( y, x, endian); + +// std::cout << "Attempted " << x << " " << y << std::endl; + TXPArchive::TileInfo info; if (!archive->getTileInfo(x,y,lod,info)) return ReadResult::ERROR_IN_READING_FILE; - osg::ref_ptr tileContent = getTileContent(info,x,y,lod,archive); + std::vector childrenLoc; + osg::ref_ptr tileContent = getTileContent(info,x,y,lod,archive, childrenLoc); tileContent->setName("TileContent"); + bool asChildren = false; + std::string childrenInfoStr; + int numLods = archive->getNumLODs(); + + int majorVersion, minorVersion; + archive->GetVersion(majorVersion, minorVersion); + if(majorVersion ==2 && minorVersion >=1) + { + // Version 2.1 and over + // The tile table only contains lod 0 and the children + // info are stored in its parent. SO if we do not want + // to be forced to reparse the parent we need to save that + // info. For now we just add it to the node name + + if(childrenLoc.size() > 0) + { + asChildren = true; + createChildrenLocationString(childrenLoc, childrenInfoStr); + } + } + else + { if (lod < (numLods-1)) + asChildren = true; + } + + if (asChildren) { char pagedLODfile[1024]; - sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp", - archive->getDir(), - lod, - x, - y, - archive->getId() - ); + sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d", + archive->getDir(), + lod, + x, + y, + archive->getId()); + + strcat(pagedLODfile, childrenInfoStr.c_str()); + strcat(pagedLODfile, ".txp"); + + + // there are tile sets which do not maintain the z extents in + // the tile table. This attempt to address the issue by using + // the geometry bounding sphere. The downside is that this is + // not coupled to the generation and may result in runtime cracks + if (info.center.z() == 0) + { + osg::BoundingSphere bSphere = tileContent->getBound(); + + info.center.z() = bSphere.center().z(); + info.radius = bSphere.radius(); + } + osg::ref_ptr pagedLOD = new TXPPagedLOD; - // not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. + // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); pagedLOD->setFileName(1,pagedLODfile); pagedLOD->setRange(1,0,info.minRange); @@ -110,111 +179,379 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin return tileContent.get(); } - // We load subtilesLOD_XxY_ID.txp - if (strncmp(name.c_str(),"sub",3)==0) + + // For 2.0 and lower we load subtilesLOD_XxY_ID.txp + // For 2.1 and over we load subtilesLOD_XxY_ID_NBCHILD_{X_Y_FID_FOFFSET_ZMIN_ZMAX_X_Y_ADDR ....}.txp + else if (strncmp(name.c_str(),"sub",3)==0) { int x,y,lod; unsigned int id; sscanf(name.c_str(),"subtiles%d_%dx%d_%d",&lod,&x,&y,&id); TXPArchive* archive = getArchive(id,osgDB::getFilePath(file)); + int majorVersion, minorVersion; + archive->GetVersion(majorVersion, minorVersion); + + std::vector childrenLoc; + osg::ref_ptr subtiles = new osg::Group; int numLods = archive->getNumLODs(); - int sizeX, sizeY; - archive->getLODSize(lod+1,sizeX,sizeY); - const trpgHeader* header = archive->GetHeader(); - trpgHeader::trpgTileType tileType; - header->GetTileOriginType(tileType); - - TXPArchive::TileInfo parentInfo; - archive->getTileInfo(x,y,lod,parentInfo); - - for (int ix = 0; ix < 2; ix++) + if(majorVersion == 2 && minorVersion >= 1) { - for (int iy = 0; iy < 2; iy++) + int nbChild; + + sscanf(name.c_str(),"subtiles%d_%dx%d_%d_%d",&lod,&x,&y,&id, &nbChild); + std::vector locs; + bool status = true; + status = extractChildrenLocations(name, lod, locs, nbChild); + if(majorVersion >= TRPG_NOMERGE_VERSION_MAJOR && minorVersion >=TRPG_NOMERGE_VERSION_MINOR && archive->GetHeader()->GetIsMaster()) + { + for(int idx=0;idxgetTileInfo(tileX,tileY,tileLOD,info)) - continue; + const trpgHeader* header = archive->GetHeader(); + trpgHeader::trpgTileType tileType; + header->GetTileOriginType(tileType); - osg::ref_ptr tileContent = getTileContent(info,tileX,tileY,tileLOD,archive); + TXPArchive::TileLocationInfo plInfo; + plInfo.x = x; + plInfo.y = y; + plInfo.lod = lod; + TXPArchive::TileInfo parentInfo; + archive->getTileInfo(plInfo,parentInfo); - tileContent->setName("TileContent"); + for(int idx = 0; idx < nbChild; ++idx) + { + std::vector childrenChildLoc; + + TXPArchive::TileLocationInfo& loc = locs[idx]; + + TXPArchive::TileInfo info; + if (!archive->getTileInfo(loc,info)) + continue; - if (tileLOD < (numLods-1)) - { - char pagedLODfile[1024]; - sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp", - archive->getDir(), - tileLOD, - tileX, - tileY, - archive->getId() - ); + osg::ref_ptr tileContent = getTileContent(info, loc, archive, childrenChildLoc); - osg::ref_ptr pagedLOD = new TXPPagedLOD; + tileContent->setName("TileContent"); - // not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. - pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); - pagedLOD->setFileName(1,pagedLODfile); - pagedLOD->setRange(1,0,info.minRange); - pagedLOD->setCenter(info.center); - pagedLOD->setRadius(info.radius); - pagedLOD->setPriorityOffset(0,numLods-lod); - pagedLOD->setPriorityScale(0,1.0f); - pagedLOD->setNumChildrenThatCannotBeExpired(1); - pagedLOD->setTileId(tileX,tileY,tileLOD); + if(childrenChildLoc.size() > 0) + { + std::string childInfoStr; + createChildrenLocationString(childrenChildLoc, childInfoStr); - if(tileType == trpgHeader::TileLocal) + char pagedLODfile[1024]; + sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d%s.txp", + archive->getDir(), + loc.lod, + loc.x, + loc.y, + archive->getId(), + childInfoStr.c_str()); + + // there are tile sets which do not maintain the z extents in + // the tile table. This attempt to address the issue by using + // the geometry bounding sphere. The downside is that this is + // not coupled to the generation and may result in runtime cracks + if (info.center.z() == 0) { - osg::Vec3d center(info.center - parentInfo.bbox._min); - osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); - sw[2] = 0.0; - pagedLOD->setCenter(center - sw); - osg::Matrix offset; - offset.setTrans(sw); - osg::MatrixTransform *tform = new osg::MatrixTransform(offset); - tform->addChild(pagedLOD.get()); - subtiles->addChild(tform); - } - else - subtiles->addChild(pagedLOD.get()); - } - else - { - subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD)); - if(tileType == trpgHeader::TileLocal) - { - osg::Vec3d center(info.center - parentInfo.bbox._min); - osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); - sw[2] = 0.0; - osg::Matrix offset; - offset.setTrans(sw); - osg::MatrixTransform *tform = new osg::MatrixTransform(offset); - tform->addChild(tileContent.get()); - subtiles->addChild(tform); - } - else - subtiles->addChild(tileContent.get()); - } + osg::BoundingSphere bSphere = tileContent->getBound(); + info.center.z() = bSphere.center().z(); + info.radius = bSphere.radius(); + } + + osg::ref_ptr pagedLOD = new TXPPagedLOD; + // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. + pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); + pagedLOD->setFileName(1,pagedLODfile); + pagedLOD->setRange(1,0,info.minRange); + pagedLOD->setCenter(info.center); + pagedLOD->setRadius(info.radius); + pagedLOD->setPriorityOffset(0,numLods - loc.lod); + pagedLOD->setPriorityScale(0,1.0f); + pagedLOD->setNumChildrenThatCannotBeExpired(1); + pagedLOD->setTileId(loc.x, loc.y, loc.lod); + + if(tileType == trpgHeader::TileLocal) + { + osg::Vec3d center(info.center - parentInfo.bbox._min); + osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); + sw[2] = 0.0; + pagedLOD->setCenter(center - sw); + osg::Matrix offset; + offset.setTrans(sw); + osg::MatrixTransform *tform = new osg::MatrixTransform(offset); + tform->addChild(pagedLOD.get()); + subtiles->addChild(tform); + } + else + subtiles->addChild(pagedLOD.get()); + subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod)); // is this really needed? + } + else + { + subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod)); + if(tileType == trpgHeader::TileLocal) + { + osg::Vec3d center(info.center - parentInfo.bbox._min); + osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); + sw[2] = 0.0; + osg::Matrix offset; + offset.setTrans(sw); + osg::MatrixTransform *tform = new osg::MatrixTransform(offset); + tform->addChild(tileContent.get()); + subtiles->addChild(tform); + } + else + subtiles->addChild(tileContent.get()); + } } } - - //osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl; + else + { + + int sizeX, sizeY; + archive->getLODSize(lod+1,sizeX,sizeY); + const trpgHeader* header = archive->GetHeader(); + trpgHeader::trpgTileType tileType; + header->GetTileOriginType(tileType); + + TXPArchive::TileInfo parentInfo; + archive->getTileInfo(x,y,lod,parentInfo); + + for (int ix = 0; ix < 2; ix++) + { + for (int iy = 0; iy < 2; iy++) + { + int tileX = x*2+ix; + int tileY = y*2+iy; + int tileLOD = lod+1; + + TXPArchive::TileInfo info; + if (!archive->getTileInfo(tileX,tileY,tileLOD,info)) + continue; + + osg::ref_ptr tileContent = getTileContent(info,tileX,tileY,tileLOD,archive, childrenLoc); + + tileContent->setName("TileContent"); + + if (tileLOD < (numLods-1)) + { + char pagedLODfile[1024]; + sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp", + archive->getDir(), + tileLOD, + tileX, + tileY, + archive->getId()); + + // there are tile sets which do not maintain the z extents in + // the tile table. This attempt to address the issue by using + // the geometry bounding sphere. The downside is that this is + // not coupled to the generation and may result in runtime cracks + if (info.center.z() == 0) + { + osg::BoundingSphere bSphere = tileContent->getBound(); + + info.center.z() = bSphere.center().z(); + info.radius = bSphere.radius(); + } + + osg::ref_ptr pagedLOD = new TXPPagedLOD; + // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out. + pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7)); + pagedLOD->setFileName(1,pagedLODfile); + pagedLOD->setRange(1,0,info.minRange); + pagedLOD->setCenter(info.center); + pagedLOD->setRadius(info.radius); + pagedLOD->setPriorityOffset(0,numLods-lod); + pagedLOD->setPriorityScale(0,1.0f); + pagedLOD->setNumChildrenThatCannotBeExpired(1); + pagedLOD->setTileId(tileX,tileY,tileLOD); + + if(tileType == trpgHeader::TileLocal) + { + osg::Vec3d center(info.center - parentInfo.bbox._min); + osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); + sw[2] = 0.0; + pagedLOD->setCenter(center - sw); + osg::Matrix offset; + offset.setTrans(sw); + osg::MatrixTransform *tform = new osg::MatrixTransform(offset); + tform->addChild(pagedLOD.get()); + subtiles->addChild(tform); + } + else + subtiles->addChild(pagedLOD.get()); + } + else + { + subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD)); + if(tileType == trpgHeader::TileLocal) + { + osg::Vec3d center(info.center - parentInfo.bbox._min); + osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min); + sw[2] = 0.0; + osg::Matrix offset; + offset.setTrans(sw); + osg::MatrixTransform *tform = new osg::MatrixTransform(offset); + tform->addChild(tileContent.get()); + subtiles->addChild(tform); + } + else + subtiles->addChild(tileContent.get()); + } + + } + } + } + + //osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl; return subtiles.get(); } return ReadResult::ERROR_IN_READING_FILE; } +// If you change this then you have to change extractChildrenLocation() +void ReaderWriterTXP::createChildrenLocationString(const std::vector& locs, std::string& locString) const +{ + std::stringstream theLoc; + + if(locs.size() == 0) + { + theLoc << "_" << locs.size(); + } + else + { + + theLoc << "_" << locs.size() << "_" << "{" ; + + for(unsigned int idx = 0; idx < locs.size(); ++idx) + { + const TXPArchive::TileLocationInfo& loc = locs[idx]; + + theLoc << loc.x + << "_" + << loc.y + << "_" + << loc.addr.file + << "_" + << loc.addr.offset + << "_" + << loc.zmin + << "_" + << loc.zmax; + if(idx != locs.size() -1) + theLoc << "_"; + } + } + + theLoc << "}" << std::ends; + + locString = theLoc.str(); +} +bool ReaderWriterTXP::extractChildrenLocations(const std::string& name, int parentLod, std::vector& locs, int nbChild) const +{ + locs.clear(); + + if(nbChild == 0) + return true; + + locs.resize(nbChild); + + // We look for '{', which should be the start of the list of {x,y,addr} children data + // '}' should end the list. + // We expect: X,Y,FID,FOFFSET,ZMIN,ZMAX + std::string::size_type startOfList = name.find_last_of('{'); + if(startOfList == std::string::npos) + return false; + + std::string::size_type endOfList = name.find_last_of('}'); + if(endOfList == std::string::npos) + return false; + + // Extract the data + strcpy(gbuf, name.substr(startOfList + 1, endOfList - startOfList - 1).c_str()); + char *token = strtok( gbuf, "_" ); + + int nbTokenRead = 0; + for(int idx = 0; idx < nbChild; idx++) + { + // X + if(!token) + break; + locs[idx].x = atoi(token); + nbTokenRead++; + + // Y + token = strtok(0, "_"); + if(!token) + break; + locs[idx].y = atoi(token); + nbTokenRead++; + + // FID + token = strtok(0, "_"); + if(!token) + break; + locs[idx].addr.file = atoi(token); + nbTokenRead++; + + // OFFSET + token = strtok(0, "_"); + if(!token) + break; + locs[idx].addr.offset = atoi(token); + nbTokenRead++; + + // ZMIN + token = strtok(0, "_"); + if(!token) + break; + locs[idx].zmin = (float)atof(token); + nbTokenRead++; + + // ZMAX + token = strtok(0, "_"); + if(!token) + break; + locs[idx].zmax= (float)atof(token); + nbTokenRead++; + + locs[idx].lod = parentLod+1; + + + + token = strtok(0, "_"); + } + + if(nbTokenRead != nbChild*6) + return false; + else + return true; + + +} + TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir) { TXPArchive* archive = NULL; @@ -279,45 +616,50 @@ TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir) class SeamFinder: public osg::NodeVisitor { public: - SeamFinder(int x, int y, int lod, TXPArchive::TileInfo& info, TXPArchive *archive ): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _x(x), _y(y), _lod(lod), _info(info), _archive(archive) - {}; + SeamFinder(int x, int y, int lod, const TXPArchive::TileInfo& info, TXPArchive *archive ): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _x(x), _y(y), _lod(lod), _info(info), _archive(archive) + {} virtual void apply(osg::Group& group) - { - for (unsigned int i = 0; i < group.getNumChildren(); i++) - { - osg::Node* child = group.getChild(i); - osg::Node* seam = seamReplacement(child); - if (child != seam) - { - group.replaceChild(child,seam); - } - else - { - child->accept(*this); - } - } - } + { + for (unsigned int i = 0; i < group.getNumChildren(); i++) + { + osg::Node* child = group.getChild(i); + osg::Node* seam = seamReplacement(child); + if (child != seam) + { + group.replaceChild(child,seam); + } + else + { + child->accept(*this); + } + } + } protected: osg::Node* seamReplacement(osg::Node* node); int _x, _y, _lod; - TXPArchive::TileInfo& _info; + const TXPArchive::TileInfo& _info; TXPArchive *_archive; }; osg::Node* SeamFinder::seamReplacement(osg::Node* node) { osg::Group* group = node->asGroup(); - if (group == 0) return node; + if ( group == 0 ) + return node; std::vector nonSeamChildren; osg::LOD* hiRes = 0; osg::LOD* loRes = 0; + const trpgHeader* header = _archive->GetHeader(); + trpgHeader::trpgTileType tileType; + header->GetTileOriginType(tileType); + for (unsigned int i = 0; i < group->getNumChildren(); i++) { osg::LOD* lod = dynamic_cast(group->getChild(i)); @@ -329,11 +671,32 @@ osg::Node* SeamFinder::seamReplacement(osg::Node* node) bool nonSeamChild = true; + // looks like the problem is in here - likely due to seamLOD info + // not being adjusted properly in tiled databases // seam center is outside the bounding box of the tile - if (!_info.bbox.contains(lod->getCenter())) + osg::Vec3 lodCenter = lod->getCenter(); + + if(tileType == trpgHeader::TileLocal) + { + trpg2dPoint tileExtents; + header->GetTileSize(0, tileExtents); + osg::BoundingBox bbox; + _archive->getExtents(bbox); + osg::Vec3 offset(0.0, 0.0, 0.0); + + int divider = (0x1 << _lod); + // calculate which tile model is located in + tileExtents.x /= divider; + tileExtents.y /= divider; + offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5; + offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5; + lodCenter += offset; + } + + if (!_info.bbox.contains(lodCenter)) { // seams have center as the neighbour tile - osg::Vec3 d = _info.center - lod->getCenter(); + osg::Vec3 d = _info.center - lodCenter; if (((fabs(d.x())-_info.size.x()) > 0.0001) && ((fabs(d.y())-_info.size.y()) > 0.0001)) { nonSeamChildren.push_back(lod); @@ -372,19 +735,43 @@ osg::Node* SeamFinder::seamReplacement(osg::Node* node) int dx = 0; int dy = 0; int lod = _lod; - osg::Vec3 delta = loRes->getCenter()-_info.center; + osg::Vec3 lodCenter = loRes->getCenter(); + + if(tileType == trpgHeader::TileLocal) + { + trpg2dPoint tileExtents; + header->GetTileSize(0, tileExtents); + osg::BoundingBox bbox; + _archive->getExtents(bbox); + osg::Vec3 offset(0.0, 0.0, 0.0); + + int divider = (0x1 << _lod); + // calculate which tile model is located in + tileExtents.x /= divider; + tileExtents.y /= divider; + offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5; + offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5; + lodCenter += offset; + } + + osg::Vec3 delta = lodCenter-_info.center; if (fabs(delta.x())>fabs(delta.y())) { - if (delta.x()<0.0) --dx; // west - else dx++; // east + if ( delta.x() < 0.0 ) + --dx; // west + else + dx++; // east } else { - if (delta.y()<0.0) --dy; // south - else ++dy; // north + if ( delta.y() < 0.0 ) + --dy; // south + else + ++dy; // north } TXPSeamLOD* seam = new TXPSeamLOD(_x, _y, lod, dx, dy); + seam->setCenter(loRes->getCenter()); seam->addChild(loRes->getChild(0)); // low res if (hiRes) { @@ -411,28 +798,34 @@ osg::Node* SeamFinder::seamReplacement(osg::Node* node) return node; } -osg::Node* ReaderWriterTXP::getTileContent(TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive) +osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive, std::vector& childrenLoc) { - if (archive == 0) return false; + if ( archive == 0 ) + return false; - int numLods = archive->getNumLODs(); + int majorVersion, minorVersion; + archive->GetVersion(majorVersion, minorVersion); double realMinRange = info.minRange; double realMaxRange = info.maxRange; - double usedMaxRange = osg::maximum(info.maxRange,1e7); + double usedMaxRange = osg::maximum(info.maxRange,1e7); osg::Vec3 tileCenter; - osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter); + osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc); // if group has only one child, then simply use its child. -#if 1 while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup()) { tileGroup = tileGroup->getChild(0)->asGroup(); } -#endif + bool doSeam = false; + if(majorVersion == 2 && minorVersion >= 1) + doSeam = (childrenLoc.size() > 0); + else + doSeam = (lod < (archive->getNumLODs() - 1)); + // Handle seams - if (lod < (numLods-1)) + if (doSeam) { SeamFinder sfv(x,y,lod,info,archive); tileGroup->accept(sfv); @@ -441,5 +834,35 @@ osg::Node* ReaderWriterTXP::getTileContent(TXPArchive::TileInfo &info, int x, in return tileGroup; } +// this version only gets called if the TXP version is >= than 2.1 +osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, const TXPArchive::TileLocationInfo& loc, TXPArchive* archive, std::vector& childrenLoc) +{ + if ( archive == 0 ) + return false; + + // int numLods = archive->getNumLODs(); + + double realMinRange = info.minRange; + double realMaxRange = info.maxRange; + double usedMaxRange = osg::maximum(info.maxRange,1e7); + osg::Vec3 tileCenter; + osg::Group* tileGroup = archive->getTileContent(loc,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc); + + // if group has only one child, then simply use its child. + while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup()) + { + tileGroup = tileGroup->getChild(0)->asGroup(); + } + + // Handle seams + if (childrenLoc.size() > 0) + { + SeamFinder sfv(loc.x, loc.y, loc.lod, info, archive); + tileGroup->accept(sfv); + } + + return tileGroup; +} + osgDB::RegisterReaderWriterProxy g_txpReaderWriterProxy; diff --git a/src/osgPlugins/txp/ReaderWriterTXP.h b/src/osgPlugins/txp/ReaderWriterTXP.h index 73514d49c..1e27afb6e 100644 --- a/src/osgPlugins/txp/ReaderWriterTXP.h +++ b/src/osgPlugins/txp/ReaderWriterTXP.h @@ -80,9 +80,13 @@ protected: TXPArchive *getArchive(int id, const std::string&); - osg::Node* getTileContent(TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive); - + osg::Node* getTileContent(const TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive, std::vector& childrenLoc); + osg::Node* getTileContent(const TXPArchive::TileInfo &info, const TXPArchive::TileLocationInfo& loc, TXPArchive* archive, std::vector& childrenLoc); + void createChildrenLocationString(const std::vector& locs, std::string& locString) const; + bool extractChildrenLocations(const std::string& name, int parentLod, std::vector& locs, int nbChild) const; + mutable osgDB::ReentrantMutex _serializerMutex; + std::map< int,osg::ref_ptr > _archives; static int _archiveId; }; diff --git a/src/osgPlugins/txp/TXPArchive.cpp b/src/osgPlugins/txp/TXPArchive.cpp index 5508fc8f1..e8800852d 100644 --- a/src/osgPlugins/txp/TXPArchive.cpp +++ b/src/osgPlugins/txp/TXPArchive.cpp @@ -25,6 +25,10 @@ #include #include +#if defined(linux) +# include +# define _access access +#endif #include "TXPArchive.h" #include "TXPParser.h" @@ -36,12 +40,36 @@ using namespace txp; #define TXPArchiveERROR(s) osg::notify(osg::NOTICE) << "txp::TXPArchive::" << (s) << " error: " + +void TXPArchive::SetTexMap(int key,osg::ref_ptr ref) +{ + _texmap[key] = ref; +} + +osg::ref_ptr TXPArchive::GetTexMapEntry(int key) +{ + return _texmap[key]; +} + +void TXPArchive::SetStatesMap(int key,osg::ref_ptr ref) +{ + _statesMap[key] = ref; +} + +osg::ref_ptr TXPArchive::GetStatesMapEntry(int key) +{ + return _statesMap[key]; +} + TXPArchive::TXPArchive(): -trpgr_Archive(), -_id(-1), -_numLODs(0), -_swExtents(0.0,0.0), -_neExtents(0.0,0.0) + trpgr_Archive(), + _id(-1), + _numLODs(0), + _swExtents(0.0,0.0), + _neExtents(0.0,0.0), + _majorVersion(-1), + _minorVersion(-1), + _isMaster(false) { } @@ -87,7 +115,7 @@ bool TXPArchive::openFile(const std::string& archiveName) return false; } - if (!ReadHeader()) + if (!ReadHeader(false)) { TXPArchiveERROR("openFile()") << "couldn't read header for archive: " << archiveName << std::endl; return false; @@ -98,19 +126,19 @@ bool TXPArchive::openFile(const std::string& archiveName) { header->GetNumLods(_numLODs); header->GetExtents(_swExtents,_neExtents); + header->GetVersion(_majorVersion, _minorVersion); + _isMaster = header->GetIsMaster(); } int numTextures; texTable.GetNumTextures(numTextures); - _textures.resize(numTextures); int numModel; modelTable.GetNumModels(numModel); - _models.resize(numModel); + _models.clear(); int numMaterials; materialTable.GetNumMaterial(numMaterials); - _gstates.resize(numMaterials); return true; } @@ -119,7 +147,9 @@ bool TXPArchive::loadMaterial(int ix) { int i = ix; - if (_gstates[ix].get()) return true; + + if (GetStatesMapEntry(ix).get()) + return true; osg::StateSet* osg_state_set = new osg::StateSet; @@ -145,17 +175,17 @@ bool TXPArchive::loadMaterial(int ix) trpgColor color; mat->GetAmbient(color); osg_material->setAmbient( osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); mat->GetDiffuse(color); osg_material->setDiffuse(osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); mat->GetSpecular(color); osg_material->setSpecular(osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); mat->GetEmission(color); osg_material->setEmission(osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); float64 shinines; mat->GetShininess(shinines); @@ -213,7 +243,7 @@ bool TXPArchive::loadMaterial(int ix) texEnv.GetWrap(wrap_s, wrap_t); loadTexture(texId); - osg::Texture2D* osg_texture = _textures[texId].get(); + osg::Texture2D* osg_texture = GetTexMapEntry(texId).get(); if(osg_texture) { @@ -299,7 +329,7 @@ bool TXPArchive::loadMaterial(int ix) osg_state_set->setAttributeAndModes(cull_face, osg::StateAttribute::ON); } } - _gstates[i] = osg_state_set; + SetStatesMap(i,osg_state_set); return true; } @@ -311,19 +341,29 @@ bool TXPArchive::loadMaterials() bool TXPArchive::loadTexture(int i) { - if (_textures[i].get()) return true; - - trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable); + if (GetTexMapEntry(i).get()) + return true; + + bool separateGeo = false; + int majorVer,minorVer; + GetVersion(majorVer,minorVer); + if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) + { + separateGeo = true; + } + trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable,separateGeo); const trpgTexture *tex; tex = texTable.GetTextureRef(i); - if (!tex) return false; + if (!tex) + return false; trpgTexture::ImageMode mode; tex->GetImageMode(mode); if(mode == trpgTexture::External) { - char texName[1024]; texName[0] = 0; + char texName[ 1024 ]; + texName[ 0 ] = 0; tex->GetName(texName,1023); // Create a texture by name. @@ -356,30 +396,32 @@ bool TXPArchive::loadTexture(int i) else { osg::notify(osg::WARN) << "TrPageArchive::LoadMaterials() error: " - << "couldn't open image: " << filename << std::endl; + << "couldn't open image: " << filename << std::endl; } - _textures[i] = osg_texture; + SetTexMap(i,osg_texture); } else if( mode == trpgTexture::Local ) { - _textures[i] = getLocalTexture(image_helper,tex); + SetTexMap(i,getLocalTexture(image_helper,tex)); } else if( mode == trpgTexture::Template ) { - _textures[i] = 0L; //GetTemplateTexture(image_helper,0, tex); + SetTexMap(i,0L); } else { - _textures[i] = 0; + SetTexMap(i,0L); } - return (_textures[i].get() != 0); + return (GetTexMapEntry(i).get() != 0); } bool TXPArchive::loadModel(int ix) { trpgModel *mod = modelTable.GetModelRef(ix); int type; + if(!mod) + return false; mod->GetType(type); // Only dealing with external models currently @@ -389,24 +431,24 @@ bool TXPArchive::loadModel(int ix) mod->GetName(name,1023); // Load the model. It's probably not TerraPage - osg::Node *osg_model = osgDB::readNodeFile(name); - if (!osg_model) + osg::Node *osg_model = osgDB::readNodeFile( name ); + if ( !osg_model ) { osg::notify(osg::WARN) << "TrPageArchive::LoadModels() error: " - << "failed to load model: " - << name << std::endl; + << "failed to load model: " + << name << std::endl; } - // Do this even if it's NULL - _models[ix] = osg_model; + // Do this even if it's NULL + _models[ ix ] = osg_model; } /* - else - { - trpgMemReadBuffer buf(GetEndian()); - mod->Read(buf); - Group *osg_model = parse->ParseScene(buf, m_gstates , m_models); - m_models.push_back(osg_model); - } + else + { + trpgMemReadBuffer buf(GetEndian()); + mod->Read(buf); + Group *osg_model = parse->ParseScene(buf, m_gstates , m_models); + m_models.push_back(osg_model); + } */ return true; } @@ -417,14 +459,14 @@ bool TXPArchive::loadModels() int numModel; modelTable.GetNumModels(numModel); - _models.resize(numModel); - // Iterate over the models - for (int i=0; i< numModel; i++) + // use a pointer to the models map to bootstrap our map + trpgModelTable::ModelMapType *mt = modelTable.GetModelMap(); + trpgModelTable::ModelMapType::iterator itr = mt->begin(); + for ( ; itr != mt->end( ); itr++) { - loadModel(i); + loadModel(itr->first); } - osg::notify(osg::NOTICE) << "txp:: ... done." << std::endl; return true; } @@ -433,11 +475,11 @@ bool TXPArchive::loadLightAttributes() { osg::notify(osg::NOTICE) << "txp:: Loading light attributes ..." << std::endl; - int num; - lightTable.GetNumLightAttrs(num); - for ( int attr_num = 0; attr_num < num; attr_num++ ) + trpgLightTable::LightMapType *lm = lightTable.getLightMap(); + trpgLightTable::LightMapType::iterator itr = lm->begin(); + for ( ; itr != lm->end() ; itr++) { - trpgLightAttr* ref = const_cast(lightTable.GetLightAttrRef(attr_num)); + trpgLightAttr* ref = &itr->second; osgSim::LightPointNode* osgLight = new osgSim::LightPointNode(); @@ -523,11 +565,12 @@ bool TXPArchive::loadLightAttributes() lp._sector = back; osgLight->addLightPoint(lp); } - else{ + else + { osgLight->addLightPoint(lp); } - addLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z)); + addLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z),itr->first); } osg::notify(osg::NOTICE) << "txp:: ... done." << std::endl; @@ -537,15 +580,17 @@ bool TXPArchive::loadLightAttributes() void trim(std::string& str) { while (!str.empty() && isspace(str[str.length()-1])) - str.erase(str.length()-1); + str.erase(str.length()-1); while (!str.empty() && isspace(str[0])) str.erase(0,1); } bool TXPArchive::loadTextStyles() { const trpgTextStyleTable *textStyleTable = GetTextStyleTable(); - if (!textStyleTable) return false; - if (textStyleTable->GetNumStyle() < 1) return true; + if ( !textStyleTable ) + return false; + if ( textStyleTable->GetNumStyle() < 1 ) + return true; // try fontmap.txt std::map< std::string, std::string > fontmap; @@ -556,78 +601,81 @@ bool TXPArchive::loadTextStyles() if (fmapfile.is_open()) { - osg::notify(osg::NOTICE) << "txp:: Font map file found: " << fmapfname << std::endl; - std::string line; - while (std::getline(fmapfile,line)) - { - unsigned int ix = line.find_first_of('='); - if (ix != std::string::npos) - { - std::string fontname = line.substr(0,ix); - std::string fontfilename = line.substr(ix+1,line.length()-ix+1); + osg::notify(osg::NOTICE) << "txp:: Font map file found: " << fmapfname << std::endl; + std::string line; + while (std::getline(fmapfile,line)) + { + std::string::size_type ix = line.find_first_of('='); + if (ix != std::string::npos) + { + std::string fontname = line.substr(0,ix); + std::string fontfilename = line.substr(ix+1,line.length()-ix+1); - trim(fontname); - trim(fontfilename); + trim(fontname); + trim(fontfilename); - fontmap[fontname] = fontfilename; + fontmap[fontname] = fontfilename; - } - } - fmapfile.close(); + } + } + fmapfile.close(); } else { - osg::notify(osg::NOTICE) << "txp:: No font map file found: " << fmapfname << std::endl; - osg::notify(osg::NOTICE) << "txp:: All fonts defaulted to arial.ttf" << std::endl; + osg::notify(osg::NOTICE) << "txp:: No font map file found: " << fmapfname << std::endl; + osg::notify(osg::NOTICE) << "txp:: All fonts defaulted to arial.ttf" << std::endl; } - _fonts.resize(textStyleTable->GetNumStyle()); - _fcolors.resize(textStyleTable->GetNumStyle()); - for (int i = 0; i < textStyleTable->GetNumStyle(); i++) + const trpgTextStyleTable::StyleMapType *smap = textStyleTable->getStyleMap(); + trpgTextStyleTable::StyleMapType::const_iterator itr = smap->begin(); + for ( ; itr != smap->end(); itr++) { - const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(i); - if (!textStyle) continue; + const trpgTextStyle *textStyle = &itr->second; + if ( !textStyle ) + continue; - const std::string *fontName = textStyle->GetFont(); - if (!fontName) continue; + const std::string *fontName = textStyle->GetFont(); + if ( !fontName ) + continue; - std::string fontfilename = fontmap[*fontName]; - if (!fontfilename.length()) fontfilename = "arial.ttf"; - osg::ref_ptr< osgText::Font > font = osgText::readFontFile(fontfilename); + std::string fontfilename = fontmap[*fontName]; + if ( !fontfilename.length() ) + fontfilename = "arial.ttf"; + osg::ref_ptr< osgText::Font > font = osgText::readFontFile(fontfilename); - _fonts[i] = font; + _fonts[itr->first] = font; - const trpgMatTable* matTable = GetMaterialTable(); - if (matTable) - { - int matId = textStyle->GetMaterial(); - const trpgMaterial* mat = matTable->GetMaterialRef(0,matId); - if (mat) - { - trpgColor faceColor; - mat->GetColor(faceColor); + const trpgMatTable* matTable = GetMaterialTable(); + if (matTable) + { + int matId = textStyle->GetMaterial(); + const trpgMaterial* mat = matTable->GetMaterialRef(0,matId); + if (mat) + { + trpgColor faceColor; + mat->GetColor(faceColor); - float64 alpha; - mat->GetAlpha(alpha); + float64 alpha; + mat->GetAlpha(alpha); - _fcolors[i] = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha ); - } - } + _fcolors[itr->first] = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha ); + } + } } return true; } -void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att) +void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att,int handle) { DeferredLightAttribute la; la.lightPoint = lpn; la.fallback = fallback; la.attitude = att; - _lights.push_back(la); + _lights[handle] = la; } -bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info) +bool TXPArchive::getTileInfo(const TileLocationInfo& loc, TileInfo& info) { info.minRange = 0.0; info.maxRange = 0.0; @@ -637,104 +685,150 @@ bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info) OpenThreads::ScopedLock lock(_mutex); - header.GetLodRange(lod,info.maxRange); - header.GetLodRange(lod+1,info.minRange); + header.GetLodRange(loc.lod,info.maxRange); + header.GetLodRange(loc.lod+1,info.minRange); header.GetLodRange(0,info.lod0Range); trpg2dPoint sw,ne; header.GetExtents(sw,ne); trpg2dPoint size; - header.GetTileSize(lod,size); + header.GetTileSize(loc.lod,size); info.size.x() = size.x; info.size.y() = size.y; info.size.z() = 0.f; - trpgwAppAddress addr; - float minz = 0.f; - float maxz = 0.f; - tileTable.GetTile(x,y,lod,addr,minz,maxz); - info.center.set( - sw.x+(x*size.x)+(size.x/2.f), - sw.y+(y*size.y)+(size.y/2.f), - (minz+maxz)/2.f - ); + sw.x+(loc.x*size.x)+(size.x/2.f), + sw.y+(loc.y*size.y)+(size.y/2.f), + (loc.zmin + loc.zmax)/2.f + ); info.bbox.set( osg::Vec3( info.center.x()-(size.x/2.f), info.center.y()-(size.y/2.f), - minz - ), + loc.zmin + ), osg::Vec3( info.center.x()+(size.x/2.f), info.center.y()+(size.y/2.f), - maxz - ) - ); + loc.zmax + ) + ); info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3; return true; + } -class ModelVisitor : public osg::NodeVisitor +bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info) { - TXPArchive* _archive; - int _x; - int _y; - int _lod; - -public: - ModelVisitor(TXPArchive* archive, int x, int y, int lod): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _archive(archive), _x(x), _y(y), _lod(lod) + + if(_majorVersion == 2 && _minorVersion >=1) { + // Version 2.1 + // Tile table contain only lod 0 + if(lod > 0) + return false; } - - virtual void apply(osg::MatrixTransform& xform) - { - const trpgHeader* header = _archive->GetHeader(); - trpgHeader::trpgTileType tileType; - header->GetTileOriginType(tileType); - const osg::Referenced* ref = xform.getUserData(); - const TileIdentifier* tileID = dynamic_cast(ref); - if(!tileID) return; // bail early - this isn't a loaded model + trpgwAppAddress addr; + float minz = 0.f; + float maxz = 0.f; + tileTable.GetTile(x, y, lod, addr, minz, maxz); - if(tileType == trpgHeader::TileLocal && tileID->lod == 9999) - { - trpg2dPoint tileExtents; - header->GetTileSize(0, tileExtents); - osg::BoundingBox bbox; - _archive->getExtents(bbox); - osg::Vec3 offset(xform.getMatrix().getTrans()); - offset[0] -= bbox._min[0]; - offset[1] -= bbox._min[1]; - - trpg2dPoint offsetXY, tileID(_x,_y); - int divider = (0x01 << _lod); - // calculate which tile model is located in - tileExtents.x /= divider; - tileExtents.y /= divider; - offset[0] -= tileID.x*tileExtents.x; - offset[1] -= tileID.y*tileExtents.y; - - osg::Matrix mat(xform.getMatrix()); - mat.setTrans(offset); - xform.setMatrix(mat); - } - } -}; + TileLocationInfo loc(x, y, lod, addr, minz, maxz); + return getTileInfo(loc, info); +} osg::Group* TXPArchive::getTileContent( int x, int y, int lod, double realMinRange, double realMaxRange, double usedMaxRange, - osg::Vec3& tileCenter) + osg::Vec3& tileCenter, + std::vector& childInfoList) { + if(_majorVersion == 2 && _minorVersion >= 1) + { + // Version 2.1 + // This call is valid only for lod = 0 + if(lod != 0) + return new osg::Group; + } + + trpgwAppAddress addr; + float minz = 0.f; + float maxz = 0.f; + tileTable.GetTile(x, y, lod, addr, minz, maxz); + TileLocationInfo loc(x,y,lod,addr, minz,maxz); + + return getTileContent(loc, realMinRange, realMaxRange, usedMaxRange, tileCenter, childInfoList); + +} + +class ModelVisitor : public osg::NodeVisitor +{ + TXPArchive* _archive; + TXPArchive::TileLocationInfo _tileInfo; +// int _x; +// int _y; +// int _lod; + +public: + ModelVisitor(TXPArchive* archive, const TXPArchive::TileLocationInfo& loc): + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _archive(archive), _tileInfo(loc) + { + } + + virtual void apply(osg::MatrixTransform& xform) + { + const trpgHeader* header = _archive->GetHeader(); + trpgHeader::trpgTileType tileType; + header->GetTileOriginType(tileType); + const osg::Referenced* ref = xform.getUserData(); + const TileIdentifier* tileID = dynamic_cast(ref); + + if(!tileID) return; // bail early - this isn't a loaded model + + if(tileType == trpgHeader::TileLocal && tileID->lod == 9999) + { + trpg2dPoint tileExtents; + header->GetTileSize(0, tileExtents); + osg::BoundingBox bbox; + _archive->getExtents(bbox); + osg::Vec3 offset(xform.getMatrix().getTrans()); + offset[0] -= bbox._min[0]; + offset[1] -= bbox._min[1]; + + trpg2dPoint offsetXY, tileID(_tileInfo.x,_tileInfo.y); + int divider = (0x01 << _tileInfo.lod); + // calculate which tile model is located in + tileExtents.x /= divider; + tileExtents.y /= divider; + offset[0] -= tileID.x*tileExtents.x; + offset[1] -= tileID.y*tileExtents.y; + + osg::Matrix mat(xform.getMatrix()); + mat.setTrans(offset); + xform.setMatrix(mat); + } + } +}; + + +osg::Group* TXPArchive::getTileContent( + const TileLocationInfo& loc, + double realMinRange, + double realMaxRange, + double usedMaxRange, + osg::Vec3& tileCenter, + std::vector& childInfoList) +{ + if (_parser.get() == 0) { _parser = new TXPParser(); @@ -742,28 +836,99 @@ osg::Group* TXPArchive::getTileContent( } trpgMemReadBuffer buf(GetEndian()); - if (!ReadTile(x,y,lod,buf)) + bool readStatus; + trpgTileTable::TileMode tileMode; + tileTable.GetMode(tileMode); + if(tileMode == trpgTileTable::External) + readStatus = ReadExternalTile(loc.x, loc.y, loc.lod, buf); + else + readStatus = ReadTile(loc.addr, buf); + + if(!readStatus) + return new osg::Group; + trpgTileHeader *tilehdr = _parser->getTileHeaderRef(); + + int majVersion,minVersion; + GetVersion(majVersion,minVersion); + // only compute block # if we are a master archive. + if((majVersion >= TRPG_NOMERGE_VERSION_MAJOR) && (minVersion >= TRPG_NOMERGE_VERSION_MINOR) && (_isMaster)) { - return new osg::Group; + if(tilehdr) + { + int x,y; + unsigned int denom = (1 << loc.lod); // this should work up to lod 31 + x = loc.x/denom; + y = loc.y/denom; + tilehdr->SetBlockNo(y,x); + } } - osg::Group *tileGroup = _parser->parseScene(buf,_gstates,_models,realMinRange,realMaxRange,usedMaxRange); + osg::Group *tileGroup = _parser->parseScene(buf,_statesMap,_models,realMinRange,realMaxRange,usedMaxRange); tileCenter = _parser->getTileCenter(); + int nbChild = _parser->GetNbChildrenRef(); + + childInfoList.clear(); + for(int idx = 0; idx < nbChild; idx++) + { + const trpgChildRef *childRef = _parser->GetChildRef(idx); + + if(childRef) + { + TileLocationInfo loc; + childRef->GetTileLoc(loc.x, loc.y, loc.lod); + childRef->GetTileZValue(loc.zmin, loc.zmax); + childRef->GetTileAddress(loc.addr); + childInfoList.push_back(loc); + + } + } + // Fix up model MatrixTransform - ModelVisitor mv(this, x, y, lod); + ModelVisitor mv(this, loc); tileGroup->accept(mv); // Prune - unsigned int i = 0; - for (i = 0; i < _gstates.size(); i++) + OSGStatesMapType::iterator itr = _statesMap.begin(); + while( itr != _statesMap.end( ) ) { - if (_gstates[i].valid() && (_gstates[i]->referenceCount()==1)) _gstates[i] = 0; + if(itr->second.valid() && + (itr->second->referenceCount()==1)) + { + // unreference it. + itr->second = NULL; + + OSGStatesMapType::iterator toRemove = itr; + ++itr; + + // remove it from the map + _statesMap.erase( toRemove ); + } + else + { + ++itr; + } } - for (i = 0; i < _textures.size(); i++) + OSGTexMapType::iterator mitr = _texmap.begin(); + while( mitr != _texmap.end( ) ) { - if (_textures[i].valid() && (_textures[i]->referenceCount()==1)) _textures[i] = 0; + if(mitr->second.valid() && + (mitr->second->referenceCount()==1)) + { + // unreference it. + mitr->second = NULL; + + OSGTexMapType::iterator toRemove = mitr; + ++mitr; + + // remove it from the map + _texmap.erase( toRemove ); + } + else + { + ++mitr; + } } return tileGroup; diff --git a/src/osgPlugins/txp/TXPArchive.h b/src/osgPlugins/txp/TXPArchive.h index e48e5c963..7c173b551 100644 --- a/src/osgPlugins/txp/TXPArchive.h +++ b/src/osgPlugins/txp/TXPArchive.h @@ -50,155 +50,210 @@ namespace txp { -// this one handles different placement of light direction in osg and terrapage -struct DeferredLightAttribute -{ - // light point at (0,0,0) looking in (0,0,0) direction - osg::ref_ptr lightPoint; - osg::ref_ptr fallback; - osg::Vec3 attitude; -}; - -class TXPParser; -class TXPArchive : public trpgr_Archive, public osg::Referenced -{ -public: - // Constructor - TXPArchive(); - - // Opens the archive file and reads the header - bool openFile(const std::string& archiveName); - - // Load the materials from the archve - bool loadMaterials(); - bool loadMaterial(int ix); - bool loadTexture(int i); - - // Load the models from the archive - bool loadModels(); - bool loadModel(int ix); - - // Load the light attribs from the archive - bool loadLightAttributes(); - - // Load the text styles from the archive - bool loadTextStyles(); - inline std::vector< osg::ref_ptr >& getStyles() { return _fonts; } - inline std::vector< osg::Vec4 >& getTextColors() { return _fcolors; } - - // Add light attrib - void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude); - - int getNumLightAttributes() { return _lights.size(); } - - // Get light attrib - inline DeferredLightAttribute& getLightAttribute(unsigned int i) + // this one handles different placement of light direction in osg and terrapage + struct DeferredLightAttribute { - return _lights[i]; + // light point at (0,0,0) looking in (0,0,0) direction + osg::ref_ptr lightPoint; + osg::ref_ptr fallback; + osg::Vec3 attitude; }; - - // Gets some informations for a given tile - struct TileInfo + + class TXPParser; + class TXPArchive : public trpgr_Archive, public osg::Referenced { - osg::Vec3 center; - double minRange; - double maxRange; - double lod0Range; - float radius; - osg::Vec3 size; - osg::BoundingBox bbox; - }; - bool getTileInfo(int x, int y, int lod, TileInfo& info); + public: + // Constructor + TXPArchive(); - // Set/Get the archive id - inline void setId(int id) - { - _id = id; - } - inline const int& getId() const - { - return _id; - } + // Opens the archive file and reads the header + bool openFile(const std::string& archiveName); + // Load the materials from the archve + bool loadMaterials(); + bool loadMaterial(int ix); + bool loadTexture(int i); - // Returns the number of LODs for this archive - inline const int& getNumLODs() const - { - return _numLODs; - } + // Load the models from the archive + bool loadModels(); + bool loadModel(int ix); - // Returns the extents of the archive - // FIXME - Needs to change for databases that aren't flat-earth - void getExtents(osg::BoundingBox& extents); + // Load the light attribs from the archive + bool loadLightAttributes(); + + // Load the text styles from the archive + bool loadTextStyles(); + inline std::map >& getStyles() + { + return _fonts; + } + inline std::map& getTextColors() + { + return _fcolors; + } + + // Add light attrib + void addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback , const osg::Vec3& attitude,int handle); + + int getNumLightAttributes() + { + return _lights.size(); + } + + // Get light attrib + inline DeferredLightAttribute& getLightAttribute(unsigned int i) + { + return _lights[i]; + }; + + // Gets some informations for a given tile + struct TileInfo + { + osg::Vec3 center; + double minRange; + double maxRange; + double lod0Range; + float radius; + osg::Vec3 size; + osg::BoundingBox bbox; + }; + struct TileLocationInfo + { + TileLocationInfo() : x( -1 ), y( -1 ), lod( -1 ) + {} + TileLocationInfo(int gx, int gy, int glod, const trpgwAppAddress& gaddr, float gzmin = 0.0f, float gzmax = 0.0f): + x( gx ), y( gy ), lod( glod ), addr( gaddr ), zmin( gzmin ), zmax( gzmax ) + {} + int x, y, lod; + trpgwAppAddress addr; + float zmin, zmax; + }; + + bool getTileInfo(int x, int y, int lod, TileInfo& info); + bool getTileInfo(const TileLocationInfo& loc, TileInfo& info); + + // Set/Get the archive id + inline void setId(int id) + { + _id = id; + } + inline const int& getId() const + { + return _id; + } + + // Returns the number of LODs for this archive + inline const int& getNumLODs() const + { + return _numLODs; + } + + // Returns the extents of the archive + // FIXME - Needs to change for databases that aren't flat-earth + void getExtents(osg::BoundingBox& extents); // { // extents.set(_swExtents.x,_swExtents.y,0.0f,_neExtents.x,_neExtents.y,0.0f); // } - // Returns the origin of the archive - inline void getOrigin(double& x, double& y) - { - x=_swExtents.x; - y=_swExtents.y; - } + // Returns the origin of the archive + inline void getOrigin(double& x, double& y) + { + x=_swExtents.x; + y=_swExtents.y; + } - // Returns global texture - inline osg::Texture2D* getGlobalTexture(int id) - { - return _textures[id].get(); - } + // Returns global texture + inline osg::Texture2D* getGlobalTexture(int id) + { + return GetTexMapEntry(id).get(); + } - // Returns scenegraph representing the Tile - osg::Group* getTileContent( - int x, - int y, - int lod, - double realMinRange, - double realMaxRange, - double usedMaxRange, - osg::Vec3& tileCenter); + // Returns scenegraph representing the Tile. + // For version 2.1 and over this function can only be call + // with lod = 0, since the archive tile table will contain + // only tiles with lod = 0 + osg::Group* TXPArchive::getTileContent( + int x, + int y, + int lod, + double realMinRange, + double realMaxRange, + double usedMaxRange, + osg::Vec3& tileCenter, + std::vector& childInfoList); - // Get the number of tiles for given LOD - bool getLODSize(int lod, int& x, int& y); + // To be used for Version 2.1 with lod > 0 + osg::Group* TXPArchive::getTileContent( + const TileLocationInfo& loc, + double realMinRange, + double realMaxRange, + double usedMaxRange, + osg::Vec3& tileCenter, + std::vector& childInfoList); + + // Get the number of tiles for given LOD + bool getLODSize(int lod, int& x, int& y); + + void GetVersion(int& majorVer, int& minorVer) const + { + majorVer = _majorVersion; + minorVer = _minorVersion; + } -protected: + protected: - // Destructor - virtual ~TXPArchive(); + // Destructor + virtual ~TXPArchive(); - // Id of the archive - int _id; + // Id of the archive + int _id; - // Number of the LODs - int _numLODs; + // Number of the LODs + int _numLODs; - // Archive extents - trpg2dPoint _swExtents; - trpg2dPoint _neExtents; + // Archive extents + trpg2dPoint _swExtents; + trpg2dPoint _neExtents; - // Terra Page Parser - osg::ref_ptr _parser; + // Terra Page Parser + osg::ref_ptr _parser; - // Textures - std::vector< osg::ref_ptr > _textures; - - // States - std::vector< osg::ref_ptr > _gstates; - - // Models - std::vector< osg::ref_ptr > _models; - - // Light attributes vector - std::vector _lights; + // Textures + typedef std::map > OSGTexMapType; + OSGTexMapType _texmap; - // Text styles / Fonts - std::vector< osg::ref_ptr > _fonts; + void SetTexMap(int key,osg::ref_ptr ref); + osg::ref_ptr GetTexMapEntry(int key); - // Text colors - std::vector< osg::Vec4 > _fcolors; - - // - OpenThreads::Mutex _mutex; -}; + // States + typedef std::map > OSGStatesMapType; + OSGStatesMapType _statesMap; + + void SetStatesMap(int key,osg::ref_ptr ref); + osg::ref_ptr GetStatesMapEntry(int key); + + // Models + typedef std::map > OSGModelsMapType; + OSGModelsMapType _models; + + // Light attributes vector + std::map _lights; + + // Text styles / Fonts + std::map > _fonts; + + // Text colors + std::map _fcolors; + + // + OpenThreads::Mutex _mutex; + + // Cache those: TerraPage version + int _majorVersion, _minorVersion; + + bool _isMaster; + + }; } // namespace diff --git a/src/osgPlugins/txp/TXPIO.cpp b/src/osgPlugins/txp/TXPIO.cpp index 8fa767e49..e32d52e5d 100644 --- a/src/osgPlugins/txp/TXPIO.cpp +++ b/src/osgPlugins/txp/TXPIO.cpp @@ -49,7 +49,8 @@ bool TXPNode_readLocalData(osg::Object &obj, osgDB::Input &fr) class Dump2Osg : public osg::NodeVisitor { public: - Dump2Osg(osgDB::Output &fw) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _fw(fw) {}; + Dump2Osg( osgDB::Output &fw ) : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), _fw( fw ) + {} virtual void apply(osg::Node& node) { @@ -64,8 +65,10 @@ bool TXPNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw) { const txp::TXPNode &txpNode = static_cast(obj); - if (!txpNode.getOptions().empty()) fw.indent() << "databaseOptions \"" << txpNode.getOptions() << "\""<(txpNode.asGroup()); diff --git a/src/osgPlugins/txp/TXPNode.cpp b/src/osgPlugins/txp/TXPNode.cpp index 25afe2160..353def14c 100644 --- a/src/osgPlugins/txp/TXPNode.cpp +++ b/src/osgPlugins/txp/TXPNode.cpp @@ -20,6 +20,41 @@ using namespace osg; +class RetestCallback : public osg::NodeCallback +{ + +public: + RetestCallback() + { + timer = osg::Timer::instance(); // get static timer + prevTime = 0; // should this be instantiated with current time? + } + + virtual void operator () ( osg::Node * node, osg::NodeVisitor * nv ) + { + osg::Group *pLOD = (osg::Group *) node; + osg::Group *n = NULL; + if ((pLOD->getNumChildren() > 0) && + (n = (osg::Group *) pLOD->getChild(0)) && + (n->getNumChildren() == 0)) + { + osg::Timer_t curTime = timer->tick(); + if ((prevTime + 2.0/timer->getSecondsPerTick() ) < curTime) + { + prevTime = curTime; + pLOD->removeChildren( 0, pLOD->getNumChildren()); + } + } + + NodeCallback::traverse( node, nv ); + } + +protected: + const osg::Timer* timer; + osg::Timer_t prevTime; +}; + + #define TXPNodeERROR(s) osg::notify(osg::NOTICE) << "txp::TXPNode::" << (s) << " error: " @@ -29,6 +64,7 @@ _originX(0.0), _originY(0.0) { setNumChildrenRequiringUpdateTraversal(1); + setCullingActive(false); } TXPNode::TXPNode(const TXPNode& txpNode,const osg::CopyOp& copyop): @@ -52,18 +88,18 @@ void TXPNode::traverse(osg::NodeVisitor& nv) { switch(nv.getVisitorType()) { - case osg::NodeVisitor::CULL_VISITOR: - { + case osg::NodeVisitor::CULL_VISITOR: + { osgUtil::CullVisitor* cv = dynamic_cast(&nv); if (cv) { -//#define PRINT_TILEMAPP_TIMEINFO -#ifdef PRINT_TILEMAPP_TIMEINFO +//#define PRINT_TILEMAPP_TIMEINFO +#ifdef PRINT_TILEMAPP_TIMEINFO const osg::Timer& timer = *osg::Timer::instance(); osg::Timer_t start = timer.tick(); std::cout<<"Doing visible tile search"< tileMapper = new TileMapper; tileMapper->setLODScale(cv->getLODScale()); @@ -92,11 +128,11 @@ void TXPNode::traverse(osg::NodeVisitor& nv) updateEye(nv); break; - } - case osg::NodeVisitor::UPDATE_VISITOR: + } + case osg::NodeVisitor::UPDATE_VISITOR: updateSceneGraph(); break; - default: + default: break; } Group::traverse(nv); @@ -186,7 +222,10 @@ bool TXPNode::loadArchive() _archive->GetHeader()->GetLodSize(0,tileSize); _pageManager = new TXPPageManager; - _pageManager->Init(_archive.get()); + + // We are going to use _pageManager to manage lod 0 only, all other lod + // are managed by this OSG plugin + _pageManager->Init(_archive.get(), 1); return true; } @@ -227,7 +266,7 @@ void TXPNode::updateEye(osg::NodeVisitor& nv) tile->GetTileLoc(x,y,lod); if (lod==0) { - osg::Node* node = addPagedLODTile(x,y,lod); + osg::Node* node = addPagedLODTile(x,y); tile->SetLocalData(node); //osg::notify(osg::NOTICE) << "Tile load: " << x << " " << y << " " << lod << std::endl; } @@ -237,8 +276,12 @@ void TXPNode::updateEye(osg::NodeVisitor& nv) } } -osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod) +osg::Node* TXPNode::addPagedLODTile(int x, int y) { + // For TerraPage 2.1 and over this method must only be use with lod = 0. + // If you look at the code that calls it, it is effectively called only when + // lod = 0. So all is OK + int lod = 0; char pagedLODfile[1024]; sprintf(pagedLODfile,"%s\\tile%d_%dx%d_%d.txp",_archive->getDir(),lod,x,y,_archive->getId()); @@ -254,6 +297,7 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod) pagedLOD->setCenter(info.center); pagedLOD->setRadius(info.radius); pagedLOD->setNumChildrenThatCannotBeExpired(1); + pagedLOD->setUpdateCallback(new RetestCallback); const trpgHeader* header = _archive->GetHeader(); trpgHeader::trpgTileType tileType; @@ -274,9 +318,10 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod) } else { - _nodesToAdd.push_back(pagedLOD); - return pagedLOD; - } + _nodesToAdd.push_back(pagedLOD); + + return pagedLOD; +} } void TXPNode::updateSceneGraph() diff --git a/src/osgPlugins/txp/TXPNode.h b/src/osgPlugins/txp/TXPNode.h index ff2a519a9..322f4b00a 100644 --- a/src/osgPlugins/txp/TXPNode.h +++ b/src/osgPlugins/txp/TXPNode.h @@ -45,6 +45,7 @@ namespace txp { + class TXPNode : public osg::Group { public: @@ -68,32 +69,35 @@ public: TXPArchive* getArchive(); - void setArchive(TXPArchive* archive) { _archive = archive; } + void setArchive( TXPArchive* archive ) + { + _archive = archive; + } virtual osg::BoundingSphere computeBound() const; - + protected: virtual ~TXPNode(); - void updateEye(osg::NodeVisitor& nv); void updateSceneGraph(); - osg::Node* addPagedLODTile(int x, int y, int lod); + // Create a page lod for lod 0 with givin grid location (x,y) + osg::Node* addPagedLODTile(int x, int y); - std::string _archiveName; - std::string _options; + std::string _archiveName; + std::string _options; - osg::ref_ptr _archive; - osg::ref_ptr _pageManager; + osg::ref_ptr _archive; + osg::ref_ptr _pageManager; - double _originX; - double _originY; - osg::BoundingBox _extents; + double _originX; + double _originY; + osg::BoundingBox _extents; - std::vector _nodesToAdd; - std::vector _nodesToRemove; + std::vector _nodesToAdd; + std::vector _nodesToRemove; }; diff --git a/src/osgPlugins/txp/TXPPagedLOD.cpp b/src/osgPlugins/txp/TXPPagedLOD.cpp index eb656518b..7bdb260fa 100644 --- a/src/osgPlugins/txp/TXPPagedLOD.cpp +++ b/src/osgPlugins/txp/TXPPagedLOD.cpp @@ -42,7 +42,8 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv) bool needToLoadChild = false; unsigned maxRangeSize = _rangeList.size(); - if (maxRangeSize!=0 && forceUseOfFirstChild) maxRangeSize=1; + if (maxRangeSize!=0 && forceUseOfFirstChild) + maxRangeSize=1; for(unsigned int i=0;iaccept(nv); lastChildTraversed = (int)i; } @@ -72,7 +73,8 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv) if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed) { //std::cout<<" to child "<accept(nv); } @@ -110,7 +112,7 @@ osg::BoundingSphere TXPPagedLOD::computeBound() const if (_centerMode==USER_DEFINED_CENTER && _radius>=0.0f) { - float tempRadius = osg::maximum( _radius, result.radius() ); + float tempRadius = osg::maximum( _radius, result.radius() ); result = osg::BoundingSphere(_userDefinedCenter,tempRadius); } return result; diff --git a/src/osgPlugins/txp/TXPPagedLOD.h b/src/osgPlugins/txp/TXPPagedLOD.h index 031700641..6ab08b2a5 100644 --- a/src/osgPlugins/txp/TXPPagedLOD.h +++ b/src/osgPlugins/txp/TXPPagedLOD.h @@ -1,3 +1,4 @@ +// -*-c++-*- /*************************************************************************** * December 2003 * diff --git a/src/osgPlugins/txp/TXPParser.cpp b/src/osgPlugins/txp/TXPParser.cpp index c498a19cb..f96f4043f 100644 --- a/src/osgPlugins/txp/TXPParser.cpp +++ b/src/osgPlugins/txp/TXPParser.cpp @@ -6,12 +6,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -23,36 +23,40 @@ #include "TXPArchive.h" #include "TileMapper.h" -#include - using namespace txp; +#include + static osg::ApplicationUsageProxy TXP_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TXP_DEFAULT_MAX_ANISOTROPY \" []\"","1.0 | 2.0 | 4.0 | 8.0 | 16.0"); TXPParser::TXPParser(): -_archive(0), -_currentTop(0), -_root(0), -_underBillboardSubgraph(false), -_numBillboardLevels(0), -_underLayerSubgraph(false), -_numLayerLevels(0), -_layerGeode(0), -_defaultMaxAnisotropy(1.0f), -_realMinRange(0.0), -_realMaxRange(0.0), -_usedMaxRange(0.0) + _archive(0), + _currentTop(0), + _root(0), + _underBillboardSubgraph(false), + _numBillboardLevels(0), + _underLayerSubgraph(false), + _numLayerLevels(0), + _layerGeode(0), + _defaultMaxAnisotropy(1.0f), + _realMinRange(0.0), + _realMaxRange(0.0), + _usedMaxRange(0.0), + _childRefCB(0) { - AddCallback(TRPG_ATTACH,new attachRead(this)); - AddCallback(TRPG_GEOMETRY,new geomRead(this)); - AddCallback(TRPG_GROUP,new groupRead(this)); - AddCallback(TRPG_LOD,new lodRead(this)); - AddCallback(TRPG_MODELREF,new modelRefRead(this)); - AddCallback(TRPG_BILLBOARD,new billboardRead(this)); - AddCallback(TRPG_LIGHT,new lightRead(this)); - AddCallback(TRPG_LAYER,new layerRead(this)); - AddCallback(TRPG_LABEL,new labelRead(this)); - AddCallback(TRPGTILEHEADER,new tileHeaderRead(this)); + AddCallback(TRPG_ATTACH, new attachRead(this)); + AddCallback(TRPG_CHILDREF, new childRefRead(this)); + AddCallback(TRPG_GEOMETRY, new geomRead(this)); + AddCallback(TRPG_GROUP, new groupRead(this)); + AddCallback(TRPG_LOD, new lodRead(this)); + AddCallback(TRPG_MODELREF, new modelRefRead(this)); + AddCallback(TRPG_BILLBOARD, new billboardRead(this)); + AddCallback(TRPG_LIGHT, new lightRead(this)); + AddCallback(TRPG_LAYER, new layerRead(this)); + AddCallback(TRPG_LABEL, new labelRead(this)); + AddCallback(TRPGTILEHEADER, new tileHeaderRead(this)); + + _childRefCB = dynamic_cast(GetCallback(TRPG_CHILDREF)); if (getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY")) { @@ -67,16 +71,20 @@ TXPParser::~TXPParser() osg::Group *TXPParser::parseScene( trpgReadBuffer &buf, - std::vector > &materials, - std::vector > &models, + std::map > &materials, + std::map > &models, double realMinRange, double realMaxRange, double usedMaxRange) { - if (_archive == 0) return NULL; + if (_archive == 0) + return NULL; + + if(_childRefCB) + _childRefCB->Reset(); _root = new osg::Group(); _currentTop = _root.get(); - _materials = &materials; + _materialMap = &materials; _localMaterials.clear(); _models = ⊧ @@ -116,8 +124,10 @@ void TXPParser::replaceTileLod(osg::Group* group) if (loLOD && hiLOD) { osg::Group *g = dynamic_cast(hiLOD->getChild(0)); - if (!g) return; - if (g->getNumChildren()) return; + if (!g) + return; + if (g->getNumChildren()) + return; _tileCenter = loLOD->getCenter(); @@ -128,21 +138,40 @@ void TXPParser::replaceTileLod(osg::Group* group) } } + +unsigned int TXPParser::GetNbChildrenRef() const +{ + if(_childRefCB) + return _childRefCB->GetNbChildrenRef(); + else + return 0; +} + +const trpgChildRef* TXPParser::GetChildRef(unsigned int idx) const +{ + if(_childRefCB) + return _childRefCB->GetChildRef(idx); + else + return 0; +} + bool TXPParser::StartChildren(void * /*in*/) { bool pushParent = true; if (_underBillboardSubgraph ) { - if (_numBillboardLevels > 0) pushParent = false; + if (_numBillboardLevels > 0) + pushParent = false; _numBillboardLevels++; } else - if (_underLayerSubgraph) - { - if (_numLayerLevels > 0) pushParent = false; - _numLayerLevels++; - } + if (_underLayerSubgraph) + { + if (_numLayerLevels > 0) + pushParent = false; + _numLayerLevels++; + } if (pushParent) { _parents.push(_currentTop); @@ -166,16 +195,16 @@ bool TXPParser::EndChildren(void *) popParent = false; } else - if (_underBillboardSubgraph) - { - _numBillboardLevels--; - if (_numBillboardLevels == 0) - { - _underBillboardSubgraph = false; - } - else - popParent = false; - } + if (_underBillboardSubgraph) + { + _numBillboardLevels--; + if (_numBillboardLevels == 0) + { + _underBillboardSubgraph = false; + } + else + popParent = false; + } if (popParent) { if (_parents.size()) @@ -199,16 +228,18 @@ class FindEmptyGroupsVisitor : public osg::NodeVisitor { public: FindEmptyGroupsVisitor(osg::NodeList& nl): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _nl(nl) {}; + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _nl(nl) + { + } virtual void apply(osg::Group& group) - { - if (group.getNumChildren()==0) - { - _nl.push_back(&group); - } - traverse(group); - } + { + if (group.getNumChildren()==0) + { + _nl.push_back(&group); + } + traverse(group); + } protected: osg::NodeList& _nl; }; @@ -225,13 +256,15 @@ void TXPParser::removeEmptyGroups() for (unsigned int i = 0; i < nl.size(); i++) { osg::Node* node = nl[i].get(); - if (node == NULL) continue; + if (node == NULL) + continue; osg::Node::ParentList parents = node->getParents(); for (unsigned int j = 0; j < parents.size(); j++) { osg::Group* parent = parents[j]; - if (parent) parent->removeChild(node); + if (parent) + parent->removeChild(node); } } } @@ -248,13 +281,13 @@ osg::Geode* TXPParser::createBoundingBox(int x,int y, int lod) osg::TessellationHints* hints = new osg::TessellationHints; hints->setDetailRatio(0.5f); osg::ShapeDrawable* sd = new osg::ShapeDrawable( - new osg::Box( - info.center, - info.bbox.xMax()-info.bbox.xMin(), - info.bbox.yMax()-info.bbox.yMin(), - 1 + new osg::Box( + info.center, + info.bbox.xMax()-info.bbox.xMin(), + info.bbox.yMax()-info.bbox.yMin(), + 1 ), - hints + hints ); if (lod==0) @@ -262,25 +295,25 @@ osg::Geode* TXPParser::createBoundingBox(int x,int y, int lod) sd->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); } else - if (lod==1) - { - sd->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); - } - else - if (lod==2) - { - sd->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); - } - else - if (lod==3) - { - sd->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); - } - else - if (lod==4) - { - sd->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); - } + if (lod==1) + { + sd->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f)); + } + else + if (lod==2) + { + sd->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f)); + } + else + if (lod==3) + { + sd->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f)); + } + else + if (lod==4) + { + sd->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); + } geode->addDrawable( sd ); return geode; @@ -288,13 +321,20 @@ osg::Geode* TXPParser::createBoundingBox(int x,int y, int lod) void TXPParser::loadLocalMaterials() { + bool separateGeo = false; + int majorVer,minorVer; + this->getArchive()->GetVersion(majorVer,minorVer); + if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) { + separateGeo = true; + } // new to 2.0 LOCAL materials trpgrImageHelper image_helper( _archive->GetEndian(), _archive->getDir(), *_archive->GetMaterialTable(), - *_archive->GetTexTable() - ); + *_archive->GetTexTable(), + separateGeo + ); trpgTileHeader* tile_head = getTileHeaderRef(); int n_materials; @@ -313,8 +353,8 @@ void TXPParser::loadLocalMaterials() trpgLocalMaterial locmat; tile_head->GetLocalMaterial(i,locmat); - const trpgMaterial* mat; - const trpgTexture *tex; + const trpgMaterial* mat = NULL; + const trpgTexture *tex = NULL; int32 size; image_helper.GetImageInfoForLocalMat(&locmat, &mat,&tex,size); @@ -335,7 +375,7 @@ void TXPParser::loadLocalMaterials() { case trpgTextureEnv::Alpha : osg_texenv->setMode(osg::TexEnv::REPLACE); - break; + break; case trpgTextureEnv::Decal: osg_texenv->setMode(osg::TexEnv::DECAL); break; @@ -400,17 +440,17 @@ void TXPParser::loadLocalMaterials() trpgColor color; mat->GetAmbient(color); osg_material->setAmbient( osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); mat->GetDiffuse(color); osg_material->setDiffuse(osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); mat->GetSpecular(color); osg_material->setSpecular(osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); mat->GetEmission(color); osg_material->setEmission(osg::Material::FRONT_AND_BACK , - osg::Vec4(color.red, color.green, color.blue, alpha)); + osg::Vec4(color.red, color.green, color.blue, alpha)); float64 shinines; mat->GetShininess(shinines); @@ -426,10 +466,10 @@ void TXPParser::loadLocalMaterials() } - /* This controls what alpha values in a texture mean. It can take the values: - None,Always,Equal,GreaterThanOrEqual,GreaterThan, - LessThanOrEqual,LessThan,Never,NotEqual - */ + /* This controls what alpha values in a texture mean. It can take the values: + None,Always,Equal,GreaterThanOrEqual,GreaterThan, + LessThanOrEqual,LessThan,Never,NotEqual + */ int alphaFunc; mat->GetAlphaFunc(alphaFunc); if( alphaFunc>=GL_NEVER && alphaFunc<=GL_ALWAYS) @@ -461,7 +501,7 @@ void TXPParser::loadLocalMaterials() } _localMaterials[i] = osg_state_set; } - } + } } bool TXPParser::requestModel(int ix) @@ -477,7 +517,8 @@ bool TXPParser::requestModel(int ix) void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgLod lod; - if (!lod.Read(buf)) return NULL; + if (!lod.Read(buf)) + return NULL; // Pull out the LOD data we'll need trpg3dPoint center; @@ -507,7 +548,7 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) 0, _parse->checkAndGetMinRange(minRange), _parse->checkAndGetMaxRange(maxRange) - ); + ); #endif // Our LODs are binary so we need to add a group under this LOD and attach stuff @@ -542,7 +583,8 @@ void* tileHeaderRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgModelRef model; - if (!model.Read(buf)) return NULL; + if (!model.Read(buf)) + return NULL; // Get the matrix and pfNode for the model int modelID; @@ -556,31 +598,27 @@ void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) (float)mat[12],(float)mat[13],(float)mat[14],(float)mat[15] ); - // Note: Array check before you do this osg::Node *osg_Model = NULL; - std::vector >*modelList = _parse->getModels(); - if( modelList->size() > size_t(modelID) ) + std::map >*modelList = _parse->getModels(); + osg_Model = (*modelList)[modelID].get(); + + if (osg_Model==NULL) { - osg_Model = (*modelList)[modelID].get(); + _parse->requestModel(modelID); + osg_Model = (*modelList)[modelID].get(); + } - if (osg_Model==NULL) - { - _parse->requestModel(modelID); - osg_Model = (*modelList)[modelID].get(); - } + // Create the SCS and position the model + if (osg_Model) + { + osg::MatrixTransform *scs = new osg::MatrixTransform(); + scs->setMatrix(osg_Mat); + scs->addChild(osg_Model); + scs->setUserData(new TileIdentifier(99,99,9999)); // tag to indicate a model - // Create the SCS and position the model - if (osg_Model) - { - osg::MatrixTransform *scs = new osg::MatrixTransform(); - scs->setMatrix(osg_Mat); - scs->addChild(osg_Model); - scs->setUserData(new TileIdentifier(99,99,9999)); // tag to indicate a model - - // Add the SCS to the hierarchy - _parse->setCurrentNode(scs); - _parse->getCurrTop()->addChild(scs); - } + // Add the SCS to the hierarchy + _parse->setCurrentNode(scs); + _parse->getCurrTop()->addChild(scs); } return (void *) 1; } @@ -594,7 +632,8 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { // Read in the txp billboard trpgBillboard bill; - if (!bill.Read(buf)) return NULL; + if (!bill.Read(buf)) + return NULL; if (_parse->underBillboardSubgraph()) { @@ -626,9 +665,11 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgGroup group; - if (!group.Read(buf)) return NULL; + if (!group.Read(buf)) + return NULL; - if (_parse->underLayerSubgraph()) return (void*)1; + if (_parse->underLayerSubgraph()) + return (void*)1; osg::ref_ptr osgGroup = new GeodeGroup(); _parse->setCurrentNode(osgGroup.get()); @@ -644,7 +685,8 @@ void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgAttach group; - if (!group.Read(buf)) return NULL; + if (!group.Read(buf)) + return NULL; // Create a new group osg::ref_ptr osgGroup = new osg::Group(); @@ -653,6 +695,27 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) return (void*)1; } +void* childRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) +{ + + // This object contribute nothing to the scenegraph, except + // where the children tile should connect. + // It only contain location info of the children tile + childRefList.push_back(trpgChildRef()); + trpgReadWriteable& obj = childRefList.back(); + + if(obj.Read(buf)) + return &obj; + else + return 0; + +} +void childRefRead::Reset() +{ + childRefList.clear(); +} + + //---------------------------------------------------------------------------- // // light Reader Class @@ -661,7 +724,8 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgLight light; - if (!light.Read(buf)) return NULL; + if (!light.Read(buf)) + return NULL; int attr_index; light.GetAttrIndex(attr_index); @@ -679,7 +743,7 @@ void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) trpg3dPoint pt; light.GetVertex(i, pt); osg::Matrix matrix; - // matrix.makeTranslate(pt.x,pt.y,pt.z); + // matrix.makeTranslate(pt.x,pt.y,pt.z); matrix.makeRotate(osg::Quat(0.0,dla.attitude)); matrix.setTrans(pt.x,pt.y,pt.z); osg::ref_ptr trans = new osg::MatrixTransform(); @@ -729,17 +793,11 @@ void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgLayer group; - if (!group.Read(buf)) return NULL; + if (!group.Read(buf)) + return NULL; -#if 0 - osg::Group* osgGroup = new osg::Group; - _parse->setCurrentNode(osgGroup); - _parse->getCurrTop()->addChild(osgGroup); - _parse->addLayer(osgGroup); - return (void*)1; - -#else - if (_parse->underLayerSubgraph()) return (void*)1; + if (_parse->underLayerSubgraph()) + return (void*)1; osg::ref_ptr layer = new GeodeGroup; @@ -749,7 +807,6 @@ void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) _parse->getCurrTop()->addChild(layer.get()); return (void *)1; -#endif } //---------------------------------------------------------------------------- @@ -760,10 +817,12 @@ void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgLabel label; - if (!label.Read(buf)) return NULL; + if (!label.Read(buf)) + return NULL; const std::string *labelText = label.GetText(); - if (!labelText) return (void*)1; + if (!labelText) + return (void*)1; osg::Vec3 pos(label.GetLocation().x, label.GetLocation().y, label.GetLocation().z); @@ -772,7 +831,7 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) // Text std::ostringstream os; - unsigned int nl; + std::string::size_type nl; std::string lb = *labelText; while ( (nl=lb.find_first_of('\\')) != std::string::npos) { @@ -781,7 +840,8 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { case 'n': lb.erase(0,nl+2); - if (sub.length()) os << sub << std::endl; + if (sub.length()) + os << sub << std::endl; break; case 't': lb.erase(0,nl+2); @@ -794,7 +854,8 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) } } - if (lb.length()) os << lb; + if (lb.length()) + os << lb; text->setText(os.str()); // Position @@ -822,10 +883,12 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) if (labelProperty) { const trpgTextStyleTable *textStyleTable = _parse->getArchive()->GetTextStyleTable(); - if (!textStyleTable) return (void*)1; + if (!textStyleTable) + return (void*)1; const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(labelProperty->GetFontStyle()); - if (!textStyle) return (void*)1; + if (!textStyle) + return (void*)1; // Size text->setCharacterSize(textStyle->GetCharacterSize()*label.GetScale()*2); @@ -927,20 +990,20 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) break; } - const std::vector *supports = label.GetSupports(); - if (supports && supports->size()) - { - osg::ref_ptr supGeode = new osg::Geode; + const std::vector *supports = label.GetSupports(); + if (supports && supports->size()) + { + osg::ref_ptr supGeode = new osg::Geode; - int supId = labelProperty->GetSupport(); - const trpgSupportStyleTable *supTable = _parse->getArchive()->GetSupportStyleTable(); - const trpgSupportStyle *supStyle = supTable ? supTable->GetStyleRef(supId) : 0; - if (supStyle) - { + int supId = labelProperty->GetSupport(); + const trpgSupportStyleTable *supTable = _parse->getArchive()->GetSupportStyleTable(); + const trpgSupportStyle *supStyle = supTable ? supTable->GetStyleRef(supId) : 0; + if (supStyle) + { int matId = supStyle->GetMaterial(); osg::Vec4 supLineColor(1.f,1.f,1.f,1.f); - _parse->loadMaterial(matId); + _parse->loadMaterial(matId); osg::ref_ptr sset = (*_parse->getMaterials())[matId]; if (cube.get()) @@ -965,80 +1028,80 @@ void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) } } - switch (supStyle->GetType()) - { - case trpgSupportStyle::Line: - { - osg::Geometry* linesGeom = new osg::Geometry(); - osg::Vec3Array* vertices = new osg::Vec3Array(supports->size()*2); + switch (supStyle->GetType()) + { + case trpgSupportStyle::Line: + { + osg::Geometry* linesGeom = new osg::Geometry(); + osg::Vec3Array* vertices = new osg::Vec3Array(supports->size()*2); - int cnt = 0; - for (unsigned int i = 0; i < supports->size(); i++) - { - const trpg3dPoint& supPt = (*supports)[i]; - (*vertices)[cnt++].set(pos); - (*vertices)[cnt++].set(osg::Vec3(supPt.x,supPt.y,supPt.z)); - } + int cnt = 0; + for (unsigned int i = 0; i < supports->size(); i++) + { + const trpg3dPoint& supPt = (*supports)[i]; + (*vertices)[cnt++].set(pos); + (*vertices)[cnt++].set(osg::Vec3(supPt.x,supPt.y,supPt.z)); + } - linesGeom->setVertexArray(vertices); + linesGeom->setVertexArray(vertices); - osg::Vec4Array* colors = new osg::Vec4Array; - colors->push_back(supLineColor); - linesGeom->setColorArray(colors); - linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL); + osg::Vec4Array* colors = new osg::Vec4Array; + colors->push_back(supLineColor); + linesGeom->setColorArray(colors); + linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL); - osg::Vec3Array* normals = new osg::Vec3Array; - normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f)); - linesGeom->setNormalArray(normals); - linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL); + osg::Vec3Array* normals = new osg::Vec3Array; + normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f)); + linesGeom->setNormalArray(normals); + linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL); - linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,supports->size()*2)); - supGeode->addDrawable(linesGeom); - } + linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,supports->size()*2)); + supGeode->addDrawable(linesGeom); + } - _parse->getCurrTop()->addChild(supGeode.get()); - break; - case trpgSupportStyle::Cylinder: - { - osg::ref_ptr hints = new osg::TessellationHints; - hints->setDetailRatio(0.5f); + _parse->getCurrTop()->addChild(supGeode.get()); + break; + case trpgSupportStyle::Cylinder: + { + osg::ref_ptr hints = new osg::TessellationHints; + hints->setDetailRatio(0.5f); - for (unsigned int i = 0; i < supports->size(); i++) - { - const trpg3dPoint& supPt = (*supports)[i]; + for (unsigned int i = 0; i < supports->size(); i++) + { + const trpg3dPoint& supPt = (*supports)[i]; - osg::Vec3 supPos(supPt.x,supPt.y,supPt.z); - osg::Vec3 supCenter = (supPos+pos)/2.f; - float supHeight = (supPos-pos).length(); + osg::Vec3 supPos(supPt.x,supPt.y,supPt.z); + osg::Vec3 supCenter = (supPos+pos)/2.f; + float supHeight = (supPos-pos).length(); - osg::Vec3 d = pos-supPos; - d.normalize(); - osg::Quat r; + osg::Vec3 d = pos-supPos; + d.normalize(); + osg::Quat r; - r.makeRotate(osg::Vec3(0.f,0.f,1.f),d); + r.makeRotate(osg::Vec3(0.f,0.f,1.f),d); - osg::Cylinder* cylinder = new osg::Cylinder(supCenter,10.f,supHeight); - cylinder->setRotation(r); + osg::Cylinder* cylinder = new osg::Cylinder(supCenter,10.f,supHeight); + cylinder->setRotation(r); - osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints.get()); - osg::StateSet* ss = cylinderDrawable->getOrCreateStateSet(); - ss->merge(*sset); + osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints.get()); + osg::StateSet* ss = cylinderDrawable->getOrCreateStateSet(); + ss->merge(*sset); - supGeode->addDrawable(cylinderDrawable); + supGeode->addDrawable(cylinderDrawable); - } + } - _parse->getCurrTop()->addChild(supGeode.get()); - } - break; - default: + _parse->getCurrTop()->addChild(supGeode.get()); + } + break; + default: break; - } + } - } - } + } + } } if (addTextGeodeIntoSceneGraph) { @@ -1064,39 +1127,40 @@ public: TransformFunctor(const osg::Matrix& m) { - _m = m; - _im.invert(_m); + _m = m; + _im.invert(_m); } - virtual ~TransformFunctor() {} + virtual ~TransformFunctor() + {} virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin) { - if (type == osg::Drawable::VERTICES) - { - osg::Vec3* end = begin+count; - for (osg::Vec3* itr=begin;itrfront())); } - + // Set up the primitive type switch (primType) { case trpgGeometry::Triangles: - { - geometry = new osg::Geometry; - geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,numPrims*3)); - } - break; + { + geometry = new osg::Geometry; + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,numPrims*3)); + } + break; case trpgGeometry::Quads: - { - geometry = new osg::Geometry; - geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,numPrims*4)); - } - break; + { + geometry = new osg::Geometry; + geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,numPrims*4)); + } + break; case trpgGeometry::TriStrips: - { - geometry = new osg::Geometry; - osg::DrawArrayLengths* dal = new osg::DrawArrayLengths(osg::PrimitiveSet::TRIANGLE_STRIP,0,numPrims); - geom.GetPrimLengths(reinterpret_cast(&(dal->front()))); - geometry->addPrimitiveSet(dal); - } - break; + { + geometry = new osg::Geometry; + osg::DrawArrayLengths* dal = new osg::DrawArrayLengths(osg::PrimitiveSet::TRIANGLE_STRIP,0,numPrims); + geom.GetPrimLengths(reinterpret_cast(&(dal->front()))); + geometry->addPrimitiveSet(dal); + } + break; case trpgGeometry::TriFans: - { - geometry = new osg::Geometry; - osg::DrawArrayLengths* dal = new osg::DrawArrayLengths(osg::PrimitiveSet::TRIANGLE_FAN,0,numPrims); - geom.GetPrimLengths(reinterpret_cast(&(dal->front()))); - geometry->addPrimitiveSet(dal); + { + geometry = new osg::Geometry; + osg::DrawArrayLengths* dal = new osg::DrawArrayLengths(osg::PrimitiveSet::TRIANGLE_FAN,0,numPrims); + geom.GetPrimLengths(reinterpret_cast(&(dal->front()))); + geometry->addPrimitiveSet(dal); - // Need to flip the fans coords. - int ind = 0; - int i; - for (i=0;iloadMaterial(matId); tmp_ss = (*_parse->getMaterials())[matId]; } - if(sset.valid()) + if((sset!=0L) && sset.valid()) { - if(tmp_ss.valid()){ + if(tmp_ss.valid()) + { osg::StateAttribute* texenv0 = tmp_ss->getTextureAttribute(0,osg::StateAttribute::TEXENV); if(texenv0) sset->setTextureAttribute(n_mat,texenv0); @@ -1346,46 +1412,46 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) top->addChild(billboard.get()); } else - if (_parse->underLayerSubgraph()) - { - osg::Geode* layer = _parse->getLayerGeode(); + if (_parse->underLayerSubgraph()) + { + osg::Geode* layer = _parse->getLayerGeode(); - if (layer->getNumDrawables()) - { - osg::StateSet* poStateSet = new osg::StateSet; - osg::PolygonOffset* polyoffset = new osg::PolygonOffset; + if (layer->getNumDrawables()) + { + osg::StateSet* poStateSet = new osg::StateSet; + osg::PolygonOffset* polyoffset = new osg::PolygonOffset; - poStateSet->merge(*sset.get()); - polyoffset->setFactor(-2.0f*layer->getNumDrawables()); - polyoffset->setUnits(-10.0f*layer->getNumDrawables()); - poStateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON); + poStateSet->merge(*sset.get()); + polyoffset->setFactor(-2.0f*layer->getNumDrawables()); + polyoffset->setUnits(-10.0f*layer->getNumDrawables()); + poStateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON); - geometry->setStateSet(poStateSet); - } - else - { - geometry->setStateSet(sset.get()); - } + geometry->setStateSet(poStateSet); + } + else + { + geometry->setStateSet(sset.get()); + } - layer->addDrawable(geometry.get()); - } - else - { - geometry->setStateSet(sset.get()); - if (geodeTop) - { - geodeTop->getGeode()->addDrawable(geometry.get()); - _parse->setCurrentNode(geodeTop->getGeode()); - } - else - { - osg::Geode* geode = new osg::Geode; - geode->addDrawable(geometry.get()); + layer->addDrawable(geometry.get()); + } + else + { + geometry->setStateSet(sset.get()); + if (geodeTop) + { + geodeTop->getGeode()->addDrawable(geometry.get()); + _parse->setCurrentNode(geodeTop->getGeode()); + } + else + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geometry.get()); - _parse->setCurrentNode(geode); - _parse->getCurrTop()->addChild(geode); - } - } + _parse->setCurrentNode(geode); + _parse->getCurrTop()->addChild(geode); + } + } } @@ -1420,11 +1486,6 @@ namespace internalFormat = GL_LUMINANCE_ALPHA; pixelFormat = GL_LUMINANCE_ALPHA; break; - case trpgTexture::trpg_FXT1: - case trpgTexture::trpg_Filler: - case trpgTexture::trpg_RGBX: // MCM - case trpgTexture::trpg_Unknown: - break; case trpgTexture::trpg_DDS: case trpgTexture::trpg_DXT1: if(depth == 3) @@ -1460,6 +1521,16 @@ namespace pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; } break; + case trpgTexture::trpg_MCM5: + case trpgTexture::trpg_MCM6R: + case trpgTexture::trpg_MCM6A: + case trpgTexture::trpg_MCM7RA: + case trpgTexture::trpg_MCM7AR: + case trpgTexture::trpg_FXT1: + case trpgTexture::trpg_Filler: + case trpgTexture::trpg_RGBX: // MCM + case trpgTexture::trpg_Unknown: + break; } } } @@ -1504,7 +1575,7 @@ osg::Texture2D* txp::getLocalTexture(trpgrImageHelper& image_helper, const trpgT data = new char [size]; image_helper.GetLocalGL(tex,data,size); image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType, - (unsigned char*)data,osg::Image::USE_NEW_DELETE); + (unsigned char*)data,osg::Image::USE_NEW_DELETE); } else { @@ -1515,8 +1586,8 @@ osg::Texture2D* txp::getLocalTexture(trpgrImageHelper& image_helper, const trpgT image_helper.GetLocalGL(tex,data,size); // Load entire texture including mipmaps image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType, - (unsigned char*)data, - osg::Image::USE_NEW_DELETE); + (unsigned char*)data, + osg::Image::USE_NEW_DELETE); // now set mipmap data (offsets into image raw data) osg::Image::MipmapDataType mipmaps; @@ -1577,7 +1648,7 @@ osg::Texture2D* txp::getTemplateTexture(trpgrImageHelper& image_helper, trpgLoca image_helper.GetNthImageForLocalMat(locmat,index, data,size); image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType, - (unsigned char*)data,osg::Image::USE_NEW_DELETE); + (unsigned char*)data,osg::Image::USE_NEW_DELETE); } else { @@ -1590,8 +1661,8 @@ osg::Texture2D* txp::getTemplateTexture(trpgrImageHelper& image_helper, trpgLoca // Load entire texture including mipmaps image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType, - (unsigned char*)data, - osg::Image::USE_NEW_DELETE); + (unsigned char*)data, + osg::Image::USE_NEW_DELETE); // now set mipmap data (offsets into image raw data) osg::Image::MipmapDataType mipmaps; diff --git a/src/osgPlugins/txp/TXPParser.h b/src/osgPlugins/txp/TXPParser.h index d29e579b0..e68f2f138 100644 --- a/src/osgPlugins/txp/TXPParser.h +++ b/src/osgPlugins/txp/TXPParser.h @@ -79,11 +79,11 @@ class GeodeGroup : public osg::Group public: GeodeGroup() : osg::Group(), _geode(NULL) - {}; + {} GeodeGroup(const GeodeGroup& gg,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): osg::Group(gg, copyop), _geode(gg._geode) - {}; + {} META_Node(txp, GeodeGroup); @@ -103,6 +103,7 @@ protected: class TXPArchive; +class childRefRead; struct DeferredLightAttribute; class TXPParser : public trpgSceneParser, public osg::Referenced @@ -116,14 +117,17 @@ public: _archive = archive; } - // Gets the archive - inline TXPArchive* getArchive() { return _archive; } + // Gets the archive + inline TXPArchive* getArchive() + { + return _archive; + } // Scene parser osg::Group *parseScene( trpgReadBuffer &buf, - std::vector > &materials, - std::vector > &models, + std::map > &materials, + std::map > &models, double realMinRange, double realMaxRange, double usedMaxRange); // Returns the current Top Group @@ -139,13 +143,16 @@ public: } // Return the current material list (passed in to ParseScene()) - inline std::vector >* getMaterials() + inline std::map >* getMaterials() { - return _materials; + return _materialMap; } - // Ensure material is loaded - inline void loadMaterial(int ix) { _archive->loadMaterial(ix); } + // Ensure material is loaded + inline void loadMaterial( int ix ) + { + _archive->loadMaterial( ix ); + } // New to TerraPage 2.0 - local materials std::vector >* getLocalMaterials() @@ -157,7 +164,7 @@ public: void loadLocalMaterials(); // Return the current model list - std::vector >* getModels() + std::map >* getModels() { return _models; } @@ -260,9 +267,23 @@ public: } // gets tile center, from the top lod node - inline const osg::Vec3 getTileCenter() const { return _tileCenter; } + inline const osg::Vec3 getTileCenter() const + { + return _tileCenter; + } - inline void setCurrentNode(osg::Node* node) { _currentNode = node; } + inline void setCurrentNode( osg::Node* node ) + { + _currentNode = node; + } + + // After parsing this will return the number of trpgChildRef node found. + unsigned int GetNbChildrenRef() const; + + // This will return the trpgChildRef node pointer associated with the index. + // Will return 0 if index is out of bound + const trpgChildRef* GetChildRef(unsigned int idx) const; + protected: @@ -300,13 +321,15 @@ protected: void replaceTileLod(osg::Group*); // Materials - std::vector >* _materials; + typedef std::map >* MaterialMapType; + MaterialMapType _materialMap; // Local materials std::vector > _localMaterials; // Model list - std::vector >* _models; + typedef std::map > OSGModelsMapType; + OSGModelsMapType* _models; // Tile header trpgTileHeader _tileHeader; @@ -342,6 +365,11 @@ protected: // TEMP osg::Geode* createBoundingBox(int x,int y, int lod); + + private: + + childRefRead *_childRefCB; + }; @@ -353,7 +381,7 @@ class geomRead : public trpgr_Callback public: geomRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -365,7 +393,7 @@ class groupRead : public trpgr_Callback { public: groupRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -376,10 +404,48 @@ class attachRead : public trpgr_Callback { public: attachRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; + +}; +//---------------------------------------------------------------------------- +class childRefRead : public trpgr_Callback +{ +public: + typedef std::vector ChildRefList; + + childRefRead(TXPParser *in_parse) : _parse(in_parse) + {} + void Reset(); + void *Parse(trpgToken tok,trpgReadBuffer &buf); + + // After parsing this will return the number of trpgChildRef node found. + unsigned int GetNbChildrenRef() const + { + return childRefList.size(); + } + // This will return the trpgChildRef node associated with the index. + // this will return 0 if idx is out of bound + const trpgChildRef* GetChildRef(unsigned int idx) const + { + if(idx >= childRefList.size()) + return 0; + else + return &childRefList[idx]; + } + +protected: + TXPParser *_parse; + + + +private: + + ChildRefList childRefList; + + }; //---------------------------------------------------------------------------- @@ -387,7 +453,7 @@ class lodRead : public trpgr_Callback { public: lodRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -398,7 +464,7 @@ class tileHeaderRead : public trpgr_Callback { public: tileHeaderRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -410,7 +476,7 @@ class modelRefRead : public trpgr_Callback { public: modelRefRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -421,7 +487,7 @@ class billboardRead : public trpgr_Callback { public: billboardRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -432,7 +498,7 @@ class lightRead: public trpgr_Callback { public: lightRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -443,7 +509,7 @@ class layerRead: public trpgr_Callback { public: layerRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; @@ -454,7 +520,7 @@ class labelRead: public trpgr_Callback { public: labelRead(TXPParser *in_parse) : _parse(in_parse) - {}; + {} void *Parse(trpgToken tok,trpgReadBuffer &buf); protected: TXPParser *_parse; diff --git a/src/osgPlugins/txp/TXPSeamLOD.cpp b/src/osgPlugins/txp/TXPSeamLOD.cpp index 1456b4c38..57c1c6c76 100644 --- a/src/osgPlugins/txp/TXPSeamLOD.cpp +++ b/src/osgPlugins/txp/TXPSeamLOD.cpp @@ -37,6 +37,7 @@ void TXPSeamLOD::traverse(osg::NodeVisitor& nv) { TileMapper* tileMapper = dynamic_cast(nv.getUserData()); + if (tileMapper && !tileMapper->isTileNeighbourALowerLODLevel(_tid,_dx,_dy)) { getChild(1)->accept(nv); diff --git a/src/osgPlugins/txp/TXPSeamLOD.h b/src/osgPlugins/txp/TXPSeamLOD.h index e3a97de06..3f75845ac 100644 --- a/src/osgPlugins/txp/TXPSeamLOD.h +++ b/src/osgPlugins/txp/TXPSeamLOD.h @@ -1,3 +1,4 @@ +// -*-c++-*- /*************************************************************************** * December 2003 * @@ -58,12 +59,15 @@ public: virtual void traverse(osg::NodeVisitor& nv); + void setCenter( const osg::Vec3& center ) { _center = center; } + osg::Vec3 getCenter() { return _center; } protected: TileIdentifier _tid; int _dx; int _dy; + osg::Vec3 _center; }; } diff --git a/src/osgPlugins/txp/TileMapper.cpp b/src/osgPlugins/txp/TileMapper.cpp index 85270ebb3..78a7ac64b 100644 --- a/src/osgPlugins/txp/TileMapper.cpp +++ b/src/osgPlugins/txp/TileMapper.cpp @@ -21,8 +21,10 @@ using namespace txp; float TileMapper::getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const { - if (withLODScale) return (pos-getEyeLocal()).length()*getLODScale(); - else return (pos-getEyeLocal()).length(); + if (withLODScale) + return (pos-getEyeLocal()).length()*getLODScale(); + else + return (pos-getEyeLocal()).length(); } inline TileMapper::value_type distance(const osg::Vec3& coord,const osg::Matrix& matrix) @@ -30,7 +32,10 @@ inline TileMapper::value_type distance(const osg::Vec3& coord,const osg::Matrix& //std::cout << "distance("<(node.getUserData()); if (tid) @@ -95,9 +104,9 @@ void TileMapper::apply(osg::Group& node) #if 0 std::cout<<"found Group="<lod - <<" X="<x - <<" Y="<y - <<" ptr="<<&node< #include @@ -36,9 +36,9 @@ // Constructor trpgGeometry::trpgGeometry() { - primType = Polygons; - normBind = Overall; - numPrim = 0; + primType = Polygons; + normBind = Overall; + numPrim = 0; } trpgGeometry::~trpgGeometry() { @@ -47,143 +47,143 @@ trpgGeometry::~trpgGeometry() // Reset function void trpgGeometry::Reset() { - primType = Polygons; - numPrim = 0; - primLength.resize(0); - materials.resize(0); - vertDataFloat.resize(0); - vertDataDouble.resize(0); - normBind = Overall; - normDataFloat.resize(0); - normDataDouble.resize(0); - colors.resize(0); - texData.resize(0); - edgeFlags.resize(0); + primType = Polygons; + numPrim = 0; + primLength.resize(0); + materials.resize(0); + vertDataFloat.resize(0); + vertDataDouble.resize(0); + normBind = Overall; + normDataFloat.resize(0); + normDataDouble.resize(0); + colors.resize(0); + texData.resize(0); + edgeFlags.resize(0); } // Set functions void trpgGeometry::SetPrimType(PrimType type) { - primType = type; + primType = type; } void trpgGeometry::SetPrimLengths(int num,const int *len) { - if (num < 0) - return; + if (num < 0) + return; - numPrim = num; - for (int i=0;i= (int)materials.size()) - return; + if (which < 0 || which >= (int)materials.size()) + return; - materials[which] = (isLocal ? -(mat+1) : mat); + materials[which] = (isLocal ? -(mat+1) : mat); } void trpgGeometry::SetMaterials(int32 num,const int32 *mat) { - materials.resize(num); - for (int i=0;i(pt.x)); vertDataFloat.push_back(static_cast(pt.y)); vertDataFloat.push_back(static_cast(pt.z)); - } else { - vertDataDouble.push_back(pt.x); - vertDataDouble.push_back(pt.y); - vertDataDouble.push_back(pt.z); - } + } else { + vertDataDouble.push_back(pt.x); + vertDataDouble.push_back(pt.y); + vertDataDouble.push_back(pt.z); + } } void trpgGeometry::SetNormals(int num,BindType bind,const float32 *data) { - if (num < 0) - return; + if (num < 0) + return; - normBind = bind; - normDataFloat.resize(0); - normDataDouble.resize(0); - for (int i=0;i<3*num;i++) - normDataFloat.push_back(data[i]); + normBind = bind; + normDataFloat.resize(0); + normDataDouble.resize(0); + for (int i=0;i<3*num;i++) + normDataFloat.push_back(data[i]); } void trpgGeometry::SetNormals(int num,BindType bind,const float64 *data) { - if (num <0) - return; + if (num <0) + return; - normBind = bind; - normDataFloat.resize(0); - normDataDouble.resize(0); - for (int i=0;i<3*num;i++) - normDataDouble.push_back(data[i]); + normBind = bind; + normDataFloat.resize(0); + normDataDouble.resize(0); + for (int i=0;i<3*num;i++) + normDataDouble.push_back(data[i]); } void trpgGeometry::AddNormal(DataType type,trpg3dPoint &pt) { - if (type == FloatData) { + if (type == FloatData) { normDataFloat.push_back(static_cast(pt.x)); normDataFloat.push_back(static_cast(pt.y)); normDataFloat.push_back(static_cast(pt.z)); - } else { - normDataDouble.push_back(pt.x); - normDataDouble.push_back(pt.y); - normDataDouble.push_back(pt.z); - } + } else { + normDataDouble.push_back(pt.x); + normDataDouble.push_back(pt.y); + normDataDouble.push_back(pt.z); + } } // Constructor trpgColorInfo::trpgColorInfo() @@ -194,24 +194,24 @@ trpgColorInfo::~trpgColorInfo() } void trpgColorInfo::Reset() { - bind = 0; - type = 0; - data.resize(0); + bind = 0; + type = 0; + data.resize(0); } void trpgGeometry::SetColors(int num,ColorType type,BindType bind,const trpgColor *data) { - trpgColorInfo ci; + trpgColorInfo ci; - if (num < 0) - return; + if (num < 0) + return; - // Set up color list - ci.type = type; - ci.bind = bind; - for (int i=0;i= (int)texData.size())) - return; - trpgTexData *td = &texData[n]; + if ((n<0) || (n >= (int)texData.size())) + return; + trpgTexData *td = &texData[n]; - if (type == FloatData) { + if (type == FloatData) { td->floatData.push_back(static_cast(pt.x)); td->floatData.push_back(static_cast(pt.y)); - } else { - td->doubleData.push_back(pt.x); - td->doubleData.push_back(pt.y); - } + } else { + td->doubleData.push_back(pt.x); + td->doubleData.push_back(pt.y); + } } void trpgGeometry::AddTexCoord(DataType type,std::vector &pts) { - if (texData.size() != pts.size()) - return; + if (texData.size() != pts.size()) + return; - for (unsigned int loop = 0; loop < pts.size(); loop++ ) { - trpgTexData *td = &texData[loop]; + for (unsigned int loop = 0; loop < pts.size(); loop++ ) { + trpgTexData *td = &texData[loop]; - if (type == FloatData) { + if (type == FloatData) { td->floatData.push_back(static_cast(pts[loop].x)); td->floatData.push_back(static_cast(pts[loop].y)); - } else { - td->doubleData.push_back(pts[loop].x); - td->doubleData.push_back(pts[loop].y); - } - } + } else { + td->doubleData.push_back(pts[loop].x); + td->doubleData.push_back(pts[loop].y); + } + } } void trpgGeometry::AddTexCoords(BindType bind) { - trpgTexData td; - td.bind = bind; - texData.push_back(td); + trpgTexData td; + td.bind = bind; + texData.push_back(td); } void trpgGeometry::SetEdgeFlags(int num,const char *flags) { - if (num < 0) - return; + if (num < 0) + return; - edgeFlags.resize(0); - for (int i=0;i= (int)materials.size()) return false; - m = materials[id]; - if (m < 0) { - m = -m - 1; - isLocal = true; - } - return true; + isLocal = false; + if (!isValid() || id < 0 || id >= (int)materials.size()) return false; + m = materials[id]; + if (m < 0) { + m = -m - 1; + isLocal = true; + } + return true; } bool trpgGeometry::GetNumVertex(int &v) const { - if (!isValid()) return false; - int nvf = vertDataFloat.size(); - int nvd = vertDataDouble.size(); - v = MAX(nvf,nvd); - v = v / 3; - return true; + if (!isValid()) return false; + 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; + unsigned int i; - if (!isValid()) return false; - if (vertDataFloat.size() != 0) - for (i=0;i(vertDataDouble[i]); - return true; + return true; } bool trpgGeometry::GetVertices(float64 *v) const { - unsigned int i; + unsigned int i; - if (!isValid()) return false; - if (vertDataFloat.size() != 0) - for (i=0;i= (int)vertDataFloat.size() && idMax >= (int)vertDataDouble.size())) - return false; - if (vertDataFloat.size() > vertDataDouble.size()) { - pt.x = vertDataFloat[id]; - pt.y = vertDataFloat[id+1]; - pt.z = vertDataFloat[id+2]; - } else { - pt.x = vertDataDouble[id]; - pt.y = vertDataDouble[id+1]; - pt.z = vertDataDouble[id+2]; - } - return true; + int id = 3*n; + int idMax = 3*n+2; + if (id < 0 || (idMax >= (int)vertDataFloat.size() && idMax >= (int)vertDataDouble.size())) + return false; + if (vertDataFloat.size() > vertDataDouble.size()) { + pt.x = vertDataFloat[id]; + pt.y = vertDataFloat[id+1]; + pt.z = vertDataFloat[id+2]; + } else { + pt.x = vertDataDouble[id]; + pt.y = vertDataDouble[id+1]; + pt.z = vertDataDouble[id+2]; + } + return true; } bool trpgGeometry::GetNumNormal(int32 &n) const { - if (!isValid()) return false; - if (normDataFloat.size() != 0) - n = normDataFloat.size(); - if (normDataDouble.size() != 0) - n = normDataDouble.size(); - n = n / 3; - return true; + if (!isValid()) return false; + if (normDataFloat.size() != 0) + n = normDataFloat.size(); + if (normDataDouble.size() != 0) + n = normDataDouble.size(); + n = n / 3; + return true; } bool trpgGeometry::GetNormals(float32 *v) const { - unsigned int i; + unsigned int i; - if (!isValid()) return false; - if (normDataFloat.size() != 0) - for (i=0;i(normDataDouble[i]); - return true; + return true; } bool trpgGeometry::GetNormals(float64 *v) const { - unsigned int i; + unsigned int i; - if (!isValid()) return false; - if (normDataFloat.size() != 0) - for (i=0;i= (int)colors.size()) return false; - *ci = colors[id]; - return true; + if (!isValid() || id < 0 || id >= (int)colors.size()) return false; + *ci = colors[id]; + return true; } bool trpgGeometry::GetNumTexCoordSets(int &n) const { - if (!isValid()) return false; - n = texData.size(); - return true; + if (!isValid()) return false; + n = texData.size(); + return true; } bool trpgGeometry::GetTexCoordSet(int id,trpgTexData *tx) const { - if (!isValid() || id < 0 || id >= (int)texData.size()) return false; - *tx = texData[id]; - return true; + if (!isValid() || id < 0 || id >= (int)texData.size()) return false; + *tx = texData[id]; + return true; } - const trpgTexData *trpgGeometry::GetTexCoordSet(int id) const { if (!isValid() || id < 0 || id >= (int)texData.size()) return 0; return &(texData[id]); } - - bool trpgGeometry::GetNumEdgeFlag(int &n) const { - if (!isValid()) return false; - n = edgeFlags.size(); - return true; + if (!isValid()) return false; + n = edgeFlags.size(); + return true; } bool trpgGeometry::GetEdgeFlags(char *e) const { - if (!isValid()) return false; - for (unsigned int i=0;i 0) { - buf.Begin(TRPG_GEOM_MATERIAL); - buf.Add((int32)materials.size()); - for (i=0;i 0) { + buf.Begin(TRPG_GEOM_MATERIAL); + buf.Add((int32)materials.size()); + for (i=0;i 0) { - buf.Begin(TRPG_GEOM_VERT32); - int32 num = vertDataFloat.size()/3; - buf.Add(num); + /* Vertices + Float and Double should never both be here + Num vertex + Vertex data + */ + if (vertDataFloat.size() > 0) { + buf.Begin(TRPG_GEOM_VERT32); + int32 num = vertDataFloat.size()/3; + buf.Add(num); for (i=0;i<(unsigned int)3*num;i++) - buf.Add(vertDataFloat[i]); - buf.End(); - } - if (vertDataDouble.size() > 0) { - buf.Begin(TRPG_GEOM_VERT64); - int32 num = vertDataDouble.size()/3; - buf.Add(num); + buf.Add(vertDataFloat[i]); + buf.End(); + } + if (vertDataDouble.size() > 0) { + buf.Begin(TRPG_GEOM_VERT64); + int32 num = vertDataDouble.size()/3; + buf.Add(num); for (i=0;i<(unsigned int)3*num;i++) - buf.Add(vertDataDouble[i]); - buf.End(); - } + buf.Add(vertDataDouble[i]); + buf.End(); + } - /* Normals - Normal binding - Num normals - Normal data - */ - if (normDataFloat.size() > 0) { - buf.Begin(TRPG_GEOM_NORM32); - buf.Add((int32)normBind); - int32 num = normDataFloat.size()/3; - buf.Add(num); + /* Normals + Normal binding + Num normals + Normal data + */ + if (normDataFloat.size() > 0) { + buf.Begin(TRPG_GEOM_NORM32); + buf.Add((int32)normBind); + int32 num = normDataFloat.size()/3; + buf.Add(num); for (i=0;i<(unsigned int)3*num;i++) - buf.Add(normDataFloat[i]); - buf.End(); - } - if (normDataDouble.size() > 0) { - buf.Begin(TRPG_GEOM_NORM64); - buf.Add((int32)normBind); - int32 num = normDataDouble.size()/3; - buf.Add(num); + buf.Add(normDataFloat[i]); + buf.End(); + } + if (normDataDouble.size() > 0) { + buf.Begin(TRPG_GEOM_NORM64); + buf.Add((int32)normBind); + int32 num = normDataDouble.size()/3; + buf.Add(num); for (i=0;i<(unsigned int)3*num;i++) - buf.Add(normDataDouble[i]); - buf.End(); - } + buf.Add(normDataDouble[i]); + buf.End(); + } - /* Colors - Color binding - Num colors - Colors - */ - if (colors.size() > 0) { - for (i=0;i 0) { + for (i=0;i 0) { - buf.Begin(TRPG_GEOM_EFLAG); - buf.Add((int32)edgeFlags.size()); - for (i=0;i 0) { + buf.Begin(TRPG_GEOM_EFLAG); + buf.Add((int32)edgeFlags.size()); + for (i=0;iSetPrimType((trpgGeometry::PrimType)primType); - buf.Get(num); - if (num < 0) throw 1; - geom->SetNumPrims(num); - buf.Get(hasPrimLen); - if (hasPrimLen) { - buf.GetArray(num,&iData); + try { + switch (tok) { + case TRPG_GEOM_PRIM: + buf.Get(primType); + geom->SetPrimType((trpgGeometry::PrimType)primType); + buf.Get(num); + if (num < 0) throw 1; + geom->SetNumPrims(num); + buf.Get(hasPrimLen); + if (hasPrimLen) { + buf.GetArray(num,&iData); if (ALIGNMENT_WORKAROUND) { int32 *aligned; @@ -672,13 +669,13 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetPrimLengths(num,iData); - } - break; - case TRPG_GEOM_MATERIAL: - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(num,&iData); + geom->SetPrimLengths(num,iData); + } + break; + case TRPG_GEOM_MATERIAL: + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(num,&iData); if (ALIGNMENT_WORKAROUND) { int32 *aligned; @@ -688,12 +685,12 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetMaterials(num,iData); - break; - case TRPG_GEOM_VERT32: - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(3*num,&fData); + geom->SetMaterials(num,iData); + break; + case TRPG_GEOM_VERT32: + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(3*num,&fData); if (ALIGNMENT_WORKAROUND) { float32 *aligned; @@ -703,12 +700,12 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetVertices(num,fData); - break; - case TRPG_GEOM_VERT64: - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(3*num,&dData); + geom->SetVertices(num,fData); + break; + case TRPG_GEOM_VERT64: + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(3*num,&dData); if (ALIGNMENT_WORKAROUND) { float64 *aligned; @@ -718,14 +715,14 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetVertices(num,dData); - break; - case TRPG_GEOM_NORM32: - buf.Get(bind); - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(3*num,&fData); - if (ALIGNMENT_WORKAROUND) + geom->SetVertices(num,dData); + break; + case TRPG_GEOM_NORM32: + buf.Get(bind); + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(3*num,&fData); + if (ALIGNMENT_WORKAROUND) { float32 *aligned; aligned = (float32 *)calloc (3*num, sizeof(float32)); @@ -734,13 +731,13 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetNormals(num,(trpgGeometry::BindType)bind,fData); - break; - case TRPG_GEOM_NORM64: - buf.Get(bind); - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(3*num,&dData); + geom->SetNormals(num,(trpgGeometry::BindType)bind,fData); + break; + case TRPG_GEOM_NORM64: + buf.Get(bind); + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(3*num,&dData); if (ALIGNMENT_WORKAROUND) { float64 *aligned; @@ -750,14 +747,14 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetNormals(num,(trpgGeometry::BindType)bind,dData); - break; - case TRPG_GEOM_COLOR: - buf.Get(num); - if (num < 0) throw 1; - buf.Get(type); - buf.Get(bind); - buf.GetArray(num,&cData); + geom->SetNormals(num,(trpgGeometry::BindType)bind,dData); + break; + case TRPG_GEOM_COLOR: + buf.Get(num); + if (num < 0) throw 1; + buf.Get(type); + buf.Get(bind); + buf.GetArray(num,&cData); if (ALIGNMENT_WORKAROUND) { trpgColor *aligned; @@ -767,13 +764,13 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetColors(num,(trpgGeometry::ColorType)type,(trpgGeometry::BindType)bind,cData); - break; - case TRPG_GEOM_TEX32: - buf.Get(bind); - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(2*num,&fData); + geom->SetColors(num,(trpgGeometry::ColorType)type,(trpgGeometry::BindType)bind,cData); + break; + case TRPG_GEOM_TEX32: + buf.Get(bind); + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(2*num,&fData); if (ALIGNMENT_WORKAROUND) { float32 *aligned; @@ -783,13 +780,13 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetTexCoords(num,(trpgGeometry::BindType)bind,fData); - break; - case TRPG_GEOM_TEX64: - buf.Get(bind); - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(2*num,&dData); + geom->SetTexCoords(num,(trpgGeometry::BindType)bind,fData); + break; + case TRPG_GEOM_TEX64: + buf.Get(bind); + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(2*num,&dData); if (ALIGNMENT_WORKAROUND) { float64 *aligned; @@ -799,44 +796,44 @@ void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf) free (aligned); } else - geom->SetTexCoords(num,(trpgGeometry::BindType)bind,dData); - break; - case TRPG_GEOM_EFLAG: - buf.Get(num); - if (num < 0) throw 1; - buf.GetArray(num,&charData); - geom->SetEdgeFlags(num,charData); - break; - default: - // Skip - break; - } - } - catch (...) { - return NULL; - } + geom->SetTexCoords(num,(trpgGeometry::BindType)bind,dData); + break; + case TRPG_GEOM_EFLAG: + buf.Get(num); + if (num < 0) throw 1; + buf.GetArray(num,&charData); + geom->SetEdgeFlags(num,charData); + break; + default: + // Skip + break; + } + } + catch (...) { + return NULL; + } - return geom; + return geom; } // Read Geometry bool trpgGeometry::Read(trpgReadBuffer &buf) { - trpgr_Parser parse; - geomCB gcb; + trpgr_Parser parse; + geomCB gcb; - gcb.geom = this; - parse.AddCallback(TRPG_GEOM_PRIM,&gcb,false); - parse.AddCallback(TRPG_GEOM_MATERIAL,&gcb,false); - parse.AddCallback(TRPG_GEOM_VERT32,&gcb,false); - parse.AddCallback(TRPG_GEOM_VERT64,&gcb,false); - parse.AddCallback(TRPG_GEOM_NORM32,&gcb,false); - parse.AddCallback(TRPG_GEOM_NORM64,&gcb,false); - parse.AddCallback(TRPG_GEOM_COLOR,&gcb,false); - parse.AddCallback(TRPG_GEOM_TEX32,&gcb,false); - parse.AddCallback(TRPG_GEOM_TEX64,&gcb,false); - parse.AddCallback(TRPG_GEOM_EFLAG,&gcb,false); - parse.Parse(buf); + gcb.geom = this; + parse.AddCallback(TRPG_GEOM_PRIM,&gcb,false); + parse.AddCallback(TRPG_GEOM_MATERIAL,&gcb,false); + parse.AddCallback(TRPG_GEOM_VERT32,&gcb,false); + parse.AddCallback(TRPG_GEOM_VERT64,&gcb,false); + parse.AddCallback(TRPG_GEOM_NORM32,&gcb,false); + parse.AddCallback(TRPG_GEOM_NORM64,&gcb,false); + parse.AddCallback(TRPG_GEOM_COLOR,&gcb,false); + parse.AddCallback(TRPG_GEOM_TEX32,&gcb,false); + parse.AddCallback(TRPG_GEOM_TEX64,&gcb,false); + parse.AddCallback(TRPG_GEOM_EFLAG,&gcb,false); + parse.Parse(buf); - return isValid(); + return isValid(); } diff --git a/src/osgPlugins/txp/trpage_geom.h b/src/osgPlugins/txp/trpage_geom.h index 37315e5c2..8fa27cf5c 100644 --- a/src/osgPlugins/txp/trpage_geom.h +++ b/src/osgPlugins/txp/trpage_geom.h @@ -17,15 +17,17 @@ #define _trpage_geom_h_ /* trpage_geom.h - Geometry and node definitions. - These are the objects that get read from and written to archives. - */ + Geometry and node definitions. + These are the objects that get read from and written to archives. +*/ #include #include #include + + // Forward declarations class trpgMaterial; @@ -33,139 +35,186 @@ class trpgTextureEnv; class trpgMatTable; /* This is the archive header structure. There is one per TerraPage archive. - You don't write it directly, but instead fill it out and pass it to - a trpgwArchive (if you're writing), or get it back from a trpgr_Archive - (if you're reading). - If you're putting together a reader, just use the default methods for - reading this class. Since it's only read once, the overhead is low. - {group:Read/Write Classes} - */ -TX_EXDECL class TX_CLDECL trpgHeader : public trpgReadWriteable { -public: + You don't write it directly, but instead fill it out and pass it to + a trpgwArchive (if you're writing), or get it back from a trpgr_Archive + (if you're reading). + If you're putting together a reader, just use the default methods for + reading this class. Since it's only read once, the overhead is low. + {group:Read/Write Classes} +*/ +TX_EXDECL class TX_CLDECL trpgHeader : public trpgReadWriteable +{ + public: trpgHeader(void); ~trpgHeader(void); // Set the TerraPage version info. - void SetVersion(int major,int minor); + void SetVersion(int major,int minor); // Set the database version info. - void SetDbVersion(int major,int minor); + void SetDbVersion(int major,int minor); /* Set the tile size for the given LOD. See GetTileSize for more info. - Each LOD must have its size set, otherwise the trpgHeader won't be valid. - You must set the number of LODs with SetNumLods first. - You should use the AddLod method if you can, which handles all of this. - */ - void SetTileSize(int lod,const trpg2dPoint &size); + Each LOD must have its size set, otherwise the trpgHeader won't be valid. + You must set the number of LODs with SetNumLods first. + You should use the AddLod method if you can, which handles all of this. + */ + void SetTileSize(int lod,const trpg2dPoint &size); // Origin defaults to 0,0,0 - void SetOrigin(const trpg3dPoint &); + void SetOrigin(const trpg3dPoint &); // 2D archive extents. Must be set. - void SetExtents(const trpg2dPoint &sw,const trpg2dPoint &ne); + void SetExtents(const trpg2dPoint &sw,const trpg2dPoint &ne); typedef enum {DatabaseLocal,Absolute,TileLocal} trpgTileType; // How the coordinates are treated with respect to real world values. - void SetTileOriginType(trpgTileType); + void SetTileOriginType(trpgTileType); /* Number of terrain LODs. If you use this method when building a database - you have to use the SetLodRange and SetLodSize methods on each LOD as well. - It's better to use AddLod instead of calling these three methods. - */ - void SetNumLods(int); + you have to use the SetLodRange and SetLodSize methods on each LOD as well. + It's better to use AddLod instead of calling these three methods. + */ + void SetNumLods(int); /* Number of tiles (x,y) for each LOD. - The single argument version assumes lod = 0, num lods = 1. - */ - void SetLodSize(int lod,const trpg2iPoint &); - void SetLodSize(const trpg2iPoint *); + The single argument version assumes lod = 0, num lods = 1. + */ + void SetLodSize(int lod,const trpg2iPoint &); + void SetLodSize(const trpg2iPoint *); /* Set the range for the given terrain LOD. - The single argument version assumes lod = 0, num lods = 1. - */ - void SetLodRange(int,float64); - void SetLodRange(const float64 *); + The single argument version assumes lod = 0, num lods = 1. + */ + void SetLodRange(int,float64); + void SetLodRange(const float64 *); // Increase the number of terrain LODs, adding a new one with the given size and range - void AddLod(const trpg2iPoint &size,const trpg2dPoint &ext,float64 range); + void AddLod(const trpg2iPoint &size,const trpg2dPoint &ext,float64 range); + + // Set details for an LOD, resizing if necessary + void SetLod(const trpg2iPoint &size,const trpg2dPoint &ext,float64 range,unsigned int lod); // Keep track of the maximum assigned group IDs (for tile paging) - void SetMaxGroupID(int); + void SetMaxGroupID(int); /* Instead of keeping a count of all the group IDs you added and then - calling SetMaxGroupID, you can call this function and it will return - the next valid groupID to you. It will also keep track of the maximum. - */ - int AddGroupID(void); + calling SetMaxGroupID, you can call this function and it will return + the next valid groupID to you. It will also keep track of the maximum. + */ + int AddGroupID(void); // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // TerraVista version information is two integers. - bool GetVersion(int &,int &) const; + bool GetVersion(int &,int &) const; // Database version information is user defined. Put whatever you want here. - bool GetDbVersion(int &,int &) const; + bool GetDbVersion(int &,int &) const; /* This is the extents, in X/Y of a - single tile. All tiles within an LOD should be the same size (although this is not - enforced). It's also assumed that a given tile lives entirely within - its own extents (as calculated with this value), although that's not - enforced either. */ - bool GetTileSize(int,trpg2dPoint &) const; + single tile. All tiles within an LOD should be the same size (although this is not + enforced). It's also assumed that a given tile lives entirely within + its own extents (as calculated with this value), although that's not + enforced either. */ + bool GetTileSize(int,trpg2dPoint &) const; /* The meaning of the database origin varies depending on the value returned - by GetTileOriginType. If the database is Absolute, then this value - will be the lower left corner. If the database is DatabaseLocal or - TileLocal you can use this value to determine the real world coordinates. - Just add origin + coordinate. - */ - bool GetOrigin(trpg3dPoint &) const; + by GetTileOriginType. If the database is Absolute, then this value + will be the lower left corner. If the database is DatabaseLocal or + TileLocal you can use this value to determine the real world coordinates. + Just add origin + coordinate. + */ + bool GetOrigin(trpg3dPoint &) const; /* These are the 2D extents that the database covers. You can use this - information to determine where the middle is, for example. - */ - bool GetExtents(trpg2dPoint &sw,trpg2dPoint &ne) const; + information to determine where the middle is, for example. + */ + bool GetExtents(trpg2dPoint &sw,trpg2dPoint &ne) const; /* The tile origin type tells you the coordinate system of each database - tile. There are three type: - * Absolute - All coordinate values are absolute. No translation is required. - * DatabaseLocal - All coordinate values are local to the database. That is - if you want to determine the real world value do: coord + origin. - * TileLocal - Each tile has its own coordinate system starting from the lower left - corner. We do this to get around floating point accuracy problems (although we - can do Double coordinates if necessary, as well). To determine the - real world coordinate value do: tileID*tileSize + coord. - */ - bool GetTileOriginType(trpgTileType &) const; + tile. There are three type: + * Absolute - All coordinate values are absolute. No translation is required. + * DatabaseLocal - All coordinate values are local to the database. That is + if you want to determine the real world value do: coord + origin. + * TileLocal - Each tile has its own coordinate system starting from the lower left + corner. We do this to get around floating point accuracy problems (although we + can do Double coordinates if necessary, as well). To determine the + real world coordinate value do: tileID*tileSize + coord. + */ + bool GetTileOriginType(trpgTileType &) const; /* Group IDs are used by TerraPage to hook level of detail structures together. - A TerraPage database can have an arbitrary number of terrain LODs, each stored - seperately. To hook them together we use trpgAttach nodes and number each group & - LOD node. This returns the maximum group ID in the file, which is important - to know if you're keeping an array of them. */ - bool GetMaxGroupID(int &) const; + A TerraPage database can have an arbitrary number of terrain LODs, each stored + seperately. To hook them together we use trpgAttach nodes and number each group & + LOD node. This returns the maximum group ID in the file, which is important + to know if you're keeping an array of them. */ + bool GetMaxGroupID(int &) const; /* A TerraPage archive can contain any number of terrain LODs (a typical number is 4). - Each of these terrain LODs is accessed seperately (as are the tiles within them). - This returns the number of terrain LODs in the file. It will be at least 1. - See trpgAttach for instructions on how to hook the terrain LODs together. - */ - bool GetNumLods(int32 &) const; + Each of these terrain LODs is accessed seperately (as are the tiles within them). + This returns the number of terrain LODs in the file. It will be at least 1. + See trpgAttach for instructions on how to hook the terrain LODs together. + + For version 2.1 and over, this number represent the depest lod that was found + in the gaming area. With variable lod, tiles will not ncessarily fill out all of + the gaming area for all of the lods. trpgAttach node are no longer used, instead + see trpgChildRef + */ + bool GetNumLods(int32 &) const; /* A terrain LOD conceptually covers the entire database and is broken up - into some X x Y set of tiles. We make no assumptions about the number - of tiles in each terrain LOD. That's entirely up to the writer. This - returns the number of tiles in 2D for a given terrain LOD. */ - bool GetLodSize(int32,trpg2iPoint &) const; + into some X x Y set of tiles. We make no assumptions about the number + of tiles in each terrain LOD. That's entirely up to the writer. This + returns the number of tiles in 2D for a given terrain LOD. */ + bool GetLodSize(int32,trpg2iPoint &) const; /* It's up to the TerraPage archive writer to make their terrain LOD structure - work by using trpgAttach nodes. The scheme they're using may be quad-tree - or replacement LOD or something where the highest LOD isn't even terrain. - It really doesn't matter. However, the reader does need a hint as to - when tiles for a given LOD must be pulled in. This returns that range - in database coordinates (usually meters). - */ - bool GetLodRange(int32,float64 &) const; + work by using trpgAttach nodes. The scheme they're using may be quad-tree + or replacement LOD or something where the highest LOD isn't even terrain. + It really doesn't matter. However, the reader does need a hint as to + when tiles for a given LOD must be pulled in. This returns that range + in database coordinates (usually meters). + */ + bool GetLodRange(int32,float64 &) const; // Read/Write functions // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // {secret} - bool ReadLodInfo(trpgReadBuffer &); + bool ReadLodInfo(trpgReadBuffer &); -protected: + void SetMaster(bool isMaster) + { + if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) + { + if(isMaster) + flags |= ISMASTER;//set the master flag + else + flags &= ~ISMASTER;//clear the master flag + } + } + bool GetIsMaster() const + { + return ((flags & ISMASTER)==ISMASTER); + } + void SetLocal(bool isLocal) + { + if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) + { + if(isLocal) + flags |= ISLOCAL;//set the local flag + else + flags &= ~ISLOCAL;//clear the local flag + } + } + bool GetIsLocal() const + { + return ((flags & ISLOCAL)==ISLOCAL); + } + void SetBlocks(int rows,int cols) + { + this->rows = rows; + this->cols = cols; + } + void GetBlocks(int &rows,int &cols) + { + rows = this->rows; + cols = this->cols; + } + protected: int verMinor,verMajor; int dbVerMinor,dbVerMajor; int maxGroupID; @@ -177,82 +226,88 @@ protected: std::vector tileSize; std::vector lodSizes; std::vector lodRanges; + const static int ISMASTER = 1; + const static int ISLOCAL = 2; + int32 flags; + int32 rows; + int32 cols; }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgTextureEnv : public trpgReadWriteable { + 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; -public: + public: trpgTextureEnv(void); ~trpgTextureEnv(void); // Environment mode values enum {Alpha,Blend,Decal,Modulate,AddDetail,ModulateDetail}; // Set the application mode for the texture. - void SetEnvMode(int); + void SetEnvMode(int); // Values used by SetMinFilter and SetMagFilter enum {Point, Linear, MipmapPoint, MipmapLinear, - MipmapBilinear, MipmapTrilinear, Nearest}; + MipmapBilinear, MipmapTrilinear, Nearest}; // Set the Minification filter for a texture - void SetMinFilter(int); + void SetMinFilter(int); // Set the Magnification filter for a texture - void SetMagFilter(int); + void SetMagFilter(int); // Values used by SetWrap enum {Clamp,Repeat}; // Set the texture wrapping for S and T, respectively - void SetWrap(int,int); + void SetWrap(int,int); // Set the texture border color - void SetBorderColor(const trpgColor &); + 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 polygon color - Decal - Doesn't take polygon color into account. - Modulate - See openGL spec for definition. - AddDetail - See openGL spec for definition. - ModulateDetail - See openGL spec for definition. - */ - bool GetEnvMode(int32 &) const; + It can take the following values: + Alpha - Used to change the alpha values on a polygon. + Blend - Blended with the polygon color + Decal - Doesn't take polygon color into account. + Modulate - See openGL spec for definition. + AddDetail - See openGL spec for definition. + ModulateDetail - 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; + 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; + 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; + 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; + bool GetBorderColor(trpgColor &) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: + protected: int envMode; int minFilter; int magFilter; @@ -261,183 +316,184 @@ protected: }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgMaterial : public trpgReadWriteable { + 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; -public: + public: trpgMaterial(void); ~trpgMaterial(void); // Set base material color - void SetColor(const trpgColor &); + void SetColor(const trpgColor &); // Ambient color - void SetAmbient(const trpgColor &); + void SetAmbient(const trpgColor &); // Diffuse color (the most commonly used) - void SetDiffuse(const trpgColor &); + void SetDiffuse(const trpgColor &); // Specular color used in lighting - void SetSpecular(const trpgColor &); + void SetSpecular(const trpgColor &); // Emissive color used in lighting - void SetEmission(const trpgColor &); + void SetEmission(const trpgColor &); // Shininess used in lighting - void SetShininess(float64); + void SetShininess(float64); enum {Smooth,Flat}; // Shading model - void SetShadeModel(int); + void SetShadeModel(int); // Point size - void SetPointSize(float64); + void SetPointSize(float64); // Line width - void SetLineWidth(float64); + void SetLineWidth(float64); enum {Front,Back,FrontAndBack}; // Cull mode. See GetCullMode - void SetCullMode(int); + 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}; + LessThanOrEqual,LessThan,Never,NotEqual}; #else enum {None,Always,Equal,GreaterThanOrEqual,GreaterThan, - LessThanOrEqual,LessThan,Never,NotEqual}; + LessThanOrEqual,LessThan,Never,NotEqual}; #endif // Alpha Function. See GetAlphaFunc - void SetAlphaFunc(int); + void SetAlphaFunc(int); // Alpha Ref value. See GetAlphaRef - void SetAlphaRef(float64); + void SetAlphaRef(float64); // Alpha value for any polygon using this material - void SetAlpha(float64); + void SetAlpha(float64); // Generate normals automatically from geometry - void SetAutoNormal(bool); + 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); + 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 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 &); + 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); + void SetNumTiles(int); // Adds a count to the number of tiles this material is used in and returns that number - int AddTile(void); + int AddTile(void); // Sets bump map status (color etc... isn't important) - void SetIsBumpMap(bool); + void SetIsBumpMap(bool); // Set an attribute (e.g. fid/smc) enum {TR_FID,TR_SMC,TR_STP,TR_SWC}; - void SetAttr(int attrCode,int val); + void SetAttr(int attrCode,int val); // Return the current color - bool GetColor(trpgColor &) const; + bool GetColor(trpgColor &) const; // Returns the ambient color - bool GetAmbient(trpgColor &) const; + bool GetAmbient(trpgColor &) const; // Returns the diffuse color (the most commonly used color) - bool GetDiffuse(trpgColor &) const; + bool GetDiffuse(trpgColor &) const; // Specular color used for lighting - bool GetSpecular(trpgColor &) const; + bool GetSpecular(trpgColor &) const; // Emissive color used for lighting - bool GetEmission(trpgColor &) const; + bool GetEmission(trpgColor &) const; // Shininess used for lighting - bool GetShininess(float64 &) const; + bool GetShininess(float64 &) const; // The shading model can be either Smooth or Flat - bool GetShadeModel(int &) const; + bool GetShadeModel(int &) const; // Point size - bool GetPointSize(float64 &) const; + bool GetPointSize(float64 &) const; // Line width - bool GetLineWidth(float64 &) const; + 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; + 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; + 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; + bool GetAlphaRef(float64 &) const; // Whether or not to generate normals from geometry - bool GetAutoNormal(bool &) const; + bool GetAutoNormal(bool &) const; // A single Alpha value that applies to any polygons using this material - bool GetAlpha(float64 &) const; + 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; + 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; /* 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; + 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; + 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; // Return whether or not this material is a bump map - bool GetIsBumpMap(bool &) const; + bool GetIsBumpMap(bool &) const; // Get an attribute (e.g. fid/smc) - bool GetAttr(int attrCode,int &val) const; + bool GetAttr(int attrCode,int &val) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Note: Need to do equality operator - -protected: + + protected: bool isBump; trpgColor color; trpgColor ambient; @@ -455,24 +511,26 @@ protected: bool autoNormal; int numTex; int32 numTile; - struct _attrSet { - int fid; - int smc; - int stp; - int swc; + struct _attrSet + { + int fid; + int smc; + int stp; + int swc; } attrSet; std::vector texids; std::vector texEnvs; }; /* Light attributes are used by the trpgLight objects. - They control all aspects of how lights are constructed and - displayed. Lights are very complicated and often system specific. - It's best to consult the Get methods to figure out what options - are available. - */ -TX_EXDECL class TX_CLDECL trpgLightAttr : public trpgReadWriteable { -public: + They control all aspects of how lights are constructed and + displayed. Lights are very complicated and often system specific. + It's best to consult the Get methods to figure out what options + are available. +*/ +TX_EXDECL class TX_CLDECL trpgLightAttr : public trpgReadWriteable +{ + public: // Default constructor trpgLightAttr(void); // Copy constructor @@ -481,85 +539,92 @@ public: ~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, + 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, + // 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 + // 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 + typedef enum + { + trpg_Raster, + trpg_Calligraphic, + trpg_RASCAL } LightType; // Light Directionality - typedef enum { - trpg_Omnidirectional, - trpg_Bidirectional, - trpg_Unidirectional + typedef enum + { + trpg_Omnidirectional, + trpg_Bidirectional, + trpg_Unidirectional } LightDirectionality; // Light Quality - typedef enum { - trpg_Off, - trpg_Low, - trpg_Medium, - trpg_High, - trpg_Undefined + 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; - } _PerformerAttr; + 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; - } _AnimationAttr; + 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; - } _CalligraphicAttr; + typedef struct CalligraphicAttr + { + CalligraphicAttr() : drawOrder(0),minDefocus(0),maxDefocus(0) {} ; + int32 drawOrder; + float64 minDefocus; + float64 maxDefocus; + }; // Setters // Set Type @@ -651,7 +716,7 @@ public: // Set the transparent scale for Performer Lights void SetPerformerTpScale( float64 ); - + // Set the transparent clamp for Performer Lights void SetPerformerTpClamp( float64 ); @@ -741,40 +806,43 @@ public: // 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; - char *commentStr; + + 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; + char *commentStr; } data; }; /* Lights in TerraPage are called out as separate objects. The trpgLight - object will appear in the scenegraph as an individual light structure. - These may consist of single lights or light strings. - The trpgLight points into the trpgLightTable for its attributes. - */ -TX_EXDECL class TX_CLDECL trpgLight : public trpgReadWriteable { -public: + object will appear in the scenegraph as an individual light structure. + These may consist of single lights or light strings. + The trpgLight points into the trpgLightTable for its attributes. +*/ +TX_EXDECL class TX_CLDECL trpgLight : public trpgReadWriteable +{ + public: // Default constructor trpgLight(void); // Copy constructor @@ -804,35 +872,36 @@ public: void GetAttrIndex(int &) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // operator trpgLight& operator = (const trpgLight &); -protected: + protected: // Here we store the light locations - std::vector lightPoints; - int index; + std::vector lightPoints; + int index; }; /* The Light Table is stored in the TerraPage header and consolidates - the attributes for all light points. trpgLight structures will index - into this table to define their appearance. - */ -TX_EXDECL class TX_CLDECL trpgLightTable : public trpgReadWriteable { -public: + the attributes for all light points. trpgLight structures will index + into this table to define their appearance. +*/ +TX_EXDECL class TX_CLDECL trpgLightTable : public trpgReadWriteable +{ + public: // Default constructor trpgLightTable(void); @@ -843,52 +912,56 @@ public: ~trpgLightTable(void); // Adds the given light attrib to the table and increments the total light attrib count. - int AddLightAttr(const trpgLightAttr&); + 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&); + 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; + 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; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // operator trpgLightTable & operator = (const trpgLightTable &); - -protected: + + typedef std::map LightMapType; + LightMapType *getLightMap() { return &lightMap; } + protected: // Here we store the light attributes - std::vector lightList; + //std::vector lightList; + LightMapType lightMap; }; /* 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: + 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); @@ -896,39 +969,39 @@ public: trpgRange(const trpgRange &); // Set the name and subName (can be NULL) - void SetCategory(const char *cat,const char *subCat); + void SetCategory(const char *cat,const 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; + 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); + 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; + void GetLodInfo(double &in,double &out) const; // Set the priority - void SetPriority(int); + 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; + 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 &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Reset back to a clean state void Reset(void); @@ -939,7 +1012,7 @@ public: // Assignment operator trpgRange & operator = (const trpgRange &); -protected: + protected: double inLod,outLod; char *category; char *subCategory; @@ -947,365 +1020,366 @@ protected: }; /* 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. + 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. + 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. + 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: + {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; + bool GetRange(int id,trpgRange &) const; + // Get the number of entries in the table + int GetNumRanges() {return int(rangeMap.size());} // Set the range info for the given ID - bool SetRange(int id,trpgRange &); + bool SetRange(int id,trpgRange &); // Add a new range and return the ID - int AddRange(trpgRange &); + int AddRange(trpgRange &); // Find a matching range and return it or add a new one if needed - int FindAddRange(trpgRange &); + int FindAddRange(trpgRange &); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Assignment operator trpgRangeTable & operator = (const trpgRangeTable &); -protected: - std::vector rangeList; + protected: + typedef std::map RangeMapType; + RangeMapType rangeMap; + //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} - */ -TX_EXDECL class TX_CLDECL trpgMatTable : public trpgReadWriteable { -public: + 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); + 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); + 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 &); - + 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 &,bool lookForExisting=true); + 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 &,bool lookForExisting=true); + + // The following method is unused currently /* This function should be used when adding materials to multiple sub-tables. - 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 AddMaterialInSubtable(const trpgMaterial &,int table,bool lookForExisting=true); + 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 AddMaterialInSubtable(const trpgMaterial &,int table,bool lookForExisting=true); /* 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; + 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; + 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; + 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. - */ + 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; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: + protected: int numTable; int numMat; - std::vector matTables; + typedef std::map MaterialMapType; + MaterialMapType materialMap; }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgTexture : public trpgReadWriteable { -public: + 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); /* 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. - */ + 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; /* 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; - - // How the image bit planes are organized - typedef enum { - trpg_RGBX_Neither=0, - trpg_RGBX_AlphaFirst, - trpg_RGBX_RegionFirst - } ImageOrg; + 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 no longer + trpg_Unknown, + trpg_DDS, + trpg_DXT1, + trpg_DXT3, + trpg_DXT5, + // This is a bit ugly, but we can't change the size of the texture record without + // breaking existing readers. So there will be multiple MCM types to indicate the number + // of bands and the nature of the extra channels, if any + trpg_MCM5, + trpg_MCM6R, + trpg_MCM6A, + trpg_MCM7RA, + trpg_MCM7AR + } ImageType; // Set the texture name. - void SetName(const char *); + 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; + and it returns the texture name in that. */ + bool GetName(char *retStr,int strLen) const; /* Sets the number of tiles this texture is used in. This hint is used by - readers to determine texture pageability. */ - void SetNumTile(int); + 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); + AddTile as you encounter each texture reference (per tile). */ + void AddTile(void); /* 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; + 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; + 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; + bool GetImageType(ImageType &) const; // Retrieve the size of this image. Valid only for Local and Template textures. - bool GetImageSize(trpg2iPoint &) const; + bool GetImageSize(trpg2iPoint &) const; // Get the location of a Local image - bool GetImageAddr(trpgwAppAddress &) const; + bool GetImageAddr(trpgwAppAddress &) const; // Figure out the image depth from the type - bool GetImageDepth(int32 &depth) const; + bool GetImageDepth(int32 &depth) const; // Determine whether this image (must be Local or Template) has all its mipmaps - bool GetIsMipmap(bool &) const; + bool GetIsMipmap(bool &) const; // Set the image mode of this texture. Used by writers only. - void SetImageMode(ImageMode); + 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); + void SetImageType(ImageType); // Set the image size of this texture. See GetImageSize for details - void SetImageSize(const trpg2iPoint &); + void SetImageSize(const trpg2iPoint &); // Set the image location (For Local images only) - void SetImageAddr(const trpgwAppAddress &); + void SetImageAddr(const trpgwAppAddress &); // Set whether or not this is a full set of mipmaps - void SetIsMipmap(bool); + void SetIsMipmap(bool); // Set the storage sizes for all mipmap levels -// void SetStorageSizes(vector &); + // void SetStorageSizes(vector &); // Get the storage sizes for all mipmap levels. -// bool GetStorageSizes(const vector *) const; + // bool GetStorageSizes(const vector *) const; // Set the number of mipmap levels - void SetNumMipmap(int); + void SetNumMipmap(int); // Set the number of layers used in an RGBX image - void SetNumLayer(int); + 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; + 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; + */ + int32 CalcNumMipmaps() const; // Calculate the total size of this texture - int32 CalcTotalSize() const; + int32 CalcTotalSize() const; // Returns the size of a given mip level - int32 MipLevelSize(int miplevel); + int32 MipLevelSize(int miplevel); // Returns the offset of the mip level in the whole texture data buffer - int32 MipLevelOffset(int miplevel); + int32 MipLevelOffset(int miplevel); // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; trpgTexture & operator = (const trpgTexture &); int operator == (const trpgTexture &) const; -protected: + protected: // 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; @@ -1337,157 +1411,186 @@ protected: }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgTexTable : public trpgReadWriteable { -public: + 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); /* 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); + 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 &); + 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 &); + 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 &); + 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; + bool GetNumTextures(int &) const; // This returns the trpgTexture corresponding to the given ID (from a trpgMaterial) - bool GetTexture(int texID,trpgTexture &) const; + 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. - */ + 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; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; trpgTexTable & operator = (const trpgTexTable &); -protected: - std::vector texList; + const trpgTexture *FindByName(const char *name, int &texid) const; + void SetCurrentBlock(int row, int col) + { + currentRow = row; + currentCol = col; + } + + //bool dumpGeoTypicalTextures(trpgwImageHelper *ihelper); + typedef std::map TextureMapType; + TextureMapType *getTextureMap() + { + return &textureMap; + } + protected: + + TextureMapType textureMap; + //These are used to initialize the row/col values for + //multi-archive archives + int currentRow; + int currentCol; + }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgModel : public trpgReadWriteable { -public: + 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 *); + // 5.28.04 - It will not set the model to be as of external type. Use the method + // from below to set the type of the model + void SetName(const char *); // Sets the on-disk reference to an internal model and sets this model to Internal type. - void SetReference(trpgDiskRef); + // 5.28.04 - It will not set the model to be as of internal type. Use the method + // from below to set the type of the model + void SetReference(trpgDiskRef); + // Sets the model type + void SetType(int); /* Models are reference counted (per-tile). It's up to the writer to set this - value. */ - void SetNumTiles(int); + 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); + 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 &); + 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; + 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; + 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; + value to determine whether or not you should page models. + */ + bool GetNumTiles(int &) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &, bool); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; trpgModel & operator = (const trpgModel &); int operator == (const trpgModel &) const; -protected: + + + protected: int type; char *name; trpgDiskRef diskRef; @@ -1495,347 +1598,397 @@ protected: }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgModelTable : public trpgReadWriteable { -public: + 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); /* 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); + 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 &); + and returns the new model ID which you'll need to reference in trpgModelRef. + */ + int AddModel(trpgModel &); /* Look for a given model. If it's not there, add it. */ - int FindAddModel(const trpgModel &); + int FindAddModel(trpgModel &); /* Sets the model definition corresponding to the given ID. Use this in conjunction - with SetNumModels. */ - void SetModel(int,const trpgModel &); + with SetNumModels. */ + void SetModel(int,const trpgModel &); // Returns the number of models in this table - bool GetNumModels(int &) const; + 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; + 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. - */ + 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; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: - std::vector models; + bool FindByName(const char *name, unsigned int &mId); + typedef std::map ModelMapType; + ModelMapType *GetModelMap() + { + return &modelsMap; + } + protected: + + ModelMapType modelsMap; }; /* The tile table keeps track of tile locations within a TerraPage archive. - 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: - // Tiles can be stored individually (External) or in grouped files (Local) - typedef enum {Local,External} TileMode; + 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. + In version 2.1 the tile table only contains the location of lod 0 tiles. + All other tiles location are stored in the parent tile as trpgChildRef + nodes, so you need to parse the parent tile to get at them. + {group:Read/Write Classes} +*/ +TX_EXDECL class TX_CLDECL trpgTileTable : public trpgReadWriteable +{ + public: + // Tiles can be stored individually (External and ExternalSaved) or in grouped files (Local). + // ExternalSaved still have an entry in the table. In this case the addess data is not valid. + + enum TileMode {Local,External, ExternalSaved}; - trpgTileTable(void); + trpgTileTable(); ~trpgTileTable(void); + // Set the tile storage mode: external or local - void SetMode(TileMode); + void SetMode(TileMode); // Set the total number of LODs - void SetNumLod(int numLod); + // For version 2.1 only lod 0 is stored in the table + 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); + 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); + void SetTile(int x,int y,int lod,trpgwAppAddress &,float32 min,float32 max); // Local or external tiles - bool GetMode(TileMode &) const; + bool GetMode(TileMode &) const; // Get the disk reference (local) - bool GetTile(int x,int y,int lod,trpgwAppAddress &,float32 &min,float32 &max) const; + bool GetTile(int x,int y,int lod,trpgwAppAddress &,float32 &min,float32 &max) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Reads this class from a read buffer - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; - -protected: + bool Print(trpgPrintBuffer &) const; + /** + * SetCurrentBlock is used in two cases: + * 1. When building a block specific tile archive (MMB and non-MMB). (local is TRUE) + * 2. When merging several blocks into memory for visualization. (local is FALSE) + **/ + void SetCurrentBlock(int row, int col, bool local) + { + currentRow = row; + currentCol = col; + localBlock = local; + } + protected: TileMode mode; - 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; + 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; + //These are used to initialize the row/col values for + //multi-archive archives + int currentRow; + int currentCol; + bool localBlock; // if true, this tile table should only contain entries for one block. }; + /* 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: + 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); + 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). - // 2003-06-17. Your prophecy (my headache) has come true. MD - */ - bool GetBaseMaterial(int32 &matSubTable,int32 &matID) const; + 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). + // 2003-06-17. Your prophecy (my headache) has come true. MD + */ + bool GetBaseMaterial(int32 &matSubTable,int32 &matID) const; - class SubImageInfo { + 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) + 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 &); + 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; + (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 &); + void SetAddr(const trpgwAppAddress &); // Set address info for one of multiple local textures - void SetNthAddr(unsigned int subtable, const trpgwAppAddress &); + void SetNthAddr(unsigned int subtable, 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; + 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; // Get address info for one of multiple local textures - bool GetNthAddr(unsigned int subtable, trpgwAppAddress &) const; + bool GetNthAddr(unsigned int subtable, trpgwAppAddress &) const; // Get the number of local images associated with this local material // Tile Local Images only - bool GetNumLocals(int &) const; + bool GetNumLocals(int &) const; // Set the storage sizes for all mipmap levels -// bool SetStorageSizes(vector &); + // bool SetStorageSizes(vector &); // Get the storage sizes for all mipmap levels. -// bool GetStorageSizes(const vector *) const; + // bool GetStorageSizes(const vector *) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Reads this class from a read buffer - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: + 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; + // vector storageSize; // This is valid only for Tile Local images std::vector addr; }; /* The tile header is one of the more interesting parts of TerraPage. Basically, - 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. + 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. 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 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. - 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. + 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. + 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: + 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); + 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); + 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 &); + 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); + 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); + 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); + It's easier to use AddModel(), if possible. + */ + void SetModel(int no,int id); // Returns the number of materials used in this tile - bool GetNumMaterial(int32 &) const; + 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; + 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; + 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; + 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; + 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; + 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. - */ + See GetLocalMaterial for an explantion of local materials. + */ const std::vector *GetLocalMaterialList(void) const; // {secret} - bool GetDate(int32 &) const; + bool GetDate(int32 &) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; - -protected: + bool Print(trpgPrintBuffer &) const; + void SetBlockNo(int row, int col) + { + this->row = row; + this->col = col; + } + void GetBlockNo(int &row, int &col) + { + row = this->row; + col = this->col; + } + protected: std::vector matList; std::vector modelList; std::vector locMats; // {secret} int date; + //These are used to find them in the block archive. + int row; + int col; }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgColorInfo { -public: + 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); @@ -1843,12 +1996,12 @@ public: */ int type; /* This refers to how the colors in the data array are used. - It can take the values "Overall", "PerPrim" or "PerVertex". - */ + 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. */ @@ -1866,25 +2019,26 @@ public: 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: +*/ +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. - */ + 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. - */ + 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. */ + 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. @@ -1917,469 +2071,513 @@ public: 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: +*/ +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; + TriFans,Triangles,QuadStrips,Quads} PrimType; // Set the primitive type for the geometry node - void SetPrimType(PrimType type); + void SetPrimType(PrimType type); /* Some primitive types require lengths. These include TriStrips and - TriFans, but not Triangles, for example. */ - void SetPrimLengths(int,const int *); + 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); + 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); + 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 + 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); + 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); + 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); + 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); + 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}; + Color,TextureFloat,TextureDouble,EdgeFlag}; /* 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 *); + 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 &); + (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 *); + 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 &); + 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(). - */ + 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 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. + 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 *); + 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); + void AddTexCoords(BindType bind); /* This method adds a texture coordinate to array n. You would use - this if you were adding vertices one at a time. - */ - void AddTexCoord(DataType type,trpg2dPoint &,int n=0); + this if you were adding vertices one at a time. + */ + void AddTexCoord(DataType type,trpg2dPoint &,int n=0); /* This method adds a texture coordinate to each trpgTexData. You would use - this if you were adding vertices one at a time with multiple materials. - */ - void AddTexCoord(DataType type,std::vector &pts); + this if you were adding vertices one at a time with multiple materials. + */ + void AddTexCoord(DataType type,std::vector &pts); /* 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 *); + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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. 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; + 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; + 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; + 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; - + index. GetNumTexCoordSets determines the total number of texture + coordinate sets. + */ + bool GetTexCoordSet(int id,trpgTexData *) const; /* This method returns this trpgGeometry's texture coordinate set specified by the given - index. GetNumTexCoordSets determines the total number of texture - coordinate sets. - */ + index. GetNumTexCoordSets determines the total number of texture + coordinate sets. + */ const trpgTexData *GetTexCoordSet(int id) 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; + 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; + bool GetEdgeFlags(char *) const; // Returns true if the trpgGeometry structure is valid - bool isValid(void) const; + bool isValid(void) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Write self to a buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Read self from a buffer. Check isValid() afterwards - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: - 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; + protected: + 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} - */ -TX_EXDECL class TX_CLDECL trpgGroup : public trpgReadWriteable { -public: + 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); - virtual ~trpgGroup(void); + virtual ~trpgGroup(void); // Resets the contents back to empty - virtual void Reset(void); + virtual void Reset(void); /* Set the total number of children this group will have */ - virtual void SetNumChild(int); + virtual void SetNumChild(int); // Starting from 0, increments the number of children - virtual int AddChild(void); + virtual int AddChild(void); /* The writer is supposed to set this value to the number of - children. */ - virtual bool GetNumChild(int &) const; + children. */ + virtual bool GetNumChild(int &) const; /* Set the group ID */ - virtual void SetID(int); + virtual void SetID(int); // Returns the group ID - virtual bool GetID(int &) const; + virtual bool GetID(int &) const; /* Set the group name */ - void SetName(const char* ); + void SetName(const char* ); // Returns the group name - const char* GetName(void) const; + const char* GetName(void) const; // Validity check - virtual bool isValid(void) const; + virtual bool isValid(void) const; // Writes this class to a write buffer - virtual bool Write(trpgWriteBuffer &); + virtual bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: + protected: 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} - */ -TX_EXDECL class TX_CLDECL trpgAttach : public trpgGroup { -public: + {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); + void Reset(void); // Set the parent of the group/LOD/whatever to attach to when loaded in - void SetParentID(int); + void SetParentID(int); // Retrieve the parent ID we'll need to attach this thing into the scene graph - bool GetParentID(int &) const; + 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); + 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; + 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 - bool isValid(void) const; + bool isValid(void) const; // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: + protected: int parentID,childPos; }; +TX_EXDECL class TX_CLDECL trpgChildRef : public trpgReadWriteable +{ + public: + trpgChildRef(); + ~trpgChildRef(); + // Resets the contents back to empty + void Reset(); + + // Set the tile grid location + void SetTileLoc(int gx,int gy,int glod); + + // Get the tile grid location + bool GetTileLoc(int &gx,int &gy,int &glod) const; + + + void SetTileAddress(const trpgwAppAddress& gAddr); + void SetTileAddress(int32 file, int32 offset); + void SetTileZValue( float gZmin, float gZmax); + bool GetTileAddress(int32& file, int32& offset) const; + bool GetTileAddress(trpgwAppAddress& gAddr) const; + bool GetTileZValue( float& gZmin, float& gZmax) const; + + + // 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: + // Grid Location + int x,y,lod; + // File Location + trpgwAppAddress addr; + + float zmin, zmax; + +}; + /* 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} - */ -TX_EXDECL class TX_CLDECL trpgBillboard : public trpgGroup { -public: + 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); + void SetType(int); // Set the center. - void SetCenter(const trpg3dPoint &); + void SetCenter(const trpg3dPoint &); enum {Axial,World,Eye}; // Set the rotation mode. - void SetMode(int); + void SetMode(int); // Set the rotation axis if mode == Axial - void SetAxis(const trpg3dPoint &); + 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; + 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; + 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; + 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; + bool GetAxis(trpg3dPoint &) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; -protected: + bool Print(trpgPrintBuffer &) const; + protected: int type; int mode; trpg3dPoint center; @@ -2387,89 +2585,90 @@ protected: }; /* 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 - Turn children on - else - Turn children off. + A simple on/off test for a TerraPage lod might look like this: + 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. - 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. + 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: + {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 &); + void SetCenter(const trpg3dPoint &); // Set the number of children hint - void SetNumChild(int); + void SetNumChild(int); // Set the LOD information - void SetLOD(double in,double out,double width); + void SetLOD(double in,double out,double width); // Center of this LOD. Distance from the viewer is calculated from this. - bool GetCenter(trpg3dPoint &) const; + bool GetCenter(trpg3dPoint &) const; // Number of children hint. - bool GetNumChild(int &) const; + 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; + bool GetLOD(double &in,double &out,double &width) const; // Set the group ID - void SetID(int); + void SetID(int); // Group IDs are used here the same way as in trpgGroup - bool GetID(int &) const; + bool GetID(int &) const; /* Set the lod name */ - void SetName(const char* ); + void SetName(const char* ); // Returns the lod name const char* GetName(void) const; // Set the range Index - void SetRangeIndex(int ri); + void SetRangeIndex(int ri); // Get the range index - bool GetRangeIndex(int &ri) const; + bool GetRangeIndex(int &ri) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: + protected: int numRange; double switchIn,switchOut,width; trpg3dPoint center; @@ -2479,172 +2678,176 @@ protected: }; /* 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} - */ -TX_EXDECL class TX_CLDECL trpgLayer : public trpgGroup { -public: + 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 &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Resets the contents back to empty - void Reset(void); -protected: + 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} - */ -TX_EXDECL class TX_CLDECL trpgTransform : public trpgGroup { -public: + 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); // Set the 4x4 matrix - void SetMatrix(const float64 *); + void SetMatrix(const float64 *); // Get the 4x4 matrix - bool GetMatrix(float64 *) const; + bool GetMatrix(float64 *) const; // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Resets the contents back to empty - void Reset(void); -protected: + void Reset(void); + protected: 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} - */ -TX_EXDECL class TX_CLDECL trpgModelRef : public trpgReadWriteable { -public: + {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); + void SetModel(int); // Set the 4x4 rotate/translate/scale matrix - void SetMatrix(const float64 *); + void SetMatrix(const float64 *); // Model ID pointing into a trpgModelTable - bool GetModel(int32 &) const; + bool GetModel(int32 &) const; // Positional matrix. Works just like a trpgTransform. - bool GetMatrix(float64 *) const; + bool GetMatrix(float64 *) const; // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Resets the contents back to empty - void Reset(void); -protected: + void Reset(void); + protected: int modelRef; float64 m[4][4]; }; /* The Text Styles are used to consolidate attributes related to labels. - It would be inefficient to store the font, for instance, for every - single label, so we do it in the Text Style table. - For the most part, text styles are very simple, consisting of - very basic font and material information. - */ -TX_EXDECL class TX_CLDECL trpgTextStyle : public trpgReadWriteable { -public: + It would be inefficient to store the font, for instance, for every + single label, so we do it in the Text Style table. + For the most part, text styles are very simple, consisting of + very basic font and material information. +*/ +TX_EXDECL class TX_CLDECL trpgTextStyle : public trpgReadWriteable +{ + public: trpgTextStyle(void); ~trpgTextStyle(void); bool operator == (const trpgTextStyle&) const; // Set the material ID. Should point into trpgMatTable - void SetMaterial(int); + void SetMaterial(int); // Get the material ID. Points into trpgMatTable - int GetMaterial(void) const; + int GetMaterial(void) const; // Set the font description - void SetFont(std::string &); + void SetFont(std::string &); // Get the font description const std::string *GetFont(void) const; // Set bold to on/off - void SetBold(bool); + void SetBold(bool); // Return value of bold status - bool GetBold(void) const; + bool GetBold(void) const; // Set italic on/off - void SetItalic(bool); + void SetItalic(bool); // Return value of italic status - bool GetItalic(void) const; + bool GetItalic(void) const; // Set underline on/off - void SetUnderline(bool); + void SetUnderline(bool); // Return value of underline status - bool GetUnderline(void) const; + bool GetUnderline(void) const; // Set character size: MUST BE IN METER - void SetCharacterSize(float32); + void SetCharacterSize(float32); // Get character (e.g. font) size - float32 GetCharacterSize(void) const; + float32 GetCharacterSize(void) const; // Write this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Reset the contents back to empty - void Reset(void); + void Reset(void); // Return object validity bool isValid(void) const; -protected: + protected: std::string font; bool bold,italic,underline; float32 characterSize; @@ -2652,49 +2855,54 @@ protected: }; /* The text style table is just a collection of trpgTextStyle obejcts for the - whole archive. Individual text styles will be indexed by trpgLabelProperty - objects. It is from these that you decide how to display a given label. - */ -TX_EXDECL class TX_CLDECL trpgTextStyleTable : public trpgReadWriteable { -public: + whole archive. Individual text styles will be indexed by trpgLabelProperty + objects. It is from these that you decide how to display a given label. +*/ +TX_EXDECL class TX_CLDECL trpgTextStyleTable : public trpgReadWriteable +{ + public: trpgTextStyleTable(void); ~trpgTextStyleTable(void); // Add a single text style - int AddStyle(const trpgTextStyle &); + int AddStyle(const trpgTextStyle &); - int FindAddStyle(const trpgTextStyle &); + int FindAddStyle(const trpgTextStyle &); // Figure out how many text styles there are - int GetNumStyle(void) const; + int GetNumStyle(void) const; // Return a reference to the given style const trpgTextStyle *GetStyleRef(int) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Reset the contents back to empty - void Reset(void); + void Reset(void); // Write this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Read this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Print this class to a print buffer - bool Print(trpgPrintBuffer &) const; - -protected: - std::vector styles; + bool Print(trpgPrintBuffer &) const; + typedef std::map StyleMapType; + const StyleMapType *getStyleMap()const { return &styleMap; } + protected: + //std::vector styles; + + StyleMapType styleMap; }; /* The Support Styles are used to consolidate attributes related to labels. - For the most part, support styles are very simple, consisting of - very basic description of object to use for drawing suport. - */ -TX_EXDECL class TX_CLDECL trpgSupportStyle : public trpgReadWriteable { -public: + For the most part, support styles are very simple, consisting of + very basic description of object to use for drawing suport. +*/ +TX_EXDECL class TX_CLDECL trpgSupportStyle : public trpgReadWriteable +{ + public: trpgSupportStyle(void); ~trpgSupportStyle(void); @@ -2703,72 +2911,75 @@ public: typedef enum {Line,Cylinder,MaxSupportType} SupportType; // Set the support type. Get GetSupportType() for more information - void SetType(SupportType); + void SetType(SupportType); /* Return the support types. Supports are geometry that run from the - bottom middle of the label object to some point in space. - Most likely that point is somewhere on the ground, but not - necessarily. How the support is drawn is controlled both by - the support type and the material ID for the support. - */ - SupportType GetType(void) const; + bottom middle of the label object to some point in space. + Most likely that point is somewhere on the ground, but not + necessarily. How the support is drawn is controlled both by + the support type and the material ID for the support. + */ + SupportType GetType(void) const; // Set the material ID. Should point into trpgMatTable - void SetMaterial(int); + void SetMaterial(int); // Get the material ID. Points into trpgMatTable - int GetMaterial(void) const; + int GetMaterial(void) const; // Write this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Reset the contents back to empty - void Reset(void); + void Reset(void); // Return object validity bool isValid(void) const; -protected: + protected: SupportType type; int matId; }; /* The support style table is just a collection of trpgSupportStyle obejcts for the - whole archive. Individual support styles will be indexed by trpgLabelProperty - objects. It is from these that you decide how to display a given support. - */ -TX_EXDECL class TX_CLDECL trpgSupportStyleTable : public trpgReadWriteable { -public: + whole archive. Individual support styles will be indexed by trpgLabelProperty + objects. It is from these that you decide how to display a given support. +*/ +TX_EXDECL class TX_CLDECL trpgSupportStyleTable : public trpgReadWriteable +{ + public: trpgSupportStyleTable(void); ~trpgSupportStyleTable(void); // Add a single text style - int AddStyle(const trpgSupportStyle &); + int AddStyle(const trpgSupportStyle &); - int FindAddStyle(const trpgSupportStyle &); + int FindAddStyle(const trpgSupportStyle &); // Figure out how many text styles there are - int GetNumStyle(void) const; + int GetNumStyle(void) const; // Return a reference to the given style const trpgSupportStyle *GetStyleRef(int) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Reset the contents back to empty - void Reset(void); + void Reset(void); // Write this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Read this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Print this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: - std::vector styles; + protected: + //std::vector styles; + typedef std::map SupportStyleMapType; + SupportStyleMapType supportStyleMap; }; @@ -2776,9 +2987,10 @@ protected: /* The Label property are used to consolidate attributes related to labels. Label properties are very simple, consisting of basic font style and support properties. - */ -TX_EXDECL class TX_CLDECL trpgLabelProperty : public trpgReadWriteable { -public: +*/ +TX_EXDECL class TX_CLDECL trpgLabelProperty : public trpgReadWriteable +{ + public: trpgLabelProperty(void); ~trpgLabelProperty(void); @@ -2787,180 +2999,183 @@ public: bool operator == (const trpgLabelProperty&) const; // Set the label type. See GetType() for more information. - void SetType(LabelType); + void SetType(LabelType); /* Return the label type. This controls the geometry for the label. - Panel labels are simple polygons. Cube labels should display - the text on every side with single sided polygons. - Billboard labels rotate toward the user with no particular axes. - That is, they will always be pointed directly toward the user. - Vertical billboards rotate toward the user, but have an axis along +Z. - */ - LabelType GetType(void) const; + Panel labels are simple polygons. Cube labels should display + the text on every side with single sided polygons. + Billboard labels rotate toward the user with no particular axes. + That is, they will always be pointed directly toward the user. + Vertical billboards rotate toward the user, but have an axis along +Z. + */ + LabelType GetType(void) const; // Set the font style ID. Should point into trpgTextStyleTable - void SetFontStyle(int); + void SetFontStyle(int); // Get the font style ID. Points into trpgTextStyleTable - int GetFontStyle(void) const; + int GetFontStyle(void) const; // Set the support style ID. Should point into trpgSupportTable - void SetSupport(int); + void SetSupport(int); // Get the font style ID. Points into trpgSupportTable - int GetSupport(void) const; - + int GetSupport(void) const; + // Write this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Reset the contents back to empty - void Reset(void); + void Reset(void); // Return object validity bool isValid(void) const; -protected: + protected: int fontId; int supportId; LabelType type; }; /* The label property table is just a collection of trpgLabelProperty obejcts for the - whole archive. Individual label property will be indexed by trpgLable - objects. - */ -TX_EXDECL class TX_CLDECL trpgLabelPropertyTable : public trpgReadWriteable { -public: + whole archive. Individual label property will be indexed by trpgLable + objects. +*/ +TX_EXDECL class TX_CLDECL trpgLabelPropertyTable : public trpgReadWriteable +{ + public: trpgLabelPropertyTable(void); ~trpgLabelPropertyTable(void); // Add a single label property - int AddProperty(const trpgLabelProperty &); + int AddProperty(const trpgLabelProperty &); // Find or Add a single label property int FindAddProperty(const trpgLabelProperty& property); // Figure out how many properties there are - int GetNumProperty(void) const; + int GetNumProperty(void) const; // Return a reference to the given property const trpgLabelProperty *GetPropertyRef(int) const; // Validity check - bool isValid(void) const; + bool isValid(void) const; // Reset the contents back to empty - void Reset(void); + void Reset(void); // Write this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Read this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Print this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; -protected: - std::vector properties; + protected: + //std::vector properties; + typedef std::map LabelPropertyMapType; + LabelPropertyMapType labelPropertyMap; }; /* Labels are objects that float above the terrain (usually) and display - some text message to the user. They're primarily used in 3D map sort of - application. In other words, they're not intended to be real world objects. - You would use one if you want to float a message such as "Natural History Museum" - over a specific building in a visual database. - */ + some text message to the user. They're primarily used in 3D map sort of + application. In other words, they're not intended to be real world objects. + You would use one if you want to float a message such as "Natural History Museum" + over a specific building in a visual database. +*/ TX_EXDECL class TX_CLDECL trpgLabel : public trpgReadWriteable { -public: + public: trpgLabel(void); ~trpgLabel(void); bool isValid(void) const; - + typedef enum {Left,Center,Right,MaxAlignmentType} AlignmentType; // Set the label property ID. This is an index into a tprgLabelPropertyTable - void SetProperty(int); - int GetProperty() const; + void SetProperty(int); + int GetProperty() const; // Set the text for this label. See GetText() for more information - void SetText(const std::string &); + void SetText(const std::string &); /* Return the text for this label. The text may contain basic formatting - such as newlines and tabs. Expect to see those as \n and \t respectively. - Eventually, this text might contain HTML formatting, but we do not use - that at present. - Should not be empty. - */ + such as newlines and tabs. Expect to see those as \n and \t respectively. + Eventually, this text might contain HTML formatting, but we do not use + that at present. + Should not be empty. + */ const std::string *GetText(void) const; // Set the text alignment. See GetAlignmentType() for more information. - void SetAlignment(AlignmentType); + void SetAlignment(AlignmentType); /* Return the alignement type. This controls the alignement of the text - with respect to the label geometry. - */ - AlignmentType GetAlignment(void) const; + with respect to the label geometry. + */ + AlignmentType GetAlignment(void) const; // Set the number of spaces between tabs - void SetTab(int); + void SetTab(int); // Get the number of spaces between tabs - int GetTab(void) const; + int GetTab(void) const; // Set the text scaling value: font size * scale = real world text size in meter - void SetScale(float32); - float32 GetScale() const; + void SetScale(float32); + float32 GetScale() const; // Set the text thickness: use to draw 3D text. if thickness = 0, we have // 2D text only. - void SetThickness(float32); - float32 GetThickness() const; + void SetThickness(float32); + float32 GetThickness() const; // Set the description for this label. Set GetDesc() for more information - void SetDesc(const std::string &); + void SetDesc(const std::string &); /* Return the description for this label. Descriptions should contain no - formatting. They are a description of what the label represents and may - appear if a user interacts with the label, but should not be drawn in 3D. - May be empty. - */ + formatting. They are a description of what the label represents and may + appear if a user interacts with the label, but should not be drawn in 3D. + May be empty. + */ const std::string *GetDesc(void) const; // Set the URL for this label. See GetURL() for more information. - void SetURL(const std::string &); + void SetURL(const std::string &); /* Return the URL for this label. The URL would invoke some sort of - web browser if the user of the 3D application clicks on the label. - May be empty. - */ + web browser if the user of the 3D application clicks on the label. + May be empty. + */ const std::string *GetURL(void) const; // Set the number of spaces between tabs - void SetTabSize(int); + void SetTabSize(int); // Get the number of spaces between tabs - int GetTabSize(void) const; + int GetTabSize(void) const; // Set the location of the label. void SetLocation(const trpg3dPoint &); const trpg3dPoint& GetLocation() const; // Add a support. See GetSupports() for more information - void AddSupport(const trpg3dPoint &); + void AddSupport(const trpg3dPoint &); /* Return the support array. Supports are linear features that run from - the middle bottom of the label to some set of points in the database. - These will often be on the ground, but need not be. Support display - is controlled by the SupportType and by the Support Material ID. - */ + the middle bottom of the label to some set of points in the database. + These will often be on the ground, but need not be. Support display + is controlled by the SupportType and by the Support Material ID. + */ const std::vector *GetSupports(void) const; // Writes this class to a write buffer - bool Write(trpgWriteBuffer &); + bool Write(trpgWriteBuffer &); // Reads this class from a read buffer - bool Read(trpgReadBuffer &); + bool Read(trpgReadBuffer &); // Prints this class to a print buffer - bool Print(trpgPrintBuffer &) const; + bool Print(trpgPrintBuffer &) const; // Resets the contents back to empty - void Reset(void); + void Reset(void); -protected: + protected: int propertyId; std::string text; // Actual label text. May contain formatting AlignmentType alignment; diff --git a/src/osgPlugins/txp/trpage_header.cpp b/src/osgPlugins/txp/trpage_header.cpp index 6d6c89cd6..93268733c 100644 --- a/src/osgPlugins/txp/trpage_header.cpp +++ b/src/osgPlugins/txp/trpage_header.cpp @@ -18,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 #include /* Write Header class - Fill it in and write it out. - */ + Fill it in and write it out. + */ // Constructor trpgHeader::trpgHeader() { - Reset(); + Reset(); } trpgHeader::~trpgHeader() { @@ -42,152 +42,181 @@ trpgHeader::~trpgHeader() // Validity check bool trpgHeader::isValid() const { - if (numLods <= 0) - { - strcpy(errMess, "Number of LOD <= 0"); - return false; - } - if (sw.x == ne.x && sw.y == ne.y) - { - strcpy(errMess, "Mbr is invalid"); + // We also need to check that this is a 'master' archive here. + if((verMajor>=TRPG_NOMERGE_VERSION_MAJOR) && (verMinor>=TRPG_NOMERGE_VERSION_MINOR)) + { + return true; + } + else { + if (numLods <= 0) + { + strcpy(errMess, "Number of LOD <= 0"); + return false; + } + if (sw.x == ne.x && sw.y == ne.y) + { + strcpy(errMess, "Mbr is invalid"); - return false; - } + return false; + } + } - return true; + return true; } // Reset contents void trpgHeader::Reset() { - // Initialize to a default state - verMinor = TRPG_VERSION_MINOR; - verMajor = TRPG_VERSION_MAJOR; - dbVerMinor = 0; - dbVerMajor = 0; - origin = trpg3dPoint(0,0,0); - sw = ne = trpg2dPoint(0,0); - tileType = DatabaseLocal; + // Initialize to a default state + verMinor = TRPG_VERSION_MINOR; + verMajor = TRPG_VERSION_MAJOR; + dbVerMinor = 0; + dbVerMajor = 0; + origin = trpg3dPoint(0,0,0); + sw = ne = trpg2dPoint(0,0); + tileType = DatabaseLocal; - numLods = 0; - lodSizes.resize(0); - lodRanges.resize(0); - tileSize.resize(0); - maxGroupID = -1; - - errMess[0] = '\0'; + numLods = 0; + lodSizes.resize(0); + lodRanges.resize(0); + tileSize.resize(0); + maxGroupID = -1; + flags = 0; + errMess[0] = '\0'; + cols = -1; + rows = -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 || id >= (int)tileSize.size()) return; - tileSize[id] = pt; + if (id < 0 || id >= (int)tileSize.size()) return; + tileSize[id] = pt; } void trpgHeader::SetOrigin(const trpg3dPoint &pt) { - origin = pt; + origin = pt; } void trpgHeader::SetExtents(const trpg2dPoint &in_sw,const trpg2dPoint &in_ne) { - sw = in_sw; - ne = in_ne; + sw = in_sw; + ne = in_ne; } void trpgHeader::SetTileOriginType(trpgTileType type) { - tileType = type; + tileType = type; } void trpgHeader::SetNumLods(int no) { - if (no < 0) return; - numLods = no; + if (no < 0) return; + numLods = no; - lodSizes.resize(no); - lodRanges.resize(no); + lodSizes.resize(no); + lodRanges.resize(no); } void trpgHeader::SetLodSize(int no,const trpg2iPoint &pt) { - if (no < 0 || no >= numLods) - return; + if (no < 0 || no >= numLods) + return; - lodSizes[no] = pt; + lodSizes[no] = pt; } void trpgHeader::SetLodSize(const trpg2iPoint *pt) { - for (int i=0;i= numLods) - return; + if (no < 0 || no >= numLods) + return; - lodRanges[no] = r; + lodRanges[no] = r; } void trpgHeader::SetLodRange(const float64 *r) { - for (int i=0;i(lod)) + numLods=lod+1; } void trpgHeader::SetMaxGroupID(int id) { - maxGroupID = id; + maxGroupID = id; } int trpgHeader::AddGroupID(void) { - maxGroupID++; - return maxGroupID; + maxGroupID++; + return maxGroupID; } // Write out to a buffer bool trpgHeader::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPGHEADER); - buf.Add((int32)verMajor); - buf.Add((int32)verMinor); - buf.Add((int32)dbVerMajor); - buf.Add((int32)dbVerMinor); - buf.Add(origin); - buf.Add(sw); - buf.Add(ne); - buf.Add((uint8)tileType); + buf.Begin(TRPGHEADER); + buf.Add((int32)verMajor); + buf.Add((int32)verMinor); + buf.Add((int32)dbVerMajor); + buf.Add((int32)dbVerMinor); + buf.Add(origin); + buf.Add(sw); + buf.Add(ne); + buf.Add((uint8)tileType); - buf.Add((int32)numLods); + buf.Add((int32)numLods); - buf.Begin(TRPGHEAD_LODINFO); - for (int i=0;i= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) { + buf.Add(flags); + buf.Add(rows); + buf.Add(cols); + } - return true; + buf.End(); + + return true; } /* ******** @@ -197,128 +226,133 @@ bool trpgHeader::Write(trpgWriteBuffer &buf) // Get Functions bool trpgHeader::GetVersion(int32 &vmaj,int32 &vmin) const { - if (!isValid()) return false; - vmin = verMinor; - vmaj = verMajor; - return true; + if (!isValid()) return false; + vmin = verMinor; + vmaj = verMajor; + return true; } bool trpgHeader::GetDbVersion(int32 &vmaj,int32 &vmin) const { - if (!isValid()) return false; - vmaj = dbVerMajor; - vmin = dbVerMinor; - return true; + if (!isValid()) return false; + vmaj = dbVerMajor; + vmin = dbVerMinor; + return true; } bool trpgHeader::GetTileSize(int id,trpg2dPoint &pt) const { - if (!isValid()) return false; - if (id < 0 || id >= (int)tileSize.size()) return false; - pt = tileSize[id]; - return true; + if (!isValid()) return false; + if (id < 0 || id >= (int)tileSize.size()) return false; + pt = tileSize[id]; + return true; } bool trpgHeader::GetOrigin(trpg3dPoint &pt) const { - if (!isValid()) return false; - pt = origin; - return true; + if (!isValid()) return false; + pt = origin; + return true; } bool trpgHeader::GetTileOriginType(trpgTileType &type) const { - if (!isValid()) return false; - type = tileType; - return true; + if (!isValid()) return false; + type = tileType; + return true; } bool trpgHeader::GetNumLods(int32 &no) const { - if (!isValid()) return false; - no = numLods; - return true; + if (!isValid()) return false; + no = numLods; + return true; } bool trpgHeader::GetLodSize(int32 id,trpg2iPoint &pt) const { - if (!isValid() || (id < 0 || id >= numLods)) return false; - pt = lodSizes[id]; - return true; + if (!isValid() || (id < 0 || id >= numLods)) return false; + pt = lodSizes[id]; + return true; } bool trpgHeader::GetLodRange(int32 id,float64 &range) const { - if (!isValid() || (id < 0 || id >= numLods)) return false; - range = lodRanges[id]; - return true; + if (!isValid() || (id < 0 || id >= numLods)) return false; + range = lodRanges[id]; + return true; } bool trpgHeader::GetExtents(trpg2dPoint &osw,trpg2dPoint &one) const { - if (!isValid()) return false; - osw = sw; - one = ne; - return true; + if (!isValid()) return false; + osw = sw; + one = ne; + return true; } bool trpgHeader::GetMaxGroupID(int &id) const { - id = maxGroupID; - return true; + id = maxGroupID; + return true; } // Read in the header bool trpgHeader::Read(trpgReadBuffer &buf) { - uint8 i8; - trpgToken tok; - bool status; - int32 len; + uint8 i8; + trpgToken tok; + bool status; + int32 len; - try { - buf.Get(verMajor); - buf.Get(verMinor); - buf.Get(dbVerMajor); - buf.Get(dbVerMinor); - buf.Get(origin); - buf.Get(sw); - buf.Get(ne); - buf.Get(i8); tileType = (trpgTileType)i8; - buf.Get(numLods); - if (numLods < 0) throw 1; + try { + buf.Get(verMajor); + buf.Get(verMinor); + buf.Get(dbVerMajor); + buf.Get(dbVerMinor); + buf.Get(origin); + buf.Get(sw); + buf.Get(ne); + buf.Get(i8); tileType = (trpgTileType)i8; + buf.Get(numLods); + if (numLods < 0) throw 1; - // Read in the LOD range info - buf.GetToken(tok,len); - if (tok != TRPGHEAD_LODINFO) throw 1; - buf.PushLimit(len); - status = ReadLodInfo(buf); - buf.PopLimit(); - if (!status) throw 1; + // Read in the LOD range info + buf.GetToken(tok,len); + if (tok != TRPGHEAD_LODINFO) throw 1; + buf.PushLimit(len); + status = ReadLodInfo(buf); + buf.PopLimit(); + if (!status) throw 1; - // Added after the first version (but still in 1.0) - buf.Get(maxGroupID); - } + // Added after the first version (but still in 1.0) + buf.Get(maxGroupID); + if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) { + buf.Get(flags); + buf.Get(rows); + buf.Get(cols); + } + } - 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 +#ifndef TeAttrH +/* was unsigned long, but it is used as if it was signed in the constructor + * and code that set the handle are using a signed value. + * 01-10-2006 David Fries + */ +typedef long TeAttrHdl; +#endif + // Macros we may need #ifndef MIN // {secret} @@ -33,16 +41,21 @@ #endif // File header Magic Number -#define TRPG_MAGIC 9480372 +#define TRPG_MAGIC 9480372 // Current TerraPage major version #define TRPG_VERSION_MAJOR 2 // Current TerraPage minor version -#define TRPG_VERSION_MINOR 0 +#define TRPG_VERSION_MINOR 2 + +// defined values for the version that doesn't need +// a merge +#define TRPG_NOMERGE_VERSION_MAJOR 2 +#define TRPG_NOMERGE_VERSION_MINOR 2 // Non-existent token // {secret} -#define TRPG_NOTOKEN 0 +#define TRPG_NOTOKEN 0 // 16 bit token definition value. These are values such as TRPGTEXTABLE or TRPG_ATTACH, etc... typedef short trpgToken; @@ -50,127 +63,132 @@ typedef short trpgToken; // Tokens for paging data structures // Update the MINTOKEN and MAXTOKEN when you add tokens // {secret} -#define TRPG_MINTOKEN 100 +#define TRPG_MINTOKEN 100 // {secret} -#define TRPG_PUSH 100 +#define TRPG_PUSH 100 // {secret} -#define TRPG_POP 101 +#define TRPG_POP 101 // {secret} -#define TRPGHEADER 200 +#define TRPGHEADER 200 // {secret} -#define TRPGHEAD_LODINFO 201 +#define TRPGHEAD_LODINFO 201 // {secret} -#define TRPGMATTABLE 300 +#define TRPGMATTABLE 300 // Added 11/14/98 - New material table // {secret} -#define TRPGMATTABLE2 301 +#define TRPGMATTABLE2 301 // Added 11/14/98 // {secret} -#define TRPGSHORTMATTABLE 302 +#define TRPGSHORTMATTABLE 302 // {secret} -#define TRPGMATERIAL 400 +#define TRPGMATERIAL 400 // {secret} -#define TRPGMAT_BASIC 401 +#define TRPGMAT_BASIC 401 // {secret} -#define TRPGMAT_SHADE 402 +#define TRPGMAT_SHADE 402 // {secret} // {secret} -#define TRPGMAT_SIZES 403 +#define TRPGMAT_SIZES 403 // {secret} -#define TRPGMAT_CULL 404 +#define TRPGMAT_CULL 404 // {secret} -#define TRPGMAT_ALPHA 405 +#define TRPGMAT_ALPHA 405 // {secret} -#define TRPGMAT_NORMAL 406 +#define TRPGMAT_NORMAL 406 // {secret} -#define TRPGMAT_TEXTURE 407 +#define TRPGMAT_TEXTURE 407 // {secret} -#define TRPGMAT_BUMP 408 +#define TRPGMAT_BUMP 408 // {secret} -#define TRPGMAT_ATTR 409 +#define TRPGMAT_ATTR 409 +// {secret} +#define TRPGMAT_HANDLE 410 // {secret} -#define TRPGMAT_TEXENV 500 +#define TRPGMAT_TEXENV 500 // {secret} -#define TRPGMAT_TXENV_MODE 501 +#define TRPGMAT_TXENV_MODE 501 // {secret} #define TRPGMAT_TXENV_FILTER 502 // {secret} -#define TRPGMAT_TXENV_WRAP 503 +#define TRPGMAT_TXENV_WRAP 503 // {secret} #define TRPGMAT_TXENV_BORDER 504 // {secret} -#define TRPGTEXTABLE 600 +#define TRPGTEXTABLE 600 // {secret} -#define TRPGTEXTABLE2 601 +#define TRPGTEXTABLE2 601 // {secret} -#define TRPGTEXTURE 650 +#define TRPGTEXTURE 650 // {secret} -#define TRPGMODELREF 700 +#define TRPGMODELREF 700 +// {secret} +#define TRPGMODELREF2 701 +// {secret} +#define TRPGMODELTABLE 800 // {secret} -#define TRPGMODELTABLE 800 +#define TRPGTILETABLE 900 +// {secret} +#define TRPG_TILE_ENTRY 901 +// {secret} +#define TRPGTILETABLE2 902 // {secret} -#define TRPGTILETABLE 900 +#define TRPGTILEHEADER 1000 // {secret} -#define TRPG_TILE_ENTRY 901 +#define TRPG_TILE_MATLIST 1001 // {secret} -#define TRPGTILETABLE2 902 - +#define TRPG_TILE_MODELLIST 1002 // {secret} -#define TRPGTILEHEADER 1000 +#define TRPG_TILE_DATE 1003 // {secret} -#define TRPG_TILE_MATLIST 1001 +#define TRPGLOCALMATERIAL 1004 // {secret} -#define TRPG_TILE_MODELLIST 1002 -// {secret} -#define TRPG_TILE_DATE 1003 -// {secret} -#define TRPGLOCALMATERIAL 1004 -// {secret} -#define TRPG_TILE_LOCMATLIST 1005 +#define TRPG_TILE_LOCMATLIST 1005 // Lights support added by Nick // {secret} -#define TRPGLIGHTTABLE 1100 +#define TRPGLIGHTTABLE 1100 // {secret} -#define TRPGLIGHTATTR 1150 +#define TRPGLIGHTATTR 1150 // {secret} -#define TRPGLIGHTATTR_BASIC 1151 +#define TRPGLIGHTATTR_BASIC 1151 // {secret} -#define TRPGLIGHTATTR_RASCAL 1152 +#define TRPGLIGHTATTR_RASCAL 1152 // {secret} -#define TRPGLIGHTATTR_CALLIGRAPHIC 1153 +#define TRPGLIGHTATTR_CALLIGRAPHIC 1153 // {secret} -#define TRPGLIGHTATTR_PERFORMER 1154 +#define TRPGLIGHTATTR_PERFORMER 1154 // {secret} -#define TRPGLIGHTATTR_ANIMATION 1155 +#define TRPGLIGHTATTR_ANIMATION 1155 // {secret} -#define TRPGLIGHTATTR_COMMENT 1156 +#define TRPGLIGHTATTR_COMMENT 1156 // {secret} -#define TRPGLIGHT 1160 +#define TRPGLIGHTATTR_HANDLE 1157 // {secret} -#define TRPG_LIGHT 1160 +#define TRPGLIGHT 1160 +// {secret} +#define TRPG_LIGHT 1160 // {secret} -#define TRPGRANGETABLE 1200 +#define TRPGRANGETABLE 1200 // {secret} -#define TRPG_RANGE 1201 +#define TRPG_RANGE 1201 // Label and style support added 12-02 // {secret} -#define TRPG_TEXT_STYLE_TABLE 1300 +#define TRPG_TEXT_STYLE_TABLE 1300 // {secret} -#define TRPG_TEXT_STYLE 1301 +#define TRPG_TEXT_STYLE 1301 // {secret} -#define TRPG_TEXT_STYLE_BASIC 1302 +#define TRPG_TEXT_STYLE_BASIC 1302 // {secret} #define TRPG_SUPPORT_STYLE_TABLE 1310 @@ -188,50 +206,53 @@ typedef short trpgToken; // {secret} -#define TRPG_LABEL 1330 +#define TRPG_LABEL 1330 // {secret} -#define TRPG_GROUP 2001 +#define TRPG_GROUP 2001 // {secret} -#define TRPG_BILLBOARD 2002 +#define TRPG_BILLBOARD 2002 // {secret} -#define TRPG_LOD 2003 +#define TRPG_LOD 2003 // {secret} -#define TRPG_TRANSFORM 2004 +#define TRPG_TRANSFORM 2004 // {secret} -#define TRPG_MODELREF 2005 +#define TRPG_MODELREF 2005 // {secret} -#define TRPG_LAYER 2006 +#define TRPG_LAYER 2006 // {secret} -#define TRPG_GEOMETRY 3000 +#define TRPG_GEOMETRY 3000 // {secret} -#define TRPG_GEOM_PRIM 3001 +#define TRPG_GEOM_PRIM 3001 // {secret} -#define TRPG_GEOM_MATERIAL 3002 +#define TRPG_GEOM_MATERIAL 3002 // {secret} -#define TRPG_GEOM_VERT32 3003 +#define TRPG_GEOM_VERT32 3003 // {secret} -#define TRPG_GEOM_VERT64 3004 +#define TRPG_GEOM_VERT64 3004 // {secret} -#define TRPG_GEOM_NORM32 3005 +#define TRPG_GEOM_NORM32 3005 // {secret} -#define TRPG_GEOM_NORM64 3006 +#define TRPG_GEOM_NORM64 3006 // {secret} -#define TRPG_GEOM_COLOR 3007 +#define TRPG_GEOM_COLOR 3007 // {secret} -#define TRPG_GEOM_TEX32 3008 +#define TRPG_GEOM_TEX32 3008 // {secret} -#define TRPG_GEOM_TEX64 3009 +#define TRPG_GEOM_TEX64 3009 // {secret} -#define TRPG_GEOM_EFLAG 3010 +#define TRPG_GEOM_EFLAG 3010 // {secret} -#define TRPG_ATTACH 4000 +#define TRPG_ATTACH 4000 // {secret} -#define TRPG_MAXTOKEN 4000 +#define TRPG_CHILDREF 5000 + +// {secret} +#define TRPG_MAXTOKEN 5000 // Basic data types @@ -243,424 +264,462 @@ typedef int trpgMatRef; /* Double precision 2 dimensional point. */ TX_EXDECL class TX_CLDECL trpg2dPoint { public: - double x, y; - trpg2dPoint (void) { }; - trpg2dPoint (double in_x,double in_y) { x = in_x; y = in_y; }; - bool operator==(const trpg2dPoint& pt ) const { - if ( x != pt.x ) return false; - if ( y != pt.y ) return false; - return true; - }; - bool operator!=(const trpg2dPoint& pt ) const { return !operator==(pt); }; + double x, y; + trpg2dPoint (void) { }; + trpg2dPoint (double in_x,double in_y) { x = in_x; y = in_y; }; + bool operator==(const trpg2dPoint& pt ) const { + if ( x != pt.x ) return false; + if ( y != pt.y ) return false; + return true; + }; + bool operator!=(const trpg2dPoint& pt ) const { return !operator==(pt); }; }; /* Integer 2 dimensional point. This is used primarily as a 2D index value. */ TX_EXDECL class TX_CLDECL trpg2iPoint { public: - int x,y; - trpg2iPoint (void) { }; - trpg2iPoint (int in_x,int in_y) {x = in_x; y = in_y;}; + int x,y; + trpg2iPoint (void) { }; + trpg2iPoint (int in_x,int in_y) {x = in_x; y = in_y;}; }; /* Double precision 3 dimensional point. */ TX_EXDECL class TX_CLDECL trpg3dPoint { public: - double x,y,z; - trpg3dPoint(void) { }; - trpg3dPoint(double in_x,double in_y,double in_z) {x = in_x; y = in_y; z = in_z;} - bool operator==(const trpg3dPoint& pt ) const { - if ( x != pt.x ) return false; - if ( y != pt.y ) return false; - if ( z != pt.z ) return false; - return true; - }; - bool operator!=(const trpg3dPoint& pt ) const { return !operator==(pt); }; + double x,y,z; + trpg3dPoint(void) { }; + trpg3dPoint(double in_x,double in_y,double in_z) {x = in_x; y = in_y; z = in_z;} + bool operator==(const trpg3dPoint& pt ) const { + if ( x != pt.x ) return false; + if ( y != pt.y ) return false; + if ( z != pt.z ) return false; + return true; + }; + bool operator!=(const trpg3dPoint& pt ) const { return !operator==(pt); }; }; /* Simple red, green, blue color definition */ TX_EXDECL class TX_CLDECL trpgColor { public: - trpgColor(float64 r,float64 g,float64 b) {red = r; green = g; blue = b;} - trpgColor(void) { }; - bool operator==(const trpgColor& color) { - if ( color.red != red ) return false; - if ( color.green != green ) return false; - if ( color.blue != blue ) return false; - return true; - }; - bool operator!=(const trpgColor& color) { return !operator==(color); }; - float64 red,green,blue; + trpgColor(float64 r,float64 g,float64 b) {red = r; green = g; blue = b;} + trpgColor(void) { }; + bool operator==(const trpgColor& color) { + if ( color.red != red ) return false; + if ( color.green != green ) return false; + if ( color.blue != blue ) return false; + return true; + }; + bool operator!=(const trpgColor& color) { return !operator==(color); }; + float64 red,green,blue; }; // Used to specify machine endianess typedef enum {LittleEndian,BigEndian} trpgEndian; -/* This is a base class for an abstract buffer type. - It contains the virtual methods for writing - data to an abstract device. The device implementation is up - to the subclass. trpgReadBuffer performs the similar function - for reading. - {group:Low Level I/O} - */ +/* This is a base class for an abstract buffer type. + It contains the virtual methods for writing + data to an abstract device. The device implementation is up + to the subclass. trpgReadBuffer performs the similar function + for reading. + {group:Low Level I/O} + */ TX_EXDECL class TX_CLDECL trpgWriteBuffer { public: - virtual ~trpgWriteBuffer(void) { }; - /* The add functions must be filled in by the child class - They add data of the appropriate type to the current buffer. */ - virtual void Add(int32) = 0; - virtual void Add(int64) = 0; - virtual void Add(const char *) = 0; - virtual void Add(float32) = 0; - virtual void Add(float64) = 0; + virtual ~trpgWriteBuffer(void) { }; + /* The add functions must be filled in by the child class + They add data of the appropriate type to the current buffer. */ + virtual void Add(int32) = 0; + virtual void Add(int64) = 0; + virtual void Add(const char *) = 0; + virtual void Add(float32) = 0; + virtual void Add(float64) = 0; //#if (bool != int32) - virtual void Add(bool) = 0; + virtual void Add(bool) = 0; //#endif - virtual void Add(uint8) = 0; + virtual void Add(uint8) = 0; #if (trpgDiskRef != int64) - virtual void Add(trpgDiskRef) = 0; + virtual void Add(trpgDiskRef) = 0; #endif - virtual void Add(trpgToken) = 0; - /* Child class method. Returns the buffer to an original state. */ - virtual void Reset(void) = 0; - // See trpgMemWriteBuffer for details - virtual void Begin(trpgToken) = 0; - // See trpgMemWriteBuffer for details - virtual void End(void) = 0; - // See trpgMemWriteBuffer for details - virtual void Push(void) = 0; - // See trpgMemWriteBuffer for details - virtual void Pop(void) = 0; + virtual void Add(trpgToken) = 0; + /* Child class method. Returns the buffer to an original state. */ + virtual void Reset(void) = 0; + // See trpgMemWriteBuffer for details + virtual void Begin(trpgToken) = 0; + // See trpgMemWriteBuffer for details + virtual void End(void) = 0; + // See trpgMemWriteBuffer for details + virtual void Push(void) = 0; + // See trpgMemWriteBuffer for details + virtual void Pop(void) = 0; - // Some add functions are helpers for composite values that call the basic add functions - virtual void Add(const trpg2iPoint &); - virtual void Add(const trpg2dPoint &); - virtual void Add(const trpg3dPoint &); - virtual void Add(const trpgColor &); - virtual void Add(const std::string &); + // Some add functions are helpers for composite values that call the basic add functions + virtual void Add(const trpg2iPoint &); + virtual void Add(const trpg2dPoint &); + virtual void Add(const trpg3dPoint &); + virtual void Add(const trpgColor &); + virtual void Add(const std::string &); - /* Endianness is something the child class buffer type must set and use. - This function returns the endiannes of the current buffer. */ - virtual trpgEndian GetEndian(void) { return ness; } + /* Endianness is something the child class buffer type must set and use. + This function returns the endiannes of the current buffer. */ + virtual trpgEndian GetEndian(void) { return ness; } protected: - // Target endianness of the buffer. This should be set by the subclass on creation. - trpgEndian ness; - // Endianness of the machine we're running on. - trpgEndian cpuNess; + // Target endianness of the buffer. This should be set by the subclass on creation. + trpgEndian ness; + // Endianness of the machine we're running on. + trpgEndian cpuNess; }; /* The Memory Write Buffer is an implementation of the Write Buffer that - uses chunks of memory. It contains implementations of the all the virtual - methods straight to memory. This is used primarily in writing archives and - tiles. - {group:Low Level I/O} - */ + uses chunks of memory. It contains implementations of the all the virtual + methods straight to memory. This is used primarily in writing archives and + tiles. + {group:Low Level I/O} + */ TX_EXDECL class TX_CLDECL trpgMemWriteBuffer : public trpgWriteBuffer { public: - /* The constructor takes an endianness for this buffer. - Data will automatically be converted to that as it goes in. */ - trpgMemWriteBuffer(trpgEndian); - virtual ~trpgMemWriteBuffer(void); - // Return the current length of buffer - virtual int length(void) const; - // Return the raw data (if you want to write to disk, for example) - virtual const char *getData(void) const; - // Allocate the given amount of space for the buffer - virtual void setLength(unsigned int); + /* The constructor takes an endianness for this buffer. + Data will automatically be converted to that as it goes in. */ + trpgMemWriteBuffer(trpgEndian); + virtual ~trpgMemWriteBuffer(void); + // Return the current length of buffer + virtual int length(void) const; + // Return the raw data (if you want to write to disk, for example) + virtual const char *getData(void) const; + // Allocate the given amount of space for the buffer + virtual void setLength(unsigned int); - // Add a 32 bit integer to the buffer - virtual void Add(int32); - // Add a 64 bit integer to the buffer - virtual void Add(int64); - /* Add an arbitrary length string to the buffer. - This writes both the length and the string itself. - */ - virtual void Add(const char *); - // Same as const char * version - virtual void Add(std::string &); - // Add a 32 bit float to the buffer - virtual void Add(float32); - // Add a 64 bit float to the buffer - virtual void Add(float64); + // Add a 32 bit integer to the buffer + virtual void Add(int32); + // Add a 64 bit integer to the buffer + virtual void Add(int64); + /* Add an arbitrary length string to the buffer. + This writes both the length and the string itself. + */ + virtual void Add(const char *); + // Same as const char * version + virtual void Add(std::string &); + // Add a 32 bit float to the buffer + virtual void Add(float32); + // Add a 64 bit float to the buffer + virtual void Add(float64); //#if (bool != int32) - // Add a boolean value to the buffer. It will become at least one byte. - virtual void Add(bool); + // Add a boolean value to the buffer. It will become at least one byte. + virtual void Add(bool); //#endif - // Add an unsigned character to the buffer - virtual void Add(uint8); + // Add an unsigned character to the buffer + virtual void Add(uint8); #if (trpgDiskRef != int64) - // Add a 64 bit disk reference to the buffer - virtual void Add(trpgDiskRef); + // Add a 64 bit disk reference to the buffer + virtual void Add(trpgDiskRef); #endif - // Add a token (16 bit) to the buffer - virtual void Add(trpgToken); - // Reset this buffer. This will set the current length to zero, but will not deallocate memory - virtual void Reset(void); - /* Start defining an tokenized object. The token is put into the buffer stream - and the position of a size value following it is kept. When End() is called - the buffer will rewind to that value and save the size. This method ensures - that token data can be skipped if necessary. */ - virtual void Begin(trpgToken); - /* This method is called at the end of a tokenized object. See Begin for details. */ - virtual void End(void); - /* Adds the TRPG_PUSH token to the current buffer. This is done by objects - that have children as they're being written. See Pop as well. */ - virtual void Push(void); - /* Adds the TRPG_POP token to the current buffer. This is done by objects - that have defined children. See Push. */ - virtual void Pop(void); + // Add a token (16 bit) to the buffer + virtual void Add(trpgToken); + // Reset this buffer. This will set the current length to zero, but will not deallocate memory + virtual void Reset(void); + /* Start defining an tokenized object. The token is put into the buffer stream + and the position of a size value following it is kept. When End() is called + the buffer will rewind to that value and save the size. This method ensures + that token data can be skipped if necessary. */ + virtual void Begin(trpgToken); + /* This method is called at the end of a tokenized object. See Begin for details. */ + virtual void End(void); + /* Adds the TRPG_PUSH token to the current buffer. This is done by objects + that have children as they're being written. See Pop as well. */ + virtual void Push(void); + /* Adds the TRPG_POP token to the current buffer. This is done by objects + that have defined children. See Push. */ + virtual void Pop(void); + /* Take out the pop from the end of the buffer, if there is one */ + /* Will return true if a pop was actually taken out */ + virtual bool UnPop(); + /* Take out the push from the end of the buffer, if there is one */ + /* Will return true if a push was actually taken out */ + virtual bool UnPush(); protected: - 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; + 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(std::string &); - 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(std::string &); + 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; + + // MD: making this public to unravel trpgModel read problem. + /* 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); 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); - std::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; + /* 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); + // Gets the size of the buffer. + int GetLength(void) { return len; } + /* 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; + + virtual TeAttrHdl GetHandle() const { + return handle; + } + virtual void SetHandle(TeAttrHdl hdl) { + writeHandle = true; + handle = hdl; + } + 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; + TeAttrHdl handle; + bool writeHandle; }; 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: - trpgReadWriteable() { errMess[0] = '\0';} + trpgReadWriteable() { errMess[0] = '\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; } + /* 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; } - const char *getErrMess() const {if(errMess[0] == '\0') return 0;else return &errMess[0];} + const char *getErrMess() const {if(errMess[0] == '\0') return 0;else return &errMess[0];} protected: - mutable char errMess[512]; + mutable char errMess[512]; }; /* Pointer into a trpgwAppFile. The full name of the file - is based on the context (e.g. texture vs. tile) - {group:Archive Writing} + is based on the context (e.g. texture vs. tile) + {group:Archive Writing} */ TX_EXDECL class TX_CLDECL trpgwAppAddress { public: - trpgwAppAddress() {file = -1; offset = -1;}; - // Which file - int32 file; - // Offset within the file - // Note: This is not a 64 bit value - int32 offset; + trpgwAppAddress() {file = -1; offset = -1; row = -1; col = -1;}; + // Which file + int32 file; + // Offset within the file + // Note: This is not a 64 bit value + int32 offset; + // Row and col are used for TerraPage 2.3 archives, so we + // can know which block to get the appropriate file from + int32 row; + int32 col; + }; /* Archive File. - This class represents an appendable file archive used for - consolidating tiles and textures. - {group:Archive Writing} + 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(); - virtual bool Flush(void); + trpgwAppFile() {valid=false;}; + trpgwAppFile(trpgEndian,const char *,bool reuse=false); + 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(); + virtual bool Flush(void); + virtual void Init(trpgEndian,const char *,bool reuse=false); - bool isValid(void) const; + bool isValid(void) const; protected: - bool valid; - trpgEndian ness,cpuNess; - FILE *fp; - int lengthSoFar; + 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. + 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 baseOffset,int32 objOffset,int32 dataSize); + trpgrAppFile() {valid=false;}; + trpgrAppFile(trpgEndian,const char *); + // real construction is here + virtual void Init(trpgEndian,const char *); + virtual ~trpgrAppFile(void); + virtual bool Read(trpgMemReadBuffer *,int32 offset); + virtual bool Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSize); - bool isValid(void) const; + bool isValid(void) const; protected: - bool valid; - trpgEndian ness,cpuNess; - FILE *fp; + bool valid; + trpgEndian ness,cpuNess; + FILE *fp; }; /* Archive File Cache. - This class keeps + 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); + trpgrAppFileCache(){;}; + trpgrAppFileCache(const char *prefix,const char *ext,int noFiles=32); + // real construction is here + virtual void Init(const char *prefix,const char *ext,int noFiles); + virtual ~trpgrAppFileCache(void); + virtual trpgrAppFile *GetFile(trpgEndian ness,int id,int col,int row); + virtual trpgrAppFile *GetFile(trpgEndian ness,int id); + virtual trpgrAppFile *GetNewRAppFile(trpgEndian ness, const char *fileName); protected: - // Prefix name and extension - char baseName[1024],ext[20]; + // 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 - }; + class OpenFile { + public: + OpenFile(void); + int id; // ID of open file + int row; + int col; + trpgrAppFile *afile; + int lastUsed; // When the file was last accessed + }; - std::vector files; - int timeCount; // Incremented for every access + std::vector files; + int timeCount; // Incremented for every access }; #endif diff --git a/src/osgPlugins/txp/trpage_label.cpp b/src/osgPlugins/txp/trpage_label.cpp index 77e4b0d7f..af5a62528 100644 --- a/src/osgPlugins/txp/trpage_label.cpp +++ b/src/osgPlugins/txp/trpage_label.cpp @@ -14,13 +14,13 @@ */ /* trpage_label.cpp - Methods for the trpgLable object and its associated support structure - including trpgTextStyle and trpgTextStyleTable. - */ + Methods for the trpgLable object and its associated support structure + including trpgTextStyle and trpgTextStyleTable. +*/ #include #include -#include +#include #include #include @@ -114,9 +114,9 @@ bool trpgTextStyle::Write(trpgWriteBuffer &buf) buf.Begin(TRPG_TEXT_STYLE_BASIC); buf.Add(font); - buf.Add(bold); - buf.Add(italic); - buf.Add(underline); + buf.Add((int32)bold); + buf.Add((int32)italic); + buf.Add((int32)underline); buf.Add(characterSize); buf.Add(matId); buf.End(); @@ -129,8 +129,9 @@ bool trpgTextStyle::Write(trpgWriteBuffer &buf) // TextStyle CB // Used to parse tokens from the text style structure. // If we do it this way it's easier to expand later. -class textStyleCB : public trpgr_Callback { -public: +class textStyleCB : public trpgr_Callback +{ + public: void * Parse(trpgToken,trpgReadBuffer &); trpgTextStyle *style; }; @@ -141,8 +142,10 @@ void * textStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf) int iVal; float32 fVal; - try { - switch (tok) { + try + { + switch (tok) + { case TRPG_TEXT_STYLE_BASIC: buf.Get(sVal); style->SetFont(sVal); @@ -161,7 +164,8 @@ void * textStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf) break; } } - catch (...) { + catch (...) + { return NULL; } @@ -196,7 +200,7 @@ bool trpgTextStyle::isValid(void) const bool trpgTextStyle::operator == (const trpgTextStyle& in) const { - if (font.compare(in.font) != 0) + if (font != in.font) return false; if (bold != in.bold || @@ -220,19 +224,22 @@ trpgTextStyleTable::trpgTextStyleTable() { Reset(); } + trpgTextStyleTable::~trpgTextStyleTable() { } void trpgTextStyleTable::Reset() { - styles.resize(0); + styleMap.clear(); } bool trpgTextStyleTable::isValid() const { - for (unsigned int i=0;isecond.isValid()) return false; return true; @@ -240,30 +247,38 @@ bool trpgTextStyleTable::isValid() const int trpgTextStyleTable::AddStyle(const trpgTextStyle &style) { - styles.push_back(style); - return styles.size() -1; + int handle = style.GetHandle(); + if(handle==-1) { + handle = styleMap.size(); + } + styleMap[handle] = style; + return handle; } int trpgTextStyleTable::FindAddStyle(const trpgTextStyle &style) { - for (unsigned int i=0;isecond == style) + return itr->first; return AddStyle(style); } int trpgTextStyleTable::GetNumStyle() const { - return styles.size(); + return styleMap.size(); } const trpgTextStyle *trpgTextStyleTable::GetStyleRef(int id) const { - if (id < 0 || id >= (int)styles.size()) + if (id < 0) return NULL; - return &styles[id]; + StyleMapType::const_iterator itr = styleMap.find(id); + if(itr == styleMap.end()) + return NULL; + return &itr->second; } bool trpgTextStyleTable::Write(trpgWriteBuffer &buf) @@ -274,12 +289,13 @@ bool trpgTextStyleTable::Write(trpgWriteBuffer &buf) buf.Begin(TRPG_TEXT_STYLE_TABLE); // Number of styles - int numStyle = styles.size(); + int numStyle = styleMap.size(); buf.Add((int32)numStyle); // Write the styles - for (unsigned int i=0;isecond.Write(buf); buf.End(); @@ -293,16 +309,17 @@ bool trpgTextStyleTable::Read(trpgReadBuffer &buf) int32 len; bool status; int numStyle; - int i; + int i; Reset(); - try { + try + { buf.Get(numStyle); if (numStyle < 0) throw 1; - styles.resize(numStyle); - for (i=0;iSetType(trpgSupportStyle::SupportType(iVal)); @@ -400,7 +423,8 @@ void * supportStyleCB::Parse(trpgToken tok,trpgReadBuffer &buf) break; } } - catch (...) { + catch (...) + { return NULL; } @@ -450,44 +474,56 @@ trpgSupportStyleTable::~trpgSupportStyleTable() void trpgSupportStyleTable::Reset() { - styles.resize(0); + //styles.resize(0); + supportStyleMap.clear(); } bool trpgSupportStyleTable::isValid() const { - for (unsigned int i=0;isecond.isValid()) return false; - + } return true; } int trpgSupportStyleTable::AddStyle(const trpgSupportStyle &style) { - styles.push_back(style); - return styles.size() -1; + int handle = style.GetHandle(); + if(handle==-1) + { + handle = supportStyleMap.size(); + } + supportStyleMap[handle] = style; + return handle; } int trpgSupportStyleTable::FindAddStyle(const trpgSupportStyle &style) { - for (unsigned int i=0;isecond == style) + return itr->first; return AddStyle(style); } int trpgSupportStyleTable::GetNumStyle() const { - return styles.size(); + return supportStyleMap.size(); } const trpgSupportStyle *trpgSupportStyleTable::GetStyleRef(int id) const { - if (id < 0 || id >= (int)styles.size()) + if (id < 0) return NULL; - - return &styles[id]; + SupportStyleMapType::const_iterator itr = supportStyleMap.find(id); + if(itr == supportStyleMap.end()) + return NULL; + return &itr->second; } bool trpgSupportStyleTable::Write(trpgWriteBuffer &buf) @@ -498,12 +534,13 @@ bool trpgSupportStyleTable::Write(trpgWriteBuffer &buf) buf.Begin(TRPG_SUPPORT_STYLE_TABLE); // Number of styles - int numStyle = styles.size(); + int numStyle = supportStyleMap.size(); buf.Add((int32)numStyle); // Write the styles - for (unsigned int i=0;isecond.Write(buf); buf.End(); @@ -517,15 +554,17 @@ bool trpgSupportStyleTable::Read(trpgReadBuffer &buf) int32 len; bool status; int numStyle; + int i; Reset(); - try { + try + { buf.Get(numStyle); if (numStyle < 0) throw 1; - styles.resize(numStyle); - for (int i=0;iSetFontStyle(iVal); @@ -637,7 +682,8 @@ void * labelPropertyCB::Parse(trpgToken tok,trpgReadBuffer &buf) break; } } - catch (...) { + catch (...) + { return NULL; } @@ -686,44 +732,56 @@ trpgLabelPropertyTable::~trpgLabelPropertyTable() void trpgLabelPropertyTable::Reset() { - properties.resize(0); + labelPropertyMap.clear(); } bool trpgLabelPropertyTable::isValid() const { - for (unsigned int i=0;isecond.isValid()) return false; - + } return true; } int trpgLabelPropertyTable::AddProperty(const trpgLabelProperty &property) { - properties.push_back(property); - return properties.size() -1; + int handle = property.GetHandle(); + if(handle==-1) + { + handle = labelPropertyMap.size(); + } + labelPropertyMap[handle] = property; + return handle; } int trpgLabelPropertyTable::FindAddProperty(const trpgLabelProperty& property) { - for (unsigned int i=0;isecond == property) + return itr->first; + } return AddProperty(property); } int trpgLabelPropertyTable::GetNumProperty() const { - return properties.size(); + return labelPropertyMap.size(); } const trpgLabelProperty *trpgLabelPropertyTable::GetPropertyRef(int id) const { - if (id < 0 || id >= (int)properties.size()) + if (id < 0) return NULL; - return &properties[id]; + LabelPropertyMapType::const_iterator itr = labelPropertyMap.find(id); + if(itr == labelPropertyMap.end()) + return NULL; + return &itr->second; } bool trpgLabelPropertyTable::Write(trpgWriteBuffer &buf) @@ -734,12 +792,15 @@ bool trpgLabelPropertyTable::Write(trpgWriteBuffer &buf) buf.Begin(TRPG_LABEL_PROPERTY_TABLE); // Number of styles - int numProperty = properties.size(); + int numProperty = labelPropertyMap.size(); buf.Add((int32)numProperty); // Write the properties - for (unsigned int i=0;isecond.Write(buf); + } buf.End(); @@ -753,15 +814,17 @@ bool trpgLabelPropertyTable::Read(trpgReadBuffer &buf) int32 len; bool status; int numProperty; + int i; Reset(); - try { + try + { buf.Get(numProperty); if (numProperty < 0) throw 1; - properties.resize(numProperty); - for (unsigned int i=0;i<(unsigned int)numProperty;i++) { + //properties.resize(numProperty); + for (i=0;i *trpgLabel::GetSupports() const bool trpgLabel::Write(trpgWriteBuffer &buf) { + unsigned int i; + buf.Begin(TRPG_LABEL); buf.Add(propertyId); buf.Add(text); @@ -931,7 +998,7 @@ bool trpgLabel::Write(trpgWriteBuffer &buf) buf.Add(url); buf.Add(location); buf.Add((int)supports.size()); - for (unsigned i=0;i #include @@ -34,864 +34,886 @@ #endif /****** - Lights Attribute + Lights Attribute ******/ trpgLightAttr::trpgLightAttr(void) { - data.commentStr = NULL; - Reset(); + data.commentStr = NULL; + Reset(); } trpgLightAttr::trpgLightAttr(const trpgLightAttr& in): trpgReadWriteable(in) { - data.commentStr = NULL; - operator=(in); + data.commentStr = NULL; + operator=(in); } trpgLightAttr::~trpgLightAttr(void) { - if (data.commentStr) - delete [] data.commentStr; - data.commentStr = NULL; + if (data.commentStr) + delete [] data.commentStr; + data.commentStr = NULL; } // Setters void trpgLightAttr::SetType( trpgLightAttr::LightType in_type ) { - data.type = in_type; + data.type = in_type; } void trpgLightAttr::SetDirectionality( trpgLightAttr::LightDirectionality in_directionality ) { - data.directionality = in_directionality; + data.directionality = in_directionality; } void trpgLightAttr::SetFrontColor( trpgColor in_frontColor ) { - data.frontColor = in_frontColor; + data.frontColor = in_frontColor; } void trpgLightAttr::SetFrontIntensity( float64 in_frontIntensity ) { - data.frontIntensity = in_frontIntensity; + data.frontIntensity = in_frontIntensity; } void trpgLightAttr::SetBackColor( trpgColor in_backColor ) { - data.backColor = in_backColor; + data.backColor = in_backColor; } void trpgLightAttr::SetBackIntensity( float64 in_backIntensity ) { - data.backIntensity = in_backIntensity; + data.backIntensity = in_backIntensity; } void trpgLightAttr::SetNormal( trpg3dPoint in_normal ) { - data.normal = in_normal; + data.normal = in_normal; } void trpgLightAttr::SetSMC( int32 in_smc ) { - data.smc = in_smc; + data.smc = in_smc; } void trpgLightAttr::SetFID( int32 in_fid ) { - data.fid = in_fid; + data.fid = in_fid; } void trpgLightAttr::SetFlags( int32 in_flags ) { - data.flags = in_flags; + data.flags = in_flags; } void trpgLightAttr::SetHLobeAngle( float64 in_hLobeAngle ) { - data.horizontalLobeAngle = in_hLobeAngle; + data.horizontalLobeAngle = in_hLobeAngle; } void trpgLightAttr::SetVLobeAngle( float64 in_vLobeAngle ) { - data.verticalLobeAngle = in_vLobeAngle; + data.verticalLobeAngle = in_vLobeAngle; } void trpgLightAttr::SetLobeRollAngle( float64 in_lobeRollAngle ) { - data.lobeRollAngle = in_lobeRollAngle; + data.lobeRollAngle = in_lobeRollAngle; } void trpgLightAttr::SetLobeFalloff( float64 in_lobeFalloff ) { - data.lobeFalloff = in_lobeFalloff; + data.lobeFalloff = in_lobeFalloff; } void trpgLightAttr::SetAmbient( float64 in_ambientIntensity ) { - data.ambientIntensity = in_ambientIntensity; + data.ambientIntensity = in_ambientIntensity; } void trpgLightAttr::SetQuality( trpgLightAttr::LightQuality in_quality ) { - data.quality = in_quality; + data.quality = in_quality; } void trpgLightAttr::SetRascalSignificance( float64 in_rascalSignificance ) { - data.rascalSignificance = in_rascalSignificance; + data.rascalSignificance = in_rascalSignificance; } void trpgLightAttr::SetRandomIntensity( trpgLightAttr::LightQuality in_randomIntensity ) { - data.randomIntensity = in_randomIntensity; + data.randomIntensity = in_randomIntensity; } void trpgLightAttr::SetCalligraphicAttr( trpgLightAttr::CalligraphicAttr& in_calligraphicAttr ) { - data.calligraphicAttr = in_calligraphicAttr; + data.calligraphicAttr = in_calligraphicAttr; } void trpgLightAttr::SetCalligraphicDrawOrder( int32 in_drawOrder ) { - data.calligraphicAttr.drawOrder = in_drawOrder; + data.calligraphicAttr.drawOrder = in_drawOrder; } void trpgLightAttr::SetCalligraphicMinDefocus( float64 in_minDefocus ) { - data.calligraphicAttr.minDefocus = in_minDefocus; + data.calligraphicAttr.minDefocus = in_minDefocus; } void trpgLightAttr::SetCalligraphicMaxDefocus( float64 in_maxDefocus ) { - data.calligraphicAttr.maxDefocus = in_maxDefocus; + data.calligraphicAttr.maxDefocus = in_maxDefocus; } void trpgLightAttr::SetPerformerAttr( trpgLightAttr::PerformerAttr& in_performerAttr ) { - data.performerAttr = in_performerAttr; + data.performerAttr = in_performerAttr; } void trpgLightAttr::SetPerformerFlags( int32 in_flags ) { - data.performerAttr.flags = in_flags & trpgLightAttr::trpg_PerformerMask; - data.flags |= data.performerAttr.flags; + data.performerAttr.flags = in_flags & trpgLightAttr::trpg_PerformerMask; + data.flags |= data.performerAttr.flags; } void trpgLightAttr::SetPerformerMinPixelSize( float64 in_minPxSize ) { - data.performerAttr.minPixelSize = in_minPxSize; + data.performerAttr.minPixelSize = in_minPxSize; } void trpgLightAttr::SetPerformerMaxPixelSize( float64 in_maxPxSize ) { - data.performerAttr.maxPixelSize = in_maxPxSize; + data.performerAttr.maxPixelSize = in_maxPxSize; } void trpgLightAttr::SetPerformerActualSize( float64 in_actualSize ) { - data.performerAttr.actualSize = in_actualSize; + data.performerAttr.actualSize = in_actualSize; } void trpgLightAttr::SetPerformerTpPixelSize( float64 in_tpPixelSize ) { - data.performerAttr.transparentPixelSize = in_tpPixelSize; + data.performerAttr.transparentPixelSize = in_tpPixelSize; } void trpgLightAttr::SetPerformerTpFalloffExp( float64 in_tpFalloffExp ) { - data.performerAttr.transparentFallofExp = in_tpFalloffExp; + data.performerAttr.transparentFallofExp = in_tpFalloffExp; } void trpgLightAttr::SetPerformerTpScale( float64 in_tpScale ) { - data.performerAttr.transparentScale = in_tpScale; + data.performerAttr.transparentScale = in_tpScale; } void trpgLightAttr::SetPerformerTpClamp( float64 in_tpClamp ) { - data.performerAttr.transparentClamp = in_tpClamp; + data.performerAttr.transparentClamp = in_tpClamp; } void trpgLightAttr::SetPerformerFogScale( float64 in_fogScale ) { - data.performerAttr.fogScale = in_fogScale; + data.performerAttr.fogScale = in_fogScale; } void trpgLightAttr::SetAnimationAttr( trpgLightAttr::AnimationAttr& in_animationAttr ) { - data.animationAttr = in_animationAttr; + data.animationAttr = in_animationAttr; } void trpgLightAttr::SetAnimationPeriod( float64 in_period ) { - data.animationAttr.period = in_period; + data.animationAttr.period = in_period; } void trpgLightAttr::SetAnimationPhaseDelay( float64 in_phaseDelay ) { - data.animationAttr.phaseDelay = in_phaseDelay; + data.animationAttr.phaseDelay = in_phaseDelay; } void trpgLightAttr::SetAnimationTimeOn( float64 in_timeOn ) { - data.animationAttr.timeOn = in_timeOn; + data.animationAttr.timeOn = in_timeOn; } void trpgLightAttr::SetAnimationVector( trpg3dPoint in_vector ) { - data.animationAttr.vector = in_vector; + data.animationAttr.vector = in_vector; } void trpgLightAttr::SetAnimationFlags( int32 flags ) { - data.animationAttr.flags = flags & trpgLightAttr::trpg_AnimationMask; - data.flags |= data.animationAttr.flags; + data.animationAttr.flags = flags & trpgLightAttr::trpg_AnimationMask; + data.flags |= data.animationAttr.flags; } void trpgLightAttr::SetComment(const char *inStr) { - if (!inStr) - return; + if (!inStr) + return; - if (data.commentStr) - delete [] data.commentStr; - data.commentStr = new char[strlen(inStr)+1]; - strcpy(data.commentStr,inStr); + if (data.commentStr) + delete [] data.commentStr; + data.commentStr = new char[strlen(inStr)+1]; + strcpy(data.commentStr,inStr); } // Getters void trpgLightAttr::GetType( trpgLightAttr::LightType& out_type ) { - out_type = data.type; + out_type = data.type; } void trpgLightAttr::GetDirectionality( trpgLightAttr::LightDirectionality& out_directionality ) { - out_directionality = data.directionality; + out_directionality = data.directionality; } void trpgLightAttr::GetFrontColor( trpgColor& out_frontColor ) { - out_frontColor = data.frontColor; + out_frontColor = data.frontColor; } void trpgLightAttr::GetFrontIntensity( float64& out_frontIntensity ) { - out_frontIntensity = data.frontIntensity; + out_frontIntensity = data.frontIntensity; } void trpgLightAttr::GetBackColor( trpgColor& out_backColor ) { - out_backColor = data.backColor; + out_backColor = data.backColor; } void trpgLightAttr::GetBackIntensity( float64& out_backIntensity ) { - out_backIntensity = data.backIntensity; + out_backIntensity = data.backIntensity; } void trpgLightAttr::GetNormal( trpg3dPoint& out_normal ) { - out_normal = data.normal; + out_normal = data.normal; } void trpgLightAttr::GetSMC( int32& out_smc ) { - out_smc = data.smc; + out_smc = data.smc; } void trpgLightAttr::GetFID( int32& out_fid ) { - out_fid = data.fid; + out_fid = data.fid; } void trpgLightAttr::GetFlags( int32& out_flags ) { - out_flags = data.flags; + out_flags = data.flags; } void trpgLightAttr::GetHLobeAngle( float64& out_hLobeAngle ) { - out_hLobeAngle = data.horizontalLobeAngle; + out_hLobeAngle = data.horizontalLobeAngle; } void trpgLightAttr::GetVLobeAngle( float64& out_vLobeAngle ) { - out_vLobeAngle = data.verticalLobeAngle; + out_vLobeAngle = data.verticalLobeAngle; } void trpgLightAttr::GetLobeRollAngle( float64& out_lobeRollAngle ) { - out_lobeRollAngle = data.lobeRollAngle; + out_lobeRollAngle = data.lobeRollAngle; } void trpgLightAttr::GetLobeFalloff( float64& out_lobeFalloff ) { - out_lobeFalloff = data.lobeFalloff; + out_lobeFalloff = data.lobeFalloff; } void trpgLightAttr::GetAmbient( float64& out_ambientIntensity ) { - out_ambientIntensity = data.ambientIntensity; + out_ambientIntensity = data.ambientIntensity; } void trpgLightAttr::GetQuality( trpgLightAttr::LightQuality& out_quality ) { - out_quality = data.quality; + out_quality = data.quality; } void trpgLightAttr::GetRascalSignificance( float64& out_rascalSignificance ) { - out_rascalSignificance = data.rascalSignificance; + out_rascalSignificance = data.rascalSignificance; } void trpgLightAttr::GetRandomIntensity( trpgLightAttr::LightQuality& out_randomIntensity ) { - out_randomIntensity = data.randomIntensity; + out_randomIntensity = data.randomIntensity; } void trpgLightAttr::GetCalligraphicAttr( trpgLightAttr::CalligraphicAttr& out_calligraphicAttr ) { - out_calligraphicAttr = data.calligraphicAttr; + out_calligraphicAttr = data.calligraphicAttr; } void trpgLightAttr::GetCalligraphicDrawOrder( int32& out_drawOrder ) { - out_drawOrder = data.calligraphicAttr.drawOrder; + out_drawOrder = data.calligraphicAttr.drawOrder; } void trpgLightAttr::GetCalligraphicMinDefocus( float64& out_minDefocus ) { - out_minDefocus = data.calligraphicAttr.minDefocus; + out_minDefocus = data.calligraphicAttr.minDefocus; } void trpgLightAttr::GetCalligraphicMaxDefocus( float64& out_maxDefocus ) { - out_maxDefocus = data.calligraphicAttr.maxDefocus; + out_maxDefocus = data.calligraphicAttr.maxDefocus; } void trpgLightAttr::GetPerformerAttr( trpgLightAttr::PerformerAttr& out_performerAttr ) { - out_performerAttr = data.performerAttr; + out_performerAttr = data.performerAttr; } void trpgLightAttr::GetPerformerFlags( int32& out_flags ) { - out_flags = data.performerAttr.flags; + out_flags = data.performerAttr.flags; } void trpgLightAttr::GetPerformerMinPixelSize( float64& out_minPxSize ) { - out_minPxSize = data.performerAttr.minPixelSize; + out_minPxSize = data.performerAttr.minPixelSize; } void trpgLightAttr::GetPerformerMaxPixelSize( float64& out_maxPxSize ) { - out_maxPxSize = data.performerAttr.maxPixelSize; + out_maxPxSize = data.performerAttr.maxPixelSize; } void trpgLightAttr::GetPerformerActualSize( float64& out_actualSize ) { - out_actualSize = data.performerAttr.actualSize; + out_actualSize = data.performerAttr.actualSize; } void trpgLightAttr::GetPerformerTpPixelSize( float64& out_tpPixelSize ) { - out_tpPixelSize = data.performerAttr.transparentPixelSize; + out_tpPixelSize = data.performerAttr.transparentPixelSize; } void trpgLightAttr::GetPerformerTpFalloffExp( float64& out_tpFalloffExp ) { - out_tpFalloffExp = data.performerAttr.transparentFallofExp; + out_tpFalloffExp = data.performerAttr.transparentFallofExp; } void trpgLightAttr::GetPerformerTpScale( float64& out_tpScale ) { - out_tpScale = data.performerAttr.transparentScale; + out_tpScale = data.performerAttr.transparentScale; } void trpgLightAttr::GetPerformerTpClamp( float64& out_tpClamp ) { - out_tpClamp = data.performerAttr.transparentClamp; + out_tpClamp = data.performerAttr.transparentClamp; } void trpgLightAttr::GetPerformerFogScale( float64& out_fogScale ) { - out_fogScale = data.performerAttr.fogScale; + out_fogScale = data.performerAttr.fogScale; } void trpgLightAttr::GetAnimationAttr( trpgLightAttr::AnimationAttr& out_animationAttr ) { - out_animationAttr = data.animationAttr; + out_animationAttr = data.animationAttr; } void trpgLightAttr::GetAnimationPeriod( float64& out_period ) { - out_period = data.animationAttr.period; + out_period = data.animationAttr.period; } void trpgLightAttr::GetAnimationPhaseDelay( float64& out_phaseDelay ) { - out_phaseDelay = data.animationAttr.phaseDelay; + out_phaseDelay = data.animationAttr.phaseDelay; } void trpgLightAttr::GetAnimationTimeOn( float64& out_timeOn ) { - out_timeOn = data.animationAttr.timeOn; + out_timeOn = data.animationAttr.timeOn; } void trpgLightAttr::GetAnimationVector( trpg3dPoint& out_vector ) { - out_vector = data.animationAttr.vector; + out_vector = data.animationAttr.vector; } void trpgLightAttr::GetAnimationFlags( int32& flags ) { - flags = data.animationAttr.flags; + flags = data.animationAttr.flags; } const char *trpgLightAttr::GetComment() { - return data.commentStr; + return data.commentStr; } // Writes this class to a write buffer bool trpgLightAttr::Write(trpgWriteBuffer &buf) { - buf.Begin(TRPGLIGHTATTR); + buf.Begin(TRPGLIGHTATTR); - buf.Begin(TRPGLIGHTATTR_BASIC); - buf.Add((int)data.type); - buf.Add((int)data.directionality); - buf.Add(data.frontColor); - buf.Add(data.frontIntensity); - buf.Add(data.backColor); - buf.Add(data.backIntensity); - buf.Add(data.normal); - buf.Add(data.smc); - buf.Add(data.fid); - buf.Add(data.flags); - buf.Add(data.horizontalLobeAngle); - buf.Add(data.verticalLobeAngle); - buf.Add(data.lobeRollAngle); - buf.Add(data.lobeFalloff); - buf.Add(data.ambientIntensity); - buf.Add((int)data.quality); - buf.Add((int)data.randomIntensity); - buf.End(); + buf.Begin(TRPGLIGHTATTR_BASIC); + buf.Add((int)data.type); + buf.Add((int)data.directionality); + buf.Add(data.frontColor); + buf.Add(data.frontIntensity); + buf.Add(data.backColor); + buf.Add(data.backIntensity); + buf.Add(data.normal); + buf.Add(data.smc); + buf.Add(data.fid); + buf.Add(data.flags); + buf.Add(data.horizontalLobeAngle); + buf.Add(data.verticalLobeAngle); + buf.Add(data.lobeRollAngle); + buf.Add(data.lobeFalloff); + buf.Add(data.ambientIntensity); + buf.Add((int)data.quality); + buf.Add((int)data.randomIntensity); + buf.End(); - buf.Begin(TRPGLIGHTATTR_RASCAL); - buf.Add(data.rascalSignificance); - buf.End(); + buf.Begin(TRPGLIGHTATTR_RASCAL); + buf.Add(data.rascalSignificance); + buf.End(); - buf.Begin(TRPGLIGHTATTR_CALLIGRAPHIC); - buf.Add(data.calligraphicAttr.drawOrder); - buf.Add(data.calligraphicAttr.minDefocus); - buf.Add(data.calligraphicAttr.maxDefocus); - buf.End(); + buf.Begin(TRPGLIGHTATTR_CALLIGRAPHIC); + buf.Add(data.calligraphicAttr.drawOrder); + buf.Add(data.calligraphicAttr.minDefocus); + buf.Add(data.calligraphicAttr.maxDefocus); + buf.End(); - buf.Begin(TRPGLIGHTATTR_PERFORMER); - buf.Add(data.performerAttr.actualSize); - buf.Add(data.performerAttr.fogScale); - buf.Add(data.performerAttr.minPixelSize); - buf.Add(data.performerAttr.maxPixelSize); - buf.Add(data.performerAttr.transparentClamp); - buf.Add(data.performerAttr.transparentFallofExp); - buf.Add(data.performerAttr.transparentPixelSize); - buf.Add(data.performerAttr.transparentScale); - buf.End(); + buf.Begin(TRPGLIGHTATTR_PERFORMER); + buf.Add(data.performerAttr.actualSize); + buf.Add(data.performerAttr.fogScale); + buf.Add(data.performerAttr.minPixelSize); + buf.Add(data.performerAttr.maxPixelSize); + buf.Add(data.performerAttr.transparentClamp); + buf.Add(data.performerAttr.transparentFallofExp); + buf.Add(data.performerAttr.transparentPixelSize); + buf.Add(data.performerAttr.transparentScale); + buf.End(); - buf.Begin(TRPGLIGHTATTR_ANIMATION); - buf.Add(data.animationAttr.period); - buf.Add(data.animationAttr.phaseDelay); - buf.Add(data.animationAttr.timeOn); - buf.Add(data.animationAttr.vector); - buf.End(); + buf.Begin(TRPGLIGHTATTR_ANIMATION); + buf.Add(data.animationAttr.period); + buf.Add(data.animationAttr.phaseDelay); + buf.Add(data.animationAttr.timeOn); + buf.Add(data.animationAttr.vector); + buf.End(); - if (data.commentStr) { - buf.Begin(TRPGLIGHTATTR_COMMENT); - buf.Add(data.commentStr); - buf.End(); - } + if (data.commentStr) { + buf.Begin(TRPGLIGHTATTR_COMMENT); + buf.Add(data.commentStr); + buf.End(); + } - buf.End(); + if(writeHandle) { + buf.Begin(TRPGLIGHTATTR_HANDLE); + buf.Add((int)handle); + buf.End(); + } + buf.End(); - return true; + return true; } /* LightAttr CB - Used to parse tokens for a light attribute. - */ + Used to parse tokens for a light attribute. + */ class lightAttrCB : public trpgr_Callback { public: - void * Parse(trpgToken,trpgReadBuffer &); - trpgLightAttr *lightAttr; + void * Parse(trpgToken,trpgReadBuffer &); + trpgLightAttr *lightAttr; }; void * lightAttrCB::Parse(trpgToken tok,trpgReadBuffer &buf) { - int type_data; - int directionality_data; - trpgColor color_data;; - float64 float64_data; - trpg3dPoint point_data;; - int32 int32_data; - int quality_data; - char commentStr[1024]; + int type_data; + int directionality_data; + trpgColor color_data;; + float64 float64_data; + trpg3dPoint point_data;; + int32 int32_data; + int quality_data; + char commentStr[1024]; - try { - switch (tok) { - case TRPGLIGHTATTR_BASIC: - buf.Get(type_data); - lightAttr->SetType((trpgLightAttr::LightType)type_data); - buf.Get(directionality_data); - lightAttr->SetDirectionality((trpgLightAttr::LightDirectionality)directionality_data); - buf.Get(color_data); - lightAttr->SetFrontColor(color_data); - buf.Get(float64_data); - lightAttr->SetFrontIntensity(float64_data); - buf.Get(color_data); - lightAttr->SetBackColor(color_data); - buf.Get(float64_data); - lightAttr->SetBackIntensity(float64_data); - buf.Get(point_data); - lightAttr->SetNormal(point_data); - buf.Get(int32_data); - lightAttr->SetSMC(int32_data); - buf.Get(int32_data); - lightAttr->SetFID(int32_data); - buf.Get(int32_data); - lightAttr->SetFlags(int32_data); - lightAttr->SetPerformerFlags(int32_data); - lightAttr->SetAnimationFlags(int32_data); - buf.Get(float64_data); - lightAttr->SetHLobeAngle(float64_data); - buf.Get(float64_data); - lightAttr->SetVLobeAngle(float64_data); - buf.Get(float64_data); - lightAttr->SetLobeRollAngle(float64_data); - buf.Get(float64_data); - lightAttr->SetLobeFalloff(float64_data); - buf.Get(float64_data); - lightAttr->SetAmbient(float64_data); - buf.Get(quality_data); - lightAttr->SetQuality((trpgLightAttr::LightQuality)quality_data); - buf.Get(quality_data); - lightAttr->SetRandomIntensity((trpgLightAttr::LightQuality)quality_data); - break; - case TRPGLIGHTATTR_RASCAL: - buf.Get(float64_data); - lightAttr->SetRascalSignificance(float64_data); - break; - case TRPGLIGHTATTR_PERFORMER: - buf.Get(float64_data); - lightAttr->SetPerformerActualSize(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerFogScale(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerMinPixelSize(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerMaxPixelSize(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerTpClamp(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerTpFalloffExp(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerTpPixelSize(float64_data); - buf.Get(float64_data); - lightAttr->SetPerformerTpScale(float64_data); - break; - case TRPGLIGHTATTR_CALLIGRAPHIC: - buf.Get(int32_data); - lightAttr->SetCalligraphicDrawOrder(int32_data); - buf.Get(float64_data); - lightAttr->SetCalligraphicMinDefocus(float64_data); - buf.Get(float64_data); - lightAttr->SetCalligraphicMaxDefocus(float64_data); - break; - case TRPGLIGHTATTR_ANIMATION: - buf.Get(float64_data); - lightAttr->SetAnimationPeriod(float64_data); - buf.Get(float64_data); - lightAttr->SetAnimationPhaseDelay(float64_data); - buf.Get(float64_data); - lightAttr->SetAnimationTimeOn(float64_data); - buf.Get(point_data); - lightAttr->SetAnimationVector(point_data); - break; - case TRPGLIGHTATTR_COMMENT: - buf.Get(commentStr,1024); - lightAttr->SetComment(commentStr); - break; - default: - break; - } - } - catch (...) { - return NULL; - } + try { + switch (tok) { + case TRPGLIGHTATTR_BASIC: + buf.Get(type_data); + lightAttr->SetType((trpgLightAttr::LightType)type_data); + buf.Get(directionality_data); + lightAttr->SetDirectionality((trpgLightAttr::LightDirectionality)directionality_data); + buf.Get(color_data); + lightAttr->SetFrontColor(color_data); + buf.Get(float64_data); + lightAttr->SetFrontIntensity(float64_data); + buf.Get(color_data); + lightAttr->SetBackColor(color_data); + buf.Get(float64_data); + lightAttr->SetBackIntensity(float64_data); + buf.Get(point_data); + lightAttr->SetNormal(point_data); + buf.Get(int32_data); + lightAttr->SetSMC(int32_data); + buf.Get(int32_data); + lightAttr->SetFID(int32_data); + buf.Get(int32_data); + lightAttr->SetFlags(int32_data); + lightAttr->SetPerformerFlags(int32_data); + lightAttr->SetAnimationFlags(int32_data); + buf.Get(float64_data); + lightAttr->SetHLobeAngle(float64_data); + buf.Get(float64_data); + lightAttr->SetVLobeAngle(float64_data); + buf.Get(float64_data); + lightAttr->SetLobeRollAngle(float64_data); + buf.Get(float64_data); + lightAttr->SetLobeFalloff(float64_data); + buf.Get(float64_data); + lightAttr->SetAmbient(float64_data); + buf.Get(quality_data); + lightAttr->SetQuality((trpgLightAttr::LightQuality)quality_data); + buf.Get(quality_data); + lightAttr->SetRandomIntensity((trpgLightAttr::LightQuality)quality_data); + break; + case TRPGLIGHTATTR_RASCAL: + buf.Get(float64_data); + lightAttr->SetRascalSignificance(float64_data); + break; + case TRPGLIGHTATTR_PERFORMER: + buf.Get(float64_data); + lightAttr->SetPerformerActualSize(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerFogScale(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerMinPixelSize(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerMaxPixelSize(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerTpClamp(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerTpFalloffExp(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerTpPixelSize(float64_data); + buf.Get(float64_data); + lightAttr->SetPerformerTpScale(float64_data); + break; + case TRPGLIGHTATTR_CALLIGRAPHIC: + buf.Get(int32_data); + lightAttr->SetCalligraphicDrawOrder(int32_data); + buf.Get(float64_data); + lightAttr->SetCalligraphicMinDefocus(float64_data); + buf.Get(float64_data); + lightAttr->SetCalligraphicMaxDefocus(float64_data); + break; + case TRPGLIGHTATTR_ANIMATION: + buf.Get(float64_data); + lightAttr->SetAnimationPeriod(float64_data); + buf.Get(float64_data); + lightAttr->SetAnimationPhaseDelay(float64_data); + buf.Get(float64_data); + lightAttr->SetAnimationTimeOn(float64_data); + buf.Get(point_data); + lightAttr->SetAnimationVector(point_data); + break; + case TRPGLIGHTATTR_COMMENT: + buf.Get(commentStr,1024); + lightAttr->SetComment(commentStr); + break; + case TRPGLIGHTATTR_HANDLE: + int hdl; + buf.Get(hdl); + lightAttr->SetHandle(hdl); + break; + default: + break; + } + } + catch (...) { + return NULL; + } - return lightAttr; + return lightAttr; } // Reads this class from a read buffer bool trpgLightAttr::Read(trpgReadBuffer &buf) { - Reset(); + Reset(); - trpgr_Parser parse; - lightAttrCB lightAttrCb; + trpgr_Parser parse; + lightAttrCB lightAttrCb; - // Light attribute is just a bunch of unordered tokens. - // Interface to it with a generic parser - lightAttrCb.lightAttr = this; - parse.AddCallback(TRPGLIGHTATTR_BASIC,&lightAttrCb,false); - parse.AddCallback(TRPGLIGHTATTR_PERFORMER,&lightAttrCb,false); - parse.AddCallback(TRPGLIGHTATTR_RASCAL,&lightAttrCb,false); - parse.AddCallback(TRPGLIGHTATTR_CALLIGRAPHIC,&lightAttrCb,false); - parse.AddCallback(TRPGLIGHTATTR_ANIMATION,&lightAttrCb,false); - parse.AddCallback(TRPGLIGHTATTR_COMMENT,&lightAttrCb,false); - parse.Parse(buf); + // Light attribute is just a bunch of unordered tokens. + // Interface to it with a generic parser + lightAttrCb.lightAttr = this; + parse.AddCallback(TRPGLIGHTATTR_BASIC,&lightAttrCb,false); + parse.AddCallback(TRPGLIGHTATTR_PERFORMER,&lightAttrCb,false); + parse.AddCallback(TRPGLIGHTATTR_RASCAL,&lightAttrCb,false); + parse.AddCallback(TRPGLIGHTATTR_CALLIGRAPHIC,&lightAttrCb,false); + parse.AddCallback(TRPGLIGHTATTR_ANIMATION,&lightAttrCb,false); + parse.AddCallback(TRPGLIGHTATTR_COMMENT,&lightAttrCb,false); + parse.AddCallback(TRPGLIGHTATTR_HANDLE,&lightAttrCb,false); + parse.Parse(buf); - return isValid(); + return isValid(); } bool trpgLightAttr::isValid(void) const { - return true; + return true; } trpgLightAttr& trpgLightAttr::operator = (const trpgLightAttr& in) { - data = in.data; - if (in.data.commentStr) { - data.commentStr = new char[strlen(in.data.commentStr)+1]; - strcpy(data.commentStr,in.data.commentStr); - } - return *this; + data = in.data; + if (in.data.commentStr) { + data.commentStr = new char[strlen(in.data.commentStr)+1]; + strcpy(data.commentStr,in.data.commentStr); + } + handle = in.handle; + writeHandle = in.writeHandle; + return *this; } bool trpgLightAttr::operator == (const trpgLightAttr& in) { - // this doesn't work, so do it a hard way - // return memcmp( &data,&in.data,sizeof(data) ) == 0; + // this doesn't work, so do it a hard way + // return memcmp( &data,&in.data,sizeof(data) ) == 0; - if ( data.type != in.data.type ) - return false; - if ( data.directionality != in.data.directionality ) - return false; - if ( data.frontColor != in.data.frontColor ) - return false; - if ( data.frontIntensity != in.data.frontIntensity ) - return false; - if ( data.backColor != in.data.backColor ) - return false; - if ( data.backIntensity != in.data.backIntensity ) - return false; - if ( data.normal != in.data.normal ) - return false; - if ( data.smc != in.data.smc ) - return false; - if ( data.fid != in.data.fid ) - return false; - if ( data.flags != in.data.flags ) - return false; - if ( data.horizontalLobeAngle != in.data.horizontalLobeAngle ) - return false; - if ( data.verticalLobeAngle != in.data.verticalLobeAngle ) - return false; - if ( data.lobeRollAngle != in.data.lobeRollAngle ) - return false; - if ( data.lobeFalloff != in.data.lobeFalloff ) - return false; - if ( data.ambientIntensity != in.data.ambientIntensity ) - return false; - if ( data.quality != in.data.quality ) - return false; - if ( data.randomIntensity != in.data.randomIntensity ) - return false; - if ( data.rascalSignificance != in.data.rascalSignificance ) - return false; - if ( data.calligraphicAttr.drawOrder != in.data.calligraphicAttr.drawOrder ) - return false; - if ( data.calligraphicAttr.minDefocus != in.data.calligraphicAttr.minDefocus ) - return false; - if ( data.calligraphicAttr.maxDefocus != in.data.calligraphicAttr.maxDefocus ) - return false; - if ( data.performerAttr.flags != in.data.performerAttr.flags ) - return false; - if ( data.performerAttr.minPixelSize != in.data.performerAttr.minPixelSize ) - return false; - if ( data.performerAttr.maxPixelSize != in.data.performerAttr.maxPixelSize ) - return false; - if ( data.performerAttr.actualSize != in.data.performerAttr.actualSize ) - return false; - if ( data.performerAttr.transparentPixelSize != in.data.performerAttr.transparentPixelSize ) - return false; - if ( data.performerAttr.transparentFallofExp != in.data.performerAttr.transparentFallofExp ) - return false; - if ( data.performerAttr.transparentScale != in.data.performerAttr.transparentScale ) - return false; - if ( data.performerAttr.transparentClamp != in.data.performerAttr.transparentClamp ) - return false; - if ( data.performerAttr.fogScale != in.data.performerAttr.fogScale ) - return false; - if ( data.animationAttr.period != in.data.animationAttr.period ) - return false; - if ( data.animationAttr.phaseDelay != in.data.animationAttr.phaseDelay ) - return false; - if ( data.animationAttr.timeOn != in.data.animationAttr.timeOn ) - return false; - if ( data.animationAttr.vector != in.data.animationAttr.vector ) - return false; - if ( data.animationAttr.flags != in.data.animationAttr.flags ) - return false; - if ( (data.commentStr && !in.data.commentStr) || - (!data.commentStr && in.data.commentStr)) - return false; - if (data.commentStr && in.data.commentStr && strcmp(data.commentStr,in.data.commentStr)) - return false; - - return true; + if ( data.type != in.data.type ) + return false; + if ( data.directionality != in.data.directionality ) + return false; + if ( data.frontColor != in.data.frontColor ) + return false; + if ( data.frontIntensity != in.data.frontIntensity ) + return false; + if ( data.backColor != in.data.backColor ) + return false; + if ( data.backIntensity != in.data.backIntensity ) + return false; + if ( data.normal != in.data.normal ) + return false; + if ( data.smc != in.data.smc ) + return false; + if ( data.fid != in.data.fid ) + return false; + if ( data.flags != in.data.flags ) + return false; + if ( data.horizontalLobeAngle != in.data.horizontalLobeAngle ) + return false; + if ( data.verticalLobeAngle != in.data.verticalLobeAngle ) + return false; + if ( data.lobeRollAngle != in.data.lobeRollAngle ) + return false; + if ( data.lobeFalloff != in.data.lobeFalloff ) + return false; + if ( data.ambientIntensity != in.data.ambientIntensity ) + return false; + if ( data.quality != in.data.quality ) + return false; + if ( data.randomIntensity != in.data.randomIntensity ) + return false; + if ( data.rascalSignificance != in.data.rascalSignificance ) + return false; + if ( data.calligraphicAttr.drawOrder != in.data.calligraphicAttr.drawOrder ) + return false; + if ( data.calligraphicAttr.minDefocus != in.data.calligraphicAttr.minDefocus ) + return false; + if ( data.calligraphicAttr.maxDefocus != in.data.calligraphicAttr.maxDefocus ) + return false; + if ( data.performerAttr.flags != in.data.performerAttr.flags ) + return false; + if ( data.performerAttr.minPixelSize != in.data.performerAttr.minPixelSize ) + return false; + if ( data.performerAttr.maxPixelSize != in.data.performerAttr.maxPixelSize ) + return false; + if ( data.performerAttr.actualSize != in.data.performerAttr.actualSize ) + return false; + if ( data.performerAttr.transparentPixelSize != in.data.performerAttr.transparentPixelSize ) + return false; + if ( data.performerAttr.transparentFallofExp != in.data.performerAttr.transparentFallofExp ) + return false; + if ( data.performerAttr.transparentScale != in.data.performerAttr.transparentScale ) + return false; + if ( data.performerAttr.transparentClamp != in.data.performerAttr.transparentClamp ) + return false; + if ( data.performerAttr.fogScale != in.data.performerAttr.fogScale ) + return false; + if ( data.animationAttr.period != in.data.animationAttr.period ) + return false; + if ( data.animationAttr.phaseDelay != in.data.animationAttr.phaseDelay ) + return false; + if ( data.animationAttr.timeOn != in.data.animationAttr.timeOn ) + return false; + if ( data.animationAttr.vector != in.data.animationAttr.vector ) + return false; + if ( data.animationAttr.flags != in.data.animationAttr.flags ) + return false; + if ( (data.commentStr && !in.data.commentStr) || + (!data.commentStr && in.data.commentStr)) + return false; + if (data.commentStr && in.data.commentStr && strcmp(data.commentStr,in.data.commentStr)) + return false; + if (handle != in.handle) + return false; + if (writeHandle != in.writeHandle) + return false; + return true; } bool trpgLightAttr::operator != (const trpgLightAttr& in) { - return !operator==(in); + return !operator==(in); } void trpgLightAttr::Reset(void) { - errMess[0] = '\0'; - data.type = trpg_Raster; - data.directionality = trpg_Omnidirectional; - data.frontColor = trpgColor(0,0,0); - data.frontIntensity = 0; - data.backColor = trpgColor(0,0,0); - data.backIntensity = 0; - data.normal = trpg3dPoint(0,0,1); - data.smc = 0; - data.fid = 0; - data.flags = 0; - data.horizontalLobeAngle = 0; - data.verticalLobeAngle = 0; - data.lobeRollAngle = 0; - data.lobeFalloff = 0; - data.ambientIntensity = 0; - data.quality = trpg_Low; - data.randomIntensity = trpg_Low; - data.rascalSignificance = 0; - data.calligraphicAttr.drawOrder = 0; - data.calligraphicAttr.minDefocus = 0; - data.calligraphicAttr.maxDefocus = 0; - data.performerAttr.flags = 0; - data.performerAttr.minPixelSize = 0; - data.performerAttr.maxPixelSize = 0; - data.performerAttr.actualSize = 0; - data.performerAttr.transparentPixelSize = 0; - data.performerAttr.transparentFallofExp = 0; - data.performerAttr.transparentScale = 0; - data.performerAttr.transparentClamp = 0; - data.performerAttr.fogScale = 0; - data.animationAttr.period = 0; - data.animationAttr.phaseDelay = 0; - data.animationAttr.timeOn = 0; - data.animationAttr.vector = trpg3dPoint(0,0,1); - data.animationAttr.flags = 0; - if (data.commentStr) - delete [] data.commentStr; - data.commentStr = NULL; + errMess[0] = '\0'; + data.type = trpg_Raster; + data.directionality = trpg_Omnidirectional; + data.frontColor = trpgColor(0,0,0); + data.frontIntensity = 0; + data.backColor = trpgColor(0,0,0); + data.backIntensity = 0; + data.normal = trpg3dPoint(0,0,1); + data.smc = 0; + data.fid = 0; + data.flags = 0; + data.horizontalLobeAngle = 0; + data.verticalLobeAngle = 0; + data.lobeRollAngle = 0; + data.lobeFalloff = 0; + data.ambientIntensity = 0; + data.quality = trpg_Low; + data.randomIntensity = trpg_Low; + data.rascalSignificance = 0; + data.calligraphicAttr.drawOrder = 0; + data.calligraphicAttr.minDefocus = 0; + data.calligraphicAttr.maxDefocus = 0; + data.performerAttr.flags = 0; + data.performerAttr.minPixelSize = 0; + data.performerAttr.maxPixelSize = 0; + data.performerAttr.actualSize = 0; + data.performerAttr.transparentPixelSize = 0; + data.performerAttr.transparentFallofExp = 0; + data.performerAttr.transparentScale = 0; + data.performerAttr.transparentClamp = 0; + data.performerAttr.fogScale = 0; + data.animationAttr.period = 0; + data.animationAttr.phaseDelay = 0; + data.animationAttr.timeOn = 0; + data.animationAttr.vector = trpg3dPoint(0,0,1); + data.animationAttr.flags = 0; + if (data.commentStr) + delete [] data.commentStr; + data.commentStr = NULL; + handle = -1; + writeHandle = false; } /************** - Light + Light */ trpgLight::trpgLight(void) { - index = -1; + index = -1; } trpgLight::trpgLight(const trpgLight &in): trpgReadWriteable(in) { - operator=(in); + operator=(in); } trpgLight::~trpgLight(void) { - Reset(); + Reset(); } // Set the index pointing into the Light Table void trpgLight::SetAttrIndex(int ix) { - index = ix; + index = ix; } // Add a new location this light is located at void trpgLight::AddVertex(trpg3dPoint pt) { - lightPoints.push_back(pt); + lightPoints.push_back(pt); } // Returns the number of locations, this light is located at void trpgLight::GetNumVertices(uint32 &nvertices) const { - nvertices = lightPoints.size(); + nvertices = lightPoints.size(); } // Returns the location at a given index bool trpgLight::GetVertex(uint32 ix, trpg3dPoint &pt) const { - if (ix < lightPoints.size() ) { - pt = lightPoints[ix]; - return true; - } - else - return false; + if (ix < lightPoints.size() ) { + pt = lightPoints[ix]; + return true; + } + else + return false; } bool trpgLight::GetVertices(trpg3dPoint *pts) const { - if (!isValid()) return false; + unsigned int i; - if (lightPoints.size() != 0) - for (unsigned int i=0;isecond.isValid()) + { + if(itr->second.getErrMess()) + strcpy(errMess, itr->second.getErrMess()); + return false; + } + } - return true; + return true; } // Set functions int trpgLightTable::AddLightAttr(const trpgLightAttr& inLight) { - lightList.push_back(inLight); - return lightList.size()-1; + int handle = inLight.GetHandle(); + if(handle==-1) { + handle = lightMap.size(); + } + lightMap[handle] = inLight; + return handle; } int trpgLightTable::FindAddLightAttr(const trpgLightAttr& inLight) { - for (unsigned int i=0;isecond==inLight) + return itr->first; + } + return AddLightAttr(inLight); } // Copy operator trpgLightTable &trpgLightTable::operator = (const trpgLightTable &in) { - Reset(); - for (unsigned int i=0;isecond); + } + //for (int i=0;isecond.Write(buf); + //for (unsigned int i=0;i= (int)lightList.size()) return NULL; - return &lightList[id]; + if (id < 0) return NULL; + + LightMapType::const_iterator itr = lightMap.find(id); + if(itr == lightMap.end()) { + return NULL; + } + + return &itr->second; } bool trpgLightTable::Read(trpgReadBuffer &buf) { - int32 numLights; - trpgToken lightTok; - int32 len; + int32 numLights; + trpgToken lightTok; + int32 len; - try { - buf.Get(numLights); - lightList.resize(numLights); - for (int i=0;i diff --git a/src/osgPlugins/txp/trpage_managers.cpp b/src/osgPlugins/txp/trpage_managers.cpp index 8f2c2d9a2..e23e52c66 100644 --- a/src/osgPlugins/txp/trpage_managers.cpp +++ b/src/osgPlugins/txp/trpage_managers.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -24,14 +25,14 @@ #include /* Managed Tile class. - Check the header file for details. + Check the header file for details. */ trpgManagedTile::trpgManagedTile() { isLoaded = false; - x = y = -1; - lod = -1; + location.x = location.y = -1; + location.lod = -1; localData = NULL; } @@ -39,20 +40,23 @@ void trpgManagedTile::Reset() { // Null out the local material data for (unsigned int i=0;i= (int)childLocationInfo.size()) + throw std::invalid_argument( + "trpgManagedTile::GetChildLocationInfo(): index argument out of bound."); + + + return childLocationInfo[childIdx]; +} + +bool trpgManagedTile::GetChildTileLoc(int childIdx, int &x,int &y,int &lod) const +{ + if(childIdx < 0 || childIdx >= (int)childLocationInfo.size()) + throw std::invalid_argument( + "trpgManagedTile::GetChildTileLoc(): index argument out of bound."); + TileLocationInfo const& info = childLocationInfo[childIdx]; + + x = info.x; + y = info.y; + lod = info.lod; + + return true; +} + +const trpgwAppAddress& trpgManagedTile::GetChildTileAddress(int childIdx) const +{ + if(childIdx < 0 || childIdx >= (int)childLocationInfo.size()) + throw std::invalid_argument( + "trpgManagedTile::GetChildTileAddress(): index argument out of bound."); + return childLocationInfo[childIdx].addr; +} + const trpgTileHeader *trpgManagedTile::GetTileHead() { return &tileHead; @@ -103,7 +191,7 @@ const trpgLocalMaterial *trpgManagedTile::GetLocMaterial(int id) const matList = tileHead.GetLocalMaterialList(); if (id <0 || id >= (int)matList->size()) - return NULL; + return NULL; return &(*matList)[id]; } @@ -121,7 +209,7 @@ void *trpgManagedTile::GetLocalData() const bool trpgManagedTile::SetMatData(int id,void *info) { if (id < 0 || id >= (int)localMatData.size()) - return false; + return false; localMatData[id] = info; @@ -131,7 +219,7 @@ bool trpgManagedTile::SetMatData(int id,void *info) void *trpgManagedTile::GetMatData(int id) const { if (id < 0 || id >= (int)localMatData.size()) - return NULL; + return NULL; return localMatData[id]; } @@ -149,14 +237,14 @@ const std::vector *trpgManagedTile::GetGroupIDs() const void trpgManagedTile::Print(trpgPrintBuffer &buf) { char line[1024]; - sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); buf.prnLine(line); + sprintf(line,"x = %d, y = %d, lod = %d",location.x, location.y, location.lod); buf.prnLine(line); // Note: Should print the rest too, probably. } /* Page Manager LOD Page Info class. Used by the page manager to keep track of paging information for a single terrain LOD. See the header file for details. - */ +*/ trpgPageManager::LodPageInfo::LodPageInfo() { @@ -173,27 +261,27 @@ trpgPageManager::LodPageInfo::~LodPageInfo() void trpgPageManager::LodPageInfo::Clean() { // Clean up managed tile structures - unsigned int i; + unsigned int i; for (i=0;iGetTileTable(); + // Need some size and shape info about our terrain LOD const trpgHeader *head = archive->GetHeader(); head->GetTileSize(lod,cellSize); @@ -209,22 +299,36 @@ bool trpgPageManager::LodPageInfo::Init(trpgr_Archive *archive, int myLod, doubl head->GetLodSize(lod,lodSize); pageDist *= scale; + head->GetVersion(majorVersion, minorVersion); + + // Area of interest size (in cells) aoiSize.x = (int)(pageDist/cellSize.x); aoiSize.y = (int)(pageDist/cellSize.y); /* Make a guess as to how many tiles we might have loaded - in at any given time. Give ourselves 15% extra room. + in at any given time. Give ourselves 15% extra room. From the area of interest in cells, we can guess the max number of tiles (aka cells) we'll have loaded in at once. Note that the AOI size is only ahead, so it must be doubled. - */ + + Version 2.1 now support variable lods, it might be overkill to + allocate a free list by supposing that the tiles exist. + So only for version 2.1 an over we will use the divider to allocate less + */ maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1)); + if(majorVersion == 2 && minorVersion >= 1) + maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1)/freeListDivider); + else + maxNumTiles = (int)(1.15*(2*aoiSize.x+1)*(2*aoiSize.y+1)); + + + // Allocate 'em for (int i=0;i 0) { - activeLoad = true; - return load[0]; + activeLoad = true; + return load[0]; } return NULL; @@ -279,8 +383,8 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextLoad() void trpgPageManager::LodPageInfo::AckLoad() { if (activeLoad) { - current.push_back(load[0]); - load.pop_front(); + current.push_back(load[0]); + load.pop_front(); } activeLoad = false; } @@ -289,15 +393,15 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextUnload() { // Can only unload one tile at a time if (activeUnload) - return NULL; + return NULL; // Clear any NULLs at the beginning while (unload.size() && !unload[0]) - unload.pop_front(); + unload.pop_front(); if (unload.size() > 0) { - activeUnload = true; - return unload[0]; + activeUnload = true; + return unload[0]; } return NULL; @@ -306,10 +410,10 @@ trpgManagedTile *trpgPageManager::LodPageInfo::GetNextUnload() void trpgPageManager::LodPageInfo::AckUnload() { if (activeUnload) { - trpgManagedTile *tile = unload[0]; - tile->Reset(); - freeList.push_back(tile); - unload.pop_front(); + trpgManagedTile *tile = unload[0]; + tile->Reset(); + freeList.push_back(tile); + unload.pop_front(); } activeUnload = false; } @@ -318,11 +422,13 @@ bool trpgPageManager::LodPageInfo::isWithin(trpgManagedTile *tile,trpg2iPoint &s { int tileX,tileY,tileLod; tile->GetTileLoc(tileX,tileY,tileLod); - if (tileX >= sw.x && tileX <= ne.x && - tileY >= sw.y && tileY <= ne.y) - return true; - - return false; + if (tileX >= sw.x && + tileX <= ne.x && + tileY >= sw.y && + tileY <= ne.y) + return true; + else + return false; } bool trpgPageManager::LodPageInfo::Stop() @@ -330,21 +436,128 @@ bool trpgPageManager::LodPageInfo::Stop() // Empty the load list unsigned int i; for (i=0;i 0); } +void trpgPageManager::LodPageInfo::AddChildrenToLoadList(std::vector& parentList) +{ + if(parentList.size() == 0) + return; + + // Area coverage, in cell unit + trpg2iPoint sw,ne; + sw.x = cell.x - aoiSize.x; + sw.y = cell.y - aoiSize.y; + ne.x = cell.x + aoiSize.x; + ne.y = cell.y + aoiSize.y; + sw.x = MAX(0,sw.x); + sw.y = MAX(0,sw.y); + ne.x = MIN(lodSize.x-1,ne.x); + ne.y = MIN(lodSize.y-1,ne.y); + + int dx = ne.x - sw.x +1; + int dy = ne.y - sw.y +1; + + // Mark the one that are already there + tmpCurrent.resize(dx*dy); + std::fill(tmpCurrent.begin(), tmpCurrent.end(), false); + for (unsigned int i = 0; iGetTileLoc(tileX,tileY,tileLod); + tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true; + } + } + for (unsigned int i=0;iGetTileLoc(tileX,tileY,tileLod); + tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true; + } + } + + for(unsigned int parentIdx = 0; parentIdx < parentList.size(); ++parentIdx) { + + trpgManagedTile* parentTile = parentList[parentIdx]; + unsigned int nbChildren = parentTile->GetNbChildren(); + + for(unsigned int childIdx = 0; childIdx < nbChildren; ++childIdx) { + + const TileLocationInfo& childLoc = parentTile->GetChildLocationInfo(childIdx); + + // a sanity check: if the lod is not the same then this + // parent is not at the right place + if(childLoc.lod != lod) + break; + + // Make sure it is within + if (childLoc.x >= sw.x && + childLoc.x <= ne.x && + childLoc.y >= sw.y && + childLoc.y <= ne.y) { + + // Is it alread there ? + if(!tmpCurrent[(childLoc.y - sw.y)*dx + (childLoc.x - sw.x)]) { + + // Not there, add it + AddToLoadList(childLoc.x, childLoc.y, childLoc.addr); + } + } + } + } +} + +bool trpgPageManager::LodPageInfo::AddToLoadList(int x, int y, const trpgwAppAddress& addr) +{ + trpg2iPoint sw,ne; + + // Figure out the lower left and upper right corners + // in cell coordinates + sw.x = cell.x - aoiSize.x; + sw.y = cell.y - aoiSize.y; + ne.x = cell.x + aoiSize.x; + ne.y = cell.y + aoiSize.y; + sw.x = MAX(0,sw.x); + sw.y = MAX(0,sw.y); + ne.x = MIN(lodSize.x-1,ne.x); + ne.y = MIN(lodSize.y-1,ne.y); + + if (x >= sw.x && + x <= ne.x && + y >= sw.y && + y <= ne.y) { + + trpgManagedTile *tile = 0; + if(freeList.size() > 0){ + + tile = freeList[0]; + freeList.pop_front(); + } + else + tile = new trpgManagedTile(); + tile->SetTileLoc(x, y, lod); + tile->SetTileAddress(addr); + load.push_back(tile); + + return true; + } + else + return false; +} /* Update does the major work of figuring out what to load and - what to unload. - */ + what to unload. +*/ void trpgPageManager::LodPageInfo::Update() { @@ -354,95 +567,137 @@ void trpgPageManager::LodPageInfo::Update() // in cell coordinates sw.x = cell.x - aoiSize.x; sw.y = cell.y - aoiSize.y; ne.x = cell.x + aoiSize.x; ne.y = cell.y + aoiSize.y; - sw.x = MAX(0,sw.x); sw.y = MAX(0,sw.y); + sw.x = MAX(0,sw.x); sw.y = MAX(0,sw.y); ne.x = MIN(lodSize.x-1,ne.x); ne.y = MIN(lodSize.y-1,ne.y); /* Load list - - Some of the tiles we're supposed to load may now be - out of range. Take them off the load list. - */ + Some of the tiles we're supposed to load may now be + out of range. Take them off the load list. + */ unsigned int i; for (i=0;iGetTileLoc(tileX,tileY,tileLod); - tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true; - } + bool doUpdate = true; + if(majorVersion == 2 && minorVersion >= 1) + { + // Version 2.1, we update only lod 0 since the tile table + // will only contain lod 0. All tiles from other lod must be + // update through the trpgPageManager::AckLoad(tile info) + if(lod != 0) + doUpdate = false; } + if(doUpdate) + { + // Sort the currently loaded stuff into a spatial array + // so we can figure out what needs to be loaded in addition. + int dx,dy; + dx = ne.x - sw.x+1; dy = ne.y - sw.y+1; + tmpCurrent.resize(dx*dy); + for (i=0;iGetTileLoc(tileX,tileY,tileLod); + tmpCurrent[(tileY-sw.y)*dx + (tileX-sw.x)] = true; + } + } // Now figure out which ones are missing and add them // to the load list - for (int x=0;x 0) { - tile = freeList[0]; - freeList.pop_front(); - } else - tile = new trpgManagedTile(); - tile->SetTileLoc(x+sw.x,y+sw.y,lod); - load.push_back(tile); - } - } + for (int x=0;x 0) { + tile = freeList[0]; + freeList.pop_front(); + } else + tile = new trpgManagedTile(); + tile->SetTileLoc(x+sw.x,y+sw.y,lod); + trpgwAppAddress addr; + float32 zmin, zmax; + + if(tileTable && tileTable->GetTile(x+sw.x, y+sw.y, lod, addr, zmin, zmax)) + tile->SetTileAddress(addr); + + load.push_back(tile); + } + } + } } // That's it. All the rest is handled by the caller // iterating through the tiles to load and unload. } +// Get the list of currently loaded tiles that falls wiithin the area calculted from +// the given paging distance +void trpgPageManager::LodPageInfo::GetLoadedTileWithin(double pagingDistance, std::vector& tileList) +{ + trpg2iPoint aoi_size((int)(pagingDistance/cellSize.x) +1, + (int)(pagingDistance/cellSize.y) +1); + + // Calculate the area that we must check, in parent cell coordinate + trpg2iPoint sw, ne; + sw.x = cell.x - aoi_size.x; + sw.y = cell.y - aoi_size.y; + ne.x = cell.x + aoi_size.x; + ne.y = cell.y + aoi_size.y; + sw.x = MAX(0,sw.x); + sw.y = MAX(0,sw.y); + ne.x = MIN(lodSize.x-1,ne.x); + ne.y = MIN(lodSize.y-1,ne.y); + + tileList.clear(); + + for (unsigned i=0; i Print(buf); + if (load[i]) + load[i]->Print(buf); buf.DecreaseIndent(); sprintf(line,"Unloads: (activeUnload = %s)",(activeUnload ? "yes" : "no")); buf.prnLine(line); buf.IncreaseIndent(); for (i=0;iPrint(buf); + if (unload[i]) + unload[i]->Print(buf); buf.DecreaseIndent(); buf.prnLine("Currently loaded:"); buf.IncreaseIndent(); for (i=0;iPrint(buf); + if (current[i]) + current[i]->Print(buf); buf.DecreaseIndent(); sprintf(line,"Free list size = %d", (int)freeList.size()); buf.prnLine(line); } /* Page Manager methods - These are methods of the main trpgPageManager. Check the header - file for more detailed information. - */ + These are methods of the main trpgPageManager. Check the header + file for more detailed information. +*/ trpgPageManager::trpgPageManager() { @@ -508,12 +763,50 @@ void trpgPageManager::Init(trpgr_Archive *inArch) const trpgHeader *head = archive->GetHeader(); int numLod; head->GetNumLods(numLod); + head->GetVersion(majorVersion, minorVersion); // Reset the terrain LOD paging classes. valid = true; pageInfo.resize(numLod); for (int i=0;i 3) + pageInfo[i].Init(archive,i,scale, 4); + else + pageInfo[i].Init(archive,i,scale); + } +} + +// We might want to init only to support the tile table content. +// For Version 2.1 the tile table contain only lod 0. +// We might want to do that to use another paging scheme for +// lower lod +void trpgPageManager::Init(trpgr_Archive *inArch, int maxLod) +{ + archive = inArch; + + // We're resetting everything. In general, Init should only + // be called once, but it'll work fine if you call it more than once. + lastLoad = None; + lastTile = NULL; + lastLod = -1; + + // Need to know the number of terrain LODs + const trpgHeader *head = archive->GetHeader(); + int numLod; + head->GetNumLods(numLod); + head->GetVersion(majorVersion, minorVersion); + + if(maxLod > numLod) + maxLod = numLod; + + // Reset the terrain LOD paging classes. + valid = true; + pageInfo.resize(maxLod); + for (int i=0;i 3) + pageInfo[i].Init(archive,i,scale, 4); + else + pageInfo[i].Init(archive,i,scale); } } @@ -521,7 +814,7 @@ bool trpgPageManager::SetPageDistFactor(double inFact) { // A scaling factor less than 1 will break the archive display. if (inFact <= 1.0) - return false; + return false; scale = inFact; @@ -532,15 +825,43 @@ bool trpgPageManager::SetLocation(trpg2dPoint &pt) { // Do a basic sanity check if (!valid || (pagePt.x == pt.x && pagePt.y == pt.y)) - return false; + return false; pagePt = pt; // Call each terrain LOD and let if figure out if something // has changed. bool change = false; for (unsigned int i=0;i= 1 && change) { + + // Version 2.1 and over + // Since we don't have a tile table for lod > 0, + // we must rely on the parent to see if children + // tiles have to be loaded: + // First we get the list of parent tiles that falls + // in the area of interest of the children, + // Second we add to the load list all the parent's + // children that are no already part of the list + + for(unsigned int lodIdx = 1; lodIdx < pageInfo.size(); ++lodIdx) { + + LodPageInfo& parentInfo = pageInfo[lodIdx -1]; + LodPageInfo& childInfo = pageInfo[lodIdx]; + + // Get the list of parents tile that are currently + // loaded in the children aoi + std::vector parentList; + parentInfo.GetLoadedTileWithin(childInfo.GetPageDistance(), parentList); + + // Add the children of those parents to the load list + // of the children info, if they are not already there + childInfo.AddChildrenToLoadList(parentList); + } + } return change; @@ -550,35 +871,58 @@ trpgManagedTile *trpgPageManager::GetNextLoad() { // If we're already doing something, let them know about it if (lastLoad != None) - throw 1; + throw 1; // Look for anything that needs loaded // Start with lowest LOD, work up to highest trpgManagedTile *tile = NULL; for (unsigned int i=0;ilod; + lastLoad = Load; + lastTile = tile; + lastLod = tile->location.lod; } return tile; } void trpgPageManager::AckLoad() +{ + std::vector children; + AckLoad(children); +} +void trpgPageManager::AckLoad(std::vector const& children) { // If we're not in the middle of a load, register our displeasure if (lastLoad != Load) - throw 1; + throw 1; - LodPageInfo &info = pageInfo[lastLod]; - info.AckLoad(); + if(majorVersion >= 2 && minorVersion >=1) + { + if(children.size() > 0) + { + LodPageInfo& childInfo = pageInfo[lastLod+1]; + for(unsigned int idx = 0; idx < children.size(); ++idx) + { + TileLocationInfo const&childLocInfo = children[idx]; + if(childLocInfo.lod != lastLod+1) + continue; // Something wrong here + childInfo.AddToLoadList(childLocInfo.x, childLocInfo.y, childLocInfo.addr); + + // Also save info in parent tile + lastTile->SetChildLocationInfo(idx, childLocInfo); + + } + } + } + + pageInfo[lastLod].AckLoad(); lastLoad = None; lastTile = NULL; } @@ -593,7 +937,7 @@ void *trpgPageManager::GetGroupData(int groupID) { ManageGroupMap::const_iterator p = groupMap.find(groupID); if (p != groupMap.end()) - return (*p).second; + return (*p).second; return NULL; } @@ -602,22 +946,22 @@ trpgManagedTile *trpgPageManager::GetNextUnload() { // If we're already doing something, let them know about it if (lastLoad != None) - throw 1; + throw 1; // Look for anything that needs unloaded // Start with highest LOD, work down to lowest trpgManagedTile *tile = NULL; for (int i=pageInfo.size()-1;i>=0;i--) { - LodPageInfo &info = pageInfo[i]; - if ((tile = info.GetNextUnload())) - break; + LodPageInfo &info = pageInfo[i]; + if ((tile = info.GetNextUnload())) + break; } // Found one. Now the user has to unload it. if (tile) { - lastLoad = Unload; - lastTile = tile; - lastLod = tile->lod; + lastLoad = Unload; + lastTile = tile; + lastLod = tile->location.lod; } return tile; @@ -627,14 +971,14 @@ void trpgPageManager::AckUnload() { // If we're not in the middle of an unload, let 'em know. if (lastLoad != Unload) - throw 1; + throw 1; // Remove this tile's group IDs from the map const std::vector *groupIDs = lastTile->GetGroupIDs(); for (unsigned int i=0;isize();i++) { - ManageGroupMap::iterator p = groupMap.find((*groupIDs)[i]); - if (p != groupMap.end()) - groupMap.erase(p); + ManageGroupMap::iterator p = groupMap.find((*groupIDs)[i]); + if (p != groupMap.end()) + groupMap.erase(p); } LodPageInfo &info = pageInfo[lastLod]; @@ -647,7 +991,7 @@ bool trpgPageManager::Stop() { bool res=false; for (unsigned int i=0;i= childList.size()) + throw std::invalid_argument( + "trpgPageManageTester::ChildRefCB::GetChild(): index argument out of bound."); + else + return childList[idx]; +} + /* Page Manager Tester - These methods are used to test the Paging Manager. - */ + These methods are used to test the Paging Manager. +*/ trpgPageManageTester::trpgPageManageTester() { @@ -689,7 +1067,12 @@ void trpgPageManageTester::Init(trpgPrintBuffer *pBuf,trpgPageManager *pMan,trpg printBuf = pBuf; if (!archive->isValid()) - throw 1; + throw 1; + + const trpgHeader *header = archive->GetHeader(); + header->GetVersion(majorVersion, minorVersion); + + tileParser.AddCallback(TRPG_CHILDREF, &childRefCB, false); // Start up the paging manager manager->Init(archive); @@ -698,11 +1081,11 @@ void trpgPageManageTester::Init(trpgPrintBuffer *pBuf,trpgPageManager *pMan,trpg void trpgPageManageTester::RandomTest(int num,int seed) { if (!manager || !archive || !printBuf) - throw 1; + throw 1; // Seed the random number generator so we can replicate runs if (seed != -1) - srand(seed); + srand(seed); // Need the extents trpg2dPoint ll,ur,lod0Size; @@ -718,20 +1101,20 @@ void trpgPageManageTester::RandomTest(int num,int seed) int i; char line[1024]; for (i=0;iSetLocation(pt); - sprintf(line,"Jumped to (%f,%f). Tiles to load/unload = %s",pt.x,pt.y, - (changes ? "yes" : "no")); printBuf->prnLine(line); + // Jump to the point + bool changes = manager->SetLocation(pt); + sprintf(line,"Jumped to (%f,%f). Tiles to load/unload = %s",pt.x,pt.y, + (changes ? "yes" : "no")); printBuf->prnLine(line); - // Process the results - ProcessChanges(); + // Process the results + ProcessChanges(); } // Ask the page manager for its final status @@ -745,7 +1128,7 @@ void trpgPageManageTester::Fly_LL_to_UR(double dist) char line[1024]; if (!manager || !archive || !printBuf) - throw 1; + throw 1; // Need the extents trpg2dPoint ll,ur,lod0Size; @@ -761,15 +1144,15 @@ void trpgPageManageTester::Fly_LL_to_UR(double dist) // Fly the path trpg2dPoint loc; loc = ll; do { - loc.x += dist; loc.y += dist; + loc.x += dist; loc.y += dist; - // Jump to next point - bool changes = manager->SetLocation(loc); - sprintf(line,"Moved to (%f,%f). Tiles to load/unload = %s",loc.x,loc.y, - (changes ? "yes" : "no")); printBuf->prnLine(line); + // Jump to next point + bool changes = manager->SetLocation(loc); + sprintf(line,"Moved to (%f,%f). Tiles to load/unload = %s",loc.x,loc.y, + (changes ? "yes" : "no")); printBuf->prnLine(line); - // Process new location - ProcessChanges(); + // Process new location + ProcessChanges(); } while (loc.x < ur.x && loc.y < ur.y); // Ask the page manager for its final status @@ -788,9 +1171,9 @@ void trpgPageManageTester::ProcessChanges() printBuf->prnLine("Tiles to unload:"); printBuf->IncreaseIndent(); while ((unloadTile = manager->GetNextUnload())) { - unloadTile->GetTileLoc(x,y,lod); - sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line); - manager->AckUnload(); + unloadTile->GetTileLoc(x,y,lod); + sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line); + manager->AckUnload(); } printBuf->DecreaseIndent(); @@ -799,9 +1182,45 @@ void trpgPageManageTester::ProcessChanges() printBuf->prnLine("Tiles to load:"); printBuf->IncreaseIndent(); while ((loadTile = manager->GetNextLoad())) { - loadTile->GetTileLoc(x,y,lod); - sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line); - manager->AckLoad(); + loadTile->GetTileLoc(x,y,lod); + sprintf(line,"x = %d, y = %d, lod = %d",x,y,lod); printBuf->prnLine(line); + + if(majorVersion == 2 && minorVersion >= 1) + { + // Version 2.1 and over + // We need to parse the loaded tile to get all of its children info + const trpgwAppAddress& tileAddress = loadTile->GetTileAddress(); + trpgMemReadBuffer buf(archive->GetEndian()); + if(archive->ReadTile(tileAddress, buf)) + { + childRefCB.Reset(); + if(tileParser.Parse(buf)) + { + // childRefCB should now have alist of trpgChildRef found in the tile + unsigned int nbChildRef = childRefCB.GetNbChildren(); + if(nbChildRef > 0) + { + std::vector locInfoList; + for(unsigned int idx = 0; idx < nbChildRef; ++idx) + { + const trpgChildRef& childRef = childRefCB.GetChildRef(idx); + locInfoList.push_back(TileLocationInfo()); + TileLocationInfo& locInfo = locInfoList.back(); + childRef.GetTileLoc(locInfo.x, locInfo.y, locInfo.lod); + childRef.GetTileAddress(locInfo.addr); + } + + manager->AckLoad(locInfoList); + } + else + manager->AckLoad(); + } + } + else + manager->AckLoad(); + } + else + manager->AckLoad(); } printBuf->DecreaseIndent(); } diff --git a/src/osgPlugins/txp/trpage_managers.h b/src/osgPlugins/txp/trpage_managers.h index 32bd4ddcb..cfd89e307 100644 --- a/src/osgPlugins/txp/trpage_managers.h +++ b/src/osgPlugins/txp/trpage_managers.h @@ -19,21 +19,31 @@ #include /* This file contains class definitions for managers - that help you keep track of data related to - paging. For instance, which tiles to load - in at any given time and what textures you need - to read for a given tile. + that help you keep track of data related to + paging. For instance, which tiles to load + in at any given time and what textures you need + to read for a given tile. */ class trpgPageManager; +// Grid and file location of a tile +struct TileLocationInfo +{ + TileLocationInfo(): x(-1), y(-1), lod(-1) {} + TileLocationInfo(int gx, int gy, int glod, const trpgwAppAddress& gaddr): x(gx), y(gy), lod(glod), addr(gaddr) {} + int x, y, lod; + trpgwAppAddress addr; +}; + /* Managed Tiles are used by the trpgPageManager to keep - track of which tiles are loaded and what textures (and - models) they need loaded into memory with them. + track of which tiles are loaded and what textures (and + models) they need loaded into memory with them. */ -TX_EXDECL class TX_CLDECL trpgManagedTile { -friend class trpgPageManager; -public: +TX_EXDECL class TX_CLDECL trpgManagedTile +{ + friend class trpgPageManager; + public: trpgManagedTile(void); // Called to clear any info out of this tile @@ -43,41 +53,49 @@ public: Scene parser callback. The managed tile can then keep track of which textures and models go with this tile. - */ + */ bool ParseTileHeader(trpgReadBuffer &); // Check if the tile is loaded (e.g. the header read in) bool IsLoaded(void); /* Set the tile location. This resets any internal - state we may be keeping. - */ + state we may be keeping. + */ bool SetTileLoc(int x,int y,int lod); - // Get the tile location - bool GetTileLoc(int &x,int &y,int &lod); + bool GetTileLoc(int &x,int &y,int &lod) const; + + // In version 2.1 we no longer have the tile table to + // find the tiles, only by traversing the parent can it be + // found. So when we have this info, this is were to save it. + void SetTileAddress(const trpgwAppAddress& gAddr); + void SetTileAddress(int32 file, int32 offset); + const trpgwAppAddress& GetTileAddress() const; + + // Return a pointer to the tile header const trpgTileHeader *GetTileHead(void); /* Return a pointer to the list of locally defined - materials. As soon as the tile header is read by - ParseTileHeader (which you call) you'll want to get - this list and load the pageable textures. You can - use SetMatData to keep track of our internal texture - structures. - */ + materials. As soon as the tile header is read by + ParseTileHeader (which you call) you'll want to get + this list and load the pageable textures. You can + use SetMatData to keep track of our internal texture + structures. + */ const std::vector *GetLocMatList(void) const; /* Returns a pointer to a single local material, if within - the valid range of local materials for this tile. - */ + the valid range of local materials for this tile. + */ const trpgLocalMaterial *GetLocMaterial(int id) const; /* Set Local Data for managed tile. The local data would - probably be a pointer to the top of the scene graph you're - using to represent just this tile. - */ + probably be a pointer to the top of the scene graph you're + using to represent just this tile. + */ void SetLocalData(void *); /* Returns the local data you set with SetLocalData. @@ -85,25 +103,25 @@ public: void *GetLocalData(void) const; /* Associates a void * with one of the materials referenced - within this tile. The idea here is that you'll want - to load the texture for a given local material and then - pass your own internal texture structure into here as - a void *. That way, the trpgPageManager will keep track - of which textures you should unload when this tile goes - out of range. - */ + within this tile. The idea here is that you'll want + to load the texture for a given local material and then + pass your own internal texture structure into here as + a void *. That way, the trpgPageManager will keep track + of which textures you should unload when this tile goes + out of range. + */ bool SetMatData(int id,void *); /* Gets the void * data you associated with a given local - material index. See SetMatData for more information. - */ + material index. See SetMatData for more information. + */ void *GetMatData(int id) const; /* Add Group ID to this tile. This is called by the page - manager to keep track of which group IDs belong to this tile. - We use this information to NULL out the appropriate positions - in the group map help by the page manager. - */ + manager to keep track of which group IDs belong to this tile. + We use this information to NULL out the appropriate positions + in the group map help by the page manager. + */ void AddGroupID(int id); /* Retrieve the list of group IDs for this tile. @@ -111,14 +129,28 @@ public: const std::vector *GetGroupIDs(void) const; /* Print the current status and information about this managed - Tile. - */ + Tile. + */ void Print(trpgPrintBuffer &); -protected: + + // Children info, will throw exception if child index is out of bound + unsigned int GetNbChildren() const + { + return (unsigned int)childLocationInfo.size(); + } + bool SetChildLocationInfo(int childIdx, int x, int y, const trpgwAppAddress& addr); + bool SetChildLocationInfo(int childIdx, const TileLocationInfo& info); + const TileLocationInfo& GetChildLocationInfo(int childIdx) const; + bool GetChildTileLoc(int childIdx, int &x,int &y,int &lod) const; + const trpgwAppAddress& GetChildTileAddress(int childIdx) const; + + + protected: // Set if a tile is currently loaded bool isLoaded; // Tile location info - int x,y,lod; + TileLocationInfo location; + // Tile Header associated with this tile trpgTileHeader tileHead; // Data to keep associated with each individual local material index @@ -128,194 +160,268 @@ protected: // Local data (probably the top of the local scene graph) void *localData; + // What are the children: this to be used for version 2.1 and up. + // Both vector should have the same size + std::vector childLocationInfo; + // Note: Should do models too if anyone wanted them. }; /* The Page Manager is a helper class that can be used - to keep track of: (1) which tiles need to be loaded - into memory for a given viewer position, (2) which tiles - are currently loaded and (3) which tiles need to be unloaded - when the viewer position moves. The tile list this - class generates is guaranteed to be in the right order - for loading. You would use this class if you're implementing - a TerraPage reader for your visual run-time system. - */ -TX_EXDECL class TX_CLDECL trpgPageManager { -public: + to keep track of: (1) which tiles need to be loaded + into memory for a given viewer position, (2) which tiles + are currently loaded and (3) which tiles need to be unloaded + when the viewer position moves. The tile list this + class generates is guaranteed to be in the right order + for loading. You would use this class if you're implementing + a TerraPage reader for your visual run-time system. +*/ +TX_EXDECL class TX_CLDECL trpgPageManager +{ + public: trpgPageManager(void); virtual ~trpgPageManager(void); // Initialize with an archive virtual void Init(trpgr_Archive *); + virtual void Init(trpgr_Archive *inArch, int maxLod); /* Set Paging Distance - This is the extra distance outside the visible range - we want to page. The defaults will be valid. You would - set this if you want to pull tiles in earlier. Be sure - to call it before you call Init(), however. - */ + This is the extra distance outside the visible range + we want to page. The defaults will be valid. You would + set this if you want to pull tiles in earlier. Be sure + to call it before you call Init(), however. + */ virtual bool SetPageDistFactor(double); /* Updates the current location for paging purposes. - Returns true if any load or unloads need to happen. - */ + Returns true if any load or unloads need to happen. + */ virtual bool SetLocation(trpg2dPoint &); /* Get next tile to load. - The paging manager is keeping track of which tiles - need to be loaded and in what order. This method - returns a pointer to the next one. The user is - expected to call AckLoad() after the tile is loaded. - */ + The paging manager is keeping track of which tiles + need to be loaded and in what order. This method + returns a pointer to the next one. The user is + expected to call AckLoad() after the tile is loaded. + */ virtual trpgManagedTile *GetNextLoad(void); - /* Acknowledge Tile Load. - This method should be called when a tile has been - loaded by the caller. This method is used in conjunction - with GetNextLoad(). - */ - virtual void AckLoad(void); + /* Acknowledge Tile Load. + This method should be called when a tile has been + loaded by the caller. This method is used in conjunction + with GetNextLoad(). + + Version 2.1 and over supports variable lod so that we cannot know + from the tile table if a tile exist or not. So to manage this + the user must parse the loaded tile and extract its list of children + and pass it on to AckLoad() which will add to the appropriate lod list + the children info. If this is not done then only lod 0 will be pageable. + */ + + virtual void AckLoad(std::vector const& children); + + // Using this call with version 2.1 and over will only page lod 0 tiles + virtual void AckLoad(); /* Add Group ID to map. - This should be called when the user encounters a group-like - object while processing the scene graph data from a tile. - The groupId is given by TerraPage and the data should be - the corresponding group object that the user creates in - their own scenegraph toolkit. This information can then - be retrieved later by GetGroupData(). - */ + This should be called when the user encounters a group-like + object while processing the scene graph data from a tile. + The groupId is given by TerraPage and the data should be + the corresponding group object that the user creates in + their own scenegraph toolkit. This information can then + be retrieved later by GetGroupData(). + */ virtual void AddGroupID(trpgManagedTile *,int groupID,void *data); /* Get Group Data fetches the data cached by the user and - associated with the given groupID. This would be used in - conjunction with trpgAttach nodes to implement geometry paging. - */ + associated with the given groupID. This would be used in + conjunction with trpgAttach nodes to implement geometry paging. + */ virtual void *GetGroupData(int groupID); /* Get next tile to unload. - The paging manager keeps track of which tiles need - to be unloaded based on a change of location. It's - best if you unload tiles before loading them, but - that's really up to you. - */ + The paging manager keeps track of which tiles need + to be unloaded based on a change of location. It's + best if you unload tiles before loading them, but + that's really up to you. + */ virtual trpgManagedTile *GetNextUnload(void); /* Acknowledge a tile unload. - You should call this after you've "unloaded" a tile - and all its associated textures. - */ + You should call this after you've "unloaded" a tile + and all its associated textures. + */ virtual void AckUnload(void); + /* Stop paging entirely. Call this right before you want to - shut down paging. Everything active will wind up on the - unload lists. Then you can unload those tiles and move on. - */ + shut down paging. Everything active will wind up on the + unload lists. Then you can unload those tiles and move on. + */ virtual bool Stop(void); // Print current status and content information virtual void Print(trpgPrintBuffer &); -protected: + protected: trpgr_Archive *archive; // Center of paging trpg2dPoint pagePt; /* Information associated with each terrain level of - detail as related to paging. - */ - class LodPageInfo { - friend class trpgPageManager; + detail as related to paging. + */ + TX_EXDECL class TX_CLDECL LodPageInfo { + friend class trpgPageManager; public: - LodPageInfo(void); - virtual ~LodPageInfo(void); + LodPageInfo(void); + virtual ~LodPageInfo(void); - /* Initializes the class with its current LOD. - It figures out all the rest. - */ - virtual bool Init(trpgr_Archive *, int myLod, double scale); + /* Initializes the class with its current LOD. + It figures out all the rest. + */ + virtual bool Init(trpgr_Archive *, int myLod, double scale, int freeListDivider = 1); - /* Reset the location. This forces a recalculation - of what to load and unload if the cell has changed - or if this is the first SetLocation. - The location passed in must be relative to the southwest - corner of the TerraPage archive. - */ - virtual bool SetLocation(trpg2dPoint &); + /* Reset the location. This forces a recalculation + of what to load and unload if the cell has changed + or if this is the first SetLocation. + The location passed in must be relative to the southwest + corner of the TerraPage archive. + */ + virtual bool SetLocation(trpg2dPoint &); + + // Return the next tile to load for this terrain lod + virtual trpgManagedTile *GetNextLoad(void); + // Acknowledge the load. Move the active tile to the + // loaded list. + virtual void AckLoad(); + + // Get the lsit of + //bool GetLoadedTile + + // Return the next tile to unload for this terrain lod + virtual trpgManagedTile *GetNextUnload(void); + // Acknowledge the unload. Move the active tile to the + // free list. + virtual void AckUnload(void); + // Called to stop paging. Everything active is dumped on + // the unload list. + virtual bool Stop(void); + // Print current status and content information + virtual void Print(trpgPrintBuffer &); + + const trpg2iPoint& GetLodSize() const + { + return lodSize; + } + + int GetLod() const + { + return lod; + } + + double GetPageDistance() const + { + return pageDist; + } + + const trpg2dPoint& GetCellSize() const + { + return cellSize; + } + + // The unit are cellSize + const trpg2iPoint& GetAreaOfInterest() const + { + return aoiSize; + } + + + // The middle of this cell correspond to our paging + // location + const trpg2iPoint& GetCellPagingLocation() const + { + return cell; + } - // Return the next tile to load for this terrain lod - virtual trpgManagedTile *GetNextLoad(void); - // Acknowledge the load. Move the active tile to the - // loaded list. - virtual void AckLoad(void); - // Return the next tile to unload for this terrain lod - virtual trpgManagedTile *GetNextUnload(void); - // Acknowledge the unload. Move the active tile to the - // free list. - virtual void AckUnload(void); - // Called to stop paging. Everything active is dumped on - // the unload list. - virtual bool Stop(void); - // Print current status and content information - virtual void Print(trpgPrintBuffer &); protected: - virtual void Clean(void); - virtual void Update(void); + virtual void Clean(void); + virtual void Update(void); - // Check if the given tile is within the area we care about - bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne); + // Add to the load list the given tile if it is within the proper + // bound + bool AddToLoadList(int x, int y, const trpgwAppAddress& addr); - bool valid; + // Add the children of the given parent list + // to the load list if it it not already loaded + // or if it is not already in the list + void AddChildrenToLoadList(std::vector& parentList); - // Terrain LOD we're responsible for - int lod; + // Check if the given tile is within the area we care about + bool isWithin(trpgManagedTile *,trpg2iPoint &sw,trpg2iPoint &ne); - /* Adjusted (e.g. paranoid) distance outward from - which to page this terrain LOD. This takes into - account the distance in the header as well as - any factor the user may have added. - */ - double pageDist; + // Get the list of currently loaded tiles that fall within + // the region calculated from the given paging distance. + void GetLoadedTileWithin(double pagingDistance, std::vector& tileList); - /* Max tiles we could have loaded in at any given time. - This is just a guess because it's up to the user - to load (and, more importantly) unload. - */ - int maxNumTiles; + bool valid; - // Size of a single cell. Copied from the archive. - trpg2dPoint cellSize; + // Terrain LOD we're responsible for + int lod; - // Number of tiles (cells) in each direction - trpg2iPoint lodSize; + /* Adjusted (e.g. paranoid) distance outward from + which to page this terrain LOD. This takes into + account the distance in the header as well as + any factor the user may have added. + */ + double pageDist; - /* Area of interest size in cells - This is a linear distance "ahead" of the center cell. - */ - trpg2iPoint aoiSize; + /* Max tiles we could have loaded in at any given time. + This is just a guess because it's up to the user + to load (and, more importantly) unload. + */ + int maxNumTiles; - /* Our effective paging location sits at the middle - of this cell. We don't recalculate unless the - cell changes. */ - trpg2iPoint cell; + // Size of a single cell. Copied from the archive. + trpg2dPoint cellSize; - // List of tiles to load - std::deque load; - // List of tiles to unload - std::deque unload; - // List of currently loaded tiles - std::deque current; + // Number of tiles (cells) in each direction + trpg2iPoint lodSize; - // Used by Update. Here because we want to avoid memory allocs, if possible. - std::vector tmpCurrent; + /* Area of interest size in cells + This is a linear distance "ahead" of the center cell. + */ + trpg2iPoint aoiSize; - // Set if a load is in progress - // Load w/o ACK - bool activeLoad; - // Set if an unload is in progress - // Unload w/o ACK - bool activeUnload; + /* Our effective paging location sits at the middle + of this cell. We don't recalculate unless the + cell changes. */ + trpg2iPoint cell; - // List of tile pointers we can reuse - std::deque freeList; + // List of tiles to load + std::deque load; + // List of tiles to unload + std::deque unload; + // List of currently loaded tiles + std::deque current; + + // Used by Update. Here because we want to avoid memory allocs, if possible. + std::vector tmpCurrent; + + // Set if a load is in progress + // Load w/o ACK + bool activeLoad; + // Set if an unload is in progress + // Unload w/o ACK + bool activeUnload; + + // List of tile pointers we can reuse + std::deque freeList; + + // TerraPage version + int majorVersion, minorVersion; + + const trpgTileTable *tileTable; }; // Per terrain lod paging information @@ -324,8 +430,8 @@ protected: // Enumerated type for lastLoad typedef enum {Load,Unload,None} LoadType; /* Information about what the pending load/unload operation - is. It's up to the user to complete and acknowledge it. - */ + is. It's up to the user to complete and acknowledge it. + */ LoadType lastLoad; // LOD for the pending load/unload requested operation int lastLod; @@ -339,40 +445,80 @@ protected: typedef std::map ManageGroupMap; ManageGroupMap groupMap; + // Terrapge Version + int majorVersion, minorVersion; + bool valid; }; +// For Version 2.1 an over, the tile table only contains +// tiles of lod 0. To get access the other tiles, parent tile +// must be parsed to get at trpgChildRef nodes that will contain +// location info about the children. This callback can be use to +// parse the tile data. After parsing the callback object will contain +// the list of trpgChildRef nodes found. +TX_EXDECL class TX_CLDECL trpgr_ChildRefCB : public trpgr_Callback +{ + public: + void *Parse(trpgToken tok, trpgReadBuffer& rbuf); + // After parsing this will return the number of trpgChildRef node found. + unsigned int GetNbChildren() const; + // This will return the trpgChildRef node associated with the index. + // Will throw an exception if the index is out of bound + const trpgChildRef& GetChildRef(unsigned int idx) const; + + // Clear the children list + void Reset(); + protected: +// typedef std::vector ChildList; +// The const in the template parameter was removed because it causes GCC to +// freak out. I am of the opinion that const doesn't make sense in a template +// parameter for std::vector anyway... const prevents you from changing the +// value, so what exactly is the point? How does one add entries to the vector +// without giving them a value? -ADS + typedef std::vector ChildList; + ChildList childList; +}; + /* Page Manager Tester. This class tests a given paging manager - by applying likely - */ -TX_EXDECL class TX_CLDECL trpgPageManageTester { -public: + by applying likely +*/ +TX_EXDECL class TX_CLDECL trpgPageManageTester +{ + public: trpgPageManageTester(); virtual ~trpgPageManageTester(); /* Initialize the tester with a paging manager - and an archive. - */ + and an archive. + */ void Init(trpgPrintBuffer *,trpgPageManager *,trpgr_Archive *); /* Feeds the paging manager coordinates starting from - the lower left to upper right of the database in the - given increment. - */ + the lower left to upper right of the database in the + given increment. + */ void Fly_LL_to_UR(double dist=100.0); /* Jumps around randomly within the archive loading and - unloading as needed. - */ + unloading as needed. + */ void RandomTest(int no=100,int seed=-1); -protected: + protected: + // Does the work of "load" and "unloading" void ProcessChanges(); trpgPageManager *manager; trpgr_Archive *archive; trpgPrintBuffer *printBuf; + + trpgr_ChildRefCB childRefCB; + trpgr_Parser tileParser; + + // TerraPage version + int majorVersion, minorVersion; }; #endif diff --git a/src/osgPlugins/txp/trpage_material.cpp b/src/osgPlugins/txp/trpage_material.cpp index fa01f932b..c34a86487 100644 --- a/src/osgPlugins/txp/trpage_material.cpp +++ b/src/osgPlugins/txp/trpage_material.cpp @@ -18,17 +18,17 @@ #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 #include /* 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() @@ -44,18 +44,21 @@ void trpgMatTable::Reset() { numTable = 0; numMat = 0; - matTables.resize(0); + materialMap.clear(); } // Validity check bool trpgMatTable::isValid() const { - if (numTable <= 0 || numMat <= 0) - return false; - - for (unsigned int i=0;i=0;tableIter--) { - int lastEntry; - for (lastEntry=0;lastEntry=0;loop--) - matTables[tableIter*no+loop]=matTables[tableIter*numMat+loop]; - } - // reset the others - for (loop=lastEntry;loop= numTable) - return; - if (nm < 0 || nm >= numMat) - return; - matTables[nt*numMat+nm] = mat; - // ensure that this entry isn't re-used - if (mat.shadeModel>100) matTables[nt*numMat+nm].shadeModel=trpgMaterial::Smooth; -} + void trpgMatTable::SetMaterial(int nm,const trpgMaterial &mat) -{ - if (nm < 0 || nm >= numMat) - return; - - for (int i=0;i100) matTables[i*numMat+nm].shadeModel=trpgMaterial::Smooth; - } +{ + materialMap[nm] = mat; + numMat = materialMap.size(); } #define CEQ(ca,cb) (ca.red == cb.red && ca.green == cb.green && ca.blue == cb.blue) int trpgMatTable::AddMaterial(const trpgMaterial &mat,bool lookForExisting) { - return AddMaterialInSubtable(mat, 1, lookForExisting); -} - -int trpgMatTable::AddMaterialInSubtable(const trpgMaterial &mat,int table, bool lookForExisting) -{ - // Doesn't work if there's more than one table - //if (numTable != 1) - // return -1; - trpgMaterial cmat = mat; // necessary? - + // having a shadeModel of 999 indicates that the entry is free. I thought this would // work fine, until I realized that evidently most of the time the shademodel isn't set // at all. Now my kludge takes so much work it's almost worth doing it right. if (cmat.shadeModel>100) cmat.shadeModel=trpgMaterial::Smooth; - int baseMat=numMat; - int offset=(table-1)*numMat+baseMat; - - if (table>numTable) { - // Add another table. But we don't have to shuffle indices or reset entries - SetNumTable(table); - offset=(table-1)*numMat; - matTables[offset] = cmat; - return 0; - } + int baseMat=0; bool spaceInTable=false; + //int offset=baseMat; + if (lookForExisting) { - // Look for a matching base material minus the textures - for (baseMat = 0;baseMat < numMat;baseMat++) { - offset=(table-1)*numMat+baseMat; + // Look for a matching base material minus the textures + //for (baseMat = 0;baseMat < numMat;baseMat++) { + MaterialMapType::const_iterator itr = materialMap.begin(); + for ( ; itr != materialMap.end( ); itr++) { + baseMat = itr->first; + const trpgMaterial &bm = itr->second; + if (bm.shadeModel==999) { + // this is an 'empty' entry. Means we won't find it, either. + spaceInTable=true; + break; + } - trpgMaterial &bm = matTables[offset]; - if (bm.shadeModel==999) { - // this is an 'empty' entry. Means we won't find it, either. - spaceInTable=true; - break; - } - - // 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.attrSet.fid == bm.attrSet.fid && cmat.attrSet.smc == bm.attrSet.smc && - cmat.attrSet.stp == bm.attrSet.stp && cmat.attrSet.swc == bm.attrSet.swc && - cmat.autoNormal == bm.autoNormal && cmat.texEnvs.size() == bm.texEnvs.size()) { - // Test the texture envs - bool isSame=true; + // 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.attrSet.fid == bm.attrSet.fid && cmat.attrSet.smc == bm.attrSet.smc && + cmat.attrSet.stp == bm.attrSet.stp && cmat.attrSet.swc == bm.attrSet.swc && + cmat.autoNormal == bm.autoNormal && cmat.texEnvs.size() == bm.texEnvs.size()) { + // Test the texture envs + bool isSame=true; unsigned int i; - for (i=0;i= numTable || nm < 0 || nm >= numMat) - return false; - mat = matTables[nt*numMat+nm]; - + + MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm); + if(itr == materialMap.end()) + return false; + + mat = (*itr).second; return true; } + const trpgMaterial *trpgMatTable::GetMaterialRef(int nt,int nm) const { - if (nt < 0 || nt >= numTable || nm < 0 || nm >= numMat) - return false; - return const_cast(&matTables[nt*numMat+nm]); + MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm); + if(itr == materialMap.end()) + return false; + return const_cast(&(*itr).second); } bool trpgMatTable::Read(trpgReadBuffer &buf) { - trpgMaterial mat; - trpgToken matTok; - int32 len; - bool status; - int i,j; + trpgMaterial mat; + trpgToken matTok; + int32 len; + bool status; + int i,j; + int nMat,nTable; - 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; - } + 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 NULL; } return tenv; @@ -495,8 +448,8 @@ bool trpgTextureEnv::Read(trpgReadBuffer &buf) } /* Write Material class - Material representation. - */ + Material representation. +*/ // Constructor trpgMaterial::trpgMaterial() @@ -533,6 +486,8 @@ void trpgMaterial::Reset() attrSet.smc = -1; attrSet.stp = -1; attrSet.swc = -1; + handle = -1; + writeHandle = false; } // Validity check @@ -540,11 +495,11 @@ bool trpgMaterial::isValid() const { // Only thing we really care about is texture if (numTex < 0) - return false; + return false; for (int i=0;i= texids.size()) - return; + return; texids[no] = id; texEnvs[no] = env; @@ -647,17 +602,17 @@ void trpgMaterial::SetAttr(int attrCode,int val) { switch (attrCode) { case TR_FID: - attrSet.fid = val; - break; + attrSet.fid = val; + break; case TR_SMC: - attrSet.smc = val; - break; + attrSet.smc = val; + break; case TR_STP: - attrSet.stp = val; - break; + attrSet.stp = val; + break; case TR_SWC: - attrSet.swc = val; - break; + attrSet.swc = val; + break; } return; @@ -667,7 +622,7 @@ void trpgMaterial::SetAttr(int attrCode,int val) bool trpgMaterial::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + return false; buf.Begin(TRPGMATERIAL); @@ -704,20 +659,20 @@ bool trpgMaterial::Write(trpgWriteBuffer &buf) buf.End(); buf.Begin(TRPGMAT_NORMAL); - buf.Add(autoNormal); + buf.Add((int32)autoNormal); buf.End(); buf.Begin(TRPGMAT_TEXTURE); buf.Add(numTex); for (int i=0;i= 2.3, handle will be set to a unique identifier. + **/ + if(writeHandle) { + buf.Begin(TRPGMAT_HANDLE); + buf.Add((int)handle); + buf.End(); + } + buf.End(); return true; @@ -735,7 +699,7 @@ bool trpgMaterial::Write(trpgWriteBuffer &buf) /* *************** - Material Read methods + Material Read methods *************** */ // Get methods @@ -832,7 +796,7 @@ bool trpgMaterial::GetNumTexture(int &no) const bool trpgMaterial::GetTexture(int no,int &id,trpgTextureEnv &te) const { if (!isValid() || no < 0 || no >= numTex) - return false; + return false; id = texids[no]; te = texEnvs[no]; return true; @@ -853,27 +817,28 @@ bool trpgMaterial::GetAttr(int attrCode,int &ret) const { switch (attrCode) { case TR_FID: - ret = attrSet.fid; - break; + ret = attrSet.fid; + break; case TR_SMC: - ret = attrSet.smc; - break; + ret = attrSet.smc; + break; case TR_STP: - ret = attrSet.stp; - break; + ret = attrSet.stp; + break; case TR_SWC: - ret = attrSet.swc; - break; + ret = attrSet.swc; + break; default: - return false; + return false; } 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 &); @@ -897,98 +862,105 @@ void * materialCB::Parse(trpgToken tok,trpgReadBuffer &buf) 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: + { + int32 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; - case TRPGMAT_BUMP: - { - int tmp; - buf.Get(tmp); - bool isBump = (tmp) ? true : false; - mat->SetIsBumpMap(isBump); - } - break; - case TRPGMAT_ATTR: - { - int tmp; - buf.Get(tmp); - mat->SetAttr(trpgMaterial::TR_FID,tmp); - buf.Get(tmp); - mat->SetAttr(trpgMaterial::TR_SMC,tmp); - buf.Get(tmp); - mat->SetAttr(trpgMaterial::TR_STP,tmp); - buf.Get(tmp); - mat->SetAttr(trpgMaterial::TR_SWC,tmp); - } - break; - default: - break; - } + mat->AddTexture(texId,texEnv); + } + break; + case TRPGMAT_BUMP: + { + int32 tmp; + buf.Get(tmp); + bool isBump = (tmp) ? true : false; + mat->SetIsBumpMap(isBump); + } + break; + case TRPGMAT_ATTR: + { + int tmp; + buf.Get(tmp); + mat->SetAttr(trpgMaterial::TR_FID,tmp); + buf.Get(tmp); + mat->SetAttr(trpgMaterial::TR_SMC,tmp); + buf.Get(tmp); + mat->SetAttr(trpgMaterial::TR_STP,tmp); + buf.Get(tmp); + mat->SetAttr(trpgMaterial::TR_SWC,tmp); + } + break; + case TRPGMAT_HANDLE: + { + int hdl; + buf.Get(hdl); + mat->SetHandle(hdl); + } + break; + default: + break; + } } catch (...) { - return NULL; + return NULL; } return mat; @@ -1011,15 +983,16 @@ bool trpgMaterial::Read(trpgReadBuffer &buf) parse.AddCallback(TRPGMAT_TEXTURE,&matCb,false); parse.AddCallback(TRPGMAT_BUMP,&matCb,false); parse.AddCallback(TRPGMAT_ATTR,&matCb,false); + parse.AddCallback(TRPGMAT_HANDLE,&matCb,false); parse.Parse(buf); 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() @@ -1027,13 +1000,16 @@ trpgTexture::trpgTexture() mode = External; type = trpg_Unknown; numLayer = -1; - org = trpg_RGBX_Neither; name = NULL; useCount = 0; sizeX = sizeY = -1; addr.file = 0; addr.offset = 0; + addr.col = -1; + addr.row = -1; isMipmap = false; + writeHandle = false; + handle = -1; } // Copy construction @@ -1043,15 +1019,18 @@ trpgTexture::trpgTexture(const trpgTexture &in): mode = in.mode; type = in.type; numLayer = in.numLayer; // RGBX - org = in.org; // RGBX name = NULL; SetName(in.name); useCount = in.useCount; sizeX = in.sizeX; sizeY = in.sizeY; addr.file = in.addr.file; addr.offset = in.addr.offset; + addr.row = in.addr.row; + addr.col = in.addr.col; isMipmap = in.isMipmap; // storageSize + levelOffset + handle = in.handle; + writeHandle = in.writeHandle; } // Destruction @@ -1066,37 +1045,43 @@ void trpgTexture::Reset() mode = External; type = trpg_Unknown; numLayer = -1; - org = trpg_RGBX_Neither; if (name) - delete [] name; + delete [] name; name = NULL; useCount = 0; sizeX = sizeY = -1; addr.file = 0; addr.offset = 0; + addr.row = -1; + addr.col = -1; isMipmap = false; storageSize.clear(); levelOffset.clear(); + handle = -1; + writeHandle = false; } + + + // Valid if we've got a name bool trpgTexture::isValid() const { switch (mode) { case External: - return (name != NULL); - break; + return (name != NULL); + break; case Local: - return (type != trpg_Unknown && sizeX != -1 && sizeY != -1); - break; + return (type != trpg_Unknown && sizeX != -1 && sizeY != -1); + break; case Global: - return (type != trpg_Unknown); - break; + return (type != trpg_Unknown); + break; case Template: - return (type != trpg_Unknown && sizeX != -1 && sizeY != -1); - break; + return (type != trpg_Unknown && sizeX != -1 && sizeY != -1); + break; default: - return false; + return false; } return false; @@ -1107,11 +1092,11 @@ bool trpgTexture::isValid() const void trpgTexture::SetName(const char *inName) { if (name) - delete [] name; + delete [] name; name = NULL; if (!inName) - return; + return; name = new char[strlen(inName)+1]; strcpy(name,inName); @@ -1120,7 +1105,8 @@ void trpgTexture::SetName(const char *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); @@ -1149,18 +1135,6 @@ bool trpgTexture::GetImageType(ImageType &outType) const return true; } -void trpgTexture::SetImageOrganization(ImageOrg inOrg) -{ - org = inOrg; -} - -bool trpgTexture::GetImageOrganization(ImageOrg &outOrg) const -{ - outOrg = org; - - return true; -} - void trpgTexture::SetImageSize(const trpg2iPoint &inSize) { sizeX = inSize.x; @@ -1169,7 +1143,7 @@ void trpgTexture::SetImageSize(const trpg2iPoint &inSize) bool trpgTexture::GetImageSize(trpg2iPoint &outSize) const { if (mode != Local && mode != Template) - return false; + return false; outSize.x = sizeX; outSize.y = sizeY; @@ -1187,7 +1161,7 @@ bool trpgTexture::GetIsMipmap(bool &ret) const bool trpgTexture::GetImageAddr(trpgwAppAddress &outAddr) const { if (mode != Local) - return false; + return false; outAddr = addr; @@ -1201,38 +1175,46 @@ bool trpgTexture::GetImageDepth(int32 &depth) const { switch (type) { case trpg_RGB8: - depth = 3; - break; + depth = 3; + break; case trpg_RGBA8: - depth = 4; - break; + depth = 4; + break; case trpg_INT8: - depth = 1; - break; + depth = 1; + break; case trpg_INTA8: - depth = 2; - break; + depth = 2; + break; case trpg_FXT1: - depth = 3; - break; + depth = 3; + break; case trpg_RGBX: - depth = numLayer; - break; - case trpg_DDS: - depth = 3; - break; + depth = numLayer; + break; case trpg_DXT1: - depth = 3; - break; + depth = 3; + break; case trpg_DXT3: - depth = 4; - break; + depth = 3; + break; case trpg_DXT5: - depth = 4; - break; + depth = 3; + break; + case trpg_MCM5: + depth = 5; + break; + case trpg_MCM6R: + case trpg_MCM6A: + depth = 6; + break; + case trpg_MCM7RA: + case trpg_MCM7AR: + depth = 7; + break; default: - depth = -1; - break; + depth = -1; + break; } return true; @@ -1245,8 +1227,9 @@ void trpgTexture::SetNumLayer(int layers) bool trpgTexture::GetNumLayer(int &layers) const { - if (!isValid()) return false; - layers = numLayer; + if (!isValid()) + return false; + GetImageDepth(layers); return true; } @@ -1261,7 +1244,8 @@ void trpgTexture::AddTile() } bool trpgTexture::GetNumTile(int &num) const { - if (!isValid()) return false; + if (!isValid()) + return false; num = useCount; return true; } @@ -1273,7 +1257,7 @@ trpgTexture &trpgTexture::operator = (const trpgTexture &in) type = in.type; if (in.name) - SetName(in.name); + SetName(in.name); useCount = in.useCount; @@ -1282,10 +1266,12 @@ trpgTexture &trpgTexture::operator = (const trpgTexture &in) // RGBX numLayer = in.numLayer; - org = in.org; isMipmap = in.isMipmap; addr = in.addr; + + writeHandle = in.writeHandle; + handle = in.handle; return *this; } @@ -1294,28 +1280,28 @@ trpgTexture &trpgTexture::operator = (const trpgTexture &in) int trpgTexture::operator == (const trpgTexture &in) const { if (mode != in.mode) - return 0; + return 0; switch (mode) { case External: - if (!in.name && !name) - return 1; - if (!in.name || !name) - return 0; - return (!strcmp(in.name,name)); - break; + 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 && - numLayer == in.numLayer && org == in.org) - return 1; - break; + if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY && + isMipmap == in.isMipmap && + addr.file == in.addr.file && addr.offset == in.addr.offset && + addr.row == in.addr.row && addr.col==in.addr.col ) + return 1; + break; case Global: case Template: - if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY && - isMipmap == in.isMipmap && numLayer == in.numLayer && org == in.org) - return 1; + if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY && + isMipmap == in.isMipmap) + return 1; } return 0; @@ -1334,8 +1320,8 @@ int32 trpgTexture::CalcNumMipmaps() const // Now look for the highest bit int p2; for (p2=0;p2<32;p2++) - if ((1<= 0 && miplevel < CalcNumMipmaps() ) { - if ( !storageSize.size() ) - CalcMipLevelSizes(); - return storageSize[miplevel]; + if ( !storageSize.size() ) + CalcMipLevelSizes(); + return storageSize[miplevel]; } return 0; @@ -1369,9 +1355,9 @@ int32 trpgTexture::MipLevelSize(int miplevel) int32 trpgTexture::MipLevelOffset(int miplevel) { if ( miplevel > 0 && miplevel < CalcNumMipmaps() ) { - if ( !levelOffset.size() ) - CalcMipLevelSizes(); - return levelOffset[miplevel]; + if ( !levelOffset.size() ) + CalcMipLevelSizes(); + return levelOffset[miplevel]; } return 0; @@ -1394,10 +1380,10 @@ bool trpgTexture::Write(trpgWriteBuffer &buf) buf.Add(sizeY); buf.Add(addr.file); buf.Add(addr.offset); - buf.Add(isMipmap); - // More for MCMs - buf.Add(numLayer); - buf.Add((unsigned char)org); + buf.Add((int32)isMipmap); + if(writeHandle) { + buf.Add((int32)handle); + } buf.End(); return true; @@ -1409,29 +1395,38 @@ bool trpgTexture::Read(trpgReadBuffer &buf) char texName[1024]; try { - buf.Get(texName,1023); - SetName(texName); - buf.Get(useCount); + buf.Get(texName,1023); + SetName(texName); + buf.Get(useCount); - 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; - if ( !buf.isEmpty() ) { - buf.Get(numLayer); - buf.Get(bval); org = (trpgTexture::ImageOrg)bval; - } + 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; + GetImageDepth(numLayer); // heh + buf.Get(sizeX); + buf.Get(sizeY); + buf.Get(addr.file); + buf.Get(addr.offset); + int32 ival; + buf.Get(ival); + // Read the handle if we can.. + try { + if(!buf.Get((int32 &)handle)) { + handle = -1; + } + else { + writeHandle = true; + } + } + catch (...) { + handle = -1; + } + isMipmap = (ival) ? true : false; } catch (...) { - return false; + return false; } if (!isValid()) return false; @@ -1455,37 +1450,51 @@ void trpgTexture::CalcMipLevelSizes() switch (type) { case trpg_DXT1: - isDXT = true; - block_size = 8; - break; + isDXT = true; + block_size = 8; + break; case trpg_DXT3: case trpg_DXT5: - isDXT = true; - block_size = 16; - break; + isDXT = true; + block_size = 16; + break; case trpg_RGB8: - pad_size = 4; - pixel_size = 3; - break; + pad_size = 4; + pixel_size = 3; + break; case trpg_RGBA8: - pad_size = 4; - pixel_size = 4; - break; + pad_size = 4; + pixel_size = 4; + break; case trpg_RGBX: - pad_size = 4; - pixel_size = numLayer; - break; + pad_size = 4; + pixel_size = numLayer; + break; + case trpg_MCM5: + pad_size = 4; + pixel_size = 5; + break; + case trpg_MCM6R: + case trpg_MCM6A: + pad_size = 4; + pixel_size = 6; + break; + case trpg_MCM7RA: + case trpg_MCM7AR: + pad_size = 4; + pixel_size = 7; + break; case trpg_INT8: - pad_size = 4; - pixel_size = 1; - break; + pad_size = 4; + pixel_size = 1; + break; case trpg_INTA8: - pad_size = 4; - pixel_size = 2; - break; + pad_size = 4; + pixel_size = 2; + break; case trpg_FXT1: - isFXT = true; - break; + isFXT = true; + break; default: break; } @@ -1499,96 +1508,97 @@ void trpgTexture::CalcMipLevelSizes() if ( isDXT ) { // DXT compressed - int num_x_blocks = ((sizeX/4)+(sizeX%4?1:0)); - int num_y_blocks = ((sizeY/4)+(sizeY%4?1:0)); + 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); + 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); + 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); + 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); - } + level_size = num_x_blocks * num_y_blocks * block_size; + storageSize.push_back(level_size); + } - return; + return; } if ( isFXT) { - // bits per pixel and size - int bpp = 4; - int x = sizeX; - int y = sizeY; - - int nummiplevels = (isMipmap ? CalcNumMipmaps() : 1); - for (int i = 0; i < nummiplevels; i++) { - if (i > 0) - levelOffset.push_back(level_offset); + // bits per pixel and size + int bpp = 4; + int x = sizeX; + int y = sizeY; + + int nummiplevels = (isMipmap ? CalcNumMipmaps() : 1); + for (int i = 0; i < nummiplevels; i++) { + if (i > 0) + levelOffset.push_back(level_offset); - x = ( x + 0x7 ) & ~0x7; - y = ( y + 0x3 ) & ~0x3; + x = ( x + 0x7 ) & ~0x7; + y = ( y + 0x3 ) & ~0x3; - // Number of bytes - level_size = ( x * y * bpp ) >> 3; - storageSize.push_back(level_size); - level_offset += level_size; + // Number of bytes + level_size = ( x * y * bpp ) >> 3; + storageSize.push_back(level_size); + level_offset += level_size; - if (x > 1) x /= 2; - if (y > 1) y /= 2; - } + if (x > 1) x /= 2; + if (y > 1) y /= 2; + } - return; + return; } { - int x_size = sizeX; - int y_size = sizeY; + int x_size = sizeX; + int y_size = sizeY; - // Pad to a given size, if necessary - int row_size = x_size * pixel_size; - if (pad_size > 0) { - int left = row_size%pad_size; - if (left) - row_size += pad_size - left; - } + // Pad to a given size, if necessary + int row_size = x_size * pixel_size; + if (pad_size > 0) { + int left = row_size%pad_size; + if (left) + row_size += pad_size - left; + } - level_size = row_size * y_size; - storageSize.push_back(level_size); - for ( int i = 1; i < num_miplevels; i++ ) { - level_offset += level_size; - levelOffset.push_back(level_offset); + level_size = row_size * y_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); + x_size /= 2; + y_size /= 2; + x_size = MAX(1,x_size); + y_size = MAX(1,y_size); - row_size = x_size * pixel_size; - if (pad_size > 0) { - int left = row_size%pad_size; - if (left) - row_size += pad_size - left; - } - level_size = row_size * y_size; - storageSize.push_back(level_size); - } + row_size = x_size * pixel_size; + if (pad_size > 0) { + int left = row_size%pad_size; + if (left) + row_size += pad_size - left; + } + level_size = row_size * y_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() { - + currentRow = -1; + currentCol = -1; } trpgTexTable::trpgTexTable(const trpgTexTable &in): trpgReadWriteable(in) @@ -1600,7 +1610,9 @@ trpgTexTable::trpgTexTable(const trpgTexTable &in): void trpgTexTable::Reset() { errMess[0] = '\0'; - texList.resize(0); + textureMap.clear(); + currentRow = -1; + currentCol = -1; } // Destructor @@ -1612,58 +1624,71 @@ trpgTexTable::~trpgTexTable() // Validity check bool trpgTexTable::isValid() const { - if (!texList.size()) + if (!textureMap.size()) { - strcpy(errMess, "Texture table list is empty"); - return false; + strcpy(errMess, "Texture table list is empty"); + return false; } - for (unsigned int i=0;isecond.isValid()) { + strcpy(errMess, "A texture in the texture table is invalid"); + return false; + } } - return true; } // Set functions -void trpgTexTable::SetNumTextures(int no) +void trpgTexTable::SetNumTextures(int /*no*/) { - texList.resize(no); + // obsolete. This method doesn't need to do anything since we're using a map instead of a vector. + // texList.resize(no); } int trpgTexTable::AddTexture(const trpgTexture &inTex) { - texList.resize(texList.size()+1); - texList[texList.size()-1] = inTex; - return texList.size()-1; + + TeAttrHdl hdl = inTex.GetHandle(); + if(hdl==-1) { + // if no handle is specified, we will use an index as the handle (just like before 2.3) + hdl = textureMap.size(); + } + TextureMapType::iterator itr = textureMap.find(hdl); + // Don't overwrite the texture if it was already there + if(itr==textureMap.end()) + textureMap[hdl] = inTex; + return hdl; } int trpgTexTable::FindAddTexture(const trpgTexture &inTex) { - for (unsigned int i=0;isecond; + if(tx == inTex) { + return itr->first; + } + } return AddTexture(inTex); } void trpgTexTable::SetTexture(int id,const trpgTexture &inTex) { - if (id < 0 || (unsigned int)id >= texList.size()) - return; - - texList[id] = inTex; + if (id < 0) + return; + textureMap[id] = inTex; } // Copy operator trpgTexTable &trpgTexTable::operator = (const trpgTexTable &in) { Reset(); - for (unsigned int i=0;isecond; + in.GetTexture(itr->first,tex); + AddTexture(tex); + } return *this; } @@ -1674,41 +1699,72 @@ bool trpgTexTable::Write(trpgWriteBuffer &buf) int32 numTex; if (!isValid()) - return false; + return false; buf.Begin(TRPGTEXTABLE2); - numTex = texList.size(); + numTex = textureMap.size(); buf.Add(numTex); - for (unsigned int i=0;isecond.Write(buf); + } buf.End(); return true; } /* *********** - Read Texture Table + Read Texture Table *********** */ // Get functions bool trpgTexTable::GetNumTextures(int &no) const { - no = texList.size(); + no = textureMap.size(); if (!isValid()) return false; return true; } bool trpgTexTable::GetTexture(int id,trpgTexture &ret) const { - if (!isValid()) return false; - if (id < 0 || id >= (int)texList.size()) return false; + if (!isValid()) + return false; + if (id < 0) + return false; + TextureMapType::const_iterator itr = textureMap.find(id); + if(itr == textureMap.end()) { + return false; + } + ret = itr->second; - ret = texList[id]; return true; } const trpgTexture *trpgTexTable::GetTextureRef(int id) const { - if (id < 0 || id >= (int)texList.size()) return NULL; - return &texList[id]; + if (id < 0) + return false; + TextureMapType::const_iterator itr = textureMap.find(id); + if(itr == textureMap.end()) { + return false; + } + const trpgTexture *ret = &(itr->second); + return ret; +} + +const trpgTexture *trpgTexTable::FindByName(const char *name, int &texid) const +{ + TextureMapType::const_iterator itr = textureMap.begin(); + for ( ; itr != textureMap.end( ); itr++) { + char thisName[1024]; + thisName[0] = '\0'; + itr->second.GetName(thisName,1023); + if(strcasecmp(thisName,name)==0) + { + texid = itr->first; + return &(itr->second); + } + } + return false; + } bool trpgTexTable::Read(trpgReadBuffer &buf) @@ -1718,29 +1774,39 @@ bool trpgTexTable::Read(trpgReadBuffer &buf) int32 len; try { - buf.Get(numTex); - texList.resize(numTex); - for (int i=0;i=2.3) + if((currentRow!=-1)&&(currentCol!=-1)) { + trpgwAppAddress taddr; + tex.GetImageAddr(taddr); + taddr.col = currentCol; + taddr.row = currentRow; + tex.SetImageAddr(taddr); + } + AddTexture(tex); + buf.PopLimit(); + if (!status) throw 1; + } } catch (...) { - return false; + return false; } return true; } + /* ************** - Local Material + Local Material ************** - */ + */ trpgLocalMaterial::trpgLocalMaterial() { @@ -1749,6 +1815,8 @@ trpgLocalMaterial::trpgLocalMaterial() addr.resize(1); addr[0].file = 0; addr[0].offset = 0; + addr[0].col = -1; + addr[0].row = -1; } trpgLocalMaterial::~trpgLocalMaterial() @@ -1765,10 +1833,12 @@ void trpgLocalMaterial::Reset() { baseMat = -1; sx = sy = ex = ey = destWidth = destHeight = 0; -// storageSize.resize(0); +// storageSize.resize(0); addr.resize(1); addr[0].file = 0; addr[0].offset = 0; + addr[0].col = -1; + addr[0].row = -1; } bool trpgLocalMaterial::GetBaseMaterial(int32 &subTable,int32 &matID) const @@ -1840,21 +1910,21 @@ bool trpgLocalMaterial::GetNumLocals(int &numLocals) const } /*bool trpgLocalMaterial::SetStorageSizes(int level,vector *inSizes) -{ - storageSize.resize(inSizes->size()); - for (int i=0;isize();i++) - storageSize[i] = (*inSizes)[i]; + { + storageSize.resize(inSizes->size()); + for (int i=0;isize();i++) + storageSize[i] = (*inSizes)[i]; - return true; -}*/ + return true; + }*/ /*bool trpgLocalMaterial::GetStorageSizes(const vector *retSize) -{ - if (!isValid()) return false; + { + if (!isValid()) return false; - retSize = storageSize; - return true; -}*/ + retSize = storageSize; + return true; + }*/ bool trpgLocalMaterial::isValid() const { @@ -1868,7 +1938,7 @@ bool trpgLocalMaterial::isValid() const bool trpgLocalMaterial::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + return false; buf.Begin(TRPGLOCALMATERIAL); @@ -1885,12 +1955,12 @@ bool trpgLocalMaterial::Write(trpgWriteBuffer &buf) buf.Add(addr[0].offset); // and in case there's more... int numAddrs=(int)(addr.size()); - buf.Add(numAddrs-1); // write even if its zero for reading purposes if (numAddrs>1) { - for (int i=1;i #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. - */ +#define OLDMODELSTYLE + +/* trpage_model.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. + */ #include #include /* 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; + diskRef = -1; + handle = -1; + writeHandle = false; } + trpgModel::trpgModel(const trpgModel &in): trpgReadWriteable(in) { - name = NULL; - type = External; - *this = in; + if (in.name) + { + name = new char[strlen(in.name)+1]; + strcpy(name,in.name); + } + else + name = NULL; + + type=in.type; + useCount=in.useCount; + diskRef=in.diskRef; + handle = in.handle; + writeHandle = in.writeHandle; } + // Reset function void trpgModel::Reset() { - if (name) - delete [] name; - name = NULL; - useCount = 0; + if (name) + delete [] name; + name = NULL; + useCount = 0; + diskRef = -1; + handle = -1; + writeHandle = false; } trpgModel::~trpgModel() { - Reset(); + Reset(); } // Set functions +void trpgModel::SetType(int t) +{ + type = t; +} + 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); - - type = External; + if (nm) + { + name = new char[(nm ? strlen(nm) : 0)+1]; + strcpy(name,nm); + } } void trpgModel::SetReference(trpgDiskRef pos) { - if (name) - delete [] name; - - diskRef = pos; - - type = Local; + diskRef = pos; } void trpgModel::SetNumTiles(int num) { - useCount = num; + useCount = num; } void trpgModel::AddTile() { - useCount++; + useCount++; } // Validity check bool trpgModel::isValid() const { - if (type == External && !name) - { - strcpy(errMess, "Model is external with no name"); - return false; - } + if (type == External && !name) + { + strcpy(errMess, "Model is external with no name"); + return false; + } - return true; + return true; } // Copy from one to another trpgModel& trpgModel::operator = (const trpgModel &in) { - if (name) { - delete [] name; - name = NULL; - } + if (name) { + delete [] name; + name = NULL; + } - type = in.type; - if (in.name) - SetName(in.name); - diskRef = in.diskRef; - useCount = in.useCount; - - return *this; + type = in.type; + if (in.name) + SetName(in.name); + diskRef = in.diskRef; + useCount = in.useCount; + writeHandle = in.writeHandle; + handle = in.handle; + 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 + // We will use two different tokens to track the + // format used in terrapage 2.2, and older versions + int tok = TRPGMODELREF; + if(writeHandle) + tok = TRPGMODELREF2; + +// Nick messed up the model entries when checking into txv4; now we're +// a bit stuck because U3 dbs don't have models in the U2 viewer. +// This will force the old behavior. +#ifdef OLDMODELSTYLE + buf.Begin(tok); + buf.Add(type); + //writeHandle is only set for terrapage 2.2, and we use the different token. + if(writeHandle) { + buf.Add((int)handle); + } + if (name) + buf.Add(name); + else buf.Add(diskRef); - buf.Add(useCount); + buf.Add(useCount); - buf.End(); +#else + buf.Begin(tok); + if(writeHandle) { + buf.Add((int)handle); + } + buf.Add(type); + buf.Add(name); + buf.Add(diskRef); + buf.Add(useCount); +#endif + 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()) 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) +bool trpgModel::Read(trpgReadBuffer &buf, bool hasHandle) { - char tmpName[1024]; + // MD: added complexity here - written multiple ways by + // mistake, unraveling the various cases. + 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); + // TerraPage 2.2 will store the unique handle after the type + // we use a different token, so this is backwards compatible. + if(hasHandle) { + buf.Get((int32 &)handle); + } + else + handle = -1; + if (type == Local) { + // two possibilities: + // name, diskRef, useCount + // diskRef, useCount + // diskRef + useCount = 12 bytes... + if (buf.TestLimit(13)) + { + buf.Get(tmpName,1023); + SetName(tmpName); + } + buf.Get(diskRef); + buf.Get(useCount); + } + else + { + // two possibilities: + // name, diskRef, useCount + // name, useCount + buf.Get(tmpName,1023); + SetName(tmpName); + // useCount = 4 bytes... + if (buf.TestLimit(5)) + buf.Get(diskRef); + buf.Get(useCount); + } + } + catch(...) { + return false; + } - return isValid(); + // going to make this fail if the buffer isn't empty. + if (buf.TestLimit(1)) return false; + + return isValid(); } /* Write Model Reference table - Groups of models for the entire file. - */ + Groups of models for the entire file. + */ // Constructor trpgModelTable::trpgModelTable() @@ -227,50 +303,73 @@ trpgModelTable::~trpgModelTable() // Reset function void trpgModelTable::Reset() { - models.resize(0); + modelsMap.clear(); } // Set functions -void trpgModelTable::SetNumModels(int no) +void trpgModelTable::SetNumModels(int /*no*/) { - models.resize(no); + // This method isn't needed with a map + //models.resize(no); } void trpgModelTable::SetModel(int id,const trpgModel &mod) { - if (id < 0 || (unsigned int)id >= models.size()) - return; + if (id < 0) + return; - models[id] = mod; + modelsMap[id] = mod; + //models[id] = mod; } -int trpgModelTable::AddModel(const trpgModel &mod) -{ - models.push_back(mod); - return models.size()-1; +int trpgModelTable::AddModel(trpgModel &mod) +{ + int hdl = modelsMap.size(); + if(mod.GetHandle()==-1) { + modelsMap[hdl] = mod; + return hdl; + } + modelsMap[mod.GetHandle()] = mod; + return mod.GetHandle(); } -int trpgModelTable::FindAddModel(const trpgModel &mod) -{ - for (unsigned int i=0;isecond == mod) { + return itr->first; + } + } + return AddModel(mod); +} + +bool trpgModelTable::FindByName(const char *name, unsigned int &mId) +{ + ModelMapType::const_iterator itr = modelsMap.begin(); + for ( ; itr != modelsMap.end( ); itr++) { + char theName[1023]; + itr->second.GetName(theName,1023); + if(strcmp(name,theName)==0) { + mId = itr->first; + return true; + } + } + return false; } // Validity check bool trpgModelTable::isValid() const { - for (unsigned int i=0;isecond.isValid()) { + if(itr->second.getErrMess()) + strcpy(errMess, itr->second.getErrMess()); + return false; + } + } + return true; } @@ -278,67 +377,85 @@ bool trpgModelTable::isValid() const // Write out the model table bool trpgModelTable::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPGMODELTABLE); - buf.Add((int32)models.size()); - for (unsigned int i=0;isecond.Write(buf); + } + buf.End(); - return true; + return true; } -/* *************** - Model Table Read methods - *************** - */ +/* *************** + Model Table Read methods + *************** + */ // Get methods bool trpgModelTable::GetNumModels(int &nm) const { - if (!isValid()) return false; - nm = models.size(); - return true; + if (!isValid()) return false; + nm = modelsMap.size(); + return true; } bool trpgModelTable::GetModel(int id,trpgModel &model) const { - if (!isValid() || id < 0 || id >= (int)models.size()) - return false; - model = models[id]; - return true; + if (!isValid() || id < 0 ) //|| id >= models.size()) + return false; + //model = models[id]; + ModelMapType::const_iterator itr = modelsMap.find(id); + if(itr == modelsMap.end()) { + return false; + } + model = itr->second; + return true; } trpgModel *trpgModelTable::GetModelRef(int id) { - if (id < 0 || id >= (int)models.size()) - return NULL; - return &models[id]; + if (id < 0 ) //|| id >= models.size()) + return NULL; + //return &models[id]; + ModelMapType::iterator itr = modelsMap.find(id); + if(itr == modelsMap.end()) { + return false; + } + return &(itr->second); } bool trpgModelTable::Read(trpgReadBuffer &buf) { - int32 numModel; - trpgModel model; - trpgToken tok; - int32 len; - bool status; + int32 numModel; + 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 #include /* Write Group - Basic group. - */ + Basic group. +*/ // Constructor trpgGroup::trpgGroup() @@ -49,8 +49,8 @@ void trpgGroup::Reset() numChild = 0; id = -1; if ( name ) { - delete [] name; - name = 0; + delete [] name; + name = 0; } } @@ -71,15 +71,18 @@ void trpgGroup::SetID(int inID) void trpgGroup::SetName(const char* newname ) { - if ( name ) { - delete [] name; - name = 0; + if ( name ) + { + delete [] name; + name = 0; } - if (newname) { - if ( strlen(newname) ) { - name = new char[strlen(newname)+1]; - strcpy(name,newname); - } + if (newname) + { + if ( strlen(newname) ) + { + name = new char[strlen(newname)+1]; + strcpy(name,newname); + } } } @@ -115,14 +118,14 @@ bool trpgGroup::isValid() const bool trpgGroup::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + return false; buf.Begin(TRPG_GROUP); buf.Add(numChild); buf.Add(id); if ( name && strlen(name) ) { - buf.Add(name); + buf.Add(name); } buf.End(); @@ -134,27 +137,27 @@ bool trpgGroup::Write(trpgWriteBuffer &buf) bool trpgGroup::Read(trpgReadBuffer &buf) { 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); - } + 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 false; } return isValid(); } /* Write Billboard - Represents rotational billboarded geometry. - */ + Represents rotational billboarded geometry. +*/ // Constructor trpgBillboard::trpgBillboard() @@ -176,9 +179,10 @@ void trpgBillboard::Reset() axis = trpg3dPoint(0,0,1); center = trpg3dPoint(0,0,0); numChild = 0; - if ( name ) { - delete [] name; - name = 0; + if ( name ) + { + delete [] name; + name = 0; } } @@ -231,7 +235,7 @@ bool trpgBillboard::GetType(int &t) const bool trpgBillboard::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + return false; buf.Begin(TRPG_BILLBOARD); buf.Add(numChild); @@ -242,7 +246,7 @@ bool trpgBillboard::Write(trpgWriteBuffer &buf) buf.Add(axis); if ( name && strlen(name) ) { - buf.Add(name); + buf.Add(name); } buf.End(); @@ -255,28 +259,28 @@ bool trpgBillboard::Read(trpgReadBuffer &buf) 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); - if ( !buf.isEmpty() ) { - char nm[1024] = {0}; - buf.Get(nm,1024); - SetName(nm); - } + 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 false; } return isValid(); } /* Write Level of Detail - Represents LOD information. - */ + Represents LOD information. +*/ // Constructor trpgLod::trpgLod() @@ -299,8 +303,8 @@ void trpgLod::Reset() rangeIndex = -1; valid = true; if ( name ) { - delete [] name; - name = 0; + delete [] name; + name = 0; } } @@ -313,7 +317,7 @@ void trpgLod::SetCenter(const trpg3dPoint &pt) void trpgLod::SetNumChild(int no) { if (no < 0) - return; + return; numRange = no; } @@ -331,14 +335,14 @@ void trpgLod::SetID(int inID) void trpgLod::SetName(const char* newname ) { if ( name ) { - delete [] name; - name = 0; + delete [] name; + name = 0; } if (newname) { - if ( strlen(newname) ) { - name = new char[strlen(newname)+1]; - strcpy(name,newname); - } + if ( strlen(newname) ) { + name = new char[strlen(newname)+1]; + strcpy(name,newname); + } } } @@ -393,7 +397,7 @@ bool trpgLod::GetRangeIndex(int &ri) const bool trpgLod::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + return false; buf.Begin(TRPG_LOD); buf.Add(id); @@ -404,9 +408,9 @@ bool trpgLod::Write(trpgWriteBuffer &buf) buf.Add(width); if ( name && strlen(name) ) { - buf.Add(name); + buf.Add(name); } else - buf.Add(""); + buf.Add(""); buf.End(); @@ -418,33 +422,33 @@ bool trpgLod::Write(trpgWriteBuffer &buf) 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); - 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); - } + 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 false; } 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() @@ -461,17 +465,17 @@ trpgLayer::~trpgLayer() bool trpgLayer::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + return false; buf.Begin(TRPG_LAYER); buf.Add(numChild); buf.Add(id); if ( name && strlen(name) ) { - buf.Add(name); + buf.Add(name); } - buf.End(); + buf.End(); return true; } @@ -480,18 +484,18 @@ bool trpgLayer::Write(trpgWriteBuffer &buf) bool trpgLayer::Read(trpgReadBuffer &buf) { 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); - } + 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 false; } return isValid(); @@ -502,14 +506,14 @@ void trpgLayer::Reset() { numChild = 0; if ( name ) { - delete [] name; - name = 0; + delete [] name; + name = 0; } } /* Write Transform - Matrix defining the transform with children. - */ + Matrix defining the transform with children. +*/ // Constructor trpgTransform::trpgTransform() @@ -533,8 +537,8 @@ void trpgTransform::Reset() m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; if ( name ) { - delete [] name; - name = 0; + delete [] name; + name = 0; } } @@ -552,9 +556,9 @@ 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]; + for (int j=0;j<4;j++) + // Note: is this right? + rm[i*4+j] = m[i][j]; return true; } @@ -562,17 +566,17 @@ bool trpgTransform::GetMatrix(float64 *rm) const bool trpgTransform::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; + 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]); + for (int j=0;j<4;j++) + buf.Add(m[i][j]); if ( name && strlen(name) ) { - buf.Add(name); + buf.Add(name); } buf.End(); @@ -583,28 +587,28 @@ bool trpgTransform::Write(trpgWriteBuffer &buf) 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]); - if ( !buf.isEmpty() ) { - char nm[1024] = {0}; - buf.Get(nm,1024); - SetName(nm); - } + 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 false; } 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() @@ -650,9 +654,9 @@ 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]; + for (int j=0;j<4;j++) + // Note: is this right? + rm[i*4+j] = m[i][j]; return true; } @@ -660,13 +664,13 @@ bool trpgModelRef::GetMatrix(float64 *rm) const bool trpgModelRef::Write(trpgWriteBuffer &buf) { if (!isValid()) - return false; - + 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]); + for (int j=0;j<4;j++) + buf.Add(m[i][j]); buf.End(); return true; @@ -676,14 +680,15 @@ bool trpgModelRef::Write(trpgWriteBuffer &buf) 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]); + 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; + return false; } valid = true; @@ -691,10 +696,10 @@ bool trpgModelRef::Read(trpgReadBuffer &buf) } /* 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() @@ -713,8 +718,8 @@ void trpgAttach::Reset() parentID = -1; childPos = -1; if ( name ) { - delete [] name; - name = 0; + delete [] name; + name = 0; } } @@ -762,7 +767,7 @@ bool trpgAttach::Write(trpgWriteBuffer &buf) buf.Add(childPos); if ( name && strlen(name) ) { - buf.Add(name); + buf.Add(name); } buf.End(); @@ -774,22 +779,165 @@ bool trpgAttach::Write(trpgWriteBuffer &buf) 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; - if ( !buf.isEmpty() ) { - char nm[1024] = {0}; - buf.Get(nm,1024); - SetName(nm); - } + 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 false; } return true; } + +/* ChildRef Node + You'll find in the parent tile one of these for each tile children. + It gives the children grid location and file address. +*/ + +// Constructor +trpgChildRef::trpgChildRef() +{ + Reset(); +} +trpgChildRef::~trpgChildRef() +{ + Reset(); +} + +// Reset +void trpgChildRef::Reset() +{ + x = -1; + y = -1; + lod = -1; + addr.file = -1; + addr.offset = -1; +} + +void trpgChildRef::SetTileLoc(int gx,int gy,int glod) +{ + x = gx; + y = gy; + lod = glod; +} + +bool trpgChildRef::GetTileLoc(int &gx,int &gy,int &glod) const +{ + if (!isValid()) return false; + + gx = x; + gy = y; + glod = lod; + + return true; +} + +void trpgChildRef::SetTileAddress(const trpgwAppAddress& gAddr) +{ + addr = gAddr; +} +void trpgChildRef::SetTileAddress(int32 file, int32 offset) +{ + addr.file = file; + addr.offset = offset; +} +bool trpgChildRef::GetTileAddress(int32& file, int32& offset) const +{ + if (!isValid()) return false; + + file = addr.file; + offset = addr.offset; + + return true; + +} + +bool trpgChildRef::GetTileAddress(trpgwAppAddress& gAddr) const +{ + if (!isValid()) return false; + + gAddr = addr; + + return true; +} + +void trpgChildRef::SetTileZValue( float gZmin, float gZmax) +{ + zmin = gZmin; + zmax = gZmax; +} + +bool trpgChildRef::GetTileZValue( float& gZmin, float& gZmax) const +{ + if (!isValid()) return false; + + gZmin = zmin; + gZmax = zmax; + + return true; +} + + +// Validity check +bool trpgChildRef::isValid() const +{ + if (lod < 0) + return false; + return true; +} + + +// Write Attach node +bool trpgChildRef::Write(trpgWriteBuffer &buf) +{ + if (!isValid()) return false; + + buf.Begin(TRPG_CHILDREF); + + buf.Add(lod); + buf.Add(x); + buf.Add(y); + buf.Add(addr.file); + buf.Add(addr.offset); + buf.Add(zmin); + buf.Add(zmax); + + buf.End(); + + return true; +} + +// Read Attach node +bool trpgChildRef::Read(trpgReadBuffer &buf) +{ + try + { + + buf.Get(lod); + if (lod < 0) throw 1; + buf.Get(x); + buf.Get(y); + buf.Get(addr.file); + buf.Get(addr.offset); + buf.Get(zmin); + buf.Get(zmax); + + } + catch (...) + { + return false; + } + + return true; +} + diff --git a/src/osgPlugins/txp/trpage_parse.cpp b/src/osgPlugins/txp/trpage_parse.cpp index 506c462ef..c57f9fa09 100644 --- a/src/osgPlugins/txp/trpage_parse.cpp +++ b/src/osgPlugins/txp/trpage_parse.cpp @@ -17,23 +17,23 @@ #include /* trpage_parse.cpp - This source file contains methods for the trpgr_Parser and trpgr_Token classes. - trpgr_Parser is the main class. It parses the basic structure of paging archive - data out of Read Buffers. You should not need to change this. - If you want to parse data out of a different structure instead, look at - subclassing trpgReadBuffer and replacing its virtual methods. That's what - trpgMemReadBuffer is doing. - - This file also contains the implementation of trpgSceneParser(). - That class implements a set of callbacks for handling the Pushes and Pops - in an archive. You fill in the Start/EndChildren callbacks and register - for the rest of the tokens that you want. - */ + This source file contains methods for the trpgr_Parser and trpgr_Token classes. + trpgr_Parser is the main class. It parses the basic structure of paging archive + data out of Read Buffers. You should not need to change this. + If you want to parse data out of a different structure instead, look at + subclassing trpgReadBuffer and replacing its virtual methods. That's what + trpgMemReadBuffer is doing. + + This file also contains the implementation of trpgSceneParser(). + That class implements a set of callbacks for handling the Pushes and Pops + in an archive. You fill in the Start/EndChildren callbacks and register + for the rest of the tokens that you want. +*/ #include /* *************************** - Paging token callback structure + Paging token callback structure *************************** */ trpgr_Token::trpgr_Token() @@ -59,13 +59,13 @@ void trpgr_Token::init(int in_tok,trpgr_Callback *in_cb,bool in_dest) void trpgr_Token::Destruct() { if (cb && destroy) - delete cb; + delete cb; cb = NULL; destroy = true; } /* *************************** - Paging parser implementation. + Paging parser implementation. *************************** */ @@ -98,10 +98,10 @@ class WriteWrapper : public trpgr_Callback { public: WriteWrapper(trpgReadWriteable *in_wr) { wr = in_wr; }; void *Parse(trpgToken,trpgReadBuffer &buf) { - if (wr->Read(buf)) - return wr; - else - return NULL; + if (wr->Read(buf)) + return wr; + else + return NULL; } protected: trpgReadWriteable *wr; @@ -114,6 +114,25 @@ void trpgr_Parser::AddCallback(trpgToken tok,trpgReadWriteable *wr) AddCallback(tok,new WriteWrapper(wr),true); } +// Get the claaback associated with a token, will return 0 if none +const trpgr_Callback *trpgr_Parser::GetCallback(trpgToken tok) const +{ + tok_map::const_iterator iter = tokenMap.find(tok); + if(iter != tokenMap.end()) + return iter->second.cb; + else + return 0; +} +trpgr_Callback *trpgr_Parser::GetCallback(trpgToken tok) +{ + tok_map::iterator iter = tokenMap.find(tok); + if(iter != tokenMap.end()) + return iter->second.cb; + else + return 0; +} + + // Remove Callback void trpgr_Parser::RemoveCallback(trpgToken tok) { @@ -129,13 +148,13 @@ void trpgr_Parser::SetDefaultCallback(trpgr_Callback *cb,bool in_dest) } /* Token Is Valid - Checks if something *could be* a token. - Doesn't necessarily mean that it is. - */ + Checks if something *could be* a token. + Doesn't necessarily mean that it is. +*/ bool trpgr_Parser::TokenIsValid(trpgToken tok) { if (tok < 0) - return false; + return false; return true; } @@ -144,97 +163,112 @@ bool trpgr_Parser::TokenIsValid(trpgToken tok) This runs through the given buffer parsing token sets until it (1) runs out of buffer or (2) fails. Note: Good place to return an exception, but keep it simple for now. - */ +*/ bool trpgr_Parser::Parse(trpgReadBuffer &buf) { bool ret = true; - try { - while (!buf.isEmpty()) { - /* We're expecting the following - Token (int32) - Length (int32) - Data (variable) - */ - trpgToken tok; - int32 len; - if (!buf.Get(tok)) throw 1; - // Push and Pop are special - no data - if (tok != TRPG_PUSH && tok != TRPG_POP) { - if (!buf.Get(len)) throw 1; - if (!TokenIsValid(tok)) throw 1; - if (len < 0) throw 1; - // Limit what we're reading to the length of this - buf.PushLimit(len); - } + try + { + while (!buf.isEmpty()) + { + /* We're expecting the following + Token (int32) + Length (int32) + Data (variable) + */ + trpgToken tok; + int32 len; + if (!buf.Get(tok)) throw 1; + // Push and Pop are special - no data + if (tok != TRPG_PUSH && tok != TRPG_POP) + { + if (!buf.Get(len)) throw 1; + if (!TokenIsValid(tok)) throw 1; + if (len < 0) throw 1; + // Limit what we're reading to the length of this + buf.PushLimit(len); + } - // Call our token handler for this one - try { - const trpgr_Token *tcb = NULL; - tok_map::const_iterator p = tokenMap.find(tok); - if (p != tokenMap.end()) - tcb = &(*p).second; - if (!tcb) - // No such token, call the default - tcb = &defCb; + // Call our token handler for this one + try + { + const trpgr_Token *tcb = NULL; + tok_map::const_iterator p = tokenMap.find(tok); + if (p != tokenMap.end()) + tcb = &(*p).second; + if (!tcb) + // No such token, call the default + tcb = &defCb; - // Run the callback - if (tcb->cb) { - void *ret = tcb->cb->Parse(tok,buf); - // Note: Do something with the return value - lastObject = ret; - } - } - catch (...) { - // Don't want to screw up the limit stack - } - // No limit to worry about with push and pop - if (tok != TRPG_PUSH && tok != TRPG_POP) { - buf.SkipToLimit(); - buf.PopLimit(); - } - } + // Run the callback + if (tcb->cb) + { + void *ret = tcb->cb->Parse(tok,buf); + // Note: Do something with the return value + lastObject = ret; + } + } + catch (...) + { + // Don't want to screw up the limit stack + } + // No limit to worry about with push and pop + if (tok != TRPG_PUSH && tok != TRPG_POP) + { + buf.SkipToLimit(); + buf.PopLimit(); + } + } } - catch (...) { - // Failed to parse. - ret = false; + catch (...) + { + // Failed to parse. + ret = false; } return ret; } -/* **************** - Scene Parser - **************** - */ +/* **************** + Scene Parser + **************** + */ // Helper - callback for Push -class trpgSceneHelperPush : public trpgr_Callback { +class trpgSceneHelperPush : public trpgr_Callback +{ public: - trpgSceneHelperPush(trpgSceneParser *in_parse) { parse = in_parse; }; - void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) { - // Call the start children callback - parse->StartChildren(parse->lastObject); - parse->parents.push_back(parse->lastObject); - return (void *)1; + trpgSceneHelperPush(trpgSceneParser *in_parse) + { parse = in_parse; }; + + void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) + { + // Call the start children callback + parse->StartChildren(parse->lastObject); + parse->parents.push_back(parse->lastObject); + return (void *)1; } protected: trpgSceneParser *parse; }; // Helper - callback for Pop -class trpgSceneHelperPop : public trpgr_Callback { +class trpgSceneHelperPop : public trpgr_Callback +{ public: - trpgSceneHelperPop(trpgSceneParser *in_parse) { parse = in_parse; }; - void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) { - // Make sure we don't have an extra pop - if (parse->parents.size() == 0) - // Note: let someone know about the extra pop - return NULL; - // Call the end children callback - int len = parse->parents.size(); - parse->EndChildren(parse->parents[len-1]); - parse->parents.resize(len-1); - return (void *)1; + trpgSceneHelperPop(trpgSceneParser *in_parse) + { parse = in_parse; }; + void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) + { + // Make sure we don't have an extra pop + if (parse->parents.size() == 0) + // Note: let someone know about the extra pop + return NULL; + // Call the end children callback + int len = parse->parents.size(); + parse->EndChildren(parse->parents[len-1]); + parse->parents.resize(len-1); + return (void *)1; } protected: trpgSceneParser *parse; @@ -243,12 +277,14 @@ protected: // Helper - default callback // Puts a 1 on the parent stack // Note: Need to use this fact above -class trpgSceneHelperDefault : public trpgr_Callback { +class trpgSceneHelperDefault : public trpgr_Callback +{ public: trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; } - void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) { - // Absorb it quietly - return (void *)1; + void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/) + { + // Absorb it quietly + return (void *)1; } protected: trpgSceneParser *parse; diff --git a/src/osgPlugins/txp/trpage_pparse.cpp b/src/osgPlugins/txp/trpage_pparse.cpp index 7eff33382..627b3823e 100644 --- a/src/osgPlugins/txp/trpage_pparse.cpp +++ b/src/osgPlugins/txp/trpage_pparse.cpp @@ -18,183 +18,293 @@ #include /* trpage_pparse.cpp - This file contains classes that can parse a TerraPage - archive for the purpose of printing it out. + This file contains classes that can parse a TerraPage + archive for the purpose of printing it out. */ #include #include +#include + +namespace +{ + // This will recursivelly call itself up until + // all the tiule are done + void printBuf(int lod, int x, int y, trpgr_Archive *archive, trpgPrintGraphParser& parser, trpgMemReadBuffer &buf, trpgPrintBuffer &pBuf) + { + char ls[1024]; + sprintf(ls,"Tile (lod) (x,y) = (%d) (%d,%d)", lod, x, y); + pBuf.prnLine(ls); + pBuf.IncreaseIndent(); + parser.Reset(); + parser.Parse(buf); + pBuf.DecreaseIndent(); + + // Save the list +// std::vector childRefList; +// The const in the template parameter was removed because it causes GCC to +// freak out. I am of the opinion that const doesn't make sense in a template +// parameter for std::vector anyway... const prevents you from changing the +// value, so what exactly is the point? How does one add entries to the vector +// without giving them a value? -ADS + std::vector childRefList; + for(unsigned int idx =0; idx < parser.GetNbChildrenRef(); idx++) + childRefList.push_back(*parser.GetChildRef(idx)); + + + for(unsigned int idx =0; idx < childRefList.size(); idx++) + { + const trpgChildRef& childRef = childRefList[idx]; + trpgMemReadBuffer childBuf(archive->GetEndian()); + trpgwAppAddress tileAddr; + int glod, gx, gy; + + childRef.GetTileAddress(tileAddr); + childRef.GetTileLoc(gx,gy,glod); + + trpgTileTable::TileMode mode; + archive->GetTileTable()->GetMode(mode); + bool status; + if(mode == trpgTileTable::Local) + status = archive->ReadTile(tileAddr, childBuf); + else + status = archive->ReadExternalTile(gx, gy, glod, childBuf); + + if(status) + printBuf(glod, gx, gy, archive, parser, childBuf, pBuf); + + } + } +} // end namespace + + + + + + + + /* Set up the callbacks for the scene graph parser. - In our case this is just one read helper with - a switch statement. + In our case this is just one read helper with + a switch statement. */ -trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelper *inImg,trpgPrintBuffer *inBuf) +trpgPrintGraphParser::trpgPrintGraphParser(trpgr_Archive *inArch,trpgrImageHelper *inImg,trpgPrintBuffer *inBuf):printBuf(inBuf), archive(inArch), imageHelp(inImg), childRefCB(0) { - printBuf = inBuf; - archive = inArch; - imageHelp = inImg; - - // Register the readers - AddCallback(TRPG_GEOMETRY,new ReadHelper(this,printBuf)); - AddCallback(TRPG_GROUP,new ReadHelper(this,printBuf)); - AddCallback(TRPG_ATTACH,new ReadHelper(this,printBuf)); - AddCallback(TRPG_BILLBOARD,new ReadHelper(this,printBuf)); - AddCallback(TRPG_LOD,new ReadHelper(this,printBuf)); - AddCallback(TRPG_TRANSFORM,new ReadHelper(this,printBuf)); - AddCallback(TRPG_MODELREF,new ReadHelper(this,printBuf)); - AddCallback(TRPG_LAYER,new ReadHelper(this,printBuf)); - AddCallback(TRPG_LIGHT,new ReadHelper(this,printBuf)); - AddCallback(TRPG_LABEL,new ReadHelper(this,printBuf)); - AddCallback(TRPGTILEHEADER,new ReadHelper(this,printBuf)); + // Register the readers + AddCallback(TRPG_GEOMETRY,new ReadHelper(this,printBuf)); + AddCallback(TRPG_GROUP,new ReadHelper(this,printBuf)); + AddCallback(TRPG_ATTACH,new ReadHelper(this,printBuf)); + AddCallback(TRPG_CHILDREF,new ReadHelper(this,printBuf)); + AddCallback(TRPG_BILLBOARD,new ReadHelper(this,printBuf)); + AddCallback(TRPG_LOD,new ReadHelper(this,printBuf)); + AddCallback(TRPG_TRANSFORM,new ReadHelper(this,printBuf)); + AddCallback(TRPG_MODELREF,new ReadHelper(this,printBuf)); + AddCallback(TRPG_LAYER,new ReadHelper(this,printBuf)); + AddCallback(TRPG_LIGHT,new ReadHelper(this,printBuf)); + AddCallback(TRPG_LABEL,new ReadHelper(this,printBuf)); + AddCallback(TRPGTILEHEADER,new ReadHelper(this,printBuf)); + + childRefCB = dynamic_cast(GetCallback(TRPG_CHILDREF)); } /* Start Children is called when the parser hits a Push - in the read buffer. We just want to indent further when - that happens. + in the read buffer. We just want to indent further when + that happens. */ bool trpgPrintGraphParser::StartChildren(void *) { - printBuf->IncreaseIndent(); + printBuf->IncreaseIndent(); - return true; + return true; } /* End Children is called when the parser hits a Pop - in the read buffer. We just want to reduce the indent - when that happens. + in the read buffer. We just want to reduce the indent + when that happens. */ bool trpgPrintGraphParser::EndChildren(void *) { - printBuf->DecreaseIndent(); + printBuf->DecreaseIndent(); - return true; + return true; +} + +unsigned int trpgPrintGraphParser::GetNbChildrenRef() const +{ + if(childRefCB) + return childRefCB->GetNbChildrenRef(); + else + return 0; +} + +const trpgChildRef* trpgPrintGraphParser::GetChildRef(unsigned int idx) const +{ + if(childRefCB) + return childRefCB->GetChildRef(idx); + else + return 0; + +} + + + +void trpgPrintGraphParser::Reset() +{ + if(childRefCB) + childRefCB->Reset(); +} + +void trpgPrintGraphParser::ReadHelper::Reset() +{ + childRefList.clear(); +} + +unsigned int trpgPrintGraphParser::ReadHelper::GetNbChildrenRef() const +{ + return childRefList.size(); +} +const trpgChildRef* trpgPrintGraphParser::ReadHelper::GetChildRef(unsigned int idx) const +{ + if(idx >= childRefList.size()) + return 0; + else + return &childRefList[idx]; } /* Read Helper parse method sets up the correct class depending - on the token and asks it to read and print itself. + on the token and asks it to read and print itself. It will save + any child ref node encountered that a user can access to continue + traversal. */ void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf) { - trpgReadWriteable *obj = NULL; - trpgTileHeader *tileHead = NULL; + // This will celar any child ref list from a previous parse. + trpgReadWriteable *obj = NULL; + trpgTileHeader *tileHead = NULL; - switch (tok) { - case TRPG_GEOMETRY: - obj = new trpgGeometry(); - break; - case TRPG_GROUP: - obj = new trpgGroup(); - break; - case TRPG_ATTACH: - obj = new trpgAttach(); - break; - case TRPG_BILLBOARD: - obj = new trpgBillboard(); - break; - case TRPG_LOD: - obj = new trpgLod(); - break; - case TRPG_TRANSFORM: - obj = new trpgTransform(); - break; - case TRPG_MODELREF: - obj = new trpgModelRef(); - break; - case TRPG_LAYER: - obj = new trpgLayer(); - break; - case TRPG_LIGHT: - obj = new trpgLight(); - break; - case TRPG_LABEL: - obj = new trpgLabel(); - break; + switch (tok) { + case TRPG_GEOMETRY: + obj = new trpgGeometry(); + break; + case TRPG_GROUP: + obj = new trpgGroup(); + break; + case TRPG_ATTACH: + obj = new trpgAttach(); + break; + case TRPG_CHILDREF: + childRefList.push_back(trpgChildRef()); + obj = &childRefList.back(); + break; + case TRPG_BILLBOARD: + obj = new trpgBillboard(); + break; + case TRPG_LOD: + obj = new trpgLod(); + break; + case TRPG_TRANSFORM: + obj = new trpgTransform(); + break; + case TRPG_MODELREF: + obj = new trpgModelRef(); + break; + case TRPG_LAYER: + obj = new trpgLayer(); + break; + case TRPG_LIGHT: + obj = new trpgLight(); + break; + case TRPG_LABEL: + obj = new trpgLabel(); + break; - case TRPGTILEHEADER: - obj = tileHead = new trpgTileHeader(); - break; - }; + case TRPGTILEHEADER: + obj = tileHead = new trpgTileHeader(); + break; + }; - if (obj) { - if (obj->Read(buf)) - obj->Print(*pBuf); - // For the tile header, do a little more work - if (tok == TRPGTILEHEADER) { - int numMat; - tileHead->GetNumLocalMaterial(numMat); - for (int i=0;iGetLocalMaterial(i,locMat); - const trpgMaterial *baseMat; - const trpgTexture *baseTex; - int totSize; - trpgrImageHelper *imageHelp = parse->GetImageHelp(); - int numImages=1; - locMat.GetNumLocals(numImages); - for (int imgN=0;imgNGetNthImageInfoForLocalMat(&locMat,imgN,&baseMat,&baseTex,totSize); + if (obj) { + if (obj->Read(buf)) + obj->Print(*pBuf); + // For the tile header, do a little more work + if (tok == TRPGTILEHEADER) { + int numMat; + tileHead->GetNumLocalMaterial(numMat); + for (int i=0;iGetLocalMaterial(i,locMat); + const trpgMaterial *baseMat; + const trpgTexture *baseTex; + int totSize; + trpgrImageHelper *imageHelp = parse->GetImageHelp(); + int numImages=1; + locMat.GetNumLocals(numImages); + for (int imgN=0;imgNGetNthImageInfoForLocalMat(&locMat,imgN,&baseMat,&baseTex,totSize); - // Fetch the whole image - { - char *pixels = new char[totSize]; - bool failed = false; - try { - failed = !imageHelp->GetNthImageForLocalMat(&locMat,imgN,pixels,totSize); - } - catch (...) { - failed = true; - } - if (failed) { - fprintf(stderr,"Failed to read local image %d from local material %d.\n",imgN,i); - } else - fprintf(stderr,"Read local image %d from local material %d successfully.\n",imgN,i); - delete [] pixels; - } + // Fetch the whole image + { + char *pixels = new char[totSize]; + bool failed = false; + try { + failed = !imageHelp->GetNthImageForLocalMat(&locMat,imgN,pixels,totSize); + } + catch (...) { + failed = true; + } + if (failed) { + fprintf(stderr,"Failed to read local image %d from local material %d.\n",imgN,i); + } else + fprintf(stderr,"Read local image %d from local material %d successfully.\n",imgN,i); + delete [] pixels; + } - // Fetch the individual mipmap levels - { - int numMipmap; - bool hasMipmap; - baseTex->GetIsMipmap(hasMipmap); - numMipmap = hasMipmap ? baseTex->CalcNumMipmaps() : 0; - for (int j=1;j(baseTex))->MipLevelOffset(j); - int mipSize = (const_cast(baseTex))->MipLevelSize(j); - if (mipSize) { - char *pixels = new char[mipSize]; - bool failed = false; - try { - failed = !imageHelp->GetNthImageMipLevelForLocalMat(j,&locMat,imgN,pixels,mipSize); - } - catch (...) { - failed = true; - } - if (failed) - fprintf(stderr,"Failed to read mipmap level %d for local image %d from local material %d.\n",j,imgN,i); - else - fprintf(stderr,"Read mipmap level %d for local image %d from local material %d.\n",j,imgN,i); - delete [] pixels; - } - } - } - } - } - } + // Fetch the individual mipmap levels + { + int numMipmap; + bool hasMipmap; + baseTex->GetIsMipmap(hasMipmap); + numMipmap = hasMipmap ? baseTex->CalcNumMipmaps() : 0; + for (int j=1;j(baseTex))->MipLevelOffset(j); + int mipSize = (const_cast(baseTex))->MipLevelSize(j); + if (mipSize) { + char *pixels = new char[mipSize]; + bool failed = false; + try { + failed = !imageHelp->GetNthImageMipLevelForLocalMat(j,&locMat,imgN,pixels,mipSize); + } + catch (...) { + failed = true; + } + if (failed) + fprintf(stderr,"Failed to read mipmap level %d for local image %d from local material %d.\n",j,imgN,i); + else + fprintf(stderr,"Read mipmap level %d for local image %d from local material %d.\n",j,imgN,i); + delete [] pixels; + } + } + } + } + } + } - delete obj; - } + // We delete all object except the child ref node + if(tok != TRPG_CHILDREF) + delete obj; + } - // Need to return non-zero. Otherwise it's interpreted as an error - return (void *)1; + // Need to return non-zero. Otherwise it's interpreted as an error + return (void *)1; } // The following routine is not compiled if there's no _splitpath #ifdef _splitpath /* This is a convenience function to print out the contents - of an entire TerraPage archive. + of an entire TerraPage archive. There are two versions of this function. The first takes a file name and the second an opened archive where the header @@ -202,88 +312,120 @@ void *trpgPrintGraphParser::ReadHelper::Parse(trpgToken tok,trpgReadBuffer &buf) */ bool trpgPrintArchive(char *filename,trpgPrintBuffer &pBuf,int flags) { - trpgr_Archive archive; + trpgr_Archive archive; - // Break path apart so we can find the directory - char drive[100],dir[1024],fname[1024],ext[1024]; - _splitpath(filename,drive,dir,fname,ext); + // Break path apart so we can find the directory + char drive[100],dir[1024],fname[1024],ext[1024]; + _splitpath(filename,drive,dir,fname,ext); - char rname[1024],baseDir[1024]; - sprintf(baseDir,"%s%s",drive,dir); - sprintf(rname,"%s%s",fname,ext); + char rname[1024],baseDir[1024]; + sprintf(baseDir,"%s%s",drive,dir); + sprintf(rname,"%s%s",fname,ext); - if (!*baseDir) strcpy(baseDir,"."); - archive.SetDirectory(baseDir); - if (!archive.OpenFile(rname)) { - fprintf(stdout,"Failed to open archive.\n"); - return false; - } - if (!archive.ReadHeader()) { - fprintf(stdout,"Failed to read header.\n"); - return false; - } + if (!*baseDir) strcpy(baseDir,"."); + archive.SetDirectory(baseDir); + if (!archive.OpenFile(rname)) { + fprintf(stdout,"Failed to open archive.\n"); + return false; + } + if (!archive.ReadHeader()) { + fprintf(stdout,"Failed to read header.\n"); + return false; + } - bool status = trpgPrintArchive(&archive,pBuff,flags); - return status; + bool status = trpgPrintArchive(&archive,pBuff,flags); + return status; } #endif bool trpgPrintArchive(trpgr_Archive *archive,trpgPrintBuffer &pBuf,int flags) { - char ls[1024]; + char ls[1024]; - if (!archive->isValid()) return false; - - pBuf.prnLine("====Header Structures===="); + if (!archive->isValid()) return false; + + pBuf.prnLine("====Header Structures===="); - // Print out the header portion - archive->GetHeader()->Print(pBuf); - archive->GetMaterialTable()->Print(pBuf); - archive->GetTexTable()->Print(pBuf); - archive->GetModelTable()->Print(pBuf); - archive->GetTileTable()->Print(pBuf); - archive->GetLightTable()->Print(pBuf); - archive->GetRangeTable()->Print(pBuf); - archive->GetTextStyleTable()->Print(pBuf); - archive->GetSupportStyleTable()->Print(pBuf); - archive->GetLabelPropertyTable()->Print(pBuf); - pBuf.prnLine(); + // Print out the header portion + archive->GetHeader()->Print(pBuf); + archive->GetMaterialTable()->Print(pBuf); + archive->GetTexTable()->Print(pBuf); + archive->GetModelTable()->Print(pBuf); + archive->GetTileTable()->Print(pBuf); + archive->GetLightTable()->Print(pBuf); + archive->GetRangeTable()->Print(pBuf); + archive->GetTextStyleTable()->Print(pBuf); + archive->GetSupportStyleTable()->Print(pBuf); + archive->GetLabelPropertyTable()->Print(pBuf); + pBuf.prnLine(); - // Read the local images and do the math for the templates + // Read the local images and do the math for the templates - // Now do the tiles - if (!archive->isValid()) return false; + // Now do the tiles + if (!archive->isValid()) return false; - // Parser that prints out a tile scene graph - trpgrImageHelper imageHelp(archive->GetEndian(),archive->getDir(),*archive->GetMaterialTable(), - *archive->GetTexTable()); - trpgPrintGraphParser parser(archive,&imageHelp,&pBuf); + int majorVersion, minorVersion; + archive->GetHeader()->GetVersion(majorVersion, minorVersion); - pBuf.prnLine("====Tile Data===="); - int nl,x,y; - trpgMemReadBuffer buf(archive->GetEndian()); - // Iterate over the terrain lods - int numLod; - archive->GetHeader()->GetNumLods(numLod); - trpg2iPoint tileSize; - for (nl=0;nlGetHeader()->GetLodSize(nl,tileSize); - // Iterate over the tiles - for (x=tileSize.x-1;x>=0;x--) - for (y=0;yReadTile(x,y,nl,buf)) { - if (flags & TRPGPRN_BODY) { - pBuf.IncreaseIndent(); - // Parse it (also prints it - parser.Parse(buf); - pBuf.DecreaseIndent(); - } - } else - pBuf.prnLine(" Couldn't read tile."); - } - } + // Parser that prints out a tile scene graph + trpgrImageHelper* imageHelp=archive->GetNewRImageHelper(archive->GetEndian(),archive->getDir(), + *archive->GetMaterialTable(),*archive->GetTexTable()); - return true; + trpgPrintGraphParser parser(archive,imageHelp,&pBuf); + + pBuf.prnLine("====Tile Data===="); + int nl,x,y; + trpgMemReadBuffer buf(archive->GetEndian()); + // Iterate over the terrain lods + int numLod; + archive->GetHeader()->GetNumLods(numLod); + trpg2iPoint tileSize; + if(majorVersion == 2 && minorVersion >= 1) + { + // Version 2.1 + // Because of variable lod support in version 2.1 and over, we can + // no longer suppose that all lod level are all populated with tiles + // in all of the gaming area. We have to parse the parent to know that. + // Also the tile table only contains lod 0 tiles so we can no longer access + // the tile directly from its grid location. So we have to traverse. + trpg2iPoint blockTileSize; + if(archive->GetHeader()->GetLodSize(0,blockTileSize)) { + for(x = 0; x < blockTileSize.x; x++) + for( y = 0; y < blockTileSize.y; y++) + if (archive->ReadTile(x,y,0,buf)) + printBuf(0, x, y, archive, parser, buf, pBuf); + + } + + } + else + { + for (nl=0;nlGetHeader()->GetLodSize(nl,tileSize); + // Iterate over the tiles + for (x=tileSize.x-1;x>=0;x--) + for (y=0;yReadTile(x,y,nl,buf)) { + if (flags & TRPGPRN_BODY) { + pBuf.IncreaseIndent(); + // Parse it (also prints it + if (!parser.Parse(buf)) + { + char errString[80]; + sprintf(errString, "**** Warning: tile anomaly detected: (%d) (%d,%d) ****",nl,x,y); + // send it both ways so it's easier to spot + pBuf.prnLine(errString); + fprintf(stderr,"%s\n",errString); + } + pBuf.DecreaseIndent(); + } + } else + pBuf.prnLine(" Couldn't read tile."); + } + } + } + + return true; } diff --git a/src/osgPlugins/txp/trpage_print.cpp b/src/osgPlugins/txp/trpage_print.cpp index 9ab53ec2d..aac21a8f5 100644 --- a/src/osgPlugins/txp/trpage_print.cpp +++ b/src/osgPlugins/txp/trpage_print.cpp @@ -18,20 +18,20 @@ #include /* trpage_print.cpp - Print out the contents of a TerraPage archive. - This module provides an example of how to access each of the classes - within a TerraPage archive. - */ + Print out the contents of a TerraPage archive. + This module provides an example of how to access each of the classes + within a TerraPage archive. +*/ #include /* ****************************************** Print Buffer implementation - The print buffer is a way to dump debugging data out - to a file (or console). You can make your own subclass - of trpgPrintBuffer if you have specific needs. + The print buffer is a way to dump debugging data out + to a file (or console). You can make your own subclass + of trpgPrintBuffer if you have specific needs. ****************************************** - */ + */ trpgPrintBuffer::trpgPrintBuffer() { @@ -96,7 +96,8 @@ bool trpgFilePrintBuffer::prnLine(char *str) if (!fp) return false; - if (str) { + if (str) + { fprintf(fp,indentStr); fprintf(fp,str); fprintf(fp,"\n"); @@ -112,7 +113,7 @@ bool trpgFilePrintBuffer::prnLine(char *str) is readable/writeable are here. These are used for debugging. ************************************* - */ + */ /* Print out the header information. */ @@ -122,14 +123,20 @@ bool trpgHeader::Print(trpgPrintBuffer &buf) const buf.prnLine("----Archive Header----"); buf.IncreaseIndent(); sprintf(ls,"verMinor = %d, verMajor = %d",verMinor,verMajor); buf.prnLine(ls); + if((verMajor >= TRPG_NOMERGE_VERSION_MAJOR) && (verMinor >=TRPG_NOMERGE_VERSION_MINOR)) + { + sprintf(ls,"isMaster = %s, numRows = %d, numCols = %d",GetIsMaster()?"YES":"NO",rows,cols); buf.prnLine(ls); + } sprintf(ls,"dbVerMinor = %d, dbVerMajor = %d",dbVerMinor,dbVerMajor); buf.prnLine(ls); + sprintf(ls,"maxGroupID = %d",maxGroupID); buf.prnLine(ls); sprintf(ls,"sw = (%f,%f), ne = (%f,%f)",sw.x,sw.y,ne.x,ne.y); buf.prnLine(ls); sprintf(ls,"tileType = %d, origin = (%f,%f,%f)",tileType,origin.x,origin.y,origin.z); buf.prnLine(ls); sprintf(ls,"numLods = %d",numLods); buf.prnLine(ls); buf.IncreaseIndent(); - for (int i=0;i(this))->GetMaterialRef(j,i); - mat->Print(buf); + MaterialMapType::const_iterator itr = materialMap.begin(); + for ( ; itr != materialMap.end( ); itr++) + { + const trpgMaterial *mat; + sprintf(ls,"Material %d",itr->first); buf.prnLine(ls); + mat = (const_cast(this))->GetMaterialRef(0,itr->first); + if(!mat) + { + sprintf(ls,"Error: Unable to load material!"); buf.prnLine(ls); } - buf.DecreaseIndent(); + else + mat->Print(buf); } buf.DecreaseIndent(2); @@ -227,9 +237,10 @@ bool trpgTexture::Print(trpgPrintBuffer &buf) const sprintf(ls,"Name = %s",name); buf.prnLine(ls); sprintf(ls,"useCount = %d",useCount); buf.prnLine(ls); sprintf(ls,"sizeX = %d, sizeY = %d, sizeZ = %d",sizeX,sizeY,numLayer); buf.prnLine(ls); - sprintf(ls,"sensor band organization = %d",org); buf.prnLine(ls); +// sprintf(ls,"sensor band organization = %d",org); buf.prnLine(ls); // does this need to be added? sprintf(ls,"ismipmap = %d",isMipmap); buf.prnLine(ls); sprintf(ls,"addr.file = %d, addr.offset = %d",addr.file,addr.offset); buf.prnLine(ls); + sprintf(ls,"addr.col = %d, addr.row = %d",addr.col,addr.row); buf.prnLine(ls); buf.DecreaseIndent(); buf.prnLine(); @@ -245,9 +256,11 @@ bool trpgTexTable::Print(trpgPrintBuffer &buf) const buf.prnLine("----Texture Table----"); buf.IncreaseIndent(); - for (unsigned int i=0;ifirst); buf.prnLine(ls); + itr->second.Print(buf); } buf.DecreaseIndent(); @@ -264,9 +277,11 @@ bool trpgModelTable::Print(trpgPrintBuffer &buf) const buf.prnLine("----Model Table----"); buf.IncreaseIndent(); - for (unsigned int i=0;ifirst); buf.prnLine(ls); + itr->second.Print(buf); } buf.DecreaseIndent(); @@ -284,7 +299,8 @@ bool trpgModel::Print(trpgPrintBuffer &buf) const buf.prnLine("----Model----"); buf.IncreaseIndent(); sprintf(ls,"type = %d",type); buf.prnLine(ls); - if (name) { + if (name) + { sprintf(ls,"name = %s",name); buf.prnLine(ls); } sprintf(ls,"diskRef = %d",(int)diskRef), buf.prnLine(ls); @@ -308,14 +324,16 @@ bool trpgTileHeader::Print(trpgPrintBuffer &buf) const sprintf(ls,"matList size = %d",static_cast(matList.size())); buf.prnLine(ls); buf.IncreaseIndent(); unsigned int i; - for (i=0;i(modelList.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (i=0;i(data.size())); buf.IncreaseIndent(); - for (unsigned int i=0;i(floatData.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (unsigned int i=0;i(doubleData.size())); buf.IncreaseIndent(); - for (unsigned int i=0;i(primLength.size())); buf.prnLine(ls); buf.IncreaseIndent(); ls[0] = 0; - for (i=0;i(vertDataFloat.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (i=0;i(vertDataDouble.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (i=0;i(normDataFloat.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (i=0;i(normDataDouble.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (i=0;i(colors.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (i=0;i(texData.size())); buf.IncreaseIndent(); - for (i=0;i(lodInfo.size())); buf.prnLine(ls); - for (unsigned int i=0;i (ex,ey) = (%d,%d) -> (%d,%d)",sx,sy,ex,ey); buf.prnLine(ls); sprintf(ls,"dest (width,height) = (%d,%d)",destWidth,destHeight); buf.prnLine(ls); - for (unsigned int i=0;ifirst); buf.prnLine(ls); + itr->second.Print(buf); } buf.DecreaseIndent(); buf.prnLine(); - + return true; } /* Print out a light node -*/ + */ bool trpgLight::Print(trpgPrintBuffer &buf) const { @@ -797,8 +878,8 @@ bool trpgLight::Print(trpgPrintBuffer &buf) const buf.prnLine("----Light----"); buf.IncreaseIndent(); - sprintf(ls,"Light Index = %d",index); buf.prnLine(ls); - sprintf(ls,"# Light Locations = %d",static_cast(lightPoints.size()) ); buf.prnLine(ls); + sprintf(ls,"Light Index = %d",index); buf.prnLine(ls); + sprintf(ls,"# Light Locations = %d",static_cast(lightPoints.size()) ); buf.prnLine(ls); buf.DecreaseIndent(); @@ -834,9 +915,11 @@ bool trpgRangeTable::Print(trpgPrintBuffer &buf) const buf.prnLine("----Range Table----"); buf.IncreaseIndent(); - for (unsigned int i=0;isecond.Print(buf); } buf.DecreaseIndent(); @@ -863,8 +946,9 @@ bool trpgLabel::Print(trpgPrintBuffer &buf) const sprintf(ls,"location: (%f %f %f)",location.x,location.y,location.z); buf.prnLine(ls); sprintf(ls,"%d support points",static_cast(supports.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (unsigned int i=0;i(styles.size())); buf.prnLine(ls); + sprintf(ls,"numStyle = %d",static_cast(styleMap.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (unsigned int i=0;isecond.Print(buf); } buf.DecreaseIndent(); buf.DecreaseIndent(); @@ -935,11 +1021,13 @@ bool trpgSupportStyleTable::Print(trpgPrintBuffer &buf) const buf.prnLine(); buf.prnLine("----Support Style Table----"); buf.IncreaseIndent(); - sprintf(ls,"numStyle = %d",static_cast(styles.size())); buf.prnLine(ls); + sprintf(ls,"numStyle = %d",static_cast(supportStyleMap.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (unsigned int i=0;isecond.Print(buf); } buf.DecreaseIndent(); buf.DecreaseIndent(); @@ -973,11 +1061,13 @@ bool trpgLabelPropertyTable::Print(trpgPrintBuffer &buf) const buf.prnLine(); buf.prnLine("----Label Property Table----"); buf.IncreaseIndent(); - sprintf(ls,"numProperty = %d",static_cast(properties.size())); buf.prnLine(ls); + sprintf(ls,"numProperty = %d",static_cast(labelPropertyMap.size())); buf.prnLine(ls); buf.IncreaseIndent(); - for (unsigned int i=0;isecond.Print(buf); } buf.DecreaseIndent(); buf.DecreaseIndent(); diff --git a/src/osgPlugins/txp/trpage_print.h b/src/osgPlugins/txp/trpage_print.h index 8e440ef58..8b3fbceb7 100644 --- a/src/osgPlugins/txp/trpage_print.h +++ b/src/osgPlugins/txp/trpage_print.h @@ -17,13 +17,16 @@ #define trpage_print_h_ #include +#include +#include /* Print Buffer for TerraPage. Subclasses of this object - are used to print out to stdout or disk (or whatever). - You won't create one of these directly, instead you'll create - something which inherits from it. + are used to print out to stdout or disk (or whatever). + You won't create one of these directly, instead you'll create + something which inherits from it. */ -TX_EXDECL class TX_CLDECL trpgPrintBuffer { +TX_EXDECL class TX_CLDECL trpgPrintBuffer +{ public: trpgPrintBuffer(void); virtual ~trpgPrintBuffer(void) { }; @@ -38,17 +41,17 @@ public: virtual void IncreaseIndent(int amount=1); // Decreases the current indentation by the amount given (defaults to one) virtual void DecreaseIndent(int amount=1); -protected: + protected: void updateIndent(void); int curIndent; char indentStr[200]; }; /* File print buffer for TerraPage. The file print buffer writes - debugging output to a file. - */ + debugging output to a file. +*/ TX_EXDECL class TX_CLDECL trpgFilePrintBuffer : public trpgPrintBuffer { -public: + public: // This class can be constructed with either a FILE pointer or a file name trpgFilePrintBuffer(FILE *); trpgFilePrintBuffer(char *); @@ -59,47 +62,83 @@ public: // For a file printer buffer, this writes a string out to a file bool prnLine(char *str = NULL); -protected: + protected: bool valid; bool isMine; FILE *fp; }; /* The Print Graph Parser is a scene graph parser that - prints out the scene graph as it goes. It's simpler - than the scene example in trpage_scene.cpp since it - isn't trying to build up a working scene graph. - */ -TX_EXDECL class TX_CLDECL trpgPrintGraphParser : public trpgSceneParser { -public: + prints out the scene graph as it goes. It's simpler + than the scene example in trpage_scene.cpp since it + isn't trying to build up a working scene graph. +*/ +TX_EXDECL class TX_CLDECL trpgPrintGraphParser : public trpgSceneParser +{ + public: trpgPrintGraphParser(trpgr_Archive *,trpgrImageHelper *,trpgPrintBuffer *); virtual ~trpgPrintGraphParser(void) { }; + // Clear all list and free associated pointer + void Reset(); + + // After parsing this will return the number of trpgChildRef node found. + unsigned int GetNbChildrenRef() const; + // This will return the trpgChildRef node pointer associated with the index. + // Will return 0 if index is out of bound + const trpgChildRef* GetChildRef(unsigned int idx) const; + /* The read helper class is the callback for all the various - token (node) types. Normally we would use a number of - these, probably one per token. However, since we're just - printing we can use a switch statement instead. - */ - class ReadHelper : public trpgr_Callback { + token (node) types. Normally we would use a number of + these, probably one per token. However, since we're just + printing we can use a switch statement instead. + */ + class ReadHelper : public trpgr_Callback + { public: - ReadHelper(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf) {pBuf = inBuf; parse = inPG;}; - void *Parse(trpgToken,trpgReadBuffer &buf); + // typedef std::vector ChildRefList; + // The const in the template parameter was removed because it causes GCC to + // freak out. I am of the opinion that const doesn't make sense in a template + // parameter for std::vector anyway... const prevents you from changing the + // value, so what exactly is the point? How does one add entries to the vector + // without giving them a value? -ADS + typedef std::vector ChildRefList; + + ReadHelper(trpgPrintGraphParser *inPG,trpgPrintBuffer *inBuf): pBuf(inBuf), parse(inPG) {} + ~ReadHelper() { Reset();} + + void *Parse(trpgToken,trpgReadBuffer &buf); + void Reset(); + // After parsing this will return the number of trpgChildRef node found. + unsigned int GetNbChildrenRef() const; + // This will return the trpgChildRef node associated with the index. + // this will retrun 0 if idx is out of bound + const trpgChildRef* GetChildRef(unsigned int idx) const; protected: - trpgPrintBuffer *pBuf; - trpgPrintGraphParser *parse; + trpgPrintBuffer *pBuf; + trpgPrintGraphParser *parse; + + private: + + ChildRefList childRefList; + + }; // Fetch the archive associated with this print trpgr_Archive *GetArchive() {return archive; }; trpgrImageHelper *GetImageHelp() {return imageHelp; }; - -protected: + + protected: bool StartChildren(void *); bool EndChildren(void *); trpgPrintBuffer *printBuf; trpgr_Archive *archive; trpgrImageHelper *imageHelp; + + ReadHelper *childRefCB; + }; // Print utitility for while archive diff --git a/src/osgPlugins/txp/trpage_range.cpp b/src/osgPlugins/txp/trpage_range.cpp index 107efe646..8a871ec3c 100644 --- a/src/osgPlugins/txp/trpage_range.cpp +++ b/src/osgPlugins/txp/trpage_range.cpp @@ -14,9 +14,9 @@ */ /* trpage_range.cpp - Methods for the Range Table. Consult trpg_geom.h for details - on what this is and how it works. - */ + Methods for the Range Table. Consult trpg_geom.h for details + on what this is and how it works. + */ #include #include @@ -26,290 +26,328 @@ #include /* ******************* - Range Methods + Range Methods ******************* */ trpgRange::trpgRange(void) { - category = NULL; - subCategory = NULL; - Reset(); + category = NULL; + subCategory = NULL; + Reset(); } trpgRange::~trpgRange(void) { - Reset(); + Reset(); } trpgRange::trpgRange(const trpgRange &in): trpgReadWriteable(in) { - category = NULL; - subCategory = NULL; - *this = in; + category = NULL; + subCategory = NULL; + *this = in; } void trpgRange::Reset(void) { - errMess[0] = '\0'; - if (category) - delete [] category; - category = NULL; - if (subCategory) - delete [] subCategory; - subCategory = NULL; + errMess[0] = '\0'; + if (category) + delete [] category; + category = NULL; + if (subCategory) + delete [] subCategory; + subCategory = NULL; - inLod = outLod = 0.0; - priority = 0; + inLod = outLod = 0.0; + priority = 0; + handle = -1; + writeHandle = false; } void trpgRange::SetCategory(const char *cat,const char *subCat) { - if (category) delete [] category; - category = NULL; - if (cat) { - category = new char[strlen(cat)+1]; - strcpy(category,cat); - } + if (category) delete [] category; + category = NULL; + if (cat) { + category = new char[strlen(cat)+1]; + strcpy(category,cat); + } - if (subCategory) delete [] subCategory; - subCategory = NULL; - if (subCat) { - subCategory = new char[strlen(subCat)+1]; - strcpy(subCategory,subCat); - } + if (subCategory) delete [] subCategory; + subCategory = NULL; + if (subCat) { + subCategory = new char[strlen(subCat)+1]; + strcpy(subCategory,subCat); + } } void trpgRange::GetCategory(char *cat,int catLen,char *subCat,int subCatLen) const { - if (category && cat) { - strncpy(cat,category,catLen); - } else - *cat = 0; - if (subCategory && subCat) { - strncpy(subCat,subCategory,subCatLen); - } else - *subCat = 0; + if (category && cat) { + strncpy(cat,category,catLen); + } else + *cat = 0; + if (subCategory && subCat) { + strncpy(subCat,subCategory,subCatLen); + } else + *subCat = 0; } void trpgRange::SetLodInfo(double in,double out) { - inLod = in; - outLod = out; + inLod = in; + outLod = out; } void trpgRange::GetLodInfo(double &in,double &out) const { - in = inLod; - out = outLod; + in = inLod; + out = outLod; } void trpgRange::SetPriority(int prior) { - priority = prior; + priority = prior; } void trpgRange::GetPriority(int &prior) const { - prior = priority; + prior = priority; } trpgRange & trpgRange::operator = (const trpgRange &other) { - Reset(); - inLod = other.inLod; - outLod = other.outLod; - SetCategory(other.category,other.subCategory); - priority = other.priority; - - return *this; + Reset(); + inLod = other.inLod; + outLod = other.outLod; + SetCategory(other.category,other.subCategory); + priority = other.priority; + handle = other.handle; + writeHandle = other.writeHandle; + return *this; } bool trpgRange::operator == (const trpgRange &in) const { - if (inLod != in.inLod || outLod != in.outLod) - return false; - if (priority != in.priority) return false; + if (inLod != in.inLod || outLod != in.outLod) + return false; + if (priority != in.priority) return false; - if (category && in.category) { - if (strcmp(category,in.category)) - return false; - } else { - if (category && !in.category || - !category && in.category) - return false; - } + if (category && in.category) { + if (strcmp(category,in.category)) + return false; + } else { + if (category && !in.category || + !category && in.category) + return false; + } - if (subCategory && in.subCategory) { - if (strcmp(subCategory,in.subCategory)) - return false; - } else { - if (subCategory && !in.subCategory || - !subCategory && in.subCategory) - return false; - } - - return true; + if (subCategory && in.subCategory) { + if (strcmp(subCategory,in.subCategory)) + return false; + } else { + if (subCategory && !in.subCategory || + !subCategory && in.subCategory) + return false; + } + if(handle != in.handle) + return false; + if(writeHandle != in.writeHandle) + return false; + return true; } bool trpgRange::Write(trpgWriteBuffer &buf) { - buf.Begin(TRPG_RANGE); - buf.Add(inLod); - buf.Add(outLod); - buf.Add(priority); - buf.Add((category ? category : "")); - buf.Add((subCategory ? subCategory : "")); - buf.End(); + buf.Begin(TRPG_RANGE); + buf.Add(inLod); + buf.Add(outLod); + buf.Add(priority); + buf.Add((category ? category : "")); + buf.Add((subCategory ? subCategory : "")); + if(writeHandle) { + buf.Add((int32)handle); + } + buf.End(); - return true; + return true; } bool trpgRange::Read(trpgReadBuffer &buf) { - char catStr[1024],subStr[1024]; + char catStr[1024],subStr[1024]; - Reset(); - valid = false; + Reset(); + valid = false; - try { - buf.Get(inLod); - buf.Get(outLod); - buf.Get(priority); - buf.Get(catStr,1024); - buf.Get(subStr,1024); - SetCategory(catStr,subStr); - valid = true; - } + try { + buf.Get(inLod); + buf.Get(outLod); + buf.Get(priority); + buf.Get(catStr,1024); + buf.Get(subStr,1024); + SetCategory(catStr,subStr); - catch (...) { - return false; - } + // Read the handle if we can.. + try { + if(!buf.Get((int32 &)handle)) { + handle = -1; + } + } + catch (...) { + handle = -1; + } + valid = true; + } - return isValid(); + catch (...) { + return false; + } + + return isValid(); } /* *************** - Range Table methods - *************** + Range Table methods + *************** */ trpgRangeTable::trpgRangeTable(void) { - valid = true; + valid = true; } trpgRangeTable::~trpgRangeTable(void) { - // vector cleans up itself + // vector cleans up itself } void trpgRangeTable::Reset(void) { - rangeList.resize(0); - valid = true; + rangeMap.clear(); + valid = true; } bool trpgRangeTable::GetRange(int id,trpgRange &ret) const { - if (!isValid()) - return false; + if (!isValid()) + return false; - if (id < 0 || id >= (int)rangeList.size()) - return false; + if (id < 0)// || id >= rangeList.size()) + return false; - ret = rangeList[id]; - - return true; + RangeMapType::const_iterator itr = rangeMap.find(id); + if(itr == rangeMap.end()) { + return false; + } + ret = itr->second; + return true; } bool trpgRangeTable::SetRange(int id,trpgRange &inRange) { - if (!isValid()) - return false; + if (!isValid()) + return false; - if (id < 0 || id >= (int)rangeList.size()) - return false; + if (id < 0)// || id >= rangeList.size()) + return false; - rangeList[id] = inRange; + rangeMap[id] = inRange; - return true; + return true; } int trpgRangeTable::AddRange(trpgRange &range) { - rangeList.push_back(range); + int handle = range.GetHandle(); + if(handle==-1) { + handle = rangeMap.size(); + } + rangeMap[handle] = range; + return handle; - return rangeList.size()-1; } int trpgRangeTable::FindAddRange(trpgRange &range) { - for (unsigned int i=0;isecond==range) + return itr->first; + } - return AddRange(range); +#if 0 + for (int i=0;isecond; + range.Write(buf); + } - buf.End(); + buf.End(); - return true; + return true; } bool trpgRangeTable::Read(trpgReadBuffer &buf) { - int32 numRange; - trpgToken tok; - int32 len; - valid = false; + int32 numRange; + trpgToken tok; + int32 len; + valid = false; - try { - buf.Get(numRange); - if (numRange < 0) throw 1; - for (int i=0;ifirst] = itr->second; - for (unsigned int i=0;i /* 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 #include @@ -38,10 +38,15 @@ trpgr_Archive::trpgr_Archive() trpgr_Archive::~trpgr_Archive() { if (fp) - fclose(fp); + fclose(fp); fp = NULL; if (tileCache) - delete tileCache; + delete tileCache; +} + +int32 trpgr_Archive::GetHeaderData(char *dataPtr, int length, FILE *filehandle) +{ + return fread(dataPtr,1,length,filehandle); } // Set the directory where the archive is @@ -60,72 +65,169 @@ bool trpgr_Archive::OpenFile(const char *name) CloseFile(); if (!(fp = fopen(file,"rb"))) - return false; + return false; // Look for a magic # and endianness int32 magic; if (fread(&magic,sizeof(int32),1,fp) != 1) - return false; + return 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 (magic == GetMagicNumber()) { + ness = cpuNess; + return true; } - if (trpg_byteswap_int(magic) == TRPG_MAGIC) { - if (cpuNess == LittleEndian) - ness = BigEndian; - else - ness = LittleEndian; - return true; + if (trpg_byteswap_int(magic) == GetMagicNumber()) { + if (cpuNess == LittleEndian) + ness = BigEndian; + else + ness = LittleEndian; + return true; } - if (magic != TRPG_MAGIC) - return false; + if (magic != GetMagicNumber()) + return false; // Not one of our files return false; } +// Get new reading app file cache +trpgrAppFileCache* trpgr_Archive::GetNewRAppFileCache(const char *fullBase, const char *ext) +{ + return new trpgrAppFileCache(fullBase,ext); +} + +trpgrImageHelper* trpgr_Archive::GetNewRImageHelper(trpgEndian ness,char *dir,const trpgMatTable &matTable,const trpgTexTable &texTable) +{ + bool separateGeo = false; + int majorVer,minorVer; + GetHeader()->GetVersion(majorVer,minorVer); + if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) { + separateGeo = true; + } + return new trpgrImageHelper(ness,dir,matTable,texTable,separateGeo); +} + // Close File // Close the currently open file void trpgr_Archive::CloseFile() { if (fp) - fclose(fp); + fclose(fp); fp = NULL; if (tileCache) - delete tileCache; + delete tileCache; tileCache = NULL; } +/** + * Read a sub block from a 2.2 TXP database. This can be called any time after ReadHeader is called + * if ReadHeader is called with the false parameter to specify not to read all the sub-archives. + * This can make a huge improvement in startup time for loading a very large archive with many blocks. + **/ +bool trpgr_Archive::ReadSubArchive(int row, int col, trpgEndian cpuNess) +{ + int ret; + trpgHeader blockHeader; + trpgr_Parser bparser; + + char blockpath[1024]; + //open the block archive + // the block archive will be in the base dir + \\cols\\row\\archive.txp + sprintf(blockpath,"%s%s%d%s%d%sarchive.txp",dir,PATHSEPERATOR,col,PATHSEPERATOR,row,PATHSEPERATOR); + FILE *bfp = fopen(blockpath,"rb"); + if(!bfp) { + return false; + } + // Look for a magic # and endianness + int32 bmagic; + if (fread(&bmagic,sizeof(int32),1,bfp) != 1) + return false; + // The block archive will always be the same endianness as the master + if ( (bmagic != GetMagicNumber()) && (trpg_byteswap_int(bmagic) != GetMagicNumber()) ) + return false; + + int32 bheaderSize=0; + if (fread(&bheaderSize,sizeof(int32),1,bfp) != 1) + return false; + if (ness != cpuNess) + bheaderSize = trpg_byteswap_int(bheaderSize); + int bheadLen = bheaderSize; + if (bheadLen < 0) + return false; + + // Read in the header whole + trpgMemReadBuffer bbuf(ness); + bbuf.SetLength(bheadLen); + char *bdata = bbuf.GetDataPtr(); + if ((ret = GetHeaderData(bdata,bheadLen,bfp)) != bheadLen) + return false; + //keep track of where this came from in the master table. + tileTable.SetCurrentBlock(row,col,true); + texTable.SetCurrentBlock(row,col); + + bparser.AddCallback(TRPGHEADER,&blockHeader); + bparser.AddCallback(TRPGMATTABLE,&materialTable); // Went back to oldest style for 2.0 + //if(!headerHasTexTable) { + bparser.AddCallback(TRPGTEXTABLE2,&texTable); // Added for 2.0 + //} + bparser.AddCallback(TRPGMODELTABLE,&modelTable); + bparser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0 + bparser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0 + bparser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1 + bparser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable); + bparser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable); + // Don't read the tile table for v1.0 archives + // It's only really used for 2.0 archives + bparser.AddCallback(TRPGTILETABLE2,&tileTable); + + // Parse the buffer + if (!bparser.Parse(bbuf)) + return false; + //close the block archive + fclose(bfp); + + tileTable.SetCurrentBlock(-1,-1,false); + + return true; +} + +bool trpgr_Archive::ReadHeader() +{ + return ReadHeader(true); +} + // Read Header // Run through the rest of the header information -bool trpgr_Archive::ReadHeader() +bool trpgr_Archive::ReadHeader(bool readAllBlocks) { int ret; if (!fp || headerRead) - return false; + return false; headerRead = true; // Next int64 should be the header size trpgEndian cpuNess = trpg_cpu_byte_order(); int32 headerSize; - if (fread(&headerSize,sizeof(int32),1,fp) != 1) return false; + if (fread(&headerSize,sizeof(int32),1,fp) != 1) + return false; if (ness != cpuNess) - headerSize = trpg_byteswap_int(headerSize); + headerSize = trpg_byteswap_int(headerSize); int headLen = headerSize; - if (headLen < 0) return false; + 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; + if ((ret = GetHeaderData(data,headLen,fp)) != headLen) + return false; // Set up a parser // Catch the tables we need for the archive @@ -136,37 +238,72 @@ bool trpgr_Archive::ReadHeader() 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(TRPGTEXTABLE2,&texTable); // Added for 2.0 parser.AddCallback(TRPGMODELTABLE,&modelTable); - parser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0 - parser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0 - parser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1 - parser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable); - parser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable); + parser.AddCallback(TRPGLIGHTTABLE,&lightTable); // Added for 2.0 + parser.AddCallback(TRPGRANGETABLE,&rangeTable); // Added for 2.0 + parser.AddCallback(TRPG_TEXT_STYLE_TABLE,&textStyleTable); // Added for 2.1 + parser.AddCallback(TRPG_SUPPORT_STYLE_TABLE,&supportStyleTable); + parser.AddCallback(TRPG_LABEL_PROPERTY_TABLE,&labelPropertyTable); // Don't read the tile table for v1.0 archives // It's only really used for 2.0 archives parser.AddCallback(TRPGTILETABLE2,&tileTable); // Parse the buffer if (!parser.Parse(buf)) - return false; + return false; + + if(header.GetIsMaster()) + { + // bool firstBlock = true; + bool headerHasTexTable = false; + //if the master has textures, we want to use them instead of the tables in the + //block archives + int numTex = 0; + texTable.GetNumTextures(numTex); + if(numTex) + headerHasTexTable = true; + // int numTiles = 0; + //tileTable. + int totalrows,totalcols; + trpg2dPoint mhdr_swExtents; + trpg2dPoint mhdr_neExtents; + trpg3dPoint mhdr_Origin; + // integrate header information from the block header. + header.GetExtents(mhdr_swExtents,mhdr_neExtents); + header.GetOrigin(mhdr_Origin); + header.GetBlocks(totalrows,totalcols); + if(readAllBlocks) { + for(int row=0;row= (unsigned int)numLods) return false; + if (static_cast(lod) >= numLods) + return false; trpg2iPoint lodSize; header.GetLodSize(lod,lodSize); - if (x >= (unsigned int)lodSize.x || y >= (unsigned int)lodSize.y) return false; + if (static_cast(x) >= lodSize.x || static_cast(y) >= lodSize.y) + return false; trpgTileTable::TileMode tileMode; tileTable.GetMode(tileMode); - if (tileMode == trpgTileTable::External) { - // Figure out the file name - // Note: This assumes External tiles - char filename[1024]; - sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod); - - // 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; - } + bool status = true; + if (tileMode == trpgTileTable::External || tileMode == trpgTileTable::ExternalSaved) { + status = ReadExternalTile(x, y, lod, buf); + } 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; + // Local tile. Figure out where it is (which file) + int majorVersion, minorVersion; + header.GetVersion(majorVersion, minorVersion); + if(majorVersion == 2 && minorVersion >=1) + { + // Version 2.1 + // Tile table contains only lod 0 tiles + if(lod != 0) + status = false; + } - // Fetch the appendable file from the cache - trpgrAppFile *tf = tileCache->GetFile(ness,addr.file); - if (!tf) return false; + if(status) + { + trpgwAppAddress addr; + float zmin,zmax; + status = tileTable.GetTile(x,y,lod,addr,zmin,zmax); - // Fetch the tile - if (!tf->Read(&buf,addr.offset)) - return false; + if(status) + status = ReadTile(addr, buf); + } + } + + return status; +} + +bool trpgr_Archive::ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf) +{ + // Figure out the file name + char filename[1024]; + int majorVer,minorVer; + header.GetVersion(majorVer,minorVer); + if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer >= TRPG_NOMERGE_VERSION_MINOR)) { + int blockx,blocky; + unsigned int denom = (1 << lod); // this should work up to lod 31 + blockx = x/denom; + blocky = y/denom; + sprintf(filename,"%s" PATHSEPERATOR "%d" PATHSEPERATOR "%d" PATHSEPERATOR "tile_%d_%d_%d.tpt", + dir,blockx,blocky,x,y,lod); + } + else { + sprintf(filename,"%s" PATHSEPERATOR "tile_%d_%d_%d.tpt",dir,x,y,lod); + } + // Open the file and read the contents + FILE *fp= 0; + 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; } return true; } +bool trpgr_Archive::ReadTile(const trpgwAppAddress& addr, trpgMemReadBuffer &buf) +{ + // Fetch the appendable file from the cache + trpgrAppFile *tf = tileCache->GetFile(ness,addr.file,addr.col,addr.row); + if (!tf) + return false; + + // Fetch the tile + if (!tf->Read(&buf,addr.offset)) + return false; + else + return true; +} // Get methods const trpgHeader *trpgr_Archive::GetHeader() const @@ -245,7 +433,7 @@ const trpgMatTable *trpgr_Archive::GetMaterialTable() const { return &materialTable; } -const trpgTexTable *trpgr_Archive::GetTexTable() const +trpgTexTable *trpgr_Archive::GetTexTable() { return &texTable; } @@ -286,13 +474,13 @@ trpgEndian trpgr_Archive::GetEndian() const bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll,trpg3dPoint &ur) const { if (!header.isValid()) - return false; + return false; int32 numLod; header.GetNumLods(numLod); trpg2iPoint maxXY; header.GetLodSize(lod,maxXY); - if (x >= (unsigned int)maxXY.x || y>= (unsigned int)maxXY.y) - return false; + if (static_cast(x) >= maxXY.x || static_cast(y)>= maxXY.y) + return false; trpg3dPoint origin; header.GetOrigin(origin); @@ -316,13 +504,20 @@ bool trpgr_Archive::trpgGetTileMBR(uint32 x,uint32 y,uint32 lod,trpg3dPoint &ll, /* ***************** Read Image Helper ***************** - */ + */ trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir, - const trpgMatTable &inMatTable,const trpgTexTable &inTexTable) + const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp) +{ + Init(inNess,inDir,inMatTable,inTexTable,separateGeoTyp); +} + +void trpgrImageHelper::Init(trpgEndian inNess,char *inDir, + const trpgMatTable &inMatTable,const trpgTexTable &inTexTable,bool separateGeoTyp) { ness = inNess; strcpy(dir,inDir); + this->separateGeoTyp = separateGeoTyp; matTable = &inMatTable; texTable = &inTexTable; @@ -330,13 +525,32 @@ trpgrImageHelper::trpgrImageHelper(trpgEndian inNess,char *inDir, // It doesn't do anything until it's called anyway char fullBase[1024]; sprintf(fullBase,"%s" PATHSEPERATOR "texFile",dir); - texCache = new trpgrAppFileCache(fullBase,"txf"); + texCache = GetNewRAppFileCache(fullBase,"txf"); + if(separateGeoTyp) { + sprintf(fullBase,"%s" PATHSEPERATOR "geotypFile",dir); + geotypCache = GetNewRAppFileCache(fullBase,"txf"); + } + else { + geotypCache = texCache; + } + } trpgrImageHelper::~trpgrImageHelper() { - if (texCache) - delete texCache; + if (texCache) { + delete texCache; + texCache = NULL; + } + if(separateGeoTyp && geotypCache) { + delete geotypCache; + geotypCache = NULL; + } +} + +trpgrAppFileCache* trpgrImageHelper::GetNewRAppFileCache(const char *fullBase,const char* /*ext*/) +{ + return new trpgrAppFileCache(fullBase,"txf"); } bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size) @@ -345,16 +559,16 @@ bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size) trpgTexture::ImageMode mode; tex->GetImageMode(mode); if (mode != trpgTexture::Local) - return false; + return false; // Fetch data data trpgwAppAddress addr; tex->GetImageAddr(addr); - trpgrAppFile *af = texCache->GetFile(ness,addr.file); + trpgrAppFile *af = geotypCache->GetFile(ness,addr.file,addr.col,addr.row); if (!af) - return false; + return false; if (!af->Read(data,addr.offset,0,size)) - return false; + return false; return true; } @@ -362,37 +576,37 @@ bool trpgrImageHelper::GetLocalGL(const trpgTexture *tex,char *data,int32 size) bool trpgrImageHelper::GetMipLevelLocalGL(int miplevel, const trpgTexture *tex,char *data,int32 dataSize) { if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 ) - return false; + return false; // Make sure the texture is Local trpgTexture::ImageMode mode; tex->GetImageMode(mode); if (mode != trpgTexture::Local) - return false; + return false; // Fetch data data trpgwAppAddress addr; tex->GetImageAddr(addr); - trpgrAppFile *af = texCache->GetFile(ness,addr.file); + trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row); if (!af) - return false; + return false; int level_offset = (const_cast(tex))->MipLevelOffset(miplevel); if (!af->Read(data,addr.offset,level_offset,dataSize)) - return false; + return false; return true; } bool trpgrImageHelper::GetImageInfoForLocalMat(const trpgLocalMaterial *locMat, - const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize) + const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize) { return GetNthImageInfoForLocalMat(locMat, 0, retMat, retTex, totSize); } bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index, - const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize) + const trpgMaterial **retMat,const trpgTexture **retTex,int &totSize) { // Get the base material for the Local Material int32 matSubTable,matID; @@ -401,18 +615,23 @@ bool trpgrImageHelper::GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMa // Eventually, either store multiple base materials for each local material, // or overhaul this in some other fashion. int numTables; - if (!matTable->GetNumTable(numTables)) return false; - if (index>=numTables) return false; + if (!matTable->GetNumTable(numTables)) + return false; + if (index>=numTables) + return false; if (index>0) matSubTable=index; // otherwise, leave it alone - could be nonzero const trpgMaterial *mat = matTable->GetMaterialRef(matSubTable,matID); - if (!mat) return false; + if (!mat) + return false; // Now get the texture (always the first one) trpgTextureEnv texEnv; int32 texID; - if (!mat->GetTexture(0,texID,texEnv)) return false; + if (!mat->GetTexture(0,texID,texEnv)) + return false; const trpgTexture *tex = texTable->GetTextureRef(texID); - if (!tex) return false; + if (!tex) + return false; totSize = tex->CalcTotalSize(); @@ -428,36 +647,38 @@ bool trpgrImageHelper::GetImageForLocalMat(const trpgLocalMaterial *locMat,char bool trpgrImageHelper::GetNthImageForLocalMat(const trpgLocalMaterial *locMat,int index, char *data,int dataSize) { - if (!locMat->isValid()) return false; + if (!locMat->isValid()) + return false; const trpgMaterial *mat; const trpgTexture *tex; int totSize; if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize)) - return false; + return false; // Determine the type trpgTexture::ImageMode imageMode; tex->GetImageMode(imageMode); switch (imageMode) { case trpgTexture::Template: - { - // Read the image data out of the Local image (in an archive somewhere) - trpgwAppAddress addr; - if (!locMat->GetNthAddr(index,addr)) return false; - trpgrAppFile *af = texCache->GetFile(ness,addr.file); - if (!af) return false; - if (!af->Read(data,addr.offset,0,dataSize)) - return false; - } - break; + { + // Read the image data out of the Local image (in an archive somewhere) + trpgwAppAddress addr; + if (!locMat->GetNthAddr(index,addr)) return false; + trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row); + if (!af) + return false; + if (!af->Read(data,addr.offset,0,dataSize)) + return false; + } + break; case trpgTexture::Global: - // Note: Not dealing with Global textures yet - return false; - break; + // Note: Not dealing with Global textures yet + return false; + break; default: - // This is not a valid Local Material - return false; + // This is not a valid Local Material + return false; }; return true; @@ -477,35 +698,35 @@ bool trpgrImageHelper::GetNthImageMipLevelForLocalMat(int miplevel, const trpgLo const trpgTexture *tex; int totSize; if (!GetNthImageInfoForLocalMat(locMat,index,&mat,&tex,totSize)) - return false; + return false; if ( miplevel >= tex->CalcNumMipmaps() || miplevel < 0 ) - return false; + return false; // Determine the type trpgTexture::ImageMode imageMode; tex->GetImageMode(imageMode); switch (imageMode) { case trpgTexture::Template: - { - // Read the image data out of the Local image (in an archive somewhere) - trpgwAppAddress addr; - if (!locMat->GetNthAddr(index,addr)) return false; - trpgrAppFile *af = texCache->GetFile(ness,addr.file); - if (!af) return false; + { + // Read the image data out of the Local image (in an archive somewhere) + trpgwAppAddress addr; + if (!locMat->GetNthAddr(index,addr)) return false; + trpgrAppFile *af = texCache->GetFile(ness,addr.file,addr.col,addr.row); + if (!af) return false; - int level_offset = (const_cast(tex))->MipLevelOffset(miplevel); - if (!af->Read(data,addr.offset,level_offset,dataSize)) - return false; - } - break; + 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; + // Note: Not dealing with Global textures yet + return false; + break; default: - // This is not a valid Local Material - return false; + // This is not a valid Local Material + return false; }; return true; @@ -518,8 +739,8 @@ bool trpgrImageHelper::GetImagePath(const trpgTexture *tex,char *fullPath,int pa tex->GetName(name,nameLen); nameLen = strlen(name); - if ((int)strlen(dir) + nameLen + 2 > pathLen) - return false; + if (static_cast(strlen(dir)) + nameLen + 2 > pathLen) + return false; sprintf(fullPath,"%s" PATHSEPERATOR "%s",dir,name); diff --git a/src/osgPlugins/txp/trpage_read.h b/src/osgPlugins/txp/trpage_read.h index db9d888b6..b9388e1e7 100644 --- a/src/osgPlugins/txp/trpage_read.h +++ b/src/osgPlugins/txp/trpage_read.h @@ -18,45 +18,48 @@ #define _txpage_read_h_ /* txpage_read.h - Classes used to represent read objects for paging files. - */ + Classes used to represent read objects for paging files. +*/ #include #include /* Callback base class - Called when a given token is found. - {group:Archive Reading} - */ -TX_EXDECL class TX_CLDECL trpgr_Callback { -public: + Called when a given token is found. + {group:Archive Reading} +*/ +TX_EXDECL class TX_CLDECL trpgr_Callback +{ + public: virtual ~trpgr_Callback(void) { }; virtual void *Parse(trpgToken,trpgReadBuffer &) { return (void *)1; }; }; /* Paging Token - Stores callback info associated with a given token. - {group:Archive Reading} - */ -TX_EXDECL class TX_CLDECL trpgr_Token { -public: + Stores callback info associated with a given token. + {group:Archive Reading} +*/ +TX_EXDECL class TX_CLDECL trpgr_Token +{ + public: trpgr_Token(void); trpgr_Token(int,trpgr_Callback *,bool destroy=true); ~trpgr_Token(void); void init(int,trpgr_Callback *,bool destroy=true); - int Token; // Constant token value + int Token; // Constant token value trpgr_Callback *cb; // Callback when we hit this token bool destroy; // Should we call delete on the callback or not void Destruct(void); // Not quite like delete }; /* Parse class for paging data structures. - This executes callbacks - {group:Archive Reading} - */ -TX_EXDECL class TX_CLDECL trpgr_Parser { -public: + This executes callbacks + {group:Archive Reading} +*/ +TX_EXDECL class TX_CLDECL trpgr_Parser +{ + public: trpgr_Parser(void); virtual ~trpgr_Parser(void); bool isValid(void) const; @@ -64,68 +67,75 @@ public: // Add and remove token callbacks virtual void AddCallback(trpgToken,trpgr_Callback *,bool destroy = true); virtual void AddCallback(trpgToken,trpgReadWriteable *); + virtual const trpgr_Callback *GetCallback(trpgToken tok) const; + virtual trpgr_Callback *GetCallback(trpgToken tok); virtual void RemoveCallback(trpgToken); virtual void SetDefaultCallback(trpgr_Callback *,bool destroy = true); // Parse a read buffer virtual bool Parse(trpgReadBuffer &); virtual bool TokenIsValid(trpgToken); // Check token validity -protected: + protected: void *lastObject; -private: + private: // Note: Just how slow is a map<> anyway? - // This usage is self-contained and could be replaced with an array + // This usage is self-contained and could be replaced with an array #if defined(_WIN32) typedef std::map tok_map; #else - typedef std::map > tok_map; + typedef std::map< trpgToken,trpgr_Token,std::less > 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 &); + 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. +*/ +class trpgwImageHelper; +TX_EXDECL class TX_CLDECL trpgrImageHelper +{ + public: + trpgrImageHelper() {;}; + trpgrImageHelper(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &,bool separateGeoTyp); + // real construction is here + virtual void Init(trpgEndian ness,char *dir,const trpgMatTable &,const trpgTexTable &,bool separateGeoTyp); virtual ~trpgrImageHelper(void); /* Fetch the bytes for the given texture. - This is only valid for Local textures. - */ + 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. - */ + 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. - */ + 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); + const trpgMaterial **retMat,const trpgTexture **retTex, + int &totSize); /* Same as above, but gets info for nth image associated with this local material */ virtual bool GetNthImageInfoForLocalMat(const trpgLocalMaterial *locMat, int index, - const trpgMaterial **retMat,const trpgTexture **retTex, - int &totSize); + 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. - */ + associated texture). This is for Tile Local and + Global textures. + Data is a pre-allocated buffer for the data and + dataSize is the size of that buffer. + */ virtual bool GetImageForLocalMat(const trpgLocalMaterial *locMat,char *data,int dataSize); /* Same as above, but gets nth image associated with this local material @@ -133,48 +143,68 @@ public: virtual bool GetNthImageForLocalMat(const trpgLocalMaterial *locMat, int index, char *data,int dataSize); /* Same as the one above, just fetch single mip levels - */ + */ virtual bool GetMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat,char *data,int dataSize); /* Get mip levels for one of multiple images - */ + */ virtual bool GetNthImageMipLevelForLocalMat(int miplevel, const trpgLocalMaterial *locMat, int index, char *data,int dataSize); /* Determine the full path of the image in the given - trpgTexture class. + trpgTexture class. Only useful for External images. - */ + */ virtual bool GetImagePath(const trpgTexture *,char *,int len); -protected: + virtual trpgrAppFileCache* GetNewRAppFileCache(const char *fullBase,const char *ext); + + trpgrAppFileCache *GetGeoTypCache() + { + return geotypCache; + } + void SetTexTable(trpgTexTable *texTable) + { + this->texTable = texTable; + } + protected: char dir[1024]; trpgEndian ness; const trpgMatTable *matTable; const trpgTexTable *texTable; trpgrAppFileCache *texCache; + trpgrAppFileCache *geotypCache; + bool separateGeoTyp; }; /* Paging Archive (read version) - This just reads the first bits of the file (and the header) - and lets you parse from there. - {group:Archive Reading} - */ -TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable { -public: + This just reads the first bits of the file (and the header) + and lets you parse from there. + {group:Archive Reading} +*/ +TX_EXDECL class TX_CLDECL trpgr_Archive : public trpgCheckable +{ + public: trpgr_Archive(void); virtual ~trpgr_Archive(void); virtual void SetDirectory(const char *); - virtual bool OpenFile(const char *); // Open File + virtual bool OpenFile(const char *); // Open File virtual void CloseFile(void); - virtual bool ReadHeader(void); // Read header (materials, tile table. etc..) + virtual bool ReadHeader(void); // Read header (materials, tile table. etc..) + //overload that lets you specify if you want to read all the blocks now, + //or defer reading them for later. + virtual bool ReadHeader(bool readAllBlocks); + bool ReadSubArchive(int row, int col, trpgEndian cpuNess); + // In version 2.1, only tile at lod 0 are fetchable via the tile table virtual bool ReadTile(uint32 x, uint32 y, uint32 lod,trpgMemReadBuffer &); + virtual bool ReadTile(const trpgwAppAddress& addr, trpgMemReadBuffer &buf); + virtual bool ReadExternalTile(uint32 x,uint32 y,uint32 lod,trpgMemReadBuffer &buf); // Get access to header info virtual const trpgHeader *GetHeader(void) const; virtual const trpgMatTable *GetMaterialTable(void) const; - virtual const trpgTexTable *GetTexTable(void) const; + virtual trpgTexTable *GetTexTable(void) ; virtual const trpgModelTable *GetModelTable(void) const; virtual const trpgTileTable *GetTileTable(void) const; virtual const trpgLightTable *GetLightTable(void) const; @@ -185,11 +215,15 @@ public: // Utility routine to calculate the MBR of a given tile virtual bool trpgGetTileMBR(uint32 x,uint32 y,uint32 lod, - trpg3dPoint &ll,trpg3dPoint &ur) const; + trpg3dPoint &ll,trpg3dPoint &ur) const; trpgEndian GetEndian(void) const; char* getDir(void){return dir;}; -protected: + virtual trpgrImageHelper* GetNewRImageHelper(trpgEndian ness,char *dir,const trpgMatTable &matTable,const trpgTexTable &texTable); + virtual trpgrAppFileCache* GetNewRAppFileCache(const char *fullBase, const char *ext); + virtual int32 GetHeaderData(char *dataPtr,int32 length,FILE *filehandle); + virtual int32 GetMagicNumber() {return TRPG_MAGIC;}; + protected: bool headerRead; trpgEndian ness; FILE *fp; @@ -214,19 +248,20 @@ class trpgSceneHelperPush; class trpgSceneHelperPop; class trpgSceneHelperDefault; /* Scene Parser - This class assists in parsing a scene graph structure (tiles and models). - To use it, do an archive ReadTile and pass the resulting Read Buffer to this - parser. - {group:Archive Reading} - */ -TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser { + This class assists in parsing a scene graph structure (tiles and models). + To use it, do an archive ReadTile and pass the resulting Read Buffer to this + parser. + {group:Archive Reading} +*/ +TX_EXDECL class TX_CLDECL trpgSceneParser : public trpgr_Parser +{ friend class trpgSceneHelperPush; friend class trpgSceneHelperPop; friend class trpgSceneHelperDefault; -public: + public: trpgSceneParser(void); virtual ~trpgSceneParser(void); -protected: + protected: // Start defining children for the given object virtual bool StartChildren(void *) { return true;}; virtual bool EndChildren(void *) { return true;}; diff --git a/src/osgPlugins/txp/trpage_readbuf.cpp b/src/osgPlugins/txp/trpage_readbuf.cpp index db1d30098..b56f247fc 100644 --- a/src/osgPlugins/txp/trpage_readbuf.cpp +++ b/src/osgPlugins/txp/trpage_readbuf.cpp @@ -18,15 +18,15 @@ #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 #include @@ -43,9 +43,9 @@ bool trpgReadBuffer::Get(int32 &ret) if (!GetData((char *)&val,sizeof(int32))) return false; if (ness != cpuNess) - ret = trpg_byteswap_int(val); + ret = trpg_byteswap_int(val); else - ret = val; + ret = val; return true; } @@ -54,10 +54,11 @@ bool trpgReadBuffer::Get(int64 &ret) int64 val; if (!GetData((char *)&val,sizeof(int64))) return false; + // trpg_byteswap_llong is defined to be 64 bit if (ness != cpuNess) - ret = trpg_byteswap_llong(val); + ret = trpg_byteswap_llong(val); else - ret = val; + ret = val; return true; } @@ -74,7 +75,7 @@ bool trpgReadBuffer::Get(char *ret,int retLen) ret[rlen] = 0; // Skip the rest - if (!Skip(rlen-len)) return false; + if (!Skip(len-rlen)) return false; return true; } @@ -86,7 +87,7 @@ bool trpgReadBuffer::Get(std::string &str) if (!Get(len)) return false; if (len < 0) - return false; + return false; // Note: Should fix this char *tmpStr = new char[len+1]; @@ -104,10 +105,10 @@ bool trpgReadBuffer::Get(float32 &ret) if (!GetData(cval,sizeof(float32))) return false; try { - if (ness == cpuNess) - memcpy(&ret,cval,4); - else - ret = trpg_byteswap_4bytes_to_float(cval); + if (ness == cpuNess) + memcpy(&ret,cval,4); + else + ret = trpg_byteswap_4bytes_to_float(cval); } catch (...) { } @@ -120,10 +121,10 @@ bool trpgReadBuffer::Get(float64 &ret) if (!GetData(cval,sizeof(float64))) return false; try { - if (ness == cpuNess) - memcpy(&ret,cval,8); - else - ret = trpg_byteswap_8bytes_to_double(cval); + if (ness == cpuNess) + memcpy(&ret,cval,8); + else + ret = trpg_byteswap_8bytes_to_double(cval); } catch (...) { } @@ -161,9 +162,9 @@ bool trpgReadBuffer::Get(trpgDiskRef &ret) if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false; if (ness == cpuNess) - ret = val; + ret = val; else - ret = trpg_byteswap_llong(val); + ret = trpg_byteswap_llong(val); return true; } @@ -175,9 +176,9 @@ bool trpgReadBuffer::Get(trpgToken &ret) if (!GetData((char *)&val,sizeof(trpgToken))) return false; if (ness == cpuNess) - ret = val; + ret = val; else - ret = trpg_byteswap_short(val); + ret = trpg_byteswap_short(val); return true; } @@ -186,13 +187,13 @@ bool trpgReadBuffer::Get(trpgToken &ret) bool trpgReadBuffer::GetArray(int len,float32 **arr) { if (!GetDataRef((char **)arr,sizeof(float32)*len)) - return false; + 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); + limits.resize(len-1); } // Skip To Limit @@ -306,10 +307,10 @@ bool trpgReadBuffer::SkipToLimit() int len=0; if (limits.size() != 0) - len = limits[limits.size()-1]; + len = limits[limits.size()-1]; if (len > 0) - return Skip(len); + return Skip(len); return true; } @@ -319,8 +320,8 @@ bool trpgReadBuffer::SkipToLimit() bool trpgReadBuffer::TestLimit(int len) { for (unsigned int i=0;i limits[i]) - return false; + if (len > limits[i]) + return false; return true; } @@ -330,7 +331,7 @@ bool trpgReadBuffer::TestLimit(int len) void trpgReadBuffer::UpdateLimits(int len) { for (unsigned int i=0;i= len) - return true; + return true; // Also test the limits for (unsigned int i=0;i totLen) { - if (data) - delete [] data; - data = new char[newLen]; - totLen = newLen; + if (data) + delete [] data; + data = new char[newLen]; + totLen = newLen; } len = newLen; pos = 0; @@ -391,7 +392,7 @@ char *trpgMemReadBuffer::GetDataPtr() bool trpgMemReadBuffer::GetData(char *ret,int rlen) { if (rlen < 0) - return false; + return false; // Test against limits imposed from without if (!TestLimit(rlen)) throw 1; @@ -433,8 +434,11 @@ bool trpgMemReadBuffer::GetDataRef(char **ret,int rlen) // Same as read except we're not, uh, reading bool trpgMemReadBuffer::Skip(int rlen) { + if (rlen == 0) + return true; + if (rlen < 0) - return false; + return false; // Test against limits if (!TestLimit(rlen)) return false; @@ -451,13 +455,18 @@ bool trpgMemReadBuffer::Skip(int rlen) */ trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName) +{ + Init(inNess,fileName); +} + +void trpgrAppFile::Init(trpgEndian inNess,const char *fileName) { valid = false; ness = inNess; cpuNess = trpg_cpu_byte_order(); if (!(fp = fopen(fileName,"rb"))) - return; + return; valid = true; } @@ -465,11 +474,16 @@ trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName) trpgrAppFile::~trpgrAppFile() { if (fp) - fclose(fp); + fclose(fp); valid = false; } +bool trpgrAppFile::isValid(void) const +{ + return valid; +} + // Read a section of data from the given file // and dump it into the given buffer bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset) @@ -478,44 +492,44 @@ bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset) // Seek to the right location if (fseek(fp,offset,SEEK_SET)) - return false; + return false; // Read a length int32 len; if (fread(&len,sizeof(int32),1,fp) != 1) { - valid = false; - return false; + valid = false; + return false; } // Byteswap if necessary if (ness != cpuNess) - trpg_byteswap_int(len); + len = trpg_byteswap_int(len); if (len < 0) { - valid = false; - return false; + valid = false; + return false; } buf->SetLength(len); char *data = buf->GetDataPtr(); if (!data) { - valid = false; - return false; + valid = false; + return false; } - if (fread(data,sizeof(char),len,fp) != (unsigned int)len) { - valid = false; - return false; + if (fread(data,sizeof(char),len,fp) != (uint32)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. - */ + 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 baseOffset,int32 objOffset,int32 dataSize) { if (!valid) return false; @@ -523,53 +537,58 @@ bool trpgrAppFile::Read(char *data,int32 baseOffset,int32 objOffset,int32 dataSi // Seek to the right place int result; if ((result = fseek(fp,baseOffset,SEEK_SET))) { - valid = false; - return false; + valid = false; + return false; } // Read the total object length int32 len; if (fread(&len,sizeof(int32),1,fp) != 1) { - valid = false; - return false; + valid = false; + return false; } // Byteswap if necessary if (ness != cpuNess) - trpg_byteswap_int(len); + len = trpg_byteswap_int(len); if (len < 0) { - valid = false; - return false; + valid = false; + return false; } // It's all right to read less than the whole data block if (objOffset+dataSize > len) - return false; + return false; // Skip to the object offset if (fseek(fp,objOffset,SEEK_CUR)) { - valid = false; - return false; + valid = false; + return false; } // Read the raw data // Note: What about byte swapping? - if (fread(data,sizeof(char),dataSize,fp) != (unsigned int)dataSize) { - valid = false; - return false; + if (fread(data,sizeof(char),dataSize,fp) != (uint32)dataSize) { + valid = false; + return false; } return true; } /* App File Cache - This class manages a group of appendable files with - the same base name and extension. It will keep a certain - number of them open to facilitate caching. - */ + This class manages a group of appendable files with + the same base name and extension. It will keep a certain + number of them open to facilitate caching. +*/ trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noFiles) +{ + Init(inPre,inExt,noFiles); +} + +void trpgrAppFileCache::Init(const char *inPre,const char *inExt,int noFiles) { strcpy(baseName,inPre); strcpy(ext,inExt); @@ -580,56 +599,101 @@ trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noF trpgrAppFileCache::~trpgrAppFileCache() { - for (unsigned int i=0;iisValid()) + { + of.lastUsed = timeCount; + return of.afile; + } + else + { + if (of.afile) + delete of.afile; + of.afile = NULL; + } } // Didn't find it. Need to reclaim one // Look for the oldest used int oldTime=-1,oldID=-1; for (i=0;i 0) { + if(baseName[len]==PATHSEPERATOR[0]) { + strcpy(filebase,&baseName[len+1]); + strcpy(dir,baseName); + dir[len]='\0'; + break; + } + } + sprintf(fileName,"%s" PATHSEPERATOR "%d" PATHSEPERATOR "%d" PATHSEPERATOR "%s_%d.%s", + dir,col,row,filebase,id,ext); + } + of.afile = GetNewRAppFile(ness,fileName); of.id = id; + of.row = row; + of.col = col; of.lastUsed = timeCount; timeCount++; diff --git a/src/osgPlugins/txp/trpage_scene.cpp b/src/osgPlugins/txp/trpage_scene.cpp index d200f2d7d..a1b7d0e82 100644 --- a/src/osgPlugins/txp/trpage_scene.cpp +++ b/src/osgPlugins/txp/trpage_scene.cpp @@ -19,448 +19,473 @@ #include /* 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 /* **************** - 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 >= (int)children.size()) + return; + children[id] = NULL; } // Unref all the children (they've probably been moved elsewhere) void trpgReadGroupBase::unRefChildren() { - for (unsigned int i=0;i(&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 (unsigned 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 trpgReadChildRefHelper : public trpgr_Callback { +public: + trpgReadChildRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; } + void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { + trpgReadChildRef *childRef = new trpgReadChildRef(); + trpgChildRef *data = childRef->GetData(); + if (!data->Read(buf)) { + delete childRef; + return NULL; + } + trpgReadGroupBase *top = parse->GetCurrTop(); + // NOTE: this is bad, we delete the pointer then we save it. + // this is done everywhere and should be corrected + if (top) + top->AddChild(childRef); + else + delete childRef; + + return childRef; + } +protected: + 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_CHILDREF,new trpgReadChildRefHelper(this)); + AddCallback(TRPG_BILLBOARD,new trpgReadBillboardHelper(this)); + AddCallback(TRPG_LOD,new trpgReadLodHelper(this)); +// AddCallback(TRPG_TRANSFORM,new trpgReadTransformHelper(this)); + AddCallback(TRPG_MODELREF,new trpgReadModelRefHelper(this)); +// AddCallback(TRPG_LAYER,new trpgReadLayerHelper(this)); + AddCallback(TRPGTILEHEADER,new trpgReadTileHeaderHelper(this)); } // Get Current Top node trpgReadGroupBase *trpgSceneGraphParser::GetCurrTop() { - if (!currTop) - return NULL; - if (currTop->isGroupType()) - return (trpgReadGroupBase *)currTop; + if (!currTop) + return NULL; + if (currTop->isGroupType()) + return (trpgReadGroupBase *)currTop; - return NULL; + return NULL; } // Return a pointer to the tile header record trpgReadTileHeader *trpgSceneGraphParser::GetTileHeaderRef() { - return &tileHead; + return &tileHead; } // Parse Scene // Parse a buffer and return the resulting scene graph trpgReadNode *trpgSceneGraphParser::ParseScene(trpgReadBuffer &buf,GroupMap &inGmap) { - gmap = &inGmap; - trpgTileHeader *data = tileHead.GetData(); - data->Reset(); + gmap = &inGmap; + trpgTileHeader *data = tileHead.GetData(); + data->Reset(); - // Always put a group up top, since there might be more than - // one node at the top level in the file. - top = currTop = new trpgReadGroup(); + // Always put a group up top, since there might be more than + // one node at the top level in the file. + top = currTop = new trpgReadGroup(); - // All the setup for tokens is handled in the constructor - // Just call parse - if (!Parse(buf)) { - // Failed to parse correctly. Give up. - delete top; - return NULL; - } + // All the setup for tokens is handled in the constructor + // Just call parse + if (!Parse(buf)) { + // Failed to parse correctly. Give up. + delete top; + return NULL; + } - return top; + return top; } // Start Children @@ -468,19 +493,19 @@ trpgReadNode *trpgSceneGraphParser::ParseScene(trpgReadBuffer &buf,GroupMap &inG // We'll want to make the node it's handing us the "top" node bool trpgSceneGraphParser::StartChildren(void *in_node) { - trpgReadNode *node = (trpgReadNode *)in_node; + trpgReadNode *node = (trpgReadNode *)in_node; - if (!node || !node->isGroupType()) { - // Looks like there's a push in the wrong place - // Make the current "top" NULL. - // This will drop all node until we pop back above - currTop = NULL; - } else { - // This node is our new "top" - currTop = node; - } + if (!node || !node->isGroupType()) { + // Looks like there's a push in the wrong place + // Make the current "top" NULL. + // This will drop all node until we pop back above + currTop = NULL; + } else { + // This node is our new "top" + currTop = node; + } - return true; + return true; } /* This is called whent he parser hits a pop. @@ -488,67 +513,67 @@ bool trpgSceneGraphParser::StartChildren(void *in_node) for the parent above the current one. If there isn't one, we'll just stick things in our top group. */ -bool trpgSceneGraphParser::EndChildren(void * /*in_node*/) +bool trpgSceneGraphParser::EndChildren(void* /*in_node*/) { - // We don't need it here, but this is the node we just - // finished putting children under. If you need to close - // it out in some way, do that here - //trpgReadNode *node = (trpgReadNode *)in_node; + // We don't need it here, but this is the node we just + // finished putting children under. If you need to close + // it out in some way, do that here + //trpgReadNode *node = (trpgReadNode *)in_node; - // Get the parent above the current one - int pos = parents.size()-2; - if (pos < 0) - // Nothing above the current one. Fall back on our top group - currTop = top; - else - currTop = (trpgReadNode *)parents[pos]; + // Get the parent above the current one + int pos = parents.size()-2; + if (pos < 0) + // Nothing above the current one. Fall back on our top group + currTop = top; + else + currTop = (trpgReadNode *)parents[pos]; - return true; + return true; } // Return group map (for use by helpers) trpgSceneGraphParser::GroupMap *trpgSceneGraphParser::GetGroupMap() { - return gmap; + return gmap; } /* *********** - Test functions - *********** - */ + Test functions + *********** + */ // Test all the tiles in an archive bool trpgTestArchive(trpgr_Archive &archive) { - int numLod; - trpg2iPoint tileSize; - trpgSceneGraphParser parse; - trpgReadNode *scene; - trpgSceneGraphParser::GroupMap gmap; + int numLod; + trpg2iPoint tileSize; + trpgSceneGraphParser parse; + trpgReadNode *scene; + trpgSceneGraphParser::GroupMap gmap; - if (!archive.isValid()) return false; + if (!archive.isValid()) return false; - const trpgHeader *head = archive.GetHeader(); - head->GetNumLods(numLod); + const trpgHeader *head = archive.GetHeader(); + head->GetNumLods(numLod); - // Iterate over the lods - int nl,x,y; - trpgMemReadBuffer buf(archive.GetEndian()); - trpg3dPoint ll,ur; - for (nl = 0;nl < numLod;nl++) { - head->GetLodSize(nl,tileSize); - // Iterate over the tiles within those - for (x = 0; x < tileSize.x; x++) - for (y = 0; y < tileSize.y; y++) { - archive.trpgGetTileMBR(x,y,nl,ll,ur); - if (archive.ReadTile(x,y,nl,buf)) { - // Parse it - scene = parse.ParseScene(buf,gmap); - if (scene) - delete scene; - } - } - } + // Iterate over the lods + int nl,x,y; + trpgMemReadBuffer buf(archive.GetEndian()); + trpg3dPoint ll,ur; + for (nl = 0;nl < numLod;nl++) { + head->GetLodSize(nl,tileSize); + // Iterate over the tiles within those + for (x = 0; x < tileSize.x; x++) + for (y = 0; y < tileSize.y; y++) { + archive.trpgGetTileMBR(x,y,nl,ll,ur); + if (archive.ReadTile(x,y,nl,buf)) { + // Parse it + scene = parse.ParseScene(buf,gmap); + if (scene) + delete scene; + } + } + } - return true; + return true; } diff --git a/src/osgPlugins/txp/trpage_scene.h b/src/osgPlugins/txp/trpage_scene.h index 264b70ed6..69ee53c95 100644 --- a/src/osgPlugins/txp/trpage_scene.h +++ b/src/osgPlugins/txp/trpage_scene.h @@ -18,221 +18,234 @@ #define _txpage_scene_h_ /* trpage_scene.h - Scene Graph definition. - This is a small scene graph we use for testing. - It's not intended to replace the scene graph you may already be using. - You do not need to translate from this scene graph structure to your own, - at run-time. Instead, use this file and trpage_scene.cpp as a guideline - for how to read TerraPage format into your own scene graph. + Scene Graph definition. + This is a small scene graph we use for testing. + It's not intended to replace the scene graph you may already be using. + You do not need to translate from this scene graph structure to your own, + at run-time. Instead, use this file and trpage_scene.cpp as a guideline + for how to read TerraPage format into your own scene graph. */ #include /* - {group:Demonstration Scene Graph} - */ + {group:Demonstration Scene Graph} + */ TX_EXDECL class TX_CLDECL trpgMBR { public: - trpgMBR(void); - ~trpgMBR(void) { }; - bool isValid(void) const; - void Reset(void); - void AddPoint(const trpg3dPoint &); - void AddPoint(double,double,double); - void GetMBR(trpg3dPoint &ll,trpg3dPoint &ur) const; - trpg3dPoint GetLL(void) const; - trpg3dPoint GetUR(void) const; - void Union(const trpgMBR &); -// bool Overlap(const trpgMBR &) const; - bool Overlap(const trpg2dPoint &ll, const trpg2dPoint &ur) const; -// bool Within(const trpg3dPoint &) const - bool Within(const trpg2dPoint &) const; + trpgMBR(void); + ~trpgMBR(void) { }; + bool isValid(void) const; + void Reset(void); + void AddPoint(const trpg3dPoint &); + void AddPoint(double,double,double); + void GetMBR(trpg3dPoint &ll,trpg3dPoint &ur) const; + trpg3dPoint GetLL(void) const; + trpg3dPoint GetUR(void) const; + void Union(const trpgMBR &); +// bool Overlap(const trpgMBR &) const; + bool Overlap(const trpg2dPoint &ll, const trpg2dPoint &ur) const; +// bool Within(const trpg3dPoint &) const + bool Within(const trpg2dPoint &) const; protected: - inline bool inRange(double minv,double maxv,double val) const { return (val >= minv && val <= maxv); } - bool valid; - trpg3dPoint ll,ur; + inline bool inRange(double minv,double maxv,double val) const { return (val >= minv && val <= maxv); } + bool valid; + trpg3dPoint ll,ur; }; // Read Node // Simple Scenegraph node used for read testing -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadNode { public: - virtual ~trpgReadNode(void) { }; - virtual bool isGroupType(void) = 0; - virtual int GetType(void) { return type; } - virtual trpgMBR GetMBR(void) const { return trpgMBR(); } + virtual ~trpgReadNode(void) { }; + virtual bool isGroupType(void) = 0; + virtual int GetType(void) { return type; } + virtual trpgMBR GetMBR(void) const { return trpgMBR(); } protected: - int type; + int type; }; // Read Group Base // Base class for all group nodes -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadGroupBase : public trpgReadNode { public: - virtual ~trpgReadGroupBase(void); - void AddChild(trpgReadNode *); - bool isGroupType(void) { return true; } - int GetNumChildren(void) { return children.size(); } - trpgReadNode *GetChild(int i) { return children[i]; } - trpgMBR GetMBR(void) const; - void unRefChild(int i); - void unRefChildren(void); + virtual ~trpgReadGroupBase(void); + void AddChild(trpgReadNode *); + bool isGroupType(void) { return true; } + int GetNumChildren(void) { return int(children.size()); } + trpgReadNode *GetChild(int i) { return children[i]; } + trpgMBR GetMBR(void) const; + void unRefChild(int i); + void unRefChildren(void); protected: - trpgMBR mbr; - void DeleteChildren(void); - std::vector children; + trpgMBR mbr; + void DeleteChildren(void); + std::vector children; }; // Read Geometry // The leaf for this scene graph -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadGeometry : public trpgReadNode { public: - trpgReadGeometry(void) { type = TRPG_GEOMETRY; } - ~trpgReadGeometry(void) { }; - bool isGroupType(void) { return false; } - trpgGeometry *GetData(void) { return &data; } - trpgMBR GetMBR(void) const; + trpgReadGeometry(void) { type = TRPG_GEOMETRY; } + ~trpgReadGeometry(void) { }; + bool isGroupType(void) { return false; } + trpgGeometry *GetData(void) { return &data; } + trpgMBR GetMBR(void) const; protected: - trpgMBR mbr; - trpgGeometry data; + trpgMBR mbr; + trpgGeometry data; }; // Read Tile Header // One per tile. Info about what materials and models are used -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadTileHeader : public trpgReadNode { public: - trpgReadTileHeader(void) { type = TRPGTILEHEADER; } - ~trpgReadTileHeader(void) { }; - bool isGroupType(void) { return false; } - trpgTileHeader *GetData(void) { return &data; } - trpgMBR GetMBR(void) const { trpgMBR mbr; return mbr; }; + trpgReadTileHeader(void) { type = TRPGTILEHEADER; } + ~trpgReadTileHeader(void) { }; + bool isGroupType(void) { return false; } + trpgTileHeader *GetData(void) { return &data; } + trpgMBR GetMBR(void) const { trpgMBR mbr; return mbr; }; protected: - trpgTileHeader data; + trpgTileHeader data; }; // Read Group // Simple group structure -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadGroup : public trpgReadGroupBase { public: - trpgReadGroup(void) { type = TRPG_GROUP; } - ~trpgReadGroup(void) { }; - trpgGroup *GetData(void) { return &data; } + trpgReadGroup(void) { type = TRPG_GROUP; } + ~trpgReadGroup(void) { }; + trpgGroup *GetData(void) { return &data; } protected: - trpgGroup data; + trpgGroup data; }; // Read Attach // Should be the top of a higher LOD tile -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadAttach : public trpgReadGroupBase { public: - trpgReadAttach(void) { type = TRPG_ATTACH; } - ~trpgReadAttach(void) { }; - trpgAttach *GetData(void) { return &data; } + trpgReadAttach(void) { type = TRPG_ATTACH; } + ~trpgReadAttach(void) { }; + trpgAttach *GetData(void) { return &data; } protected: - trpgAttach data; + trpgAttach data; +}; + +// Read ChildRef +// Should point to a block tile +// {group:Demonstration Scene Graph} +TX_EXDECL class TX_CLDECL trpgReadChildRef : public trpgReadGroupBase { +public: + trpgReadChildRef(void) { type = TRPG_CHILDREF; } + ~trpgReadChildRef(void) { }; + bool isGroupType(void) { return false;} + trpgChildRef *GetData(void) { return &data; } +protected: + trpgChildRef data; }; // Read billboard -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadBillboard : public trpgReadGroupBase { public: - trpgReadBillboard(void) { type = TRPG_BILLBOARD; } - ~trpgReadBillboard(void) { }; - trpgBillboard *GetData(void) { return &data; } + trpgReadBillboard(void) { type = TRPG_BILLBOARD; } + ~trpgReadBillboard(void) { }; + trpgBillboard *GetData(void) { return &data; } protected: - trpgBillboard data; + trpgBillboard data; }; // Read LOD -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadLod : public trpgReadGroupBase { public: - trpgReadLod(void) { type = TRPG_LOD; } - ~trpgReadLod(void) { }; - trpgLod *GetData(void) { return &data; } + trpgReadLod(void) { type = TRPG_LOD; } + ~trpgReadLod(void) { }; + trpgLod *GetData(void) { return &data; } protected: - trpgLod data; + trpgLod data; }; // Read Layer -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadLayer : public trpgReadGroupBase { public: - trpgReadLayer(void) { type = TRPG_LAYER; } - ~trpgReadLayer(void) { }; - trpgLayer *GetData(void) { return &data; } + trpgReadLayer(void) { type = TRPG_LAYER; } + ~trpgReadLayer(void) { }; + trpgLayer *GetData(void) { return &data; } protected: - trpgLayer data; + trpgLayer data; }; // Read Transform -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadTransform : public trpgReadGroupBase { public: - trpgReadTransform(void) { type = TRPG_TRANSFORM; } - ~trpgReadTransform(void) { }; - trpgTransform *GetData(void) { return &data; } + trpgReadTransform(void) { type = TRPG_TRANSFORM; } + ~trpgReadTransform(void) { }; + trpgTransform *GetData(void) { return &data; } protected: - trpgTransform data; + trpgTransform data; }; // Read Model Reference -// {group:Demonstration Scene Graph} +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgReadModelRef : public trpgReadGroupBase { public: - trpgReadModelRef(void) { type = TRPG_MODELREF; } - ~trpgReadModelRef(void) { }; - trpgModelRef *GetData(void) { return &data; } + trpgReadModelRef(void) { type = TRPG_MODELREF; } + ~trpgReadModelRef(void) { }; + trpgModelRef *GetData(void) { return &data; } protected: - trpgModelRef data; + trpgModelRef data; }; /* Scene Graph Parser - Parses a read buffer and returns a full scenegraph. - You don't want to use this if you're reading into your own scenegraph. - Instead, you'll want to sublcass trpgSceneParser, which is a helper - class to keep track of pushes and pops and implement the same functionality - that trpgSceneGraphParser has for your own scene graph. - */ -// {group:Demonstration Scene Graph} + Parses a read buffer and returns a full scenegraph. + You don't want to use this if you're reading into your own scenegraph. + Instead, you'll want to sublcass trpgSceneParser, which is a helper + class to keep track of pushes and pops and implement the same functionality + that trpgSceneGraphParser has for your own scene graph. + */ +// {group:Demonstration Scene Graph} TX_EXDECL class TX_CLDECL trpgSceneGraphParser : public trpgSceneParser { public: #if defined(_WIN32) - typedef std::map GroupMap; + typedef std::map GroupMap; #else - typedef std::map > GroupMap; + typedef std::map< int,trpgReadGroupBase *,std::less > GroupMap; #endif - trpgSceneGraphParser(void); - virtual ~trpgSceneGraphParser(void) { }; - // Call this instead of Parse() - // Deleting it is your responsibility - trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &); - trpgReadGroupBase *GetCurrTop(void); // Get the current parent object - trpgReadTileHeader *GetTileHeaderRef(void); + trpgSceneGraphParser(void); + virtual ~trpgSceneGraphParser(void) { }; + // Call this instead of Parse() + // Deleting it is your responsibility + trpgReadNode *ParseScene(trpgReadBuffer &,GroupMap &); + trpgReadGroupBase *GetCurrTop(void); // Get the current parent object + trpgReadTileHeader *GetTileHeaderRef(void); - // For use by the helpers only - GroupMap *GetGroupMap(void); + // For use by the helpers only + GroupMap *GetGroupMap(void); protected: - bool StartChildren(void *); - bool EndChildren(void *); - trpgReadNode *currTop; // Current parent group - trpgReadNode *top; // Top of everything - GroupMap *gmap; - trpgReadTileHeader tileHead; // Tile header gets read into here + bool StartChildren(void *); + bool EndChildren(void *); + trpgReadNode *currTop; // Current parent group + trpgReadNode *top; // Top of everything + GroupMap *gmap; + trpgReadTileHeader tileHead; // Tile header gets read into here }; /* Test Archive - Utility function that loads and tests all tiles. - The only reason you'd want to call this is to test a TerraPage archive - you'd written. - */ -// {group:Demonstration Scene Graph} + Utility function that loads and tests all tiles. + The only reason you'd want to call this is to test a TerraPage archive + you'd written. + */ +// {group:Demonstration Scene Graph} TX_CPPDECL bool trpgTestArchive(trpgr_Archive &); #endif diff --git a/src/osgPlugins/txp/trpage_swap.cpp b/src/osgPlugins/txp/trpage_swap.cpp index be72293ed..35efb7012 100644 --- a/src/osgPlugins/txp/trpage_swap.cpp +++ b/src/osgPlugins/txp/trpage_swap.cpp @@ -17,15 +17,15 @@ #include /* trpage_swap.h - Byte swapping utility functions. - */ + Byte swapping utility functions. + */ #include /* -** func: swap_two( in, out ) +** func: swap_two( in, out ) ** -** desc: byte-swaps a two-byte array. +** desc: byte-swaps a two-byte array. */ void trpg_swap_two ( const char *in, char *out ) { @@ -38,9 +38,9 @@ void trpg_swap_two ( const char *in, char *out ) } /* -** func: swap_four( in, out ) +** func: swap_four( in, out ) ** -** desc: byte-swaps a four-byte array. +** desc: byte-swaps a four-byte array. */ void trpg_swap_four ( const char *in, char *out ) { @@ -55,9 +55,9 @@ void trpg_swap_four ( const char *in, char *out ) } /* -** func: swap_eight( in, out ) +** func: swap_eight( in, out ) ** -** desc: byte-swaps an eight-byte array. +** desc: byte-swaps an eight-byte array. */ void trpg_swap_eight ( const char *in, char *out ) { @@ -76,9 +76,9 @@ void trpg_swap_eight ( const char *in, char *out ) } /* -** func: swap_sixteen( in, out ) +** func: swap_sixteen( in, out ) ** -** desc: byte-swaps an sixteen-byte array. +** desc: byte-swaps an sixteen-byte array. */ void trpg_swap_sixteen ( const char *in, char *out ) { @@ -105,105 +105,105 @@ void trpg_swap_sixteen ( const char *in, char *out ) } /* -** func: tx_byteswap_short( number ) +** func: tx_byteswap_short( number ) ** -** desc: byte-swaps a short int. +** desc: byte-swaps a short int. */ short trpg_byteswap_short( short number ) { - short result; + short result; - trpg_swap_two( (const char*) &number, (char*) &result ); - return result; + trpg_swap_two( (const char*) &number, (char*) &result ); + return result; } /* -** func: tx_byteswap_int( number ) +** func: tx_byteswap_int( number ) ** -** desc: byte-swaps an int. +** desc: byte-swaps an int. */ -int trpg_byteswap_int( int number ) +TX_CPPDECL 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) +TX_CPPDECL 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 4eefcb255..82671f722 100644 --- a/src/osgPlugins/txp/trpage_swap.h +++ b/src/osgPlugins/txp/trpage_swap.h @@ -17,7 +17,7 @@ #define trpage_swap_h_ /* trpage_swap.h - Byte swapping utility functions. + Byte swapping utility functions. */ #include @@ -29,7 +29,7 @@ short trpg_byteswap_short( short number ); // Byte swap and return an integer // {group:Byte Ordering Utilities} -int trpg_byteswap_int( int number ); +TX_CPPDECL int trpg_byteswap_int( int number ); // Byte swap and return a long // {group:Byte Ordering Utilities} long trpg_byteswap_long( long number ); @@ -50,7 +50,7 @@ float trpg_byteswap_4bytes_to_float( const char result[4] ); double trpg_byteswap_8bytes_to_double( const char result[8] ); // Determine the current CPU's byte ordering // {group:Byte Ordering Utilities} -trpgEndian trpg_cpu_byte_order(void); +TX_CPPDECL trpgEndian trpg_cpu_byte_order(void); // Swap two chars // {group:Byte Ordering Utilities} diff --git a/src/osgPlugins/txp/trpage_sys.h b/src/osgPlugins/txp/trpage_sys.h index 5f3de1667..a53469891 100644 --- a/src/osgPlugins/txp/trpage_sys.h +++ b/src/osgPlugins/txp/trpage_sys.h @@ -14,8 +14,8 @@ */ /* trpage_sys.h - System specific declarations. - */ + System specific declarations. + */ #ifndef trpage_sys_h_ #define trpage_sys_h_ @@ -29,11 +29,11 @@ #endif #if defined(_WIN32) -/* ********************* - System Specific Section. - This is currently set up for win32. - ********************* - */ +/* ********************* + System Specific Section. + This is currently set up for win32. + ********************* + */ #include @@ -86,15 +86,15 @@ typedef float float32; typedef double float64; #endif -// Note: replace this with your own STL implementation -// You can use the Microsoft provided one by deleting the first #include -#ifdef USEROGUE -#include -#endif +#if defined(_WIN32) || defined(linux) #include #include #include +#else +#include +#include +#endif #if defined(_WIN32) // PJM // Had to take this out because of an iostream conflict diff --git a/src/osgPlugins/txp/trpage_tile.cpp b/src/osgPlugins/txp/trpage_tile.cpp index d763c0fc8..ec58f6ec0 100644 --- a/src/osgPlugins/txp/trpage_tile.cpp +++ b/src/osgPlugins/txp/trpage_tile.cpp @@ -17,234 +17,316 @@ #include #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 #include /* Write Tile Table - Keeps track of tiles written to disk. - */ + Keeps track of tiles written to disk. + */ // Constructor trpgTileTable::trpgTileTable() { - Reset(); + localBlock = false; + Reset(); } // Reset function void trpgTileTable::Reset() { - errMess[0] = '\0'; - mode = External; - lodInfo.resize(0); - valid = true; + errMess[0] = '\0'; + mode = External; + lodInfo.resize(0); + valid = true; + currentRow = -1; + currentCol = -1; + } // Destructor trpgTileTable::~trpgTileTable() { - valid = false; } // Set functions void trpgTileTable::SetMode(TileMode inMode) { - Reset(); - mode = inMode; + Reset(); + mode = inMode; } void trpgTileTable::SetNumLod(int numLod) { - lodInfo.resize(numLod); + lodInfo.resize(numLod); } + void trpgTileTable::SetNumTiles(int nx,int ny,int lod) { - if (nx <= 0 || ny <= 0 || lod < 0 || lod >= (int)lodInfo.size()) - return; + + if(localBlock) { + LodInfo &li = lodInfo[lod]; + li.numX = nx; li.numY = ny; + li.addr.resize(1); + li.elev_min.resize(1,0.0); + li.elev_max.resize(1,0.0); + valid = true; + // no need to do anything else if we only have one block. + return; + } + if (nx <= 0 || ny <= 0 || lod < 0 || lod >= static_cast(lodInfo.size())) + return; - // Got a table we need to maintain - if (mode == Local) { - // If there's a pre-existing table, we need to preserve the entries - LodInfo oldLodInfo = lodInfo[lod]; + // Got a table we need to maintain + if (mode == Local || mode == ExternalSaved) { + // If there's a pre-existing table, we need to preserve the entries + LodInfo oldLodInfo = lodInfo[lod]; - LodInfo &li = lodInfo[lod]; - li.numX = nx; li.numY = ny; - int numTile = li.numX*li.numY; - li.addr.resize(numTile); - li.elev_min.resize(numTile,0.0); - li.elev_max.resize(numTile,0.0); + LodInfo &li = lodInfo[lod]; + li.numX = nx; li.numY = ny; + int numTile = li.numX*li.numY; + li.addr.resize(numTile); + li.elev_min.resize(numTile,0.0); + li.elev_max.resize(numTile,0.0); - // Copy pre-existing data if it's there - if (oldLodInfo.addr.size() > 0) { - for (int x=0;x 0) { + for (int x=0;x= (int)lodInfo.size()) return; - if (mode != Local) - return; - LodInfo &li = lodInfo[lod]; - if (x < 0 || x >= li.numX || y < 0 || y >= li.numY) - return; - - int loc = y*li.numX + x; - li.addr[loc] = ref; - li.elev_min[loc] = zmin; - li.elev_max[loc] = zmax; + if (lod < 0 || lod >= static_cast(lodInfo.size())) + return; + if (mode == External) + return; + LodInfo &li = lodInfo[lod]; + int loc; + if(localBlock) { + loc = 0; + } + else { + if (x < 0 || x >= li.numX || y < 0 || y >= li.numY) + return; + loc = y*li.numX + x; + } + li.addr[loc] = ref; + li.elev_min[loc] = zmin; + li.elev_max[loc] = zmax; } bool trpgTileTable::isValid() const { - return valid; + return valid; } // Get methods bool trpgTileTable::GetMode(TileMode &outMode) const { - if (!isValid()) return false; + if (!isValid()) return false; - outMode = mode; - return true; + outMode = mode; + return true; } bool trpgTileTable::GetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 &zmin,float32 &zmax) const { - if (!isValid()) return false; + if (!isValid()) return false; - if (lod < 0 || lod >= (int)lodInfo.size()) return false; - if (mode != Local) - return false; - const LodInfo &li = lodInfo[lod]; - if (x < 0 || x >= li.numX || y < 0 || y >= li.numY) - return false; + if (lod < 0 || lod >= static_cast(lodInfo.size())) return false; + if (mode == External) + return false; - int loc = y*li.numX + x; - ref = li.addr[loc]; - zmin = li.elev_min[loc]; - zmax = li.elev_max[loc]; + const LodInfo &li = lodInfo[lod]; + int loc; + if(localBlock) { + loc = 0; + } + else { + if (x < 0 || x >= li.numX || y < 0 || y >= li.numY) + return false; + loc = y*li.numX + x; + } + + ref = li.addr[loc]; + zmin = li.elev_min[loc]; + zmax = li.elev_max[loc]; - return true; + return true; } // Write tile table bool trpgTileTable::Write(trpgWriteBuffer &buf) { - if (!isValid()) - return false; + if (!isValid()) + return false; - buf.Begin(TRPGTILETABLE2); - - // Write the mode - buf.Add(mode); + buf.Begin(TRPGTILETABLE2); + + // Write the mode + buf.Add(mode); - // Depending on the mode we'll have a lot or a little data - if (mode == Local) { - // The lod sizing is redundant, but it's convenient here - int numLod = lodInfo.size(); - buf.Add(numLod); + // Depending on the mode we'll have a lot or a little data + if (mode == Local || mode == ExternalSaved) { + // The lod sizing is redundant, but it's convenient here + int numLod = lodInfo.size(); + buf.Add(numLod); - // Write each terrain LOD set - for (int i=0;i= (int)matList.size()) - return; - matList[no] = id; + if (no < 0 || no >= static_cast(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 >= static_cast(modelList.size())) + return; + modelList[no] = id; } // Set functions void trpgTileHeader::AddMaterial(int id) { - // Look for it first + // Look for it first for (unsigned int i=0;i= (int)locMats.size()) - return false; + if (id < 0 || id >= static_cast(locMats.size())) + return false; retMat = locMats[id]; @@ -328,78 +412,78 @@ const std::vector *trpgTileHeader::GetLocalMaterialList() con // Get methods bool trpgTileHeader::GetNumMaterial(int32 &no) const { - if (!isValid()) return false; - no = matList.size(); - return true; + if (!isValid()) return false; + no = matList.size(); + return true; } bool trpgTileHeader::GetMaterial(int32 id,int32 &mat) const { - if (!isValid() || id < 0 || id >= (int)matList.size()) - return false; - mat = matList[id]; - return true; + if (!isValid() || id < 0 || id >= static_cast(matList.size())) + return false; + mat = matList[id]; + return true; } bool trpgTileHeader::GetNumModel(int32 &no) const { - if (!isValid()) return false; - no = modelList.size(); - return true; + if (!isValid()) return false; + no = modelList.size(); + return true; } bool trpgTileHeader::GetModel(int32 id,int32 &m) const { - if (!isValid() || id < 0 || id >= (int)modelList.size()) - return false; - m = modelList[id]; - return true; + if (!isValid() || id < 0 || id >= static_cast(modelList.size())) + return false; + m = modelList[id]; + return true; } bool trpgTileHeader::GetDate(int32 &d) const { - if (!isValid()) return false; - d = date; - return true; + if (!isValid()) return false; + d = date; + return true; } // Validity check bool trpgTileHeader::isValid() const { - return true; + return true; } // Write to a buffer bool trpgTileHeader::Write(trpgWriteBuffer &buf) { - unsigned int i; + unsigned int i; - if (!isValid()) - return false; - for (i=0;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; - 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;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; + 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;iGetBlockNo(addr.row,addr.col); + locMat.SetAddr(addr); - return head; + buf.PopLimit(); + } + } + break; + default: + // Don't care + break; + } + } + catch (...) { + return NULL; + } + + return head; } // Read tile header bool trpgTileHeader::Read(trpgReadBuffer &buf) { - tileHeaderCB tcb; - trpgr_Parser parse; + tileHeaderCB tcb; + trpgr_Parser parse; - tcb.head = this; - parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false); - parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false); - parse.AddCallback(TRPG_TILE_DATE,&tcb,false); - // New for 2.0 - parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false); - parse.Parse(buf); + tcb.head = this; + parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false); + parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false); + parse.AddCallback(TRPG_TILE_DATE,&tcb,false); + // New for 2.0 + parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false); + parse.Parse(buf); - return isValid(); + return isValid(); } diff --git a/src/osgPlugins/txp/trpage_util.cpp b/src/osgPlugins/txp/trpage_util.cpp index 3e4027761..772679565 100644 --- a/src/osgPlugins/txp/trpage_util.cpp +++ b/src/osgPlugins/txp/trpage_util.cpp @@ -16,8 +16,8 @@ #include /* trpage_util.cpp - This source file implements various utility routines for paging archive - */ + This source file implements various utility routines for paging archive + */ /* The merge routine used to be in here. However, merge isn't actually general enough to be part of the library. @@ -25,4 +25,3 @@ Instead, there's a Windows specific program that merges TerraPage archives in the merge/ directory of this distribution. */ - diff --git a/src/osgPlugins/txp/trpage_util.h b/src/osgPlugins/txp/trpage_util.h index 783544e27..bf1091f7b 100644 --- a/src/osgPlugins/txp/trpage_util.h +++ b/src/osgPlugins/txp/trpage_util.h @@ -14,8 +14,8 @@ */ /* trpage_sys.h - System specific declarations. - */ + System specific declarations. + */ #ifndef trpage_util_h_ #define trpage_util_h_ @@ -26,7 +26,7 @@ TX_EXDECL class TX_CLDECL trpgUtil { public: - enum {DoReport = 1<<0,DoCopy = 1<<1, DoTileOpt = 1<<2}; - int merge(trpgr_Archive &inArch1,trpgr_Archive &inArch2,trpgwArchive &outArch, int flags = 0); + enum {DoReport = 1<<0,DoCopy = 1<<1, DoTileOpt = 1<<2}; + int merge(trpgr_Archive &inArch1,trpgr_Archive &inArch2,trpgwArchive &outArch, int flags = 0); }; #endif diff --git a/src/osgPlugins/txp/trpage_warchive.cpp b/src/osgPlugins/txp/trpage_warchive.cpp index fca3d46ac..57ec5c7c5 100644 --- a/src/osgPlugins/txp/trpage_warchive.cpp +++ b/src/osgPlugins/txp/trpage_warchive.cpp @@ -18,15 +18,15 @@ #include /* 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 #include @@ -34,11 +34,23 @@ #include // Constructor -trpgwArchive::trpgwArchive(trpgEndian inNess,TileMode inTileMode,int inVersion) +trpgwArchive::trpgwArchive(trpgEndian inNess,trpgwArchive::TileMode inTileMode,int majorVer, int minorVer) { - version = inVersion; - if (version != 1 && version != 2) + Init(inNess,inTileMode,majorVer, minorVer); +} + +void trpgwArchive::Init(trpgEndian inNess, trpgwArchive::TileMode inTileMode,int majorVer, int minorVer) +{ + minorVersion = minorVer; + majorVersion = majorVer; + if (majorVersion < 1 || majorVersion > TRPG_VERSION_MAJOR) throw 1; + if(majorVersion == TRPG_VERSION_MAJOR) + { + if(minorVersion < 0 || minorVersion > TRPG_VERSION_MINOR) + throw 1; + } + fp = NULL; strcpy(dir,"."); ness = inNess; @@ -53,10 +65,16 @@ trpgwArchive::trpgwArchive(trpgEndian inNess,TileMode inTileMode,int inVersion) } // Constructor for regenerate -trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne) +trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne, int majorVer, int minorVer) +{ + Init(inDir,inFile,sw,ne, majorVer, minorVer); +} + +void trpgwArchive::Init(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint &ne, int majorVer, int minorVer) { maxTileFileLen = -1; - version = TRPG_VERSION_MAJOR; + majorVersion = majorVer; + minorVersion = minorVer; fp = NULL; strcpy(dir,inDir); cpuNess = trpg_cpu_byte_order(); @@ -65,15 +83,19 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint isRegenerate = true; errMess[0] = '\0'; + // TODO: have a "setup from file" method for trpgwArchive + // Open a Read Archive to get the rest of the info we need - trpgr_Archive *inArch = new trpgr_Archive(); + trpgr_Archive *inArch = this->GetArchiveReader(); inArch->SetDirectory(inDir); - if (!inArch->OpenFile(inFile)) { + if (!inArch->OpenFile(inFile)) + { delete inArch; throw 1; } // Get the header (this is what we need) - if (!inArch->ReadHeader()) { + if (!inArch->ReadHeader()) + { delete inArch; throw 1; } @@ -81,16 +103,39 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint ness = inArch->GetEndian(); const trpgHeader *inHeader = inArch->GetHeader(); + // use the version in the archive instead. + inHeader->GetVersion(majorVersion,minorVersion); + // Expand the coverage trpg2dPoint newSW,newNE; trpg2dPoint oldSW,oldNE; + + // Or not. Have to add in something to avoid recalculation + // when merging geocentric databases. We don't really support + // them, and everything goes to hell. So: hack is: + // if sw=ne, don't change anything. + // This will also help a little with MMB TXP merge speed. + + bool extentsUnchanged=false; inHeader->GetExtents(oldSW,oldNE); - newSW.x = MIN(sw.x,oldSW.x); - newSW.y = MIN(sw.y,oldSW.y); - newNE.x = MAX(ne.x,oldNE.x); - newNE.y = MAX(ne.y,oldNE.y); + // just checking for equality right now. Bad? + if ((sw==ne) || ((oldSW==sw) && (oldNE==ne))) + { + extentsUnchanged = true; + // set up passed-in SW and NE as well. + sw=newSW=oldSW; + ne=newNE=oldNE; + } + else + { + newSW.x = MIN(sw.x,oldSW.x); + newSW.y = MIN(sw.y,oldSW.y); + newNE.x = MAX(ne.x,oldNE.x); + newNE.y = MAX(ne.y,oldNE.y); + } // Decide what the offset should be for new tiles + if (!extentsUnchanged) { trpg2dPoint blockSize; inHeader->GetTileSize(0,blockSize); @@ -107,17 +152,19 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint // Header can mostly stay the same header = *inHeader; - // Update to the new MBR and tile grid sizes header.SetExtents(newSW,newNE); header.GetNumLods(numLod); - for (int i=0;iGetTileSize(i,tileSize); - trpg2iPoint newTileExt; - newTileExt.x = (int)((newNE.x - newSW.x)/tileSize.x + 10e-5); - newTileExt.y = (int)((newNE.y - newSW.y)/tileSize.y + 10e-15); - header.SetLodSize(i,newTileExt); + // Update to the new MBR and tile grid sizes + if (!extentsUnchanged) { + for (int i=0;iGetTileSize(i,tileSize); + trpg2iPoint newTileExt; + newTileExt.x = int((newNE.x - newSW.x)/tileSize.x + 10e-5); + newTileExt.y = int((newNE.y - newSW.y)/tileSize.y + 10e-15); + header.SetLodSize(i,newTileExt); + } } // These tables we can copy straight over @@ -131,36 +178,84 @@ trpgwArchive::trpgwArchive(char *inDir,char *inFile,trpg2dPoint &sw, trpg2dPoint supportStyleTable = *inArch->GetSupportStyleTable(); labelPropertyTable = *inArch->GetLabelPropertyTable(); - // Need to resize the tile table - const trpgTileTable *oldTiles = inArch->GetTileTable(); + // Need to resize the tile table (maybe) + // NOTE: Starting with version 2.1, the tile tables will contain only + // the lod 0 tiles trpgTileTable::TileMode tileTableMode; - oldTiles->GetMode(tileTableMode); - tileTable.SetMode(tileTableMode); - tileTable.SetNumLod(numLod); - for (int lod=0;lodGetTileTable(); + oldTiles->GetMode(tileTableMode); + tileTable.SetMode(tileTableMode); + if(majorVersion == 2 && minorVersion >=1) + { + // Version 2.1. we store only lod 0, all other lod tiles are + // stored in the parent tile + tileTable.SetNumLod(0); + // Size the output tile table + trpg2iPoint tileSize; + header.GetLodSize(0,tileSize); + tileTable.SetNumTiles(tileSize.x, tileSize.y, 0); - // Copy over individual tiles - trpg2iPoint levelOffset; - levelOffset.x = addOffset.x*(lod+1); - levelOffset.y = addOffset.y*(lod+1); - trpg2iPoint oldTileSize; - inHeader->GetLodSize(lod,oldTileSize); - for (int ix=0;ixGetTile(ix,iy,lod,addr,zmin,zmax); - tileTable.SetTile(ix+addOffset.x,iy+addOffset.y,lod,addr,zmin,zmax); + // Copy over individual tiles + trpg2iPoint levelOffset; + levelOffset.x = addOffset.x; + levelOffset.y = addOffset.y; + trpg2iPoint oldTileSize; + inHeader->GetLodSize(0, oldTileSize); + for (int ix=0;ixGetTile(ix, iy, 0,addr,zmin,zmax); + tileTable.SetTile(ix+addOffset.x, iy+addOffset.y ,0, addr, zmin, zmax); + } + } + + } + else + { + tileTable.SetNumLod(numLod); + for (int lod=0;lodGetLodSize(lod,oldTileSize); + for (int ix=0;ixGetTile(ix,iy,lod,addr,zmin,zmax); + tileTable.SetTile(ix+addOffset.x,iy+addOffset.y,lod,addr,zmin,zmax); + } + } } } + } else { + tileTable = *inArch->GetTileTable(); + tileTable.GetMode(tileTableMode); } // Continue to work in the mode the original database is in - tileMode = (tileTableMode == trpgTileTable::Local) ? TileLocal : TileExternal; + switch(tileTableMode) + { + case trpgTileTable::Local: + tileMode = TileLocal; + break; + case trpgTileTable::External: + tileMode = TileExternal; + break; + case trpgTileTable::ExternalSaved: + tileMode = TileExternalSaved; + break; + } + // That's it for the read archive delete inArch; @@ -177,6 +272,12 @@ trpgwArchive::~trpgwArchive() } } +// WriteHeaderData +int32 trpgwArchive::WriteHeaderData(const char *dataPtr, int length, FILE* /*filehandle*/) +{ + return fwrite(dataPtr,1,length,fp); +} + // IsValid() // Verifies that our file is open bool trpgwArchive::isValid() const @@ -206,9 +307,9 @@ void trpgwArchive::SetMaxTileFileLength(int 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; @@ -260,8 +361,8 @@ bool trpgwArchive::SetSupportStyleTable(const trpgSupportStyleTable &styles) /* Get Methods - Used in regenerate. - */ + Used in regenerate. +*/ trpgHeader *trpgwArchive::GetHeader() { return &header; @@ -326,8 +427,8 @@ void trpgwArchive::CloseFile() } /* Write Header - Flush out the header (checkpoint) and return. - */ + Flush out the header (checkpoint) and return. +*/ bool trpgwArchive::WriteHeader() { bool ret = CheckpointHeader(); @@ -341,10 +442,10 @@ bool trpgwArchive::WriteHeader() } /* CheckpointHeader - The header lives in its own file, so we can write it at any point we - have a valid archive. - This includes all the tables, as well as basic header info. - */ + The header lives in its own file, so we can write it at any point we + have a valid archive. + This includes all the tables, as well as basic header info. +*/ bool trpgwArchive::CheckpointHeader() { trpgMemWriteBuffer buf(ness); @@ -365,30 +466,83 @@ bool trpgwArchive::CheckpointHeader() } /* Build a Tile Table - We need to build one from scratch here. However, - we have all the relevant information collected during - the WriteTile calls. - */ + We need to build one from scratch here. However, + we have all the relevant information collected during + the WriteTile calls. + */ + + + if(header.GetIsLocal()) { + int row = 0; + int col = 0; + header.GetBlocks(row,col); + tileTable.SetCurrentBlock(row,col,true); + } if (tileMode == TileExternal) { // External tiles are easy tileTable.SetMode(trpgTileTable::External); - } else { - if (!isRegenerate && firstHeaderWrite) { - // Local tiles require more work - tileTable.SetMode(trpgTileTable::Local); + } else if( tileMode == TileExternalSaved) { + + if(!isRegenerate && firstHeaderWrite) + { // Set up the sizes - int32 numLod; - header.GetNumLods(numLod); - tileTable.SetNumLod(numLod); - for (int i=0;i= 1) + { + // Version 2.1, we store only lod 0 in the tile table + + // Set up the sizes + tileTable.SetNumLod(1); + trpg2iPoint lodSize; + header.GetLodSize(0,lodSize); + tileTable.SetNumTiles(lodSize.x, lodSize.y, 0); + + } + else + { + + // Set up the sizes + int32 numLod; + header.GetNumLods(numLod); + tileTable.SetNumLod(numLod); + for (int i=0;iGetVersion(majorVer,minorVer); + if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) { + separateGeo = true; + } + return new trpgwImageHelper(ness,dir,inTexTable,separateGeo); +} + +/* Increment Tile File. + Close the current tile file (if any) and open the next one. + Also update the records we're keeping of which tiles went in + which files. +*/ bool trpgwArchive::IncrementTileFile() { if (tileMode != TileLocal) @@ -583,7 +769,7 @@ bool trpgwArchive::IncrementTileFile() // Open the next one char filename[1024]; sprintf(filename,"%s" PATHSEPERATOR "tileFile_%d.tpf",dir,tileFileCount++); - tileFile = new trpgwAppFile(ness,filename); + tileFile = GetNewWAppFile(ness,filename,true); if (!tileFile->isValid()) return false; @@ -595,13 +781,13 @@ bool trpgwArchive::IncrementTileFile() } /* Designate Tile File - Close the current tile file (if any) and open one with the - given base name. This is used for regenerate. - */ + 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 (tileMode != TileLocal) - return false; + return false; // Close the current tile file if (tileFile) { @@ -612,9 +798,9 @@ bool trpgwArchive::DesignateTileFile(int id) // Open a named on char filename[1024]; sprintf(filename,"%s" PATHSEPERATOR "tileFile_%d.tpf",dir,id); - tileFile = new trpgwAppFile(ness,filename); + tileFile = GetNewWAppFile(ness,filename); if (!tileFile->isValid()) - return false; + return false; // Add another TileFiles entry tileFiles.resize(tileFiles.size()+1); @@ -624,20 +810,23 @@ bool trpgwArchive::DesignateTileFile(int id) } /* 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. - */ + 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) + const trpgMemWriteBuffer *head,const trpgMemWriteBuffer *buf, int32& fileId, int32& fileOffset) { FILE *tfp=NULL; if (!isValid()) return false; + fileId = -1; + fileOffset = -1; + // External tiles get their own individual files - if (tileMode == TileExternal) { + if (tileMode == TileExternal || tileMode == TileExternalSaved) { // Make a new filename char filename[1024]; // Note: Windows specific @@ -646,7 +835,7 @@ bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, flo return false; // Write the header first - unsigned int len; + unsigned int len; const char *data; if (head) { data = head->getData(); @@ -665,14 +854,29 @@ bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, flo return false; } fclose(tfp); + + // In version 2.1 and over we still add an entry to the tile table + // to save the zmin and zmax value. + if(tileMode == TileExternalSaved && lod == 0) + { + externalTiles.push_back(TileFileEntry()); + TileFileEntry& tf = externalTiles.back(); + tf.x = x; + tf.y = y; + tf.lod = lod; + tf.offset = -1; + tf.zmax = zmax; + tf.zmin = zmin; + } + } 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) + } + // See if we've exceeded the maximum advised size for a tile file + while (maxTileFileLen > 0 && tileFile->GetLengthWritten() > maxTileFileLen) { if (!IncrementTileFile()) return false; } @@ -685,7 +889,18 @@ bool trpgwArchive::WriteTile(unsigned int x,unsigned int y,unsigned int lod, flo 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); + if(majorVersion == 2 && minorVersion >=1) + { + // Version 2.1, we need to keep track of lod 0 only + if(lod == 0) + tf.tiles.push_back(te); + } + else + tf.tiles.push_back(te); + + fileOffset = pos; + + fileId = tileFiles[tileFiles.size()-1].id; } return true; @@ -783,7 +998,7 @@ void trpgwGeomHelper::EndPolygon() switch (mode) { case trpgGeometry::Triangles: - { + { int num = polyVert.size() - 2; int id1,id2; for (int i=0;iseparateGeoTypical = separateGeoTypical; maxTexFileLen = -1; } @@ -1165,6 +1387,8 @@ trpgwImageHelper::~trpgwImageHelper() { if (texFile) delete texFile; + if (geotypFile) + delete geotypFile; } bool trpgwImageHelper::AddExternal(char *name,int &texID,bool lookForExisting) @@ -1185,53 +1409,27 @@ void trpgwImageHelper::SetMaxTexFileLength(int len) maxTexFileLen = len; } -// doing this so people don't have to modify thier code, for both TXP users out there bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY, - bool isMipmap,char *data,int &texID) -{ - int depth; - switch (type) { - case trpgTexture::trpg_INT8: - depth = 1; - break; - case trpgTexture::trpg_INTA8: - depth = 2; - break; - case trpgTexture::trpg_RGB8: - case trpgTexture::trpg_FXT1: - case trpgTexture::trpg_DXT1: - case trpgTexture::trpg_DXT3: - case trpgTexture::trpg_DXT5: - depth = 3; - break; - case trpgTexture::trpg_RGBA8: - depth = 4; - break; - default: - depth = -1; - break; - } - - return AddLocal(name,type,sizeX,sizeY,depth,trpgTexture::trpg_RGBX_Neither,isMipmap,data,texID); -} - -bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY, int sizeZ, - trpgTexture::ImageOrg org, bool isMipmap,char *data,int &texID) + bool isMipmap,char *data,int &texID,bool deferWrite) { // Set up the basic texture trpgTexture tex; + if(texID!=-1) + tex.SetHandle(texID); tex.SetName(name); tex.SetImageMode(trpgTexture::Local); tex.SetImageType(type); + int depth; + tex.GetImageDepth(depth); + tex.SetNumLayer(depth); tex.SetImageSize(trpg2iPoint(sizeX,sizeY)); - tex.SetNumLayer(sizeZ); - tex.SetImageOrganization(org); tex.SetIsMipmap(isMipmap); // Write the image out to disk trpgwAppAddress addr; - if (!WriteToArchive(tex,data,addr)) - return false; + if(!deferWrite) + if (!WriteToArchive(tex,data,addr,true)) + return false; // Now add the specifics to the texture table tex.SetImageAddr(addr); @@ -1240,76 +1438,87 @@ bool trpgwImageHelper::AddLocal(char *name,trpgTexture::ImageType type,int sizeX return true; } -// doing this so people don't have to modify thier code, for both TXP users out there +bool trpgwImageHelper::ReplaceLocal(char *data,int &texID) +{ + const trpgTexture *texRef=texTable->GetTextureRef(texID); + + if (!texRef) return false; + + // Write the image out to disk + trpgwAppAddress addr; + if (!WriteToArchive(*texRef,data,addr,true)) + return false; + + // Now add the specifics to the texture table + const_cast(texRef)->SetImageAddr(addr); + + return true; +} + bool trpgwImageHelper::AddTileLocal(char *name,trpgTexture::ImageType type, int sizeX, int sizeY, bool isMipmap,char *data,int &texID,trpgwAppAddress &addr) -{ - int depth; - switch (type) { - case trpgTexture::trpg_INT8: - depth = 1; - break; - case trpgTexture::trpg_INTA8: - depth = 2; - break; - case trpgTexture::trpg_RGB8: - case trpgTexture::trpg_FXT1: - case trpgTexture::trpg_DXT1: - case trpgTexture::trpg_DXT3: - case trpgTexture::trpg_DXT5: - depth = 3; - break; - case trpgTexture::trpg_RGBA8: - depth = 4; - break; - default: - depth = -1; - break; - } - - return AddTileLocal(name,type,sizeX,sizeY,depth,trpgTexture::trpg_RGBX_Neither,isMipmap,data,texID,addr); -} - -bool trpgwImageHelper::AddTileLocal(char *name,trpgTexture::ImageType type, int sizeX, int sizeY, int sizeZ, - trpgTexture::ImageOrg org, bool isMipmap,char *data,int &texID,trpgwAppAddress &addr) { // Set up the texture template and add to the table trpgTexture tex; + if(texID!=-1) + tex.SetHandle(texID); tex.SetName(name); tex.SetImageMode(trpgTexture::Template); tex.SetImageType(type); + int depth; + tex.GetImageDepth(depth); + tex.SetNumLayer(depth); tex.SetImageSize(trpg2iPoint(sizeX,sizeY)); - tex.SetNumLayer(sizeZ); - tex.SetImageOrganization(org); tex.SetIsMipmap(isMipmap); texID = texTable->FindAddTexture(tex); // Write the specific data out to an archive (return the address) - if (!WriteToArchive(tex,data,addr)) + if (!WriteToArchive(tex,data,addr,false)) return false; + return true; } -/* Increment Texture File. - Close the current texture file (if any) and open the next one. +/* Get new appendable file. */ -bool trpgwImageHelper::IncrementTextureFile() +trpgwAppFile* trpgwImageHelper::GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse) { + return new trpgwAppFile(inNess,fileName,reuse); +} + +/* Increment Texture File. + Close the current texture file (if any) and open the next one. +*/ +trpgwAppFile * trpgwImageHelper::IncrementTextureFile(bool geotyp) { - // 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,static_cast(texFileIDs.size())); - texFile = new trpgwAppFile(ness,filename); - if (!texFile->isValid()) - return false; + trpgwAppFile *thefile = texFile; + + if(geotyp && separateGeoTypical) { + thefile = geotypFile; + sprintf(filename,"%s" PATHSEPERATOR "geotypFile_%d.txf",dir,static_cast(geotypFileIDs.size())); + } + else { + sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,static_cast(texFileIDs.size())); + } - texFileIDs.push_back(texFileIDs.size()); + // Closes the current texture file + if (thefile) delete thefile; + thefile = NULL; - return true; + // Open the next one + thefile = GetNewWAppFile(ness,filename,true); + if (!thefile->isValid()) + return NULL; + if(geotyp && separateGeoTypical) { + geotypFileIDs.push_back(geotypFileIDs.size()); + geotypFile = thefile; + } + else { + texFileIDs.push_back(texFileIDs.size()); + texFile = thefile; + } + return thefile; } // Flush current texture file (if any) @@ -1317,14 +1526,15 @@ bool trpgwImageHelper::Flush() { if (texFile) texFile->Flush(); - + if (geotypFile) + geotypFile->Flush(); return true; } /* Designate Texture File - Close the curren texture file (if any) and open one with the given - base name. - */ + 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 @@ -1334,45 +1544,61 @@ bool trpgwImageHelper::DesignateTextureFile(int id) // Open one with the given base name char filename[1024]; sprintf(filename,"%s" PATHSEPERATOR "texFile_%d.txf",dir,id); - texFile = new trpgwAppFile(ness,filename); + texFile = GetNewWAppFile(ness,filename); if (!texFile->isValid()) - return false; - + return false; texFileIDs.push_back(id); + sprintf(filename,"%s" PATHSEPERATOR "geotypFile_%d.txf",dir,id); + geotypFile = GetNewWAppFile(ness,filename); + if (!geotypFile->isValid()) + return false; + geotypFileIDs.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. + 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) +bool trpgwImageHelper::WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr,bool geotyp) { 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; - } + trpgwAppFile *thefile = texFile; + if(geotyp && separateGeoTypical) { + thefile = geotypFile; } + + // Get a usable texture archive file + if (!thefile) { + if (! (thefile=IncrementTextureFile(geotyp && separateGeoTypical))) + return false; + } + + while (maxTexFileLen > 0 && thefile->GetLengthWritten() > maxTexFileLen) { + if (!(thefile=IncrementTextureFile(geotyp && separateGeoTypical))) + return false; + } + + // Get the current address - addr.file = texFileIDs[texFileIDs.size()-1]; - addr.offset = static_cast(texFile->Pos()); + if(geotyp && separateGeoTypical) { + addr.file = geotypFileIDs[geotypFileIDs.size()-1]; + } + else { + addr.file = texFileIDs[texFileIDs.size()-1]; + } + addr.offset = (int32)thefile->Pos(); // Write the data out to the archive. int totSize = tex.CalcTotalSize(); - if (!texFile->Append(data,totSize)) + if (!thefile->Append(data,totSize)) return false; return true; diff --git a/src/osgPlugins/txp/trpage_write.h b/src/osgPlugins/txp/trpage_write.h index 77a9a46a4..d1c4f7b42 100644 --- a/src/osgPlugins/txp/trpage_write.h +++ b/src/osgPlugins/txp/trpage_write.h @@ -18,313 +18,342 @@ #define _txpage_write_h_ /* trpage_write.h - Classes that are used to write paging archives. - */ + Classes that are used to write paging archives. + */ #include #include #include +#include /* 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;} + // Helper functions + inline void AddStripStat(int val) { stripStat[MIN(14,val)]++; totalStripTri += val; totalTri += val; numStrip++;} + inline void AddFanStat(int val) { fanStat[MIN(14,val)]++; totalFanTri += val; totalTri += val; numFan++;} + inline void AddBagStat(int val) { totalBagTri += val; totalTri += val;} inline void AddQuadStat(int val) { totalQuad += val; } }; /* Geometry Helper - Collects up geometry and tries to form triangle strips, fans, - and groups of triangles. - Right now this looks for a very careful ordering. If that ordering - isn't there you won't get useful tristrips or fans. You can, however - use this class as a starting point and build something more akin - to the geometry builder in Performer. - {group:Archive Writing} + Collects up geometry and tries to form triangle strips, fans, + and groups of triangles. + Right now this looks for a very careful ordering. If that ordering + isn't there you won't get useful tristrips or fans. You can, however + use this class as a starting point and build something more akin + to the geometry builder in Performer. + {group:Archive Writing} */ TX_EXDECL class TX_CLDECL trpgwGeomHelper { public: - trpgwGeomHelper(void); - virtual ~trpgwGeomHelper(void); - enum {UseDouble,UseFloat}; - trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble); - void init(trpgWriteBuffer *,int dataType=UseDouble); - virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default) - virtual void Reset(void); - // Start/End polygon definition - virtual void StartPolygon(void); - virtual void EndPolygon(void); - virtual void ResetPolygon(void); // If you change your mind about the current poly - // Set the current state - // Note: Currently you *must* set all of these - virtual void SetColor(trpgColor &); - virtual void SetTexCoord(trpg2dPoint &); - virtual void AddTexCoord(trpg2dPoint &); // for multiple textures - virtual void SetNormal(trpg3dPoint &); - virtual void SetMaterial(int32); - virtual void AddMaterial(int32); // for multiple textures - // Pull the state info together and add a vertex - virtual void AddVertex(trpg3dPoint &); + trpgwGeomHelper(void); + virtual ~trpgwGeomHelper(void); + enum {UseDouble,UseFloat}; + trpgwGeomHelper(trpgWriteBuffer *,int dataType=UseDouble); + void init(trpgWriteBuffer *,int dataType=UseDouble); + virtual void SetMode(int); // Takes a trpgGeometry primitive type (triangle by default) + virtual void Reset(void); + // Start/End polygon definition + virtual void StartPolygon(void); + virtual void EndPolygon(void); + virtual void ResetPolygon(void); // If you change your mind about the current poly + // Set the current state + // Note: Currently you *must* set all of these + virtual void SetColor(trpgColor &); + virtual void SetTexCoord(trpg2dPoint &); + virtual void AddTexCoord(trpg2dPoint &); // for multiple textures + virtual void SetNormal(trpg3dPoint &); + virtual void SetMaterial(int32); + virtual void AddMaterial(int32); // for multiple textures + // Pull the state info together and add a vertex + virtual void AddVertex(trpg3dPoint &); - // Dump whatever we're doing and move on - virtual void FlushGeom(void); + // Dump whatever we're doing and move on + virtual void FlushGeom(void); - // Get the Min and Max Z values - virtual void GetZMinMax(double &min,double &max); + // Get the Min and Max Z values + virtual void GetZMinMax(double &min,double &max); - // Get statistics for whatever we built - trpgwGeomStats *GetStats(void) { return &stats; } + // Get statistics for whatever we built + trpgwGeomStats *GetStats(void) { return &stats; } protected: - int mode; - int dataType; - trpgWriteBuffer *buf; + int mode; + int dataType; + trpgWriteBuffer *buf; - /* Builds strips and fans from the triangle array. - We (TERREX) are assuming a certain ordering in our vertex array - because we do this optimization elsewhere. This won't work well - for anyone else. What you will need to do if you want good - performance is to implement a more generic form of this method. - All you should have to do is override Optimize(). You've - got the triangle arrays and a guarantee that the triangles - have the same material. All you really need is a decent fan/strip - algorithm. - */ - virtual void Optimize(void); + /* Builds strips and fans from the triangle array. + We (TERREX) are assuming a certain ordering in our vertex array + because we do this optimization elsewhere. This won't work well + for anyone else. What you will need to do if you want good + performance is to implement a more generic form of this method. + All you should have to do is override Optimize(). You've + got the triangle arrays and a guarantee that the triangles + have the same material. All you really need is a decent fan/strip + algorithm. + */ + virtual void Optimize(void); - // Reset Triangle arrays - virtual void ResetTri(void); + // Reset Triangle arrays + virtual void ResetTri(void); - // Collections of geometry - trpgGeometry strips,fans,bags; + // Collections of geometry + trpgGeometry strips,fans,bags; - // Temporary data arrays for triangles/quads - std::vector matTri; - std::vector tex; - std::vector norm,vert; - // Data arrays for a polygon - std::vector matPoly; - std::vector polyTex; - std::vector polyNorm,polyVert; - // Single points - std::vector tmpTex; - trpg3dPoint tmpNorm; - trpgColor tmpCol; + // Temporary data arrays for triangles/quads + std::vector matTri; + std::vector tex; + std::vector norm,vert; + // Data arrays for a polygon + std::vector matPoly; + std::vector polyTex; + std::vector polyNorm,polyVert; + // Single points + std::vector tmpTex; + trpg3dPoint tmpNorm; + trpgColor tmpCol; - // Geometry status built up as we go - trpgwGeomStats stats; + // Geometry status built up as we go + trpgwGeomStats stats; - // Keeps track of min and max z values - double zmin,zmax; + // Keeps track of min and max z values + double zmin,zmax; }; /* Image Write Helper. - Used to manage textures being added to a TerraPage archive. - It can write Local and Tile Local textures and also manages - the names of External textures (but you have to write those yourself). + Used to manage textures being added to a TerraPage archive. + It can write Local and Tile Local textures and also manages + the names of External textures (but you have to write those yourself). */ TX_EXDECL class TX_CLDECL trpgwImageHelper { public: - trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &); - virtual ~trpgwImageHelper(void); + trpgwImageHelper() {;}; + trpgwImageHelper(trpgEndian ness,char *dir,trpgTexTable &,bool separateGeoTypical); + // construction is really here + virtual void Init(trpgEndian ness,char *dir,trpgTexTable &,bool separateGeoTypical); - // Adds an entry to the texture table for an external texture - virtual bool AddExternal(char *name,int &texID,bool lookForExisting=true); + virtual ~trpgwImageHelper(void); - /* Adds an entry to the texture table for a local texture and - writes the data for that texture out to one of our texture - archive files. - */ - virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data,int &texID); - virtual bool AddLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,int sizeZ,trpgTexture::ImageOrg org,bool isMipmap,char *data,int &texID); + // Adds an entry to the texture table for an external texture + virtual bool AddExternal(char *name,int &texID,bool lookForExisting=true); - /* Write a Tile Local texture out to one of our texture archive files. - Also creates a texture template, if necessary. - Caller is responsible for creating the Tile Local material and - placing it in the appropriate tile. - */ - virtual bool AddTileLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,bool isMipmap,char *data, int &texID,trpgwAppAddress &addr); - virtual bool AddTileLocal(char *name,trpgTexture::ImageType type,int sizeX,int sizeY,int sizeZ,trpgTexture::ImageOrg org,bool isMipmap,char *data, int &texID,trpgwAppAddress &addr); + /* 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,bool deferWrite); - /* 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); + /* Replaces texture table information for a local texture and + writes the data for that texture out to one of our texture + archive files. + Up to you to ensure data is appropriate for the texture. + */ + virtual bool ReplaceLocal(char *data,int &texID); - /* 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); + /* 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); - /* Close the current texture file and go on to one with the - given base name. This is used for regenerate. - */ - virtual bool DesignateTextureFile(int); + /* 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); - // Flush current texture output files - virtual bool Flush(void); + /* Texture archive files are managed by this class and will + be created as needed. This method will increment to + the next texture file. + Note: This may create more files than we really need. + */ + virtual trpgwAppFile * IncrementTextureFile(bool geotyp); + /* Close the current texture file and go on to one with the + given base name. This is used for regenerate. + */ + virtual bool DesignateTextureFile(int); + + // Flush current texture output files + virtual bool Flush(void); + + // Get a new appendable file + virtual trpgwAppFile* GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse=false); + + // Write the given texture data into one our local archives + bool WriteToArchive(const trpgTexture &tex,char *data,trpgwAppAddress &addr,bool geotyp=false); + // Merge block textable into a master. + 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; + + trpgEndian ness; + char dir[1024]; + trpgTexTable *texTable; + std::vector texFileIDs; + trpgwAppFile *texFile; + std::vector geotypFileIDs; + trpgwAppFile *geotypFile; + bool separateGeoTypical; + int maxTexFileLen; }; /* Paging Archive - This is a writeable paging archive. - It organizes where things get written and how. - {group:Archive Writing} - */ + This is a writeable paging archive. + It organizes where things get written and how. + {group:Archive Writing} + */ TX_EXDECL class TX_CLDECL trpgwArchive : public trpgCheckable { public: - // Tiles can be stored as individual files (External) or grouped together (Local) - typedef enum {TileLocal,TileExternal} TileMode; + // Tiles can be stored as individual files (External) or grouped together (Local) + enum TileMode {TileLocal,TileExternal,TileExternalSaved}; - // Add data to an existing archive - trpgwArchive(char *baseDir,char *name,trpg2dPoint &ll,trpg2dPoint &ur); - // Start an archive from scratch. - trpgwArchive(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int version=2); - virtual ~trpgwArchive(void); + // real constructor work done in Init(...) now for quasi-virtual ctor action. + // Add data to an existing archive + trpgwArchive(char *baseDir,char *name,trpg2dPoint &ll,trpg2dPoint &ur, int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR); + virtual void Init(char *baseDir,char *name,trpg2dPoint &ll,trpg2dPoint &ur, int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR); + // Start an archive from scratch. + trpgwArchive(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR); + virtual void Init(trpgEndian ness=LittleEndian,TileMode tileMode=TileLocal,int majorVer=TRPG_VERSION_MAJOR, int minorVer=TRPG_VERSION_MINOR); + // dummy constructor, does nothing so subclasses can have more control + trpgwArchive(int ) {;}; + virtual ~trpgwArchive(void); - // Set the maximum length for a tile file (if using them) - // This is only a suggestion for when to stop appending - virtual void SetMaxTileFileLength(int len); + // Set the maximum length for a tile file (if using them) + // This is only a suggestion for when to stop appending + virtual void SetMaxTileFileLength(int len); - // Set functions. Have to fill all these out before writing - virtual bool SetHeader(const trpgHeader &); - virtual bool SetMaterialTable(const trpgMatTable &); - virtual bool SetTextureTable(const trpgTexTable &); - virtual bool SetModelTable(const trpgModelTable &); - virtual bool SetLightTable(const trpgLightTable &); - virtual bool SetRangeTable(const trpgRangeTable &); - virtual bool SetLabelPropertyTable(const trpgLabelPropertyTable &); - virtual bool SetSupportStyleTable(const trpgSupportStyleTable &); - virtual bool SetTextStyleTable(const trpgTextStyleTable &); + // Set functions. Have to fill all these out before writing + virtual bool SetHeader(const trpgHeader &); + virtual bool SetMaterialTable(const trpgMatTable &); + virtual bool SetTextureTable(const trpgTexTable &); + virtual bool SetModelTable(const trpgModelTable &); + virtual bool SetLightTable(const trpgLightTable &); + virtual bool SetRangeTable(const trpgRangeTable &); + virtual bool SetLabelPropertyTable(const trpgLabelPropertyTable &); + virtual bool SetSupportStyleTable(const trpgSupportStyleTable &); + virtual bool SetTextStyleTable(const trpgTextStyleTable &); - // Get functions. If we're doing a regenerate we need to get at these - virtual trpgHeader *GetHeader(); - virtual trpgMatTable *GetMatTable(); - virtual trpgTexTable *GetTextureTable(); - virtual trpgModelTable *GetModelTable(); - virtual trpgLightTable *GetLightTable(); - virtual trpgRangeTable *GetRangeTable(); - virtual trpgLabelPropertyTable *GetLabelPropertyTable(); - virtual trpgTextStyleTable *GetTextStyleTable(); - virtual trpgSupportStyleTable *GetSupportStyleTable(); + // Get functions. If we're doing a regenerate we need to get at these + virtual trpgHeader *GetHeader(); + virtual trpgMatTable *GetMatTable(); + virtual trpgTexTable *GetTextureTable(); + virtual trpgModelTable *GetModelTable(); + virtual trpgLightTable *GetLightTable(); + virtual trpgRangeTable *GetRangeTable(); + virtual trpgLabelPropertyTable *GetLabelPropertyTable(); + virtual trpgTextStyleTable *GetTextStyleTable(); + virtual trpgSupportStyleTable *GetSupportStyleTable(); - virtual bool IncrementTileFile(void); - virtual bool DesignateTileFile(int); + virtual bool IncrementTileFile(void); + virtual bool DesignateTileFile(int); - // Write functions. - // For now, the header is written last. + // Write functions. + // For now, the header is written last. - virtual bool OpenFile(const char *,const char *); - virtual void CloseFile(void); - virtual bool WriteHeader(void); - virtual bool CheckpointHeader(void); - virtual bool WriteTile(unsigned int,unsigned int,unsigned int,float zmin,float zmax, - const trpgMemWriteBuffer *,const trpgMemWriteBuffer *); -// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &); - - bool isValid(void) const; - const char *getErrMess() const; - char* getDir(void){return dir;}; - - class TileFileEntry { - public: - int x,y,lod; // Identifying info for tile - float zmin,zmax; - int32 offset; // Offset into file - }; - class TileFile { - public: - int id; - std::vector tiles; - }; + virtual bool OpenFile(const char *,const char *); + virtual void CloseFile(void); + virtual bool WriteHeader(void); + virtual bool CheckpointHeader(void); + virtual bool WriteTile(unsigned int,unsigned int,unsigned int,float zmin,float zmax, + const trpgMemWriteBuffer *,const trpgMemWriteBuffer *, int32& fileId, int32& fileOffset); +// virtual bool WriteModel(unsigned int,trpgMemWriteBuffer &); + bool isValid(void) const; + const char *getErrMess() const; + char* getDir(void){return dir;}; + virtual trpgwImageHelper* GetNewWImageHelper(trpgEndian ness,char *dir,trpgTexTable &); + virtual trpgwAppFile* GetNewWAppFile(trpgEndian inNess,const char *fileName,bool reuse=false); + virtual trpgr_Archive* GetArchiveReader() {return new trpgr_Archive();}; + virtual int32 WriteHeaderData(const char *dataPtr,int32 length,FILE *filehandle); + virtual int32 GetMagicNumber() {return TRPG_MAGIC;}; protected: - // Set if we're adding to an existing archive - bool isRegenerate; + // Set if we're adding to an existing archive + bool isRegenerate; - // Used to keep track of which tiles are in which file + // Used to keep track of which tiles are in which file + class TileFileEntry { + public: + int x,y,lod; // Identifying info for tile + float zmin,zmax; + int32 offset; // Offset into file + }; + class TileFile { + public: + int id; + std::vector tiles; + }; - trpgEndian ness,cpuNess; - int version; - // Fed in from the outside - char dir[1024]; // Directory where we're doing all this + trpgEndian ness,cpuNess; + int majorVersion, minorVersion; + // Fed in from the outside + char dir[1024]; // Directory where we're doing all this - // These are passed in + // These are passed in - trpgHeader header; - trpgMatTable matTable; - trpgTexTable texTable; - trpgModelTable modelTable; - trpgLightTable lightTable; - trpgRangeTable rangeTable; - trpgTextStyleTable textStyleTable; - trpgSupportStyleTable supportStyleTable; - trpgLabelPropertyTable labelPropertyTable; + trpgHeader header; + trpgMatTable matTable; + trpgTexTable texTable; + trpgModelTable modelTable; + trpgLightTable lightTable; + trpgRangeTable rangeTable; + trpgTextStyleTable textStyleTable; + trpgSupportStyleTable supportStyleTable; + trpgLabelPropertyTable labelPropertyTable; - trpgTileTable tileTable; + trpgTileTable tileTable; - int numX,numY,numLod; - TileMode tileMode; + int numX,numY,numLod; + TileMode tileMode; - trpgwAppFile *tileFile; - int tileFileCount; + trpgwAppFile *tileFile; + int tileFileCount; - std::vector tileFiles; + std::vector tileFiles; - int maxTileFileLen; + std::vector externalTiles; - // This offset is used when we're adding to an existing archive - trpg2iPoint addOffset; + int maxTileFileLen; - FILE *fp; + // This offset is used when we're adding to an existing archive + trpg2iPoint addOffset; - bool firstHeaderWrite; + FILE *fp; - mutable char errMess[512]; + bool firstHeaderWrite; + + mutable char errMess[512]; }; #endif diff --git a/src/osgPlugins/txp/trpage_writebuf.cpp b/src/osgPlugins/txp/trpage_writebuf.cpp index 154aaeaf7..69c20c656 100644 --- a/src/osgPlugins/txp/trpage_writebuf.cpp +++ b/src/osgPlugins/txp/trpage_writebuf.cpp @@ -18,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 #include @@ -39,158 +39,158 @@ // Constructor trpgMemWriteBuffer::trpgMemWriteBuffer(trpgEndian in_ness) { - ness = in_ness; - cpuNess = trpg_cpu_byte_order(); - data = NULL; - curLen = totLen = 0; + ness = in_ness; + cpuNess = trpg_cpu_byte_order(); + data = NULL; + curLen = totLen = 0; } // Destructor trpgMemWriteBuffer::~trpgMemWriteBuffer() { - if (data) - delete [] data; - data = NULL; + if (data) + delete [] data; + data = NULL; } /* Length() - Return the length of the given buffer. - */ + Return the length of the given buffer. + */ int trpgMemWriteBuffer::length() const { - return curLen; + return curLen; } /* getData() - Return a pointer to the memory buffer. - */ + Return a pointer to the memory buffer. + */ const char *trpgMemWriteBuffer::getData() const { - return data; + return data; } /* Length() - Set the maximum buffer length. - */ + Set the maximum buffer length. + */ void trpgMemWriteBuffer::setLength(unsigned int len) { - if ((int)len > totLen) { - char *old_data = data; - int oldLen = totLen; - totLen = 2*len; - data = new char[totLen]; + if ((int)len > totLen) { + char *old_data = data; + int oldLen = totLen; + totLen = 2*len; + data = new char[totLen]; - if (old_data) { - memcpy(data,old_data,oldLen); - delete [] old_data; - } - } + if (old_data) { + memcpy(data,old_data,oldLen); + delete [] old_data; + } + } } /* append() - Append the given data to our buffer. - */ + Append the given data to our buffer. + */ void trpgMemWriteBuffer::append(unsigned int len,const char *val) { - if (len == 0) return; - setLength(curLen+len); - memcpy(&data[curLen],val,len); - curLen += len; + if (len == 0) return; + setLength(curLen+len); + memcpy(&data[curLen],val,len); + curLen += len; } /* set() - Set a specific portion of the buffer to a given value. - */ + Set a specific portion of the buffer to a given value. + */ void trpgMemWriteBuffer::set(unsigned int pos,unsigned int len,const char *val) { - if (len == 0) return; - if (pos+len > (unsigned int)curLen) return; + if (len == 0) return; + if (pos+len > (unsigned int)curLen) return; - memcpy(&data[pos],val,len); + memcpy(&data[pos],val,len); } /* --- replacement virtual functions --- */ /* Reset() - Drop whatever's being stored. - */ + Drop whatever's being stored. + */ void trpgMemWriteBuffer::Reset() { - curLen = 0; + curLen = 0; } // Add(Int32) void trpgMemWriteBuffer::Add(int32 val) { - if (ness != cpuNess) - val = trpg_byteswap_int(val); - append(sizeof(int32),(const char *)&val); + if (ness != cpuNess) + val = trpg_byteswap_int(val); + append(sizeof(int32),(const char *)&val); } // Add(int64) void trpgMemWriteBuffer::Add(int64 val) { - if (ness != cpuNess) - val = trpg_byteswap_llong(val); - append(sizeof(int64),(const char *)&val); + if (ness != cpuNess) + val = trpg_byteswap_llong(val); + append(sizeof(int64),(const char *)&val); } // Add(string) // [len] [value...] void trpgMemWriteBuffer::Add(const char *val) { - int32 len = (val ? strlen(val) : 0),vlen = len; - if (ness != cpuNess) - vlen = trpg_byteswap_int(vlen); - append(sizeof(int32),(const char *)&vlen); - append(len,val); + int32 len = (val ? strlen(val) : 0),vlen = len; + if (ness != cpuNess) + vlen = trpg_byteswap_int(vlen); + append(sizeof(int32),(const char *)&vlen); + append(len,val); } // Add(std::string) void trpgMemWriteBuffer::Add(std::string &val) { - Add(val.c_str()); + Add(val.c_str()); } // Add(float32) void trpgMemWriteBuffer::Add(float32 val) { - char cval[4]; - if (ness != cpuNess) - trpg_byteswap_float_to_4bytes(val,cval); - else - memcpy(cval,&val,4); + char cval[4]; + if (ness != cpuNess) + trpg_byteswap_float_to_4bytes(val,cval); + else + memcpy(cval,&val,4); - append(sizeof(float32),cval); + append(sizeof(float32),cval); } // Add(float64) void trpgMemWriteBuffer::Add(float64 val) { - char cval[8]; - if (ness != cpuNess) - trpg_byteswap_double_to_8bytes(val,cval); - else - memcpy(cval,&val,8); + char cval[8]; + if (ness != cpuNess) + trpg_byteswap_double_to_8bytes(val,cval); + else + memcpy(cval,&val,8); - append(sizeof(float64),cval); + append(sizeof(float64),cval); } // Add(int8) void trpgMemWriteBuffer::Add(uint8 val) { - // No byte swapping needed - append(sizeof(uint8),(const char *)&val); + // No byte swapping needed + append(sizeof(uint8),(const char *)&val); } //#if (bool != int32) // Add(bool) void trpgMemWriteBuffer::Add(bool val) { - uint8 ival; + uint8 ival; - ival = (val ? 1 : 0); - Add(ival); + ival = (val ? 1 : 0); + Add(ival); } //#endif @@ -198,127 +198,169 @@ void trpgMemWriteBuffer::Add(bool val) // Add(trpgDiskRef) void trpgMemWriteBuffer::Add(trpgDiskRef val) { - if (ness != cpuNess) - val = trpg_byteswap_llong(val); + if (ness != cpuNess) + val = trpg_byteswap_llong(val); - append(sizeof(trpgDiskRef),(const char *)&val); + append(sizeof(trpgDiskRef),(const char *)&val); } #endif // Add(trpgToken) void trpgMemWriteBuffer::Add(trpgToken val) { - if (ness != cpuNess) - val = trpg_byteswap_short(val); + if (ness != cpuNess) + val = trpg_byteswap_short(val); - append(sizeof(trpgToken),(const char *)&val); + append(sizeof(trpgToken),(const char *)&val); } // Add(tx2iPoint) void trpgWriteBuffer::Add(const trpg2iPoint &val) { - Add((int32)val.x); - Add((int32)val.y); + Add((int32)val.x); + Add((int32)val.y); } // Add(tx2dPoint) void trpgWriteBuffer::Add(const trpg2dPoint &val) { - Add((float64)val.x); - Add((float64)val.y); + Add((float64)val.x); + Add((float64)val.y); } // Add(trpg3dPoint) void trpgWriteBuffer::Add(const trpg3dPoint &val) { - Add((float64)val.x); - Add((float64)val.y); - Add((float64)val.z); + Add((float64)val.x); + Add((float64)val.y); + Add((float64)val.z); } // Add(trpgColor) void trpgWriteBuffer::Add(const trpgColor &val) { - Add(val.red); - Add(val.green); - Add(val.blue); + Add(val.red); + Add(val.green); + Add(val.blue); } // Add(std::string) void trpgWriteBuffer::Add(const std::string &val) { - Add(val.c_str()); + Add(val.c_str()); } /* Push() - Starts defining a new object. - Need to keep track of where length goes. - */ + Starts defining a new object. + Need to keep track of where length goes. + */ void trpgMemWriteBuffer::Begin(trpgToken tok) { - Add(tok); - lengths.push_back(curLen); - Add((int32)0); + Add(tok); + lengths.push_back(curLen); + Add((int32)0); } /* Push() - Pushes a level on the stack. For defining children. - */ + Pushes a level on the stack. For defining children. + */ void trpgMemWriteBuffer::Push() { - Add((trpgToken)TRPG_PUSH); + Add((trpgToken)TRPG_PUSH); } /* Pop() - Pops a level off the "stack". - */ + Pops a level off the "stack". + */ void trpgMemWriteBuffer::Pop() { - Add((trpgToken)TRPG_POP); + Add((trpgToken)TRPG_POP); +} + +/* Will take out a pop from the end of the buffer, if there is one */ +bool trpgMemWriteBuffer::UnPop() +{ + //Check to see if there is a pop token ant the end + trpgToken tk; + memcpy(&tk, &data[curLen - sizeof(trpgToken)], sizeof(trpgToken)); + if(tk == TRPG_POP) + { + curLen -= sizeof(trpgToken); + return true; + } + else + return false; +} +/* Will take out a push from the end of the buffer, if there is one */ +bool trpgMemWriteBuffer::UnPush() +{ + //Check to see if there is a push token ant the end + trpgToken tk; + memcpy(&tk, &data[curLen - sizeof(trpgToken)], sizeof(trpgToken)); + if(tk == TRPG_PUSH) + { + curLen -= sizeof(trpgToken); + return true; + } + else + return false; } /* End() - Finished defining an object. - Write the length out where appropriate. - */ + Finished defining an object. + Write the length out where appropriate. + */ void trpgMemWriteBuffer::End() { - if (lengths.size() == 0) - // Note: say something clever here - return; + if (lengths.size() == 0) + // Note: say something clever here + return; - int id = lengths.size()-1; - int32 len = curLen - lengths[id]; - int32 rlen = len-sizeof(int32); - if (ness != cpuNess) - rlen = trpg_byteswap_int(rlen); - set(curLen - len,sizeof(int32),(const char *)&rlen); - lengths.resize(id); + int id = lengths.size()-1; + int32 len = curLen - lengths[id]; + int32 rlen = len-sizeof(int32); + if (ness != cpuNess) + rlen = trpg_byteswap_int(rlen); + set(curLen - len,sizeof(int32),(const char *)&rlen); + lengths.resize(id); } /* Appendable File - This class is used as a simple appendable file. It's used - for dumping tile and texture (or most anything) into. + This class is used as a simple appendable file. It's used + for dumping tile and texture (or most anything) into. */ -trpgwAppFile::trpgwAppFile(trpgEndian inNess,const char *fileName) +trpgwAppFile::trpgwAppFile(trpgEndian inNess,const char *fileName,bool reuse) { - valid = false; - ness = inNess; - cpuNess = trpg_cpu_byte_order(); + Init(inNess,fileName,reuse); +} - if (!(fp = fopen(fileName,"wb"))) - return; +void trpgwAppFile::Init(trpgEndian inNess,const char *fileName,bool reuse) +{ + valid = false; + ness = inNess; + cpuNess = trpg_cpu_byte_order(); - lengthSoFar = 0; - valid = true; + if (reuse==false) { + if (!(fp = fopen(fileName,"wb"))) + return; + lengthSoFar = 0; + valid = true; + } else { + if (!(fp = fopen(fileName,"ab"))) + return; + // ftell is still zero, dammit. Arg. + fseek(fp,0,SEEK_END); + lengthSoFar = ftell(fp); + valid = true; + } } trpgwAppFile::~trpgwAppFile() { - if (fp) - fclose(fp); - valid = false; + if (fp) + fclose(fp); + valid = false; } // Return the amount of data written so far (in total) @@ -330,87 +372,87 @@ int trpgwAppFile::GetLengthWritten() // Append the given buffer to our appendable file bool trpgwAppFile::Append(const trpgMemWriteBuffer *buf1,const trpgMemWriteBuffer *buf2) { - if (!isValid()) return false; + if (!isValid()) return false; - // Get the total length - int totLen = buf1->length() + (buf2 ? buf2->length() : 0); + // Get the total length + int totLen = buf1->length() + (buf2 ? buf2->length() : 0); - // Write the length out - if (fwrite(&totLen,sizeof(int32),1,fp) != 1) { - valid = false; - return false; - } + // Write the length out + if (fwrite(&totLen,sizeof(int32),1,fp) != 1) { + valid = false; + return false; + } - // Write the data out - const char *data = buf1->getData(); - int len = buf1->length(); - if (fwrite(data,sizeof(char),len,fp) != (unsigned int)len) { - valid = false; - return false; - } - if (buf2) { - data = buf2->getData(); - len = buf2->length(); - if (fwrite(data,sizeof(char),len,fp) != (unsigned int)len) { - valid = false; - return false; - } - } + // Write the data out + const char *data = buf1->getData(); + unsigned int len = buf1->length(); + if (fwrite(data,sizeof(char),len,fp) != len) { + valid = false; + return false; + } + if (buf2) { + data = buf2->getData(); + len = buf2->length(); + if (fwrite(data,sizeof(char),len,fp) != len) { + valid = false; + return false; + } + } - lengthSoFar += totLen; + lengthSoFar += totLen; - return true; + return true; } // Append the given raw data to our appendable file bool trpgwAppFile::Append(const char *data,int size) { - if (!isValid()) return false; + if (!isValid()) return false; - if (!data) - return false; + if (!data) + return false; - // Write the length out - if (fwrite(&size,sizeof(int32),1,fp) != 1) { - valid = false; - return false; - } + // Write the length out + if (fwrite(&size,sizeof(int32),1,fp) != 1) { + valid = false; + return false; + } - // Write the data out - if (fwrite(data,sizeof(char),size,fp) != (unsigned int)size) { - valid = false; - return false; - } + // Write the data out + if (fwrite(data,sizeof(char),size,fp) != (size_t)size) { + valid = false; + return false; + } - lengthSoFar += size; + lengthSoFar += size; - return true; + return true; } // Flushes the current tile file bool trpgwAppFile::Flush() { - // Flush the File * - if (fp) - fflush(fp); + // Flush the File * + if (fp) + fflush(fp); - return true; + return true; } // Return the current file position int64 trpgwAppFile::Pos() const { - if (!isValid()) - return 0; - - // Note: This means an appendable file is capped at 2GB - long pos = ftell(fp); + if (!isValid()) + return 0; + + // Note: This means an appendable file is capped at 2GB + long pos = ftell(fp); - return pos; + return pos; } // Validity check bool trpgwAppFile::isValid() const { - return valid; + return valid; }