pcb-scene3d-viewer 1.1.21 → 1.1.31

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 (55) hide show
  1. package/README.md +3 -2
  2. package/docs/api.md +27 -1
  3. package/docs/circuitjson.md +63 -18
  4. package/docs/model-format.md +13 -2
  5. package/package.json +1 -1
  6. package/spec/library-scope.md +2 -2
  7. package/src/PcbAssemblyBoardSubstrateBuilder.mjs +25 -5
  8. package/src/PcbAssemblyComponentMeshBuilder.mjs +762 -0
  9. package/src/PcbAssemblyFillGeometryResolver.mjs +579 -0
  10. package/src/PcbAssemblyFillRingNormalizer.mjs +209 -0
  11. package/src/PcbAssemblyGeometryBuilder.mjs +41 -301
  12. package/src/PcbAssemblyGltfModelMeshParser.mjs +912 -0
  13. package/src/PcbAssemblyGltfValidator.mjs +460 -0
  14. package/src/PcbAssemblyGltfWriter.mjs +801 -0
  15. package/src/PcbAssemblyMeshUtils.mjs +117 -0
  16. package/src/PcbAssemblyModelMeshLoader.mjs +18 -0
  17. package/src/PcbAssemblyPadMeshBuilder.mjs +394 -0
  18. package/src/PcbAssemblyStepWriter.mjs +24 -2
  19. package/src/PcbAssemblyTextModelMeshParser.mjs +602 -0
  20. package/src/PcbModelArchiveExporter.mjs +521 -7
  21. package/src/PcbScene3dCircuitJsonAdapter.mjs +409 -7
  22. package/src/PcbScene3dCircuitJsonModelTransform.mjs +232 -0
  23. package/src/PcbScene3dCompanionBasePlacementAdjuster.mjs +242 -0
  24. package/src/PcbScene3dComponentVisibility.mjs +100 -5
  25. package/src/PcbScene3dController.mjs +25 -55
  26. package/src/PcbScene3dCopperDetailFilter.mjs +86 -9
  27. package/src/PcbScene3dCopperDetailGroupBuilder.mjs +186 -15
  28. package/src/PcbScene3dCopperDrillCutoutBuilder.mjs +258 -0
  29. package/src/PcbScene3dCopperFactory.mjs +99 -85
  30. package/src/PcbScene3dCopperFillMeshBuilder.mjs +393 -0
  31. package/src/PcbScene3dCopperLayerFilter.mjs +32 -3
  32. package/src/PcbScene3dCutoutGeometryFilter.mjs +17 -14
  33. package/src/PcbScene3dExternalCompanionFallback.mjs +202 -0
  34. package/src/PcbScene3dExternalModelCenteringPolicy.mjs +21 -0
  35. package/src/PcbScene3dExternalModelOpacity.mjs +51 -0
  36. package/src/PcbScene3dExternalModelPlacementRepair.mjs +5 -2
  37. package/src/PcbScene3dExternalModelSourceOriginPolicy.mjs +41 -0
  38. package/src/PcbScene3dExternalModels.mjs +16 -7
  39. package/src/PcbScene3dFallbackBodyFactory.mjs +105 -0
  40. package/src/PcbScene3dFallbackVisibility.mjs +58 -1
  41. package/src/PcbScene3dMaskCoveredCopperSideGroupBuilder.mjs +68 -0
  42. package/src/PcbScene3dPadFactory.mjs +35 -2
  43. package/src/PcbScene3dRenderGroupVisibility.mjs +8 -1
  44. package/src/PcbScene3dRuntime.mjs +94 -100
  45. package/src/PcbScene3dRuntimeHelpers.mjs +39 -0
  46. package/src/PcbScene3dSelectionIndexBuilder.mjs +87 -0
  47. package/src/PcbScene3dSelectionInspectorRenderer.mjs +50 -11
  48. package/src/PcbScene3dSelectionMarkerFactory.mjs +333 -0
  49. package/src/PcbScene3dSelectionMarkerOverlay.mjs +70 -0
  50. package/src/PcbScene3dSelectionStyler.mjs +52 -2
  51. package/src/PcbScene3dStaticBodyFactory.mjs +263 -0
  52. package/src/PcbScene3dText.mjs +1 -0
  53. package/src/PcbScene3dTransparentMeshSplitter.mjs +623 -0
  54. package/src/PcbScene3dViaFactory.mjs +27 -7
  55. package/src/scene3d.mjs +3 -0
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,9 @@ 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.
67
69
 
68
70
  `PcbScene3dController` and `PcbScene3dRuntime` call this adapter automatically
69
71
  when they receive direct CircuitJSON input. See
@@ -121,6 +123,30 @@ worker.postMessage({
121
123
  Workers respond with `scene3d:success` and `sceneDescription`, or
122
124
  `scene3d:error` and `message`.
123
125
 
126
+ ## Assembly Geometry Export
127
+
128
+ ### `PcbAssemblyGeometryBuilder.build(sceneDescription, options?)`
129
+
130
+ Builds export meshes from a prepared scene description. `options.modelMeshLoader`
131
+ can provide external model meshes, `options.includeModels: false` skips external
132
+ model loading, and `options.renderFallbackBodies: false` disables procedural
133
+ component bodies for unresolved models.
134
+
135
+ ### `PcbAssemblyGltfWriter.write(options?)`
136
+
137
+ Writes faceted assembly meshes as GLTF 2.0 JSON or binary GLB.
138
+
139
+ Options:
140
+
141
+ - `name`: scene name.
142
+ - `meshes`: export meshes with `vertices`, `faces`, optional RGB or RGBA
143
+ `color`, optional `opacity`, and optional board `texture` data URIs.
144
+ - `format`: `gltf` or `glb`.
145
+ - `binary`: optional boolean equivalent to `format: 'glb'`.
146
+
147
+ Returns a GLTF JSON object for `gltf` and a `Uint8Array` for `glb`. RGBA colors
148
+ or opacity values below `1` are emitted as blended GLTF materials.
149
+
124
150
  ## Model Archive Export
125
151
 
126
152
  ### `PcbModelArchiveExporter.buildArchive(options?)`
@@ -109,6 +109,21 @@ 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
+
112
127
  `isDirectCircuitJsonModel(value)` returns `false` for compatibility arrays that
113
128
  also carry legacy parser fields such as `pcb`, `schematic`, or `bom`. Those
114
129
  arrays continue through the host-provided `buildScene` callback so existing
@@ -120,9 +135,10 @@ CircuitJSON input uses millimeters. The adapter converts all board, component,
120
135
  pad, via, trace, and silkscreen dimensions into mils before handing the scene to
121
136
  the Three.js runtime.
122
137
 
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.
138
+ The board center defaults to `{ x: 0, y: 0 }` when omitted. If no `pcb_panel`
139
+ or `pcb_board` element is present, the adapter creates a 25.4 mm by 25.4 mm
140
+ board with a 1.6 mm thickness so incomplete test or preview models still
141
+ render.
126
142
 
127
143
  Layer values resolve as follows:
128
144
 
@@ -135,18 +151,28 @@ Layer values resolve as follows:
135
151
  The adapter focuses on renderer-ready PCB geometry and ignores unsupported
136
152
  CircuitJSON elements instead of failing the whole scene.
137
153
 
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 |
154
+ | Element type | Rendered as |
155
+ | --------------------- | ------------------------------------------------------------------- |
156
+ | `pcb_panel` | Preferred board/panel size, thickness, center, and optional outline |
157
+ | `pcb_board` | Board size, thickness, center, and optional outline |
158
+ | `pcb_cutout` | Through-board cutout loop |
159
+ | `source_component` | Component designator and package metadata |
160
+ | `pcb_component` | Fallback component body and selection target |
161
+ | `cad_component` | External model URL metadata and placement data |
162
+ | `pcb_smtpad` | Top or bottom SMT pad copper |
163
+ | `pcb_plated_hole` | Through-hole pad copper and drill |
164
+ | `pcb_hole` | Non-plated drill opening |
165
+ | `pcb_via` | Via copper and drill |
166
+ | `pcb_trace` | Routed copper track segments |
167
+ | `pcb_silkscreen_line` | Top or bottom silkscreen stroke |
168
+ | `pcb_silkscreen_text` | Top or bottom silkscreen text placeholder |
169
+
170
+ `cad_component` entries can provide external model URLs and model-local
171
+ placement hints. The adapter maps `model_unit_to_mm_scale_factor`,
172
+ `model_origin_position`, `model_offset`, `model_origin_alignment`,
173
+ `model_object_fit`, `model_board_normal_direction`, and `size` into normalized
174
+ model transforms, and maps `show_as_translucent_model` into export/display
175
+ opacity metadata.
150
176
 
151
177
  Board outlines can be supplied as `pcb_board.outline`, using an array of points:
152
178
 
@@ -162,6 +188,24 @@ Board outlines can be supplied as `pcb_board.outline`, using an array of points:
162
188
  }
163
189
  ```
164
190
 
191
+ Through-board cutouts can be supplied as polygon, rectangle, or circle
192
+ `pcb_cutout` elements:
193
+
194
+ ```js
195
+ {
196
+ type: 'pcb_cutout',
197
+ shape: 'rect',
198
+ center: { x: 25, y: 15 },
199
+ width: 4,
200
+ height: 2
201
+ }
202
+ ```
203
+
204
+ Component model metadata can be supplied on `cad_component` elements with
205
+ `model_step_url`, `model_wrl_url`, `model_glb_url`, `model_gltf_url`,
206
+ `model_stl_url`, or `model_obj_url`. The adapter emits external placement
207
+ metadata for the host runtime or export pipeline to resolve.
208
+
165
209
  Traces can be supplied as a `route` array. Each adjacent point pair becomes one
166
210
  track segment:
167
211
 
@@ -185,6 +229,7 @@ model conversion. Use `PcbScene3dCircuitJsonAdapter.isCircuitJsonModel(value)`
185
229
  for a cheap guard when accepting untrusted JSON from users, and catch conversion
186
230
  errors around `build(value)` when you need to show a custom diagnostic.
187
231
 
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.
232
+ The viewer does not fetch external assets for CircuitJSON input by itself.
233
+ Model URL matching, same-origin checks, proxying, and file loading remain the
234
+ responsibility of source-specific toolkits or host applications that create or
235
+ post-process normalized scene descriptions.
@@ -66,7 +66,7 @@ Components describe fallback package bodies and selection metadata:
66
66
 
67
67
  ## External Placements
68
68
 
69
- External placements describe STEP or WRL model instances:
69
+ External placements describe STEP, WRL, GLB, GLTF, STL, or OBJ model instances:
70
70
 
71
71
  ```js
72
72
  {
@@ -78,8 +78,15 @@ External placements describe STEP or WRL model instances:
78
78
  bodyRotationDeg: 0,
79
79
  modelTransform: {
80
80
  rotationDeg: { x: 90, y: 0, z: 0 },
81
- dzMil: 0
81
+ offsetMil: { x: 0, y: 0, z: 0 },
82
+ scale: { x: 1, y: 1, z: 1 },
83
+ originPositionMil: { x: 0, y: 0, z: 0 },
84
+ originAlignment: 'center_of_component_on_board_surface',
85
+ objectFit: 'fill_bounds',
86
+ boardNormalDirection: 'z+',
87
+ targetSizeMil: { x: 200, y: 300, z: 60 }
82
88
  },
89
+ bodyOpacity: 0.5,
83
90
  externalModel: {
84
91
  origin: 'session',
85
92
  name: 'soic-8.step',
@@ -90,6 +97,10 @@ External placements describe STEP or WRL model instances:
90
97
  }
91
98
  ```
92
99
 
100
+ OBJ models can carry sidecar material libraries in `resources`, `relatedFiles`,
101
+ `assets`, or similar metadata collections. GLTF/GLB material alpha and mesh
102
+ opacity are preserved in exported GLTF/GLB materials.
103
+
93
104
  Embedded STEP models can use:
94
105
 
95
106
  ```js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pcb-scene3d-viewer",
3
- "version": "1.1.21",
3
+ "version": "1.1.31",
4
4
  "description": "Reusable Three.js PCB 3D scene viewer for normalized ECAD and CircuitJSON scene descriptions",
5
5
  "keywords": [
6
6
  "pcb",
@@ -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
@@ -145,13 +145,20 @@ export class PcbAssemblyBoardSubstrateBuilder {
145
145
  * @returns {number[][][]}
146
146
  */
147
147
  static #boardHoleLoops(sceneDescription, outer) {
148
- const contourLoops =
149
- PcbAssemblyBoardSubstrateBuilder.#drillCutoutLoops(sceneDescription)
150
- const rawLoops = contourLoops.length
151
- ? contourLoops
152
- : PcbAssemblyBoardSubstrateBuilder.#primitiveHoleLoops(
148
+ const explicitLoops =
149
+ PcbAssemblyBoardSubstrateBuilder.#explicitCutoutLoops(
150
+ sceneDescription
151
+ )
152
+ const primitiveLoops =
153
+ PcbAssemblyBoardSubstrateBuilder.#primitiveHoleLoops(
154
+ sceneDescription
155
+ )
156
+ const fallbackLoops = primitiveLoops.length
157
+ ? primitiveLoops
158
+ : PcbAssemblyBoardSubstrateBuilder.#drillCutoutLoops(
153
159
  sceneDescription
154
160
  )
161
+ const rawLoops = [...explicitLoops, ...fallbackLoops]
155
162
  const seen = new Set()
156
163
  const holes = []
157
164
 
@@ -187,6 +194,19 @@ export class PcbAssemblyBoardSubstrateBuilder {
187
194
  return holes
188
195
  }
189
196
 
197
+ /**
198
+ * Reads explicit board cutout contours from the scene board metadata.
199
+ * @param {object} sceneDescription Prepared scene description.
200
+ * @returns {Array<Array<object | number[]>>}
201
+ */
202
+ static #explicitCutoutLoops(sceneDescription) {
203
+ return PcbAssemblyBoardSubstrateBuilder.#array(
204
+ sceneDescription?.board?.cutouts
205
+ )
206
+ .map((cutout) => cutout?.points || cutout?.vertices || cutout)
207
+ .filter((loop) => Array.isArray(loop))
208
+ }
209
+
190
210
  /**
191
211
  * Reads existing drill cutout contours from scene silkscreen details.
192
212
  * @param {object} sceneDescription Prepared scene description.