1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-29 22:15:34 +00:00

Calculate recast mesh bounds when building navmesh

This commit is contained in:
elsid 2021-11-05 15:30:56 +01:00
parent e10bbb9ad7
commit f4f4458d01
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
4 changed files with 66 additions and 66 deletions

View file

@ -1109,16 +1109,16 @@ namespace
Status::PartialPath);
EXPECT_THAT(mPath, ElementsAre(
Vec3fEq(56.66666412353515625, 460, -2.5371043682098388671875),
Vec3fEq(76.4206390380859375, 439.688446044921875, -2.913421630859375),
Vec3fEq(96.17461395263671875, 419.37689208984375, -4.508244037628173828125),
Vec3fEq(115.9285888671875, 399.06536865234375, -6.103069305419921875),
Vec3fEq(135.68255615234375, 378.753814697265625, -7.69789028167724609375),
Vec3fEq(155.4365386962890625, 358.44232177734375, -20.9574832916259765625),
Vec3fEq(175.190521240234375, 338.130767822265625, -35.907501220703125),
Vec3fEq(194.944488525390625, 317.8192138671875, -50.8574981689453125),
Vec3fEq(214.6984710693359375, 297.507720947265625, -65.8075103759765625),
Vec3fEq(222.0000457763671875, 290.00006103515625, -71.3334197998046875)
Vec3fEq(56.66664886474609375, 460, -2.5371043682098388671875),
Vec3fEq(76.42063140869140625, 439.6884765625, -2.9134314060211181640625),
Vec3fEq(96.17461395263671875, 419.376953125, -4.50826549530029296875),
Vec3fEq(115.9285888671875, 399.0654296875, -6.1030979156494140625),
Vec3fEq(135.6825714111328125, 378.753936767578125, -7.697928905487060546875),
Vec3fEq(155.436553955078125, 358.442413330078125, -20.9574985504150390625),
Vec3fEq(175.190521240234375, 338.130889892578125, -35.907512664794921875),
Vec3fEq(194.9445037841796875, 317.8193359375, -50.85752105712890625),
Vec3fEq(214.698486328125, 297.5078125, -65.807525634765625),
Vec3fEq(222.0001068115234375, 290.000091552734375, -71.333465576171875)
)) << mPath;
}

View file

