From efffbe2c0a8ff20978d3f5c62732a3eee2a26b95 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Wed, 21 Jan 2026 21:33:15 +0000 Subject: [PATCH] feat: improve gear-case 3D geometry with realistic housing features Added external features to make the gear case look like a real gearbox housing: - Mating flange with 6 bolt bosses and bolt holes - Two shaft bearing housings (cylindrical protrusions) - Vertical structural ribbing - Output shaft housing boss - Drain plug boss Also includes camera position fix (150,150,150) and grid size (200) for mm-scale parts. Co-Authored-By: Claude Opus 4.5 --- .../ford/fiesta/gearbox/parts/gear-case.json | 38 +++++++++++++++++-- .../src/components/PartViewer3D.tsx | 13 ++++++- .../src/components/ThreeCanvas.tsx | 4 +- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/exploded-diagrams/public/packages/automotive/ford/fiesta/gearbox/parts/gear-case.json b/exploded-diagrams/public/packages/automotive/ford/fiesta/gearbox/parts/gear-case.json index e12ab8bcc..7419a8665 100644 --- a/exploded-diagrams/public/packages/automotive/ford/fiesta/gearbox/parts/gear-case.json +++ b/exploded-diagrams/public/packages/automotive/ford/fiesta/gearbox/parts/gear-case.json @@ -43,9 +43,39 @@ { "type": "text", "content": "IB5", "offsetY": 5, "fill": "#333", "fontSize": 12 } ], "geometry3d": [ - { "type": "box", "width": 90, "height": 80, "depth": 120, "fill": "#555" }, - { "type": "cylinder", "r": 30, "height": 82, "rotateX": 90, "offsetZ": -20, "subtract": true }, - { "type": "cylinder", "r": 25, "height": 82, "rotateX": 90, "offsetZ": 20, "subtract": true }, - { "type": "box", "width": 70, "height": 60, "depth": 100, "offsetY": 5, "subtract": true } + { "type": "box", "width": 100, "height": 85, "depth": 130, "fill": "#606070" }, + { "type": "box", "width": 80, "height": 65, "depth": 110, "offsetY": 5, "subtract": true }, + + { "type": "box", "width": 120, "height": 95, "depth": 12, "offsetZ": -65, "fill": "#707080" }, + + { "type": "cylinder", "r": 10, "height": 20, "offsetX": -50, "offsetY": -38, "offsetZ": -65, "fill": "#808090" }, + { "type": "cylinder", "r": 10, "height": 20, "offsetX": 50, "offsetY": -38, "offsetZ": -65, "fill": "#808090" }, + { "type": "cylinder", "r": 10, "height": 20, "offsetX": -50, "offsetY": 38, "offsetZ": -65, "fill": "#808090" }, + { "type": "cylinder", "r": 10, "height": 20, "offsetX": 50, "offsetY": 38, "offsetZ": -65, "fill": "#808090" }, + { "type": "cylinder", "r": 10, "height": 20, "offsetX": 0, "offsetY": -42, "offsetZ": -65, "fill": "#808090" }, + { "type": "cylinder", "r": 10, "height": 20, "offsetX": 0, "offsetY": 42, "offsetZ": -65, "fill": "#808090" }, + + { "type": "cylinder", "r": 4, "height": 25, "offsetX": -50, "offsetY": -38, "offsetZ": -65, "subtract": true }, + { "type": "cylinder", "r": 4, "height": 25, "offsetX": 50, "offsetY": -38, "offsetZ": -65, "subtract": true }, + { "type": "cylinder", "r": 4, "height": 25, "offsetX": -50, "offsetY": 38, "offsetZ": -65, "subtract": true }, + { "type": "cylinder", "r": 4, "height": 25, "offsetX": 50, "offsetY": 38, "offsetZ": -65, "subtract": true }, + { "type": "cylinder", "r": 4, "height": 25, "offsetX": 0, "offsetY": -42, "offsetZ": -65, "subtract": true }, + { "type": "cylinder", "r": 4, "height": 25, "offsetX": 0, "offsetY": 42, "offsetZ": -65, "subtract": true }, + + { "type": "box", "width": 8, "height": 70, "depth": 110, "offsetX": -42, "fill": "#555560" }, + { "type": "box", "width": 8, "height": 70, "depth": 110, "offsetX": 42, "fill": "#555560" }, + { "type": "box", "width": 8, "height": 70, "depth": 110, "offsetX": 0, "fill": "#555560" }, + + { "type": "cylinder", "r": 35, "height": 20, "rotateX": 90, "offsetZ": 55, "fill": "#707080" }, + { "type": "cylinder", "r": 25, "height": 25, "rotateX": 90, "offsetZ": 55, "subtract": true }, + + { "type": "cylinder", "r": 38, "height": 15, "rotateX": 90, "offsetZ": -20, "fill": "#656575" }, + { "type": "cylinder", "r": 30, "height": 90, "rotateX": 90, "offsetZ": -20, "subtract": true }, + + { "type": "cylinder", "r": 32, "height": 15, "rotateX": 90, "offsetZ": 20, "fill": "#656575" }, + { "type": "cylinder", "r": 25, "height": 90, "rotateX": 90, "offsetZ": 20, "subtract": true }, + + { "type": "box", "width": 30, "height": 20, "depth": 25, "offsetX": -55, "offsetY": -30, "fill": "#606070" }, + { "type": "cylinder", "r": 8, "height": 30, "offsetX": -55, "offsetY": -30, "subtract": true } ] } diff --git a/exploded-diagrams/src/components/PartViewer3D.tsx b/exploded-diagrams/src/components/PartViewer3D.tsx index d5d3de5d0..9846b96e8 100644 --- a/exploded-diagrams/src/components/PartViewer3D.tsx +++ b/exploded-diagrams/src/components/PartViewer3D.tsx @@ -19,13 +19,22 @@ interface PartMeshProps { function PartMesh({ part, materials }: PartMeshProps) { const geometry = useMemo(() => { + console.log('PartMesh rendering:', part.id, 'geometry3d:', part.geometry3d) if (part.geometry3d && part.geometry3d.length > 0) { // Convert geometry3d to Three.js BufferGeometry - return geometryToThree(part.geometry3d) + try { + const geom = geometryToThree(part.geometry3d) + console.log('Generated geometry:', geom, 'positions:', geom.attributes.position?.count) + return geom + } catch (err) { + console.error('Failed to convert geometry3d:', err) + return new THREE.BoxGeometry(2, 2, 2) + } } // Fallback to a simple box if no geometry3d present + console.log('No geometry3d, using fallback box') return new THREE.BoxGeometry(2, 2, 2) - }, [part.geometry3d]) + }, [part.geometry3d, part.id]) const materialColor = useMemo(() => { // Try to get color from first geometry3d fill, or material reference, or part material diff --git a/exploded-diagrams/src/components/ThreeCanvas.tsx b/exploded-diagrams/src/components/ThreeCanvas.tsx index 316f99a5d..389cc6c27 100644 --- a/exploded-diagrams/src/components/ThreeCanvas.tsx +++ b/exploded-diagrams/src/components/ThreeCanvas.tsx @@ -11,7 +11,7 @@ export default function ThreeCanvas({ children }: ThreeCanvasProps) { return ( @@ -21,7 +21,7 @@ export default function ThreeCanvas({ children }: ThreeCanvasProps) { {/* Ground plane grid */} - + {/* Camera controls */}