refactor: aligned the parameter order of RasterizeTriangles() to match that of rcRasterizeTriangles() in the recastnavigation project.

This commit is contained in:
ikpil 2024-01-05 00:37:40 +09:00
parent 48a1e18101
commit 507e3548ef
4 changed files with 92 additions and 72 deletions

View File

@ -62,8 +62,8 @@ namespace DotRecast.Detour.Dynamic.Colliders
{ {
for (int i = 0; i < triangles.Length; i += 3) for (int i = 0; i < triangles.Length; i += 3)
{ {
RcRasterizations.RasterizeTriangle(hf, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area, RcRasterizations.RasterizeTriangle(telemetry, vertices, triangles[i], triangles[i + 1], triangles[i + 2], area,
(int)MathF.Floor(flagMergeThreshold / hf.ch), telemetry); hf, (int)MathF.Floor(flagMergeThreshold / hf.ch));
} }
} }
} }

View File

@ -229,31 +229,35 @@ namespace DotRecast.Recast
/// @param[in] inverseCellHeight 1 / cellHeight /// @param[in] inverseCellHeight 1 / cellHeight
/// @param[in] flagMergeThreshold The threshold in which area flags will be merged /// @param[in] flagMergeThreshold The threshold in which area flags will be merged
/// @returns true if the operation completes successfully. false if there was an error adding spans to the heightfield. /// @returns true if the operation completes successfully. false if there was an error adding spans to the heightfield.
private static void RasterizeTri(float[] verts, int v0, int v1, int v2, int area, RcHeightfield heightfield, private static bool RasterizeTri(float[] verts, int v0, int v1, int v2,
int areaID, RcHeightfield heightfield,
RcVec3f heightfieldBBMin, RcVec3f heightfieldBBMax, RcVec3f heightfieldBBMin, RcVec3f heightfieldBBMax,
float cellSize, float inverseCellSize, float inverseCellHeight, float cellSize, float inverseCellSize, float inverseCellHeight,
int flagMergeThreshold) int flagMergeThreshold)
{ {
float by = heightfieldBBMax.Y - heightfieldBBMin.Y;
// Calculate the bounding box of the triangle. // Calculate the bounding box of the triangle.
RcVec3f tmin = RcVecUtils.Create(verts, v0 * 3); RcVec3f triBBMin = RcVecUtils.Create(verts, v0 * 3);
RcVec3f tmax = RcVecUtils.Create(verts, v0 * 3); triBBMin = RcVecUtils.Min(triBBMin, verts, v1 * 3);
tmin = RcVecUtils.Min(tmin, verts, v1 * 3); triBBMin = RcVecUtils.Min(triBBMin, verts, v2 * 3);
tmin = RcVecUtils.Min(tmin, verts, v2 * 3);
tmax = RcVecUtils.Max(tmax, verts, v1 * 3);
tmax = RcVecUtils.Max(tmax, verts, v2 * 3);
// If the triangle does not touch the bbox of the heightfield, skip the triagle. RcVec3f triBBMax = RcVecUtils.Create(verts, v0 * 3);
if (!OverlapBounds(heightfieldBBMin, heightfieldBBMax, tmin, tmax)) triBBMax = RcVecUtils.Max(triBBMax, verts, v1 * 3);
return; triBBMax = RcVecUtils.Max(triBBMax, verts, v2 * 3);
// Calculate the footprint of the triangle on the grid's y-axis // If the triangle does not touch the bounding box of the heightfield, skip the triangle.
int z0 = (int)((tmin.Z - heightfieldBBMin.Z) * inverseCellSize); if (!OverlapBounds(triBBMin, triBBMax, heightfieldBBMin, heightfieldBBMax))
int z1 = (int)((tmax.Z - heightfieldBBMin.Z) * inverseCellSize); {
return true;
}
int w = heightfield.width; int w = heightfield.width;
int h = heightfield.height; int h = heightfield.height;
float by = heightfieldBBMax.Y - heightfieldBBMin.Y;
// Calculate the footprint of the triangle on the grid's y-axis
int z0 = (int)((triBBMin.Z - heightfieldBBMin.Z) * inverseCellSize);
int z1 = (int)((triBBMax.Z - heightfieldBBMin.Z) * inverseCellSize);
// use -1 rather than 0 to cut the polygon properly at the start of the tile // use -1 rather than 0 to cut the polygon properly at the start of the tile
z0 = Math.Clamp(z0, -1, h - 1); z0 = Math.Clamp(z0, -1, h - 1);
z1 = Math.Clamp(z1, 0, h - 1); z1 = Math.Clamp(z1, 0, h - 1);
@ -268,7 +272,8 @@ namespace DotRecast.Recast
RcVecUtils.Copy(buf, 0, verts, v0 * 3); RcVecUtils.Copy(buf, 0, verts, v0 * 3);
RcVecUtils.Copy(buf, 3, verts, v1 * 3); RcVecUtils.Copy(buf, 3, verts, v1 * 3);
RcVecUtils.Copy(buf, 6, verts, v2 * 3); RcVecUtils.Copy(buf, 6, verts, v2 * 3);
int nvRow, nvIn = 3; int nvRow;
int nvIn = 3;
for (int z = z0; z <= z1; ++z) for (int z = z0; z <= z1; ++z)
{ {
@ -278,15 +283,18 @@ namespace DotRecast.Recast
(@in, p1) = (p1, @in); (@in, p1) = (p1, @in);
if (nvRow < 3) if (nvRow < 3)
{
continue; continue;
}
if (z < 0) if (z < 0)
{ {
continue; continue;
} }
// find the horizontal bounds in the row // find X-axis bounds of the row
float minX = buf[inRow], maxX = buf[inRow]; float minX = buf[inRow];
float maxX = buf[inRow];
for (int i = 1; i < nvRow; ++i) for (int i = 1; i < nvRow; ++i)
{ {
float v = buf[inRow + i * 3]; float v = buf[inRow + i * 3];
@ -304,7 +312,8 @@ namespace DotRecast.Recast
x0 = Math.Clamp(x0, -1, w - 1); x0 = Math.Clamp(x0, -1, w - 1);
x1 = Math.Clamp(x1, 0, w - 1); x1 = Math.Clamp(x1, 0, w - 1);
int nv, nv2 = nvRow; int nv;
int nv2 = nvRow;
for (int x = x0; x <= x1; ++x) for (int x = x0; x <= x1; ++x)
{ {
// Clip polygon to column. store the remaining polygon as well // Clip polygon to column. store the remaining polygon as well
@ -313,7 +322,9 @@ namespace DotRecast.Recast
(inRow, p2) = (p2, inRow); (inRow, p2) = (p2, inRow);
if (nv < 3) if (nv < 3)
{
continue; continue;
}
if (x < 0) if (x < 0)
{ {
@ -331,78 +342,87 @@ namespace DotRecast.Recast
spanMin -= heightfieldBBMin.Y; spanMin -= heightfieldBBMin.Y;
spanMax -= heightfieldBBMin.Y; spanMax -= heightfieldBBMin.Y;
// Skip the span if it is outside the heightfield bbox // Skip the span if it is outside the heightfield bbox
if (spanMax < 0.0f) if (spanMax < 0.0f)
{
continue; continue;
}
if (spanMin > by) if (spanMin > by)
{
continue; continue;
}
// Clamp the span to the heightfield bbox. // Clamp the span to the heightfield bbox.
if (spanMin < 0.0f) if (spanMin < 0.0f)
{
spanMin = 0; spanMin = 0;
}
if (spanMax > by) if (spanMax > by)
{
spanMax = by; spanMax = by;
}
// Snap the span to the heightfield height grid. // Snap the span to the heightfield height grid.
int spanMinCellIndex = Math.Clamp((int)MathF.Floor(spanMin * inverseCellHeight), 0, RC_SPAN_MAX_HEIGHT); int spanMinCellIndex = Math.Clamp((int)MathF.Floor(spanMin * inverseCellHeight), 0, RC_SPAN_MAX_HEIGHT);
int spanMaxCellIndex = Math.Clamp((int)MathF.Ceiling(spanMax * inverseCellHeight), spanMinCellIndex + 1, RC_SPAN_MAX_HEIGHT); int spanMaxCellIndex = Math.Clamp((int)MathF.Ceiling(spanMax * inverseCellHeight), spanMinCellIndex + 1, RC_SPAN_MAX_HEIGHT);
AddSpan(heightfield, x, z, spanMinCellIndex, spanMaxCellIndex, area, flagMergeThreshold); AddSpan(heightfield, x, z, spanMinCellIndex, spanMaxCellIndex, areaID, flagMergeThreshold);
}
} }
} }
/** return true;
* Rasterizes a single triangle into the specified heightfield. Calling this for each triangle in a mesh is less }
* efficient than calling rasterizeTriangles. No spans will be added if the triangle does not overlap the
* heightfield grid. /// Rasterizes a single triangle into the specified heightfield.
* ///
* @param heightfield /// Calling this for each triangle in a mesh is less efficient than calling rcRasterizeTriangles
* An initialized heightfield. ///
* @param verts /// No spans will be added if the triangle does not overlap the heightfield grid.
* An array with vertex coordinates [(x, y, z) * N] ///
* @param v0 /// @see rcHeightfield
* Index of triangle vertex 0, will be multiplied by 3 to get vertex coordinates /// @ingroup recast
* @param v1 /// @param[in,out] context The build context to use during the operation.
* Triangle vertex 1 index /// @param[in] v0 Triangle vertex 0 [(x, y, z)]
* @param v2 /// @param[in] v1 Triangle vertex 1 [(x, y, z)]
* Triangle vertex 2 index /// @param[in] v2 Triangle vertex 2 [(x, y, z)]
* @param areaId /// @param[in] areaID The area id of the triangle. [Limit: <= #RC_WALKABLE_AREA]
* The area id of the triangle. [Limit: <= WALKABLE_AREA) /// @param[in,out] heightfield An initialized heightfield.
* @param flagMergeThreshold /// @param[in] flagMergeThreshold The distance where the walkable flag is favored over the non-walkable flag.
* The distance where the walkable flag is favored over the non-walkable flag. [Limit: >= 0] [Units: vx] /// [Limit: >= 0] [Units: vx]
* @see Heightfield /// @returns True if the operation completed successfully.
*/ public static void RasterizeTriangle(RcTelemetry context, float[] verts, int v0, int v1, int v2, int areaID,
public static void RasterizeTriangle(RcHeightfield heightfield, float[] verts, int v0, int v1, int v2, int area, RcHeightfield heightfield, int flagMergeThreshold)
int flagMergeThreshold, RcTelemetry ctx)
{ {
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES); using var timer = context.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES);
// Rasterize the single triangle.
float inverseCellSize = 1.0f / heightfield.cs; float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch; float inverseCellHeight = 1.0f / heightfield.ch;
RasterizeTri(verts, v0, v1, v2, area, heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize, RasterizeTri(verts, v0, v1, v2, areaID, heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize,
inverseCellHeight, flagMergeThreshold); inverseCellHeight, flagMergeThreshold);
} }
/** /// Rasterizes an indexed triangle mesh into the specified heightfield.
* Rasterizes an indexed triangle mesh into the specified heightfield. Spans will only be added for triangles that ///
* overlap the heightfield grid. /// Spans will only be added for triangles that overlap the heightfield grid.
* ///
* @param heightfield /// @see rcHeightfield
* An initialized heightfield. /// @ingroup recast
* @param verts /// @param[in,out] context The build context to use during the operation.
* The vertices. [(x, y, z) * N] /// @param[in] verts The vertices. [(x, y, z) * @p nv]
* @param tris /// @param[in] numVerts The number of vertices. (unused) TODO (graham): Remove in next major release
* The triangle indices. [(vertA, vertB, vertC) * nt] /// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt]
* @param areaIds /// @param[in] triAreaIDs The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
* The area id's of the triangles. [Limit: <= WALKABLE_AREA] [Size: numTris] /// @param[in] numTris The number of triangles.
* @param numTris /// @param[in,out] heightfield An initialized heightfield.
* The number of triangles. /// @param[in] flagMergeThreshold The distance where the walkable flag is favored over the non-walkable flag.
* @param flagMergeThreshold /// [Limit: >= 0] [Units: vx]
* The distance where the walkable flag is favored over the non-walkable flag. [Limit: >= 0] [Units: vx] /// @returns True if the operation completed successfully.
* @see Heightfield public static void RasterizeTriangles(RcTelemetry ctx, float[] verts, int[] tris, int[] triAreaIDs, int numTris,
*/ RcHeightfield heightfield, int flagMergeThreshold)
public static void RasterizeTriangles(RcHeightfield heightfield, float[] verts, int[] tris, int[] areaIds, int numTris,
int flagMergeThreshold, RcTelemetry ctx)
{ {
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES); using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES);
@ -413,7 +433,7 @@ namespace DotRecast.Recast
int v0 = tris[triIndex * 3 + 0]; int v0 = tris[triIndex * 3 + 0];
int v1 = tris[triIndex * 3 + 1]; int v1 = tris[triIndex * 3 + 1];
int v2 = tris[triIndex * 3 + 2]; int v2 = tris[triIndex * 3 + 2];
RasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, RasterizeTri(verts, v0, v1, v2, triAreaIDs[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
inverseCellSize, inverseCellHeight, flagMergeThreshold); inverseCellSize, inverseCellHeight, flagMergeThreshold);
} }
} }

