Recast: expose option to ignore input triangle winding order to user interface

Disabled by default.
This commit is contained in:
Kawe Mazidjatari 2024-10-25 16:35:20 +02:00
parent 0940ad3ce6
commit 67c5145862
6 changed files with 17 additions and 5 deletions

View File

@ -142,6 +142,7 @@ Editor::Editor() :
m_navMeshDrawFlags( m_navMeshDrawFlags(
DU_DRAW_DETOURMESH_OFFMESHCONS|DU_DRAW_DETOURMESH_WITH_CLOSED_LIST| DU_DRAW_DETOURMESH_OFFMESHCONS|DU_DRAW_DETOURMESH_WITH_CLOSED_LIST|
DU_DRAW_DETOURMESH_POLY_FACES|DU_DRAW_DETOURMESH_POLY_BOUNDS_OUTER|DU_DRAW_DETOURMESH_ALPHA), DU_DRAW_DETOURMESH_POLY_FACES|DU_DRAW_DETOURMESH_POLY_BOUNDS_OUTER|DU_DRAW_DETOURMESH_ALPHA),
m_ignoreWindingOrder(false),
m_filterLowHangingObstacles(true), m_filterLowHangingObstacles(true),
m_filterLedgeSpans(true), m_filterLedgeSpans(true),
m_filterWalkableLowHeightSpans(true), m_filterWalkableLowHeightSpans(true),
@ -331,6 +332,8 @@ void Editor::handleCommonSettings()
snprintf(text, 64, "Voxels: %d x %d", gw, gh); snprintf(text, 64, "Voxels: %d x %d", gw, gh);
ImGui::Text(text); ImGui::Text(text);
} }
ImGui::Checkbox("Ignore Winding Order", &m_ignoreWindingOrder);
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Agent"); ImGui::Text("Agent");

View File

@ -189,6 +189,7 @@ bool Editor_SoloMesh::handleBuild()
m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly; m_cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist; m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError; m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
m_cfg.ignoreWindingOrder = m_ignoreWindingOrder;
// Set the area where the navigation will be build. // Set the area where the navigation will be build.
// Here the bounds of the input mesh are used, but the // Here the bounds of the input mesh are used, but the
@ -238,7 +239,7 @@ bool Editor_SoloMesh::handleBuild()
// If your input data is multiple meshes, you can transform them here, calculate // If your input data is multiple meshes, you can transform them here, calculate
// the are type for each of the meshes and rasterize them. // the are type for each of the meshes and rasterize them.
memset(m_triareas, 0, ntris*sizeof(unsigned char)); memset(m_triareas, 0, ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triareas, true); rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, verts, nverts, tris, ntris, m_triareas, m_cfg.ignoreWindingOrder);
if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, m_triareas, ntris, *m_solid, m_cfg.walkableClimb)) if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, m_triareas, ntris, *m_solid, m_cfg.walkableClimb))
{ {
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not rasterize triangles."); m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not rasterize triangles.");

View File

@ -253,6 +253,8 @@ int Editor_TempObstacles::rasterizeTileLayers(
tcfg.bmin[1] -= tcfg.borderSize*tcfg.cs; tcfg.bmin[1] -= tcfg.borderSize*tcfg.cs;
tcfg.bmax[0] += tcfg.borderSize*tcfg.cs; tcfg.bmax[0] += tcfg.borderSize*tcfg.cs;
tcfg.bmax[1] += tcfg.borderSize*tcfg.cs; tcfg.bmax[1] += tcfg.borderSize*tcfg.cs;
tcfg.ignoreWindingOrder = m_ignoreWindingOrder;
// Allocate voxel heightfield where we rasterize our input data to. // Allocate voxel heightfield where we rasterize our input data to.
rc.solid = rcAllocHeightfield(); rc.solid = rcAllocHeightfield();
@ -298,7 +300,7 @@ int Editor_TempObstacles::rasterizeTileLayers(
memset(rc.triareas, 0, ntris*sizeof(unsigned char)); memset(rc.triareas, 0, ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(m_ctx, tcfg.walkableSlopeAngle, rcMarkWalkableTriangles(m_ctx, tcfg.walkableSlopeAngle,
verts, nverts, tris, ntris, rc.triareas, false); verts, nverts, tris, ntris, rc.triareas, tcfg.ignoreWindingOrder);
if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, rc.triareas, ntris, *rc.solid, tcfg.walkableClimb)) if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, rc.triareas, ntris, *rc.solid, tcfg.walkableClimb))
return 0; return 0;
@ -319,7 +321,7 @@ int Editor_TempObstacles::rasterizeTileLayers(
memset(rc.triareas, 0, ntris * sizeof(unsigned char)); memset(rc.triareas, 0, ntris * sizeof(unsigned char));
rcMarkWalkableTriangles(m_ctx, tcfg.walkableSlopeAngle, rcMarkWalkableTriangles(m_ctx, tcfg.walkableSlopeAngle,
verts, nverts, tris, ntris, rc.triareas, true); verts, nverts, tris, ntris, rc.triareas, tcfg.ignoreWindingOrder);
if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, rc.triareas, ntris, *rc.solid, tcfg.walkableClimb)) if (!rcRasterizeTriangles(m_ctx, verts, nverts, tris, rc.triareas, ntris, *rc.solid, tcfg.walkableClimb))
return 0; return 0;

View File

@ -966,6 +966,7 @@ unsigned char* Editor_TileMesh::buildTileMesh(const int tx, const int ty, const
m_cfg.height = m_cfg.tileSize + m_cfg.borderSize*2; m_cfg.height = m_cfg.tileSize + m_cfg.borderSize*2;
m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist; m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError; m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
m_cfg.ignoreWindingOrder = m_ignoreWindingOrder;
// Expand the heighfield bounding box by border size to find the extents of geometry we need to build this tile. // Expand the heighfield bounding box by border size to find the extents of geometry we need to build this tile.
// //
@ -1051,7 +1052,7 @@ unsigned char* Editor_TileMesh::buildTileMesh(const int tx, const int ty, const
memset(m_triareas, 0, nctris*sizeof(unsigned char)); memset(m_triareas, 0, nctris*sizeof(unsigned char));
rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle,
verts, nverts, ctris, nctris, m_triareas, false); verts, nverts, ctris, nctris, m_triareas, m_cfg.ignoreWindingOrder);
if (!rcRasterizeTriangles(m_ctx, verts, nverts, ctris, m_triareas, nctris, *m_solid, m_cfg.walkableClimb)) if (!rcRasterizeTriangles(m_ctx, verts, nverts, ctris, m_triareas, nctris, *m_solid, m_cfg.walkableClimb))
return 0; return 0;
@ -1075,7 +1076,7 @@ unsigned char* Editor_TileMesh::buildTileMesh(const int tx, const int ty, const
memset(m_triareas, 0, nctris * sizeof(unsigned char)); memset(m_triareas, 0, nctris * sizeof(unsigned char));
rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle,
verts, nverts, ctris, nctris, m_triareas, true); verts, nverts, ctris, nctris, m_triareas, m_cfg.ignoreWindingOrder);
if (!rcRasterizeTriangles(m_ctx, verts, nverts, ctris, m_triareas, nctris, *m_solid, m_cfg.walkableClimb)) if (!rcRasterizeTriangles(m_ctx, verts, nverts, ctris, m_triareas, nctris, *m_solid, m_cfg.walkableClimb))
return 0; return 0;

View File

@ -236,6 +236,7 @@ protected:
class dtNavMeshQuery* m_navQuery; class dtNavMeshQuery* m_navQuery;
class dtCrowd* m_crowd; class dtCrowd* m_crowd;
bool m_ignoreWindingOrder;
bool m_filterLowHangingObstacles; bool m_filterLowHangingObstacles;
bool m_filterLedgeSpans; bool m_filterLedgeSpans;
bool m_filterWalkableLowHeightSpans; bool m_filterWalkableLowHeightSpans;

View File

@ -274,6 +274,10 @@ struct rcConfig
/// The maximum distance the detail mesh surface should deviate from heightfield /// The maximum distance the detail mesh surface should deviate from heightfield
/// data. (For height detail only.) [Limit: >=0] [Units: wu] /// data. (For height detail only.) [Limit: >=0] [Units: wu]
float detailSampleMaxError; float detailSampleMaxError;
/// Whether to ignore the winding order of the input geometry's triangles. If set, backwards
/// facing triangles will still be considered walkable if they meet all other criteria.
bool ignoreWindingOrder;
}; };
/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax. /// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.