diff --git a/src/osgPlugins/txp/TXPArchive.cpp b/src/osgPlugins/txp/TXPArchive.cpp index a734f8057..5f80793db 100644 --- a/src/osgPlugins/txp/TXPArchive.cpp +++ b/src/osgPlugins/txp/TXPArchive.cpp @@ -544,6 +544,7 @@ bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info) header.GetLodRange(lod,info.maxRange); header.GetLodRange(lod+1,info.minRange); + header.GetLodRange(0,info.lod0Range); trpg2dPoint sw,ne; header.GetExtents(sw,ne); @@ -551,6 +552,10 @@ bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info) trpg2dPoint size; header.GetTileSize(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; @@ -582,7 +587,8 @@ osg::Group* TXPArchive::getTileContent( int x, int y, int lod, double realMinRange, double realMaxRange, - double usedMaxRange) + double usedMaxRange, + osg::Vec3& tileCenter) { if (_parser.get() == 0) { @@ -597,6 +603,7 @@ osg::Group* TXPArchive::getTileContent( } osg::Group *tileGroup = _parser->parseScene(buf,_gstates,_models,realMinRange,realMaxRange,usedMaxRange); + tileCenter = _parser->getTileCenter(); return tileGroup; } diff --git a/src/osgPlugins/txp/TXPArchive.h b/src/osgPlugins/txp/TXPArchive.h index b508420ac..c1c313430 100644 --- a/src/osgPlugins/txp/TXPArchive.h +++ b/src/osgPlugins/txp/TXPArchive.h @@ -91,10 +91,12 @@ public: // Gets some informations for a given tile struct TileInfo { - osg::Vec3 center; + 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); @@ -141,7 +143,8 @@ public: int lod, double realMinRange, double realMaxRange, - double usedMaxRange); + double usedMaxRange, + osg::Vec3& tileCenter); // Get the number of tiles for given LOD bool getLODSize(int lod, int& x, int& y); diff --git a/src/osgPlugins/txp/TXPPagedLOD.h b/src/osgPlugins/txp/TXPPagedLOD.h index 22e47d2d4..5673e0962 100644 --- a/src/osgPlugins/txp/TXPPagedLOD.h +++ b/src/osgPlugins/txp/TXPPagedLOD.h @@ -63,13 +63,15 @@ namespace txp _neighbours.push_back(n); } - protected: - virtual ~TXPPagedLOD(); - int _tileX; int _tileY; int _tileLOD; + protected: + virtual ~TXPPagedLOD(); + + + struct Neighbour { int _x, _y; diff --git a/src/osgPlugins/txp/TXPParser.cpp b/src/osgPlugins/txp/TXPParser.cpp index 0e7f7fba2..e6092ff0c 100644 --- a/src/osgPlugins/txp/TXPParser.cpp +++ b/src/osgPlugins/txp/TXPParser.cpp @@ -39,6 +39,7 @@ _realMinRange(0.0), _realMaxRange(0.0), _usedMaxRange(0.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)); @@ -83,6 +84,8 @@ osg::Group *TXPParser::parseScene( _realMaxRange = realMaxRange; _usedMaxRange = usedMaxRange; + _tileCenter = osg::Vec3(0.f,0.f,0.f); + if (!Parse(buf)) { osg::notify(osg::NOTICE) << "txp::TXPParser::parseScene(): failed to parse the given tile" << std::endl; @@ -111,6 +114,8 @@ void TXPParser::replaceTileLod(osg::Group* group) if (!g) return; if (g->getNumChildren()) return; + _tileCenter = loLOD->getCenter(); + group->addChild(loLOD->getChild(0)); group->removeChild(loLOD); group->removeChild(hiLOD); @@ -120,27 +125,31 @@ void TXPParser::replaceTileLod(osg::Group* group) bool TXPParser::StartChildren(void *in) { + + bool pushParent = true; if (_underBillboardSubgraph ) { + if (_numBillboardLevels > 0) pushParent = false; _numBillboardLevels++; } else if (_underLayerSubgraph) { + if (_numLayerLevels > 0) pushParent = false; _numLayerLevels++; } - else - if (in && (in != (void*)1)) + if (pushParent) { - osg::Group *parent = (osg::Group*)in; - _parents.push(parent); - _currentTop = parent; + _parents.push(_currentTop); + _currentTop = _currentNode->asGroup(); } + return true; } bool TXPParser::EndChildren(void *) { + bool popParent = true; if (_underLayerSubgraph) { _numLayerLevels--; @@ -148,6 +157,8 @@ bool TXPParser::EndChildren(void *) { _underLayerSubgraph = false; } + else + popParent = false; } else if (_underBillboardSubgraph) @@ -157,18 +168,18 @@ bool TXPParser::EndChildren(void *) { _underBillboardSubgraph = false; } + else + popParent = false; } - else + if (popParent) { - _currentTop = 0; if (_parents.size()) { + _currentTop = _parents.top(); _parents.pop(); - if (_parents.size()) - { - _currentTop = _parents.top(); - } } + else + _currentTop = _root.get(); } return true; @@ -475,36 +486,33 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) // Create a new osg LOD osg::ref_ptr osgLod = new osg::LOD(); + osg::ref_ptr osgLodG = new GeodeGroup; + + osgLod->addChild(osgLodG.get()); osg::Vec3 osgCenter; osgCenter[0] = center.x; osgCenter[1] = center.y; osgCenter[2] = center.z; osgLod->setCenter(osgCenter); - //osgLod->setRange(0,minRange, maxRange ); +#if 1 + osgLod->setRange(0,minRange, maxRange ); +#else osgLod->setRange( 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 - // to that instead of the LOD - osg::ref_ptr osgLodG = new GeodeGroup(); - osgLod->addChild(osgLodG.get()); - + // to that instead of the LOD // Add it into the scene graph - osg::Group *top = _parse->getCurrTop(); - if (top) - { - top->addChild(osgLod.get()); - _parse->setPotentionalTileGroup(top); - return (void *) osgLodG.get(); - } - else - { - return (void*) 1; - } + _parse->setCurrentNode(osgLodG.get()); + _parse->getCurrTop()->addChild(osgLod.get()); + _parse->setPotentionalTileGroup(_parse->getCurrTop()); + + return (void*)1; } //---------------------------------------------------------------------------- @@ -562,12 +570,10 @@ void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) osg::MatrixTransform *scs = new osg::MatrixTransform(); scs->setMatrix(osg_Mat); scs->addChild(osg_Model); + // Add the SCS to the hierarchy - osg::Group *top = _parse->getCurrTop(); - if (top) - { - top->addChild(scs); - } + _parse->setCurrentNode(scs); + _parse->getCurrTop()->addChild(scs); } } return (void *) 1; @@ -591,6 +597,10 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) } else { + GeodeGroup* grp = new GeodeGroup; + _parse->setCurrentNode(grp); + _parse->getCurrTop()->addChild(grp); + TXPParser::TXPBillboardInfo info; if (bill.GetType(info.type) && bill.GetMode(info.mode) && bill.GetCenter(info.center) && bill.GetAxis(info.axis)) { @@ -599,7 +609,6 @@ void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) _parse->setUnderBillboardSubgraph(true); } } - return (void *)1; } @@ -613,21 +622,29 @@ void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) trpgGroup group; if (!group.Read(buf)) return NULL; - // Create a new group - osg::ref_ptr osgGroup = new GeodeGroup(); + if (_parse->underLayerSubgraph()) return (void*)1; - // Add it into the scene graph - osg::Group *top = _parse->getCurrTop(); - if (top) - { - top->addChild(osgGroup.get()); - _parse->setPotentionalTileGroup(top); - return (void *) osgGroup.get(); - } - else - { - return (void*) 1; - } + osg::ref_ptr osgGroup = new GeodeGroup(); + _parse->setCurrentNode(osgGroup.get()); + _parse->getCurrTop()->addChild(osgGroup.get()); + return (void*)1; +} + +//---------------------------------------------------------------------------- +// +// Attach Reader Class +// +//---------------------------------------------------------------------------- +void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) +{ + trpgAttach group; + if (!group.Read(buf)) return NULL; + + // Create a new group + osg::ref_ptr osgGroup = new osg::Group(); + _parse->setCurrentNode(osgGroup.get()); + _parse->getCurrTop()->addChild(osgGroup.get()); + return (void*)1; } //---------------------------------------------------------------------------- @@ -649,8 +666,6 @@ void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) uint32 nvert; light.GetNumVertices(nvert); - osg::Group *top = _parse->getCurrTop(); - if( node->getLightPoint(0)._sector.valid() ) // osgSim::LigthPoint is a must { for(unsigned int i = 0; i < nvert; i++) @@ -665,10 +680,9 @@ void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) osg::ref_ptr trans = new osg::MatrixTransform(); trans->setMatrix(matrix); trans->addChild(node); - if (top) - { - top->addChild(trans.get()); - } + + _parse->setCurrentNode(trans.get()); + _parse->getCurrTop()->addChild(trans.get()); } } else @@ -693,13 +707,10 @@ void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) geom->setUseDisplayList(false); geom->setStateSet(dla.fallback.get()); - if (top) - { - osg::Geode* g = new osg::Geode; - g->addDrawable(geom.get()); - top->addChild(g); - - } + osg::Geode* g = new osg::Geode; + g->addDrawable(geom.get()); + _parse->setCurrentNode(g); + _parse->getCurrTop()->addChild(g); } return (void *) 1; @@ -715,18 +726,25 @@ void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) trpgLayer group; 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; osg::ref_ptr layer = new GeodeGroup; - osg::Group* top = _parse->getCurrTop(); - if (top) - { - _parse->setLayerGeode(layer->getGeode()); - _parse->setUnderLayerSubgraph(true); - top->addChild(layer.get()); - } - return (void *) 1; + _parse->setLayerGeode(layer->getGeode()); + _parse->setUnderLayerSubgraph(true); + _parse->setCurrentNode(layer.get()); + _parse->getCurrTop()->addChild(layer.get()); + + return (void *)1; +#endif } //---------------------------------------------------------------------------- @@ -785,7 +803,7 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) { trpgGeometry geom; if (!geom.Read(buf)) return NULL; - + // Get the necessary info out of the geom trpgGeometry::PrimType primType; int numPrims; @@ -1050,12 +1068,15 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) if (geodeTop) { geodeTop->getGeode()->addDrawable(geometry); + _parse->setCurrentNode(geodeTop->getGeode()); } else { osg::Geode* geode = new osg::Geode; geode->addDrawable(geometry); - top->addChild(geode); + + _parse->setCurrentNode(geode); + _parse->getCurrTop()->addChild(geode); } } diff --git a/src/osgPlugins/txp/TXPParser.h b/src/osgPlugins/txp/TXPParser.h index 7fcef5a7d..de6378335 100644 --- a/src/osgPlugins/txp/TXPParser.h +++ b/src/osgPlugins/txp/TXPParser.h @@ -250,7 +250,12 @@ public: else return range; } - + + // gets tile center, from the top lod node + inline const osg::Vec3 getTileCenter() const { return _tileCenter; } + + inline void setCurrentNode(osg::Node* node) { _currentNode = node; } + protected: @@ -270,6 +275,9 @@ protected: // Current parent osg::Group* _currentTop; + + // Current node + osg::Node* _currentNode; // The root of the tile osg::ref_ptr _root; @@ -291,7 +299,7 @@ protected: // Model list std::vector >* _models; - + // Tile header trpgTileHeader _tileHeader; @@ -320,7 +328,10 @@ protected: double _realMinRange; double _realMaxRange; double _usedMaxRange; - + + // tile center + osg::Vec3 _tileCenter; + // TEMP osg::Geode* createBoundingBox(int x,int y, int lod); @@ -352,6 +363,17 @@ protected: TXPParser *_parse; }; +//---------------------------------------------------------------------------- +class attachRead : public trpgr_Callback +{ +public: + attachRead(TXPParser *in_parse) : _parse(in_parse) + {}; + void *Parse(trpgToken tok,trpgReadBuffer &buf); +protected: + TXPParser *_parse; +}; + //---------------------------------------------------------------------------- class lodRead : public trpgr_Callback { diff --git a/src/osgPlugins/txp/TXPSeamLOD.cpp b/src/osgPlugins/txp/TXPSeamLOD.cpp index 7debe9579..6710e6ceb 100644 --- a/src/osgPlugins/txp/TXPSeamLOD.cpp +++ b/src/osgPlugins/txp/TXPSeamLOD.cpp @@ -14,6 +14,8 @@ TXPSeamLOD::TXPSeamLOD() : _tileRef = 0; _txpNode = 0; _archive = 0; + _hiResPresent = false; + _nonSeamChildrenIndex = -1; } TXPSeamLOD::TXPSeamLOD(int x, int y, int lod, const osg::Vec3& center, float dmin, float dmid, float dmax) : @@ -29,6 +31,8 @@ TXPSeamLOD::TXPSeamLOD(int x, int y, int lod, const osg::Vec3& center, float dmi _txpNode = 0; _tileRef = 0; _archive = 0; + _hiResPresent = false; + _nonSeamChildrenIndex = -1; } TXPSeamLOD::TXPSeamLOD(const TXPSeamLOD& ttg,const osg::CopyOp& copyop) : @@ -39,6 +43,8 @@ TXPSeamLOD::TXPSeamLOD(const TXPSeamLOD& ttg,const osg::CopyOp& copyop) : _neighbourTileLOD = ttg._neighbourTileLOD; _tileRef = ttg._tileRef; _archive = ttg._archive; + _hiResPresent = ttg._hiResPresent; + _nonSeamChildrenIndex = ttg._nonSeamChildrenIndex; } void TXPSeamLOD::traverse(osg::NodeVisitor& nv) @@ -46,12 +52,12 @@ void TXPSeamLOD::traverse(osg::NodeVisitor& nv) if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR && _children.size()==2) { -#if 1 osg::PagedLOD* pagedLOD = TileMapper::instance()->getPagedLOD(_neighbourTileX,_neighbourTileY, _neighbourTileLOD); +#if 1 bool acceptLoRes = true; if (pagedLOD) { - + float distance = nv.getDistanceToEyePoint(_center,true); distance = nv.getDistanceToEyePoint(pagedLOD->getCenter(),true); @@ -73,6 +79,12 @@ void TXPSeamLOD::traverse(osg::NodeVisitor& nv) { getChild(0)->accept(nv); // pick low res } + + if (_nonSeamChildrenIndex > -1) + { + for (int i = _nonSeamChildrenIndex; i < (int)getNumChildren(); i++ ) + getChild(i)->accept(nv); + } #else float distance = nv.getDistanceToEyePoint(_center,true); if (distance<=_mid) diff --git a/src/osgPlugins/txp/TXPSeamLOD.h b/src/osgPlugins/txp/TXPSeamLOD.h index 1ad757fd1..0eb7b05fe 100644 --- a/src/osgPlugins/txp/TXPSeamLOD.h +++ b/src/osgPlugins/txp/TXPSeamLOD.h @@ -80,8 +80,15 @@ public: _archive = ar; } + inline void setHiResPresent(bool p) { _hiResPresent = p; } + inline void setNonSeamChildrenIndex(int ix) { _nonSeamChildrenIndex = ix; } + protected: + bool _hiResPresent; + + int _nonSeamChildrenIndex; + int _neighbourTileX; int _neighbourTileY; int _neighbourTileLOD; diff --git a/src/osgPlugins/txp/TXPTileNode.cpp b/src/osgPlugins/txp/TXPTileNode.cpp index 7ac37d18b..1be0898d7 100644 --- a/src/osgPlugins/txp/TXPTileNode.cpp +++ b/src/osgPlugins/txp/TXPTileNode.cpp @@ -46,10 +46,15 @@ class PrintVisitor : public osg::NodeVisitor { moveIn(); writeIndent(); std::cout << lod.className() <getMaxRange(0)==lod2->getMaxRange(0)) - { -// std::cout<<" lod1 and lod2 range equal. ****************"<getCenter(),lod1->getMinRange(0),lod1->getMaxRange(0),lod2->getMaxRange(0)); - seam->setArchive(_archive); - seam->addChild(lod1->getChild(0)); // low res - seam->addChild(lod2->getChild(0)); // high res - return seam; + 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); } } } - return child; + +protected: + osg::Node* seamReplacement(osg::Node* node); + + int _x, _y, _lod; + TXPArchive::TileInfo& _info; + TXPArchive *_archive; +}; + +osg::Node* SeamFinder::seamReplacement(osg::Node* node) +{ + osg::Group* group = node->asGroup(); + if (group == 0) return node; + + std::vector nonSeamChildren; + osg::LOD* hiRes = 0; + osg::LOD* loRes = 0; + + for (unsigned int i = 0; i < group->getNumChildren(); i++) + { + osg::LOD* lod = dynamic_cast(group->getChild(i)); + if (lod == 0) + { + nonSeamChildren.push_back(group->getChild(i)); + continue; + } + + bool nonSeamChild = true; + + // seam center is outside the bounding box of the tile + if (!_info.bbox.contains(lod->getCenter())) + { + // seams have center as the neighbour tile + osg::Vec3 d = _info.center - lod->getCenter(); + if (((fabs(d.x())-_info.size.x()) > 0.0001) && ((fabs(d.y())-_info.size.y()) > 0.0001)) + { + nonSeamChildren.push_back(lod); + continue; + } + + // low res seam has min/max ranges of lod+1 range/lod 0 range + if ((fabs(_info.minRange-lod->getMinRange(0))<0.001)&&(fabs(_info.lod0Range-lod->getMaxRange(0))<0.001)) + { + + if (loRes==0) + { + loRes = lod; + nonSeamChild = false; + } + } + + // hi res seam has min/max ranges of 0 range/lod+1 range + if ((lod->getMinRange(0)==0.0f)&&(fabs(_info.minRange-lod->getMaxRange(0))<0.001)) + { + if (hiRes==0) + { + hiRes = lod; + nonSeamChild = false; + } + } + } + if (nonSeamChild) + { + nonSeamChildren.push_back(lod); + } + } + + if (loRes) + { + int x = _x; + int y = _y; + int lod = _lod; + osg::Vec3 delta = loRes->getCenter()-_info.center; + if (fabs(delta.x())>fabs(delta.y())) + { + if (delta.x()<0.0) --x; // west + else x++; // east + } + else + { + if (delta.y()<0.0) --y; // south + else ++y; // north + } + TXPSeamLOD* seam = new TXPSeamLOD( + x, + y, + lod, + loRes->getCenter(), + 0.f, + _info.minRange, + _info.maxRange + ); + seam->setArchive(_archive); + seam->addChild(loRes->getChild(0)); // low res + if (hiRes) + { + seam->addChild(hiRes->getChild(0)); // high res + seam->setHiResPresent(true); + } + if (nonSeamChildren.size()) + { + seam->setNonSeamChildrenIndex(seam->getNumChildren()); + for (unsigned int i = 0; i < nonSeamChildren.size(); i++) + seam->addChild(nonSeamChildren[i]); + } + return seam; + } + + return node; } bool TXPTileNode::loadTile(int x, int y, int lod) @@ -173,38 +237,24 @@ bool TXPTileNode::loadTile(int x, int y, int lod) double realMinRange = info.minRange; double realMaxRange = info.maxRange; double usedMaxRange = osg::maximum(info.maxRange,1e7); - osg::Group* tileGroup = _archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange); + osg::Vec3 tileCenter; + osg::Group* tileGroup = _archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter); - - // if group has only one child, then simply use its child. + // 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 - - - if (tileGroup->getNumChildren()==5) + // Handle seams + if (lod < (numLods-1)) { - // candidate for being a Tile with seams. -// std::cout<<"------- Seams candidate ------ "<