pcb-scene3d-viewer 1.1.22 → 1.1.44

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.
Files changed (67) hide show
  1. package/AGENTS.md +4 -3
  2. package/README.md +3 -2
  3. package/docs/api.md +59 -1
  4. package/docs/circuitjson.md +206 -22
  5. package/docs/model-format.md +65 -3
  6. package/package.json +2 -2
  7. package/spec/library-scope.md +2 -2
  8. package/src/CircuitJsonCadModelAssetResolver.mjs +261 -0
  9. package/src/PcbAssemblyBoardSubstrateBuilder.mjs +49 -10
  10. package/src/PcbAssemblyComponentMeshBuilder.mjs +842 -0
  11. package/src/PcbAssemblyFillGeometryResolver.mjs +579 -0
  12. package/src/PcbAssemblyFillRingNormalizer.mjs +209 -0
  13. package/src/PcbAssemblyGeometryBuildProgress.mjs +3 -0
  14. package/src/PcbAssemblyGeometryBuilder.mjs +94 -174
  15. package/src/PcbAssemblyGltfModelMeshParser.mjs +969 -0
  16. package/src/PcbAssemblyGltfValidator.mjs +460 -0
  17. package/src/PcbAssemblyGltfWriter.mjs +978 -0
  18. package/src/PcbAssemblyModelMeshLoader.mjs +330 -2
  19. package/src/PcbAssemblyPadMeshBuilder.mjs +9 -7
  20. package/src/PcbAssemblyTextModelMeshParser.mjs +725 -0
  21. package/src/PcbModelArchiveExporter.mjs +17 -2
  22. package/src/PcbScene3dCircuitJsonAdapter.mjs +585 -246
  23. package/src/PcbScene3dCircuitJsonCopperPourBuilder.mjs +298 -0
  24. package/src/PcbScene3dCircuitJsonDocumentationArtworkBuilder.mjs +606 -0
  25. package/src/PcbScene3dCircuitJsonGeometry.mjs +542 -0
  26. package/src/PcbScene3dCircuitJsonLayer.mjs +110 -0
  27. package/src/PcbScene3dCircuitJsonModelTransform.mjs +232 -0
  28. package/src/PcbScene3dCircuitJsonModelUrlResolver.mjs +142 -0
  29. package/src/PcbScene3dCircuitJsonSilkscreenBuilder.mjs +729 -0
  30. package/src/PcbScene3dCircuitJsonSolderPasteBuilder.mjs +359 -0
  31. package/src/PcbScene3dCircuitJsonThermalSpokeBuilder.mjs +167 -0
  32. package/src/PcbScene3dCircuitJsonTraceRouteBuilder.mjs +335 -0
  33. package/src/PcbScene3dComponentVisibility.mjs +9 -6
  34. package/src/PcbScene3dController.mjs +25 -55
  35. package/src/PcbScene3dCopperDetailFilter.mjs +86 -9
  36. package/src/PcbScene3dCopperDetailGroupBuilder.mjs +186 -15
  37. package/src/PcbScene3dCopperDrillCutoutBuilder.mjs +258 -0
  38. package/src/PcbScene3dCopperFactory.mjs +99 -85
  39. package/src/PcbScene3dCopperFillMeshBuilder.mjs +393 -0
  40. package/src/PcbScene3dCopperLayerFilter.mjs +32 -3
  41. package/src/PcbScene3dCutoutGeometryFilter.mjs +17 -14
  42. package/src/PcbScene3dExternalModelCenteringPolicy.mjs +21 -0
  43. package/src/PcbScene3dExternalModelOpacity.mjs +51 -0
  44. package/src/PcbScene3dExternalModelPlacementRepair.mjs +5 -2
  45. package/src/PcbScene3dExternalModelSourceOriginPolicy.mjs +41 -0
  46. package/src/PcbScene3dExternalModels.mjs +10 -7
  47. package/src/PcbScene3dFallbackBodyFactory.mjs +45 -4
  48. package/src/PcbScene3dFallbackVisibility.mjs +17 -32
  49. package/src/PcbScene3dFootprintBodyBuilder.mjs +894 -0
  50. package/src/PcbScene3dMaskCoveredCopperSideGroupBuilder.mjs +68 -0
  51. package/src/PcbScene3dModelSeatingPolicy.mjs +58 -0
  52. package/src/PcbScene3dPadFactory.mjs +35 -2
  53. package/src/PcbScene3dRenderGroupVisibility.mjs +10 -13
  54. package/src/PcbScene3dRuntime.mjs +99 -91
  55. package/src/PcbScene3dRuntimeHelpers.mjs +39 -0
  56. package/src/PcbScene3dRuntimeSurfaceArtworkLoader.mjs +91 -0
  57. package/src/PcbScene3dSelectionIndexBuilder.mjs +87 -0
  58. package/src/PcbScene3dSelectionInspectorRenderer.mjs +50 -11
  59. package/src/PcbScene3dSelectionMarkerFactory.mjs +368 -0
  60. package/src/PcbScene3dSelectionMarkerOverlay.mjs +70 -0
  61. package/src/PcbScene3dSelectionStyler.mjs +52 -2
  62. package/src/PcbScene3dStaticBodyFactory.mjs +30 -8
  63. package/src/PcbScene3dStepLoader.mjs +42 -6
  64. package/src/PcbScene3dText.mjs +1 -0
  65. package/src/PcbScene3dTransparentMeshSplitter.mjs +623 -0
  66. package/src/PcbScene3dViaFactory.mjs +27 -7
  67. package/src/scene3d.mjs +4 -0
