egametang/ET · warning · Exception

removeVertex: Too many polygons {mesh.npolys} (max:{maxTris}

Error message

removeVertex: Too many polygons {mesh.npolys} (max:{maxTris}.

What it means

Thrown inside removeVertex (RecastMesh) when the number of generated polygons (mesh.npolys) exceeds maxTris during vertex removal and re-triangulation. Removing a shared vertex can fan out into many triangles; if the surrounding geometry is dense, the re-triangulation overflows the allocated polygon buffer.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Recast/RecastMesh.cs:958

                    }
                }
            }

            // Store polygons.
            for (int i = 0; i < npolys; ++i)
            {
                if (mesh.npolys >= maxTris)
                    break;
                int p = mesh.npolys * nvp * 2;
                Array.Fill(mesh.polys, RC_MESH_NULL_IDX, p, (p + nvp * 2) - (p));
                for (int j = 0; j < nvp; ++j)
                    mesh.polys[p + j] = polys[i * nvp + j];
                mesh.regs[mesh.npolys] = pregs[i];
                mesh.areas[mesh.npolys] = pareas[i];
                mesh.npolys++;
                if (mesh.npolys > maxTris)
                {
                    throw new Exception("removeVertex: Too many polygons " + mesh.npolys + " (max:" + maxTris + ".");
                }
            }
        }

        /// @par
        ///
        /// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper
        /// limit must be restricted to <= #DT_VERTS_PER_POLYGON.
        ///
        /// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
        public static RcPolyMesh BuildPolyMesh(RcTelemetry ctx, RcContourSet cset, int nvp)
        {
            using var timer = ctx.ScopedTimer(RcTimerLabel.RC_TIMER_BUILD_POLYMESH);

            RcPolyMesh mesh = new RcPolyMesh();
            mesh.bmin = cset.bmin;
            mesh.bmax = cset.bmax;
            mesh.cs = cset.cs;

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Increase the maxTris / detail polygon budget passed to the mesh builder.
  2. Reduce tile size so each tile's polygon count stays under the limit.
  3. Simplify source geometry or increase contour simplification to lower polygon density.
  4. Avoid manually removing highly-shared vertices; let the builder choose removables.

Example fix

// before
int maxTris = nvp * 4; // too small for dense tile

// after
int maxTris = Math.Max(nvp * 4, expectedPolyCount * 2);
// and/or reduce cfg.tileSize
Defensive patterns

Strategy: validation

Validate before calling

int maxTris = Math.Max(nvp * 4, expectedPolyCount * 2);
if (maxTris < mesh.npolys + safetyMargin) throw new InvalidOperationException("maxTris too small for vertex removal");

Try / catch

try { RecastMesh.RemoveVertex(...); }
catch (Exception e) when (e.Message.Contains("Too many polygons"))
{ /* increase maxTris budget or reduce tile size, retry */ }

Prevention

When it happens

Trigger: Removing a vertex shared by many polygons in dense mesh detail; maxTris (derived from the detail/triangle budget) too small for the fan-out; large complex contours feeding BuildPolyMesh.

Common situations: High-detail input meshes producing dense polymes; tile size too large concentrating polygons; nvp config causing many-triangle fans.

Related errors


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