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<const txp::TileIdentifier*>(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::Node* SeamFinder::seamReplacement(osg::Node* node) { osg::Group* group = node->asGroup(); if ( group == 0 ) return node; std::vector<osg::Node*> 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<osg::LOD*>(group->getChild(i)); if (lod == 0) { nonSeamChildren.push_back(group->getChild(i)); continue; } 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 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)) { const osg::LOD::RangeList& rangeList = lod->getRangeList(); if (!rangeList.size()) { // TODO: Warn here continue; } TXPArchive::TileInfo lod_plus_one_info; if (!this->_archive->getTileInfo(_x,_y,_lod+1,lod_plus_one_info)) { // TODO: Warn here continue; } double lod_plus_oneSwitchInDistance = lod_plus_one_info.maxRange; double lod0SwitchInDistance = _info.lod0Range; // low res seam has min/max ranges of lod+1 range/lod 0 range if (equalDoubles(lod_plus_oneSwitchInDistance,rangeList.at(0).first) && equalDoubles(lod0SwitchInDistance,rangeList.at(0).second)) { if (loRes==0) { loRes = lod; nonSeamChild = false; } } else // hi res seam has min/max ranges of 0 range/lod+1 range if (rangeList.at(0).first==0.0 && equalDoubles(lod_plus_oneSwitchInDistance,rangeList.at(0).second)) { if (hiRes==0) { hiRes = lod; nonSeamChild = false; } } } if (nonSeamChild) { nonSeamChildren.push_back(lod); } } if (loRes) { int dx = 0; int dy = 0; int lod = _lod; 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 } else { 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) { seam->addChild(hiRes->getChild(0)); // high res } if (nonSeamChildren.empty()) { return seam; } else { osg::Group* newGroup = new osg::Group; newGroup->addChild(seam); for (unsigned int i = 0; i < nonSeamChildren.size(); i++) newGroup->addChild(nonSeamChildren[i]); return newGroup; } } return node; }