package/AGENTS.md CHANGED
@@ -35,9 +35,10 @@
35
35
  ## Library Scope
36
36
 
37
37
  - Include browser-side Three.js scene runtime, geometry factories, STEP/WRL
38
- model loading, component picking, view presets, archive export, the optional
39
- DOM controller, and the optional 3D shell renderer/styles.
40
- - Do not include ECAD parser logic or format-specific scene-description
38
+ model loading, component picking, view presets, archive export, CircuitJSON
39
+ scene adapters and CAD model asset resolution, the optional DOM controller,
40
+ and the optional 3D shell renderer/styles.
41
+ - Do not include ECAD parser logic or source-format-specific scene-description
41
42
  builders. Altium and KiCad scene descriptions are produced by their own
42
43
  toolkits and passed into this package.
43
44
  - Keep renderer fixes universal. Never special-case a specific file name,
package/README.md CHANGED
@@ -17,8 +17,9 @@ runtime.
17
17
 
18
18
  The package was extracted from [ECAD Forge](https://ecadforge.app/), where it
19
19
  is used for browser-based PCB 3D scene rendering. Its runtime, geometry
20
- factories, model loading, component picking, view presets, archive export, and
21
- optional DOM shell can be reused by other browser-based ECAD tools.
20
+ factories, model loading, component picking, view presets, archive export,
21
+ GLTF/GLB assembly writing, and optional DOM shell can be reused by other
22
+ browser-based ECAD tools.
22
23
 
23
24
  ## Install
24
25
 
package/docs/api.md CHANGED
@@ -63,7 +63,15 @@ Methods:
63
63
  - `isCircuitJsonModel(value)`: returns true for serialized CircuitJSON arrays.
64
64
  - `isDirectCircuitJsonModel(value)`: returns true when the array should bypass
65
65
  host `buildScene` callbacks.
66
- - `build(circuitJson)`: returns a runtime-ready scene description.
66
+ - `build(circuitJson, options?)`: returns a runtime-ready scene description.
67
+ `options.modelUrlResolver` can attach caller-owned URL resolution metadata to
68
+ `cad_component` external models without fetching them. `projectBaseUrl`
69
+ resolves relative model URLs and package-style `node_modules/...` model paths,
70
+ `drawFauxBoard: true` generates a board around component bounds when no board
71
+ or panel exists, `boardDrillQuality` controls generated circular
72
+ drill/cutout sampling, and `showPcbNotes: true` renders note, fabrication,
73
+ and courtyard artwork as silkscreen detail. `showPcbPaste: true` renders
74
+ direct solder-paste artwork as a separate top/bottom overlay.
67
75
 
68
76
  `PcbScene3dController` and `PcbScene3dRuntime` call this adapter automatically
69
77
  when they receive direct CircuitJSON input. See
@@ -121,6 +129,56 @@ worker.postMessage({
121
129
  Workers respond with `scene3d:success` and `sceneDescription`, or
122
130
  `scene3d:error` and `message`.
123
131
 
132
+ ## Assembly Geometry Export
133
+
134
+ ### `PcbAssemblyGeometryBuilder.build(sceneDescription, options?)`
135
+
136
+ Builds export meshes from a prepared scene description. `options.modelMeshLoader`
137
+ can provide external model meshes, `options.includeModels: false` skips external
138
+ model loading, and `options.renderFallbackBodies: false` disables procedural
139
+ component bodies for unresolved models. Placements with `renderAsBoundingBox:
140
+ true` are exported as procedural component bodies instead of loading the
141
+ referenced model. Optional solder-paste detail exports as distinct paste meshes
142
+ when present in `sceneDescription.detail.paste`.
143
+
144
+ ### `PcbAssemblyGltfWriter.write(options?)`
145
+
146
+ Writes faceted assembly meshes as GLTF 2.0 JSON or binary GLB.
147
+
148
+ Options:
149
+
150
+ - `name`: scene name.
151
+ - `meshes`: export meshes with `vertices`, `faces`, optional RGB or RGBA
152
+ `color`, optional `opacity`, and optional board `texture` data URIs.
153
+ - `format`: `gltf` or `glb`.
154
+ - `binary`: optional boolean equivalent to `format: 'glb'`.
155
+ - `includeSceneMetadata`: when `true`, emits a default camera and punctual light
156
+ for third-party GLTF viewers.
157
+
158
+ Returns a GLTF JSON object for `gltf` and a `Uint8Array` for `glb`. RGBA colors
159
+ or opacity values below `1` are emitted as blended GLTF materials. Mesh
160
+ `vertexColors` are exported as `COLOR_0`, and mesh `material` metadata is
161
+ preserved in material extras.
162
+
163
+ ### `new PcbAssemblyModelMeshLoader(options?)`
164
+
165
+ Loads STEP, WRL, STL, OBJ, GLTF, and GLB external models into assembly meshes.
166
+ By default the loader only reads embedded payloads, session files, and provided
167
+ byte buffers. Network loading is opt-in through either an injected `fetch`
168
+ function or `allowNetworkModelFetch: true`. Remote `.gltf` buffer sidecars are
169
+ resolved relative to the `.gltf` URL and use the same fetch, auth-header,
170
+ timeout, and cache policy as the top-level model.
171
+
172
+ Options:
173
+
174
+ - `stepLoader`: custom STEP loader.
175
+ - `fetch`: host-provided fetch function for resolved model URLs.
176
+ - `allowNetworkModelFetch`: use `globalThis.fetch` for `resolvedUrl` or
177
+ `sourceUrl` models when no local payload is present.
178
+ - `authHeaders`: headers forwarded to network model requests.
179
+ - `fetchTimeoutMs`: abort timeout for network model requests.
180
+ - `modelCache`: optional cache map keyed by resolved model URL.
181
+
124
182
  ## Model Archive Export
125
183
 
126
184
  ### `PcbModelArchiveExporter.buildArchive(options?)`
@@ -109,6 +109,39 @@ if (PcbScene3dCircuitJsonAdapter.isCircuitJsonModel(circuitJson)) {
109
109
  }
110
110
  ```
111
111
 
112
+ Hosts that need URL policy control can pass a synchronous `modelUrlResolver`.
113
+ The adapter records the returned metadata on each external model but does not
114
+ fetch the referenced file:
115
+
116
+ ```js
117
+ const sceneDescription = PcbScene3dCircuitJsonAdapter.build(circuitJson, {
118
+ modelUrlResolver(url, context) {
119
+ return {
120
+ resolvedUrl: sameOriginProxyUrl(url),
121
+ sameOrigin: context.format === 'step'
122
+ }
123
+ }
124
+ })
125
+ ```
126
+
127
+ Hosts can also pass `projectBaseUrl` to resolve relative model URLs without a
128
+ custom resolver. Package-style `node_modules/...` paths resolve to the
129
+ project-origin `/package_files/download` endpoint with package and file-path
130
+ query parameters. Package download file paths are normalized under `dist/` when
131
+ the source path does not already include it. Model fetching remains a separate
132
+ host/export decision.
133
+ `boardDrillQuality` accepts `low`, `medium`, or `high` and controls generated
134
+ circle sampling for direct CircuitJSON drill/cutout geometry. When a
135
+ CircuitJSON file has components but no board or panel, `drawFauxBoard: true`
136
+ generates a board from component bounds with a 2 mm margin per side.
137
+ Set `showPcbNotes: true` to render `pcb_note_text`,
138
+ `pcb_fabrication_note_text`, note/fabrication path artwork, and courtyard
139
+ artwork as silkscreen detail. Notes are hidden by default so manufacturing
140
+ annotations do not unexpectedly appear in board previews.
141
+ Set `showPcbPaste: true` to render `pcb_solder_paste` as a grey top/bottom
142
+ surface overlay. Paste is hidden by default so stencil-only manufacturing data
143
+ does not clutter normal board previews.
144
+
112
145
  `isDirectCircuitJsonModel(value)` returns `false` for compatibility arrays that
113
146
  also carry legacy parser fields such as `pcb`, `schematic`, or `bom`. Those
114
147
  arrays continue through the host-provided `buildScene` callback so existing
@@ -120,14 +153,30 @@ CircuitJSON input uses millimeters. The adapter converts all board, component,
120
153
  pad, via, trace, and silkscreen dimensions into mils before handing the scene to
121
154
  the Three.js runtime.
122
155
 
123
- The board center defaults to `{ x: 0, y: 0 }` when omitted. If no `pcb_board`
124
- element is present, the adapter creates a 25.4 mm by 25.4 mm board with a
125
- 1.6 mm thickness so incomplete test or preview models still render.
156
+ The board center defaults to `{ x: 0, y: 0 }` when omitted. If no `pcb_panel`
157
+ or `pcb_board` element is present, the adapter creates a 25.4 mm by 25.4 mm
158
+ board with a 1.6 mm thickness so incomplete test or preview models still
159
+ render. With `drawFauxBoard: true`, that fallback board is instead sized around
160
+ the PCB component bounds with a minimum 10 mm by 10 mm footprint.
161
+
162
+ `cad_component` records with `show_as_bounding_box: true` are exported as
163
+ procedural component bodies. If `size` or `model_size` is present, those
164
+ dimensions drive the generated body; otherwise the paired `pcb_component`
165
+ footprint dimensions are used.
166
+
167
+ When a `cad_component` has no explicit model URL, package footprint metadata
168
+ from `footprinter_string`, `footprint_string`, `footprint`, or `package` can
169
+ generate a richer fallback body. Common dual-row, quad-row, SOT-style,
170
+ through-hole pin-header, passive-chip, pushbutton, testpoint, and TO-style
171
+ package strings add simple lead, pin, or terminal geometry while keeping the
172
+ plain box fallback for unrecognized package text.
126
173
 
127
174
  Layer values resolve as follows:
128
175
 
129
- - `1`, `top`, `front`, and `f.cu` map to the top side.
130
- - `32`, `bottom`, `back`, and `b.cu` map to the bottom side.
176
+ - `1`, `top`, `front`, `f.cu`, and top-side artwork layer names map to the
177
+ top side.
178
+ - `32`, `bottom`, `back`, `b.cu`, and bottom-side artwork layer names map to
179
+ the bottom side.
131
180
  - Unknown layer values default to the top side.
132
181
 
133
182
  ## Supported Elements
@@ -135,18 +184,44 @@ Layer values resolve as follows:
135
184
  The adapter focuses on renderer-ready PCB geometry and ignores unsupported
136
185
  CircuitJSON elements instead of failing the whole scene.
137
186
 
138
- | Element type | Rendered as |
139
- | --------------------- | --------------------------------------------------- |
140
- | `pcb_board` | Board size, thickness, center, and optional outline |
141
- | `source_component` | Component designator and package metadata |
142
- | `pcb_component` | Fallback component body and selection target |
143
- | `pcb_smtpad` | Top or bottom SMT pad copper |
144
- | `pcb_plated_hole` | Through-hole pad copper and drill |
145
- | `pcb_hole` | Non-plated drill opening |
146
- | `pcb_via` | Via copper and drill |
147
- | `pcb_trace` | Routed copper track segments |
148
- | `pcb_silkscreen_line` | Top or bottom silkscreen stroke |
149
- | `pcb_silkscreen_text` | Top or bottom silkscreen text placeholder |
187
+ | Element type | Rendered as |
188
+ | --------------------------- | ------------------------------------------------------------------- |
189
+ | `pcb_panel` | Preferred board/panel size, thickness, center, and optional outline |
190
+ | `pcb_board` | Board size, thickness, center, and optional outline |
191
+ | `pcb_cutout` | Through-board cutout loop |
192
+ | `source_component` | Component designator and package metadata |
193
+ | `pcb_component` | Fallback component body and selection target |
194
+ | `cad_component` | External model URL metadata and placement data |
195
+ | `pcb_smtpad` | Top or bottom SMT pad copper, including pill pads |
196
+ | `pcb_plated_hole` | Through-hole pad copper and drill |
197
+ | `pcb_hole` | Non-plated drill opening |
198
+ | `pcb_via` | Via copper and drill |
199
+ | `pcb_trace` | Routed copper track segments and route-derived surface vias |
200
+ | `pcb_copper_pour` | Top or bottom copper zone polygon |
201
+ | `pcb_solder_paste` | Optional top or bottom paste fill when `showPcbPaste` is enabled |
202
+ | `pcb_silkscreen_line` | Top or bottom silkscreen stroke |
203
+ | `pcb_silkscreen_path` | Top or bottom routed silkscreen strokes |
204
+ | `pcb_silkscreen_circle` | Top or bottom full-circle silkscreen stroke |
205
+ | `pcb_silkscreen_rect` | Top or bottom rectangular silkscreen outline |
206
+ | `pcb_silkscreen_oval` | Top or bottom oval silkscreen outline |
207
+ | `pcb_silkscreen_pill` | Top or bottom pill silkscreen outline |
208
+ | `pcb_silkscreen_text` | Top or bottom silkscreen text placeholder |
209
+ | `pcb_note_text` | Optional top or bottom note text when `showPcbNotes` is enabled |
210
+ | `pcb_note_line` | Optional top or bottom note stroke when `showPcbNotes` is enabled |
211
+ | `pcb_note_path` | Optional top or bottom note path when `showPcbNotes` is enabled |
212
+ | `pcb_note_rect` | Optional top or bottom note outline when `showPcbNotes` is enabled |
213
+ | `pcb_fabrication_note_text` | Optional fabrication text when `showPcbNotes` is enabled |
214
+ | `pcb_fabrication_note_path` | Optional fabrication path when `showPcbNotes` is enabled |
215
+ | `pcb_courtyard_rect` | Optional courtyard rectangle when `showPcbNotes` is enabled |
216
+ | `pcb_courtyard_circle` | Optional courtyard circle when `showPcbNotes` is enabled |
217
+ | `pcb_courtyard_outline` | Optional courtyard outline when `showPcbNotes` is enabled |
218
+
219
+ `cad_component` entries can provide external model URLs and model-local
220
+ placement hints. The adapter maps `model_unit_to_mm_scale_factor`,
221
+ `model_origin_position`, `model_offset`, `model_origin_alignment`,
222
+ `model_object_fit`, `model_board_normal_direction`, and `size` into normalized
223
+ model transforms, and maps `show_as_translucent_model` into export/display
224
+ opacity metadata.
150
225
 
151
226
  Board outlines can be supplied as `pcb_board.outline`, using an array of points:
152
227
 
@@ -162,8 +237,91 @@ Board outlines can be supplied as `pcb_board.outline`, using an array of points:
162
237
  }
163
238
  ```
164
239
 
165
- Traces can be supplied as a `route` array. Each adjacent point pair becomes one
166
- track segment:
240
+ Through-board cutouts can be supplied as polygon, rectangle, or circle
241
+ `pcb_cutout` elements. A `pcb_cutout` with `pcb_board_id` only applies when that
242
+ board is selected, while cutouts without a board target are global. Rectangular
243
+ cutouts support `ccw_rotation`:
244
+
245
+ ```js
246
+ {
247
+ type: 'pcb_cutout',
248
+ shape: 'rect',
249
+ center: { x: 25, y: 15 },
250
+ width: 4,
251
+ height: 2,
252
+ ccw_rotation: 45
253
+ }
254
+ ```
255
+
256
+ Drills can use circular, pill, or rotated pill geometry. `hole_offset_x` and
257
+ `hole_offset_y` move the drill center independently of the pad/copper center:
258
+
259
+ ```js
260
+ {
261
+ type: 'pcb_plated_hole',
262
+ x: 10,
263
+ y: 8,
264
+ hole_shape: 'rotated_pill',
265
+ hole_width: 0.5,
266
+ hole_height: 1.5,
267
+ hole_offset_x: 0.1,
268
+ hole_offset_y: -0.1,
269
+ outer_diameter: 2
270
+ }
271
+ ```
272
+
273
+ SMT pads can use circular, rectangular, rotated rectangular, or pill geometry.
274
+ Pill pads are normalized as rounded rectangles so their copper keeps the
275
+ expected capsule outline:
276
+
277
+ ```js
278
+ {
279
+ type: 'pcb_smtpad',
280
+ layer: 'top',
281
+ shape: 'rotated_pill',
282
+ x: 12,
283
+ y: 8,
284
+ width: 2,
285
+ height: 1,
286
+ ccw_rotation: 30
287
+ }
288
+ ```
289
+
290
+ SMT pads, plated holes, and vias honor `is_covered_with_solder_mask` and
291
+ `covered_with_solder_mask` when present. `true` keeps the copper under solder
292
+ mask, while `false` exposes the copper on the applicable board side. For vias,
293
+ covered values map to tenting metadata on both sides.
294
+
295
+ Copper pours can use rectangular, polygon, or B-Rep geometry. Rectangular pours
296
+ support `rotation` or `ccw_rotation`; polygon and B-Rep point coordinates are
297
+ converted from millimeters to mils. `covered_with_solder_mask: true` renders the
298
+ zone under solder mask, while false or omitted values expose the copper:
299
+
300
+ ```js
301
+ {
302
+ type: 'pcb_copper_pour',
303
+ layer: 'top',
304
+ shape: 'rect',
305
+ center: { x: 25, y: 15 },
306
+ width: 8,
307
+ height: 5,
308
+ rotation: 45,
309
+ covered_with_solder_mask: false
310
+ }
311
+ ```
312
+
313
+ Silkscreen text uses `anchor_position` when available, falling back to `x` and
314
+ `y`. Common `anchor_alignment` values such as `center`, `bottom_left`, or
315
+ `top_right` are normalized into horizontal and vertical alignment metadata for
316
+ stroke text rendering.
317
+
318
+ Component model metadata can be supplied on `cad_component` elements with
319
+ `model_3mf_url`, `model_step_url`, `model_wrl_url`, `model_glb_url`,
320
+ `model_gltf_url`, `model_stl_url`, or `model_obj_url`. The adapter emits
321
+ external placement metadata for the host runtime or export pipeline to resolve.
322
+
323
+ Traces can be supplied as a `route` array. Each adjacent wire point pair becomes
324
+ one track segment:
167
325
 
168
326
  ```js
169
327
  {
@@ -178,6 +336,31 @@ track segment:
178
336
  }
179
337
  ```
180
338
 
339
+ Route entries with `route_type: 'via'` produce via primitives when their
340
+ `from_layer`, `to_layer`, or `layer` touches the top or bottom surface. Adjacent
341
+ surface wire segments remain visible through those vias. Inner-only vias and
342
+ inner-only wire segments are ignored by the surface-copper view. If a route via
343
+ omits `hole_diameter`, `via_hole_diameter`, or `drill_diameter`, the drill
344
+ diameter defaults to half of `via_diameter`.
345
+
346
+ ```js
347
+ {
348
+ type: 'pcb_trace',
349
+ route: [
350
+ { route_type: 'wire', x: 5, y: 5, width: 0.2, layer: 'top' },
351
+ {
352
+ route_type: 'via',
353
+ x: 8,
354
+ y: 5,
355
+ from_layer: 'top',
356
+ to_layer: 'bottom',
357
+ via_diameter: 0.4
358
+ },
359
+ { route_type: 'wire', x: 8, y: 10, width: 0.2, layer: '32' }
360
+ ]
361
+ }
362
+ ```
363
+
181
364
  ## Diagnostics
182
365
 
183
366
  Malformed CircuitJSON input is rejected by `circuitjson-toolkit` before render
@@ -185,6 +368,7 @@ model conversion. Use `PcbScene3dCircuitJsonAdapter.isCircuitJsonModel(value)`
185
368
  for a cheap guard when accepting untrusted JSON from users, and catch conversion
186
369
  errors around `build(value)` when you need to show a custom diagnostic.
187
370
 
188
- The viewer does not fetch external assets for CircuitJSON input. STEP and WRL
189
- model matching remains the responsibility of source-specific toolkits or host
190
- applications that create normalized scene descriptions.
371
+ The viewer does not fetch external assets for CircuitJSON input by itself.
372
+ Model URL matching, same-origin checks, proxying, and file loading remain the
373
+ responsibility of source-specific toolkits or host applications that create or
374
+ post-process normalized scene descriptions.
@@ -35,6 +35,10 @@ toolkits are responsible for creating this data.
35
35
  silkscreen: {
36
36
  top: {},
37
37
  bottom: {}
38
+ },
39
+ paste: {
40
+ top: {},
41
+ bottom: {}
38
42
  }
39
43
  }
40
44
  }
@@ -66,7 +70,7 @@ Components describe fallback package bodies and selection metadata:
66
70
 
67
71
  ## External Placements
68
72
 
69
- External placements describe STEP or WRL model instances:
73
+ External placements describe STEP, WRL, GLB, GLTF, STL, or OBJ model instances:
70
74
 
71
75
  ```js
72
76
  {
@@ -78,18 +82,63 @@ External placements describe STEP or WRL model instances:
78
82
  bodyRotationDeg: 0,
79
83
  modelTransform: {
80
84
  rotationDeg: { x: 90, y: 0, z: 0 },
81
- dzMil: 0
85
+ offsetMil: { x: 0, y: 0, z: 0 },
86
+ scale: { x: 1, y: 1, z: 1 },
87
+ originPositionMil: { x: 0, y: 0, z: 0 },
88
+ originAlignment: 'center_of_component_on_board_surface',
89
+ objectFit: 'fill_bounds',
90
+ boardNormalDirection: 'z+',
91
+ targetSizeMil: { x: 200, y: 300, z: 60 }
82
92
  },
93
+ bodyOpacity: 0.5,
83
94
  externalModel: {
84
95
  origin: 'session',
85
96
  name: 'soic-8.step',
86
97
  relativePath: 'packages/soic-8.step',
87
98
  format: 'step',
99
+ sourceUrl: '/models/soic-8.step',
100
+ resolvedUrl: 'https://assets.example.invalid/models/soic-8.step',
88
101
  file: File
89
102
  }
90
103
  }
91
104
  ```
92
105
 
106
+ OBJ models can carry sidecar material libraries in `resources`, `relatedFiles`,
107
+ `assets`, or similar metadata collections. OBJ diffuse, ambient, specular,
108
+ shininess, alpha, and vertex colors are preserved in the parsed mesh metadata.
109
+ GLTF/GLB material alpha, mesh opacity, and `COLOR_0` vertex colors are
110
+ preserved in imported and exported GLTF/GLB materials and primitives.
111
+ GLTF/GLB import consumes triangle primitives and ignores unsupported primitive
112
+ modes such as points or lines. Remote `.gltf` files can reference external
113
+ `buffers[].uri` sidecars; when URL-backed model loading is enabled, the loader
114
+ resolves those sidecars relative to the `.gltf` URL and fetches them with the
115
+ same cache, timeout, and auth-header policy.
116
+
117
+ Resolved model URLs are not fetched by default. Hosts that want URL-backed model
118
+ loading must provide an explicit fetch policy through `PcbAssemblyModelMeshLoader`
119
+ or a higher-level export service. Use `authHeaders`, `fetchTimeoutMs`, and a
120
+ caller-owned `modelCache` when remote model requests are enabled.
121
+
122
+ When `projectBaseUrl` is provided to the CircuitJSON adapter, package-style
123
+ model paths such as `node_modules/package-name/path/to/model.step` are resolved
124
+ to `/package_files/download` on the project origin with
125
+ `package_name_with_version` and `file_path` query parameters. Package download
126
+ file paths are normalized under `dist/` unless they already start there. This
127
+ only records a resolved URL; fetching still requires an explicit loader/export
128
+ fetch policy.
129
+
130
+ CAD placements can request procedural bounding-box output with
131
+ `show_as_bounding_box: true`. The adapter marks those placements with
132
+ `renderAsBoundingBox: true`, copies `size`/`model_size` into fallback body
133
+ dimensions when present, and the assembly geometry builder skips external model
134
+ loading for that placement.
135
+
136
+ When package footprint text is available, fallback bodies can derive simple
137
+ package-specific geometry for passive chips, dual-row and quad-row ICs,
138
+ SOT-style packages, pin headers, pushbuttons, testpoints, and TO-style
139
+ through-hole packages. Testpoints and radial capacitors use round fallback
140
+ bodies in both runtime rendering and assembly export.
141
+
93
142
  Embedded STEP models can use:
94
143
 
95
144
  ```js
@@ -107,11 +156,24 @@ The runtime expects pre-normalized primitive lists for:
107
156
 
108
157
  - pads and vias with drill and copper dimensions;
109
158
  - tracks and arcs with layer metadata;
110
- - fills and polygons with point loops;
159
+ - fills and polygons with point loops or B-Rep ring metadata;
111
160
  - silkscreen tracks, arcs, fills, and texts;
161
+ - optional solder-paste fills in `detail.paste`;
112
162
  - copper text primitives.
113
163
 
114
164
  The viewer does not infer source-file semantics. When a scene needs
115
165
  format-specific layer mapping, solder-mask interpretation, text layout, or
116
166
  model matching, the source toolkit should encode those decisions in the scene
117
167
  description.
168
+
169
+ Through-hole pads can describe offset or slotted drills with `holeOffsetX`,
170
+ `holeOffsetY`, `holeSlotLength`, and `holeRotation`. Board substrate export uses
171
+ `detail.drillQuality` values of `low`, `medium`, or `high` to choose circular
172
+ drill sampling density.
173
+
174
+ Rounded SMT pads set `hasRoundedRect`, the side-specific
175
+ `roundedRectShapeTop`/`roundedRectShapeBottom`, and
176
+ `cornerRadiusTop`/`cornerRadiusBottom` as a percent of the shortest copper side.
177
+ Route-derived vias use the same `detail.vias` shape as standalone vias, and
178
+ surface route segments use `layerId: 1` for top copper or `layerId: 32` for
179
+ bottom copper.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pcb-scene3d-viewer",
3
- "version": "1.1.22",
3
+ "version": "1.1.44",
4
4
  "description": "Reusable Three.js PCB 3D scene viewer for normalized ECAD and CircuitJSON scene descriptions",
5
5
  "keywords": [
6
6
  "pcb",
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@sunbox/occt-import-js": "^0.0.25",
55
- "circuitjson-toolkit": "^1.0.1",
55
+ "circuitjson-toolkit": "^1.0.10",
56
56
  "earcut": "^3.0.2",
57
57
  "fflate": "^0.8.2",
58
58
  "three": "^0.183.2"
@@ -8,12 +8,12 @@ scene descriptions.
8
8
  - Three.js runtime orchestration for PCB scenes.
9
9
  - Board, copper, via, drill, silkscreen, solder-mask, and fallback package mesh
10
10
  factories.
11
- - STEP and WRL model loading and placement.
11
+ - STEP, WRL, GLB, GLTF, STL, and OBJ model loading and placement.
12
12
  - Camera presets, view compensation, selection styling, picking, and visibility
13
13
  toggles.
14
14
  - Optional DOM shell/controller helpers for hosts that want ready-made scene
15
15
  chrome.
16
- - ZIP export of resolved STEP and WRL model assets.
16
+ - ZIP export of resolved component model assets.
17
17
  - CSS for the optional scene shell.
18
18
 
19
19
  ## Out of Scope