1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-28 16:09:43 +00:00

Simplify adding water to recast mesh

Remove redundant computations and conversions.
This commit is contained in:
elsid 2021-07-16 00:09:05 +02:00
parent 5d6c93566d
commit 24b802b3d8
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
2 changed files with 46 additions and 53 deletions

View file

@ -28,32 +28,35 @@ namespace
{
using namespace DetourNavigator;
struct WaterBounds
struct Rectangle
{
osg::Vec3f mMin;
osg::Vec3f mMax;
TileBounds mBounds;
float mHeight;
};
WaterBounds getWaterBounds(const Cell& water, const Settings& settings,
Rectangle getSwimRectangle(const Cell& water, const Settings& settings,
const osg::Vec3f& agentHalfExtents)
{
if (water.mSize == std::numeric_limits<int>::max())
{
const auto transform = getSwimLevelTransform(settings, water.mShift, agentHalfExtents.z());
const auto min = toNavMeshCoordinates(settings, Misc::Convert::makeOsgVec3f(transform(btVector3(-1, -1, 0))));
const auto max = toNavMeshCoordinates(settings, Misc::Convert::makeOsgVec3f(transform(btVector3(1, 1, 0))));
return WaterBounds {
osg::Vec3f(-std::numeric_limits<float>::max(), min.y(), -std::numeric_limits<float>::max()),
osg::Vec3f(std::numeric_limits<float>::max(), max.y(), std::numeric_limits<float>::max())
return Rectangle {
TileBounds {
osg::Vec2f(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max()),
osg::Vec2f(std::numeric_limits<float>::max(), std::numeric_limits<float>::max())
},
toNavMeshCoordinates(settings, getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z()))
};
}
else
{
const auto transform = getSwimLevelTransform(settings, water.mShift, agentHalfExtents.z());
const auto halfCellSize = water.mSize / 2.0f;
return WaterBounds {
toNavMeshCoordinates(settings, Misc::Convert::makeOsgVec3f(transform(btVector3(-halfCellSize, -halfCellSize, 0)))),
toNavMeshCoordinates(settings, Misc::Convert::makeOsgVec3f(transform(btVector3(halfCellSize, halfCellSize, 0))))
const osg::Vec2f shift(water.mShift.x(), water.mShift.y());
const float halfCellSize = water.mSize / 2.0f;
return Rectangle {
TileBounds{
toNavMeshCoordinates(settings, shift + osg::Vec2f(-halfCellSize, -halfCellSize)),
toNavMeshCoordinates(settings, shift + osg::Vec2f(halfCellSize, halfCellSize))
},
toNavMeshCoordinates(settings, getSwimLevel(settings, water.mShift.z(), agentHalfExtents.z()))
};
}
}
@ -192,49 +195,43 @@ namespace
);
}
void rasterizeWaterTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
void rasterizeWaterTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const std::vector<Cell>& cells,
const Settings& settings, const rcConfig& config, rcHeightfield& solid)
{
const std::array<unsigned char, 2> areas {{AreaType_water, AreaType_water}};
for (const auto& water : recastMesh.getWater())
for (const Cell& cell : cells)
{
const auto bounds = getWaterBounds(water, settings, agentHalfExtents);
const auto rectangle = getSwimRectangle(cell, settings, agentHalfExtents);
const osg::Vec2f tileBoundsMin(
std::min(config.bmax[0], std::max(config.bmin[0], bounds.mMin.x())),
std::min(config.bmax[2], std::max(config.bmin[2], bounds.mMin.z()))
std::min(config.bmax[0], std::max(config.bmin[0], rectangle.mBounds.mMin.x())),
std::min(config.bmax[2], std::max(config.bmin[2], rectangle.mBounds.mMin.y()))
);
const osg::Vec2f tileBoundsMax(
std::min(config.bmax[0], std::max(config.bmin[0], bounds.mMax.x())),
std::min(config.bmax[2], std::max(config.bmin[2], bounds.mMax.z()))
std::min(config.bmax[0], std::max(config.bmin[0], rectangle.mBounds.mMax.x())),
std::min(config.bmax[2], std::max(config.bmin[2], rectangle.mBounds.mMax.y()))
);
if (tileBoundsMax == tileBoundsMin)
continue;
const std::array<osg::Vec3f, 4> vertices {{
osg::Vec3f(tileBoundsMin.x(), bounds.mMin.y(), tileBoundsMin.y()),
osg::Vec3f(tileBoundsMin.x(), bounds.mMin.y(), tileBoundsMax.y()),
osg::Vec3f(tileBoundsMax.x(), bounds.mMin.y(), tileBoundsMax.y()),
osg::Vec3f(tileBoundsMax.x(), bounds.mMin.y(), tileBoundsMin.y()),
}};
const std::array vertices {
tileBoundsMin.x(), rectangle.mHeight, tileBoundsMin.y(),
tileBoundsMin.x(), rectangle.mHeight, tileBoundsMax.y(),
tileBoundsMax.x(), rectangle.mHeight, tileBoundsMax.y(),
tileBoundsMax.x(), rectangle.mHeight, tileBoundsMin.y(),
};
std::array<float, 4 * 3> convertedVertices;
auto convertedVerticesIt = convertedVertices.begin();
for (const auto& vertex : vertices)
convertedVerticesIt = std::copy(vertex.ptr(), vertex.ptr() + 3, convertedVerticesIt);
const std::array<int, 6> indices {{
const std::array indices {
0, 1, 2,
0, 2, 3,
}};
};
const auto trianglesRasterized = rcRasterizeTriangles(
&context,
convertedVertices.data(),
static_cast<int>(convertedVertices.size() / 3),
vertices.data(),
static_cast<int>(vertices.size() / 3),
indices.data(),
areas.data(),
static_cast<int>(areas.size()),
@ -253,7 +250,7 @@ namespace
if (!rasterizeTriangles(context, recastMesh.getMesh(), settings, config, solid))
return false;
rasterizeWaterTriangles(context, agentHalfExtents, recastMesh, settings, config, solid);
rasterizeWaterTriangles(context, agentHalfExtents, recastMesh.getWater(), settings, config, solid);
return true;
}
@ -504,9 +501,9 @@ namespace DetourNavigator
for (const auto& water : recastMesh->getWater())
{
const auto waterBounds = getWaterBounds(water, settings, agentHalfExtents);
recastMeshBounds.mMin.y() = std::min(recastMeshBounds.mMin.y(), waterBounds.mMin.y());
recastMeshBounds.mMax.y() = std::max(recastMeshBounds.mMax.y(), waterBounds.mMax.y());
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))

View file

@ -37,6 +37,11 @@ namespace DetourNavigator
return value * settings.mRecastScaleFactor;
}
inline osg::Vec2f toNavMeshCoordinates(const Settings& settings, osg::Vec2f position)
{
return position * settings.mRecastScaleFactor;
}
inline osg::Vec3f toNavMeshCoordinates(const Settings& settings, osg::Vec3f position)
{
std::swap(position.y(), position.z());
@ -77,18 +82,9 @@ namespace DetourNavigator
return static_cast<float>(settings.mBorderSize) * settings.mCellSize;
}
inline float getSwimLevel(const Settings& settings, const float agentHalfExtentsZ)
inline float getSwimLevel(const Settings& settings, const float waterLevel, const float agentHalfExtentsZ)
{
return - settings.mSwimHeightScale * agentHalfExtentsZ;
}
inline btTransform getSwimLevelTransform(const Settings& settings, const osg::Vec3f& shift,
const float agentHalfExtentsZ)
{
return btTransform(
btMatrix3x3::getIdentity(),
btVector3(shift.x(), shift.y(), shift.z() + getSwimLevel(settings, agentHalfExtentsZ) - agentHalfExtentsZ)
);
return waterLevel - settings.mSwimHeightScale * agentHalfExtentsZ - agentHalfExtentsZ;;
}
inline float getRealTileSize(const Settings& settings)