diff --git a/simgear/io/untar.cxx b/simgear/io/untar.cxx index f73bbfa3..4cf66372 100644 --- a/simgear/io/untar.cxx +++ b/simgear/io/untar.cxx @@ -730,10 +730,11 @@ ArchiveExtractor::DetermineResult ArchiveExtractor::determineType(const uint8_t* } auto r = isTarData(bytes, count); - if ((r == TarData) || (r == InsufficientData) || (r == GZData)) + if ((r == TarData) || (r == InsufficientData) || (r == GZData)) { return r; + } - return Invalid; + return Invalid; } diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index 36816ed3..b9a0cb95 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -662,6 +662,19 @@ struct ReaderWriterSTG::_ModelBin { SG_LOG(SG_TERRAIN, SG_INFO, "Loading: " << filename); } } + + // OBJECTs include airports + for (auto stgObject : _objectList) { + osg::ref_ptr node; + node = osgDB::readRefNodeFile(stgObject._name, stgObject._options.get()); + + if (!node.valid()) { + SG_LOG(SG_TERRAIN, SG_ALERT, stgObject._errorLocation << ": Failed to load " + << stgObject._token << " '" << stgObject._name << "'"); + continue; + } + terrainGroup->addChild(node.get()); + } } else if (_foundBase) { for (auto stgObject : _objectList) { osg::ref_ptr node; diff --git a/simgear/scene/tgdb/VPBTechnique.cxx b/simgear/scene/tgdb/VPBTechnique.cxx index 669b757b..2756b1b2 100644 --- a/simgear/scene/tgdb/VPBTechnique.cxx +++ b/simgear/scene/tgdb/VPBTechnique.cxx @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include @@ -57,7 +59,6 @@ VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options) setFilterWidth(0.1); setFilterMatrixAs(GAUSSIAN); setOptions(options); - } VPBTechnique::VPBTechnique(const VPBTechnique& gt,const osg::CopyOp& copyop): @@ -505,8 +506,12 @@ void VertexNormalGenerator::populateCenter(osgTerrain::Layer* elevationLayer, La if (validValue) { osg::Vec3d model; + osg::Vec3d origin; + _masterLocator->convertLocalToModel(osg::Vec3d(ndc.x(), ndc.y(), -1000), origin); _masterLocator->convertLocalToModel(ndc, model); + model = VPBTechnique::checkAgainstElevationConstraints(origin, model); + for(VertexNormalGenerator::LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin(); itr != layerToTexCoordMap.end(); ++itr) @@ -1447,6 +1452,7 @@ void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator) atlas = _matcache->getAtlas(); SGMaterialCache::AtlasIndex atlasIndex = atlas.index; + // Set the "g" color channel to an index into the atlas index. for (int s = 0; s < image->s(); s++) { for (int t = 0; t < image->t(); t++) { osg::Vec4 c = image->getColor(s, t); @@ -1614,7 +1620,6 @@ void VPBTechnique::traverse(osg::NodeVisitor& nv) } } - void VPBTechnique::cleanSceneGraph() { } @@ -1625,3 +1630,73 @@ void VPBTechnique::releaseGLObjects(osg::State* state) const if (_newBufferData.valid() && _newBufferData->_transform.valid()) _newBufferData->_transform->releaseGLObjects(state); } +// Simple vistor to check for any underlying terrain meshes that contain a given constraint and therefore may need to be modified +// (e.g elevation lowered to ensure the terrain doesn't poke through an airport mesh) +class TerrainVisitor : public osg::NodeVisitor { + public: + osg::ref_ptr _constraint; // Object to flatten the terrain under. + TerrainVisitor( osg::ref_ptr node) : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + _constraint(node) + { } + virtual ~TerrainVisitor() + { } + + void apply(osg::Node& node) + { + osgTerrain::TerrainTile* tile = dynamic_cast(&node); + if (tile) + { + // Determine if the constraint should affect this tile. + const osg::BoundingSphere tileBB = tile->getBound(); + if (tileBB.intersects(_constraint->getBound())) { + // Dirty any existing terrain tiles containing this constraint, which will force regeneration of the elevation mesh. + tile->setDirty(true); + //tile->init(tile->getDirtyMask(), true); + } + } else { + traverse(node); + } + } +}; + +// Add an osg object representing a contraint on the terrain mesh. The generated terrain mesh will not include any vertices that +// lie above the constraint model. (Note that geometry may result in edges intersecting the constraint model in cases where there +// are significantly higher vertices that lie just outside the constraint model. +void VPBTechnique::addElevationConstraint(osg::ref_ptr constraint, osg::Group* terrain) +{ + const std::lock_guard lock(VPBTechnique::_constraint_mutex); // Lock the _constraintGroup for this scope + _constraintGroup->addChild(constraint.get()); + + TerrainVisitor ftv(constraint); + terrain->accept(ftv); +} + +// Remove a previously added constraint. E.g on model unload. +void VPBTechnique::removeElevationConstraint(osg::ref_ptr constraint) +{ + const std::lock_guard lock(VPBTechnique::_constraint_mutex); // Lock the _constraintGroup for this scope + _constraintGroup->removeChild(constraint.get()); +} + +// Check a given vertex against any elevation constraints E.g. to ensure the terrain mesh doesn't +// poke through any airport meshes. If such a constraint exists, the function will return a replacement +// vertex displaces such that it lies 1m below the contraint relative to the passed in origin. +osg::Vec3d VPBTechnique::checkAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex) +{ + const std::lock_guard lock(VPBTechnique::_constraint_mutex); // Lock the _constraintGroup for this scope + osg::ref_ptr intersector; + intersector = new osgUtil::LineSegmentIntersector(origin, vertex); + osgUtil::IntersectionVisitor visitor(intersector.get()); + _constraintGroup->accept(visitor); + + if (intersector->containsIntersections()) { + // We have an intersection with our constraints model, so move the terrain vertex to 1m below the intersection point + osg::Vec3d ray = intersector->getFirstIntersection().getWorldIntersectPoint() - origin; + ray.normalize(); + return intersector->getFirstIntersection().getWorldIntersectPoint() - ray*1.0; + } else { + return vertex; + } +} + diff --git a/simgear/scene/tgdb/VPBTechnique.hxx b/simgear/scene/tgdb/VPBTechnique.hxx index 244dcde5..dd8d7f7d 100644 --- a/simgear/scene/tgdb/VPBTechnique.hxx +++ b/simgear/scene/tgdb/VPBTechnique.hxx @@ -19,6 +19,8 @@ #ifndef VPBTECHNIQUE #define VPBTECHNIQUE 1 +#include + #include #include #include @@ -27,6 +29,7 @@ #include #include +#include using namespace osgTerrain; @@ -84,6 +87,9 @@ class VPBTechnique : public TerrainTechnique * for all graphics contexts. */ virtual void releaseGLObjects(osg::State* = 0) const; + static void addElevationConstraint(osg::ref_ptr constraint, osg::Group* terrain); + static void removeElevationConstraint(osg::ref_ptr constraint); + static osg::Vec3d checkAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex); protected: @@ -111,7 +117,6 @@ class VPBTechnique : public TerrainTechnique virtual void applyTransparency(BufferData& buffer); - OpenThreads::Mutex _writeBufferMutex; osg::ref_ptr _currentBufferData; osg::ref_ptr _newBufferData; @@ -125,6 +130,9 @@ class VPBTechnique : public TerrainTechnique osg::ref_ptr _options; osg::ref_ptr _atlas; osg::ref_ptr _matcache; + + inline static osg::ref_ptr _constraintGroup = new osg::Group();; + inline static std::mutex _constraint_mutex; // protects the _constraintGroup; }; }