From 1a37dcf3d598f348153cbe02ad5c924315e4513b Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Thu, 24 Feb 2022 22:29:34 +0000 Subject: [PATCH] WS30: Improved algorithm for airport placement Previously the vertices directly underneath an airport were displaced downwards. In general this worked OK, but for airports surrounded by higher terrain, this could cause "ridges" from edges from vertices just outside the airport boundary. This commit modifies the algorithm to also reduce the elevation of vertices immediately outside the airport boundary as well. --- simgear/scene/tgdb/VPBTechnique.cxx | 53 ++++++++++++++++++++--------- simgear/scene/tgdb/VPBTechnique.hxx | 2 +- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/simgear/scene/tgdb/VPBTechnique.cxx b/simgear/scene/tgdb/VPBTechnique.cxx index 17612d64..dceb4b1d 100644 --- a/simgear/scene/tgdb/VPBTechnique.cxx +++ b/simgear/scene/tgdb/VPBTechnique.cxx @@ -537,11 +537,8 @@ void VertexNormalGenerator::populateCenter(osgTerrain::Layer* elevationLayer, os if (validValue) { osg::Vec3d model; - osg::Vec3d origin; - _masterLocator->convertLocalToModel(osg::Vec3d(ndc.x(), ndc.y(), -1000), origin); - _masterLocator->convertLocalToModel(ndc, model); - model = VPBTechnique::checkAndDisplaceAgainstElevationConstraints(origin, model, _constraint_vtx_gap); + model = VPBTechnique::checkAndDisplaceAgainstElevationConstraints(ndc, _numColumns, _numRows, _constraint_vtx_gap, _masterLocator); texcoords->push_back(osg::Vec2(ndc.x(), ndc.y())); @@ -2382,23 +2379,45 @@ void VPBTechnique::removeElevationConstraint(osg::ref_ptr constraint) // 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::checkAndDisplaceAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex, float vtx_gap) +// vertex displaces such that it below the contraint relative to the passed in origin by vtx_gap meters. +osg::Vec3d VPBTechnique::checkAndDisplaceAgainstElevationConstraints(osg::Vec3d ndc, int cols, int rows, float vtx_gap, Locator* masterLocator) { const std::lock_guard lock(VPBTechnique::_elevationConstraintMutex); // Lock the _elevationConstraintGroup for this scope - osg::ref_ptr intersector; - intersector = new osgUtil::LineSegmentIntersector(origin, vertex); - osgUtil::IntersectionVisitor visitor(intersector.get()); - _elevationConstraintGroup->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*vtx_gap; - } else { - return vertex; + osg::Vec3d origin, vertex, deltaX, deltaY; + masterLocator->convertLocalToModel(osg::Vec3d(ndc.x(), ndc.y(), -1000), origin); + masterLocator->convertLocalToModel(ndc, vertex); + masterLocator->convertLocalToModel(ndc + osg::Vec3d(1.0 / (double) cols, 0.0,0.0), deltaX); + masterLocator->convertLocalToModel(ndc + osg::Vec3d(0.0, 1.0 / (double) rows, 0.0), deltaY); + + double elev = ndc.z(); + + for (int i = -1; i < 2; ++i) { + for (int j = -1; j < 2; ++j) { + osg::Vec3d delta = deltaX * i + deltaY * j; + osg::ref_ptr intersector; + intersector = new osgUtil::LineSegmentIntersector(origin + delta, vertex + delta); + osgUtil::IntersectionVisitor visitor(intersector.get()); + _elevationConstraintGroup->accept(visitor); + + if (intersector->containsIntersections()) { + // We have an intersection with our constraints model, so move the terrain vertex to below the intersection point by vtx_gap meters + osg::Vec3d ray = intersector->getFirstIntersection().getWorldIntersectPoint() - (origin + delta); + ray.normalize(); + osg::Vec3d local; + masterLocator->convertModelToLocal(intersector->getFirstIntersection().getWorldIntersectPoint() - ray*vtx_gap, local); + if (elev > local.z()) { + elev = local.z(); + } + } + } } + + // elev now contains the local elevation of a point constrained by the elevation constraints of the vertex and the 8 surrounding + // vertices. + osg::Vec3d constrained; + masterLocator->convertLocalToModel(osg::Vec3d(ndc.x(), ndc.y(), elev), constrained); + return constrained; } bool VPBTechnique::checkAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex) diff --git a/simgear/scene/tgdb/VPBTechnique.hxx b/simgear/scene/tgdb/VPBTechnique.hxx index df986eb7..f83748f4 100644 --- a/simgear/scene/tgdb/VPBTechnique.hxx +++ b/simgear/scene/tgdb/VPBTechnique.hxx @@ -96,7 +96,7 @@ class VPBTechnique : public TerrainTechnique // As airports are generated in a separate loading thread, these are static. static void addElevationConstraint(osg::ref_ptr constraint); static void removeElevationConstraint(osg::ref_ptr constraint); - static osg::Vec3d checkAndDisplaceAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex, float vertex_gap); + static osg::Vec3d checkAndDisplaceAgainstElevationConstraints(osg::Vec3d ndc, int cols, int rows, float vtx_gap, Locator* masterLocator); static bool checkAgainstElevationConstraints(osg::Vec3d origin, osg::Vec3d vertex); static void clearConstraints();