forgecad 0.10.1 → 0.10.3

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 (113) hide show
  1. package/README.md +7 -6
  2. package/dist/assets/{AdminPage-DcCnj0qo.js → AdminPage-CK7ObBz3.js} +1 -1
  3. package/dist/assets/{BenchmarkPage-BVEpJSVk.js → BenchmarkPage-Ds7Z2doN.js} +1 -1
  4. package/dist/assets/{BlogPage-DHaGP50_.js → BlogPage-DlPbpt6A.js} +1 -1
  5. package/dist/assets/{DocsPage-CDoxHkz8.js → DocsPage-vZb3b3Y0.js} +9 -14
  6. package/dist/assets/{EditorApp-BpjZgzk0.css → EditorApp-C5f24ZN9.css} +8 -0
  7. package/dist/assets/{EditorApp-BJ0Dloyh.js → EditorApp-HLoKfe15.js} +152 -21
  8. package/dist/assets/{EmbedViewer-CRKZbY0y.js → EmbedViewer--KnqBKrJ.js} +3 -3
  9. package/dist/assets/{LandingPageProofDriven-BxHkYRE7.js → LandingPageProofDriven-C_LssmnA.js} +1 -1
  10. package/dist/assets/{LegalPage-B-u6FrVv.js → LegalPage-DGsyo4n1.js} +1 -1
  11. package/dist/assets/{PricingPage-CzpZ6-Ce.js → PricingPage-BOE27B-R.js} +1 -1
  12. package/dist/assets/{SettingsPage-CIZSSAd0.js → SettingsPage-f47cnk39.js} +1 -1
  13. package/dist/assets/{app-DaTMg3nH.js → app-D6ccu2Xx.js} +7826 -7559
  14. package/dist/assets/{scalar-sampling-budget-prBw_s8t.js → backendInit-DbTkQN9J.js} +87141 -78777
  15. package/dist/assets/cli/{render-DPf4AYJK.js → render-BsngirjC.js} +147 -186
  16. package/dist/assets/{constructionHistoryWorker-AwMMWSxg.js → constructionHistoryWorker-PCwXrTDB.js} +8419 -1447
  17. package/dist/assets/{evalWorker-CjZZWRWW.js → evalWorker-CS63PfZu.js} +25501 -17997
  18. package/dist/assets/{forgecad_geometry-Dgceylq9.js → forgecad_geometry-CZ_IfuvA.js} +120 -9
  19. package/dist/assets/forgecad_geometry_bg-C3rQHfwg.wasm +0 -0
  20. package/dist/assets/{inspectWorker-CZsCFtQT.js → inspectWorker-Y4cOzNyA.js} +37208 -34464
  21. package/dist/assets/{jointPose-DzQOViQH.js → jointPose-AMvCywzS.js} +1 -1
  22. package/dist/assets/{manifold-DgXo0T5P.js → manifold-CBry38ly.js} +2 -2
  23. package/dist/assets/{manifold-K1SkarlQ.js → manifold-Crd_F2qx.js} +1 -1
  24. package/dist/assets/{manifold-BYlzU521.js → manifold-k2kRcc85.js} +1 -1
  25. package/dist/assets/{reportWorker-B9nWwSrB.js → reportWorker-CWvn0CEv.js} +46635 -44646
  26. package/dist/cli/render.html +1 -1
  27. package/dist/docs/index.html +2 -2
  28. package/dist/docs-raw/AI/usage.md +2 -4
  29. package/dist/docs-raw/CLI.md +34 -20
  30. package/dist/docs-raw/README.md +1 -1
  31. package/dist/docs-raw/component-model.md +1 -1
  32. package/dist/docs-raw/generated/assembly.md +2 -2
  33. package/dist/docs-raw/generated/concepts.md +6 -4
  34. package/dist/docs-raw/generated/core.md +71 -2
  35. package/dist/docs-raw/generated/curves.md +8 -1
  36. package/dist/docs-raw/generated/lib.md +1 -1
  37. package/dist/docs-raw/generated/output.md +0 -64
  38. package/dist/docs-raw/generated/runtime-names.md +6 -6
  39. package/dist/docs-raw/generated/sdf.md +2 -2
  40. package/dist/docs-raw/generated/viewport.md +3 -12
  41. package/dist/docs-raw/guides/inspection-bundles.md +1 -1
  42. package/dist/docs-raw/guides/simready-quickstart.md +3 -1
  43. package/dist/docs-raw/simulation-workflow.md +58 -0
  44. package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
  45. package/dist/docs-raw/skills/forgecad-image-replicator.md +2 -2
  46. package/dist/docs-raw/skills/forgecad-mujoco-verify.md +78 -0
  47. package/dist/docs-raw/skills/forgecad-spec-by-walking-through-it.md +145 -0
  48. package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
  49. package/dist/docs-raw/skills/forgecad.md +24 -24
  50. package/dist/docs-raw/skills/index.md +2 -3
  51. package/dist/index.html +1 -1
  52. package/dist/sitemap.xml +15 -15
  53. package/dist-cli/{check-compiler-II7NLPAB.js → check-compiler-HPF2T2FS.js} +1 -1
  54. package/dist-cli/{check-query-propagation-7462TR3R.js → check-query-propagation-HYSLTXAB.js} +1 -1
  55. package/dist-cli/{chunk-UWTJCGXF.js → chunk-WLUKAW3H.js} +51134 -43247
  56. package/dist-cli/forgecad.js +5467 -1451
  57. package/dist-cli/{forgecad_geometry-QOQIIP53.js → forgecad_geometry-2IMYCUWW.js} +119 -8
  58. package/dist-cli/forgecad_geometry_bg.wasm +0 -0
  59. package/dist-skill/CONTEXT.md +98 -86
  60. package/dist-skill/SKILL.md +1 -1
  61. package/dist-skill/docs/API/core/concepts.md +1 -1
  62. package/dist-skill/docs/CLI.md +34 -20
  63. package/dist-skill/docs/generated/assembly.md +2 -2
  64. package/dist-skill/docs/generated/core.md +71 -2
  65. package/dist-skill/docs/generated/curves.md +8 -1
  66. package/dist-skill/docs/generated/lib.md +1 -1
  67. package/dist-skill/docs/generated/output.md +0 -64
  68. package/dist-skill/docs/generated/runtime-names.md +6 -6
  69. package/dist-skill/docs/generated/sdf.md +2 -2
  70. package/dist-skill/docs/generated/viewport.md +3 -12
  71. package/dist-skill/docs/guides/inspection-bundles.md +1 -1
  72. package/dist-skill/library/README.md +2 -3
  73. package/dist-skill/library/forgecad-blockout-model/SKILL.md +1 -1
  74. package/dist-skill/library/forgecad-image-replicator/SKILL.md +2 -2
  75. package/dist-skill/library/forgecad-mujoco-verify/SKILL.md +66 -0
  76. package/dist-skill/library/forgecad-mujoco-verify/scripts/mujoco_verify.py +385 -0
  77. package/dist-skill/library/forgecad-spec-by-walking-through-it/SKILL.md +132 -0
  78. package/dist-skill/library/forgecad-visual-spec/SKILL.md +1 -1
  79. package/dist-skill/website/skills/forgecad-blockout-model.md +1 -1
  80. package/dist-skill/website/skills/forgecad-image-replicator.md +2 -2
  81. package/dist-skill/website/skills/forgecad-mujoco-verify.md +78 -0
  82. package/dist-skill/website/skills/forgecad-spec-by-walking-through-it.md +145 -0
  83. package/dist-skill/website/skills/forgecad-visual-spec.md +1 -1
  84. package/dist-skill/website/skills/forgecad.md +24 -24
  85. package/dist-skill/website/skills/index.md +2 -3
  86. package/examples/analysis/clearance-fit.forge.js +31 -0
  87. package/examples/analysis/lever-arm-actuator.forge.js +43 -0
  88. package/examples/analysis/tipping-tripod.forge.js +35 -0
  89. package/examples/api/gyroid-voronoi-blend.forge.js +1 -1
  90. package/examples/api/organic-noise-sculpture.forge.js +1 -1
  91. package/examples/api/sdf-circular-array-knurling.forge.js +1 -1
  92. package/examples/api/{sdf-custom-raymarch.forge.js → sdf-custom-field-mesh-preview.forge.js} +3 -4
  93. package/examples/api/sdf-materialize-tree.forge.js +2 -2
  94. package/examples/api/sdf-plain-return.forge.js +3 -2
  95. package/examples/api/sdf-shapes.forge.js +2 -2
  96. package/examples/api/sdf-surface-basket-weave.forge.js +2 -2
  97. package/examples/generative/twisted-lattice-tower.forge.js +1 -1
  98. package/examples/generative/voronoi-lampshade.forge.js +1 -1
  99. package/examples/products/sportscar.forge.js +77 -0
  100. package/package.json +2 -4
  101. package/dist/assets/forgecad_geometry_bg-dD4RNQF1.wasm +0 -0
  102. package/dist/assets/manifold-CzYf_iub.js +0 -3023
  103. package/dist/docs-raw/skills/forgecad-high-level-spec.md +0 -101
  104. package/dist/docs-raw/skills/forgecad-lld.md +0 -41
  105. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +0 -63
  106. package/dist-skill/library/forgecad-high-level-spec/SKILL.md +0 -94
  107. package/dist-skill/library/forgecad-lld/SKILL.md +0 -34
  108. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +0 -50
  109. package/dist-skill/website/skills/forgecad-high-level-spec.md +0 -101
  110. package/dist-skill/website/skills/forgecad-lld.md +0 -41
  111. package/dist-skill/website/skills/forgecad-prepare-prompt.md +0 -63
  112. /package/dist-skill/library/{forgecad-prepare-prompt → forgecad-spec-by-walking-through-it}/references/default-profiles.md +0 -0
  113. /package/dist-skill/library/{forgecad-prepare-prompt → forgecad-spec-by-walking-through-it}/references/master-prompt.md +0 -0
