add scoped timer

This commit is contained in:
ikpil 2023-07-08 12:20:20 +09:00
parent deeee5e9d2
commit bc14092125
13 changed files with 205 additions and 110 deletions

View File

@ -0,0 +1,20 @@
using System;
namespace DotRecast.Core
{
public struct RcAnonymousDisposable : IDisposable
{
private Action _dispose;
public RcAnonymousDisposable(Action dispose)
{
_dispose = dispose;
}
public void Dispose()
{
_dispose?.Invoke();
_dispose = null;
}
}
}

View File

@ -35,16 +35,23 @@ namespace DotRecast.Core
_timerAccum = new ConcurrentDictionary<string, RcAtomicLong>();
}
public void StartTimer(string name)
public IDisposable ScopedTimer(RcTimerLabel label)
{
_timerStart.Value[name] = new RcAtomicLong(RcFrequency.Ticks);
StartTimer(label);
return new RcAnonymousDisposable(() => StopTimer(label));
}
public void StartTimer(RcTimerLabel label)
{
_timerStart.Value[label.Name] = new RcAtomicLong(RcFrequency.Ticks);
}
public void StopTimer(string name)
public void StopTimer(RcTimerLabel label)
{
_timerAccum
.GetOrAdd(name, _ => new RcAtomicLong(0))
.AddAndGet(RcFrequency.Ticks - _timerStart.Value?[name].Read() ?? 0);
.GetOrAdd(label.Name, _ => new RcAtomicLong(0))
.AddAndGet(RcFrequency.Ticks - _timerStart.Value?[label.Name].Read() ?? 0);
}
public void Warn(string message)

View File