@ -121,7 +121,7 @@ namespace
return result;
}
rcConfig makeConfig(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& boundsMin, const osg::Vec3f& boundsMax,
rcConfig makeConfig(const osg::Vec3f& agentHalfExtents, const TilePosition& tile, float minZ, float maxZ,
const Settings& settings)
{
rcConfig config;
@ -140,15 +140,18 @@ namespace
config.detailSampleDist = settings.mDetailSampleDist < 0.9f ? 0 : config.cs * settings.mDetailSampleDist;
config.detailSampleMaxError = config.ch * settings.mDetailSampleMaxError;
config.borderSize = settings.mBorderSize;
config.width = settings.mTileSize + config.borderSize * 2;
config.height = settings.mTileSize + config.borderSize * 2;
rcVcopy(config.bmin, boundsMin.ptr());
rcVcopy(config.bmax, boundsMax.ptr());
config.bmin[0] -= getBorderSize(settings);
config.bmin[2] -= getBorderSize(settings);
config.bmax[0] += getBorderSize(settings);
config.bmax[2] += getBorderSize(settings);
config.tileSize = settings.mTileSize;
const int size = config.tileSize + config.borderSize * 2;
config.width = size;
config.height = size;
const float halfBoundsSize = size * config.cs * 0.5f;
const osg::Vec2f shift = osg::Vec2f(tile.x() + 0.5f, tile.y() + 0.5f) * getTileSize(settings);
config.bmin[0] = shift.x() - halfBoundsSize;
config.bmin[1] = minZ;
config.bmin[2] = shift.y() - halfBoundsSize;
config.bmax[0] = shift.x() + halfBoundsSize;
config.bmax[1] = maxZ;
config.bmax[2] = shift.y() + halfBoundsSize;
return config;
}
@ -388,20 +391,56 @@ namespace
++power;
return power;
}
std::pair<float, float> getBoundsByZ(const RecastMesh& recastMesh, const osg::Vec3f& agentHalfExtents, const Settings& settings)
{
float minZ = 0;
float maxZ = 0;
const std::vector<float>& vertices = recastMesh.getMesh().getVertices();
for (std::size_t i = 0, n = vertices.size(); i < n; i += 3)
{
minZ = std::min(minZ, vertices[i + 2]);
maxZ = std::max(maxZ, vertices[i + 2]);
}
for (const Cell& water : recastMesh.getWater())
{
const float swimLevel = getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z());
minZ = std::min(minZ, swimLevel);
maxZ = std::max(maxZ, swimLevel);
}
for (const Heightfield& heightfield : recastMesh.getHeightfields())
{
if (heightfield.mHeights.empty())
continue;
const auto [minHeight, maxHeight] = std::minmax_element(heightfield.mHeights.begin(), heightfield.mHeights.end());
minZ = std::min(minZ, *minHeight);
maxZ = std::max(maxZ, *maxHeight);
}
for (const FlatHeightfield& heightfield : recastMesh.getFlatHeightfields())
{
minZ = std::min(minZ, heightfield.mHeight);
maxZ = std::max(maxZ, heightfield.mHeight);
}
return {minZ, maxZ};
}
}
} // namespace DetourNavigator
namespace DetourNavigator
{
std::unique_ptr<PreparedNavMeshData> prepareNavMeshTileData(const RecastMesh& recastMesh,
const TilePosition& tile, const Bounds& bounds, const osg::Vec3f& agentHalfExtents, const Settings& settings)
const TilePosition& tilePosition, const osg::Vec3f& agentHalfExtents, const Settings& settings)
{
const TileBounds tileBounds = makeTileBounds(settings, tile);
const osg::Vec3f boundsMin(tileBounds.mMin.x(), bounds.mMin.y() - 1, tileBounds.mMin.y());
const osg::Vec3f boundsMax(tileBounds.mMax.x(), bounds.mMax.y() + 1, tileBounds.mMax.y());
const auto [minZ, maxZ] = getBoundsByZ(recastMesh, agentHalfExtents, settings);
rcContext context;
const auto config = makeConfig(agentHalfExtents, boundsMin, boundsMax, settings);
const auto config = makeConfig(agentHalfExtents, tilePosition, toNavMeshCoordinates(settings, minZ),
toNavMeshCoordinates(settings, maxZ), settings);
rcHeightfield solid;
createHeightfield(context, solid, config.width, config.height, config.bmin, config.bmax, config.cs, config.ch);
@ -529,18 +568,8 @@ namespace DetourNavigator
return navMeshCacheItem->lock()->removeTile(changedTile);
}
auto recastMeshBounds = recastMesh->getBounds();
recastMeshBounds.mMin = toNavMeshCoordinates(settings, recastMeshBounds.mMin);
recastMeshBounds.mMax = toNavMeshCoordinates(settings, recastMeshBounds.mMax);
for (const auto& water : recastMesh->getWater())
{
const float height = toNavMeshCoordinates(settings, getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z()));
recastMeshBounds.mMin.y() = std::min(recastMeshBounds.mMin.y(), height);
recastMeshBounds.mMax.y() = std::max(recastMeshBounds.mMax.y(), height);
}
if (isEmpty(recastMeshBounds))
if (recastMesh->getMesh().getIndices().empty() && recastMesh->getWater().empty()
&& recastMesh->getHeightfields().empty() && recastMesh->getFlatHeightfields().empty())
{
Log(Debug::Debug) << "Ignore add tile: recastMesh is empty";
return navMeshCacheItem->lock()->removeTile(changedTile);
@ -559,8 +588,7 @@ namespace DetourNavigator
if (!cachedNavMeshData)
{
auto prepared = prepareNavMeshTileData(*recastMesh, changedTile, recastMeshBounds,
agentHalfExtents, settings);
auto prepared = prepareNavMeshTileData(*recastMesh, changedTile, agentHalfExtents, settings);
if (prepared == nullptr)
{

View file

@ -27,31 +27,9 @@ namespace DetourNavigator
, mHeightfields(std::move(heightfields))
, mFlatHeightfields(std::move(flatHeightfields))
{
if (mMesh.getVerticesCount() > 0)
rcCalcBounds(mMesh.getVertices().data(), static_cast<int>(mMesh.getVerticesCount()),
mBounds.mMin.ptr(), mBounds.mMax.ptr());
mWater.shrink_to_fit();
mHeightfields.shrink_to_fit();
for (Heightfield& v : mHeightfields)
v.mHeights.shrink_to_fit();
for (const Heightfield& v : mHeightfields)
{
const auto [min, max] = std::minmax_element(v.mHeights.begin(), v.mHeights.end());
mBounds.mMin.x() = std::min(mBounds.mMin.x(), v.mBounds.mMin.x());
mBounds.mMin.y() = std::min(mBounds.mMin.y(), v.mBounds.mMin.y());
mBounds.mMin.z() = std::min(mBounds.mMin.z(), *min);
mBounds.mMax.x() = std::max(mBounds.mMax.x(), v.mBounds.mMax.x());
mBounds.mMax.y() = std::max(mBounds.mMax.y(), v.mBounds.mMax.y());
mBounds.mMax.z() = std::max(mBounds.mMax.z(), *max);
}
for (const FlatHeightfield& v : mFlatHeightfields)
{
mBounds.mMin.x() = std::min(mBounds.mMin.x(), v.mBounds.mMin.x());
mBounds.mMin.y() = std::min(mBounds.mMin.y(), v.mBounds.mMin.y());
mBounds.mMin.z() = std::min(mBounds.mMin.z(), v.mHeight);
mBounds.mMax.x() = std::max(mBounds.mMax.x(), v.mBounds.mMax.x());
mBounds.mMax.y() = std::max(mBounds.mMax.y(), v.mBounds.mMax.y());
mBounds.mMax.z() = std::max(mBounds.mMax.z(), v.mHeight);
}
}
}

View file

@ -118,11 +118,6 @@ namespace DetourNavigator
return mFlatHeightfields;
}
const Bounds& getBounds() const
{
return mBounds;
}
private:
std::size_t mGeneration;
std::size_t mRevision;
@ -130,7 +125,6 @@ namespace DetourNavigator
std::vector<Cell> mWater;
std::vector<Heightfield> mHeightfields;
std::vector<FlatHeightfield> mFlatHeightfields;
Bounds mBounds;
friend inline std::size_t getSize(const RecastMesh& value) noexcept
{