Skip to content

feat(mesh-ops): read-only inspect_mesh and suggest_fixes ops (T-A2) - #376

Merged
lightningpixel merged 1 commit into
devfrom
feat/296-inspect-mesh
Oct 19, 2026
Merged

lightningpixel merged 1 commit into
devfrom
feat/296-inspect-mesh

Conversation

@lightningpixel

Copy link
Copy Markdown
Owner

Closes #296

Summary

Adds two read-only operations to the mesh_ops registry so the agent can diagnose a mesh before acting on it — "Is this mesh printable?" now returns an accurate diagnostic without modifying anything.

  • inspect_mesh — watertight, manifold, consistent winding, holes (count, open edges, largest hole), non-manifold edges, degenerate faces, self-intersecting faces, disconnected parts, bounds/dimensions, surface area, volume (only when closed), UVs/normals, and a printable verdict with a list of issues.
  • suggest_fixes — derives registry op calls from the report (repair with flags matching the detected problems and a max_hole_size sized to the largest hole, decimate above 500k faces). Problems no op can fix yet (winding, self-intersections, stray parts) are returned as notes instead of invented fixes.

Changes

  • api/services/mesh_ops/inspection.py — new module; both ops registered in builtin.py under the analysis category (non-destructive).
  • MeshOpResult.file_path is now optional: analysis ops produce no file. /optimize/op/{id} returns the bare report for them; the workflow processor rejects them explicitly.
  • Agent: new inspect_mesh and suggest_fixes tools, and a prompt rule to inspect rather than guess.
  • MCP server: modly_inspect_mesh and modly_suggest_fixes.

Design notes

  • Topology is computed on a position-merged copy of the geometry (scene transforms applied), so UV seams don't read as holes — a naive trimesh load reports textured closed meshes as non-watertight.
  • Self-intersections use pymeshlab (already a repair dependency), in memory. They can be skipped with check_self_intersections: false; printable is then null instead of a claim.
  • Normals are read from the file (glTF NORMAL attribute, OBJ vn, PLY nx), since trimesh always computes them on demand.

Testing

  • npm run test:py — 240 tests pass (4 skipped). 15 new inspection tests on real exported meshes (closed/open box, UV seams, multi-node scene, overlapping parts, normals per format, input never modified), plus router and agent tests.
  • Diagnostic → suggested repair → re-inspection gives a printable mesh.
  • Cross-checked against MeshLab's topological measures on Khronos sample models (Duck, Avocado, DamagedHelmet, BoxTextured): boundary edges, components, holes and non-manifold edges match exactly.
  • Timing: ~2 s for 327k faces, ~8 s for 1.3M faces with self-intersections.

Follow-ups

  • The agent can see that repair is needed but has no tool to run it (only decimate/smooth) — a generic "run registry op" tool belongs to a later Epic A ticket.
  • Not yet run on real TripoSR / Hunyuan outputs.

inspect_mesh diagnoses a mesh without modifying it: watertight, manifold,
winding, holes, degenerate and self-intersecting faces, parts, bounds,
area, volume, UVs/normals, and a printable verdict. suggest_fixes derives
registry op calls (repair, decimate) from that report, and lists the
problems no op can fix yet as notes.

Topology is checked on a position-merged copy, so UV seams do not read
as holes. Self-intersections go through pymeshlab; when they are not
checked, printable is null rather than a claim. Normals are read from
the file itself, since trimesh computes them on demand.

MeshOpResult.file_path is now optional so analysis ops return only
their report. Both ops are exposed to the agent and the MCP server.

Closes #296
@lightningpixel lightningpixel added this to the Release 0.5 milestone Oct 19, 2026
@lightningpixel lightningpixel added the feature New feature label Oct 19, 2026
@lightningpixel lightningpixel self-assigned this Oct 19, 2026
@lightningpixel
lightningpixel merged commit 456f888 into dev Oct 19, 2026
5 checks passed
@lightningpixel
lightningpixel deleted the feat/296-inspect-mesh branch October 19, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant