From bbe1d0c02701f8699d305230738fd9c3d5754c51 Mon Sep 17 00:00:00 2001 From: Liam Conner Date: Fri, 26 Dec 2025 19:11:14 -0600 Subject: [PATCH] fix: process each component box as separate ManifoldSolidBrep in STEP export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously all triangles from all component boxes were merged into a single ClosedShell, which violated STEP's requirement that each solid have its own watertight boundary. This caused components to be missing from STEP output. Now each box from scene3d.boxes is processed individually, creating a separate ManifoldSolidBrep for each component with its own ClosedShell. Fixes #6 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- lib/mesh-generation.ts | 66 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/mesh-generation.ts b/lib/mesh-generation.ts index 1df41fe..ddbd40b 100644 --- a/lib/mesh-generation.ts +++ b/lib/mesh-generation.ts @@ -327,46 +327,46 @@ export async function generateComponentMeshes( renderBoardTextures: false, }) - // Extract or generate triangles from component boxes - const allTriangles: GLTFTriangle[] = [] + // Process each box separately to create individual solids for (const box of scene3d.boxes) { + let boxTriangles: GLTFTriangle[] = [] + if (box.mesh && "triangles" in box.mesh) { - allTriangles.push(...box.mesh.triangles) + boxTriangles = box.mesh.triangles } else { // Generate simple box mesh for this component - const boxTriangles = createBoxTriangles(box) - allTriangles.push(...boxTriangles) + boxTriangles = createBoxTriangles(box) } - } - // Create STEP faces from triangles if we have any - if (allTriangles.length > 0) { - // Transform triangles from GLTF XZ plane (Y=up) to STEP XY plane (Z=up) - const transformedTriangles = allTriangles.map((tri) => ({ - vertices: tri.vertices.map((v) => ({ - x: v.x, - y: v.z, // GLTF Z becomes STEP Y - z: v.y, // GLTF Y becomes STEP Z - })), - normal: { - x: tri.normal.x, - y: tri.normal.z, // GLTF Z becomes STEP Y - z: tri.normal.y, // GLTF Y becomes STEP Z - }, - })) - const componentFaces = createStepFacesFromTriangles( - repo, - transformedTriangles as any, - ) + // Create STEP faces from triangles if we have any for this box + if (boxTriangles.length > 0) { + // Transform triangles from GLTF XZ plane (Y=up) to STEP XY plane (Z=up) + const transformedTriangles = boxTriangles.map((tri) => ({ + vertices: tri.vertices.map((v) => ({ + x: v.x, + y: v.z, // GLTF Z becomes STEP Y + z: v.y, // GLTF Y becomes STEP Z + })), + normal: { + x: tri.normal.x, + y: tri.normal.z, // GLTF Z becomes STEP Y + z: tri.normal.y, // GLTF Y becomes STEP Z + }, + })) + const componentFaces = createStepFacesFromTriangles( + repo, + transformedTriangles as any, + ) - // Create closed shell and solid for components - const componentShell = repo.add( - new ClosedShell("", componentFaces as any), - ) - const componentSolid = repo.add( - new ManifoldSolidBrep("Components", componentShell), - ) - solids.push(componentSolid) + // Create closed shell and solid for this component + const componentShell = repo.add( + new ClosedShell("", componentFaces as any), + ) + const componentSolid = repo.add( + new ManifoldSolidBrep(box.label || "Component", componentShell), + ) + solids.push(componentSolid) + } } } catch (error) { console.warn("Failed to generate component mesh:", error)