@ -0,0 +1,109 @@
namespace DotRecast.Core
{
/// Recast performance timer categories.
/// @see rcContext
public class RcTimerLabel
{
/// The user defined total time of the build.
public static readonly RcTimerLabel RC_TIMER_TOTAL = new RcTimerLabel(nameof(RC_TIMER_TOTAL));
/// A user defined build time.
public static readonly RcTimerLabel RC_TIMER_TEMP = new RcTimerLabel(nameof(RC_TIMER_TEMP));
/// The time to rasterize the triangles. (See: #rcRasterizeTriangle)
public static readonly RcTimerLabel RC_TIMER_RASTERIZE_TRIANGLES = new RcTimerLabel(nameof(RC_TIMER_RASTERIZE_TRIANGLES));
public static readonly RcTimerLabel RC_TIMER_RASTERIZE_SPHERE = new RcTimerLabel(nameof(RC_TIMER_RASTERIZE_SPHERE));
public static readonly RcTimerLabel RC_TIMER_RASTERIZE_CAPSULE = new RcTimerLabel(nameof(RC_TIMER_RASTERIZE_CAPSULE));
public static readonly RcTimerLabel RC_TIMER_RASTERIZE_CYLINDER = new RcTimerLabel(nameof(RC_TIMER_RASTERIZE_CYLINDER));
public static readonly RcTimerLabel RC_TIMER_RASTERIZE_BOX = new RcTimerLabel(nameof(RC_TIMER_RASTERIZE_BOX));
public static readonly RcTimerLabel RC_TIMER_RASTERIZE_CONVEX = new RcTimerLabel(nameof(RC_TIMER_RASTERIZE_CONVEX));
/// The time to build the compact heightfield. (See: #rcBuildCompactHeightfield)
public static readonly RcTimerLabel RC_TIMER_BUILD_COMPACTHEIGHTFIELD = new RcTimerLabel(nameof(RC_TIMER_BUILD_COMPACTHEIGHTFIELD));
/// The total time to build the contours. (See: #rcBuildContours)
public static readonly RcTimerLabel RC_TIMER_BUILD_CONTOURS = new RcTimerLabel(nameof(RC_TIMER_BUILD_CONTOURS));
/// The time to trace the boundaries of the contours. (See: #rcBuildContours)
public static readonly RcTimerLabel RC_TIMER_BUILD_CONTOURS_TRACE = new RcTimerLabel(nameof(RC_TIMER_BUILD_CONTOURS_TRACE));
public static readonly RcTimerLabel RC_TIMER_BUILD_CONTOURS_WALK = new RcTimerLabel(nameof(RC_TIMER_BUILD_CONTOURS_WALK));
/// The time to simplify the contours. (See: #rcBuildContours)
public static readonly RcTimerLabel RC_TIMER_BUILD_CONTOURS_SIMPLIFY = new RcTimerLabel(nameof(RC_TIMER_BUILD_CONTOURS_SIMPLIFY));
/// The time to filter ledge spans. (See: #rcFilterLedgeSpans)
public static readonly RcTimerLabel RC_TIMER_FILTER_BORDER = new RcTimerLabel(nameof(RC_TIMER_FILTER_BORDER));
/// The time to filter low height spans. (See: #rcFilterWalkableLowHeightSpans)
public static readonly RcTimerLabel RC_TIMER_FILTER_WALKABLE = new RcTimerLabel(nameof(RC_TIMER_FILTER_WALKABLE));
/// The time to apply the median filter. (See: #rcMedianFilterWalkableArea)
public static readonly RcTimerLabel RC_TIMER_MEDIAN_AREA = new RcTimerLabel(nameof(RC_TIMER_MEDIAN_AREA));
/// The time to filter low obstacles. (See: #rcFilterLowHangingWalkableObstacles)
public static readonly RcTimerLabel RC_TIMER_FILTER_LOW_OBSTACLES = new RcTimerLabel(nameof(RC_TIMER_FILTER_LOW_OBSTACLES));
/// The time to build the polygon mesh. (See: #rcBuildPolyMesh)
public static readonly RcTimerLabel RC_TIMER_BUILD_POLYMESH = new RcTimerLabel(nameof(RC_TIMER_BUILD_POLYMESH));
/// The time to merge polygon meshes. (See: #rcMergePolyMeshes)
public static readonly RcTimerLabel RC_TIMER_MERGE_POLYMESH = new RcTimerLabel(nameof(RC_TIMER_MERGE_POLYMESH));
/// The time to erode the walkable area. (See: #rcErodeWalkableArea)
public static readonly RcTimerLabel RC_TIMER_ERODE_AREA = new RcTimerLabel(nameof(RC_TIMER_ERODE_AREA));
/// The time to mark a box area. (See: #rcMarkBoxArea)
public static readonly RcTimerLabel RC_TIMER_MARK_BOX_AREA = new RcTimerLabel(nameof(RC_TIMER_MARK_BOX_AREA));
/// The time to mark a cylinder area. (See: #rcMarkCylinderArea)
public static readonly RcTimerLabel RC_TIMER_MARK_CYLINDER_AREA = new RcTimerLabel(nameof(RC_TIMER_MARK_CYLINDER_AREA));
/// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea)
public static readonly RcTimerLabel RC_TIMER_MARK_CONVEXPOLY_AREA = new RcTimerLabel(nameof(RC_TIMER_MARK_CONVEXPOLY_AREA));
/// The total time to build the distance field. (See: #rcBuildDistanceField)
public static readonly RcTimerLabel RC_TIMER_BUILD_DISTANCEFIELD = new RcTimerLabel(nameof(RC_TIMER_BUILD_DISTANCEFIELD));
/// The time to build the distances of the distance field. (See: #rcBuildDistanceField)
public static readonly RcTimerLabel RC_TIMER_BUILD_DISTANCEFIELD_DIST = new RcTimerLabel(nameof(RC_TIMER_BUILD_DISTANCEFIELD_DIST));
/// The time to blur the distance field. (See: #rcBuildDistanceField)
public static readonly RcTimerLabel RC_TIMER_BUILD_DISTANCEFIELD_BLUR = new RcTimerLabel(nameof(RC_TIMER_BUILD_DISTANCEFIELD_BLUR));
/// The total time to build the regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
public static readonly RcTimerLabel RC_TIMER_BUILD_REGIONS = new RcTimerLabel(nameof(RC_TIMER_BUILD_REGIONS));
/// The total time to apply the watershed algorithm. (See: #rcBuildRegions)
public static readonly RcTimerLabel RC_TIMER_BUILD_REGIONS_WATERSHED = new RcTimerLabel(nameof(RC_TIMER_BUILD_REGIONS_WATERSHED));
/// The time to expand regions while applying the watershed algorithm. (See: #rcBuildRegions)
public static readonly RcTimerLabel RC_TIMER_BUILD_REGIONS_EXPAND = new RcTimerLabel(nameof(RC_TIMER_BUILD_REGIONS_EXPAND));
/// The time to flood regions while applying the watershed algorithm. (See: #rcBuildRegions)
public static readonly RcTimerLabel RC_TIMER_BUILD_REGIONS_FLOOD = new RcTimerLabel(nameof(RC_TIMER_BUILD_REGIONS_FLOOD));
/// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
public static readonly RcTimerLabel RC_TIMER_BUILD_REGIONS_FILTER = new RcTimerLabel(nameof(RC_TIMER_BUILD_REGIONS_FILTER));
/// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers)
public static readonly RcTimerLabel RC_TIMER_BUILD_LAYERS = new RcTimerLabel(nameof(RC_TIMER_BUILD_LAYERS));
/// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail)
public static readonly RcTimerLabel RC_TIMER_BUILD_POLYMESHDETAIL = new RcTimerLabel(nameof(RC_TIMER_BUILD_POLYMESHDETAIL));
/// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails)
public static readonly RcTimerLabel RC_TIMER_MERGE_POLYMESHDETAIL = new RcTimerLabel(nameof(RC_TIMER_MERGE_POLYMESHDETAIL));
/// The maximum number of timers. (Used for iterating timers.)
public static readonly RcTimerLabel RC_MAX_TIMERS = new RcTimerLabel(nameof(RC_MAX_TIMERS));
public readonly string Name;
private RcTimerLabel(string name)
{
Name = name;
}
};
}

View File

@ -39,7 +39,7 @@ namespace DotRecast.Recast
{
int w = chf.width;
int h = chf.height;
ctx.StartTimer("ERODE_AREA");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_ERODE_AREA);
int[] dist = new int[chf.spanCount];
Array.Fill(dist, 255);
@ -205,8 +205,6 @@ namespace DotRecast.Recast
for (int i = 0; i < chf.spanCount; ++i)
if (dist[i] < thr)
chf.areas[i] = RC_NULL_AREA;
ctx.StopTimer("ERODE_AREA");
}
/// @par
@ -220,7 +218,7 @@ namespace DotRecast.Recast
int w = chf.width;
int h = chf.height;
ctx.StartTimer("MEDIAN_AREA");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MEDIAN_AREA);
int[] areas = new int[chf.spanCount];
@ -273,8 +271,6 @@ namespace DotRecast.Recast
chf.areas = areas;
ctx.StopTimer("MEDIAN_AREA");
return true;
}
@ -285,7 +281,7 @@ namespace DotRecast.Recast
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
public static void MarkBoxArea(RcTelemetry ctx, float[] bmin, float[] bmax, AreaModification areaMod, RcCompactHeightfield chf)
{
ctx.StartTimer("MARK_BOX_AREA");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MARK_BOX_AREA);
int minx = (int)((bmin[0] - chf.bmin.x) / chf.cs);
int miny = (int)((bmin[1] - chf.bmin.y) / chf.ch);
@ -328,8 +324,6 @@ namespace DotRecast.Recast
}
}
}
ctx.StopTimer("MARK_BOX_AREA");
}
static bool PointInPoly(float[] verts, RcVec3f p)
@ -360,7 +354,7 @@ namespace DotRecast.Recast
public static void MarkConvexPolyArea(RcTelemetry ctx, float[] verts, float hmin, float hmax, AreaModification areaMod,
RcCompactHeightfield chf)
{
ctx.StartTimer("MARK_CONVEXPOLY_AREA");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MARK_CONVEXPOLY_AREA);
RcVec3f bmin = new RcVec3f();
RcVec3f bmax = new RcVec3f();
@ -368,8 +362,8 @@ namespace DotRecast.Recast
RcVec3f.Copy(ref bmax, verts, 0);
for (int i = 3; i < verts.Length; i += 3)
{
bmin.Min(verts, i);
bmax.Max(verts, i);
bmin.Min(verts, i);
bmax.Max(verts, i);
}
bmin.y = hmin;
@ -426,8 +420,6 @@ namespace DotRecast.Recast
}
}
}
ctx.StopTimer("MARK_CONVEXPOLY_AREA");
}
/// @par
@ -437,7 +429,7 @@ namespace DotRecast.Recast
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
public static void MarkCylinderArea(RcTelemetry ctx, float[] pos, float r, float h, AreaModification areaMod, RcCompactHeightfield chf)
{
ctx.StartTimer("MARK_CYLINDER_AREA");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MARK_CYLINDER_AREA);
RcVec3f bmin = new RcVec3f();
RcVec3f bmax = new RcVec3f();
@ -501,8 +493,6 @@ namespace DotRecast.Recast
}
}
}
ctx.StopTimer("MARK_CYLINDER_AREA");
}
}
}
}