View File

@ -59,7 +59,7 @@ namespace DotRecast.Recast
int[] tris = node.tris; int[] tris = node.tris;
int ntris = tris.Length / 3; int ntris = tris.Length / 3;
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod); int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx); RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
} }
} }
else else
@ -67,7 +67,7 @@ namespace DotRecast.Recast
int[] tris = geom.GetTris(); int[] tris = geom.GetTris();
int ntris = tris.Length / 3; int ntris = tris.Length / 3;
int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod); int[] m_triareas = RcCommons.MarkWalkableTriangles(ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, ctx); RcRasterizations.RasterizeTriangles(ctx, verts, tris, m_triareas, ntris, solid, cfg.WalkableClimb);
} }
} }

View File

@ -140,7 +140,7 @@ public class RecastSoloMeshTest
// 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.
int[] m_triareas = RcCommons.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod); int[] m_triareas = RcCommons.MarkWalkableTriangles(m_ctx, cfg.WalkableSlopeAngle, verts, tris, ntris, cfg.WalkableAreaMod);
RcRasterizations.RasterizeTriangles(m_solid, verts, tris, m_triareas, ntris, cfg.WalkableClimb, m_ctx); RcRasterizations.RasterizeTriangles(m_ctx, verts, tris, m_triareas, ntris, m_solid, cfg.WalkableClimb);
} }
// //