@@ -1,8 +1,8 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { D as DoubleSide, cE as initSolverWasm, cD as initKernel, S as Scene, cF as BoxGeometry, bW as MeshStandardMaterial, a4 as BackSide, b7 as PointLight, M as Mesh, aa as MeshBasicMaterial, cG as localAabbPlaneRelation, h as Vector2, cH as ShapeUtils, cI as analyzePhysicalConnectivity, g as Vector3, $ as Matrix4, cJ as Frustum, G as Box3, a0 as MathUtils, cK as meshContactDataFor, cL as AabbSpatialIndex, cM as detectPhysicalContact, cN as resolveThicknessInspectionOptions, R as Raycaster, cO as thicknessColor, cP as thicknessClass, a$ as BufferAttribute, cQ as roughnessClassForAngle, cR as resolveRoughnessInspectionOptions, cS as roughnessColorForAngle, cT as roughnessScoreForAngle, cU as activateBackend, e as Color, ba as COMPARISON_COLORS, ay as resolveForgeRenderStyle, by as getRenderStylePreset, ax as setParamOverrides, bl as runScript, cn as scanProxyGridForBounds, cV as Group, be as shapeToGeometry, bm as MeshPhysicalMaterial, bw as AdditiveBlending, bB as scanMaterialShellColor, cW as createScanProxyGeometry, aO as LineBasicMaterial, bA as NormalBlending, bn as LineSegments, aN as BufferGeometry, P as PerspectiveCamera, ck as DEFAULT_VIEW_CONFIG, bs as worldAuthorPlaneToLocal, cX as resolveSectionHatchMetrics, cv as buildGeometryComparisonPointCloud, ct as triangleSoupFromMeshes, O as OrthographicCamera, k as ShaderMaterial, bH as ZEBRA_STRIPE_FRAGMENT_SHADER, bI as ZEBRA_STRIPE_VERTEX_SHADER, bC as ZEBRA_STRIPE_SOFTNESS, bD as ZEBRA_STRIPE_SCALE, bE as ZEBRA_LIGHT_COLOR, bF as ZEBRA_DARK_COLOR, bG as ZEBRA_ACCENT_COLOR, bx as geometryWithVisibleVertexColors, cY as intersectWithPlane, cZ as setActiveBackend, W as WebGLRenderer, A as ACESFilmicToneMapping, c as SRGBColorSpace, c_ as parseCameraCliSpec, c$ as PMREMGenerator, b0 as CanvasTexture, b1 as Object3D, b2 as FogExp2, b3 as Fog, b4 as AmbientLight, b8 as DirectionalLight, b5 as HemisphereLight, aI as findJointAnimationClip, p as Plane, bL as SURFACE_FIELD_FRAGMENT_SHADER, bM as SURFACE_FIELD_VERTEX_SHADER, bK as scanMaterialLayerStyles, bJ as SCAN_PROXY_LAYER_STYLES, Y as Vector4, bZ as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bY as buildSdfRaymarchFragmentShader, aJ as resolveJointAnimation, aK as resolveJointViewValues, bR as ROUGHNESS_COLORS, d0 as PointsMaterial, d1 as Points, b9 as heatPointsForSide, d2 as analyzeCollisionIntersections, d3 as serializeCollisionFinding, d4 as summarizeThicknessSamples, bQ as THICKNESS_GRADIENT_COLORS, d5 as THICKNESS_COLORS, b6 as SpotLight, c1 as CylinderGeometry, d6 as TorusGeometry, bO as CatmullRomCurve3, bP as TubeGeometry, cz as resolveScalarSceneSampleBudget, bf as buildComparisonHeatPatchGeometry, bg as EdgesGeometry, d7 as SphereGeometry, d8 as ConeGeometry, bb as comparisonHeatDepthTest, bc as comparisonHeatEdgeOpacity, bd as comparisonHeatPatchOpacity, cB as comparisonCandidateContextOpacity, d9 as DEFAULT_COMPARISON_CANDIDATE_OPACITY } from "../scalar-sampling-budget-prBw_s8t.js";
5
- import { m as mergeViewportRenderSceneStates, v as validateJointOverrides, b as buildBaseJointValues, p as parseRenderSceneCliSpec, g as getSceneObjectTreePath } from "../jointPose-DzQOViQH.js";
4
+ import { D as DoubleSide, a as Scene, bw as BoxGeometry, c1 as MeshStandardMaterial, a5 as BackSide, b2 as PointLight, M as Mesh, af as MeshBasicMaterial, cF as localAabbPlaneRelation, i as Vector2, cG as ShapeUtils, cH as analyzePhysicalConnectivity, h as Vector3, a0 as Matrix4, cI as Frustum, J as Box3, a1 as MathUtils, cJ as meshContactDataFor, cK as AabbSpatialIndex, cL as detectPhysicalContact, cM as resolveThicknessInspectionOptions, R as Raycaster, cN as thicknessColor, cO as thicknessClass, a6 as BufferAttribute, cE as initBackendForEvaluation, f as Color, b5 as COMPARISON_COLORS, aE as resolveForgeRenderStyle, bG as getRenderStylePreset, aD as setParamOverrides, bk as runScript, cp as scanProxyGridForBounds, cP as Group, b9 as shapeToGeometry, bl as MeshPhysicalMaterial, bD as AdditiveBlending, bJ as scanMaterialShellColor, cQ as createScanProxyGeometry, aU as LineBasicMaterial, bI as NormalBlending, bm as LineSegments, P as PerspectiveCamera, cm as DEFAULT_VIEW_CONFIG, bs as worldAuthorPlaneToLocal, cR as resolveSectionHatchMetrics, cv as buildGeometryComparisonPointCloud, ct as triangleSoupFromMeshes, O as OrthographicCamera, l as ShaderMaterial, bP as ZEBRA_STRIPE_FRAGMENT_SHADER, bQ as ZEBRA_STRIPE_VERTEX_SHADER, bK as ZEBRA_STRIPE_SOFTNESS, bL as ZEBRA_STRIPE_SCALE, bM as ZEBRA_LIGHT_COLOR, bN as ZEBRA_DARK_COLOR, bO as ZEBRA_ACCENT_COLOR, bE as geometryWithVisibleVertexColors, cS as intersectWithPlane, cT as setActiveBackend, W as WebGLRenderer, A as ACESFilmicToneMapping, d as SRGBColorSpace, cU as parseCameraCliSpec, cV as PMREMGenerator, aX as CanvasTexture, aY as Object3D, aZ as FogExp2, a_ as Fog, a$ as AmbientLight, b3 as DirectionalLight, b0 as HemisphereLight, aO as findJointAnimationClip, q as Plane, bT as SURFACE_FIELD_FRAGMENT_SHADER, bU as SURFACE_FIELD_VERTEX_SHADER, bS as scanMaterialLayerStyles, bR as SCAN_PROXY_LAYER_STYLES, aP as resolveJointAnimation, aQ as resolveJointViewValues, aT as BufferGeometry, cW as DEFAULT_ROUGHNESS_COLOR_SCALE, cX as PointsMaterial, cY as Points, b4 as heatPointsForSide, cZ as analyzeCollisionIntersections, c_ as serializeCollisionFinding, c$ as summarizeThicknessSamples, d0 as THICKNESS_GRADIENT_COLORS, d1 as THICKNESS_COLORS, d2 as DEFAULT_THICKNESS_COLOR_SCALE, b1 as SpotLight, c5 as CylinderGeometry, d3 as TorusGeometry, bW as CatmullRomCurve3, bX as TubeGeometry, cz as resolveScalarSceneSampleBudget, d4 as sampleColorScale, ba as buildComparisonHeatPatchGeometry, bb as EdgesGeometry, d5 as SphereGeometry, d6 as ConeGeometry, b6 as comparisonHeatDepthTest, b7 as comparisonHeatEdgeOpacity, b8 as comparisonHeatPatchOpacity, cC as comparisonCandidateContextOpacity, d7 as DEFAULT_COMPARISON_CANDIDATE_OPACITY } from "../backendInit-DbTkQN9J.js";
5
+ import { m as mergeViewportRenderSceneStates, v as validateJointOverrides, b as buildBaseJointValues, p as parseRenderSceneCliSpec, g as getSceneObjectTreePath } from "../jointPose-AMvCywzS.js";
6
6
  const CAD_MATERIAL_PROPS = {
7
7
  color: 6003669,
8
8
  metalness: 0.05,
@@ -18,10 +18,6 @@ const EDGE_MATERIAL_PROPS = {
18
18
  transparent: true,
19
19
  opacity: 0.6
20
20
  };
21
- async function init() {
22
- await initSolverWasm();
23
- await initKernel();
24
- }
25
21
  class RoomEnvironment extends Scene {
26
22
  constructor() {
27
23
  super();
@@ -1468,6 +1464,79 @@ function analyzeThicknessGeometry(sourceGeometry, rawOptions = {}, context = {})
1468
1464
  warnings
1469
1465
  };
1470
1466
  }
1467
+ const DEFAULT_ROUGHNESS_INSPECTION_OPTIONS = {
1468
+ smoothAngleDeg: 5,
1469
+ sharpAngleDeg: 30,
1470
+ harshAngleDeg: 90,
1471
+ maxSamplesPerObject: 5e3
1472
+ };
1473
+ const ROUGHNESS_COLORS = {
1474
+ smooth: [62, 72, 84],
1475
+ moderate: [255, 214, 0],
1476
+ sharp: [255, 124, 34],
1477
+ harsh: [255, 42, 96]
1478
+ };
1479
+ function resolveRoughnessInspectionOptions(raw = {}) {
1480
+ const options = {
1481
+ smoothAngleDeg: raw.smoothAngleDeg ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.smoothAngleDeg,
1482
+ sharpAngleDeg: raw.sharpAngleDeg ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.sharpAngleDeg,
1483
+ harshAngleDeg: raw.harshAngleDeg ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.harshAngleDeg,
1484
+ maxSamplesPerObject: raw.maxSamplesPerObject ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.maxSamplesPerObject
1485
+ };
1486
+ if (!Number.isFinite(options.smoothAngleDeg) || options.smoothAngleDeg < 0) {
1487
+ throw new Error(`smoothAngleDeg must be a finite non-negative angle (got ${options.smoothAngleDeg}).`);
1488
+ }
1489
+ if (!Number.isFinite(options.sharpAngleDeg) || options.sharpAngleDeg <= options.smoothAngleDeg) {
1490
+ throw new Error(`sharpAngleDeg must be greater than smoothAngleDeg (got ${options.sharpAngleDeg}).`);
1491
+ }
1492
+ if (!Number.isFinite(options.harshAngleDeg) || options.harshAngleDeg <= options.sharpAngleDeg || options.harshAngleDeg > 180) {
1493
+ throw new Error(`harshAngleDeg must be greater than sharpAngleDeg and <= 180 (got ${options.harshAngleDeg}).`);
1494
+ }
1495
+ if (!Number.isFinite(options.maxSamplesPerObject) || options.maxSamplesPerObject <= 0) {
1496
+ throw new Error(`maxSamplesPerObject must be a positive finite number (got ${options.maxSamplesPerObject}).`);
1497
+ }
1498
+ return {
1499
+ ...options,
1500
+ maxSamplesPerObject: Math.max(1, Math.floor(options.maxSamplesPerObject))
1501
+ };
1502
+ }
1503
+ function roughnessClassForAngle(angleDeg, options) {
1504
+ if (angleDeg >= options.harshAngleDeg) return "harsh";
1505
+ if (angleDeg >= options.sharpAngleDeg) return "sharp";
1506
+ if (angleDeg >= options.smoothAngleDeg) return "moderate";
1507
+ return "smooth";
1508
+ }
1509
+ function roughnessScoreForAngle(angleDeg, options) {
1510
+ if (angleDeg < options.sharpAngleDeg) return 0;
1511
+ if (angleDeg < options.harshAngleDeg) {
1512
+ return MathUtils.lerp(0.48, 0.82, (angleDeg - options.sharpAngleDeg) / (options.harshAngleDeg - options.sharpAngleDeg));
1513
+ }
1514
+ return 1;
1515
+ }
1516
+ function roughnessColorForAngle(angleDeg, options) {
1517
+ const cls = roughnessClassForAngle(angleDeg, options);
1518
+ if (cls === "smooth" || cls === "harsh") return ROUGHNESS_COLORS[cls];
1519
+ if (cls === "moderate") {
1520
+ return lerpRgb(
1521
+ ROUGHNESS_COLORS.moderate,
1522
+ ROUGHNESS_COLORS.sharp,
1523
+ (angleDeg - options.smoothAngleDeg) / (options.sharpAngleDeg - options.smoothAngleDeg)
1524
+ );
1525
+ }
1526
+ return lerpRgb(
1527
+ ROUGHNESS_COLORS.sharp,
1528
+ ROUGHNESS_COLORS.harsh,
1529
+ (angleDeg - options.sharpAngleDeg) / (options.harshAngleDeg - options.sharpAngleDeg)
1530
+ );
1531
+ }
1532
+ function lerpRgb(a, b, t) {
1533
+ const clamped = MathUtils.clamp(t, 0, 1);
1534
+ return [
1535
+ Math.round(MathUtils.lerp(a[0], b[0], clamped)),
1536
+ Math.round(MathUtils.lerp(a[1], b[1], clamped)),
1537
+ Math.round(MathUtils.lerp(a[2], b[2], clamped))
1538
+ ];
1539
+ }
1471
1540
  function emptyRoughnessSummary() {
1472
1541
  return {
1473
1542
  triangleCount: 0,
@@ -2011,7 +2080,7 @@ function summarizeSceneGeometry(entries) {
2011
2080
  const max = [-Infinity, -Infinity, -Infinity];
2012
2081
  let volume = 0;
2013
2082
  for (const entry of entries) {
2014
- const bb = entry.shape ? entry.shape.boundingBox() : entry.sdf ? padSdfBounds(entry.sdf.bounds) : null;
2083
+ const bb = entry.shape ? entry.shape.boundingBox() : null;
2015
2084
  if (!bb) continue;
2016
2085
  for (let axis = 0; axis < 3; axis += 1) {
2017
2086
  min[axis] = Math.min(min[axis], bb.min[axis]);
@@ -2030,14 +2099,6 @@ function summarizeSceneGeometry(entries) {
2030
2099
  }
2031
2100
  return { bbox: { min, max }, volume };
2032
2101
  }
2033
- function padSdfBounds(bounds) {
2034
- const diagonal = Math.hypot(bounds.max[0] - bounds.min[0], bounds.max[1] - bounds.min[1], bounds.max[2] - bounds.min[2]);
2035
- const pad = Math.max(1, diagonal * 0.04);
2036
- return {
2037
- min: [bounds.min[0] - pad, bounds.min[1] - pad, bounds.min[2] - pad],
2038
- max: [bounds.max[0] + pad, bounds.max[1] + pad, bounds.max[2] + pad]
2039
- };
2040
- }
2041
2102
  function rendererContextKeyFor(pixelRatio) {
2042
2103
  const antialias = pixelRatio <= 1.25;
2043
2104
  return `aa:${antialias ? "1" : "0"};preserve:0;logDepth:0`;
@@ -2115,98 +2176,6 @@ function getStudioEnvironment(r) {
2115
2176
  pmrem.dispose();
2116
2177
  return studioEnvTexture;
2117
2178
  }
2118
- const BLACK_RGB = [0, 0, 0];
2119
- const MAX_SDF_CLIP_PLANES = 8;
2120
- function clamp01(value) {
2121
- return Math.min(1, Math.max(0, value));
2122
- }
2123
- function colorToRgb(value, fallback = "#5b9bd5") {
2124
- const color = new Color(value || fallback);
2125
- return [color.r, color.g, color.b];
2126
- }
2127
- function setSdfClipPlaneUniforms(target, clippingPlanes) {
2128
- const count = Math.min(clippingPlanes.length, MAX_SDF_CLIP_PLANES);
2129
- for (let i = 0; i < MAX_SDF_CLIP_PLANES; i += 1) {
2130
- const plane = clippingPlanes[i];
2131
- target[i].set((plane == null ? void 0 : plane.normal.x) ?? 0, (plane == null ? void 0 : plane.normal.y) ?? 0, (plane == null ? void 0 : plane.normal.z) ?? 0, (plane == null ? void 0 : plane.constant) ?? 0);
2132
- }
2133
- return count;
2134
- }
2135
- function createSdfRaymarchRuntime(entry, clippingPlanes) {
2136
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2137
- if (!entry.sdf) {
2138
- throw new Error("Internal render error: createSdfRaymarchRuntime() requires an SDF entry.");
2139
- }
2140
- const sdf = entry.sdf;
2141
- const bounds = padSdfBounds(sdf.bounds);
2142
- const materialAlpha = ((_a = sdf.materialProps) == null ? void 0 : _a.opacity) ?? 1;
2143
- const leaf = {
2144
- node: sdf.node,
2145
- color: colorToRgb(entry.color ?? sdf.colorHex),
2146
- alpha: clamp01(Math.min(entry.opacity, materialAlpha)),
2147
- emissive: ((_b = sdf.materialProps) == null ? void 0 : _b.emissive) ? colorToRgb(sdf.materialProps.emissive, "#000000") : BLACK_RGB,
2148
- emissiveIntensity: ((_c = sdf.materialProps) == null ? void 0 : _c.emissiveIntensity) ?? 0,
2149
- metalness: clamp01(((_d = sdf.materialProps) == null ? void 0 : _d.metalness) ?? 0.05),
2150
- roughness: clamp01(((_e = sdf.materialProps) == null ? void 0 : _e.roughness) ?? 0.35),
2151
- clearcoat: clamp01(((_f = sdf.materialProps) == null ? void 0 : _f.clearcoat) ?? 0.1),
2152
- clearcoatRoughness: clamp01(((_g = sdf.materialProps) == null ? void 0 : _g.clearcoatRoughness) ?? 0.4),
2153
- transmission: clamp01(((_h = sdf.materialProps) == null ? void 0 : _h.transmission) ?? 0),
2154
- reflectivity: clamp01(((_i = sdf.materialProps) == null ? void 0 : _i.reflectivity) ?? 0.5)
2155
- };
2156
- const clipPlaneUniforms = Array.from({ length: MAX_SDF_CLIP_PLANES }, () => new Vector4());
2157
- const material = new ShaderMaterial({
2158
- vertexShader: SDF_RAYMARCH_PROXY_VERTEX_SHADER,
2159
- fragmentShader: buildSdfRaymarchFragmentShader([leaf]),
2160
- side: BackSide,
2161
- transparent: leaf.alpha < 1 || leaf.transmission > 0,
2162
- depthTest: true,
2163
- depthWrite: leaf.alpha >= 1 && leaf.transmission <= 0,
2164
- uniforms: {
2165
- uCameraMatrixWorld: { value: new Matrix4() },
2166
- uViewProjectionMatrix: { value: new Matrix4() },
2167
- uSceneMin: { value: new Vector3() },
2168
- uSceneMax: { value: new Vector3() },
2169
- uClipPlaneCount: { value: 0 },
2170
- uClipPlanes: { value: clipPlaneUniforms },
2171
- uHoverLeafIndex: { value: -1 },
2172
- uHoverColor: { value: new Vector3() },
2173
- uHoverIntensity: { value: 0 },
2174
- uIsOrthographic: { value: 0 }
2175
- }
2176
- });
2177
- const size = [
2178
- Math.max(bounds.max[0] - bounds.min[0], 1e-3),
2179
- Math.max(bounds.max[1] - bounds.min[1], 1e-3),
2180
- Math.max(bounds.max[2] - bounds.min[2], 1e-3)
2181
- ];
2182
- const center = [
2183
- (bounds.min[0] + bounds.max[0]) * 0.5,
2184
- (bounds.min[1] + bounds.max[1]) * 0.5,
2185
- (bounds.min[2] + bounds.max[2]) * 0.5
2186
- ];
2187
- const mesh = new Mesh(new BoxGeometry(...size), material);
2188
- mesh.position.set(center[0], center[1], center[2]);
2189
- mesh.frustumCulled = false;
2190
- return {
2191
- mesh,
2192
- material,
2193
- runtime: { bounds, material, clippingPlanes, clipPlaneUniforms }
2194
- };
2195
- }
2196
- function updateSdfRaymarchUniforms(session) {
2197
- const viewProjection = new Matrix4().multiplyMatrices(session.camera.projectionMatrix, session.camera.matrixWorldInverse);
2198
- const isOrthographic = session.camera.isOrthographicCamera ? 1 : 0;
2199
- for (const renderable of session.renderables) {
2200
- const sdf = renderable.sdfRaymarch;
2201
- if (!sdf) continue;
2202
- sdf.material.uniforms.uCameraMatrixWorld.value.copy(session.camera.matrixWorld);
2203
- sdf.material.uniforms.uViewProjectionMatrix.value.copy(viewProjection);
2204
- sdf.material.uniforms.uSceneMin.value.set(sdf.bounds.min[0], sdf.bounds.min[1], sdf.bounds.min[2]);
2205
- sdf.material.uniforms.uSceneMax.value.set(sdf.bounds.max[0], sdf.bounds.max[1], sdf.bounds.max[2]);
2206
- sdf.material.uniforms.uClipPlaneCount.value = setSdfClipPlaneUniforms(sdf.clipPlaneUniforms, sdf.clippingPlanes);
2207
- sdf.material.uniforms.uIsOrthographic.value = isOrthographic;
2208
- }
2209
- }
2210
2179
  function applyDirectionCamera(session, dir, distanceOverride) {
2211
2180
  const d = normalizeCameraDirection(dir);
2212
2181
  const fov = session.camera instanceof PerspectiveCamera ? session.camera.fov : 45;
@@ -2222,7 +2191,6 @@ function applyDirectionCamera(session, dir, distanceOverride) {
2222
2191
  }
2223
2192
  function renderCurrentRgb(session) {
2224
2193
  const r = getRenderer(session.size, session.pixelRatio);
2225
- updateSdfRaymarchUniforms(session);
2226
2194
  r.render(session.scene, session.camera);
2227
2195
  return captureRenderedPng(session.size);
2228
2196
  }
@@ -2423,7 +2391,6 @@ function renderSessionCoverageImageData(session, color) {
2423
2391
  () => withSolidOnlyVisibility(
2424
2392
  session,
2425
2393
  () => withTemporarySceneBackground(session, new Color(0), () => {
2426
- updateSdfRaymarchUniforms(session);
2427
2394
  r.clear(true, true, true);
2428
2395
  r.render(session.scene, session.camera);
2429
2396
  return captureRenderedImageData(session.size);
@@ -2737,7 +2704,6 @@ function renderCurrentDepth(session) {
2737
2704
  const png = withSolidOnlyVisibility(
2738
2705
  session,
2739
2706
  () => withTemporarySceneBackground(session, new Color(0), () => {
2740
- updateSdfRaymarchUniforms(session);
2741
2707
  r.render(session.scene, session.camera);
2742
2708
  return captureRenderedPng(session.size);
2743
2709
  })
@@ -2774,7 +2740,6 @@ function renderCurrentNormals(session) {
2774
2740
  return withSolidOnlyVisibility(
2775
2741
  session,
2776
2742
  () => withTemporarySceneBackground(session, new Color(0), () => {
2777
- updateSdfRaymarchUniforms(session);
2778
2743
  r.render(session.scene, session.camera);
2779
2744
  return captureRenderedPng(session.size);
2780
2745
  })
@@ -2805,7 +2770,6 @@ function renderCurrentZebra(session) {
2805
2770
  return withSolidOnlyVisibility(
2806
2771
  session,
2807
2772
  () => withTemporarySceneBackground(session, new Color(0), () => {
2808
- updateSdfRaymarchUniforms(session);
2809
2773
  r.render(session.scene, session.camera);
2810
2774
  return captureRenderedPng(session.size);
2811
2775
  })
@@ -2899,7 +2863,6 @@ function renderCurrentMask(session) {
2899
2863
  const png = withSolidOnlyVisibility(
2900
2864
  session,
2901
2865
  () => withTemporarySceneBackground(session, new Color(0), () => {
2902
- updateSdfRaymarchUniforms(session);
2903
2866
  r.render(session.scene, session.camera);
2904
2867
  return captureRenderedPng(session.size);
2905
2868
  })
@@ -3202,7 +3165,6 @@ function renderCurrentRig(session) {
3202
3165
  session.scene.add(group);
3203
3166
  try {
3204
3167
  const png = withTemporarySceneBackground(session, new Color(132105), () => {
3205
- updateSdfRaymarchUniforms(session);
3206
3168
  r.render(session.scene, session.camera);
3207
3169
  return captureRenderedPng(session.size);
3208
3170
  });
@@ -3243,9 +3205,7 @@ function baseObjectIdForConnectivityEntry(entryId, renderableIds) {
3243
3205
  }
3244
3206
  function buildThicknessRaycastConnectivityContext(session) {
3245
3207
  const report = analyzeSessionConnectivity(session);
3246
- const renderableById = new Map(
3247
- session.renderables.filter((renderable) => !renderable.sdfRaymarch).map((renderable) => [renderable.id, renderable])
3248
- );
3208
+ const renderableById = new Map(session.renderables.map((renderable) => [renderable.id, renderable]));
3249
3209
  const renderableIds = new Set(renderableById.keys());
3250
3210
  const neighborIdsByObjectId = /* @__PURE__ */ new Map();
3251
3211
  for (const edge of report.edges) {
@@ -3326,7 +3286,6 @@ function renderCurrentConnectivity(session, rawReport) {
3326
3286
  const png = withSolidOnlyVisibility(
3327
3287
  session,
3328
3288
  () => withTemporarySceneBackground(session, new Color(0), () => {
3329
- updateSdfRaymarchUniforms(session);
3330
3289
  r.render(session.scene, session.camera);
3331
3290
  return captureRenderedPng(session.size);
3332
3291
  })
@@ -3420,7 +3379,6 @@ function renderCurrentDistance(session) {
3420
3379
  const png = withSolidOnlyVisibility(
3421
3380
  session,
3422
3381
  () => withTemporarySceneBackground(session, new Color(0), () => {
3423
- updateSdfRaymarchUniforms(session);
3424
3382
  r.render(session.scene, session.camera);
3425
3383
  return captureRenderedPng(session.size);
3426
3384
  })
@@ -3551,7 +3509,6 @@ function renderCurrentFloating(session) {
3551
3509
  });
3552
3510
  try {
3553
3511
  const png = withTemporarySceneBackground(session, new Color(0), () => {
3554
- updateSdfRaymarchUniforms(session);
3555
3512
  r.render(session.scene, session.camera);
3556
3513
  return captureRenderedPng(session.size);
3557
3514
  });
@@ -3669,7 +3626,6 @@ function renderCurrentCollisions(session) {
3669
3626
  const png = withSolidOnlyVisibility(
3670
3627
  session,
3671
3628
  () => withTemporarySceneBackground(session, new Color(0), () => {
3672
- updateSdfRaymarchUniforms(session);
3673
3629
  r.render(session.scene, session.camera);
3674
3630
  return captureRenderedPng(session.size);
3675
3631
  })
@@ -3692,7 +3648,7 @@ function inspectionOptionsKey(value) {
3692
3648
  return JSON.stringify(value ?? {});
3693
3649
  }
3694
3650
  function scalarInspectableObjectCount(session) {
3695
- return session.renderables.filter((renderable) => !renderable.sdfRaymarch).length;
3651
+ return session.renderables.length;
3696
3652
  }
3697
3653
  function withSceneSampleBudget(session, options, explicitMaxSamplesPerObject) {
3698
3654
  const sampleBudget = resolveScalarSceneSampleBudget({
@@ -3719,7 +3675,7 @@ function bboxFromGeometry(geometry) {
3719
3675
  max: bbox ? [bbox.max.x, bbox.max.y, bbox.max.z] : [0, 0, 0]
3720
3676
  };
3721
3677
  }
3722
- function pointBuffersFromSamples(samples, offset = 0.025) {
3678
+ function pointBuffersFromSamples(samples, colorScale, offset = 0.025) {
3723
3679
  const positions = new Float32Array(samples.length * 3);
3724
3680
  const colors = new Float32Array(samples.length * 3);
3725
3681
  samples.forEach((sample, index) => {
@@ -3727,9 +3683,16 @@ function pointBuffersFromSamples(samples, offset = 0.025) {
3727
3683
  positions[base] = sample.position[0] + sample.normal[0] * offset;
3728
3684
  positions[base + 1] = sample.position[1] + sample.normal[1] * offset;
3729
3685
  positions[base + 2] = sample.position[2] + sample.normal[2] * offset;
3730
- colors[base] = sample.color[0] / 255;
3731
- colors[base + 1] = sample.color[1] / 255;
3732
- colors[base + 2] = sample.color[2] / 255;
3686
+ if (colorScale && sample.value != null && Number.isFinite(sample.value)) {
3687
+ const [r, g, b] = sampleColorScale(colorScale, sample.value);
3688
+ colors[base] = r / 255;
3689
+ colors[base + 1] = g / 255;
3690
+ colors[base + 2] = b / 255;
3691
+ } else {
3692
+ colors[base] = sample.color[0] / 255;
3693
+ colors[base + 1] = sample.color[1] / 255;
3694
+ colors[base + 2] = sample.color[2] / 255;
3695
+ }
3733
3696
  });
3734
3697
  return { positions, colors };
3735
3698
  }
@@ -3774,7 +3737,6 @@ function renderScalarPointOverlays(session, overlays) {
3774
3737
  return withSolidOnlyVisibility(
3775
3738
  session,
3776
3739
  () => withTemporarySceneBackground(session, new Color(0), () => {
3777
- updateSdfRaymarchUniforms(session);
3778
3740
  r.render(session.scene, session.camera);
3779
3741
  return captureRenderedPng(session.size);
3780
3742
  })
@@ -3798,6 +3760,11 @@ function getSessionThicknessInspection(session, rawOptions) {
3798
3760
  const byId = new Map(session.objects.map((obj) => [obj.id, obj]));
3799
3761
  const warnings = [];
3800
3762
  maybePushSceneSampleBudgetWarning(warnings, "Thickness", sampleBudget);
3763
+ const thicknessColorScale = {
3764
+ colormap: DEFAULT_THICKNESS_COLOR_SCALE.colormap,
3765
+ domainMin: options.colorMinThickness,
3766
+ domainMax: options.colorMaxThickness
3767
+ };
3801
3768
  const objects = [];
3802
3769
  const cloudObjects = [];
3803
3770
  const points = [];
@@ -3805,10 +3772,6 @@ function getSessionThicknessInspection(session, rawOptions) {
3805
3772
  const raycastConnectivity = buildThicknessRaycastConnectivityContext(session);
3806
3773
  session.renderables.forEach((renderable, index) => {
3807
3774
  const sourceObject = byId.get(renderable.id);
3808
- if (renderable.sdfRaymarch) {
3809
- warnings.push(`${renderable.name}: SDF raymarch objects are not included in mesh thickness inspection.`);
3810
- return;
3811
- }
3812
3775
  const analysis = analyzeThicknessGeometry(renderable.solid.geometry, options, {
3813
3776
  connectedGeometries: connectedThicknessGeometriesFor(raycastConnectivity, renderable)
3814
3777
  });
@@ -3849,7 +3812,7 @@ function getSessionThicknessInspection(session, rawOptions) {
3849
3812
  ...sample
3850
3813
  });
3851
3814
  });
3852
- overlays.push({ renderable, ...pointBuffersFromSamples(analysis.pointSamples) });
3815
+ overlays.push({ renderable, ...pointBuffersFromSamples(analysis.pointSamples, thicknessColorScale) });
3853
3816
  analysis.geometry.dispose();
3854
3817
  });
3855
3818
  const state = {
@@ -3872,7 +3835,10 @@ function getSessionThicknessInspection(session, rawOptions) {
3872
3835
  objects,
3873
3836
  warnings,
3874
3837
  style: {
3838
+ // gradientColors is the legacy 'thickness-classic' rainbow, kept for
3839
+ // back-compat. colorScale is the truth the viewport/CLI now render with.
3875
3840
  gradientColors: THICKNESS_GRADIENT_COLORS.map((color) => [...color]),
3841
+ colorScale: thicknessColorScale,
3876
3842
  colorMinThickness: options.colorMinThickness,
3877
3843
  colorMaxThickness: options.colorMaxThickness,
3878
3844
  unknownColor: THICKNESS_COLORS.unknown
@@ -3905,12 +3871,22 @@ function getSessionRoughnessInspection(session, rawOptions) {
3905
3871
  const cloudObjects = [];
3906
3872
  const points = [];
3907
3873
  const overlays = [];
3908
- session.renderables.forEach((renderable, index) => {
3909
- if (renderable.sdfRaymarch) {
3910
- warnings.push(`${renderable.name}: SDF raymarch objects are not included in mesh roughness inspection.`);
3911
- return;
3912
- }
3874
+ let roughnessMin = Infinity;
3875
+ let roughnessMax = -Infinity;
3876
+ const analysesByIndex = [];
3877
+ session.renderables.forEach((renderable) => {
3913
3878
  const analysis = analyzeRoughnessGeometry(renderable.solid.geometry, options);
3879
+ analysesByIndex.push(analysis);
3880
+ for (const sample of analysis.pointSamples) {
3881
+ if (sample.value != null && Number.isFinite(sample.value)) {
3882
+ if (sample.value < roughnessMin) roughnessMin = sample.value;
3883
+ if (sample.value > roughnessMax) roughnessMax = sample.value;
3884
+ }
3885
+ }
3886
+ });
3887
+ const roughnessColorScale = Number.isFinite(roughnessMin) && roughnessMax > roughnessMin ? { colormap: DEFAULT_ROUGHNESS_COLOR_SCALE.colormap, domainMin: roughnessMin, domainMax: roughnessMax } : DEFAULT_ROUGHNESS_COLOR_SCALE;
3888
+ session.renderables.forEach((renderable, index) => {
3889
+ const analysis = analysesByIndex[index];
3914
3890
  const bbox = bboxFromGeometry(analysis.geometry);
3915
3891
  const sourceObject = byId.get(renderable.id);
3916
3892
  if (analysis.warnings.length > 0) {
@@ -3945,7 +3921,7 @@ function getSessionRoughnessInspection(session, rawOptions) {
3945
3921
  ...sample
3946
3922
  });
3947
3923
  });
3948
- overlays.push({ renderable, ...pointBuffersFromSamples(analysis.pointSamples) });
3924
+ overlays.push({ renderable, ...pointBuffersFromSamples(analysis.pointSamples, roughnessColorScale) });
3949
3925
  analysis.geometry.dispose();
3950
3926
  });
3951
3927
  const state = {
@@ -3968,6 +3944,9 @@ function getSessionRoughnessInspection(session, rawOptions) {
3968
3944
  objects,
3969
3945
  warnings,
3970
3946
  style: {
3947
+ // Legacy class colors kept for back-compat; colorScale is the truth the
3948
+ // viewport/CLI now render with (continuous viridis over the data domain).
3949
+ colorScale: roughnessColorScale,
3971
3950
  smoothColor: ROUGHNESS_COLORS.smooth,
3972
3951
  moderateColor: ROUGHNESS_COLORS.moderate,
3973
3952
  sharpColor: ROUGHNESS_COLORS.sharp,
@@ -5007,7 +4986,6 @@ function renderCaptureFrame(session, opts) {
5007
4986
  captureMark("capsMs");
5008
4987
  const r = getRenderer(session.size, session.pixelRatio);
5009
4988
  session.scene.updateMatrixWorld(true);
5010
- updateSdfRaymarchUniforms(session);
5011
4989
  r.render(session.scene, session.camera);
5012
4990
  captureMark("renderMs");
5013
4991
  const png = captureRenderedImage(session.size, (opts == null ? void 0 : opts.imageFormat) === "jpeg" ? "jpeg" : "png", (opts == null ? void 0 : opts.jpegQuality) ?? 0.96);
@@ -5143,20 +5121,32 @@ function createSession(code, opts) {
5143
5121
  }
5144
5122
  const focus = (opts == null ? void 0 : opts.focus) ?? null;
5145
5123
  const hide = (opts == null ? void 0 : opts.hide) ?? null;
5146
- const objs = result.objects.map((obj) => {
5124
+ const mappedEntries = result.objects.map((obj) => {
5147
5125
  var _a2, _b2, _c2, _d2, _e2, _f2, _g2;
5148
5126
  return {
5149
5127
  source: obj,
5150
5128
  shape: obj.shape || (obj.sketch ? obj.sketch.extrude(1) : null),
5151
- sdf: obj.sdf ?? null,
5152
5129
  color: ((_b2 = (_a2 = requestedSceneState == null ? void 0 : requestedSceneState.objects) == null ? void 0 : _a2[obj.id]) == null ? void 0 : _b2.color) ?? obj.color,
5153
5130
  materialProps: obj.materialProps,
5154
5131
  opacity: MathUtils.clamp(((_d2 = (_c2 = requestedSceneState == null ? void 0 : requestedSceneState.objects) == null ? void 0 : _c2[obj.id]) == null ? void 0 : _d2.opacity) ?? ((_e2 = obj.materialProps) == null ? void 0 : _e2.opacity) ?? 1, 0, 1),
5155
5132
  visible: ((_g2 = (_f2 = requestedSceneState == null ? void 0 : requestedSceneState.objects) == null ? void 0 : _f2[obj.id]) == null ? void 0 : _g2.visible) !== false && isFocusVisible(obj, focus, hide)
5156
5133
  };
5157
- }).filter((entry) => entry.shape != null || entry.sdf != null);
5134
+ });
5135
+ const sdfOnlyNames = mappedEntries.filter((entry) => entry.shape == null && entry.visible && entry.source.sdf).map((entry) => entry.source.name);
5136
+ if (sdfOnlyNames.length > 0) {
5137
+ return {
5138
+ ok: false,
5139
+ error: `CLI rendering is mesh-based and cannot raymarch raw SDF fields. ${sdfOnlyNames.length} object(s) returned raw SDFs without mesh geometry: ${sdfOnlyNames.map((name) => `"${name}"`).join(", ")}.
5140
+ Fix one:
5141
+ - Mesh the field in-script: return toShape(mySdf) (or mySdf.toShape())
5142
+ - Export the raw field instead: forgecad export implicit <model.forge.js>`
5143
+ };
5144
+ }
5145
+ const objs = mappedEntries.filter(
5146
+ (entry) => entry.shape != null
5147
+ );
5158
5148
  if (objs.length === 0) {
5159
- return { ok: false, error: "No renderable shape or SDF returned" };
5149
+ return { ok: false, error: "No mesh-backed renderable shape returned" };
5160
5150
  }
5161
5151
  const visibleObjs = objs.filter((entry) => entry.visible);
5162
5152
  if (visibleObjs.length === 0) {
@@ -5166,8 +5156,7 @@ function createSession(code, opts) {
5166
5156
  totalObjects: result.objects.length,
5167
5157
  renderableObjects: objs.length,
5168
5158
  visibleObjects: visibleObjs.length,
5169
- shapeObjects: visibleObjs.filter((entry) => entry.shape != null).length,
5170
- sdfObjects: visibleObjs.filter((entry) => entry.sdf != null).length
5159
+ shapeObjects: visibleObjs.filter((entry) => entry.shape != null).length
5171
5160
  });
5172
5161
  const boundsObjs = selectRenderSceneBoundsEntries(objs);
5173
5162
  const objectVisibility = new Map(objs.map((entry) => [entry.source.id, entry.visible]));
@@ -5361,8 +5350,7 @@ function createSession(code, opts) {
5361
5350
  total: visibleObjs.length,
5362
5351
  id: obj.source.id,
5363
5352
  name: objectLabel,
5364
- hasShape: Boolean(obj.shape),
5365
- hasSdf: Boolean(obj.sdf)
5353
+ hasShape: Boolean(obj.shape)
5366
5354
  });
5367
5355
  const applicableCutPlanes = activeCutPlanes.filter((cutPlane) => !isObjectExcludedFromCutPlane(obj.source, cutPlane)).map(toClippingPlane);
5368
5356
  if (sweep && !isObjectExcludedFromCutPlane(obj.source, { normal: sweep.normal, offset: sweep.from })) {
@@ -5377,9 +5365,8 @@ function createSession(code, opts) {
5377
5365
  let shell;
5378
5366
  let scanProxy;
5379
5367
  let wireMaterial;
5380
- let sdfRaymarch;
5381
5368
  let sectionMesh = null;
5382
- if (obj.shape) {
5369
+ {
5383
5370
  const geometryStart = performance.now();
5384
5371
  const geo = shapeToGeometry(obj.shape);
5385
5372
  debug("renderable:geometry", {
@@ -5489,27 +5476,6 @@ function createSession(code, opts) {
5489
5476
  });
5490
5477
  wire = new LineSegments(geo.edges, wireMaterial);
5491
5478
  sectionMesh = sweep ? buildSectionMeshPayload(obj.source.id, obj.shape, debug, objectLabel) : null;
5492
- } else if (obj.sdf) {
5493
- const sdfStart = performance.now();
5494
- const sdfRenderable = createSdfRaymarchRuntime(obj, applicableCutPlanes);
5495
- debug("renderable:sdf", {
5496
- index: renderableIndex + 1,
5497
- id: obj.source.id,
5498
- name: objectLabel,
5499
- ms: Number((performance.now() - sdfStart).toFixed(1))
5500
- });
5501
- solid = sdfRenderable.mesh;
5502
- solidMaterial = sdfRenderable.material;
5503
- sdfRaymarch = sdfRenderable.runtime;
5504
- wireMaterial = new LineBasicMaterial({
5505
- ...EDGE_MATERIAL_PROPS,
5506
- color: parseColor(obj.color, EDGE_MATERIAL_PROPS.color),
5507
- transparent: true,
5508
- opacity: 0
5509
- });
5510
- wire = new LineSegments(new BufferGeometry(), wireMaterial);
5511
- } else {
5512
- continue;
5513
5479
  }
5514
5480
  root.add(solid);
5515
5481
  if (shell) root.add(shell);
@@ -5533,8 +5499,7 @@ function createSession(code, opts) {
5533
5499
  sourceColor: obj.color ?? "#5b9bd5",
5534
5500
  opacity: obj.opacity,
5535
5501
  sectionMesh,
5536
- sectionCapGroup,
5537
- ...sdfRaymarch ? { sdfRaymarch } : {}
5502
+ sectionCapGroup
5538
5503
  });
5539
5504
  }
5540
5505
  const renderableById = new Map(renderables.map((renderable) => [renderable.id, renderable]));
@@ -5637,8 +5602,7 @@ function createSession(code, opts) {
5637
5602
  debug("session:ready");
5638
5603
  return { ok: true, session };
5639
5604
  }
5640
- async function setup() {
5641
- await init();
5605
+ function setup() {
5642
5606
  setActiveBackend(CLI_DEFAULT_BACKEND);
5643
5607
  window.__forgeCaptureCapabilities = CAPTURE_RUNTIME_CAPABILITIES;
5644
5608
  window.__forgeReady = true;
@@ -5666,9 +5630,8 @@ window.__forgeRender = async (code, opts) => {
5666
5630
  const requestedChannelList = (opts == null ? void 0 : opts.channels) ?? ["rgb"];
5667
5631
  const requestedChannels = new Set(requestedChannelList);
5668
5632
  await emitInspectProgress(opts, { type: "session-start" });
5669
- if (opts == null ? void 0 : opts.activeBackend) {
5670
- await activateBackend(opts.activeBackend);
5671
- }
5633
+ const activeBackend = (opts == null ? void 0 : opts.activeBackend) ?? CLI_DEFAULT_BACKEND;
5634
+ await initBackendForEvaluation(activeBackend);
5672
5635
  const built = createSession(code, {
5673
5636
  size: (opts == null ? void 0 : opts.size) || 1024,
5674
5637
  pixelRatio: (opts == null ? void 0 : opts.pixelRatio) || 1,
@@ -5676,7 +5639,7 @@ window.__forgeRender = async (code, opts) => {
5676
5639
  allFiles: opts == null ? void 0 : opts.allFiles,
5677
5640
  binaryFiles: opts == null ? void 0 : opts.binaryFiles,
5678
5641
  fileName: opts == null ? void 0 : opts.fileName,
5679
- activeBackend: opts == null ? void 0 : opts.activeBackend,
5642
+ activeBackend,
5680
5643
  background: opts == null ? void 0 : opts.background,
5681
5644
  camera: opts == null ? void 0 : opts.camera,
5682
5645
  cameraSpec: opts == null ? void 0 : opts.cameraSpec,
@@ -5708,9 +5671,8 @@ window.__forgeRender = async (code, opts) => {
5708
5671
  disposeSession(session);
5709
5672
  return { ok: false, error: "comparison evidence requires --compare-with <reference> or compareWith(path) in the model." };
5710
5673
  }
5711
- if (comparisonReference.activeBackend) {
5712
- await activateBackend(comparisonReference.activeBackend);
5713
- }
5674
+ const comparisonBackend = comparisonReference.activeBackend ?? activeBackend;
5675
+ await initBackendForEvaluation(comparisonBackend);
5714
5676
  const referenceBuilt = createSession(comparisonReference.code, {
5715
5677
  size: (opts == null ? void 0 : opts.size) || 1024,
5716
5678
  pixelRatio: (opts == null ? void 0 : opts.pixelRatio) || 1,
@@ -5718,7 +5680,7 @@ window.__forgeRender = async (code, opts) => {
5718
5680
  allFiles: comparisonReference.allFiles,
5719
5681
  binaryFiles: comparisonReference.binaryFiles,
5720
5682
  fileName: comparisonReference.fileName,
5721
- activeBackend: comparisonReference.activeBackend ?? (opts == null ? void 0 : opts.activeBackend),
5683
+ activeBackend: comparisonBackend,
5722
5684
  background: opts == null ? void 0 : opts.background,
5723
5685
  renderStyle: opts == null ? void 0 : opts.renderStyle,
5724
5686
  scanGranularity: opts == null ? void 0 : opts.scanGranularity,
@@ -6054,10 +6016,9 @@ window.__forgeRender = async (code, opts) => {
6054
6016
  window.__forgeCaptureInit = async (code, opts) => {
6055
6017
  var _a;
6056
6018
  destroyCaptureSession();
6057
- if (opts == null ? void 0 : opts.activeBackend) {
6058
- await activateBackend(opts.activeBackend);
6059
- }
6060
- const built = createSession(code, opts);
6019
+ const activeBackend = (opts == null ? void 0 : opts.activeBackend) ?? CLI_DEFAULT_BACKEND;
6020
+ await initBackendForEvaluation(activeBackend);
6021
+ const built = createSession(code, { ...opts, activeBackend });
6061
6022
  if (!built.ok) {
6062
6023
  return built;
6063
6024
  }