← All Baltor Engineering Posts · Post 03 of 08 · 2026-10-18 · 3D Geometry & Verification · 9 min read · Raw Markdown (.md) · Open Live Studio ↗

Eliminating Non-Manifold LLM Meshes in Blender bpy and Three.js r170+

Unassisted LLMs generate 3D meshes with open boundary seams, inverted winding normals, and self-intersecting lathe profiles. Here is the exact half-edge manifold gate Baltor runs before exporting .glb assets.


HALF-EDGE MANIFOLD & NORMAL WINDING VERIFICATION GATE (BLENDER BPY + THREE.JS R186) UNASSISTED LLM MESH FAILURES 1. Edge valence != 2 (open seams) 2. Inconsistent CCW face winding 3. Zero-area pole triangles at r=0 4. Flat bump map faking 3D relief DETERMINISTIC MANIFOLD CHECKER weldVertices(eps = 1e-5) assert every directed edge (u,v) has exactly 1 opposite (v,u) V - E + F == 2 - 2g (Euler-Poincare) VERIFIED .GLB / BUFFERGEOMETRY Watertight 2-manifold shell Outward MikkTSpace tangents True fluted lathe relief 0 boundary edges | 60 FPS

When asked to create a fluted architectural column, a procedural ceramic vessel, or an articulated character mesh in Blender bpy or Three.js r170+, unassisted language models fail in two predictable ways. Either they emit a smooth cylinder with a 2D noise texture and call it "3D surface relief," or they emit raw vertex arrays with open seam edges (valence != 2), inverted face winding, and degenerate zero-area triangles at the poles. By placing a deterministic half-edge manifold verifier and parametric lathe generator inside the Baltor harness (assets.baltor.ai and compare.baltor.ai/?mode=relief), 100% of promoted meshes satisfy watertight 2-manifold invariants before rendering or .glb export.

Three geometric invariants every procedural mesh must pass

A triangle mesh M = (V, E, F) is a closed, orientable 2-manifold only if it satisfies three topological and geometric checks after spatial vertex welding (epsilon = 1e-5):

// Half-Edge Manifold & Winding Verifier for Three.js BufferGeometry
export function verifyWatertightManifold(positions, indices) {
  const directedEdges = new Map();
  const undirectedCounts = new Map();
  let degenerateFaces = 0;
  let signedVolume6 = 0;

  for (let i = 0; i < indices.length; i += 3) {
    const a = indices[i], b = indices[i + 1], c = indices[i + 2];
    const ax = positions[a*3], ay = positions[a*3+1], az = positions[a*3+2];
    const bx = positions[b*3], by = positions[b*3+1], bz = positions[b*3+2];
    const cx = positions[c*3], cy = positions[c*3+1], cz = positions[c*3+2];

    const abx = bx - ax, aby = by - ay, abz = bz - az;
    const acx = cx - ax, acy = cy - ay, acz = cz - az;
    const nx = aby * acz - abz * acy;
    const ny = abz * acx - abx * acz;
    const nz = abx * acy - aby * acx;
    if (Math.hypot(nx, ny, nz) < 1e-8) degenerateFaces++;

    signedVolume6 += ax * (by * cz - bz * cy) + ay * (bz * cx - bx * cz) + az * (bx * cy - by * cx);

    for (const [u, v] of [[a, b], [b, c], [c, a]]) {
      const dirKey = `${u}:${v}`;
      directedEdges.set(dirKey, (directedEdges.get(dirKey) || 0) + 1);
      const undirKey = u < v ? `${u}:${v}` : `${v}:${u}`;
      undirectedCounts.set(undirKey, (undirectedCounts.get(undirKey) || 0) + 1);
    }
  }

  let boundaryEdges = 0, nonManifoldEdges = 0, windingConflicts = 0;
  for (const [edge, count] of undirectedCounts.entries()) {
    if (count === 1) boundaryEdges++;
    else if (count > 2) nonManifoldEdges++;
    const [u, v] = edge.split(":");
    if (directedEdges.get(`${u}:${v}`) !== 1 || directedEdges.get(`${v}:${u}`) !== 1) {
      windingConflicts++;
    }
  }
  return {
    isManifold: boundaryEdges === 0 && nonManifoldEdges === 0 && windingConflicts === 0 && degenerateFaces === 0 && signedVolume6 > 0,
    boundaryEdges,
    nonManifoldEdges,
    windingConflicts,
    degenerateFaces,
    signedVolume: signedVolume6 / 6.0
  };
}

Inspecting true relief vs. bump illusions with a 3x Loupe

On compare.baltor.ai/?mode=relief, you can hover the 3x magnification loupe across the vessel silhouette. The unassisted model's cylinder silhouette stays razor-flat because its fluting is only a fragment shader perturbation. The Baltor-verified mesh displaces radial vertices r(theta, v) along continuous harmonic flutes and welds the polar caps cleanly, casting true self-shadowing across the grazing rim light.


Navigation Post Title Direct Links
Previous Post Why Every Baltor Capability Starts as a < 2 KB Contract Card Before Loading Source
Next Post Building Playable Godot 4 and WebGL Games That Survive Revision
Blog Index & Feeds Return to Baltor Engineering Blog Index (8 Posts)