forgecad 0.9.15 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{AdminPage-CDyGUinA.js → AdminPage-DwYHz72L.js} +1 -1
- package/dist/assets/{BenchmarkPage-DfPMY_-d.js → BenchmarkPage-a9_f-1US.js} +1 -1
- package/dist/assets/{BlogPage-kF0fkdJT.js → BlogPage-DodHpvmf.js} +1 -1
- package/dist/assets/{DocsPage-B954L3YN.js → DocsPage-B5LePEuj.js} +8 -858
- package/dist/assets/{EditorApp-CuDLxKqL.css → EditorApp-BpjZgzk0.css} +148 -0
- package/dist/assets/EditorApp-QXsAISLR.js +16307 -0
- package/dist/assets/{EmbedViewer-C77B-TrF.js → EmbedViewer-DdEHGUMU.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-Cr6fXMDj.js → LandingPageProofDriven-yhhOodbf.js} +2 -2
- package/dist/assets/{LegalPage-Dzklqmmg.js → LegalPage-5RbKRGYK.js} +1 -1
- package/dist/assets/{PricingPage-zWXkvlwl.js → PricingPage-E3Rma7aV.js} +1 -1
- package/dist/assets/{SettingsPage-Bz0of4KQ.js → SettingsPage-BJZcM97j.js} +1 -1
- package/dist/assets/{app-D3kDkggg.js → app-DSYrDg0V.js} +1846 -352
- package/dist/assets/cli/{render-DSY3mMQa.js → render-ZMHR9HkV.js} +161 -70
- package/dist/assets/{constructionHistoryWorker-gpDo-uH2.js → constructionHistoryWorker-AwMMWSxg.js} +1104 -349
- package/dist/assets/{evalWorker-CU0Ke6DP.js → evalWorker-DbNs7Dkp.js} +5155 -3772
- package/dist/assets/{inspectWorker-COyp8XXA.js → inspectWorker-CZsCFtQT.js} +1415 -439
- package/dist/assets/{targets-B9sGB5nB.js → jointPose-DO6mnXn_.js} +71 -3
- package/dist/assets/{manifold-DNkrUWpA.js → manifold-BGlQBBH9.js} +1 -1
- package/dist/assets/{manifold-BRI5prcH.js → manifold-BU-tJwQh.js} +1 -1
- package/dist/assets/{manifold-C-3h2M7p.js → manifold-fy2MV7K1.js} +2 -2
- package/dist/assets/{reportWorker-CdBz5bNg.js → reportWorker-DO6hcQbh.js} +8474 -4549
- package/dist/assets/{scalar-sampling-budget-wJF98aY9.js → scalar-sampling-budget-o90NSNmF.js} +5347 -3906
- package/dist/assets/{scanProxyWorker-B-9VbLIs.js → scanProxyWorker-2GtDLk-R.js} +19 -6
- package/dist/assets/{javascript-1kQXfVaz.js → typescript-DBQ6RN5l.js} +874 -22
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +3 -3
- package/dist/docs-raw/AI/usage.md +3 -1
- package/dist/docs-raw/CLI.md +65 -239
- package/dist/docs-raw/README.md +6 -0
- package/dist/docs-raw/component-model.md +17 -150
- package/dist/docs-raw/generated/assembly.md +159 -520
- package/dist/docs-raw/generated/concepts.md +245 -3491
- package/dist/docs-raw/generated/core.md +277 -1251
- package/dist/docs-raw/generated/curves.md +387 -1608
- package/dist/docs-raw/generated/legacy.md +162 -0
- package/dist/docs-raw/generated/lib.md +238 -112
- package/dist/docs-raw/generated/output.md +51 -76
- package/dist/docs-raw/generated/runtime-names.md +30 -22
- package/dist/docs-raw/generated/sdf.md +68 -284
- package/dist/docs-raw/generated/sheet-metal.md +68 -335
- package/dist/docs-raw/generated/sketch.md +240 -1161
- package/dist/docs-raw/generated/viewport.md +75 -316
- package/dist/docs-raw/generated/wood.md +21 -49
- package/dist/docs-raw/guides/coordinate-system.md +4 -42
- package/dist/docs-raw/guides/inspection-bundles.md +44 -442
- package/dist/docs-raw/guides/joint-design.md +18 -79
- package/dist/docs-raw/guides/positioning.md +21 -143
- package/dist/docs-raw/guides/scene-presentation.md +89 -0
- package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +25 -111
- package/dist/docs-raw/skills/forgecad-blockout-model.md +20 -117
- package/dist/docs-raw/skills/forgecad-component-model.md +23 -107
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +47 -155
- package/dist/docs-raw/skills/forgecad-image-replicator.md +26 -143
- package/dist/docs-raw/skills/forgecad-lld.md +19 -113
- package/dist/docs-raw/skills/forgecad-make-a-model.md +113 -532
- package/dist/docs-raw/skills/forgecad-model-grader.md +38 -108
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +24 -211
- package/dist/docs-raw/skills/forgecad-project.md +13 -129
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +42 -134
- package/dist/docs-raw/skills/forgecad-render-inspect.md +27 -174
- package/dist/docs-raw/skills/forgecad-visual-spec.md +32 -112
- package/dist/docs-raw/skills/forgecad.md +19 -18
- package/dist/docs-raw/skills/index.md +2 -0
- package/dist/docs-raw/welcome.md +4 -2
- package/dist/index.html +1 -1
- package/dist/llms.txt +1 -2
- package/dist/sitemap.xml +13 -13
- package/dist-cli/{check-compiler-SDX5QIXI.js → check-compiler-JTVBITCR.js} +1 -1
- package/dist-cli/{check-query-propagation-EAYEFT77.js → check-query-propagation-3FFLSMVN.js} +1 -1
- package/dist-cli/{chunk-N4O47JLF.js → chunk-OAN5T4XD.js} +5722 -4287
- package/dist-cli/forgecad.js +2195 -656
- package/dist-skill/CONTEXT.md +1778 -7912
- package/dist-skill/SKILL.md +15 -15
- package/dist-skill/docs/API/core/concepts.md +27 -157
- package/dist-skill/docs/CLI.md +65 -239
- package/dist-skill/docs/generated/assembly.md +160 -493
- package/dist-skill/docs/generated/core.md +277 -1251
- package/dist-skill/docs/generated/curves.md +387 -1609
- package/dist-skill/docs/generated/lib.md +238 -112
- package/dist-skill/docs/generated/output.md +51 -76
- package/dist-skill/docs/generated/runtime-names.md +16 -22
- package/dist-skill/docs/generated/sdf.md +68 -284
- package/dist-skill/docs/generated/sheet-metal.md +68 -335
- package/dist-skill/docs/generated/sketch.md +240 -1160
- package/dist-skill/docs/generated/viewport.md +75 -223
- package/dist-skill/docs/generated/wood.md +21 -49
- package/dist-skill/docs/guides/coordinate-system.md +4 -42
- package/dist-skill/docs/guides/inspection-bundles.md +44 -442
- package/dist-skill/docs/guides/joint-design.md +18 -79
- package/dist-skill/docs/guides/positioning.md +21 -143
- package/dist-skill/docs/guides/scene-presentation.md +89 -0
- package/dist-skill/docs/guides/surface-members.md +26 -0
- package/dist-skill/library/forgecad-3d-reconstruction/SKILL.md +23 -111
- package/dist-skill/library/forgecad-blockout-model/SKILL.md +18 -117
- package/dist-skill/library/forgecad-component-model/SKILL.md +21 -107
- package/dist-skill/library/forgecad-high-level-spec/SKILL.md +45 -155
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +24 -143
- package/dist-skill/library/forgecad-lld/SKILL.md +17 -113
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +111 -532
- package/dist-skill/library/forgecad-model-grader/SKILL.md +36 -108
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +35 -224
- package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +43 -271
- package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +30 -99
- package/dist-skill/library/forgecad-project/SKILL.md +13 -131
- package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +29 -123
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +25 -174
- package/dist-skill/library/forgecad-visual-spec/SKILL.md +30 -111
- package/dist-skill/website/skills/forgecad-3d-reconstruction.md +58 -0
- package/dist-skill/website/skills/forgecad-blockout-model.md +49 -0
- package/dist-skill/website/skills/forgecad-component-model.md +53 -0
- package/dist-skill/website/skills/forgecad-high-level-spec.md +101 -0
- package/dist-skill/website/skills/forgecad-image-replicator.md +63 -0
- package/dist-skill/website/skills/forgecad-lld.md +41 -0
- package/dist-skill/website/skills/forgecad-make-a-model.md +186 -0
- package/dist-skill/website/skills/forgecad-model-grader.md +82 -0
- package/dist-skill/website/skills/forgecad-prepare-prompt.md +63 -0
- package/dist-skill/website/skills/forgecad-project.md +26 -0
- package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +60 -0
- package/dist-skill/website/skills/forgecad-render-inspect.md +80 -0
- package/dist-skill/website/skills/forgecad-visual-spec.md +71 -0
- package/dist-skill/website/skills/forgecad.md +122 -0
- package/dist-skill/website/skills/index.md +26 -0
- package/examples/api/comparison-imported-sphere-candidate.forge.js +1 -1
- package/examples/api/conformal-product-ribbon.forge.js +1 -1
- package/examples/api/exact-sheet-shell-assembly.forge.js +1 -1
- package/examples/api/extrude-options.forge.js +4 -2
- package/examples/api/field-loft-drive-tip.forge.js +40 -0
- package/examples/api/guided-loft-olive-oil-bottle.forge.js +1 -1
- package/examples/api/helix-basics.forge.js +2 -2
- package/examples/api/highlight-debug.forge.js +10 -10
- package/examples/api/mesh-import-slats.forge.js +1 -1
- package/examples/api/real-product-curves.forge.js +1 -1
- package/examples/api/route3d-elbow.forge.js +3 -0
- package/examples/api/sculpt-box-circle-booleans.forge.js +1 -1
- package/examples/api/sdf-shapes.forge.js +2 -5
- package/examples/api/sketch-rounding-strategies.forge.js +6 -6
- package/examples/api/surface-member-bottle-cage.forge.js +3 -3
- package/examples/api/surface-member-conformal-product-ribbon.forge.js +3 -3
- package/examples/api/surface-member-razor-inlay.forge.js +1 -1
- package/examples/api/variable-sweep-test.forge.js +4 -2
- package/examples/mechanical/airplane-propeller.forge.js +74 -39
- package/examples/nurbs-surface.forge.js +1 -1
- package/examples/products/iphone.forge.js +1 -1
- package/package.json +4 -1
- package/dist/assets/EditorApp-Beb-IZ0y.js +0 -14014
- package/dist/docs-raw/guides/geometry-conventions.md +0 -52
- package/dist/docs-raw/guides/modeling-recipes.md +0 -78
- package/dist-skill/docs/guides/geometry-conventions.md +0 -52
- package/dist-skill/docs/guides/modeling-recipes.md +0 -78
- package/dist-skill/library/forgecad-visual-spec/references/prompt-template.md +0 -79
- package/examples/api/bolted-service-cover.forge.js +0 -17
- package/examples/api/cable-gland-anchor.forge.js +0 -14
- package/examples/api/captured-cartridge-guide.forge.js +0 -14
- package/examples/api/captured-linear-slide.forge.js +0 -13
- package/examples/api/clevis-pin-joint.forge.js +0 -13
- package/examples/api/datum-enclosure.forge.js +0 -16
- package/examples/api/hose-barb-port.forge.js +0 -14
- package/examples/api/knuckled-hinge-assembly.forge.js +0 -15
- package/examples/api/living-hinge-cover.forge.js +0 -14
- package/examples/api/pcb-terminal-block.forge.js +0 -22
- package/examples/api/pinned-lever-pivot-stack.forge.js +0 -14
- package/examples/api/retained-shaft-knob-stack.forge.js +0 -15
- package/examples/api/routed-tube-clip.forge.js +0 -15
- package/examples/api/seated-bearing-stack.forge.js +0 -30
- package/examples/api/snap-latch-cover.forge.js +0 -14
- package/examples/api/thumb-screw-clamp.forge.js +0 -15
|
@@ -10,591 +10,170 @@ Create new ForgeCAD models in the user's active ForgeCAD project.
|
|
|
10
10
|
|
|
11
11
|
## Default Output Standard
|
|
12
12
|
|
|
13
|
-
Unless the user
|
|
13
|
+
Unless the user asks otherwise, the output is a **manufacture-realistic prototype**: a model someone could fabricate, buy parts for, assemble, inspect, and iterate in a real shop — not a concept sketch, not a universal 3D-printing exercise, not a claim of certified production readiness.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
- Include prototype-real features: wall thickness, fastener stacks, bosses, ribs, flanges, bends, seats, bushings, gaskets, cable exits, service access, toleranced clearances, and believable purchased parts.
|
|
19
|
-
- Use production cues only when they help prototype realism. Do not invent expensive production tooling details, certification claims, or safety ratings unless the user asked for that level.
|
|
20
|
-
- If the user asks for `production-realistic`, push toward manufacturing DFM and production-intent materials. If they ask for `printable`, make the selected printed parts honest. If they ask for `visual-CAD`, keep it clearly visual rather than pretending it is build-ready.
|
|
21
|
-
- Checking for collisions and removing unexpected overlaps is part of the normal definition of done. The expected final collision count is zero except in rare, explicit cases such as welded, fused, overmolded, cast-in, potted, or bonded matter; those exceptions must be declared with `verify.intentionalOverlap(...)` or isolated with focused inspection so the remaining collision report is meaningful.
|
|
15
|
+
- Include prototype-real features: wall thickness, fastener stacks, bosses, ribs, flanges, seats, gaskets, cable exits, service access, toleranced clearances, believable purchased parts. No invented tooling details, certifications, or safety ratings unless asked.
|
|
16
|
+
- Modifiers shift the standard: `blockout` → rough massing; `production-realistic` → DFM and production-intent materials; `printable` → make the selected printed parts honest; `visual-CAD` → clearly visual, not pretending build-ready.
|
|
17
|
+
- Zero unexpected final collisions is part of the definition of done (see Collision Policy).
|
|
22
18
|
|
|
23
19
|
## File Placement
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
New `.forge.js` files go under date-based directories (today's date) in the user's current ForgeCAD project or a clearly named local folder:
|
|
26
22
|
|
|
27
23
|
```
|
|
28
|
-
YYYY/MM/DD/file.forge.js
|
|
29
|
-
YYYY/MM/DD/folder/main.forge.js
|
|
30
|
-
YYYY/MM/DD/folder/parts/*.forge.js — standalone/importable
|
|
31
|
-
YYYY/MM/DD/folder/lib/*.js
|
|
24
|
+
YYYY/MM/DD/file.forge.js — single-file model
|
|
25
|
+
YYYY/MM/DD/folder/main.forge.js — multi-file entry point (always main.forge.js)
|
|
26
|
+
YYYY/MM/DD/folder/parts/*.forge.js — standalone/importable parts
|
|
27
|
+
YYYY/MM/DD/folder/lib/*.js — pure helpers/constants, no geometry
|
|
32
28
|
```
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- Use kebab-case for file and folder names: `parametric-lego.forge.js`
|
|
39
|
-
- Use descriptive names that communicate what the model is
|
|
40
|
-
- For any multi-file project, name the runnable ForgeCAD entry point `main.forge.js`
|
|
41
|
-
- Put renderable/importable parts and sub-assemblies in separate `.forge.js` files when splitting is justified; each should be standalone-runnable and importable with `require('./parts/name.forge.js', params)`.
|
|
42
|
-
- Use plain `.js` files only for pure constants, math helpers, tables, or formatting code that does not construct and return ForgeCAD geometry.
|
|
43
|
-
- Do not create multiple `.forge.js` files merely for organization; split only for reusable parts, large self-contained components, or independent sub-assemblies.
|
|
30
|
+
- Kebab-case descriptive names (`parametric-lego.forge.js`). Each part file must run standalone and import via `require('./parts/name.forge.js', params)`.
|
|
31
|
+
- Plain `.js` only for constants, math, tables, formatting — never geometry.
|
|
32
|
+
- Split files only for reusable parts or independent sub-assemblies, never for organization.
|
|
44
33
|
|
|
45
34
|
## Workflow
|
|
46
35
|
|
|
47
|
-
1. Load the
|
|
48
|
-
2.
|
|
49
|
-
3.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- Use clear variable names
|
|
55
|
-
- Build any implied internal structure as real geometry, even when it will be hidden in the final view
|
|
56
|
-
- Build the complete physical artifact first: closed shells, installed covers, real part positions, and all meaningful internal structure in place
|
|
57
|
-
- Make final mating geometry physically plausible: parts may touch, clear each other, or be boolean-joined, but should not unintentionally pass through each other
|
|
58
|
-
- Model the physical artifact, not an educational diagram: no explanatory arrows, floating labels, section labels, legends, or text plaques unless the user explicitly requested a presentation/teaching view
|
|
59
|
-
- Do not make the default returned model a cutaway, sectioned shell, permanently exploded assembly, or hidden-parts teaching view. ForgeCAD gives the user viewer and inspection tools for slicing, exploding, hiding, and looking inside after the real CAD exists.
|
|
60
|
-
- Return the final geometry (single shape, array, or named objects array)
|
|
61
|
-
- Treat `fillet(shape, r)` and `chamfer(shape, r)` as experimental edge treatments: Manifold can produce incorrect results and OCCT can be very slow. Prefer simpler primitive profiles, lower segment counts, targeted edge selectors, and inspection before relying on the result.
|
|
62
|
-
4. Validate — run `forgecad run <file>` to check for errors. For multi-file projects, always validate `main.forge.js`.
|
|
63
|
-
5. Verify geometry — render a multi-angle visual evidence set before final delivery: whole-model context plus agent-chosen orthographic, oblique, underside, or hidden-object views that expose the relevant components and interfaces. Choose camera directions from the model's shape and likely failure modes, not from a fixed recipe. Use those views to look for internals that are accidentally visible, parts that visibly do not fit, floating details, blocked access, missing seats, and unexpected interference. Run `forgecad inspect physical components` when the model has multiple returned objects or visible attachments, run `forgecad debug assembly --fail-on warning` when the script uses `assembly()`, run `forgecad inspect mechanical-integrity <project-or-file> --collisions` before sharing generated mechanical work, and run the targeted `forgecad inspect <family> <mode>` commands that match the task (see Final Acceptance Gate and Render-Verify Loop below). For multi-file projects, render and inspect `main.forge.js`. Collision findings are model work, not FYI: remove unexpected overlaps before delivery.
|
|
64
|
-
6. Iterate from visual and inspection feedback — treat every render and inspection bundle as model evidence, not a checkbox. Read the normal PNGs, manifest, and evidence PNGs; convert each unexpected collision, thin region, missing section detail, wrong component count, floating body, distance gap, confusing object-color result, accidentally exposed internal structure, bad fit, or visually unsupported interface into a concrete model edit; then rerun the same targeted evidence pass until the result matches the intended physical component graph.
|
|
65
|
-
|
|
66
|
-
## Manufacturing Process Is Not Assumed
|
|
67
|
-
|
|
68
|
-
Do not interpret every ForgeCAD model as a printable object.
|
|
69
|
-
Choose the manufacturing/process cues that fit the artifact unless the user explicitly asked for a specific process. A manufacture-realistic prototype can be CNC-machined, bent sheet, tube-and-plate, wood/composite, molded-look low-volume, printed, or hybrid; the right answer depends on the load path and operating story.
|
|
70
|
-
|
|
71
|
-
- For rideable products such as scooters, bikes, skateboards, carts, or mobility-adjacent devices, use realistic metal/composite/wood structural members, purchased wheels/bearings/axles/brakes/grips, and standard hardware unless the user asked for a printable toy/model.
|
|
72
|
-
- For furniture and load-bearing structures, consider wood, sheet goods, tube, metal brackets, conventional joinery, and printed parts only where they are honest secondary components.
|
|
73
|
-
- For enclosures, choose injection-molded, sheet-metal, CNC, thermoformed, printed, or hybrid cues based on quantity, ruggedness, serviceability, and the brief.
|
|
74
|
-
- For fixtures and tooling, choose machined, laser-cut, welded, printed, or hybrid construction based on load, repeatability, and shop realism.
|
|
75
|
-
- Use printing-specific features such as slicer clearances, support strategy, layer-oriented ribs, and heat-set inserts only when the selected process includes printed parts.
|
|
76
|
-
|
|
77
|
-
## Physical Artifact, Not Teaching Diagram
|
|
78
|
-
|
|
79
|
-
The deliverable is the object someone would build, assemble, inspect, or export. It is not an educational display model unless the user explicitly asks for one.
|
|
36
|
+
1. **Load the `forgecad` skill** — read at least the Core API reference. Moving parts: also the assembly group and joint-design guide. Mating parts: the positioning guide; default to connectors + `matchTo()`.
|
|
37
|
+
2. `mkdir -p YYYY/MM/DD/[folder]`.
|
|
38
|
+
3. Moving parts: prove the rig first (Kinematics-First below).
|
|
39
|
+
4. Write the model — `param()`/`Param.bool()` for tunable dimensions; pick the manufacturing process before styling; build real internals; follow the contracts below.
|
|
40
|
+
5. Validate — `forgecad run <file>` (`main.forge.js` for multi-file).
|
|
41
|
+
6. Run the Final Acceptance Gate and Manufacturing Outputs checks below on `main.forge.js`.
|
|
42
|
+
7. Iterate — convert every render/inspect finding into a model edit and rerun the same targeted evidence until reality matches the intended component graph.
|
|
80
43
|
|
|
81
|
-
|
|
82
|
-
- Do not use in-model text to make a vague object understandable. If the geometry needs labels to be understood, make the geometry more physically specific instead.
|
|
83
|
-
- Explain part roles through named return objects, clear variable names, comments, BOM entries, docs, and inspection results.
|
|
84
|
-
- Product markings are allowed only when they would exist on the real artifact: serial plates, connector labels, keyboard legends, gauge ticks, warning marks, alignment marks, service arrows, scale marks, branding, or molded icons.
|
|
85
|
-
- Keep real markings sparse and process-appropriate. Prefer simple recessed/raised marks or icons over heavy font geometry, especially on exact/OCCT workflows.
|
|
86
|
-
- If a temporary review view needs annotations, use `Viewport.label()` or a separate debug/presentation mode, not final exported geometry.
|
|
44
|
+
## Process, Style, and Variants
|
|
87
45
|
|
|
88
|
-
|
|
46
|
+
**Manufacturing process is a choice, not an assumption.** Never treat every model as printable. Pick process cues from the load path and operating story: machined, bent sheet, tube-and-plate, wood/composite, molded-look, printed, or hybrid purchased-hardware construction (rideables: metal/composite structure + purchased wheels/bearings; furniture: real joinery). Print-specific features (slicer clearances, heat-set inserts, layer-oriented ribs) only when the process includes printed parts.
|
|
89
47
|
|
|
90
|
-
|
|
48
|
+
**Visual style: expensive and credible, not generically colorful.** Restrained material-driven palette (ivory, charcoal, satin black, brushed aluminum, brass, muted burgundy/green/navy, smoked polymer, natural wood); match color to material/process so metal, polymer, rubber, PCB, and wood read differently. Bright color only as small accents (controls, seals, indicators). Keep seams, fasteners, gaskets, and purchased parts legible.
|
|
91
49
|
|
|
92
|
-
|
|
93
|
-
- Use bright colors sparingly as small accents for controls, seals, indicators, warnings, or brand-neutral identity lines.
|
|
94
|
-
- Match color to material/process: anodized or powder-coated metal, molded or dyed polymer, rubber/silicone, glass/acrylic, PCB/FR4, wood grain, leather/fabric, and standard hardware should each read differently.
|
|
95
|
-
- Avoid one-note rainbow/neon palettes, random saturated part colors, or color groups that make a serious artifact feel like a toy unless the brief asks for that.
|
|
96
|
-
- If the object normally has user-facing markings, include only the markings that belong on the real artifact: keyboard legends, button labels, gauge ticks, icons, connector labels, alignment marks, service arrows, and scale markings. Do not leave expected production markings blank, but do not add explanatory labels just to teach the model.
|
|
97
|
-
- Use color to clarify part boundaries and serviceability without hiding the engineering stack: seams, fasteners, gaskets, inserts, ports, and purchased components should remain legible.
|
|
50
|
+
**Form is part of credibility.** Real products carry deliberate edge treatment — chamfered or rounded profiles where hands, seals, or tooling meet the part, draft on molded faces, consistent proportions and design language across parts. A knife-sharp box reads as a blockout, not a product. Get the rounding from profile-level geometry (rounded sketch corners, chamfered profiles) per the fillet caveat below.
|
|
98
51
|
|
|
99
|
-
|
|
52
|
+
**Variants are parameter-selected.** Sizes/styles/revisions go behind one choice parameter (`Variant`, `Preset`); return only the selected variant. Comparison lineups only behind an explicit debug parameter so they can never pollute collision findings.
|
|
100
53
|
|
|
101
|
-
|
|
54
|
+
## Physical Artifact, Not Teaching Diagram
|
|
102
55
|
|
|
103
|
-
|
|
56
|
+
Deliver the real closed artifact — covers installed, parts in assembled positions. The `forgecad` skill carries the no-labels/no-cutaway rule (no explanatory labels, arrows, or legends in production geometry; never a cutaway, sectioned, or exploded default); it binds here. Markings only when the real artifact has them (serial plates, gauge ticks, molded icons) — sparse, process-appropriate. Explain roles via named return objects and `verify.*`; review annotations go in `Viewport.label()` or a debug mode, never exported geometry.
|
|
104
57
|
|
|
105
|
-
|
|
58
|
+
**Internal geometry is part of the model.** If the real artifact has internals, model them as real geometry even when hidden: cavities, ribs, bosses, screw holes, bearing seats, electronics/battery volumes, wire channels, mechanism clearances and stops. Verify hidden structure with exploration tools — alternate views, `inspect sections`, `--hide`, transparent shells, named ghosts — never by mutilating the returned model.
|
|
106
59
|
|
|
107
|
-
|
|
60
|
+
## Kinematics-First for Moving Parts
|
|
108
61
|
|
|
109
|
-
|
|
62
|
+
For any mechanism (linkage, hinge, slider, suspension, gripper, drawer), the rig is the source of truth: build and prove the motion structure first, then attach geometry — never retrofit motion onto finished shells.
|
|
110
63
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
- Mechanism clearances, travel envelopes, stops, guides, rails, hinges, gear spaces, and service access
|
|
115
|
-
- Process-specific features such as bends, tubes, sheet-metal flanges, machined bosses, cast ribs, molded draft, weld tabs, laser-cut slots, or print-oriented ribs where appropriate
|
|
64
|
+
- Pick the rig shape before geometry: point-link graphs for closed-loop skeletons with distance/angle constraints; frames and connector joints when part orientation matters (API roster in the assembly docs).
|
|
65
|
+
- Name every degree of freedom; encode limits/defaults at rig level. Mirrored revolute axes need an explicit sign mapping — equal joint values do not automatically mirror poses.
|
|
66
|
+
- Attach proxy geometry only (pivot markers, bars, slider blocks, wheel discs). Run the rig at rest, mid-travel, both limits, and mirrored/coupled poses until the solver, controls, connector alignment, and `verify.*` checks all pass:
|
|
116
67
|
|
|
117
|
-
|
|
68
|
+
```bash
|
|
69
|
+
forgecad run model.forge.js --joint "theta=45"
|
|
70
|
+
forgecad render 3d model.forge.js /tmp/theta-45.png --joint "theta=45" --camera iso
|
|
71
|
+
```
|
|
118
72
|
|
|
119
|
-
|
|
73
|
+
Use real joint names; repeat `--joint` per control. A pose that fails to solve, clamps unexpectedly, breaks a connector check, or adds a collision means the rig is not ready for final geometry.
|
|
74
|
+
- Only then attach manufacture-real geometry to the solved links, frames, and connectors — never via a final `rotate()` that makes one pose look assembled.
|
|
75
|
+
- Return the unsolved `Assembly` so Motion controls re-run the real solve. Never bake a posed `SolvedAssembly` to make one pose look right.
|
|
76
|
+
- Encode pose checks in-script with `verify.*`: convergence, connector origins coinciding, link lengths holding, end effectors reaching targets, running clearances positive.
|
|
120
77
|
|
|
121
78
|
## Mechanical Assembly Contract
|
|
122
79
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- For bespoke fixed assemblies that do not match an existing `lib.*` helper, start from `examples/api/static-assembly-connectors.forge.js`: build each part in local coordinates, pick one root part, place every other touching part with `matchTo()`, and verify the mate with `verify.connectorDistance(...)`. Do not use final `translate()` calls as assembly contracts.
|
|
126
|
-
- If you use `assembly().addPart()`, do not treat `addFixed()`, `addRevolute()`, or `addPrismatic()` with a manual `frame: Transform.identity().translate(...)` as a physical contract. Manual joint frames are acceptable only as a temporary scaffold. Before delivery, convert mating interfaces to connectors with `connect()` / `match()` where the interfaces physically meet, or prove the manual joint with `forgecad debug assembly --fail-on warning` and documented geometry.
|
|
127
|
-
- A named assembly part should not contain unintentional disconnected bodies. If a "cover plate" contains floating pull tabs, loose screw heads, or a separate gasket, either boolean-join the manufactured features, model the fasteners/seals as separate named parts, or provide the receiving holes/lands that explain the separation.
|
|
128
|
-
- Screws are not decoration. A screw needs a clearance/counterbore in the cover, a receiving threaded hole/boss or through stack in the parent, enough material around both, and aligned axes from one shared bolt pattern.
|
|
129
|
-
- Handles and levers need a load path. Model the hub-to-arm connection, pivot pin/bore, thrust washers or shoulders, stops/detents where relevant, and the connected follower/contact surface. A handle tangent to a hub is a failed mechanism.
|
|
130
|
-
- Covers, doors, cartridges, and service panels need seats. Model ledges, gasket grooves, bosses, snap hooks, tabs, or hinge barrels, then show how the removable part is retained.
|
|
131
|
-
- Cables, wires, and tubes need receiving geometry. Model a gland, grommet, clamp, socket, ferrule, routed channel, or hose barb; do not let a cylinder end in open space.
|
|
132
|
-
- Purchased loose parts may remain separate bodies, but they should be named as purchased hardware or consumables and should sit in believable sockets, bores, races, guides, or fastener stacks.
|
|
133
|
-
- Encode interface intent with `verify.*`, not only comments. Use `verify.clearanceBetween("cover is seated on gasket", cover, gasket, -0.01, 0.05)` for contact/seated fits and clearance bands, `verify.minClearance(...)` or `verify.notColliding(...)` for keep-out/running gaps, and `verify.connectorDistance(...)` for connector-authored mates. Part counts and generic dimensions are useful supporting checks, but they do not prove an interface by themselves.
|
|
134
|
-
|
|
135
|
-
For ordinary removable covers, prefer `lib.boltedServiceCover(...)` before hand-placing plates, tabs, screw heads, gaskets, and holes. It creates the parent ledge, gasket, cover plate with fused pull tabs, shared bolt pattern, and installed screws as one mechanically accountable interface.
|
|
136
|
-
|
|
137
|
-
For electronics boxes, backplates, service-stack housings, and camera/monitor enclosures, prefer `lib.datumEnclosureAssembly(...)` before independently placing panels, ribs, bosses, ports, covers, and screws. It creates the tray, ledges, standoffs, ribs, service port, gasket, cover, and screws from one shared datum system.
|
|
138
|
-
|
|
139
|
-
For PCB-mounted terminal blocks, thermostat backplates, control boards, and wire-entry electronics panels, prefer `lib.pcbTerminalBlockAssembly(...)` before placing a loose green block near a board or cover. It creates the backplate, fused standoffs, PCB mounting screws, PCB pin holes, terminal pins, and seated purchased terminal block from one shared datum system.
|
|
140
|
-
|
|
141
|
-
For snap-retained covers, cartridges, small clasps, and housings, prefer `lib.snapLatchCoverAssembly(...)` before drawing decorative snap tabs. It creates latch windows, underside catch lands, fused snap hooks, barbs, and clearance checks so the cover is retained by real geometry.
|
|
142
|
-
|
|
143
|
-
For ordinary pinned handles, cam levers, release levers, and latch arms, prefer `lib.pinnedLeverAssembly(...)` before hand-placing a hub, arm, washers, and pin. It creates a fused lever body, aligned pivot bore, retained pin, thrust washers, support land, and low stop land as one mechanically accountable pivot stack.
|
|
144
|
-
|
|
145
|
-
For trunnions, side knobs, adjustable pivots, and clamp shafts, prefer `lib.retainedShaftAssembly(...)` before hand-placing rods, washers, and knobs. It creates bored support cheeks, a through shaft, thrust washers, knobs, retaining heads, and shared bore dimensions as one mechanically accountable stack.
|
|
146
|
-
|
|
147
|
-
For thumb screws, desk clamps, vise screws, capo pressure screws, and small fixture hold-downs, prefer `lib.thumbScrewClampAssembly(...)` before hand-placing a knob, screw cylinder, pressure pad, and bracket jaw. It creates the C-frame, threaded boss/bore, captive pressure pad, hand knob, and seated workpiece contact from one shared datum system.
|
|
148
|
-
|
|
149
|
-
For drawer slides, quick-release plates, and guided linear carriages, prefer `lib.capturedLinearSlide(...)` before hand-placing rails and a block. It creates a U-channel rail with return lips, end stops, a captured carriage, and explicit travel/clearance dimensions.
|
|
80
|
+
A mechanical script is not done when it merely looks assembled. Every visible piece needs a physical reason to be where it is: fused material, contact faces, a screw stack, a pin in a bore, a tab in a slot, a gasket on a land, a bearing in a seat, a cable in a channel, or a named intentional ghost.
|
|
150
81
|
|
|
151
|
-
|
|
82
|
+
- Bespoke fixed assemblies: build each part in local coordinates, pick one root, place every touching part with `matchTo()`, verify each mate with `verify.connectorDistance`. Final `translate()` calls are not assembly contracts.
|
|
83
|
+
- Manual joint frames (`addFixed`/`addRevolute`/`addPrismatic` with a hand-built `frame:`) are scaffolding, not contracts. Before delivery, convert mating interfaces to connectors with `connect()`/`match()`, or prove the manual joint with `forgecad debug assembly --fail-on warning` and documented geometry.
|
|
84
|
+
- A named part must not contain unintentional disconnected bodies: boolean-join manufactured features, model fasteners/seals as separate named parts, or add the receiving holes/lands that explain the separation.
|
|
85
|
+
- Screws are not decoration: clearance/counterbore in the cover, receiving boss or through stack in the parent, material around both, axes aligned from one shared bolt pattern.
|
|
86
|
+
- Handles and levers need a load path: hub-to-arm neck, pivot pin/bore, thrust shoulders, stops/detents, and the connected follower. A handle tangent to a hub is a failed mechanism.
|
|
87
|
+
- Covers, doors, cartridges, service panels need seats: ledges, gasket grooves, bosses, snap hooks, tabs, or hinge barrels — plus a visible retention story.
|
|
88
|
+
- Cables, wires, tubes need receiving geometry: gland, grommet, clamp, socket, ferrule, routed channel, or hose barb. Never let a cylinder end in open space.
|
|
89
|
+
- Purchased loose parts may stay separate bodies — name them as purchased hardware/consumables and seat them in believable sockets, bores, races, or fastener stacks.
|
|
90
|
+
- Encode interface intent with `verify.*`, not comments: `verify.clearanceBetween` for seated fits and clearance bands, `verify.minClearance`/`verify.notColliding` for keep-out and running gaps, `verify.connectorDistance` for connector mates. Part counts and generic dimensions never prove an interface.
|
|
91
|
+
- No canned finished-object helpers for project-specific assemblies. Reusable vocabulary is primitives, cutters, patterns, and mechanical contracts (`lib.fastenerSet()`, `lib.boltPattern()`, real bores and pockets, connectors + `matchTo()`) — not finished backplates, brackets, or hinge leaves.
|
|
152
92
|
|
|
153
|
-
|
|
93
|
+
Treat `fillet()`/`chamfer()` as experimental (Manifold can be incorrect, OCCT slow); prefer profile-level rounding and inspect before relying on the result.
|
|
154
94
|
|
|
155
|
-
|
|
95
|
+
## Imported Parts (User-Supplied 3D Files)
|
|
156
96
|
|
|
157
|
-
|
|
97
|
+
When the user supplies mesh or CAD files to design around (a motor, an off-the-shelf housing, a scanned part), the import IS a component of the assembly — keep it, don't rebuild it parametrically (rebuilding is `forgecad-3d-reconstruction`, a different request).
|
|
158
98
|
|
|
159
|
-
|
|
99
|
+
- Wrap each import in its own part file: `Import.mesh()` for STL/OBJ/3MF, `Import.step()` for STEP (OCCT backend), normalize scale and orientation, recenter to a sane local origin, then treat it exactly like a purchased part — connectors at its real mating features, positioned by the assembly via `matchTo()`.
|
|
100
|
+
- Never trust units. Verify against a known dimension before mating anything: bbox via `forgecad run --details`, or `inspect section --ray` across a bore or face pair. For 3MF, account for every build item printed by `forgecad run` before flattening.
|
|
101
|
+
- Derive mating geometry by measurement, not eyeball: pull bore positions, diameters, and face offsets from sections, then hold them with `verify.clearanceBetween`/`verify.connectorDistance` against the import like any other body. Collision Policy applies to imports too.
|
|
102
|
+
- The import is a purchased/fixed line item; the manufactured deliverables are the ForgeCAD-authored parts around it. Remodel an imported feature only where a boolean against the mesh is unreliable — and say so.
|
|
160
103
|
|
|
161
|
-
|
|
104
|
+
## Collision Policy
|
|
162
105
|
|
|
163
|
-
|
|
106
|
+
Each returned part is real matter. Expected final collision count: **zero**.
|
|
164
107
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
Treat each returned part as real matter occupying space. In the final build, separate parts should not intersect unless the intersection is the actual manufacturing intent, such as a welded/fused region, an overmolded insert, or a boolean-unioned solid that is no longer a separate part.
|
|
170
|
-
|
|
171
|
-
Do not use final interpenetration as a placement shortcut. For joints and interfaces, model the contact, clearance, or connector honestly: pins in holes, shafts in bearing seats, tabs in slots, hinges with knuckle clearance, screws through clearance holes, nested parts with wall offsets, and moving parts with their travel envelope accounted for.
|
|
172
|
-
|
|
173
|
-
Temporary collisions during construction are fine when they are part of how the model is made or verified: oversized cutter solids before `difference()`, overlapping primitives before `union()`, transparent ghost parts for fit checks, or exploratory joint layouts. Those temporary bodies should be consumed, hidden, named as ghosts, or isolated with inspection filters so final collision findings stay meaningful.
|
|
174
|
-
|
|
175
|
-
If a final overlap is real manufacturing intent, document the exact visible object pair with `verify.intentionalOverlap("rubber grip is overmolded on handle core", rubberGrip, handleCore, "overmolded bonded grip")`. Use this only for welded, fused, overmolded, cast-in, potted, or bonded matter. The mechanical-integrity gate honors it only when the same visible object pair has a confirmed exact collision; unused or non-visible declarations still fail.
|
|
176
|
-
|
|
177
|
-
Before delivery on any multi-part, internal, or mechanical model, run `forgecad inspect fit interference`, read the collision evidence PNGs, and check `manifest.json`. Fix unexpected overlaps; collision removal is part of the expected modeling pass, not optional polish. If a collision is intentional, declare the exact visible pair with `verify.intentionalOverlap(...)` or isolate that inspection with `--focus` / `--hide` so the remaining collision report proves the final assembly is real.
|
|
108
|
+
- Only exceptions: welded, fused, overmolded, cast-in, potted, or bonded matter — declared with `verify.intentionalOverlap` on the exact visible object pair with the physical reason. The mechanical-integrity gate honors a declaration only when that pair has a confirmed exact collision; unused or non-visible declarations still fail.
|
|
109
|
+
- Never use interpenetration as a placement shortcut. Model contact honestly: pins in holes, shafts in seats, tabs in slots, hinges with knuckle clearance, nested parts with wall offsets, moving parts with travel envelopes.
|
|
110
|
+
- Temporary construction overlaps (oversized cutters before `difference()`, primitives before `union()`, exploratory layouts) must be consumed, hidden, named as ghosts, or isolated with `--focus`/`--hide` so final findings stay meaningful.
|
|
111
|
+
- Collision removal is part of the modeling pass, not optional polish.
|
|
178
112
|
|
|
179
113
|
## Final Acceptance Gate
|
|
180
114
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
1. State the intended physical component graph. Decide whether the final artifact should be one connected component, several intentionally separate components, or a selected assembly plus named ghosts. Then run:
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
forgecad inspect physical components model.forge.js --camera iso
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
The reported component count must match the design intent. Treat unexpected islands, accidental fusion, or bbox-only "touching" that does not make physical sense as model bugs.
|
|
190
|
-
|
|
191
|
-
If the script uses `assembly()`, also run:
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
forgecad debug assembly model.forge.js --fail-on warning
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
Fix warnings about multiple roots, manual joint contracts, disconnected bodies inside parts, unused connectors, solve warnings, and collisions before delivery. If a warning is truly intentional, rename the part or add a short code comment so a reviewer can see the physical reason.
|
|
198
|
-
|
|
199
|
-
For generated mechanical projects or batches, also run:
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
forgecad inspect mechanical-integrity . --collisions
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
This is the shareability gate. It fails on missing `verify.*` checks, missing mechanical-interface verification, fragmented named groups, uncontracted manual assemblies, positive-volume object collisions, timeouts, and runtime failures. Do not share a generated mechanical model while this gate is red unless the user explicitly asked for a rough concept/blockout.
|
|
115
|
+
Prove technical validity and visual plausibility before declaring done. Apply to any model with multiple bodies, surface details, cables, rails, handles, product skins, or hidden mating geometry.
|
|
206
116
|
|
|
207
|
-
|
|
117
|
+
1. **State the intended physical component graph** — one connected component, several intentionally separate, or a selected assembly plus named ghosts — then run `forgecad inspect physical components` and require the count to match. Unexpected islands, accidental fusion, or bbox-only "touching" are model bugs.
|
|
118
|
+
- Scripts using `assembly()`: `forgecad debug assembly model.forge.js --fail-on warning`. Fix warnings (multiple roots, manual joint contracts, disconnected bodies, unused connectors, collisions); a truly intentional one gets a visible reason in code.
|
|
119
|
+
- Generated mechanical work: `forgecad inspect mechanical-integrity . --collisions` is the shareability gate — it fails on missing `verify.*` interface checks, fragmented named groups, uncontracted manual assemblies, positive-volume collisions, timeouts, runtime failures. Do not share while red unless the user asked for a blockout.
|
|
120
|
+
- Include at least one verification that proves a mechanical interface (clearance band, keep-out, connector mate), not just object counts.
|
|
121
|
+
- Moving assemblies: incomplete until poses cover rest, mid-travel, both limits, coupled and mirrored states via `--joint` and/or in-script `solve(state)` checks, with convergence, attachment, and clearances holding at every pose.
|
|
122
|
+
2. **Collision evidence**: run `forgecad inspect fit interference`; read the manifest collision count AND the evidence PNGs. Zero unexpected findings per Collision Policy; visually confirm where any findings appear.
|
|
123
|
+
3. **Risk-specific views, not just a hero shot.** Delivery renders use the model's `scene()` rig (Scene Presentation below) — default flat lighting in a final render is a finding. One whole-model context view plus views chosen from this object's failure modes — opposing, underside, interior-facing, or grazing angles that catch internals showing through openings, covers that don't close, bad boolean cuts. Per meaningful interface: one contextual and one focused/isolated view. Risk prompts:
|
|
124
|
+
- long products, rails, handles, tools: views along and across the dominant length (bends, sag, end attachments)
|
|
125
|
+
- enclosures/shells with internals: exterior plus hidden-cover views (fit, concealment, service access)
|
|
126
|
+
- sockets, underside joins, stands, brackets: look directly into the mating face or underside; `inspect sections` for hidden geometry
|
|
127
|
+
- cables, strings, belts, tubes: both endpoints, route clearance, sag, termination hardware
|
|
128
|
+
- surface details on curved ProductSkin bodies: grazing and contextual views proving details conform or embed
|
|
129
|
+
4. **Visual attachment audit.** For every detail that should be connected, ask "where does this physically enter, seat, wrap, terminate, or fasten?" and check that view directly. Known failures to fix before delivery:
|
|
130
|
+
- a flat rail or bed sitting on a curved shell instead of being recessed, saddled, socketed, or blended in
|
|
131
|
+
- strings/cables passing through space without knots, hooks, holes, posts, ferrules, pulleys, or anchors
|
|
132
|
+
- trim lines floating above the body instead of following the surface or being inset/raised strips with real thickness
|
|
133
|
+
- handles/grips touching only by a tangent instead of having a neck, bridge, socket, screws, or overmolded landing
|
|
134
|
+
- small hardware/gems that are bbox-connected but visually levitate; give them flush/inset seats or explicit brackets
|
|
135
|
+
5. **ProductSkin honesty.** Boolean-test warnings from sampled-loft boundary edges are not real collisions. Deliver only if the collision count is clean, connectivity is correct, and the attachment audit passes; mention the residual warning in the final response.
|
|
136
|
+
6. **Name the evidence** in the final response: commands run, views checked, joint values tested, focus/hide filters, component count, collision count, residual warnings or intentional exceptions. Never just say "validated."
|
|
208
137
|
|
|
209
|
-
|
|
138
|
+
## Manufacturing Outputs
|
|
210
139
|
|
|
211
|
-
|
|
212
|
-
forgecad inspect fit interference model.forge.js /tmp/model-collisions-inspect --camera <collision-evidence-camera> --force --size 700
|
|
213
|
-
jq '.evidence.collisions | {collisionCount, collisions, warnings}' /tmp/model-collisions-inspect/manifest.json
|
|
214
|
-
```
|
|
140
|
+
A manufacture-realistic model must yield a package a shop can consume, not just a clean viewport.
|
|
215
141
|
|
|
216
|
-
|
|
142
|
+
- Register every purchased and fabricated part with `bom()` (exact spec, quantity, purpose) so the BOM lives in the model — `forgecad export report` must reproduce it without prose supplements.
|
|
143
|
+
- Put `dim()` annotations on the dimensions a builder must hit: overall envelope, critical interfaces, mating bores and bolt patterns.
|
|
144
|
+
- Prove the process-appropriate export runs cleanly and name the output path in the final response: `export stl`/`export 3mf` for printed parts; `export step` for machined parts and CAD interchange; sheet-metal parts must unfold to a valid flat pattern (`export cutting-layout` for sheet goods). `step`, `report`, and `cutting-layout` need a Production license — if unavailable, run the free exports and name the gated commands that complete the package instead of failing.
|
|
145
|
+
- An export failure (non-manifold body, open shell, fused multi-part blob where one fabricated part was expected) is a model bug, not an export problem.
|
|
217
146
|
|
|
218
|
-
|
|
147
|
+
## Render and Inspect Cadence
|
|
219
148
|
|
|
220
|
-
|
|
221
|
-
- Use opposing, underside, interior-facing, or grazing views when they are the views most likely to catch internals accidentally showing through openings, transparent shells, thin walls, bad boolean cuts, or covers that do not actually close.
|
|
222
|
-
- Render focused views for important components or subsystems with `--focus`, especially mounts, covers, hinges, cartridges, electronics, routed cables, fastener stacks, moving links, and purchased parts.
|
|
223
|
-
- Render hidden-object views with `--hide` when an exterior shell, cover, fixture, or decorative layer blocks the interface being checked. This is for evidence only; do not turn the default returned model into a cutaway or exploded teaching scene.
|
|
224
|
-
- For each meaningful interface, capture at least one contextual view with neighboring parts present and one isolated/focused view that makes the interface easy to inspect.
|
|
149
|
+
**You are building blind unless you render.** `forgecad run` passing only means the code didn't crash — it cannot tell you a hole is misplaced, a rib pokes through a cover, or a part doesn't fit. Render from angles chosen for the model's actual geometry and read every PNG. For command syntax, evidence selection, and manifest reading, use the `forgecad-render-inspect` skill and the CLI docs — this skill fixes only the cadence and the gates.
|
|
225
150
|
|
|
226
|
-
|
|
151
|
+
Render after every feature addition, boolean cut, symmetric copy placement, and the last feature. Inspect after adding hidden geometry a surface render cannot prove, after adding or moving mating parts, ghosts, connectors, thin walls, or screw holes, and before delivery with thresholds set for the material/process.
|
|
227
152
|
|
|
228
|
-
|
|
229
|
-
- enclosures, shells, covers, and products with internals: choose exterior and hidden-cover views that reveal whether internal structures fit, stay hidden when they should, and leave service access
|
|
230
|
-
- sockets, underside joins, stands, brackets, and handles: choose views that look directly into the mating face or underside; use `inspect sections at|stack|sample` when hidden geometry must be checked
|
|
231
|
-
- cables, strings, belts, tubes, and hoses: choose views that show both endpoints, route clearance, sag, and termination hardware
|
|
232
|
-
- surface details on curved ProductSkin bodies: choose grazing and contextual views that prove details conform or are embedded as intended
|
|
153
|
+
**Keep inspection scenes small.** Return one selected configuration; include only the parts needed to prove the current risk (if a check concerns three objects, inspect those three, not the whole shop floor); prefer `--focus`/`--hide` and parameter-selected diagnostic modes over permanent extra objects; collapse proven subassemblies into fewer named objects where identity doesn't matter for collisions, masks, or contracts. If you cannot hold the scene in your head, you cannot debug it honestly.
|
|
233
154
|
|
|
234
|
-
|
|
155
|
+
**Ghost parts for fit checks.** When a part holds or contains another object, render both with the contained object as a compact transparent named ghost — e.g. a `box()` at the seat position with `.color('#ff4444').material({ opacity: 0.4 })`, returned as `{ name: 'Servo Ghost', shape: ghost }`.
|
|
235
156
|
|
|
236
|
-
|
|
237
|
-
- strings/cables that pass through space without terminal knots, hooks, holes, posts, ferrules, pulleys, or anchors
|
|
238
|
-
- decorative brass/trim lines floating above the body instead of following a ProductSkin surface or being built as inset/raised strips with believable thickness
|
|
239
|
-
- handles/grips touching only by a tangent or thin face instead of having a neck, bridge, socket, screws, or overmolded landing
|
|
240
|
-
- small hardware or gems that are bbox-connected but visually read as levitating; replace with flush/inset seats or explicit brackets
|
|
157
|
+
Use `verify.*` for dimensions and clearances that decide acceptance; `console.log()` only for explanatory traces (shown under "Script output:" in `forgecad run`).
|
|
241
158
|
|
|
242
|
-
|
|
159
|
+
## Build Bottom-Up
|
|
243
160
|
|
|
244
|
-
|
|
161
|
+
You cannot target a complex model in one pass. Decompose, solve the smallest piece, verify, compose upward:
|
|
245
162
|
|
|
246
|
-
|
|
163
|
+
1. **Decompose** into the smallest parts you can reason about confidently. A gear is not small — a single tooth profile is.
|
|
164
|
+
2. **Solve one piece** in isolation: own variables, own return, no connection logic yet.
|
|
165
|
+
3. **Verify it**: `forgecad run`, then render and read the PNG. Fix while the scope is tiny.
|
|
166
|
+
4. **Compose one layer at a time**, verifying at each level so a break is always at the newest seam.
|
|
247
167
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
### How to render and inspect
|
|
251
|
-
|
|
252
|
-
```bash
|
|
253
|
-
# Render from multiple agent-chosen angles; do not stop at one hero view.
|
|
254
|
-
node dist-cli/forgecad.js render model.forge.js /tmp/preview.png \
|
|
255
|
-
--camera <context-az:el> \
|
|
256
|
-
--camera <failure-mode-az:el> \
|
|
257
|
-
--camera <interface-az:el> \
|
|
258
|
-
--size 600
|
|
259
|
-
|
|
260
|
-
# Camera format: --camera az:el (degrees). Repeatable.
|
|
261
|
-
# Choose camera directions that prove or disprove the physical questions in this model.
|
|
262
|
-
# Good evidence sets usually include a context view plus views aimed at hidden internals,
|
|
263
|
-
# underside joins, mating faces, routed paths, thin walls, or surface attachments.
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
Then read the PNG(s) to inspect visually. Single camera → single file. Multiple cameras → suffixed files (`_az45_el25.png`). If any angle reveals internal geometry where the outside should be closed, a cover that does not seat, a hidden part that cannot fit, or a detail that floats/intersects, edit the model and rerender the same angles.
|
|
267
|
-
|
|
268
|
-
### Focused visual evidence
|
|
269
|
-
|
|
270
|
-
Use focused and hidden-object renders to collect evidence from the parts a normal hero shot hides. The goal is to answer specific physical questions: "is the cover seated?", "does the cable enter a gland?", "are the screws aligned with bosses?", "does the bracket actually touch the frame?"
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
# Isolate the target subsystem from several angles.
|
|
274
|
-
node dist-cli/forgecad.js render model.forge.js /tmp/model-cover-stack.png \
|
|
275
|
-
--focus "Cover,Screws,Gasket,Bosses" \
|
|
276
|
-
--camera <subsystem-context-az:el> \
|
|
277
|
-
--camera <seating-interface-az:el> \
|
|
278
|
-
--camera <fastener-axis-az:el> \
|
|
279
|
-
--size 700
|
|
280
|
-
|
|
281
|
-
# Hide exterior clutter to inspect the installed internals in context.
|
|
282
|
-
node dist-cli/forgecad.js render model.forge.js /tmp/model-internals.png \
|
|
283
|
-
--hide "Outer Shell,Top Cover" \
|
|
284
|
-
--camera <internal-context-az:el> \
|
|
285
|
-
--camera <clearance-path-az:el> \
|
|
286
|
-
--camera <underside-or-access-az:el> \
|
|
287
|
-
--size 700
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
For important components, collect both:
|
|
291
|
-
|
|
292
|
-
- Context view — neighbors present, proving the part belongs in the final assembly.
|
|
293
|
-
- Focus view — only the relevant objects visible, making small gaps, intersections, missing seats, and floating parts easy to see.
|
|
294
|
-
|
|
295
|
-
Prefer CLI `--focus` / `--hide` filters, named views, or parameter-selected diagnostic modes over changing production geometry. Use the object paths from `node dist-cli/forgecad.js ls model.forge.js --tree` when you are unsure what the filters should target.
|
|
296
|
-
|
|
297
|
-
### Structured inspection bundles
|
|
298
|
-
|
|
299
|
-
After the normal PNG render, run targeted `forgecad inspect <family> <mode>` commands and read both the evidence PNGs and `manifest.json`. Keep inspection bundles targeted to the current risk; for any multi-part final build, `inspect fit interference` is mandatory:
|
|
300
|
-
|
|
301
|
-
```bash
|
|
302
|
-
forgecad inspect fit interference model.forge.js /tmp/model-collisions-inspect --camera <collision-evidence-camera> --force --size 700
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Inspection feedback loop
|
|
306
|
-
|
|
307
|
-
Use inspections as the repair loop for the model:
|
|
308
|
-
|
|
309
|
-
1. Ask one physical question before each bundle: "what evidence would prove this model is wrong?"
|
|
310
|
-
2. Run the smallest inspection command that can answer it. Add `inspect visual image` or `inspect visual objects` alongside the risk evidence when you need visual context or object-color lookup.
|
|
311
|
-
3. Read `manifest.json` first for counts, pairs, thresholds, filters, object mappings, and warnings.
|
|
312
|
-
4. Read the evidence PNGs next, using `inspect visual image` and `inspect visual objects` outputs to locate findings in the real geometry when needed.
|
|
313
|
-
5. Convert findings into model edits:
|
|
314
|
-
- `collisions`: add real receiving geometry, holes, seats, clearance, connectors, or `verify.intentionalOverlap(...)` for true fused/overmolded/bonded matter only.
|
|
315
|
-
- `thickness`: change wall, rib, boss, shell, slot, or process dimensions; set material/process thresholds before accepting the result.
|
|
316
|
-
- `sections`: add or repair the hidden cavity, screw path, pocket, cable route, captured part, or internal support the slice exposed.
|
|
317
|
-
- `connectivity`, `floating`, and `distance`: fix disconnected islands, accidental fusion, unsupported bodies, or surprising gaps in the component graph.
|
|
318
|
-
- `objects`, `depth`, `normals`, and `zebra`: fix missing objects, confusing object identity, flipped/odd surfaces, faceting, protrusions, and bad surface continuity.
|
|
319
|
-
6. Rerun the same targeted evidence command after the edit so the before/after evidence is comparable. Add a second evidence command only when the repaired area creates a new risk.
|
|
320
|
-
|
|
321
|
-
### Keep CLI inspection scenes small
|
|
322
|
-
|
|
323
|
-
When using CLI inspection commands, make the scene as few returned/named objects as the requirement allows. The goal is not to hide required geometry; it is to keep the evidence small enough that the agent can reason about it properly.
|
|
324
|
-
|
|
325
|
-
- Return one selected configuration, not every variant, option bundle, or debug lineup.
|
|
326
|
-
- Include only the parts, ghosts, and fixtures needed to prove the current risk. If a collision, clearance, thickness, or section check concerns three objects, inspect those three objects instead of the whole shop floor.
|
|
327
|
-
- Prefer `--focus` / `--hide` and parameter-selected diagnostic modes over adding permanent extra objects to the default scene.
|
|
328
|
-
- Collapse decorative or already-proven subassemblies into fewer named objects when their internal boundaries are irrelevant to the inspection. Keep separate names only where object identity matters for collisions, masks, clearances, BOM roles, or mechanical contracts.
|
|
329
|
-
|
|
330
|
-
Small inspection scenes make `manifest.json`, mask colors, collision pairs, component counts, and section images cognitively tractable. If the agent cannot hold the scene in its head, it cannot debug the model honestly.
|
|
331
|
-
|
|
332
|
-
For faster iteration, request the evidence that matches the current risk:
|
|
333
|
-
|
|
334
|
-
- `inspect fit interference` — final multi-part assemblies, fixtures, enclosures, ghost fit checks, moving clearances, and any parts intended to touch without overlapping. Visually inspect this evidence; do not rely only on the count.
|
|
335
|
-
- `inspect manufacture thickness` — printed shells, sheet metal, molded walls, ribs, bosses, holes, snap fits, slots, brackets, and any feature where thin walls can fail. Set thresholds for the selected material/process instead of blindly accepting defaults.
|
|
336
|
-
- `inspect sections at|stack|sample` — hidden internals, cavities, wire channels, pockets, screw paths, captured components, and anything a surface render cannot show.
|
|
337
|
-
- `inspect physical components` — parts that should be one connected solid, parts that should remain separate, and assemblies where floating or accidentally fused bodies matter.
|
|
338
|
-
- `inspect physical floating` and `inspect physical gaps` — loose bodies, unsupported bodies, or surprising gaps in the component graph.
|
|
339
|
-
- `inspect visual objects` — object identity, missing named parts, duplicate geometry, hidden mocks, and color/name confusion.
|
|
340
|
-
- `inspect visual depth` / `inspect visual normals` / `inspect surface zebra` — occlusion, orientation, flipped surfaces, odd protrusions, faceting, and surface continuity.
|
|
341
|
-
- `inspect visual image` — the human-readable view that keeps structured evidence grounded.
|
|
342
|
-
|
|
343
|
-
Useful manifest checks:
|
|
344
|
-
|
|
345
|
-
```bash
|
|
346
|
-
jq '.evidence.collisions | {collisionCount, collisions, warnings}' /tmp/model-inspect/manifest.json
|
|
347
|
-
jq '.evidence.thickness.objects[] | {name, minThickness, p05Thickness, criticalAreaPercent, warningAreaPercent, unresolvedAreaPercent}' /tmp/model-inspect/manifest.json
|
|
348
|
-
jq '.evidence.connectivity | {componentCount, edges, warnings}' /tmp/model-inspect/manifest.json
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
Treat unexpected collision findings, critical thin regions, high unresolved thickness, missing sections, or wrong component counts as model bugs. If an overlap is intentional, make that explicit in the model or isolate the inspection with `--focus` / `--hide` so the remaining findings are meaningful:
|
|
352
|
-
|
|
353
|
-
```bash
|
|
354
|
-
forgecad inspect fit interference model.forge.js /tmp/model-fit-collisions --focus "Bracket,Screw Ghost" --camera <fit-evidence-camera> --force
|
|
355
|
-
forgecad inspect sections sample model.forge.js /tmp/model-fit-sections --plane yz --count 5 --focus "Bracket,Screw Ghost" --force
|
|
356
|
-
forgecad inspect manufacture thickness model.forge.js /tmp/model-thickness --min 1.6 --warn 2.4 --camera <thickness-evidence-camera> --force
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### When to render
|
|
360
|
-
|
|
361
|
-
- After every feature addition (not just at the end)
|
|
362
|
-
- After any boolean subtraction that creates a hole/pocket
|
|
363
|
-
- After placing symmetric copies (to check symmetry)
|
|
364
|
-
- After adding the last feature (final check)
|
|
365
|
-
|
|
366
|
-
### When to inspect
|
|
367
|
-
|
|
368
|
-
- After adding hidden/internal geometry that a surface render cannot prove
|
|
369
|
-
- After adding or moving mating parts, ghosts, connectors, holes, pockets, or clearances
|
|
370
|
-
- After adding thin walls, ribs, slots, snap features, bosses, or screw holes
|
|
371
|
-
- Before final delivery, with the evidence that matches the remaining risks, and with thresholds appropriate to the model
|
|
372
|
-
|
|
373
|
-
### Ghost parts for fit verification
|
|
374
|
-
|
|
375
|
-
When building a part that holds/contains another object (enclosure, mount, bracket), render both together with the contained object transparent:
|
|
376
|
-
|
|
377
|
-
```js
|
|
378
|
-
// Ghost servo for visual fit check
|
|
379
|
-
const ghost = box(servoW, servoD, servoH)
|
|
380
|
-
.placeReference('center', [0, 0, wallThick])
|
|
381
|
-
.color('#ff4444').material({ opacity: 0.4 });
|
|
382
|
-
|
|
383
|
-
return [
|
|
384
|
-
{ name: 'Mount', shape: mount.color('#556B2F') },
|
|
385
|
-
{ name: 'Servo Ghost', shape: ghost },
|
|
386
|
-
];
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
This immediately reveals: does it fit? Does it collide with walls? Does the shaft clear the opening?
|
|
390
|
-
|
|
391
|
-
### Use verify for acceptance, console.log for traces
|
|
392
|
-
|
|
393
|
-
Use `verify.*` for dimensions and clearances that decide whether the model is acceptable. Use `console.log()` only for explanatory traces that help you read the run output.
|
|
394
|
-
|
|
395
|
-
```js
|
|
396
|
-
verify.greaterThan("wall remains around slot", (outerW - slotW) / 2, 1.6);
|
|
397
|
-
verify.greaterThan("hole clears flange edge", flangeW / 2 - holeX - holeDia / 2, 2.0);
|
|
398
|
-
console.log("wall remaining:", ((outerW - slotW) / 2).toFixed(1));
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
Output appears under "Script output:" in `forgecad run`.
|
|
402
|
-
|
|
403
|
-
### Self-inspecting shared constants
|
|
404
|
-
|
|
405
|
-
For multi-file projects with a shared constants file (e.g. `shared-dims.js`), add a summary block that prints all computed values when the file is run directly. This replaces one-off throwaway debug scripts.
|
|
406
|
-
|
|
407
|
-
```js
|
|
408
|
-
// At the bottom of shared-dims.js:
|
|
409
|
-
if (require.main === module) {
|
|
410
|
-
console.log('=== SERVO ===');
|
|
411
|
-
console.log(' body:', servo.bodyW, '×', servo.bodyD, '×', servo.bodyH, 'mm');
|
|
412
|
-
// ... all computed dimensions, clearance checks, etc.
|
|
413
|
-
console.log('✓ All validations passed.');
|
|
414
|
-
}
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
Run with `node shared-dims.js` to see the full dimension summary. Don't write throwaway `node -e "require(...)..."` scripts — put the inspection logic in the source file itself where it stays up to date automatically.
|
|
418
|
-
|
|
419
|
-
## ForgeCAD Quick Reference
|
|
420
|
-
|
|
421
|
-
The `forgecad` skill has full API docs.
|
|
422
|
-
|
|
423
|
-
Key primitives:
|
|
424
|
-
|
|
425
|
-
- `box(x, y, z)`, `cylinder(h, r, rTop?, segments?)`, `sphere(r)`, `torus(R, r)`
|
|
426
|
-
- `union()`, `difference()`, `intersection()`
|
|
427
|
-
- `.fillet()`, `.chamfer()` for experimental edge treatments only
|
|
428
|
-
- `param(name, default, opts)`, `boolParam(name, default)`
|
|
429
|
-
- Return `[{ name, shape, color }]` for multi-part colored models
|
|
430
|
-
|
|
431
|
-
Primitive placement convention:
|
|
432
|
-
|
|
433
|
-
- `box()` and `cylinder()` are centered in X/Y and sit on `z=0`.
|
|
434
|
-
- `sphere()` and `torus()` are centered in X/Y/Z.
|
|
435
|
-
- Use `.placeReference('center', [0, 0, 0])` when a box or cylinder should be centered around the origin.
|
|
436
|
-
- Do not pass `center: true` or a positional `true` to primitives; that is stale OpenSCAD-style guidance.
|
|
437
|
-
|
|
438
|
-
Key composition tools:
|
|
439
|
-
|
|
440
|
-
- Connectors + `matchTo()` for parts that should touch in the final model
|
|
441
|
-
- `group()` for local-coordinate subassemblies
|
|
442
|
-
- `attachTo()` for quick bounding-box placement
|
|
443
|
-
- `.translate()` / `.rotate()` for free offsets or bridging computed locations, not as the default assembly contract
|
|
444
|
-
|
|
445
|
-
## Managing Complexity: Build Bottom-Up
|
|
446
|
-
|
|
447
|
-
You cannot target a complex model directly. A chess set, a mechanical assembly, an articulated figure — if you try to write the whole thing in one pass, you will get lost in coordinate math, produce subtle geometry bugs, and waste cycles debugging a tangled script.
|
|
448
|
-
|
|
449
|
-
Instead, do what engineers do: decompose, solve the smallest piece, verify, then compose upward.
|
|
450
|
-
|
|
451
|
-
### The process
|
|
452
|
-
|
|
453
|
-
1. Decompose — Break the model into the smallest independent parts you can reason about confidently. A "gear" is not a small part — a single tooth profile is. A "house" is not small — a wall panel with a window cutout is.
|
|
454
|
-
|
|
455
|
-
2. Solve the smallest piece — Write the geometry for one part. Keep it isolated: its own variables, its own return statement. Don't think about how it connects to the rest yet.
|
|
456
|
-
|
|
457
|
-
3. Verify — Run `forgecad run` to check for errors, then `forgecad render` to actually see the shape. Read the rendered PNG. Does it match your intent? Are holes where they should be? Are walls thick enough? Fix it now while the scope is tiny. `forgecad run` passing does not mean the geometry is correct — it only means the code didn't crash.
|
|
458
|
-
|
|
459
|
-
4. Compose upward — Once a piece is verified, combine it with the next piece. Verify again. Each level of assembly should be independently checkable.
|
|
460
|
-
|
|
461
|
-
5. Repeat — Keep climbing. Each step adds one layer of complexity on top of verified foundations. If something breaks, you know it's in the new layer, not buried three levels deep.
|
|
462
|
-
|
|
463
|
-
### Why this matters
|
|
464
|
-
|
|
465
|
-
- Debugging is local. When a verified piece breaks after composition, the bug is at the seam, not inside the piece.
|
|
466
|
-
- You avoid coordinate chaos. Small pieces use simple local coordinates. Transforms and placements happen at composition time, one layer at a time.
|
|
467
|
-
- Iteration is cheap. Changing a tooth profile doesn't require re-reading 200 lines of gear assembly code.
|
|
468
|
-
|
|
469
|
-
### In practice
|
|
470
|
-
|
|
471
|
-
For a model with more than ~3 distinct geometric features, explicitly plan the decomposition before writing any geometry. Write each piece as a function or variable block, verify it, then combine. Do not skip verification steps to "save time" — it costs more time in the end.
|
|
168
|
+
For any model with more than ~3 distinct geometric features, plan the decomposition explicitly before writing geometry.
|
|
472
169
|
|
|
473
170
|
## Scene Presentation
|
|
474
171
|
|
|
475
|
-
Always set up
|
|
476
|
-
|
|
477
|
-
### Minimum scene setup
|
|
478
|
-
|
|
479
|
-
Every model should have at least:
|
|
480
|
-
|
|
481
|
-
```js
|
|
482
|
-
scene({
|
|
483
|
-
background: { top: '#1a1a2e', bottom: '#0a0a14' },
|
|
484
|
-
camera: { position: [x, y, z], target: [0, 0, 0], fov: 42 },
|
|
485
|
-
environment: { preset: 'studio', intensity: 0.6 },
|
|
486
|
-
lights: [
|
|
487
|
-
{ type: 'ambient', color: '#c8cdd4', intensity: 0.15 },
|
|
488
|
-
{ type: 'directional', position: [80, -60, 120], target: [0, 0, 0], color: '#fff4e0', intensity: 1.8, castShadow: true },
|
|
489
|
-
{ type: 'directional', position: [-60, 40, 80], target: [0, 0, 0], color: '#b0c4de', intensity: 0.7 },
|
|
490
|
-
],
|
|
491
|
-
ground: { visible: true, color: '#111118', height: -10, receiveShadow: true },
|
|
492
|
-
postProcessing: {
|
|
493
|
-
bloom: { intensity: 0.3, threshold: 0.85, radius: 0.3 },
|
|
494
|
-
vignette: { darkness: 0.5, offset: 0.4 },
|
|
495
|
-
toneMappingExposure: 1.3,
|
|
496
|
-
},
|
|
497
|
-
});
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
### Named render views
|
|
501
|
-
|
|
502
|
-
For models that need repeatable review, docs, or hero renders, declare named views inside
|
|
503
|
-
`scene({ views })`. The canonical form wraps each camera in `{ camera: ... }`; direct camera
|
|
504
|
-
shorthand is accepted by the runtime, but the wrapped form is the clearest prompt/example shape.
|
|
505
|
-
|
|
506
|
-
```js
|
|
507
|
-
scene({
|
|
508
|
-
camera: { position: [430, -540, 340], target: [0, 30, 125], fov: 38 },
|
|
509
|
-
views: {
|
|
510
|
-
hero: {
|
|
511
|
-
camera: { position: [430, -540, 340], target: [0, 30, 125], up: [0, 0, 1], fov: 38 },
|
|
512
|
-
},
|
|
513
|
-
side: {
|
|
514
|
-
camera: { position: [700, 0, 180], target: [0, 30, 100], up: [0, 0, 1], fov: 32 },
|
|
515
|
-
},
|
|
516
|
-
},
|
|
517
|
-
});
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
Render one later with:
|
|
521
|
-
|
|
522
|
-
```bash
|
|
523
|
-
forgecad render 3d model.forge.js --view hero
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
### Lighting principles
|
|
527
|
-
|
|
528
|
-
- When `lights` is set, all defaults are replaced, so always include an ambient light or the scene goes black.
|
|
529
|
-
- Use a 3-point setup at minimum: ambient fill + warm key light (with `castShadow: true`) + cool rim/back light for edge separation.
|
|
530
|
-
- Add accent point lights near focal features (e.g. a gold crown, a polished surface) for highlights.
|
|
531
|
-
- Use `distance` and `decay` on point lights to keep them localized.
|
|
532
|
-
|
|
533
|
-
### Adapt to the model
|
|
534
|
-
|
|
535
|
-
- Metallic/jewelry models: `studio` environment, higher `toneMappingExposure` (1.2–1.5), subtle bloom for specular highlights.
|
|
536
|
-
- Organic/wood/matte models: `warehouse` or `apartment` environment, lower bloom, warmer ambient.
|
|
537
|
-
- Mechanical/industrial models: `warehouse` environment, stronger directional lights, minimal bloom.
|
|
538
|
-
- Dark/dramatic models: dark gradient background, `night` environment, bloom + vignette for mood.
|
|
539
|
-
|
|
540
|
-
### Matte industrial hero-shot recipe
|
|
541
|
-
|
|
542
|
-
For mechanisms, tools, product prototypes, vehicles, and other industrial showpieces, prefer a matte studio look over glossy or atmospheric drama:
|
|
543
|
-
|
|
544
|
-
```js
|
|
545
|
-
scene({
|
|
546
|
-
background: { top: '#c3ccd7', bottom: '#566474' },
|
|
547
|
-
camera: { position: [430, -540, 340], target: [0, 30, 125], fov: 38 },
|
|
548
|
-
environment: { preset: 'studio', intensity: 0.15 - 0.25, background: false },
|
|
549
|
-
lights: [
|
|
550
|
-
{ type: 'ambient', color: '#efe7dc', intensity: 0.12 - 0.2 },
|
|
551
|
-
{ type: 'directional', position: [260, -320, 420], color: '#ffe2bf', intensity: 2.6 - 3.2, castShadow: true },
|
|
552
|
-
{ type: 'directional', position: [-260, 210, 220], color: '#d4e6fb', intensity: 0.7 - 1.0 },
|
|
553
|
-
{ type: 'hemisphere', skyColor: '#c7d3df', groundColor: '#495463', intensity: 0.1 - 0.2 },
|
|
554
|
-
],
|
|
555
|
-
postProcessing: {
|
|
556
|
-
bloom: { intensity: 0.0 - 0.06, threshold: 0.92 - 0.96, radius: 0.25 - 0.3 },
|
|
557
|
-
vignette: { darkness: 0.35 - 0.45, offset: 0.3 - 0.35 },
|
|
558
|
-
toneMappingExposure: 1.05 - 1.18,
|
|
559
|
-
},
|
|
560
|
-
});
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
Use a simple plinth or stage under the model, and make it intentionally matte too:
|
|
564
|
-
|
|
565
|
-
```js
|
|
566
|
-
const stage = cylinder(16, 226)
|
|
567
|
-
.translate(0, 0, -26)
|
|
568
|
-
.color('#8b97a4')
|
|
569
|
-
.material({ metalness: 0.04, roughness: 0.78 });
|
|
570
|
-
|
|
571
|
-
mock(stage, 'StudioPlinth');
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
What worked well in practice:
|
|
575
|
-
|
|
576
|
-
- Keep `environment.intensity` low. High environment fill kills shadows and makes everything look washed out.
|
|
577
|
-
- Let one warm directional key light do most of the shaping. Add only a weaker cool fill/rim for separation.
|
|
578
|
-
- Prefer roughness over fog for softness. Fog flattens the model and hides form; matte materials preserve shadow definition.
|
|
579
|
-
- Keep bloom extremely low for mechanical scenes. A little is fine; too much makes manufactured parts feel toy-like or overly glossy.
|
|
580
|
-
- If the render is close but not perfect, change `toneMappingExposure` by about `0.05` first before redoing the whole lighting rig.
|
|
581
|
-
- Avoid large ambient-light jumps. They brighten fast and remove contrast faster than expected.
|
|
582
|
-
|
|
583
|
-
### Ground plane
|
|
584
|
-
|
|
585
|
-
Enable `ground` with `receiveShadow: true` for models that benefit from visual grounding (furniture, vehicles, standalone objects). Skip it for floating/abstract geometry.
|
|
586
|
-
|
|
587
|
-
### Camera
|
|
588
|
-
|
|
589
|
-
- Position the camera at a 3/4 angle (not dead-on axis) for natural perspective.
|
|
590
|
-
- Use `fov` 35–50 for most models. Lower FOV = more telephoto/flatter, higher = more dramatic perspective.
|
|
591
|
-
- Set `target` to the visual center of mass, not necessarily `[0,0,0]`.
|
|
592
|
-
|
|
593
|
-
## Tips
|
|
172
|
+
Always set up `scene()` — default lighting looks flat. Worked recipes (studio and matte-industrial setups, named views, plinth) live in `guides/scene-presentation.md` via the `forgecad` skill; the schema is in the viewport docs. Hard-won cliffs:
|
|
594
173
|
|
|
595
|
-
-
|
|
596
|
-
-
|
|
597
|
-
-
|
|
598
|
-
-
|
|
599
|
-
-
|
|
600
|
-
-
|
|
174
|
+
- Setting `lights` replaces ALL defaults — always include an ambient light or the scene goes black.
|
|
175
|
+
- Minimum rig: ambient fill + one warm key (`castShadow: true`) + weaker cool fill/rim. Keep `environment.intensity` low — environment fill kills shadows.
|
|
176
|
+
- Prefer roughness over fog for softness; keep bloom near zero for mechanical parts or they read toy-like.
|
|
177
|
+
- If a render is close, nudge `toneMappingExposure` by ~0.05 before redoing the rig; avoid big ambient jumps.
|
|
178
|
+
- Camera: 3/4 angle, `fov` 35–50, `target` at the visual center of mass. Ground plane with shadows for grounded objects.
|
|
179
|
+
- Environment by type: `studio` for metallic/jewelry, `warehouse`/`apartment` for organic/matte, `warehouse` + strong directionals for mechanical, `night` + bloom/vignette for dramatic.
|