View File

@ -41,7 +41,7 @@ namespace DotRecast.Recast
public static RcCompactHeightfield BuildCompactHeightfield(RcTelemetry ctx, int walkableHeight, int walkableClimb,
RcHeightfield hf)
{
ctx.StartTimer("BUILD_COMPACTHEIGHTFIELD");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
RcCompactHeightfield chf = new RcCompactHeightfield();
int w = hf.width;
@ -161,7 +161,6 @@ namespace DotRecast.Recast
+ " (max: " + MAX_LAYERS + ")");
}
ctx.StopTimer("BUILD_COMPACTHEIGHTFIELD");
return chf;
}

View File

@ -722,7 +722,8 @@ namespace DotRecast.Recast
int borderSize = chf.borderSize;
RcContourSet cset = new RcContourSet();
ctx.StartTimer("CONTOURS");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS);
cset.bmin = chf.bmin;
cset.bmax = chf.bmax;
if (borderSize > 0)
@ -744,7 +745,7 @@ namespace DotRecast.Recast
int[] flags = new int[chf.spanCount];
ctx.StartTimer("CONTOURS_TRACE");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS_TRACE);
// Mark boundaries.
for (int y = 0; y < h; ++y)
@ -782,7 +783,7 @@ namespace DotRecast.Recast
}
}
ctx.StopTimer("CONTOURS_TRACE");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS_TRACE);
List<int> verts = new List<int>(256);
List<int> simplified = new List<int>(64);
@ -808,14 +809,14 @@ namespace DotRecast.Recast
verts.Clear();
simplified.Clear();
ctx.StartTimer("CONTOURS_WALK");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS_WALK);
WalkContour(x, y, i, chf, flags, verts);
ctx.StopTimer("CONTOURS_WALK");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS_WALK);
ctx.StartTimer("CONTOURS_SIMPLIFY");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
SimplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
RemoveDegenerateSegments(simplified);
ctx.StopTimer("CONTOURS_SIMPLIFY");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
// Store region->contour remap info.
// Create contour.
@ -956,7 +957,6 @@ namespace DotRecast.Recast
}
}
ctx.StopTimer("CONTOURS");
return cset;
}
}

View File

@ -31,7 +31,7 @@ namespace DotRecast.Recast
public static void RasterizeSphere(RcHeightfield hf, RcVec3f center, float radius, int area, int flagMergeThr, RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_SPHERE");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_SPHERE);
float[] bounds =
{
center.x - radius, center.y - radius, center.z - radius, center.x + radius, center.y + radius,
@ -39,13 +39,12 @@ namespace DotRecast.Recast
};
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectSphere(rectangle, center, radius * radius));
ctx.StopTimer("RASTERIZE_SPHERE");
}
public static void RasterizeCapsule(RcHeightfield hf, RcVec3f start, RcVec3f end, float radius, int area, int flagMergeThr,
RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_CAPSULE");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CAPSULE);
float[] bounds =
{
Math.Min(start.x, end.x) - radius, Math.Min(start.y, end.y) - radius,
@ -55,13 +54,12 @@ namespace DotRecast.Recast
RcVec3f axis = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectCapsule(rectangle, start, end, axis, radius * radius));
ctx.StopTimer("RASTERIZE_CAPSULE");
}
public static void RasterizeCylinder(RcHeightfield hf, RcVec3f start, RcVec3f end, float radius, int area, int flagMergeThr,
RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_CYLINDER");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CYLINDER);
float[] bounds =
{
Math.Min(start.x, end.x) - radius, Math.Min(start.y, end.y) - radius,
@ -71,13 +69,12 @@ namespace DotRecast.Recast
RcVec3f axis = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectCylinder(rectangle, start, end, axis, radius * radius));
ctx.StopTimer("RASTERIZE_CYLINDER");
}
public static void RasterizeBox(RcHeightfield hf, RcVec3f center, RcVec3f[] halfEdges, int area, int flagMergeThr,
RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_BOX");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_BOX);
RcVec3f[] normals =
{
RcVec3f.Of(halfEdges[0].x, halfEdges[0].y, halfEdges[0].z),
@ -123,13 +120,12 @@ namespace DotRecast.Recast
}
RasterizationFilledShape(hf, bounds, area, flagMergeThr, rectangle => IntersectBox(rectangle, vertices, planes));
ctx.StopTimer("RASTERIZE_BOX");
}
public static void RasterizeConvex(RcHeightfield hf, float[] vertices, int[] triangles, int area, int flagMergeThr,
RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_CONVEX");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_CONVEX);
float[] bounds = new float[] { vertices[0], vertices[1], vertices[2], vertices[0], vertices[1], vertices[2] };
for (int i = 0; i < vertices.Length; i += 3)
{
@ -179,7 +175,6 @@ namespace DotRecast.Recast
RasterizationFilledShape(hf, bounds, area, flagMergeThr,
rectangle => IntersectConvex(rectangle, triangles, vertices, planes, triBounds));
ctx.StopTimer("RASTERIZE_CONVEX");
}
private static void Plane(float[][] planes, int p, float[] v1, float[] v2, float[] vertices, int vert)
@ -796,4 +791,4 @@ namespace DotRecast.Recast
return overlap;
}
}
}
}

View File

@ -40,7 +40,7 @@ namespace DotRecast.Recast
/// @see rcHeightfield, rcConfig
public static void FilterLowHangingWalkableObstacles(RcTelemetry ctx, int walkableClimb, RcHeightfield solid)
{
ctx.StartTimer("FILTER_LOW_OBSTACLES");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_FILTER_LOW_OBSTACLES);
int w = solid.width;
int h = solid.height;
@ -71,8 +71,6 @@ namespace DotRecast.Recast
}
}
}
ctx.StopTimer("FILTER_LOW_OBSTACLES");
}
/// @par
@ -87,7 +85,7 @@ namespace DotRecast.Recast
/// @see rcHeightfield, rcConfig
public static void FilterLedgeSpans(RcTelemetry ctx, int walkableHeight, int walkableClimb, RcHeightfield solid)
{
ctx.StartTimer("FILTER_LEDGE");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_FILTER_BORDER);
int w = solid.width;
int h = solid.height;
@ -168,8 +166,6 @@ namespace DotRecast.Recast
}
}
}
ctx.StopTimer("FILTER_LEDGE");
}
/// @par
@ -180,7 +176,7 @@ namespace DotRecast.Recast
/// @see rcHeightfield, rcConfig
public static void FilterWalkableLowHeightSpans(RcTelemetry ctx, int walkableHeight, RcHeightfield solid)
{
ctx.StartTimer("FILTER_WALKABLE");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_FILTER_WALKABLE);
int w = solid.width;
int h = solid.height;
@ -200,8 +196,6 @@ namespace DotRecast.Recast
}
}
}
ctx.StopTimer("FILTER_WALKABLE");
}
}
}

View File

@ -53,7 +53,8 @@ namespace DotRecast.Recast
public static RcHeightfieldLayerSet BuildHeightfieldLayers(RcTelemetry ctx, RcCompactHeightfield chf, int walkableHeight)
{
ctx.StartTimer("RC_TIMER_BUILD_LAYERS");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_LAYERS);
int w = chf.width;
int h = chf.height;
int borderSize = chf.borderSize;
@ -397,7 +398,7 @@ namespace DotRecast.Recast
// No layers, return empty.
if (layerId == 0)
{
// ctx.StopTimer(RC_TIMER_BUILD_LAYERS);
// ctx.Stop(RC_TIMER_BUILD_LAYERS);
return null;
}

View File

@ -966,7 +966,8 @@ namespace DotRecast.Recast
/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
public static RcPolyMesh BuildPolyMesh(RcTelemetry ctx, RcContourSet cset, int nvp)
{
ctx.StartTimer("POLYMESH");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_POLYMESH);
RcPolyMesh mesh = new RcPolyMesh();
mesh.bmin = cset.bmin;
mesh.bmax = cset.bmax;
@ -1204,7 +1205,6 @@ namespace DotRecast.Recast
+ " (max " + MAX_MESH_VERTS_POLY + "). Data can be corrupted.");
}
ctx.StopTimer("POLYMESH");
return mesh;
}
@ -1214,7 +1214,8 @@ namespace DotRecast.Recast
if (nmeshes == 0 || meshes == null)
return null;
ctx.StartTimer("MERGE_POLYMESH");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MERGE_POLYMESH);
RcPolyMesh mesh = new RcPolyMesh();
mesh.nvp = meshes[0].nvp;
mesh.cs = meshes[0].cs;
@ -1333,8 +1334,6 @@ namespace DotRecast.Recast
+ " (max " + MAX_MESH_VERTS_POLY + "). Data can be corrupted.");
}
ctx.StopTimer("MERGE_POLYMESH");
return mesh;
}

View File

@ -1009,8 +1009,8 @@ namespace DotRecast.Recast
RcVec3f.Copy(ref bmax, @in, 0);
for (int i = 1; i < nin; ++i)
{
bmin.Min(@in, i * 3);
bmax.Max(@in, i * 3);
bmin.Min(@in, i * 3);
bmax.Max(@in, i * 3);
}
int x0 = (int)Math.Floor(bmin.x / sampleDist);
@ -1426,7 +1426,7 @@ namespace DotRecast.Recast
public static RcPolyMeshDetail BuildPolyMeshDetail(RcTelemetry ctx, RcPolyMesh mesh, RcCompactHeightfield chf,
float sampleDist, float sampleMaxError)
{
ctx.StartTimer("POLYMESHDETAIL");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_POLYMESHDETAIL);
if (mesh.nverts == 0 || mesh.npolys == 0)
{
return null;
@ -1610,16 +1610,15 @@ namespace DotRecast.Recast
}
}
ctx.StopTimer("POLYMESHDETAIL");
return dmesh;
}
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
private static RcPolyMeshDetail MergePolyMeshDetails(RcTelemetry ctx, RcPolyMeshDetail[] meshes, int nmeshes)
{
RcPolyMeshDetail mesh = new RcPolyMeshDetail();
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_MERGE_POLYMESHDETAIL);
ctx.StartTimer("MERGE_POLYMESHDETAIL");
RcPolyMeshDetail mesh = new RcPolyMeshDetail();
int maxVerts = 0;
int maxTris = 0;
@ -1680,7 +1679,6 @@ namespace DotRecast.Recast
}
}
ctx.StopTimer("MERGE_POLYMESHDETAIL");
return mesh;
}
}

View File

@ -400,14 +400,12 @@ namespace DotRecast.Recast
public static void RasterizeTriangle(RcHeightfield heightfield, float[] verts, int v0, int v1, int v2, int area,
int flagMergeThreshold, RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_TRIANGLES");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES);
float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch;
RasterizeTri(verts, v0, v1, v2, area, heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs, inverseCellSize,
inverseCellHeight, flagMergeThreshold);
ctx.StopTimer("RASTERIZE_TRIANGLES");
}
/**
@ -431,7 +429,7 @@ namespace DotRecast.Recast
public static void RasterizeTriangles(RcHeightfield heightfield, float[] verts, int[] tris, int[] areaIds, int numTris,
int flagMergeThreshold, RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_TRIANGLES");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES);
float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch;
@ -443,8 +441,6 @@ namespace DotRecast.Recast
RasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
inverseCellSize, inverseCellHeight, flagMergeThreshold);
}
ctx.StopTimer("RASTERIZE_TRIANGLES");
}
/**
@ -468,7 +464,7 @@ namespace DotRecast.Recast
public static void RasterizeTriangles(RcHeightfield heightfield, float[] verts, int[] areaIds, int numTris,
int flagMergeThreshold, RcTelemetry ctx)
{
ctx.StartTimer("RASTERIZE_TRIANGLES");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_RASTERIZE_TRIANGLES);
float inverseCellSize = 1.0f / heightfield.cs;
float inverseCellHeight = 1.0f / heightfield.ch;
@ -480,8 +476,6 @@ namespace DotRecast.Recast
RasterizeTri(verts, v0, v1, v2, areaIds[triIndex], heightfield, heightfield.bmin, heightfield.bmax, heightfield.cs,
inverseCellSize, inverseCellHeight, flagMergeThreshold);
}
ctx.StopTimer("RASTERIZE_TRIANGLES");
}
}
}

View File

@ -580,7 +580,6 @@ namespace DotRecast.Recast
}
private static void RemoveAdjacentNeighbours(RcRegion reg)
{
// Remove adjacent duplicates.
@ -1418,16 +1417,16 @@ namespace DotRecast.Recast
/// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone
public static void BuildDistanceField(RcTelemetry ctx, RcCompactHeightfield chf)
{
ctx.StartTimer("DISTANCEFIELD");
int[] src = new int[chf.spanCount];
ctx.StartTimer("DISTANCEFIELD_DIST");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_DISTANCEFIELD);
int[] src = new int[chf.spanCount];
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_DISTANCEFIELD_DIST);
int maxDist = CalculateDistanceField(chf, src);
chf.maxDistance = maxDist;
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_DISTANCEFIELD_DIST);
ctx.StopTimer("DISTANCEFIELD_DIST");
ctx.StartTimer("DISTANCEFIELD_BLUR");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_DISTANCEFIELD_BLUR);
// Blur
src = BoxBlur(chf, 1, src);
@ -1435,9 +1434,7 @@ namespace DotRecast.Recast
// Store distance.
chf.dist = src;
ctx.StopTimer("DISTANCEFIELD_BLUR");
ctx.StopTimer("DISTANCEFIELD");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_DISTANCEFIELD_BLUR);
}
private static void PaintRectRegion(int minx, int maxx, int miny, int maxy, int regId, RcCompactHeightfield chf,
@ -1482,7 +1479,7 @@ namespace DotRecast.Recast
public static void BuildRegionsMonotone(RcTelemetry ctx, RcCompactHeightfield chf, int minRegionArea,
int mergeRegionArea)
{
ctx.StartTimer("REGIONS");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS);
int w = chf.width;
int h = chf.height;
@ -1624,23 +1621,19 @@ namespace DotRecast.Recast
}
}
ctx.StartTimer("REGIONS_FILTER");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER);
// Merge regions and filter out small regions.
List<int> overlaps = new List<int>();
chf.maxRegions = MergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, id, chf, srcReg, overlaps);
// Monotone partitioning does not generate overlapping regions.
ctx.StopTimer("REGIONS_FILTER");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER);
// Store the result out.
for (int i = 0; i < chf.spanCount; ++i)
{
chf.spans[i].reg = srcReg[i];
}
ctx.StopTimer("REGIONS");
}
/// @par
@ -1665,13 +1658,13 @@ namespace DotRecast.Recast
public static void BuildRegions(RcTelemetry ctx, RcCompactHeightfield chf, int minRegionArea,
int mergeRegionArea)
{
ctx.StartTimer("REGIONS");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS);
int w = chf.width;
int h = chf.height;
int borderSize = chf.borderSize;
ctx.StartTimer("REGIONS_WATERSHED");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_WATERSHED);
int LOG_NB_STACKS = 3;
int NB_STACKS = 1 << LOG_NB_STACKS;
@ -1732,14 +1725,14 @@ namespace DotRecast.Recast
// ctx->StopTimer(RC_TIMER_DIVIDE_TO_LEVELS);
ctx.StartTimer("REGIONS_EXPAND");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_EXPAND);
// Expand current regions until no empty connected cells found.
ExpandRegions(expandIters, level, chf, srcReg, srcDist, lvlStacks[sId], false);
ctx.StopTimer("REGIONS_EXPAND");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_EXPAND);
ctx.StartTimer("REGIONS_FLOOD");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FLOOD);
// Mark new regions with IDs.
for (int j = 0; j < lvlStacks[sId].Count; j += 3)
@ -1756,15 +1749,15 @@ namespace DotRecast.Recast
}
}
ctx.StopTimer("REGIONS_FLOOD");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FLOOD);
}
// Expand current regions until no empty connected cells found.
ExpandRegions(expandIters * 8, 0, chf, srcReg, srcDist, stack, true);
ctx.StopTimer("REGIONS_WATERSHED");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_WATERSHED);
ctx.StartTimer("REGIONS_FILTER");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER);
// Merge regions and filter out smalle regions.
List<int> overlaps = new List<int>();
@ -1776,20 +1769,18 @@ namespace DotRecast.Recast
ctx.Warn("rcBuildRegions: " + overlaps.Count + " overlapping regions.");
}
ctx.StopTimer("REGIONS_FILTER");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER);
// Write the result out.
for (int i = 0; i < chf.spanCount; ++i)
{
chf.spans[i].reg = srcReg[i];
}
ctx.StopTimer("REGIONS");
}
public static void BuildLayerRegions(RcTelemetry ctx, RcCompactHeightfield chf, int minRegionArea)
{
ctx.StartTimer("REGIONS");
using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS);
int w = chf.width;
int h = chf.height;
@ -1930,21 +1921,19 @@ namespace DotRecast.Recast
}
}
ctx.StartTimer("REGIONS_FILTER");
ctx.StartTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER);
// Merge monotone regions to layers and remove small regions.
List<int> overlaps = new List<int>();
chf.maxRegions = MergeAndFilterLayerRegions(ctx, minRegionArea, id, chf, srcReg, overlaps);
ctx.StopTimer("REGIONS_FILTER");
ctx.StopTimer(RcTimerLabel.RC_TIMER_BUILD_REGIONS_FILTER);
// Store the result out.
for (int i = 0; i < chf.spanCount; ++i)
{
chf.spans[i].reg = srcReg[i];
}
ctx.StopTimer("REGIONS");
}
}
}
}