@vcad/mcp 0.9.4-main.13 → 0.9.4-main.15

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/README.md CHANGED
@@ -6,4 +6,4 @@ vcad's MCP server as a self-contained bundle (server + BRep kernel WASM).
6
6
  { "mcpServers": { "vcad": { "command": "npx", "args": ["-y", "@vcad/mcp"] } } }
7
7
  ```
8
8
 
9
- Built from 70552964e3760fb5b103235917b00364f6d45763 at 2026-07-24T16:29:07.170Z. Source: https://github.com/ecto/vcad
9
+ Built from ba0bbea017e3e720ec8796167b6824f3cdf235cf at 2026-07-24T17:18:07.764Z. Source: https://github.com/ecto/vcad
package/index.mjs CHANGED
@@ -68,8 +68,13 @@ __export(vcad_kernel_wasm_exports, {
68
68
  atoms_minimize: () => atoms_minimize,
69
69
  atoms_parse_xyz: () => atoms_parse_xyz,
70
70
  atoms_write_xyz: () => atoms_write_xyz,
71
+ buildCalibrationReportJson: () => buildCalibrationReportJson,
72
+ buildGlbBytes: () => buildGlbBytes,
71
73
  buildPart: () => buildPart,
74
+ buildStlBytes: () => buildStlBytes,
72
75
  build_chat_system_prompt: () => build_chat_system_prompt,
76
+ calibrationDefaultTolerance: () => calibrationDefaultTolerance,
77
+ calibrationFingerprintDocument: () => calibrationFingerprintDocument,
73
78
  camDropCutter: () => camDropCutter,
74
79
  camExportGcode: () => camExportGcode,
75
80
  camExportLinuxCnc: () => camExportLinuxCnc,
@@ -147,6 +152,7 @@ __export(vcad_kernel_wasm_exports, {
147
152
  emSimulate: () => emSimulate,
148
153
  estimatePrintCost: () => estimatePrintCost,
149
154
  estimate_cost_for_process: () => estimate_cost_for_process,
155
+ eulerXyzDegToQuat: () => eulerXyzDegToQuat,
150
156
  evalVcadSource: () => evalVcadSource,
151
157
  evaluateDocument: () => evaluateDocument,
152
158
  evaluateSheetMetalChain: () => evaluateSheetMetalChain,
@@ -155,6 +161,9 @@ __export(vcad_kernel_wasm_exports, {
155
161
  exportKicadProject: () => exportKicadProject,
156
162
  exportKicadSch: () => exportKicadSch,
157
163
  exportProjectedViewToDxf: () => exportProjectedViewToDxf,
164
+ exprEvalAst: () => exprEvalAst,
165
+ exprEvaluate: () => exprEvaluate,
166
+ exprParse: () => exprParse,
158
167
  feaAnalyzeMesh: () => feaAnalyzeMesh,
159
168
  generate3mf: () => generate3mf,
160
169
  generate3mfWithGcode: () => generate3mfWithGcode,
@@ -184,6 +193,7 @@ __export(vcad_kernel_wasm_exports, {
184
193
  nestSheetMetalParts: () => nestSheetMetalParts,
185
194
  nestedSheetMetalDxf: () => nestedSheetMetalDxf,
186
195
  neutronicsSimulate: () => neutronicsSimulate,
196
+ noteToHz: () => noteToHz,
187
197
  offsetSectionMesh: () => offsetSectionMesh,
188
198
  op_chamfer: () => op_chamfer,
189
199
  op_circular_pattern: () => op_circular_pattern,
@@ -218,11 +228,14 @@ __export(vcad_kernel_wasm_exports, {
218
228
  render_svg_view: () => render_svg_view,
219
229
  render_svg_view_highlight: () => render_svg_view_highlight,
220
230
  render_svg_view_section: () => render_svg_view_section,
231
+ resolveDocumentJson: () => resolveDocumentJson,
232
+ resolveParametersJson: () => resolveParametersJson,
221
233
  sample_timeline_sequence: () => sample_timeline_sequence,
222
234
  sample_timeline_track: () => sample_timeline_track,
223
235
  sectionMesh: () => sectionMesh,
224
236
  sheetMetalFoldedStep: () => sheetMetalFoldedStep,
225
237
  sheetMetalSequence: () => sheetMetalSequence,
238
+ simulateStrikeKernel: () => simulateStrikeKernel,
226
239
  sketchCircleSegments: () => sketchCircleSegments,
227
240
  sketchHitTest: () => sketchHitTest,
228
241
  sketchPlaneBasis: () => sketchPlaneBasis,
@@ -428,6 +441,46 @@ function atoms_write_xyz(molecule_json) {
428
441
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
429
442
  }
430
443
  }
444
+ function buildCalibrationReportJson(prediction_json, measurements_json, options_json) {
445
+ let deferred5_0;
446
+ let deferred5_1;
447
+ try {
448
+ const ptr0 = passStringToWasm0(prediction_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
449
+ const len0 = WASM_VECTOR_LEN;
450
+ const ptr1 = passStringToWasm0(measurements_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
451
+ const len1 = WASM_VECTOR_LEN;
452
+ const ptr2 = passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
453
+ const len2 = WASM_VECTOR_LEN;
454
+ const ret = wasm.buildCalibrationReportJson(ptr0, len0, ptr1, len1, ptr2, len2);
455
+ var ptr4 = ret[0];
456
+ var len4 = ret[1];
457
+ if (ret[3]) {
458
+ ptr4 = 0;
459
+ len4 = 0;
460
+ throw takeFromExternrefTable0(ret[2]);
461
+ }
462
+ deferred5_0 = ptr4;
463
+ deferred5_1 = len4;
464
+ return getStringFromWasm0(ptr4, len4);
465
+ } finally {
466
+ wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
467
+ }
468
+ }
469
+ function buildGlbBytes(spec_json, f32_data, u32_data) {
470
+ const ptr0 = passStringToWasm0(spec_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
471
+ const len0 = WASM_VECTOR_LEN;
472
+ const ptr1 = passArrayF32ToWasm0(f32_data, wasm.__wbindgen_malloc);
473
+ const len1 = WASM_VECTOR_LEN;
474
+ const ptr2 = passArray32ToWasm0(u32_data, wasm.__wbindgen_malloc);
475
+ const len2 = WASM_VECTOR_LEN;
476
+ const ret = wasm.buildGlbBytes(ptr0, len0, ptr1, len1, ptr2, len2);
477
+ if (ret[3]) {
478
+ throw takeFromExternrefTable0(ret[2]);
479
+ }
480
+ var v4 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
481
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
482
+ return v4;
483
+ }
431
484
  function buildPart(path, params_json) {
432
485
  let deferred4_0;
433
486
  let deferred4_1;
@@ -451,6 +504,21 @@ function buildPart(path, params_json) {
451
504
  wasm.__wbindgen_free(deferred4_0, deferred4_1, 1);
452
505
  }
453
506
  }
507
+ function buildStlBytes(spec_json, f32_data, u32_data) {
508
+ const ptr0 = passStringToWasm0(spec_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
509
+ const len0 = WASM_VECTOR_LEN;
510
+ const ptr1 = passArrayF32ToWasm0(f32_data, wasm.__wbindgen_malloc);
511
+ const len1 = WASM_VECTOR_LEN;
512
+ const ptr2 = passArray32ToWasm0(u32_data, wasm.__wbindgen_malloc);
513
+ const len2 = WASM_VECTOR_LEN;
514
+ const ret = wasm.buildStlBytes(ptr0, len0, ptr1, len1, ptr2, len2);
515
+ if (ret[3]) {
516
+ throw takeFromExternrefTable0(ret[2]);
517
+ }
518
+ var v4 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
519
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
520
+ return v4;
521
+ }
454
522
  function build_chat_system_prompt(parts_json, selection_json) {
455
523
  let deferred3_0;
456
524
  let deferred3_1;
@@ -467,6 +535,36 @@ function build_chat_system_prompt(parts_json, selection_json) {
467
535
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
468
536
  }
469
537
  }
538
+ function calibrationDefaultTolerance(kind, predicted) {
539
+ const ptr0 = passStringToWasm0(kind, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
540
+ const len0 = WASM_VECTOR_LEN;
541
+ const ret = wasm.calibrationDefaultTolerance(ptr0, len0, predicted);
542
+ if (ret[2]) {
543
+ throw takeFromExternrefTable0(ret[1]);
544
+ }
545
+ return ret[0];
546
+ }
547
+ function calibrationFingerprintDocument(doc_json) {
548
+ let deferred3_0;
549
+ let deferred3_1;
550
+ try {
551
+ const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
552
+ const len0 = WASM_VECTOR_LEN;
553
+ const ret = wasm.calibrationFingerprintDocument(ptr0, len0);
554
+ var ptr2 = ret[0];
555
+ var len2 = ret[1];
556
+ if (ret[3]) {
557
+ ptr2 = 0;
558
+ len2 = 0;
559
+ throw takeFromExternrefTable0(ret[2]);
560
+ }
561
+ deferred3_0 = ptr2;
562
+ deferred3_1 = len2;
563
+ return getStringFromWasm0(ptr2, len2);
564
+ } finally {
565
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
566
+ }
567
+ }
470
568
  function camDropCutter(vertices_json, indices_json, tool_json, bounds_json, resolution) {
471
569
  let deferred6_0;
472
570
  let deferred6_1;
@@ -1441,6 +1539,12 @@ function estimate_cost_for_process(process3, material_name, part_volume_mm3, sto
1441
1539
  }
1442
1540
  return takeFromExternrefTable0(ret[0]);
1443
1541
  }
1542
+ function eulerXyzDegToQuat(x_deg, y_deg, z_deg) {
1543
+ const ret = wasm.eulerXyzDegToQuat(x_deg, y_deg, z_deg);
1544
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
1545
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
1546
+ return v1;
1547
+ }
1444
1548
  function evalVcadSource(source) {
1445
1549
  const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1446
1550
  const len0 = WASM_VECTOR_LEN;
@@ -1548,6 +1652,31 @@ function exportProjectedViewToDxf(view_json) {
1548
1652
  wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
1549
1653
  return v2;
1550
1654
  }
1655
+ function exprEvalAst(ast, env) {
1656
+ const ret = wasm.exprEvalAst(ast, env);
1657
+ if (ret[2]) {
1658
+ throw takeFromExternrefTable0(ret[1]);
1659
+ }
1660
+ return ret[0];
1661
+ }
1662
+ function exprEvaluate(src, env) {
1663
+ const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1664
+ const len0 = WASM_VECTOR_LEN;
1665
+ const ret = wasm.exprEvaluate(ptr0, len0, env);
1666
+ if (ret[2]) {
1667
+ throw takeFromExternrefTable0(ret[1]);
1668
+ }
1669
+ return ret[0];
1670
+ }
1671
+ function exprParse(src) {
1672
+ const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1673
+ const len0 = WASM_VECTOR_LEN;
1674
+ const ret = wasm.exprParse(ptr0, len0);
1675
+ if (ret[2]) {
1676
+ throw takeFromExternrefTable0(ret[1]);
1677
+ }
1678
+ return takeFromExternrefTable0(ret[0]);
1679
+ }
1551
1680
  function feaAnalyzeMesh(spec_json, options_json, positions, indices) {
1552
1681
  const ptr0 = passStringToWasm0(spec_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1553
1682
  const len0 = WASM_VECTOR_LEN;
@@ -1856,6 +1985,15 @@ function neutronicsSimulate(spec_json, params_json) {
1856
1985
  }
1857
1986
  return takeFromExternrefTable0(ret[0]);
1858
1987
  }
1988
+ function noteToHz(note) {
1989
+ const ptr0 = passStringToWasm0(note, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1990
+ const len0 = WASM_VECTOR_LEN;
1991
+ const ret = wasm.noteToHz(ptr0, len0);
1992
+ if (ret[2]) {
1993
+ throw takeFromExternrefTable0(ret[1]);
1994
+ }
1995
+ return ret[0];
1996
+ }
1859
1997
  function offsetSectionMesh(mesh_js, plane_json, hatch_json) {
1860
1998
  const ptr0 = passStringToWasm0(plane_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1861
1999
  const len0 = WASM_VECTOR_LEN;
@@ -2344,6 +2482,48 @@ function render_svg_view_section(vcad_json, scale, view, section) {
2344
2482
  wasm.__wbindgen_free(deferred5_0, deferred5_1, 1);
2345
2483
  }
2346
2484
  }
2485
+ function resolveDocumentJson(doc_json) {
2486
+ let deferred3_0;
2487
+ let deferred3_1;
2488
+ try {
2489
+ const ptr0 = passStringToWasm0(doc_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2490
+ const len0 = WASM_VECTOR_LEN;
2491
+ const ret = wasm.resolveDocumentJson(ptr0, len0);
2492
+ var ptr2 = ret[0];
2493
+ var len2 = ret[1];
2494
+ if (ret[3]) {
2495
+ ptr2 = 0;
2496
+ len2 = 0;
2497
+ throw takeFromExternrefTable0(ret[2]);
2498
+ }
2499
+ deferred3_0 = ptr2;
2500
+ deferred3_1 = len2;
2501
+ return getStringFromWasm0(ptr2, len2);
2502
+ } finally {
2503
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
2504
+ }
2505
+ }
2506
+ function resolveParametersJson(params_json) {
2507
+ let deferred3_0;
2508
+ let deferred3_1;
2509
+ try {
2510
+ const ptr0 = passStringToWasm0(params_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2511
+ const len0 = WASM_VECTOR_LEN;
2512
+ const ret = wasm.resolveParametersJson(ptr0, len0);
2513
+ var ptr2 = ret[0];
2514
+ var len2 = ret[1];
2515
+ if (ret[3]) {
2516
+ ptr2 = 0;
2517
+ len2 = 0;
2518
+ throw takeFromExternrefTable0(ret[2]);
2519
+ }
2520
+ deferred3_0 = ptr2;
2521
+ deferred3_1 = len2;
2522
+ return getStringFromWasm0(ptr2, len2);
2523
+ } finally {
2524
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
2525
+ }
2526
+ }
2347
2527
  function sample_timeline_sequence(timeline_json) {
2348
2528
  let deferred3_0;
2349
2529
  let deferred3_1;
@@ -2410,6 +2590,27 @@ function sheetMetalSequence(chain_json) {
2410
2590
  wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
2411
2591
  }
2412
2592
  }
2593
+ function simulateStrikeKernel(input_json) {
2594
+ let deferred3_0;
2595
+ let deferred3_1;
2596
+ try {
2597
+ const ptr0 = passStringToWasm0(input_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
2598
+ const len0 = WASM_VECTOR_LEN;
2599
+ const ret = wasm.simulateStrikeKernel(ptr0, len0);
2600
+ var ptr2 = ret[0];
2601
+ var len2 = ret[1];
2602
+ if (ret[3]) {
2603
+ ptr2 = 0;
2604
+ len2 = 0;
2605
+ throw takeFromExternrefTable0(ret[2]);
2606
+ }
2607
+ deferred3_0 = ptr2;
2608
+ deferred3_1 = len2;
2609
+ return getStringFromWasm0(ptr2, len2);
2610
+ } finally {
2611
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
2612
+ }
2613
+ }
2413
2614
  function sketchCircleSegments(cx, cy, radius, segments) {
2414
2615
  let deferred2_0;
2415
2616
  let deferred2_1;
@@ -2793,6 +2994,12 @@ function __wbg_get_imports() {
2793
2994
  const ret = arg0.WorkerGlobalScope;
2794
2995
  return ret;
2795
2996
  },
2997
+ __wbg___wbindgen_bigint_get_as_i64_8fcf4ce7f1ca72a2: function(arg0, arg1) {
2998
+ const v = arg1;
2999
+ const ret = typeof v === "bigint" ? v : void 0;
3000
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
3001
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
3002
+ },
2796
3003
  __wbg___wbindgen_boolean_get_bbbb1c18aa2f5e25: function(arg0) {
2797
3004
  const v = arg0;
2798
3005
  const ret = typeof v === "boolean" ? v : void 0;
@@ -2809,6 +3016,10 @@ function __wbg_get_imports() {
2809
3016
  const ret = arg0 in arg1;
2810
3017
  return ret;
2811
3018
  },
3019
+ __wbg___wbindgen_is_bigint_31b12575b56f32fc: function(arg0) {
3020
+ const ret = typeof arg0 === "bigint";
3021
+ return ret;
3022
+ },
2812
3023
  __wbg___wbindgen_is_function_0095a73b8b156f76: function(arg0) {
2813
3024
  const ret = typeof arg0 === "function";
2814
3025
  return ret;
@@ -2830,6 +3041,10 @@ function __wbg_get_imports() {
2830
3041
  const ret = arg0 === void 0;
2831
3042
  return ret;
2832
3043
  },
3044
+ __wbg___wbindgen_jsval_eq_11888390b0186270: function(arg0, arg1) {
3045
+ const ret = arg0 === arg1;
3046
+ return ret;
3047
+ },
2833
3048
  __wbg___wbindgen_jsval_loose_eq_9dd77d8cd6671811: function(arg0, arg1) {
2834
3049
  const ret = arg0 == arg1;
2835
3050
  return ret;
@@ -3385,6 +3600,10 @@ function __wbg_get_imports() {
3385
3600
  __wbg_end_6f776519f1faa582: function(arg0) {
3386
3601
  arg0.end();
3387
3602
  },
3603
+ __wbg_entries_58c7934c745daac7: function(arg0) {
3604
+ const ret = Object.entries(arg0);
3605
+ return ret;
3606
+ },
3388
3607
  __wbg_error_7534b8e9a36f1ab4: function(arg0, arg1) {
3389
3608
  let deferred0_0;
3390
3609
  let deferred0_1;
@@ -3730,6 +3949,16 @@ function __wbg_get_imports() {
3730
3949
  const ret = result;
3731
3950
  return ret;
3732
3951
  },
3952
+ __wbg_instanceof_Map_53af74335dec57f4: function(arg0) {
3953
+ let result;
3954
+ try {
3955
+ result = arg0 instanceof Map;
3956
+ } catch (_) {
3957
+ result = false;
3958
+ }
3959
+ const ret = result;
3960
+ return ret;
3961
+ },
3733
3962
  __wbg_instanceof_Object_1c6af87502b733ed: function(arg0) {
3734
3963
  let result;
3735
3964
  try {
@@ -8537,8 +8766,8 @@ function evaluateDocument2(doc, kernel2, options = {}) {
8537
8766
  if (p.mesh.positions.length === 0 && i < visibleRoots.length) {
8538
8767
  const emb = findEmbroideryPattern(visibleRoots[i].root, doc.nodes);
8539
8768
  if (emb) {
8540
- const baseMesh = embroideryPatternToMesh(emb.pattern);
8541
- const mesh = transformMesh(baseMesh, emb.transform);
8769
+ const baseMesh = embroideryPatternToMeshWithKernel(emb.pattern, kernel2);
8770
+ const mesh = transformMeshWithKernel(baseMesh, emb.transform, kernel2);
8542
8771
  return { mesh, material: p.material };
8543
8772
  }
8544
8773
  try {
@@ -8616,35 +8845,9 @@ function convertSketchToProfile(op) {
8616
8845
  }
8617
8846
  function solidToMesh(solid) {
8618
8847
  const meshData = solid.getMesh();
8619
- const positions = new Float32Array(meshData.positions);
8620
- const indices = new Uint32Array(meshData.indices);
8621
- const numVertices = positions.length / 3;
8622
- let hasInvalidIndices = false;
8623
- for (let i = 0; i < indices.length; i++) {
8624
- if (indices[i] >= numVertices) {
8625
- hasInvalidIndices = true;
8626
- break;
8627
- }
8628
- }
8629
- if (hasInvalidIndices) {
8630
- const validIndices = [];
8631
- for (let i = 0; i < indices.length; i += 3) {
8632
- const i0 = indices[i];
8633
- const i1 = indices[i + 1];
8634
- const i2 = indices[i + 2];
8635
- if (i0 < numVertices && i1 < numVertices && i2 < numVertices) {
8636
- validIndices.push(i0, i1, i2);
8637
- }
8638
- }
8639
- return {
8640
- positions,
8641
- indices: new Uint32Array(validIndices),
8642
- normals: meshData.normals ? new Float32Array(meshData.normals) : void 0
8643
- };
8644
- }
8645
8848
  return {
8646
- positions,
8647
- indices,
8849
+ positions: new Float32Array(meshData.positions),
8850
+ indices: new Uint32Array(meshData.indices),
8648
8851
  normals: meshData.normals ? new Float32Array(meshData.normals) : void 0
8649
8852
  };
8650
8853
  }
@@ -8665,7 +8868,7 @@ function resolveSheetMetalPart(rootId, nodes, kernel2) {
8665
8868
  return null;
8666
8869
  const { mesh, sheetMetal } = evaluateSheetMetalChain2(chain, kernel2);
8667
8870
  return {
8668
- mesh: isIdentityTransform(sm.transform) ? mesh : transformMesh(mesh, sm.transform),
8871
+ mesh: isIdentityTransform(sm.transform) ? mesh : transformMeshWithKernel(mesh, sm.transform, kernel2),
8669
8872
  sheetMetal
8670
8873
  };
8671
8874
  }
@@ -8708,6 +8911,37 @@ function embroideryPatternToMesh(op) {
8708
8911
  colors: new Float32Array(allColors)
8709
8912
  };
8710
8913
  }
8914
+ function embroideryPatternToMeshWithKernel(op, kernel2) {
8915
+ if (kernel2?.embroideryDesignToMesh) {
8916
+ try {
8917
+ const m = kernel2.embroideryDesignToMesh(JSON.stringify(op.design));
8918
+ return {
8919
+ positions: new Float32Array(m.positions),
8920
+ indices: new Uint32Array(m.indices),
8921
+ colors: new Float32Array(m.colors)
8922
+ };
8923
+ } catch (e) {
8924
+ console.warn("[ENGINE] kernel embroideryDesignToMesh failed, falling back to TS:", e);
8925
+ }
8926
+ }
8927
+ return embroideryPatternToMesh(op);
8928
+ }
8929
+ function transformMeshWithKernel(mesh, transform2, kernel2) {
8930
+ if (kernel2?.transformMeshBuffers) {
8931
+ try {
8932
+ const r = kernel2.transformMeshBuffers(mesh.positions, mesh.normals, JSON.stringify(transform2));
8933
+ return {
8934
+ positions: new Float32Array(r.positions),
8935
+ indices: mesh.indices,
8936
+ normals: r.normals ? new Float32Array(r.normals) : void 0,
8937
+ colors: mesh.colors
8938
+ };
8939
+ } catch (e) {
8940
+ console.warn("[ENGINE] kernel transformMeshBuffers failed, falling back to TS:", e);
8941
+ }
8942
+ }
8943
+ return transformMesh(mesh, transform2);
8944
+ }
8711
8945
  function transformMesh(mesh, transform2) {
8712
8946
  const { translate, rotate, scale } = transform2;
8713
8947
  const positions = new Float32Array(mesh.positions.length);
@@ -8764,8 +8998,8 @@ function evaluateDocumentTS(doc, kernel2, options = {}) {
8764
8998
  const parts = visibleRoots.map((entry, idx) => {
8765
8999
  const embPattern = findEmbroideryPattern(entry.root, doc.nodes);
8766
9000
  if (embPattern) {
8767
- const baseMesh = embroideryPatternToMesh(embPattern.pattern);
8768
- const mesh = transformMesh(baseMesh, embPattern.transform);
9001
+ const baseMesh = embroideryPatternToMeshWithKernel(embPattern.pattern, kernel2);
9002
+ const mesh = transformMeshWithKernel(baseMesh, embPattern.transform, kernel2);
8769
9003
  solids.push(Solid2.empty());
8770
9004
  return { mesh, material: entry.material };
8771
9005
  }
@@ -8776,7 +9010,7 @@ function evaluateDocumentTS(doc, kernel2, options = {}) {
8776
9010
  indices: new Uint32Array(imported.mesh.indices),
8777
9011
  normals: imported.mesh.normals ? new Float32Array(imported.mesh.normals) : void 0
8778
9012
  };
8779
- const mesh = transformMesh(baseMesh, imported.transform);
9013
+ const mesh = transformMeshWithKernel(baseMesh, imported.transform, kernel2);
8780
9014
  solids.push(Solid2.empty());
8781
9015
  return { mesh, material: entry.material };
8782
9016
  }
@@ -11450,6 +11684,7 @@ __export(dist_exports, {
11450
11684
  decimateMeshGpu: () => decimateMeshGpu2,
11451
11685
  defaultParamsFor: () => defaultParamsFor,
11452
11686
  deriveBoardFromCavity: () => deriveBoardFromCavity,
11687
+ embroideryPatternToMeshWithKernel: () => embroideryPatternToMeshWithKernel,
11453
11688
  estimateCost: () => estimateCost,
11454
11689
  evalAst: () => evalAst,
11455
11690
  evalExprSafe: () => evalExprSafe,
@@ -11527,6 +11762,7 @@ __export(dist_exports, {
11527
11762
  threeWayMerge: () => threeWayMerge,
11528
11763
  toWorld: () => toWorld,
11529
11764
  transformMesh: () => transformMesh,
11765
+ transformMeshWithKernel: () => transformMeshWithKernel,
11530
11766
  tryExportFabFiles: () => tryExportFabFiles,
11531
11767
  tryPcbPreviewMeshes: () => tryPcbPreviewMeshes,
11532
11768
  tryRunDrc: () => tryRunDrc,
@@ -11552,6 +11788,7 @@ var init_dist = __esm({
11552
11788
  init_mesh_cache();
11553
11789
  init_dependency_graph();
11554
11790
  init_evaluate();
11791
+ init_evaluate();
11555
11792
  init_sequence();
11556
11793
  init_sheet_metal();
11557
11794
  init_expressions();
@@ -40800,6 +41037,7 @@ var init_part_labels = __esm({
40800
41037
  var init_export_stl = __esm({
40801
41038
  "../core/dist/utils/export-stl.js"() {
40802
41039
  "use strict";
41040
+ init_dist();
40803
41041
  }
40804
41042
  });
40805
41043
 
@@ -40807,6 +41045,7 @@ var init_export_stl = __esm({
40807
41045
  var init_export_gltf = __esm({
40808
41046
  "../core/dist/utils/export-gltf.js"() {
40809
41047
  "use strict";
41048
+ init_dist();
40810
41049
  }
40811
41050
  });
40812
41051
 
@@ -49177,370 +49416,87 @@ var init_loon = __esm({
49177
49416
  });
49178
49417
 
49179
49418
  // src/export/glb.ts
49419
+ function exportKernel() {
49420
+ const mod = getKernelWasmSync();
49421
+ if (!mod) {
49422
+ throw new Error(
49423
+ "kernel WASM not initialized \u2014 await getKernelWasm() before exporting"
49424
+ );
49425
+ }
49426
+ return mod;
49427
+ }
49180
49428
  function buildPartLabels(doc) {
49181
49429
  return doc.roots.filter((entry) => entry.visible !== false).map((entry) => {
49182
49430
  const name = doc.nodes[String(entry.root)]?.name;
49183
49431
  return `${entry.root}:${name ?? ""}`;
49184
49432
  });
49185
49433
  }
49186
- function eulerXyzDegToQuat(rotation) {
49187
- const rad = Math.PI / 180;
49188
- const hx = rotation.x * rad / 2;
49189
- const hy = rotation.y * rad / 2;
49190
- const hz = rotation.z * rad / 2;
49191
- const c1 = Math.cos(hx);
49192
- const s1 = Math.sin(hx);
49193
- const c2 = Math.cos(hy);
49194
- const s2 = Math.sin(hy);
49195
- const c3 = Math.cos(hz);
49196
- const s3 = Math.sin(hz);
49197
- return [
49198
- s1 * c2 * c3 - c1 * s2 * s3,
49199
- c1 * s2 * c3 + s1 * c2 * s3,
49200
- c1 * c2 * s3 - s1 * s2 * c3,
49201
- c1 * c2 * c3 + s1 * s2 * s3
49202
- ];
49434
+ function eulerXyzDegToQuat2(rotation) {
49435
+ const q = exportKernel().eulerXyzDegToQuat(rotation.x, rotation.y, rotation.z);
49436
+ return [q[0], q[1], q[2], q[3]];
49203
49437
  }
49204
49438
  function buildGlb(inputMeshes, name, animation) {
49205
- const materialMap = /* @__PURE__ */ new Map();
49206
- const materials = [];
49207
- const materialIndexFor = (m) => {
49208
- const emissive = m.emissive ?? [0, 0, 0];
49209
- const emissiveStrength = m.emissiveStrength ?? 1;
49210
- const clearcoat = m.clearcoat ?? 0;
49211
- const clearcoatRoughness = m.clearcoatRoughness ?? 0;
49212
- const alpha = m.alpha ?? 1;
49213
- const key = `${m.color[0]},${m.color[1]},${m.color[2]},${m.metallic},${m.roughness},${emissive[0]},${emissive[1]},${emissive[2]},${emissiveStrength},${clearcoat},${clearcoatRoughness},${alpha}`;
49214
- const existing = materialMap.get(key);
49215
- if (existing !== void 0) return existing;
49216
- const idx = materials.length;
49217
- materialMap.set(key, idx);
49218
- materials.push({
49219
- name: m.name.includes(":") ? m.name.split(":")[0] : m.name,
49220
- color: m.color,
49221
- metallic: m.metallic,
49222
- roughness: m.roughness,
49223
- emissive,
49224
- emissiveStrength,
49225
- clearcoat,
49226
- clearcoatRoughness,
49227
- alpha
49228
- });
49229
- return idx;
49439
+ let f32Len = 0;
49440
+ let u32Len = 0;
49441
+ for (const m of inputMeshes) {
49442
+ f32Len += m.positions.length;
49443
+ u32Len += m.indices.length;
49444
+ if (m.normals && m.normals.length === m.positions.length) {
49445
+ f32Len += m.normals.length;
49446
+ }
49447
+ }
49448
+ for (const ch of animation?.channels ?? []) {
49449
+ f32Len += ch.times.length + ch.values.length;
49450
+ }
49451
+ const f32Data = new Float32Array(f32Len);
49452
+ const u32Data = new Uint32Array(u32Len);
49453
+ let f32Off = 0;
49454
+ let u32Off = 0;
49455
+ const pushF32 = (data) => {
49456
+ f32Data.set(data, f32Off);
49457
+ const span = [f32Off, data.length];
49458
+ f32Off += data.length;
49459
+ return span;
49230
49460
  };
49231
- if (inputMeshes.length === 0) {
49232
- materials.push({
49233
- ...DEFAULT_MATERIAL,
49234
- emissive: [0, 0, 0],
49235
- emissiveStrength: 1,
49236
- clearcoat: 0,
49237
- clearcoatRoughness: 0,
49238
- alpha: 1
49239
- });
49240
- }
49241
- const bufferChunks = [];
49242
- const bufferViews = [];
49243
- const accessors = [];
49244
- const meshes = [];
49245
- const nodes = [];
49246
- let bufferOffset = 0;
49247
- const meshKeyToIdx = /* @__PURE__ */ new Map();
49248
- for (let inputIdx = 0; inputIdx < inputMeshes.length; inputIdx++) {
49249
- const input = inputMeshes[inputIdx];
49250
- const dedupIdx = input.meshKey !== void 0 ? meshKeyToIdx.get(input.meshKey) : void 0;
49251
- if (dedupIdx !== void 0) {
49252
- nodes.push(makeNode(input, dedupIdx));
49253
- continue;
49254
- }
49255
- const positions = f32(input.positions);
49256
- const normals = input.normals && input.normals.length === positions.length ? f32(input.normals) : void 0;
49257
- const vertexCount = positions.length / 3;
49258
- const indexCount = input.indices.length;
49259
- let minX = Infinity, minY = Infinity, minZ = Infinity;
49260
- let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
49261
- for (let i = 0; i < vertexCount; i++) {
49262
- const x = positions[i * 3];
49263
- const y = positions[i * 3 + 1];
49264
- const z = positions[i * 3 + 2];
49265
- minX = Math.min(minX, x);
49266
- minY = Math.min(minY, y);
49267
- minZ = Math.min(minZ, z);
49268
- maxX = Math.max(maxX, x);
49269
- maxY = Math.max(maxY, y);
49270
- maxZ = Math.max(maxZ, z);
49271
- }
49272
- const indicesBytes = new Uint8Array(indexCount * 4);
49273
- const indicesView = new DataView(indicesBytes.buffer);
49274
- for (let i = 0; i < indexCount; i++) {
49275
- indicesView.setUint32(i * 4, input.indices[i], true);
49276
- }
49277
- const indicesPadded = padTo4(indicesBytes);
49278
- bufferChunks.push(indicesPadded);
49279
- const indicesBvIdx = bufferViews.length;
49280
- bufferViews.push({
49281
- buffer: 0,
49282
- byteOffset: bufferOffset,
49283
- byteLength: indexCount * 4,
49284
- target: 34963
49285
- // ELEMENT_ARRAY_BUFFER
49286
- });
49287
- bufferOffset += indicesPadded.length;
49288
- const indicesAccIdx = accessors.length;
49289
- accessors.push({
49290
- bufferView: indicesBvIdx,
49291
- componentType: 5125,
49292
- // UNSIGNED_INT
49293
- count: indexCount,
49294
- type: "SCALAR"
49295
- });
49296
- const positionsBytes = new Uint8Array(
49297
- positions.buffer.slice(
49298
- positions.byteOffset,
49299
- positions.byteOffset + vertexCount * 12
49300
- )
49301
- );
49302
- const positionsPadded = padTo4(positionsBytes);
49303
- bufferChunks.push(positionsPadded);
49304
- const positionsBvIdx = bufferViews.length;
49305
- bufferViews.push({
49306
- buffer: 0,
49307
- byteOffset: bufferOffset,
49308
- byteLength: vertexCount * 12,
49309
- target: 34962
49310
- // ARRAY_BUFFER
49311
- });
49312
- bufferOffset += positionsPadded.length;
49313
- const positionsAccIdx = accessors.length;
49314
- accessors.push({
49315
- bufferView: positionsBvIdx,
49316
- componentType: 5126,
49317
- // FLOAT
49318
- count: vertexCount,
49319
- type: "VEC3",
49320
- min: [minX, minY, minZ],
49321
- max: [maxX, maxY, maxZ]
49322
- });
49323
- const attributes = {
49324
- POSITION: positionsAccIdx
49325
- };
49326
- if (normals) {
49327
- const normalsBytes = new Uint8Array(
49328
- normals.buffer.slice(
49329
- normals.byteOffset,
49330
- normals.byteOffset + vertexCount * 12
49331
- )
49332
- );
49333
- const normalsPadded = padTo4(normalsBytes);
49334
- bufferChunks.push(normalsPadded);
49335
- const normalsBvIdx = bufferViews.length;
49336
- bufferViews.push({
49337
- buffer: 0,
49338
- byteOffset: bufferOffset,
49339
- byteLength: vertexCount * 12,
49340
- target: 34962
49341
- // ARRAY_BUFFER
49342
- });
49343
- bufferOffset += normalsPadded.length;
49344
- const normalsAccIdx = accessors.length;
49345
- accessors.push({
49346
- bufferView: normalsBvIdx,
49347
- componentType: 5126,
49348
- // FLOAT
49349
- count: vertexCount,
49350
- type: "VEC3"
49351
- });
49352
- attributes.NORMAL = normalsAccIdx;
49353
- }
49354
- const meshIdx = meshes.length;
49355
- meshes.push({
49356
- name: `mesh_${meshIdx}`,
49357
- primitives: [
49358
- {
49359
- attributes,
49360
- indices: indicesAccIdx,
49361
- material: materialIndexFor(input)
49362
- }
49363
- ]
49364
- });
49365
- if (input.meshKey !== void 0) meshKeyToIdx.set(input.meshKey, meshIdx);
49366
- nodes.push(makeNode(input, meshIdx));
49367
- }
49368
- let sceneNodeIndices = nodes.map((_, i) => i);
49369
- if (animation?.rootNodeName !== void 0) {
49370
- const rootIdx = nodes.length;
49371
- nodes.push({
49372
- name: animation.rootNodeName,
49373
- children: sceneNodeIndices
49374
- });
49375
- sceneNodeIndices = [rootIdx];
49376
- }
49377
- for (const extra of animation?.extraNodes ?? []) {
49378
- const idx = nodes.length;
49379
- nodes.push({ name: extra });
49380
- sceneNodeIndices = [...sceneNodeIndices, idx];
49381
- }
49382
- let animationsJson;
49383
- if (animation && animation.channels.length > 0) {
49384
- const nodeIndexByName = /* @__PURE__ */ new Map();
49385
- for (let i = 0; i < nodes.length; i++) {
49386
- nodeIndexByName.set(nodes[i].name, i);
49387
- }
49388
- const writeF32Accessor = (data, type, withMinMax) => {
49389
- const arr = new Float32Array(data);
49390
- const bytes = new Uint8Array(arr.buffer.slice(0));
49391
- const padded = padTo4(bytes);
49392
- bufferChunks.push(padded);
49393
- const bvIdx = bufferViews.length;
49394
- bufferViews.push({
49395
- buffer: 0,
49396
- byteOffset: bufferOffset,
49397
- byteLength: bytes.length
49398
- });
49399
- bufferOffset += padded.length;
49400
- const components = type === "SCALAR" ? 1 : type === "VEC3" ? 3 : 4;
49401
- const accIdx = accessors.length;
49402
- const acc = {
49403
- bufferView: bvIdx,
49404
- componentType: 5126,
49405
- // FLOAT
49406
- count: data.length / components,
49407
- type
49408
- };
49409
- if (withMinMax) {
49410
- acc.min = [Math.min(...data)];
49411
- acc.max = [Math.max(...data)];
49412
- }
49413
- accessors.push(acc);
49414
- return accIdx;
49415
- };
49416
- const samplers = [];
49417
- const channels = [];
49418
- for (const ch of animation.channels) {
49419
- const nodeIdx = nodeIndexByName.get(ch.nodeName);
49420
- if (nodeIdx === void 0) {
49421
- console.warn(
49422
- `buildGlb: animation channel targets unknown node "${ch.nodeName}" \u2014 skipped`
49423
- );
49424
- continue;
49425
- }
49426
- const inputAcc = writeF32Accessor(ch.times, "SCALAR", true);
49427
- const outputAcc = writeF32Accessor(
49428
- ch.values,
49429
- ch.path === "rotation" ? "VEC4" : "VEC3",
49430
- false
49431
- );
49432
- const samplerIdx = samplers.length;
49433
- samplers.push({
49434
- input: inputAcc,
49435
- output: outputAcc,
49436
- interpolation: ch.interpolation ?? "LINEAR"
49437
- });
49438
- channels.push({
49439
- sampler: samplerIdx,
49440
- target: { node: nodeIdx, path: ch.path }
49441
- });
49442
- }
49443
- if (channels.length > 0) {
49444
- animationsJson = [
49445
- { name: animation.name ?? "timeline", samplers, channels }
49446
- ];
49447
- }
49448
- }
49449
- let usesClearcoat = false;
49450
- let usesEmissiveStrength = false;
49451
- const materialJson = materials.map((m) => {
49452
- const mat = {
49453
- name: m.name,
49454
- pbrMetallicRoughness: {
49455
- baseColorFactor: [...m.color, m.alpha],
49456
- metallicFactor: m.metallic,
49457
- roughnessFactor: m.roughness
49458
- }
49459
- };
49460
- if (m.alpha < 1) {
49461
- mat.alphaMode = "BLEND";
49462
- mat.doubleSided = true;
49463
- }
49464
- if (isEmissive(m.emissive)) {
49465
- mat.emissiveFactor = m.emissive;
49466
- }
49467
- const extensions = {};
49468
- if (m.clearcoat > 0) {
49469
- usesClearcoat = true;
49470
- extensions.KHR_materials_clearcoat = {
49471
- clearcoatFactor: m.clearcoat,
49472
- clearcoatRoughnessFactor: m.clearcoatRoughness
49473
- };
49474
- }
49475
- if (isEmissive(m.emissive) && m.emissiveStrength !== 1) {
49476
- usesEmissiveStrength = true;
49477
- extensions.KHR_materials_emissive_strength = {
49478
- emissiveStrength: m.emissiveStrength
49479
- };
49480
- }
49481
- if (Object.keys(extensions).length > 0) mat.extensions = extensions;
49482
- return mat;
49483
- });
49484
- const extensionsUsed = [];
49485
- if (usesClearcoat) extensionsUsed.push("KHR_materials_clearcoat");
49486
- if (usesEmissiveStrength)
49487
- extensionsUsed.push("KHR_materials_emissive_strength");
49488
- const json = {
49489
- asset: { version: "2.0", generator: "vcad-mcp" },
49490
- scene: 0,
49491
- scenes: [{ name, nodes: sceneNodeIndices }],
49492
- nodes,
49461
+ const pushU32 = (data) => {
49462
+ u32Data.set(data, u32Off);
49463
+ const span = [u32Off, data.length];
49464
+ u32Off += data.length;
49465
+ return span;
49466
+ };
49467
+ const meshes = inputMeshes.map((m) => ({
49468
+ name: m.name,
49469
+ positions: pushF32(m.positions),
49470
+ indices: pushU32(m.indices),
49471
+ normals: m.normals && m.normals.length === m.positions.length ? pushF32(m.normals) : void 0,
49472
+ color: m.color,
49473
+ metallic: m.metallic,
49474
+ roughness: m.roughness,
49475
+ emissive: m.emissive,
49476
+ emissiveStrength: m.emissiveStrength,
49477
+ clearcoat: m.clearcoat,
49478
+ clearcoatRoughness: m.clearcoatRoughness,
49479
+ alpha: m.alpha,
49480
+ transform: m.transform,
49481
+ meshKey: m.meshKey
49482
+ }));
49483
+ const spec = {
49484
+ name,
49493
49485
  meshes,
49494
- materials: materialJson,
49495
- accessors,
49496
- bufferViews,
49497
- buffers: [{ byteLength: bufferOffset }]
49486
+ animation: animation ? {
49487
+ name: animation.name,
49488
+ channels: animation.channels.map((ch) => ({
49489
+ nodeName: ch.nodeName,
49490
+ path: ch.path,
49491
+ times: pushF32(ch.times),
49492
+ values: pushF32(ch.values),
49493
+ interpolation: ch.interpolation
49494
+ })),
49495
+ rootNodeName: animation.rootNodeName,
49496
+ extraNodes: animation.extraNodes
49497
+ } : void 0
49498
49498
  };
49499
- if (extensionsUsed.length > 0) json.extensionsUsed = extensionsUsed;
49500
- if (animationsJson) json.animations = animationsJson;
49501
- const jsonStr = JSON.stringify(json);
49502
- const jsonBytes = new TextEncoder().encode(jsonStr);
49503
- const jsonPadded = padTo4(jsonBytes, 32);
49504
- const binBuffer = new Uint8Array(bufferOffset);
49505
- let binOffset = 0;
49506
- for (const chunk of bufferChunks) {
49507
- binBuffer.set(chunk, binOffset);
49508
- binOffset += chunk.length;
49509
- }
49510
- const totalLength = 12 + 8 + jsonPadded.length + 8 + binBuffer.length;
49511
- const glb = new Uint8Array(totalLength);
49512
- const glbView = new DataView(glb.buffer);
49513
- let offset = 0;
49514
- glb.set(new TextEncoder().encode("glTF"), offset);
49515
- offset += 4;
49516
- glbView.setUint32(offset, 2, true);
49517
- offset += 4;
49518
- glbView.setUint32(offset, totalLength, true);
49519
- offset += 4;
49520
- glbView.setUint32(offset, jsonPadded.length, true);
49521
- offset += 4;
49522
- glbView.setUint32(offset, 1313821514, true);
49523
- offset += 4;
49524
- glb.set(jsonPadded, offset);
49525
- offset += jsonPadded.length;
49526
- glbView.setUint32(offset, binBuffer.length, true);
49527
- offset += 4;
49528
- glbView.setUint32(offset, 5130562, true);
49529
- offset += 4;
49530
- glb.set(binBuffer, offset);
49531
- return glb;
49532
- }
49533
- function makeNode(input, meshIdx) {
49534
- const node = { mesh: meshIdx, name: input.name };
49535
- const t2 = input.transform;
49536
- if (!t2) return node;
49537
- const [tx, ty, tz] = t2.translation;
49538
- if (tx !== 0 || ty !== 0 || tz !== 0) node.translation = t2.translation;
49539
- const [qx, qy, qz, qw] = t2.rotationQuat;
49540
- if (qx !== 0 || qy !== 0 || qz !== 0 || qw !== 1) node.rotation = t2.rotationQuat;
49541
- const [sx, sy, sz] = t2.scale;
49542
- if (sx !== 1 || sy !== 1 || sz !== 1) node.scale = t2.scale;
49543
- return node;
49499
+ return exportKernel().buildGlbBytes(JSON.stringify(spec), f32Data, u32Data);
49544
49500
  }
49545
49501
  function toGlbBytes(scene, name, partLabels) {
49546
49502
  const meshes = scene.parts.map((part, i) => ({
@@ -49554,28 +49510,17 @@ function toGlbBytes(scene, name, partLabels) {
49554
49510
  }));
49555
49511
  return buildGlb(meshes, name);
49556
49512
  }
49557
- function padTo4(bytes, padByte = 0) {
49558
- const paddedLength = bytes.length + 3 & ~3;
49559
- if (paddedLength === bytes.length) return bytes;
49560
- const padded = new Uint8Array(paddedLength);
49561
- padded.set(bytes);
49562
- for (let i = bytes.length; i < paddedLength; i++) {
49563
- padded[i] = padByte;
49564
- }
49565
- return padded;
49566
- }
49567
- var DEFAULT_MATERIAL, isEmissive, f32;
49513
+ var DEFAULT_MATERIAL;
49568
49514
  var init_glb = __esm({
49569
49515
  "src/export/glb.ts"() {
49570
49516
  "use strict";
49517
+ init_dist();
49571
49518
  DEFAULT_MATERIAL = {
49572
49519
  name: "default",
49573
49520
  color: [0.8, 0.8, 0.8],
49574
49521
  metallic: 0.1,
49575
49522
  roughness: 0.5
49576
49523
  };
49577
- isEmissive = (e) => e[0] > 0 || e[1] > 0 || e[2] > 0;
49578
- f32 = (a) => a instanceof Float32Array ? a : new Float32Array(a);
49579
49524
  }
49580
49525
  });
49581
49526
 
@@ -49699,7 +49644,7 @@ function generateInstancesGlbPreview(doc, engine) {
49699
49644
  inst.transform.translation.y,
49700
49645
  inst.transform.translation.z
49701
49646
  ],
49702
- rotationQuat: eulerXyzDegToQuat(inst.transform.rotation),
49647
+ rotationQuat: eulerXyzDegToQuat2(inst.transform.rotation),
49703
49648
  scale: [
49704
49649
  inst.transform.scale.x,
49705
49650
  inst.transform.scale.y,
@@ -56362,80 +56307,37 @@ var init_parts2 = __esm({
56362
56307
 
56363
56308
  // src/export/stl.ts
56364
56309
  function toStlBytes(scene, name) {
56365
- let totalTriangles = 0;
56366
- for (const part of scene.parts) {
56367
- totalTriangles += part.mesh.indices.length / 3;
56368
- }
56369
- const buffer = new ArrayBuffer(84 + totalTriangles * 50);
56370
- const view = new DataView(buffer);
56371
- const uint8 = new Uint8Array(buffer);
56372
- const header = name.slice(0, 80).padEnd(80, " ");
56373
- for (let i = 0; i < 80; i++) {
56374
- uint8[i] = header.charCodeAt(i);
56375
- }
56376
- view.setUint32(80, totalTriangles, true);
56377
- let offset = 84;
56310
+ let f32Len = 0;
56311
+ let u32Len = 0;
56378
56312
  for (const part of scene.parts) {
56379
- offset = writeMeshTriangles(part.mesh, view, offset);
56380
- }
56381
- return uint8;
56382
- }
56383
- function writeMeshTriangles(mesh, view, offset) {
56384
- const positions = mesh.positions;
56385
- const indices = mesh.indices;
56386
- const numTriangles = indices.length / 3;
56387
- for (let t2 = 0; t2 < numTriangles; t2++) {
56388
- const i0 = indices[t2 * 3];
56389
- const i1 = indices[t2 * 3 + 1];
56390
- const i2 = indices[t2 * 3 + 2];
56391
- const v0x = positions[i0 * 3];
56392
- const v0y = positions[i0 * 3 + 1];
56393
- const v0z = positions[i0 * 3 + 2];
56394
- const v1x = positions[i1 * 3];
56395
- const v1y = positions[i1 * 3 + 1];
56396
- const v1z = positions[i1 * 3 + 2];
56397
- const v2x = positions[i2 * 3];
56398
- const v2y = positions[i2 * 3 + 1];
56399
- const v2z = positions[i2 * 3 + 2];
56400
- const e1x = v1x - v0x;
56401
- const e1y = v1y - v0y;
56402
- const e1z = v1z - v0z;
56403
- const e2x = v2x - v0x;
56404
- const e2y = v2y - v0y;
56405
- const e2z = v2z - v0z;
56406
- let nx = e1y * e2z - e1z * e2y;
56407
- let ny = e1z * e2x - e1x * e2z;
56408
- let nz = e1x * e2y - e1y * e2x;
56409
- const len = Math.sqrt(nx * nx + ny * ny + nz * nz);
56410
- if (len > 1e-10) {
56411
- nx /= len;
56412
- ny /= len;
56413
- nz /= len;
56414
- }
56415
- view.setFloat32(offset, nx, true);
56416
- view.setFloat32(offset + 4, ny, true);
56417
- view.setFloat32(offset + 8, nz, true);
56418
- offset += 12;
56419
- view.setFloat32(offset, v0x, true);
56420
- view.setFloat32(offset + 4, v0y, true);
56421
- view.setFloat32(offset + 8, v0z, true);
56422
- offset += 12;
56423
- view.setFloat32(offset, v1x, true);
56424
- view.setFloat32(offset + 4, v1y, true);
56425
- view.setFloat32(offset + 8, v1z, true);
56426
- offset += 12;
56427
- view.setFloat32(offset, v2x, true);
56428
- view.setFloat32(offset + 4, v2y, true);
56429
- view.setFloat32(offset + 8, v2z, true);
56430
- offset += 12;
56431
- view.setUint16(offset, 0, true);
56432
- offset += 2;
56433
- }
56434
- return offset;
56313
+ f32Len += part.mesh.positions.length;
56314
+ u32Len += part.mesh.indices.length;
56315
+ }
56316
+ const f32Data = new Float32Array(f32Len);
56317
+ const u32Data = new Uint32Array(u32Len);
56318
+ let f32Off = 0;
56319
+ let u32Off = 0;
56320
+ const meshes = scene.parts.map((part) => {
56321
+ f32Data.set(part.mesh.positions, f32Off);
56322
+ u32Data.set(part.mesh.indices, u32Off);
56323
+ const spec = {
56324
+ positions: [f32Off, part.mesh.positions.length],
56325
+ indices: [u32Off, part.mesh.indices.length]
56326
+ };
56327
+ f32Off += part.mesh.positions.length;
56328
+ u32Off += part.mesh.indices.length;
56329
+ return spec;
56330
+ });
56331
+ return exportKernel().buildStlBytes(
56332
+ JSON.stringify({ name, meshes }),
56333
+ f32Data,
56334
+ u32Data
56335
+ );
56435
56336
  }
56436
56337
  var init_stl = __esm({
56437
56338
  "src/export/stl.ts"() {
56438
56339
  "use strict";
56340
+ init_glb();
56439
56341
  }
56440
56342
  });
56441
56343
 
@@ -76302,7 +76204,7 @@ function buildSequenceGlb(doc, timeline, frames, engine) {
76302
76204
  rec.times.push(frame.t);
76303
76205
  rec.trans.push(...translation);
76304
76206
  rec.rot.push(
76305
- ...eulerXyzDegToQuat(
76207
+ ...eulerXyzDegToQuat2(
76306
76208
  t2?.rotation ?? { x: 0, y: 0, z: 0 }
76307
76209
  )
76308
76210
  );
@@ -77903,8 +77805,8 @@ var init_server3 = __esm({
77903
77805
  init_order_feed();
77904
77806
  init_animate();
77905
77807
  PKG_VERSION = (() => {
77906
- if ("0.9.4-main.13") {
77907
- return "0.9.4-main.13";
77808
+ if ("0.9.4-main.15") {
77809
+ return "0.9.4-main.15";
77908
77810
  }
77909
77811
  try {
77910
77812
  const req = createRequire2(import.meta.url);
@@ -77913,8 +77815,8 @@ var init_server3 = __esm({
77913
77815
  return "0.0.0";
77914
77816
  }
77915
77817
  })();
77916
- BUILD_SHA = "70552964e3760fb5b103235917b00364f6d45763";
77917
- BUILD_TIME = "2026-07-24T16:29:07.170Z";
77818
+ BUILD_SHA = "ba0bbea017e3e720ec8796167b6824f3cdf235cf";
77819
+ BUILD_TIME = "2026-07-24T17:18:07.764Z";
77918
77820
  SHORT_SHA = BUILD_SHA === "unknown" ? "unknown" : BUILD_SHA.slice(0, 7);
77919
77821
  VERSION_WITH_BUILD = SHORT_SHA === "unknown" ? PKG_VERSION : `${PKG_VERSION}+${SHORT_SHA}`;
77920
77822
  INSTANCE_ID = randomUUID6().slice(0, 8);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcad/mcp",
3
- "version": "0.9.4-main.13",
3
+ "version": "0.9.4-main.15",
4
4
  "description": "vcad MCP server — parametric CAD + PCB design tools for AI agents (self-contained: bundled server + kernel WASM)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "homepage": "https://vcad.io",
21
21
  "vcadBuild": {
22
- "sha": "70552964e3760fb5b103235917b00364f6d45763",
23
- "builtAt": "2026-07-24T16:29:07.170Z"
22
+ "sha": "ba0bbea017e3e720ec8796167b6824f3cdf235cf",
23
+ "builtAt": "2026-07-24T17:18:07.764Z"
24
24
  }
25
25
  }
Binary file