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:
parent
e10bbb9ad7
commit
f4f4458d01
4 changed files with 66 additions and 66 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue