egametang/ET · error · Exception

rcBuildPolyMeshDetail: Shrinking triangle count from {ntris}

Error message

rcBuildPolyMeshDetail: Shrinking triangle count from {ntris} to max {MAX_TRIS}

What it means

rcBuildPolyMeshDetail caps the per-polygon detail triangle count at MAX_TRIS (255). If Delaunay triangulation yields more, it silently truncates the list to 255*4 ints and then throws to signal the truncation. The data is usable but the highest-detail triangles were dropped.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastMeshDetail.cs:1109

                    // Mark sample as added.
                    samples[besti * 4 + 3] = 1;
                    // Add the new sample point.
                    RcVec3f.Copy(verts, nverts * 3, bestpt, 0);
                    nverts++;

                    // Create new triangulation.
                    // TODO: Incremental add instead of full rebuild.
                    DelaunayHull(ctx, nverts, verts, nhull, hull, tris);
                }
            }

            int ntris = tris.Count / 4;
            if (ntris > MAX_TRIS)
            {
                List<int> subList = tris.GetRange(0, MAX_TRIS * 4);
                tris.Clear();
                tris.AddRange(subList);
                throw new Exception(
                    "rcBuildPolyMeshDetail: Shrinking triangle count from " + ntris + " to max " + MAX_TRIS);
            }

            return nverts;
        }

        static void SeedArrayWithPolyCenter(RcTelemetry ctx, RcCompactHeightfield chf, int[] meshpoly, int poly, int npoly,
            int[] verts, int bs, RcHeightPatch hp, List<int> array)
        {
            // Note: Reads to the compact heightfield are offset by border size (bs)
            // since border size offset is already removed from the polymesh vertices.

            int[] offset = { 0, 0, -1, -1, 0, -1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, -1, 0, };

            // Find cell closest to a poly vertex
            int startCellX = 0, startCellY = 0, startSpanIndex = -1;
            int dmin = RC_UNSET_HEIGHT;
            for (int j = 0; j < npoly && dmin > 0; ++j)

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Reduce detail sampling density: increase rcConfig.detailSampleDist (larger spacing between samples).
  2. Reduce the base polygon size by lowering rcConfig.maxVertsPerPoly or raising cellSize so individual polys are smaller.
  3. Disable internal sampling entirely (detailSampleDist = 0) if fine detail isn't needed.
  4. Accept the truncation by catching the exception if lossy detail is tolerable — but prefer reducing sampling.

Example fix

// before: per-poly detail exceeds 255 tris
cfg.detailSampleDist = 1f;
// after: coarser sampling keeps detail tris under 255
cfg.detailSampleDist = 6f;
Defensive patterns

Strategy: try-catch

Validate before calling

// Estimate detail triangle count; warn if likely to exceed 255
// Heuristic: detail tris scale with sample density * poly area
if (cfg.detailSampleDist > 0 && estimatedDetailTris > MAX_TRIS)
    Log.Warning($"Polygon likely to exceed {MAX_TRIS} detail tris; raising detailSampleDist");

Try / catch

// The mesh is truncated but usable; log and continue if lossy detail is acceptable
try { nverts = buildPolyDetail(...); }
catch (Exception e) when (e.Message.Contains("Shrinking triangle count")) {
    Log.Warning($"Detail truncated to {MAX_TRIS} tris: {e.Message}");
    // tris list is valid (first 255 tris), proceed with lossy detail
}

Prevention

When it happens

Trigger: After DelaunayHull rebuild, ntris = tris.Count/4 exceeds MAX_TRIS (255). The code takes a sub-range of the first 255 triangles and throws. This fires when a single polygon's detail triangulation (with internal sample points) generates more than 255 triangles.

Common situations: Very large base polygons combined with small detailSampleDist (dense internal sampling); polygons spanning large walkable areas that produce hundreds of detail triangles. The truncated mesh loses fine detail at the polygon's edges.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/5326b8f8e2a2d31f. Report an issue: GitHub.