forgecad 0.10.3 → 0.10.4

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 (99) hide show
  1. package/dist/assets/{AdminPage-CK7ObBz3.js → AdminPage-B3L3W1Uo.js} +1 -1
  2. package/dist/assets/{BenchmarkPage-Ds7Z2doN.js → BenchmarkPage-DXKVXMrJ.js} +2 -2
  3. package/dist/assets/{BlogPage-DlPbpt6A.js → BlogPage-B7BWxOCg.js} +1 -1
  4. package/dist/assets/{DocsPage-vZb3b3Y0.js → DocsPage-BPGGwht1.js} +28 -43
  5. package/dist/assets/{EditorApp-HLoKfe15.js → EditorApp-BWUGCdD5.js} +49 -16
  6. package/dist/assets/{EmbedViewer--KnqBKrJ.js → EmbedViewer-DygByZS2.js} +2 -2
  7. package/dist/assets/{LandingPageProofDriven-C_LssmnA.js → LandingPageProofDriven-BoVE7JGY.js} +54 -36
  8. package/dist/assets/{LegalPage-DGsyo4n1.js → LegalPage-Din8wv8d.js} +2 -2
  9. package/dist/assets/{PricingPage-BOE27B-R.js → PricingPage-C2PMzmDc.js} +2 -2
  10. package/dist/assets/{SettingsPage-f47cnk39.js → SettingsPage-BlJDCRe8.js} +1 -1
  11. package/dist/assets/{app-D6ccu2Xx.js → app-BsRYSfxY.js} +238 -3714
  12. package/dist/assets/{backendInit-DbTkQN9J.js → backendInit-6C0DLgH0.js} +5972 -1566
  13. package/dist/assets/cli/{render-BsngirjC.js → render-XXol_ET7.js} +724 -112
  14. package/dist/assets/{constructionHistoryWorker-PCwXrTDB.js → constructionHistoryWorker-cTHWRJEi.js} +528 -252
  15. package/dist/assets/{evalWorker-CS63PfZu.js → evalWorker-BssDYW9u.js} +1453 -902
  16. package/dist/assets/{inspectWorker-Y4cOzNyA.js → inspectWorker-ymhBV4Ll.js} +2635 -1024
  17. package/dist/assets/{jointPose-AMvCywzS.js → jointPose-B0blBj9A.js} +1 -1
  18. package/dist/assets/{landing-proof-driven-ORyigZ6p.css → landing-proof-driven-Cpf-MIbI.css} +73 -13
  19. package/dist/assets/{manifold-Crd_F2qx.js → manifold-B_7QXpGB.js} +1 -1
  20. package/dist/assets/{manifold-k2kRcc85.js → manifold-CNShmpEJ.js} +1 -1
  21. package/dist/assets/{manifold-CBry38ly.js → manifold-CYlIm-M6.js} +2 -2
  22. package/dist/assets/{reportWorker-CWvn0CEv.js → reportWorker-Cb5eyM7D.js} +1407 -892
  23. package/dist/cli/render.html +1 -1
  24. package/dist/docs/index.html +2 -2
  25. package/dist/docs-raw/AI/usage.md +17 -15
  26. package/dist/docs-raw/component-model.md +2 -2
  27. package/dist/docs-raw/generated/concepts.md +5 -1
  28. package/dist/docs-raw/generated/core.md +26 -0
  29. package/dist/docs-raw/generated/runtime-names.md +1 -1
  30. package/dist/docs-raw/guides/inspection-bundles.md +1 -1
  31. package/dist/docs-raw/simulation-workflow.md +1 -1
  32. package/dist/docs-raw/skills/{forgecad-make-a-model.md → forgecad-build-model.md} +18 -8
  33. package/dist/docs-raw/skills/{forgecad-spec-by-walking-through-it.md → forgecad-design-spec.md} +6 -6
  34. package/dist/docs-raw/skills/{forgecad-model-grader.md → forgecad-grade-model.md} +8 -6
  35. package/{dist-skill/website/skills/forgecad-visual-spec.md → dist/docs-raw/skills/forgecad-image-prompt.md} +7 -7
  36. package/dist/docs-raw/skills/{forgecad-render-inspect.md → forgecad-inspect-model.md} +6 -6
  37. package/{dist-skill/website/skills/forgecad-project.md → dist/docs-raw/skills/forgecad-project-sync.md} +5 -5
  38. package/dist/docs-raw/skills/{forgecad-3d-reconstruction.md → forgecad-reconstruct-cad-file.md} +7 -7
  39. package/dist/docs-raw/skills/{forgecad-image-replicator.md → forgecad-reconstruct-from-images.md} +12 -12
  40. package/dist/docs-raw/skills/{forgecad-mujoco-verify.md → forgecad-verify-mujoco.md} +6 -6
  41. package/dist/docs-raw/skills/index.md +9 -12
  42. package/dist/index.html +9 -9
  43. package/dist/llms.txt +7 -7
  44. package/dist/sitemap.xml +16 -16
  45. package/dist-cli/{check-compiler-HPF2T2FS.js → check-compiler-4RPB6SB5.js} +1 -1
  46. package/dist-cli/{check-query-propagation-HYSLTXAB.js → check-query-propagation-KN3DFQTX.js} +1 -1
  47. package/dist-cli/{chunk-WLUKAW3H.js → chunk-UHBRMYA6.js} +28802 -28152
  48. package/dist-cli/forgecad.js +660 -9
  49. package/dist-skill/CONTEXT.md +27 -1
  50. package/dist-skill/docs/generated/core.md +26 -0
  51. package/dist-skill/docs/generated/runtime-names.md +1 -1
  52. package/dist-skill/docs/guides/inspection-bundles.md +1 -1
  53. package/dist-skill/library/README.md +9 -12
  54. package/dist-skill/library/{forgecad-make-a-model → forgecad-build-model}/SKILL.md +16 -6
  55. package/dist-skill/library/{forgecad-spec-by-walking-through-it → forgecad-design-spec}/SKILL.md +4 -4
  56. package/dist-skill/library/{forgecad-spec-by-walking-through-it → forgecad-design-spec}/references/master-prompt.md +1 -1
  57. package/dist-skill/library/{forgecad-model-grader → forgecad-grade-model}/SKILL.md +6 -4
  58. package/dist-skill/library/forgecad-grade-model/agents/openai.yaml +4 -0
  59. package/dist-skill/library/{forgecad-visual-spec → forgecad-image-prompt}/SKILL.md +5 -5
  60. package/dist-skill/library/forgecad-image-prompt/agents/openai.yaml +4 -0
  61. package/dist-skill/library/{forgecad-render-inspect → forgecad-inspect-model}/SKILL.md +4 -4
  62. package/dist-skill/library/{forgecad-project → forgecad-project-sync}/SKILL.md +3 -3
  63. package/dist-skill/library/{forgecad-3d-reconstruction → forgecad-reconstruct-cad-file}/SKILL.md +5 -5
  64. package/dist-skill/library/forgecad-reconstruct-cad-file/agents/openai.yaml +4 -0
  65. package/dist-skill/library/{forgecad-image-replicator → forgecad-reconstruct-from-images}/SKILL.md +10 -10
  66. package/dist-skill/library/forgecad-reconstruct-from-images/agents/openai.yaml +4 -0
  67. package/dist-skill/library/{forgecad-mujoco-verify → forgecad-verify-mujoco}/SKILL.md +4 -4
  68. package/dist-skill/website/skills/{forgecad-make-a-model.md → forgecad-build-model.md} +18 -8
  69. package/dist-skill/website/skills/{forgecad-spec-by-walking-through-it.md → forgecad-design-spec.md} +6 -6
  70. package/dist-skill/website/skills/{forgecad-model-grader.md → forgecad-grade-model.md} +8 -6
  71. package/{dist/docs-raw/skills/forgecad-visual-spec.md → dist-skill/website/skills/forgecad-image-prompt.md} +7 -7
  72. package/dist-skill/website/skills/{forgecad-render-inspect.md → forgecad-inspect-model.md} +6 -6
  73. package/{dist/docs-raw/skills/forgecad-project.md → dist-skill/website/skills/forgecad-project-sync.md} +5 -5
  74. package/dist-skill/website/skills/{forgecad-3d-reconstruction.md → forgecad-reconstruct-cad-file.md} +7 -7
  75. package/dist-skill/website/skills/{forgecad-image-replicator.md → forgecad-reconstruct-from-images.md} +12 -12
  76. package/dist-skill/website/skills/{forgecad-mujoco-verify.md → forgecad-verify-mujoco.md} +6 -6
  77. package/dist-skill/website/skills/index.md +9 -12
  78. package/examples/api/texture-projection.forge.js +75 -0
  79. package/examples/assets/uv-grid.png +0 -0
  80. package/package.json +1 -1
  81. package/dist/docs-raw/skills/forgecad-blockout-model.md +0 -49
  82. package/dist/docs-raw/skills/forgecad-component-model.md +0 -53
  83. package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +0 -60
  84. package/dist-skill/library/forgecad-3d-reconstruction/agents/openai.yaml +0 -4
  85. package/dist-skill/library/forgecad-blockout-model/SKILL.md +0 -42
  86. package/dist-skill/library/forgecad-component-model/SKILL.md +0 -46
  87. package/dist-skill/library/forgecad-image-replicator/agents/openai.yaml +0 -4
  88. package/dist-skill/library/forgecad-model-grader/agents/openai.yaml +0 -4
  89. package/dist-skill/library/forgecad-reconstruction-benchmark/SKILL.md +0 -48
  90. package/dist-skill/library/forgecad-reconstruction-benchmark/agents/openai.yaml +0 -4
  91. package/dist-skill/library/forgecad-visual-spec/agents/openai.yaml +0 -4
  92. package/dist-skill/website/skills/forgecad-blockout-model.md +0 -49
  93. package/dist-skill/website/skills/forgecad-component-model.md +0 -53
  94. package/dist-skill/website/skills/forgecad-reconstruction-benchmark.md +0 -60
  95. /package/dist/assets/{landing-proof-driven-DiGqdtWa.js → landing-proof-driven-BxZZh5r5.js} +0 -0
  96. /package/dist-skill/library/{forgecad-spec-by-walking-through-it → forgecad-design-spec}/references/default-profiles.md +0 -0
  97. /package/dist-skill/library/{forgecad-render-inspect → forgecad-inspect-model}/summarize_manifest.py +0 -0
  98. /package/dist-skill/library/{forgecad-image-replicator → forgecad-reconstruct-from-images}/scripts/compare_images.py +0 -0
  99. /package/dist-skill/library/{forgecad-mujoco-verify → forgecad-verify-mujoco}/scripts/mujoco_verify.py +0 -0
@@ -1,10 +1,10 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/EditorApp-C5f24ZN9.css","assets/landing-proof-driven-ORyigZ6p.css","assets/BenchmarkPage-BAbsyMaF.css","assets/PricingPage-BPF6HKyO.css","assets/LegalPage-BRlScr9A.css"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/EditorApp-C5f24ZN9.css","assets/landing-proof-driven-Cpf-MIbI.css","assets/BenchmarkPage-BAbsyMaF.css","assets/PricingPage-BPF6HKyO.css","assets/LegalPage-BRlScr9A.css"])))=>i.map(i=>d[i]);
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
5
  var _a2;
6
6
  import { c as create, j as jsxRuntimeExports, r as reactExports, a as createWithEqualityFn, R as React, T as Tb, s as schedulerExports, b as clientExports, d as reactDomExports, u as useParams, e as useSearchParams, f as useNavigate, L as Link, g as useLocation, B as BrowserRouter, h as Routes, i as Route, N as Navigate } from "./vendor-react-6j1Kke-Y.js";
7
- import { _ as __vitePreload, S as SDF_PROGRAM_OP, z as zipSync, s as strToU8, W as WebGLRenderer, R as Raycaster, O as OrthographicCamera$1, P as PerspectiveCamera$1, a as Scene, b as PCFSoftShadowMap, V as VSMShadowMap, c as PCFShadowMap, B as BasicShadowMap, C as ColorManagement, L as LinearSRGBColorSpace, d as SRGBColorSpace, N as NoToneMapping, A as ACESFilmicToneMapping, e as Layers, f as Color, g as RGBAFormat, U as UnsignedByteType, h as Vector3, i as Vector2, j as Clock, T as THREE, D as DoubleSide, k as REVISION, M as Mesh, I as IcosahedronGeometry, l as ShaderMaterial, m as Spherical, Q as Quaternion, n as MOUSE, o as TOUCH, p as Ray, q as Plane, r as DataTextureLoader, H as HalfFloatType, F as FloatType, t as DataUtils, u as LinearFilter, v as RedFormat, w as InstancedBufferGeometry, x as Float32BufferAttribute, y as InstancedInterleavedBuffer, E as InterleavedBufferAttribute, G as WireframeGeometry, J as Box3, K as Sphere, X as UniformsUtils, Y as UniformsLib, Z as Vector4, $ as Line3, a0 as Matrix4, a1 as MathUtils, a2 as Uniform, a3 as WebGLRenderTarget, a4 as DepthTexture, a5 as BackSide, a6 as BufferAttribute, a7 as Triangle, a8 as FrontSide, a9 as BatchedMesh, aa as ClampToEdgeWrapping, ab as PlaneGeometry, ac as UVMapping, ad as DataTexture, ae as Texture, af as MeshBasicMaterial, ag as IntType, ah as ShortType, ai as ByteType, aj as UnsignedIntType, ak as Loader, al as LoadingManager, am as LinearMipMapLinearFilter, an as FileLoader, ao as NoBlending, ap as CubeReflectionMapping, aq as EquirectangularReflectionMapping, ar as CubeTextureLoader, as as WebGLCubeRenderTarget, at as ConstraintSketch, au as setSketchPlacement3D, av as Sketch, aw as PROFILE_BACKEND_MARKER, ax as FrozenShape, ay as setShapeCompilePlan, az as hasAnyPorts, aA as setShapePortsInternal, aB as markShapePortsUsed, aC as resolveColormapName, aD as setParamOverrides, aE as resolveForgeRenderStyle, aF as DEFAULT_ACTIVE_BACKEND, aG as isConstraintSketch, aH as updateConstraintValue, aI as linearizeMultiObjectSteps, aJ as getShapeCompilePlan, aK as SCAN_PROXY_GRANULARITY_DEFAULT, aL as publishSolverWasmRunDebug, aM as resolveForgeQualityPreset, aN as SCAN_PROXY_MATRIX_GRANULARITY_MAX, aO as findJointAnimationClip, aP as resolveJointAnimation, aQ as resolveJointViewValues, aR as resolveImportPath, aS as resolveScanProxyGranularity, aT as BufferGeometry, aU as LineBasicMaterial, aV as Line$1, aW as LineDashedMaterial, aX as CanvasTexture, aY as Object3D, aZ as FogExp2, a_ as Fog, a$ as AmbientLight, b0 as HemisphereLight, b1 as SpotLight, b2 as PointLight, b3 as DirectionalLight, b4 as heatPointsForSide, b5 as COMPARISON_COLORS, b6 as comparisonHeatDepthTest, b7 as comparisonHeatEdgeOpacity, b8 as comparisonHeatPatchOpacity, b9 as shapeToGeometry, ba as buildComparisonHeatPatchGeometry, bb as EdgesGeometry, bc as buildShapeFromCompilePlan, bd as VIEWPORT_CAMERA_STORAGE_KEY, be as parseViewportCameraState, bf as getKernelFaceNameForTriangle, bg as OBJECT_CONTEXT_MENU_MARGIN, bh as buildVisibleHistoryStacks, bi as sketchToSvg, bj as sketchToDxf, bk as runScript, bl as MeshPhysicalMaterial, bm as LineSegments, bn as findDesignTraceNodeForConstructionStep, bo as formatDesignTraceAnchor, bp as waitForAnimationFrame, bq as selectBuildLedgerNodes, br as NoColorSpace, bs as worldAuthorPlaneToLocal, bt as compileSdfProgramEvaluator3, bu as SDF_LINEAR_OUTPUT_COLOR_GLSL, bv as GLSL3, bw as BoxGeometry, bx as Data3DTexture, by as buildSdfRaymarchFragmentShader, bz as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bA as scanProxySourceBytes, bB as disposeScanProxyGeometry, bC as scanProxyGeometryFromPayload, bD as AdditiveBlending, bE as geometryWithVisibleVertexColors, bF as colorScaleLUT, bG as getRenderStylePreset, bH as SCAN_RENDER_COLORS, bI as NormalBlending, bJ as scanMaterialShellColor, 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, bP as ZEBRA_STRIPE_FRAGMENT_SHADER, bQ as ZEBRA_STRIPE_VERTEX_SHADER, bR as SCAN_PROXY_LAYER_STYLES, bS as scanMaterialLayerStyles, bT as SURFACE_FIELD_FRAGMENT_SHADER, bU as SURFACE_FIELD_VERTEX_SHADER, bV as WORLD_UP$1, bW as CatmullRomCurve3, bX as TubeGeometry, bY as DEFAULT_COLORMAP, bZ as colorScaleHexStops, b_ as PERFORMANCE_SAMPLE_INTERVAL_SEC, b$ as formatPerformanceCount, c0 as NON_TEXT_INPUT_TYPES, c1 as MeshStandardMaterial, c2 as Shape, c3 as ShapeGeometry, c4 as ShaderLib, c5 as CylinderGeometry, c6 as createResolvedExplodeConfig, c7 as explodeBoundsCenter, c8 as explodeMergeBounds, c9 as resolveExplodeDirective, ca as computeExplodeMotion, cb as getSketchWorldMatrix, cc as explodeAdd, cd as hasExplodeOverride, ce as resolveExplodeLocalFanDirection, cf as explodeMul, cg as explodeLeafFanStage, ch as normalizeCutPlane, ci as toClippingPlane, cj as isObjectExcludedFromCutPlane, ck as getShapePorts, cl as getShapeUsedPorts, cm as DEFAULT_VIEW_CONFIG, cn as SECTION_EXPLORER_PLANE_NAME, co as ZERO_OFFSET, cp as scanProxyGridForBounds, cq as IDENTITY_MATRIX$2, cr as OBJECT_CONTEXT_MENU_WIDTH, cs as OBJECT_CONTEXT_MENU_HEIGHT, ct as triangleSoupFromMeshes, cu as compareTriangleSoups, cv as buildGeometryComparisonPointCloud, cw as aabbOverlaps, cx as aabbOverlapVolume, cy as DEFAULT_COLLISION_INSPECTION_OPTIONS, cz as resolveScalarSceneSampleBudget, cA as FOCUS_MODE_DIM_OPACITY, cB as DEFAULT_THICKNESS_INSPECTION_OPTIONS, cC as comparisonCandidateContextOpacity, cD as Matrix3, cE as initBackendForEvaluation } from "./backendInit-DbTkQN9J.js";
7
+ import { _ as __vitePreload, S as SDF_PROGRAM_OP, z as zipSync, s as strToU8, W as WebGLRenderer, R as Raycaster, O as OrthographicCamera$1, P as PerspectiveCamera$1, a as Scene, b as PCFSoftShadowMap, V as VSMShadowMap, c as PCFShadowMap, B as BasicShadowMap, C as ColorManagement, L as LinearSRGBColorSpace, d as SRGBColorSpace, N as NoToneMapping, A as ACESFilmicToneMapping, e as Layers, f as Color, g as RGBAFormat, U as UnsignedByteType, h as Vector3, i as Vector2, j as Clock, T as THREE, D as DoubleSide, k as REVISION, M as Mesh, I as IcosahedronGeometry, l as ShaderMaterial, m as Spherical, Q as Quaternion, n as MOUSE, o as TOUCH, p as Ray, q as Plane, r as DataTextureLoader, H as HalfFloatType, F as FloatType, t as DataUtils, u as LinearFilter, v as RedFormat, w as InstancedBufferGeometry, x as Float32BufferAttribute, y as InstancedInterleavedBuffer, E as InterleavedBufferAttribute, G as WireframeGeometry, J as Box3, K as Sphere, X as UniformsUtils, Y as UniformsLib, Z as Vector4, $ as Line3, a0 as Matrix4, a1 as MathUtils, a2 as Uniform, a3 as WebGLRenderTarget, a4 as DepthTexture, a5 as BackSide, a6 as ClampToEdgeWrapping, a7 as PlaneGeometry, a8 as UVMapping, a9 as DataTexture, aa as Texture, ab as MeshBasicMaterial, ac as IntType, ad as ShortType, ae as ByteType, af as UnsignedIntType, ag as Loader, ah as LoadingManager, ai as LinearMipMapLinearFilter, aj as FileLoader, ak as NoBlending, al as CubeReflectionMapping, am as EquirectangularReflectionMapping, an as CubeTextureLoader, ao as WebGLCubeRenderTarget, ap as ConstraintSketch, aq as setSketchPlacement3D, ar as Sketch, as as PROFILE_BACKEND_MARKER, at as FrozenShape, au as setShapeCompilePlan, av as hasAnyPorts, aw as setShapePortsInternal, ax as markShapePortsUsed, ay as writeViewPreferences, az as setParamOverrides, aA as readViewPreferences, aB as resolveForgeRenderStyle, aC as isConstraintSketch, aD as updateConstraintValue, aE as linearizeMultiObjectSteps, aF as getShapeCompilePlan, aG as resolveCameraControlMode, aH as resolveComparisonOpacity, aI as resolveComparisonInspectMode, aJ as resolveBooleanPref, aK as resolveInspectQuantizeBands, aL as resolveInspectIsolineSpacing, aM as resolveInspectColormap, aN as resolveThicknessColorRange, aO as resolveInspectPointSampleCount, aP as SCAN_PROXY_GRANULARITY_DEFAULT, aQ as DEFAULT_MANUAL_SCENE_SETTINGS, aR as resolveManualSceneSettings, aS as publishSolverWasmRunDebug, aT as resolveForgeQualityPreset, aU as DEFAULT_INSPECT_ISOLINES_ENABLED, aV as SCAN_PROXY_MATRIX_GRANULARITY_MAX, aW as findJointAnimationClip, aX as resolveJointAnimation, aY as resolveJointViewValues, aZ as resolveImportPath, a_ as DEFAULT_INSPECT_CRITICAL_LINE_ENABLED, a$ as resolveScanProxyGranularity, b0 as DEFAULT_COMPARISON_REFERENCE_OPACITY, b1 as DEFAULT_COMPARISON_CANDIDATE_OPACITY, b2 as BufferGeometry, b3 as LineBasicMaterial, b4 as Line$1, b5 as LineDashedMaterial, b6 as CanvasTexture, b7 as Object3D, b8 as FogExp2, b9 as Fog, ba as AmbientLight, bb as HemisphereLight, bc as SpotLight, bd as PointLight, be as DirectionalLight, bf as BufferAttribute, bg as heatPointsForSide, bh as COMPARISON_COLORS, bi as comparisonHeatDepthTest, bj as comparisonHeatEdgeOpacity, bk as comparisonHeatPatchOpacity, bl as shapeToGeometry, bm as buildComparisonHeatPatchGeometry, bn as EdgesGeometry, bo as buildShapeFromCompilePlan, bp as VIEWPORT_CAMERA_STORAGE_KEY, bq as parseViewportCameraState, br as getKernelFaceNameForTriangle, bs as OBJECT_CONTEXT_MENU_MARGIN, bt as buildVisibleHistoryStacks, bu as sketchToSvg, bv as sketchToDxf, bw as runScript, bx as MeshPhysicalMaterial, by as LineSegments, bz as findDesignTraceNodeForConstructionStep, bA as formatDesignTraceAnchor, bB as waitForAnimationFrame, bC as selectBuildLedgerNodes, bD as worldAuthorPlaneToLocal, bE as compileSdfProgramEvaluator3, bF as SDF_LINEAR_OUTPUT_COLOR_GLSL, bG as GLSL3, bH as BoxGeometry, bI as Data3DTexture, bJ as buildSdfRaymarchFragmentShader, bK as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bL as scanProxySourceBytes, bM as disposeScanProxyGeometry, bN as scanProxyGeometryFromPayload, bO as AdditiveBlending, bP as geometryWithVisibleVertexColors, bQ as MeshBVH, bR as makeColorScaleTexture, bS as colorScaleLUT, bT as makeInspectScalarUniforms, bU as updateInspectScalarUniforms, bV as descriptorToThreeTexture, bW as applyProjectedTexture, bX as getRenderStylePreset, bY as SCAN_RENDER_COLORS, bZ as NormalBlending, b_ as acceleratedRaycast, b$ as INSPECT_SCALAR_FRAGMENT_SHADER, c0 as INSPECT_SCALAR_VERTEX_SHADER, c1 as scanMaterialShellColor, c2 as ZEBRA_STRIPE_SOFTNESS, c3 as ZEBRA_STRIPE_SCALE, c4 as ZEBRA_LIGHT_COLOR, c5 as ZEBRA_DARK_COLOR, c6 as ZEBRA_ACCENT_COLOR, c7 as ZEBRA_STRIPE_FRAGMENT_SHADER, c8 as ZEBRA_STRIPE_VERTEX_SHADER, c9 as SCAN_PROXY_LAYER_STYLES, ca as scanMaterialLayerStyles, cb as SURFACE_FIELD_FRAGMENT_SHADER, cc as SURFACE_FIELD_VERTEX_SHADER, cd as WORLD_UP$1, ce as CatmullRomCurve3, cf as TubeGeometry, cg as DEFAULT_THICKNESS_COLOR_RANGE, ch as DEFAULT_COLORMAP, ci as colorScaleHexStops, cj as PERFORMANCE_SAMPLE_INTERVAL_SEC, ck as formatPerformanceCount, cl as NON_TEXT_INPUT_TYPES, cm as MeshStandardMaterial, cn as Shape, co as ShapeGeometry, cp as ShaderLib, cq as CylinderGeometry, cr as createResolvedExplodeConfig, cs as explodeBoundsCenter, ct as explodeMergeBounds, cu as resolveExplodeDirective, cv as computeExplodeMotion, cw as getSketchWorldMatrix, cx as explodeAdd, cy as hasExplodeOverride, cz as resolveExplodeLocalFanDirection, cA as explodeMul, cB as explodeLeafFanStage, cC as normalizeCutPlane, cD as toClippingPlane, cE as isObjectExcludedFromCutPlane, cF as getShapePorts, cG as getShapeUsedPorts, cH as DEFAULT_VIEW_CONFIG, cI as SECTION_EXPLORER_PLANE_NAME, cJ as ZERO_OFFSET, cK as scanProxyGridForBounds, cL as IDENTITY_MATRIX$2, cM as OBJECT_CONTEXT_MENU_WIDTH, cN as OBJECT_CONTEXT_MENU_HEIGHT, cO as triangleSoupFromMeshes, cP as compareTriangleSoups, cQ as buildGeometryComparisonPointCloud, cR as aabbOverlaps, cS as aabbOverlapVolume, cT as DEFAULT_COLLISION_INSPECTION_OPTIONS, cU as resolveScalarSceneSampleBudget, cV as INSPECT_POINT_SAMPLE_COUNT_MIN, cW as FOCUS_MODE_DIM_OPACITY, cX as DEFAULT_THICKNESS_INSPECTION_OPTIONS, cY as comparisonCandidateContextOpacity, cZ as Matrix3, c_ as initBackendForEvaluation } from "./backendInit-6C0DLgH0.js";
8
8
  function getCsrfToken() {
9
9
  const match = document.cookie.match(/(?:^|;\s*)fc-csrf-token=([^;]+)/);
10
10
  return match == null ? void 0 : match[1];
@@ -13391,3329 +13391,6 @@ const Grid = /* @__PURE__ */ reactExports.forwardRef(({
13391
13391
  args
13392
13392
  }));
13393
13393
  });
13394
- const CENTER = 0;
13395
- const AVERAGE = 1;
13396
- const SAH = 2;
13397
- const CONTAINED = 2;
13398
- const TRIANGLE_INTERSECT_COST = 1.25;
13399
- const TRAVERSAL_COST = 1;
13400
- const BYTES_PER_NODE = 6 * 4 + 4 + 4;
13401
- const IS_LEAFNODE_FLAG = 65535;
13402
- const FLOAT32_EPSILON = Math.pow(2, -24);
13403
- const SKIP_GENERATION = Symbol("SKIP_GENERATION");
13404
- function getVertexCount(geo) {
13405
- return geo.index ? geo.index.count : geo.attributes.position.count;
13406
- }
13407
- function getTriCount(geo) {
13408
- return getVertexCount(geo) / 3;
13409
- }
13410
- function getIndexArray(vertexCount, BufferConstructor = ArrayBuffer) {
13411
- if (vertexCount > 65535) {
13412
- return new Uint32Array(new BufferConstructor(4 * vertexCount));
13413
- } else {
13414
- return new Uint16Array(new BufferConstructor(2 * vertexCount));
13415
- }
13416
- }
13417
- function ensureIndex(geo, options) {
13418
- if (!geo.index) {
13419
- const vertexCount = geo.attributes.position.count;
13420
- const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
13421
- const index = getIndexArray(vertexCount, BufferConstructor);
13422
- geo.setIndex(new BufferAttribute(index, 1));
13423
- for (let i = 0; i < vertexCount; i++) {
13424
- index[i] = i;
13425
- }
13426
- }
13427
- }
13428
- function getFullGeometryRange(geo, range) {
13429
- const triCount = getTriCount(geo);
13430
- const drawRange = range ? range : geo.drawRange;
13431
- const start = drawRange.start / 3;
13432
- const end = (drawRange.start + drawRange.count) / 3;
13433
- const offset = Math.max(0, start);
13434
- const count = Math.min(triCount, end) - offset;
13435
- return [{
13436
- offset: Math.floor(offset),
13437
- count: Math.floor(count)
13438
- }];
13439
- }
13440
- function getRootIndexRanges(geo, range) {
13441
- if (!geo.groups || !geo.groups.length) {
13442
- return getFullGeometryRange(geo, range);
13443
- }
13444
- const ranges = [];
13445
- const rangeBoundaries = /* @__PURE__ */ new Set();
13446
- const drawRange = range ? range : geo.drawRange;
13447
- const drawRangeStart = drawRange.start / 3;
13448
- const drawRangeEnd = (drawRange.start + drawRange.count) / 3;
13449
- for (const group of geo.groups) {
13450
- const groupStart = group.start / 3;
13451
- const groupEnd = (group.start + group.count) / 3;
13452
- rangeBoundaries.add(Math.max(drawRangeStart, groupStart));
13453
- rangeBoundaries.add(Math.min(drawRangeEnd, groupEnd));
13454
- }
13455
- const sortedBoundaries = Array.from(rangeBoundaries.values()).sort((a2, b2) => a2 - b2);
13456
- for (let i = 0; i < sortedBoundaries.length - 1; i++) {
13457
- const start = sortedBoundaries[i];
13458
- const end = sortedBoundaries[i + 1];
13459
- ranges.push({
13460
- offset: Math.floor(start),
13461
- count: Math.floor(end - start)
13462
- });
13463
- }
13464
- return ranges;
13465
- }
13466
- function hasGroupGaps(geometry, range) {
13467
- const vertexCount = getTriCount(geometry);
13468
- const groups = getRootIndexRanges(geometry, range).sort((a2, b2) => a2.offset - b2.offset);
13469
- const finalGroup = groups[groups.length - 1];
13470
- finalGroup.count = Math.min(vertexCount - finalGroup.offset, finalGroup.count);
13471
- let total = 0;
13472
- groups.forEach(({ count }) => total += count);
13473
- return vertexCount !== total;
13474
- }
13475
- function getBounds(triangleBounds, offset, count, target, centroidTarget) {
13476
- let minx = Infinity;
13477
- let miny = Infinity;
13478
- let minz = Infinity;
13479
- let maxx = -Infinity;
13480
- let maxy = -Infinity;
13481
- let maxz = -Infinity;
13482
- let cminx = Infinity;
13483
- let cminy = Infinity;
13484
- let cminz = Infinity;
13485
- let cmaxx = -Infinity;
13486
- let cmaxy = -Infinity;
13487
- let cmaxz = -Infinity;
13488
- for (let i = offset * 6, end = (offset + count) * 6; i < end; i += 6) {
13489
- const cx = triangleBounds[i + 0];
13490
- const hx = triangleBounds[i + 1];
13491
- const lx = cx - hx;
13492
- const rx = cx + hx;
13493
- if (lx < minx) minx = lx;
13494
- if (rx > maxx) maxx = rx;
13495
- if (cx < cminx) cminx = cx;
13496
- if (cx > cmaxx) cmaxx = cx;
13497
- const cy = triangleBounds[i + 2];
13498
- const hy = triangleBounds[i + 3];
13499
- const ly = cy - hy;
13500
- const ry = cy + hy;
13501
- if (ly < miny) miny = ly;
13502
- if (ry > maxy) maxy = ry;
13503
- if (cy < cminy) cminy = cy;
13504
- if (cy > cmaxy) cmaxy = cy;
13505
- const cz = triangleBounds[i + 4];
13506
- const hz = triangleBounds[i + 5];
13507
- const lz = cz - hz;
13508
- const rz = cz + hz;
13509
- if (lz < minz) minz = lz;
13510
- if (rz > maxz) maxz = rz;
13511
- if (cz < cminz) cminz = cz;
13512
- if (cz > cmaxz) cmaxz = cz;
13513
- }
13514
- target[0] = minx;
13515
- target[1] = miny;
13516
- target[2] = minz;
13517
- target[3] = maxx;
13518
- target[4] = maxy;
13519
- target[5] = maxz;
13520
- centroidTarget[0] = cminx;
13521
- centroidTarget[1] = cminy;
13522
- centroidTarget[2] = cminz;
13523
- centroidTarget[3] = cmaxx;
13524
- centroidTarget[4] = cmaxy;
13525
- centroidTarget[5] = cmaxz;
13526
- }
13527
- function computeTriangleBounds(geo, target = null, offset = null, count = null) {
13528
- const posAttr = geo.attributes.position;
13529
- const index = geo.index ? geo.index.array : null;
13530
- const triCount = getTriCount(geo);
13531
- const normalized = posAttr.normalized;
13532
- let triangleBounds;
13533
- if (target === null) {
13534
- triangleBounds = new Float32Array(triCount * 6);
13535
- offset = 0;
13536
- count = triCount;
13537
- } else {
13538
- triangleBounds = target;
13539
- offset = offset || 0;
13540
- count = count || triCount;
13541
- }
13542
- const posArr = posAttr.array;
13543
- const bufferOffset = posAttr.offset || 0;
13544
- let stride = 3;
13545
- if (posAttr.isInterleavedBufferAttribute) {
13546
- stride = posAttr.data.stride;
13547
- }
13548
- const getters = ["getX", "getY", "getZ"];
13549
- for (let tri = offset; tri < offset + count; tri++) {
13550
- const tri3 = tri * 3;
13551
- const tri6 = tri * 6;
13552
- let ai = tri3 + 0;
13553
- let bi = tri3 + 1;
13554
- let ci = tri3 + 2;
13555
- if (index) {
13556
- ai = index[ai];
13557
- bi = index[bi];
13558
- ci = index[ci];
13559
- }
13560
- if (!normalized) {
13561
- ai = ai * stride + bufferOffset;
13562
- bi = bi * stride + bufferOffset;
13563
- ci = ci * stride + bufferOffset;
13564
- }
13565
- for (let el = 0; el < 3; el++) {
13566
- let a2, b2, c2;
13567
- if (normalized) {
13568
- a2 = posAttr[getters[el]](ai);
13569
- b2 = posAttr[getters[el]](bi);
13570
- c2 = posAttr[getters[el]](ci);
13571
- } else {
13572
- a2 = posArr[ai + el];
13573
- b2 = posArr[bi + el];
13574
- c2 = posArr[ci + el];
13575
- }
13576
- let min = a2;
13577
- if (b2 < min) min = b2;
13578
- if (c2 < min) min = c2;
13579
- let max2 = a2;
13580
- if (b2 > max2) max2 = b2;
13581
- if (c2 > max2) max2 = c2;
13582
- const halfExtents = (max2 - min) / 2;
13583
- const el2 = el * 2;
13584
- triangleBounds[tri6 + el2 + 0] = min + halfExtents;
13585
- triangleBounds[tri6 + el2 + 1] = halfExtents + (Math.abs(min) + halfExtents) * FLOAT32_EPSILON;
13586
- }
13587
- }
13588
- return triangleBounds;
13589
- }
13590
- function arrayToBox(nodeIndex32, array, target) {
13591
- target.min.x = array[nodeIndex32];
13592
- target.min.y = array[nodeIndex32 + 1];
13593
- target.min.z = array[nodeIndex32 + 2];
13594
- target.max.x = array[nodeIndex32 + 3];
13595
- target.max.y = array[nodeIndex32 + 4];
13596
- target.max.z = array[nodeIndex32 + 5];
13597
- return target;
13598
- }
13599
- function getLongestEdgeIndex(bounds) {
13600
- let splitDimIdx = -1;
13601
- let splitDist = -Infinity;
13602
- for (let i = 0; i < 3; i++) {
13603
- const dist = bounds[i + 3] - bounds[i];
13604
- if (dist > splitDist) {
13605
- splitDist = dist;
13606
- splitDimIdx = i;
13607
- }
13608
- }
13609
- return splitDimIdx;
13610
- }
13611
- function copyBounds(source, target) {
13612
- target.set(source);
13613
- }
13614
- function unionBounds(a2, b2, target) {
13615
- let aVal, bVal;
13616
- for (let d = 0; d < 3; d++) {
13617
- const d3 = d + 3;
13618
- aVal = a2[d];
13619
- bVal = b2[d];
13620
- target[d] = aVal < bVal ? aVal : bVal;
13621
- aVal = a2[d3];
13622
- bVal = b2[d3];
13623
- target[d3] = aVal > bVal ? aVal : bVal;
13624
- }
13625
- }
13626
- function expandByTriangleBounds(startIndex, triangleBounds, bounds) {
13627
- for (let d = 0; d < 3; d++) {
13628
- const tCenter = triangleBounds[startIndex + 2 * d];
13629
- const tHalf = triangleBounds[startIndex + 2 * d + 1];
13630
- const tMin = tCenter - tHalf;
13631
- const tMax = tCenter + tHalf;
13632
- if (tMin < bounds[d]) {
13633
- bounds[d] = tMin;
13634
- }
13635
- if (tMax > bounds[d + 3]) {
13636
- bounds[d + 3] = tMax;
13637
- }
13638
- }
13639
- }
13640
- function computeSurfaceArea(bounds) {
13641
- const d0 = bounds[3] - bounds[0];
13642
- const d1 = bounds[4] - bounds[1];
13643
- const d2 = bounds[5] - bounds[2];
13644
- return 2 * (d0 * d1 + d1 * d2 + d2 * d0);
13645
- }
13646
- const BIN_COUNT = 32;
13647
- const binsSort = (a2, b2) => a2.candidate - b2.candidate;
13648
- const sahBins = new Array(BIN_COUNT).fill().map(() => {
13649
- return {
13650
- count: 0,
13651
- bounds: new Float32Array(6),
13652
- rightCacheBounds: new Float32Array(6),
13653
- leftCacheBounds: new Float32Array(6),
13654
- candidate: 0
13655
- };
13656
- });
13657
- const leftBounds = new Float32Array(6);
13658
- function getOptimalSplit(nodeBoundingData, centroidBoundingData, triangleBounds, offset, count, strategy) {
13659
- let axis = -1;
13660
- let pos = 0;
13661
- if (strategy === CENTER) {
13662
- axis = getLongestEdgeIndex(centroidBoundingData);
13663
- if (axis !== -1) {
13664
- pos = (centroidBoundingData[axis] + centroidBoundingData[axis + 3]) / 2;
13665
- }
13666
- } else if (strategy === AVERAGE) {
13667
- axis = getLongestEdgeIndex(nodeBoundingData);
13668
- if (axis !== -1) {
13669
- pos = getAverage(triangleBounds, offset, count, axis);
13670
- }
13671
- } else if (strategy === SAH) {
13672
- const rootSurfaceArea = computeSurfaceArea(nodeBoundingData);
13673
- let bestCost = TRIANGLE_INTERSECT_COST * count;
13674
- const cStart = offset * 6;
13675
- const cEnd = (offset + count) * 6;
13676
- for (let a2 = 0; a2 < 3; a2++) {
13677
- const axisLeft = centroidBoundingData[a2];
13678
- const axisRight = centroidBoundingData[a2 + 3];
13679
- const axisLength = axisRight - axisLeft;
13680
- const binWidth = axisLength / BIN_COUNT;
13681
- if (count < BIN_COUNT / 4) {
13682
- const truncatedBins = [...sahBins];
13683
- truncatedBins.length = count;
13684
- let b2 = 0;
13685
- for (let c2 = cStart; c2 < cEnd; c2 += 6, b2++) {
13686
- const bin = truncatedBins[b2];
13687
- bin.candidate = triangleBounds[c2 + 2 * a2];
13688
- bin.count = 0;
13689
- const {
13690
- bounds,
13691
- leftCacheBounds,
13692
- rightCacheBounds
13693
- } = bin;
13694
- for (let d = 0; d < 3; d++) {
13695
- rightCacheBounds[d] = Infinity;
13696
- rightCacheBounds[d + 3] = -Infinity;
13697
- leftCacheBounds[d] = Infinity;
13698
- leftCacheBounds[d + 3] = -Infinity;
13699
- bounds[d] = Infinity;
13700
- bounds[d + 3] = -Infinity;
13701
- }
13702
- expandByTriangleBounds(c2, triangleBounds, bounds);
13703
- }
13704
- truncatedBins.sort(binsSort);
13705
- let splitCount = count;
13706
- for (let bi = 0; bi < splitCount; bi++) {
13707
- const bin = truncatedBins[bi];
13708
- while (bi + 1 < splitCount && truncatedBins[bi + 1].candidate === bin.candidate) {
13709
- truncatedBins.splice(bi + 1, 1);
13710
- splitCount--;
13711
- }
13712
- }
13713
- for (let c2 = cStart; c2 < cEnd; c2 += 6) {
13714
- const center = triangleBounds[c2 + 2 * a2];
13715
- for (let bi = 0; bi < splitCount; bi++) {
13716
- const bin = truncatedBins[bi];
13717
- if (center >= bin.candidate) {
13718
- expandByTriangleBounds(c2, triangleBounds, bin.rightCacheBounds);
13719
- } else {
13720
- expandByTriangleBounds(c2, triangleBounds, bin.leftCacheBounds);
13721
- bin.count++;
13722
- }
13723
- }
13724
- }
13725
- for (let bi = 0; bi < splitCount; bi++) {
13726
- const bin = truncatedBins[bi];
13727
- const leftCount = bin.count;
13728
- const rightCount = count - bin.count;
13729
- const leftBounds2 = bin.leftCacheBounds;
13730
- const rightBounds = bin.rightCacheBounds;
13731
- let leftProb = 0;
13732
- if (leftCount !== 0) {
13733
- leftProb = computeSurfaceArea(leftBounds2) / rootSurfaceArea;
13734
- }
13735
- let rightProb = 0;
13736
- if (rightCount !== 0) {
13737
- rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
13738
- }
13739
- const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
13740
- if (cost < bestCost) {
13741
- axis = a2;
13742
- bestCost = cost;
13743
- pos = bin.candidate;
13744
- }
13745
- }
13746
- } else {
13747
- for (let i = 0; i < BIN_COUNT; i++) {
13748
- const bin = sahBins[i];
13749
- bin.count = 0;
13750
- bin.candidate = axisLeft + binWidth + i * binWidth;
13751
- const bounds = bin.bounds;
13752
- for (let d = 0; d < 3; d++) {
13753
- bounds[d] = Infinity;
13754
- bounds[d + 3] = -Infinity;
13755
- }
13756
- }
13757
- for (let c2 = cStart; c2 < cEnd; c2 += 6) {
13758
- const triCenter = triangleBounds[c2 + 2 * a2];
13759
- const relativeCenter = triCenter - axisLeft;
13760
- let binIndex = ~~(relativeCenter / binWidth);
13761
- if (binIndex >= BIN_COUNT) binIndex = BIN_COUNT - 1;
13762
- const bin = sahBins[binIndex];
13763
- bin.count++;
13764
- expandByTriangleBounds(c2, triangleBounds, bin.bounds);
13765
- }
13766
- const lastBin = sahBins[BIN_COUNT - 1];
13767
- copyBounds(lastBin.bounds, lastBin.rightCacheBounds);
13768
- for (let i = BIN_COUNT - 2; i >= 0; i--) {
13769
- const bin = sahBins[i];
13770
- const nextBin = sahBins[i + 1];
13771
- unionBounds(bin.bounds, nextBin.rightCacheBounds, bin.rightCacheBounds);
13772
- }
13773
- let leftCount = 0;
13774
- for (let i = 0; i < BIN_COUNT - 1; i++) {
13775
- const bin = sahBins[i];
13776
- const binCount = bin.count;
13777
- const bounds = bin.bounds;
13778
- const nextBin = sahBins[i + 1];
13779
- const rightBounds = nextBin.rightCacheBounds;
13780
- if (binCount !== 0) {
13781
- if (leftCount === 0) {
13782
- copyBounds(bounds, leftBounds);
13783
- } else {
13784
- unionBounds(bounds, leftBounds, leftBounds);
13785
- }
13786
- }
13787
- leftCount += binCount;
13788
- let leftProb = 0;
13789
- let rightProb = 0;
13790
- if (leftCount !== 0) {
13791
- leftProb = computeSurfaceArea(leftBounds) / rootSurfaceArea;
13792
- }
13793
- const rightCount = count - leftCount;
13794
- if (rightCount !== 0) {
13795
- rightProb = computeSurfaceArea(rightBounds) / rootSurfaceArea;
13796
- }
13797
- const cost = TRAVERSAL_COST + TRIANGLE_INTERSECT_COST * (leftProb * leftCount + rightProb * rightCount);
13798
- if (cost < bestCost) {
13799
- axis = a2;
13800
- bestCost = cost;
13801
- pos = bin.candidate;
13802
- }
13803
- }
13804
- }
13805
- }
13806
- } else {
13807
- console.warn(`MeshBVH: Invalid build strategy value ${strategy} used.`);
13808
- }
13809
- return { axis, pos };
13810
- }
13811
- function getAverage(triangleBounds, offset, count, axis) {
13812
- let avg = 0;
13813
- for (let i = offset, end = offset + count; i < end; i++) {
13814
- avg += triangleBounds[i * 6 + axis * 2];
13815
- }
13816
- return avg / count;
13817
- }
13818
- class MeshBVHNode {
13819
- constructor() {
13820
- this.boundingData = new Float32Array(6);
13821
- }
13822
- }
13823
- function partition(indirectBuffer, index, triangleBounds, offset, count, split) {
13824
- let left = offset;
13825
- let right = offset + count - 1;
13826
- const pos = split.pos;
13827
- const axisOffset = split.axis * 2;
13828
- while (true) {
13829
- while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
13830
- left++;
13831
- }
13832
- while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
13833
- right--;
13834
- }
13835
- if (left < right) {
13836
- for (let i = 0; i < 3; i++) {
13837
- let t02 = index[left * 3 + i];
13838
- index[left * 3 + i] = index[right * 3 + i];
13839
- index[right * 3 + i] = t02;
13840
- }
13841
- for (let i = 0; i < 6; i++) {
13842
- let tb = triangleBounds[left * 6 + i];
13843
- triangleBounds[left * 6 + i] = triangleBounds[right * 6 + i];
13844
- triangleBounds[right * 6 + i] = tb;
13845
- }
13846
- left++;
13847
- right--;
13848
- } else {
13849
- return left;
13850
- }
13851
- }
13852
- }
13853
- function partition_indirect(indirectBuffer, index, triangleBounds, offset, count, split) {
13854
- let left = offset;
13855
- let right = offset + count - 1;
13856
- const pos = split.pos;
13857
- const axisOffset = split.axis * 2;
13858
- while (true) {
13859
- while (left <= right && triangleBounds[left * 6 + axisOffset] < pos) {
13860
- left++;
13861
- }
13862
- while (left <= right && triangleBounds[right * 6 + axisOffset] >= pos) {
13863
- right--;
13864
- }
13865
- if (left < right) {
13866
- let t2 = indirectBuffer[left];
13867
- indirectBuffer[left] = indirectBuffer[right];
13868
- indirectBuffer[right] = t2;
13869
- for (let i = 0; i < 6; i++) {
13870
- let tb = triangleBounds[left * 6 + i];
13871
- triangleBounds[left * 6 + i] = triangleBounds[right * 6 + i];
13872
- triangleBounds[right * 6 + i] = tb;
13873
- }
13874
- left++;
13875
- right--;
13876
- } else {
13877
- return left;
13878
- }
13879
- }
13880
- }
13881
- function IS_LEAF(n16, uint16Array2) {
13882
- return uint16Array2[n16 + 15] === 65535;
13883
- }
13884
- function OFFSET(n32, uint32Array2) {
13885
- return uint32Array2[n32 + 6];
13886
- }
13887
- function COUNT(n16, uint16Array2) {
13888
- return uint16Array2[n16 + 14];
13889
- }
13890
- function LEFT_NODE(n32) {
13891
- return n32 + 8;
13892
- }
13893
- function RIGHT_NODE(n32, uint32Array2) {
13894
- return uint32Array2[n32 + 6];
13895
- }
13896
- function SPLIT_AXIS(n32, uint32Array2) {
13897
- return uint32Array2[n32 + 7];
13898
- }
13899
- function BOUNDING_DATA_INDEX(n32) {
13900
- return n32;
13901
- }
13902
- let float32Array, uint32Array, uint16Array, uint8Array;
13903
- const MAX_POINTER = Math.pow(2, 32);
13904
- function countNodes(node) {
13905
- if ("count" in node) {
13906
- return 1;
13907
- } else {
13908
- return 1 + countNodes(node.left) + countNodes(node.right);
13909
- }
13910
- }
13911
- function populateBuffer(byteOffset, node, buffer) {
13912
- float32Array = new Float32Array(buffer);
13913
- uint32Array = new Uint32Array(buffer);
13914
- uint16Array = new Uint16Array(buffer);
13915
- uint8Array = new Uint8Array(buffer);
13916
- return _populateBuffer(byteOffset, node);
13917
- }
13918
- function _populateBuffer(byteOffset, node) {
13919
- const stride4Offset = byteOffset / 4;
13920
- const stride2Offset = byteOffset / 2;
13921
- const isLeaf = "count" in node;
13922
- const boundingData = node.boundingData;
13923
- for (let i = 0; i < 6; i++) {
13924
- float32Array[stride4Offset + i] = boundingData[i];
13925
- }
13926
- if (isLeaf) {
13927
- if (node.buffer) {
13928
- const buffer = node.buffer;
13929
- uint8Array.set(new Uint8Array(buffer), byteOffset);
13930
- for (let offset = byteOffset, l2 = byteOffset + buffer.byteLength; offset < l2; offset += BYTES_PER_NODE) {
13931
- const offset2 = offset / 2;
13932
- if (!IS_LEAF(offset2, uint16Array)) {
13933
- uint32Array[offset / 4 + 6] += stride4Offset;
13934
- }
13935
- }
13936
- return byteOffset + buffer.byteLength;
13937
- } else {
13938
- const offset = node.offset;
13939
- const count = node.count;
13940
- uint32Array[stride4Offset + 6] = offset;
13941
- uint16Array[stride2Offset + 14] = count;
13942
- uint16Array[stride2Offset + 15] = IS_LEAFNODE_FLAG;
13943
- return byteOffset + BYTES_PER_NODE;
13944
- }
13945
- } else {
13946
- const left = node.left;
13947
- const right = node.right;
13948
- const splitAxis = node.splitAxis;
13949
- let nextUnusedPointer;
13950
- nextUnusedPointer = _populateBuffer(byteOffset + BYTES_PER_NODE, left);
13951
- if (nextUnusedPointer / 4 > MAX_POINTER) {
13952
- throw new Error("MeshBVH: Cannot store child pointer greater than 32 bits.");
13953
- }
13954
- uint32Array[stride4Offset + 6] = nextUnusedPointer / 4;
13955
- nextUnusedPointer = _populateBuffer(nextUnusedPointer, right);
13956
- uint32Array[stride4Offset + 7] = splitAxis;
13957
- return nextUnusedPointer;
13958
- }
13959
- }
13960
- function generateIndirectBuffer(geometry, useSharedArrayBuffer) {
13961
- const triCount = (geometry.index ? geometry.index.count : geometry.attributes.position.count) / 3;
13962
- const useUint32 = triCount > 2 ** 16;
13963
- const byteCount = useUint32 ? 4 : 2;
13964
- const buffer = useSharedArrayBuffer ? new SharedArrayBuffer(triCount * byteCount) : new ArrayBuffer(triCount * byteCount);
13965
- const indirectBuffer = useUint32 ? new Uint32Array(buffer) : new Uint16Array(buffer);
13966
- for (let i = 0, l2 = indirectBuffer.length; i < l2; i++) {
13967
- indirectBuffer[i] = i;
13968
- }
13969
- return indirectBuffer;
13970
- }
13971
- function buildTree(bvh, triangleBounds, offset, count, options) {
13972
- const {
13973
- maxDepth,
13974
- verbose,
13975
- maxLeafTris,
13976
- strategy,
13977
- onProgress,
13978
- indirect
13979
- } = options;
13980
- const indirectBuffer = bvh._indirectBuffer;
13981
- const geometry = bvh.geometry;
13982
- const indexArray = geometry.index ? geometry.index.array : null;
13983
- const partionFunc = indirect ? partition_indirect : partition;
13984
- const totalTriangles = getTriCount(geometry);
13985
- const cacheCentroidBoundingData = new Float32Array(6);
13986
- let reachedMaxDepth = false;
13987
- const root = new MeshBVHNode();
13988
- getBounds(triangleBounds, offset, count, root.boundingData, cacheCentroidBoundingData);
13989
- splitNode(root, offset, count, cacheCentroidBoundingData);
13990
- return root;
13991
- function triggerProgress(trianglesProcessed) {
13992
- if (onProgress) {
13993
- onProgress(trianglesProcessed / totalTriangles);
13994
- }
13995
- }
13996
- function splitNode(node, offset2, count2, centroidBoundingData = null, depth = 0) {
13997
- if (!reachedMaxDepth && depth >= maxDepth) {
13998
- reachedMaxDepth = true;
13999
- if (verbose) {
14000
- console.warn(`MeshBVH: Max depth of ${maxDepth} reached when generating BVH. Consider increasing maxDepth.`);
14001
- console.warn(geometry);
14002
- }
14003
- }
14004
- if (count2 <= maxLeafTris || depth >= maxDepth) {
14005
- triggerProgress(offset2 + count2);
14006
- node.offset = offset2;
14007
- node.count = count2;
14008
- return node;
14009
- }
14010
- const split = getOptimalSplit(node.boundingData, centroidBoundingData, triangleBounds, offset2, count2, strategy);
14011
- if (split.axis === -1) {
14012
- triggerProgress(offset2 + count2);
14013
- node.offset = offset2;
14014
- node.count = count2;
14015
- return node;
14016
- }
14017
- const splitOffset = partionFunc(indirectBuffer, indexArray, triangleBounds, offset2, count2, split);
14018
- if (splitOffset === offset2 || splitOffset === offset2 + count2) {
14019
- triggerProgress(offset2 + count2);
14020
- node.offset = offset2;
14021
- node.count = count2;
14022
- } else {
14023
- node.splitAxis = split.axis;
14024
- const left = new MeshBVHNode();
14025
- const lstart = offset2;
14026
- const lcount = splitOffset - offset2;
14027
- node.left = left;
14028
- getBounds(triangleBounds, lstart, lcount, left.boundingData, cacheCentroidBoundingData);
14029
- splitNode(left, lstart, lcount, cacheCentroidBoundingData, depth + 1);
14030
- const right = new MeshBVHNode();
14031
- const rstart = splitOffset;
14032
- const rcount = count2 - lcount;
14033
- node.right = right;
14034
- getBounds(triangleBounds, rstart, rcount, right.boundingData, cacheCentroidBoundingData);
14035
- splitNode(right, rstart, rcount, cacheCentroidBoundingData, depth + 1);
14036
- }
14037
- return node;
14038
- }
14039
- }
14040
- function buildPackedTree(bvh, options) {
14041
- const geometry = bvh.geometry;
14042
- if (options.indirect) {
14043
- bvh._indirectBuffer = generateIndirectBuffer(geometry, options.useSharedArrayBuffer);
14044
- if (hasGroupGaps(geometry, options.range) && !options.verbose) {
14045
- console.warn(
14046
- 'MeshBVH: Provided geometry contains groups or a range that do not fully span the vertex contents while using the "indirect" option. BVH may incorrectly report intersections on unrendered portions of the geometry.'
14047
- );
14048
- }
14049
- }
14050
- if (!bvh._indirectBuffer) {
14051
- ensureIndex(geometry, options);
14052
- }
14053
- const BufferConstructor = options.useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer;
14054
- const triangleBounds = computeTriangleBounds(geometry);
14055
- const geometryRanges = options.indirect ? getFullGeometryRange(geometry, options.range) : getRootIndexRanges(geometry, options.range);
14056
- bvh._roots = geometryRanges.map((range) => {
14057
- const root = buildTree(bvh, triangleBounds, range.offset, range.count, options);
14058
- const nodeCount = countNodes(root);
14059
- const buffer = new BufferConstructor(BYTES_PER_NODE * nodeCount);
14060
- populateBuffer(0, root, buffer);
14061
- return buffer;
14062
- });
14063
- }
14064
- class SeparatingAxisBounds {
14065
- constructor() {
14066
- this.min = Infinity;
14067
- this.max = -Infinity;
14068
- }
14069
- setFromPointsField(points, field) {
14070
- let min = Infinity;
14071
- let max2 = -Infinity;
14072
- for (let i = 0, l2 = points.length; i < l2; i++) {
14073
- const p2 = points[i];
14074
- const val = p2[field];
14075
- min = val < min ? val : min;
14076
- max2 = val > max2 ? val : max2;
14077
- }
14078
- this.min = min;
14079
- this.max = max2;
14080
- }
14081
- setFromPoints(axis, points) {
14082
- let min = Infinity;
14083
- let max2 = -Infinity;
14084
- for (let i = 0, l2 = points.length; i < l2; i++) {
14085
- const p2 = points[i];
14086
- const val = axis.dot(p2);
14087
- min = val < min ? val : min;
14088
- max2 = val > max2 ? val : max2;
14089
- }
14090
- this.min = min;
14091
- this.max = max2;
14092
- }
14093
- isSeparated(other) {
14094
- return this.min > other.max || other.min > this.max;
14095
- }
14096
- }
14097
- SeparatingAxisBounds.prototype.setFromBox = (function() {
14098
- const p2 = new Vector3();
14099
- return function setFromBox(axis, box2) {
14100
- const boxMin = box2.min;
14101
- const boxMax = box2.max;
14102
- let min = Infinity;
14103
- let max2 = -Infinity;
14104
- for (let x = 0; x <= 1; x++) {
14105
- for (let y = 0; y <= 1; y++) {
14106
- for (let z = 0; z <= 1; z++) {
14107
- p2.x = boxMin.x * x + boxMax.x * (1 - x);
14108
- p2.y = boxMin.y * y + boxMax.y * (1 - y);
14109
- p2.z = boxMin.z * z + boxMax.z * (1 - z);
14110
- const val = axis.dot(p2);
14111
- min = Math.min(val, min);
14112
- max2 = Math.max(val, max2);
14113
- }
14114
- }
14115
- }
14116
- this.min = min;
14117
- this.max = max2;
14118
- };
14119
- })();
14120
- const closestPointLineToLine = (function() {
14121
- const dir1 = new Vector3();
14122
- const dir2 = new Vector3();
14123
- const v02 = new Vector3();
14124
- return function closestPointLineToLine2(l1, l2, result) {
14125
- const v0 = l1.start;
14126
- const v10 = dir1;
14127
- const v22 = l2.start;
14128
- const v32 = dir2;
14129
- v02.subVectors(v0, v22);
14130
- dir1.subVectors(l1.end, l1.start);
14131
- dir2.subVectors(l2.end, l2.start);
14132
- const d0232 = v02.dot(v32);
14133
- const d3210 = v32.dot(v10);
14134
- const d3232 = v32.dot(v32);
14135
- const d0210 = v02.dot(v10);
14136
- const d1010 = v10.dot(v10);
14137
- const denom = d1010 * d3232 - d3210 * d3210;
14138
- let d, d2;
14139
- if (denom !== 0) {
14140
- d = (d0232 * d3210 - d0210 * d3232) / denom;
14141
- } else {
14142
- d = 0;
14143
- }
14144
- d2 = (d0232 + d * d3210) / d3232;
14145
- result.x = d;
14146
- result.y = d2;
14147
- };
14148
- })();
14149
- const closestPointsSegmentToSegment = (function() {
14150
- const paramResult = new Vector2();
14151
- const temp12 = new Vector3();
14152
- const temp22 = new Vector3();
14153
- return function closestPointsSegmentToSegment2(l1, l2, target1, target2) {
14154
- closestPointLineToLine(l1, l2, paramResult);
14155
- let d = paramResult.x;
14156
- let d2 = paramResult.y;
14157
- if (d >= 0 && d <= 1 && d2 >= 0 && d2 <= 1) {
14158
- l1.at(d, target1);
14159
- l2.at(d2, target2);
14160
- return;
14161
- } else if (d >= 0 && d <= 1) {
14162
- if (d2 < 0) {
14163
- l2.at(0, target2);
14164
- } else {
14165
- l2.at(1, target2);
14166
- }
14167
- l1.closestPointToPoint(target2, true, target1);
14168
- return;
14169
- } else if (d2 >= 0 && d2 <= 1) {
14170
- if (d < 0) {
14171
- l1.at(0, target1);
14172
- } else {
14173
- l1.at(1, target1);
14174
- }
14175
- l2.closestPointToPoint(target1, true, target2);
14176
- return;
14177
- } else {
14178
- let p2;
14179
- if (d < 0) {
14180
- p2 = l1.start;
14181
- } else {
14182
- p2 = l1.end;
14183
- }
14184
- let p22;
14185
- if (d2 < 0) {
14186
- p22 = l2.start;
14187
- } else {
14188
- p22 = l2.end;
14189
- }
14190
- const closestPoint = temp12;
14191
- const closestPoint2 = temp22;
14192
- l1.closestPointToPoint(p22, true, temp12);
14193
- l2.closestPointToPoint(p2, true, temp22);
14194
- if (closestPoint.distanceToSquared(p22) <= closestPoint2.distanceToSquared(p2)) {
14195
- target1.copy(closestPoint);
14196
- target2.copy(p22);
14197
- return;
14198
- } else {
14199
- target1.copy(p2);
14200
- target2.copy(closestPoint2);
14201
- return;
14202
- }
14203
- }
14204
- };
14205
- })();
14206
- const sphereIntersectTriangle = (function() {
14207
- const closestPointTemp = new Vector3();
14208
- const projectedPointTemp = new Vector3();
14209
- const planeTemp = new Plane();
14210
- const lineTemp = new Line3();
14211
- return function sphereIntersectTriangle2(sphere, triangle3) {
14212
- const { radius, center } = sphere;
14213
- const { a: a2, b: b2, c: c2 } = triangle3;
14214
- lineTemp.start = a2;
14215
- lineTemp.end = b2;
14216
- const closestPoint1 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
14217
- if (closestPoint1.distanceTo(center) <= radius) return true;
14218
- lineTemp.start = a2;
14219
- lineTemp.end = c2;
14220
- const closestPoint2 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
14221
- if (closestPoint2.distanceTo(center) <= radius) return true;
14222
- lineTemp.start = b2;
14223
- lineTemp.end = c2;
14224
- const closestPoint3 = lineTemp.closestPointToPoint(center, true, closestPointTemp);
14225
- if (closestPoint3.distanceTo(center) <= radius) return true;
14226
- const plane = triangle3.getPlane(planeTemp);
14227
- const dp = Math.abs(plane.distanceToPoint(center));
14228
- if (dp <= radius) {
14229
- const pp = plane.projectPoint(center, projectedPointTemp);
14230
- const cp = triangle3.containsPoint(pp);
14231
- if (cp) return true;
14232
- }
14233
- return false;
14234
- };
14235
- })();
14236
- const ZERO_EPSILON = 1e-15;
14237
- function isNearZero(value) {
14238
- return Math.abs(value) < ZERO_EPSILON;
14239
- }
14240
- class ExtendedTriangle extends Triangle {
14241
- constructor(...args) {
14242
- super(...args);
14243
- this.isExtendedTriangle = true;
14244
- this.satAxes = new Array(4).fill().map(() => new Vector3());
14245
- this.satBounds = new Array(4).fill().map(() => new SeparatingAxisBounds());
14246
- this.points = [this.a, this.b, this.c];
14247
- this.sphere = new Sphere();
14248
- this.plane = new Plane();
14249
- this.needsUpdate = true;
14250
- }
14251
- intersectsSphere(sphere) {
14252
- return sphereIntersectTriangle(sphere, this);
14253
- }
14254
- update() {
14255
- const a2 = this.a;
14256
- const b2 = this.b;
14257
- const c2 = this.c;
14258
- const points = this.points;
14259
- const satAxes = this.satAxes;
14260
- const satBounds = this.satBounds;
14261
- const axis0 = satAxes[0];
14262
- const sab0 = satBounds[0];
14263
- this.getNormal(axis0);
14264
- sab0.setFromPoints(axis0, points);
14265
- const axis1 = satAxes[1];
14266
- const sab1 = satBounds[1];
14267
- axis1.subVectors(a2, b2);
14268
- sab1.setFromPoints(axis1, points);
14269
- const axis2 = satAxes[2];
14270
- const sab2 = satBounds[2];
14271
- axis2.subVectors(b2, c2);
14272
- sab2.setFromPoints(axis2, points);
14273
- const axis3 = satAxes[3];
14274
- const sab3 = satBounds[3];
14275
- axis3.subVectors(c2, a2);
14276
- sab3.setFromPoints(axis3, points);
14277
- this.sphere.setFromPoints(this.points);
14278
- this.plane.setFromNormalAndCoplanarPoint(axis0, a2);
14279
- this.needsUpdate = false;
14280
- }
14281
- }
14282
- ExtendedTriangle.prototype.closestPointToSegment = (function() {
14283
- const point1 = new Vector3();
14284
- const point2 = new Vector3();
14285
- const edge = new Line3();
14286
- return function distanceToSegment(segment, target1 = null, target2 = null) {
14287
- const { start, end } = segment;
14288
- const points = this.points;
14289
- let distSq;
14290
- let closestDistanceSq = Infinity;
14291
- for (let i = 0; i < 3; i++) {
14292
- const nexti = (i + 1) % 3;
14293
- edge.start.copy(points[i]);
14294
- edge.end.copy(points[nexti]);
14295
- closestPointsSegmentToSegment(edge, segment, point1, point2);
14296
- distSq = point1.distanceToSquared(point2);
14297
- if (distSq < closestDistanceSq) {
14298
- closestDistanceSq = distSq;
14299
- if (target1) target1.copy(point1);
14300
- if (target2) target2.copy(point2);
14301
- }
14302
- }
14303
- this.closestPointToPoint(start, point1);
14304
- distSq = start.distanceToSquared(point1);
14305
- if (distSq < closestDistanceSq) {
14306
- closestDistanceSq = distSq;
14307
- if (target1) target1.copy(point1);
14308
- if (target2) target2.copy(start);
14309
- }
14310
- this.closestPointToPoint(end, point1);
14311
- distSq = end.distanceToSquared(point1);
14312
- if (distSq < closestDistanceSq) {
14313
- closestDistanceSq = distSq;
14314
- if (target1) target1.copy(point1);
14315
- if (target2) target2.copy(end);
14316
- }
14317
- return Math.sqrt(closestDistanceSq);
14318
- };
14319
- })();
14320
- ExtendedTriangle.prototype.intersectsTriangle = (function() {
14321
- const saTri2 = new ExtendedTriangle();
14322
- const arr1 = new Array(3);
14323
- const arr2 = new Array(3);
14324
- const cachedSatBounds = new SeparatingAxisBounds();
14325
- const cachedSatBounds2 = new SeparatingAxisBounds();
14326
- const cachedAxis = new Vector3();
14327
- const dir = new Vector3();
14328
- const dir1 = new Vector3();
14329
- const dir2 = new Vector3();
14330
- const tempDir = new Vector3();
14331
- const edge = new Line3();
14332
- const edge1 = new Line3();
14333
- const edge2 = new Line3();
14334
- const tempPoint = new Vector3();
14335
- function triIntersectPlane(tri, plane, targetEdge) {
14336
- const points = tri.points;
14337
- let count = 0;
14338
- let startPointIntersection = -1;
14339
- for (let i = 0; i < 3; i++) {
14340
- const { start, end } = edge;
14341
- start.copy(points[i]);
14342
- end.copy(points[(i + 1) % 3]);
14343
- edge.delta(dir);
14344
- const startIntersects = isNearZero(plane.distanceToPoint(start));
14345
- if (isNearZero(plane.normal.dot(dir)) && startIntersects) {
14346
- targetEdge.copy(edge);
14347
- count = 2;
14348
- break;
14349
- }
14350
- const doesIntersect = plane.intersectLine(edge, tempPoint);
14351
- if (!doesIntersect && startIntersects) {
14352
- tempPoint.copy(start);
14353
- }
14354
- if ((doesIntersect || startIntersects) && !isNearZero(tempPoint.distanceTo(end))) {
14355
- if (count <= 1) {
14356
- const point = count === 1 ? targetEdge.start : targetEdge.end;
14357
- point.copy(tempPoint);
14358
- if (startIntersects) {
14359
- startPointIntersection = count;
14360
- }
14361
- } else if (count >= 2) {
14362
- const point = startPointIntersection === 1 ? targetEdge.start : targetEdge.end;
14363
- point.copy(tempPoint);
14364
- count = 2;
14365
- break;
14366
- }
14367
- count++;
14368
- if (count === 2 && startPointIntersection === -1) {
14369
- break;
14370
- }
14371
- }
14372
- }
14373
- return count;
14374
- }
14375
- return function intersectsTriangle(other, target = null, suppressLog = false) {
14376
- if (this.needsUpdate) {
14377
- this.update();
14378
- }
14379
- if (!other.isExtendedTriangle) {
14380
- saTri2.copy(other);
14381
- saTri2.update();
14382
- other = saTri2;
14383
- } else if (other.needsUpdate) {
14384
- other.update();
14385
- }
14386
- const plane1 = this.plane;
14387
- const plane2 = other.plane;
14388
- if (Math.abs(plane1.normal.dot(plane2.normal)) > 1 - 1e-10) {
14389
- const satBounds1 = this.satBounds;
14390
- const satAxes1 = this.satAxes;
14391
- arr2[0] = other.a;
14392
- arr2[1] = other.b;
14393
- arr2[2] = other.c;
14394
- for (let i = 0; i < 4; i++) {
14395
- const sb = satBounds1[i];
14396
- const sa = satAxes1[i];
14397
- cachedSatBounds.setFromPoints(sa, arr2);
14398
- if (sb.isSeparated(cachedSatBounds)) return false;
14399
- }
14400
- const satBounds2 = other.satBounds;
14401
- const satAxes2 = other.satAxes;
14402
- arr1[0] = this.a;
14403
- arr1[1] = this.b;
14404
- arr1[2] = this.c;
14405
- for (let i = 0; i < 4; i++) {
14406
- const sb = satBounds2[i];
14407
- const sa = satAxes2[i];
14408
- cachedSatBounds.setFromPoints(sa, arr1);
14409
- if (sb.isSeparated(cachedSatBounds)) return false;
14410
- }
14411
- for (let i = 0; i < 4; i++) {
14412
- const sa1 = satAxes1[i];
14413
- for (let i2 = 0; i2 < 4; i2++) {
14414
- const sa2 = satAxes2[i2];
14415
- cachedAxis.crossVectors(sa1, sa2);
14416
- cachedSatBounds.setFromPoints(cachedAxis, arr1);
14417
- cachedSatBounds2.setFromPoints(cachedAxis, arr2);
14418
- if (cachedSatBounds.isSeparated(cachedSatBounds2)) return false;
14419
- }
14420
- }
14421
- if (target) {
14422
- if (!suppressLog) {
14423
- console.warn("ExtendedTriangle.intersectsTriangle: Triangles are coplanar which does not support an output edge. Setting edge to 0, 0, 0.");
14424
- }
14425
- target.start.set(0, 0, 0);
14426
- target.end.set(0, 0, 0);
14427
- }
14428
- return true;
14429
- } else {
14430
- const count1 = triIntersectPlane(this, plane2, edge1);
14431
- if (count1 === 1 && other.containsPoint(edge1.end)) {
14432
- if (target) {
14433
- target.start.copy(edge1.end);
14434
- target.end.copy(edge1.end);
14435
- }
14436
- return true;
14437
- } else if (count1 !== 2) {
14438
- return false;
14439
- }
14440
- const count2 = triIntersectPlane(other, plane1, edge2);
14441
- if (count2 === 1 && this.containsPoint(edge2.end)) {
14442
- if (target) {
14443
- target.start.copy(edge2.end);
14444
- target.end.copy(edge2.end);
14445
- }
14446
- return true;
14447
- } else if (count2 !== 2) {
14448
- return false;
14449
- }
14450
- edge1.delta(dir1);
14451
- edge2.delta(dir2);
14452
- if (dir1.dot(dir2) < 0) {
14453
- let tmp = edge2.start;
14454
- edge2.start = edge2.end;
14455
- edge2.end = tmp;
14456
- }
14457
- const s1 = edge1.start.dot(dir1);
14458
- const e1 = edge1.end.dot(dir1);
14459
- const s2 = edge2.start.dot(dir1);
14460
- const e2 = edge2.end.dot(dir1);
14461
- const separated1 = e1 < s2;
14462
- const separated2 = s1 < e2;
14463
- if (s1 !== e2 && s2 !== e1 && separated1 === separated2) {
14464
- return false;
14465
- }
14466
- if (target) {
14467
- tempDir.subVectors(edge1.start, edge2.start);
14468
- if (tempDir.dot(dir1) > 0) {
14469
- target.start.copy(edge1.start);
14470
- } else {
14471
- target.start.copy(edge2.start);
14472
- }
14473
- tempDir.subVectors(edge1.end, edge2.end);
14474
- if (tempDir.dot(dir1) < 0) {
14475
- target.end.copy(edge1.end);
14476
- } else {
14477
- target.end.copy(edge2.end);
14478
- }
14479
- }
14480
- return true;
14481
- }
14482
- };
14483
- })();
14484
- ExtendedTriangle.prototype.distanceToPoint = (function() {
14485
- const target = new Vector3();
14486
- return function distanceToPoint(point) {
14487
- this.closestPointToPoint(point, target);
14488
- return point.distanceTo(target);
14489
- };
14490
- })();
14491
- ExtendedTriangle.prototype.distanceToTriangle = (function() {
14492
- const point = new Vector3();
14493
- const point2 = new Vector3();
14494
- const cornerFields = ["a", "b", "c"];
14495
- const line1 = new Line3();
14496
- const line2 = new Line3();
14497
- return function distanceToTriangle(other, target1 = null, target2 = null) {
14498
- const lineTarget = target1 || target2 ? line1 : null;
14499
- if (this.intersectsTriangle(other, lineTarget)) {
14500
- if (target1 || target2) {
14501
- if (target1) lineTarget.getCenter(target1);
14502
- if (target2) lineTarget.getCenter(target2);
14503
- }
14504
- return 0;
14505
- }
14506
- let closestDistanceSq = Infinity;
14507
- for (let i = 0; i < 3; i++) {
14508
- let dist;
14509
- const field = cornerFields[i];
14510
- const otherVec = other[field];
14511
- this.closestPointToPoint(otherVec, point);
14512
- dist = otherVec.distanceToSquared(point);
14513
- if (dist < closestDistanceSq) {
14514
- closestDistanceSq = dist;
14515
- if (target1) target1.copy(point);
14516
- if (target2) target2.copy(otherVec);
14517
- }
14518
- const thisVec = this[field];
14519
- other.closestPointToPoint(thisVec, point);
14520
- dist = thisVec.distanceToSquared(point);
14521
- if (dist < closestDistanceSq) {
14522
- closestDistanceSq = dist;
14523
- if (target1) target1.copy(thisVec);
14524
- if (target2) target2.copy(point);
14525
- }
14526
- }
14527
- for (let i = 0; i < 3; i++) {
14528
- const f11 = cornerFields[i];
14529
- const f12 = cornerFields[(i + 1) % 3];
14530
- line1.set(this[f11], this[f12]);
14531
- for (let i2 = 0; i2 < 3; i2++) {
14532
- const f21 = cornerFields[i2];
14533
- const f22 = cornerFields[(i2 + 1) % 3];
14534
- line2.set(other[f21], other[f22]);
14535
- closestPointsSegmentToSegment(line1, line2, point, point2);
14536
- const dist = point.distanceToSquared(point2);
14537
- if (dist < closestDistanceSq) {
14538
- closestDistanceSq = dist;
14539
- if (target1) target1.copy(point);
14540
- if (target2) target2.copy(point2);
14541
- }
14542
- }
14543
- }
14544
- return Math.sqrt(closestDistanceSq);
14545
- };
14546
- })();
14547
- class OrientedBox {
14548
- constructor(min, max2, matrix) {
14549
- this.isOrientedBox = true;
14550
- this.min = new Vector3();
14551
- this.max = new Vector3();
14552
- this.matrix = new Matrix4();
14553
- this.invMatrix = new Matrix4();
14554
- this.points = new Array(8).fill().map(() => new Vector3());
14555
- this.satAxes = new Array(3).fill().map(() => new Vector3());
14556
- this.satBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
14557
- this.alignedSatBounds = new Array(3).fill().map(() => new SeparatingAxisBounds());
14558
- this.needsUpdate = false;
14559
- if (min) this.min.copy(min);
14560
- if (max2) this.max.copy(max2);
14561
- if (matrix) this.matrix.copy(matrix);
14562
- }
14563
- set(min, max2, matrix) {
14564
- this.min.copy(min);
14565
- this.max.copy(max2);
14566
- this.matrix.copy(matrix);
14567
- this.needsUpdate = true;
14568
- }
14569
- copy(other) {
14570
- this.min.copy(other.min);
14571
- this.max.copy(other.max);
14572
- this.matrix.copy(other.matrix);
14573
- this.needsUpdate = true;
14574
- }
14575
- }
14576
- OrientedBox.prototype.update = /* @__PURE__ */ (function() {
14577
- return function update2() {
14578
- const matrix = this.matrix;
14579
- const min = this.min;
14580
- const max2 = this.max;
14581
- const points = this.points;
14582
- for (let x = 0; x <= 1; x++) {
14583
- for (let y = 0; y <= 1; y++) {
14584
- for (let z = 0; z <= 1; z++) {
14585
- const i = (1 << 0) * x | (1 << 1) * y | (1 << 2) * z;
14586
- const v = points[i];
14587
- v.x = x ? max2.x : min.x;
14588
- v.y = y ? max2.y : min.y;
14589
- v.z = z ? max2.z : min.z;
14590
- v.applyMatrix4(matrix);
14591
- }
14592
- }
14593
- }
14594
- const satBounds = this.satBounds;
14595
- const satAxes = this.satAxes;
14596
- const minVec = points[0];
14597
- for (let i = 0; i < 3; i++) {
14598
- const axis = satAxes[i];
14599
- const sb = satBounds[i];
14600
- const index = 1 << i;
14601
- const pi = points[index];
14602
- axis.subVectors(minVec, pi);
14603
- sb.setFromPoints(axis, points);
14604
- }
14605
- const alignedSatBounds = this.alignedSatBounds;
14606
- alignedSatBounds[0].setFromPointsField(points, "x");
14607
- alignedSatBounds[1].setFromPointsField(points, "y");
14608
- alignedSatBounds[2].setFromPointsField(points, "z");
14609
- this.invMatrix.copy(this.matrix).invert();
14610
- this.needsUpdate = false;
14611
- };
14612
- })();
14613
- OrientedBox.prototype.intersectsBox = (function() {
14614
- const aabbBounds = new SeparatingAxisBounds();
14615
- return function intersectsBox(box2) {
14616
- if (this.needsUpdate) {
14617
- this.update();
14618
- }
14619
- const min = box2.min;
14620
- const max2 = box2.max;
14621
- const satBounds = this.satBounds;
14622
- const satAxes = this.satAxes;
14623
- const alignedSatBounds = this.alignedSatBounds;
14624
- aabbBounds.min = min.x;
14625
- aabbBounds.max = max2.x;
14626
- if (alignedSatBounds[0].isSeparated(aabbBounds)) return false;
14627
- aabbBounds.min = min.y;
14628
- aabbBounds.max = max2.y;
14629
- if (alignedSatBounds[1].isSeparated(aabbBounds)) return false;
14630
- aabbBounds.min = min.z;
14631
- aabbBounds.max = max2.z;
14632
- if (alignedSatBounds[2].isSeparated(aabbBounds)) return false;
14633
- for (let i = 0; i < 3; i++) {
14634
- const axis = satAxes[i];
14635
- const sb = satBounds[i];
14636
- aabbBounds.setFromBox(axis, box2);
14637
- if (sb.isSeparated(aabbBounds)) return false;
14638
- }
14639
- return true;
14640
- };
14641
- })();
14642
- OrientedBox.prototype.intersectsTriangle = (function() {
14643
- const saTri = new ExtendedTriangle();
14644
- const pointsArr = new Array(3);
14645
- const cachedSatBounds = new SeparatingAxisBounds();
14646
- const cachedSatBounds2 = new SeparatingAxisBounds();
14647
- const cachedAxis = new Vector3();
14648
- return function intersectsTriangle(triangle3) {
14649
- if (this.needsUpdate) {
14650
- this.update();
14651
- }
14652
- if (!triangle3.isExtendedTriangle) {
14653
- saTri.copy(triangle3);
14654
- saTri.update();
14655
- triangle3 = saTri;
14656
- } else if (triangle3.needsUpdate) {
14657
- triangle3.update();
14658
- }
14659
- const satBounds = this.satBounds;
14660
- const satAxes = this.satAxes;
14661
- pointsArr[0] = triangle3.a;
14662
- pointsArr[1] = triangle3.b;
14663
- pointsArr[2] = triangle3.c;
14664
- for (let i = 0; i < 3; i++) {
14665
- const sb = satBounds[i];
14666
- const sa = satAxes[i];
14667
- cachedSatBounds.setFromPoints(sa, pointsArr);
14668
- if (sb.isSeparated(cachedSatBounds)) return false;
14669
- }
14670
- const triSatBounds = triangle3.satBounds;
14671
- const triSatAxes = triangle3.satAxes;
14672
- const points = this.points;
14673
- for (let i = 0; i < 3; i++) {
14674
- const sb = triSatBounds[i];
14675
- const sa = triSatAxes[i];
14676
- cachedSatBounds.setFromPoints(sa, points);
14677
- if (sb.isSeparated(cachedSatBounds)) return false;
14678
- }
14679
- for (let i = 0; i < 3; i++) {
14680
- const sa1 = satAxes[i];
14681
- for (let i2 = 0; i2 < 4; i2++) {
14682
- const sa2 = triSatAxes[i2];
14683
- cachedAxis.crossVectors(sa1, sa2);
14684
- cachedSatBounds.setFromPoints(cachedAxis, pointsArr);
14685
- cachedSatBounds2.setFromPoints(cachedAxis, points);
14686
- if (cachedSatBounds.isSeparated(cachedSatBounds2)) return false;
14687
- }
14688
- }
14689
- return true;
14690
- };
14691
- })();
14692
- OrientedBox.prototype.closestPointToPoint = /* @__PURE__ */ (function() {
14693
- return function closestPointToPoint2(point, target1) {
14694
- if (this.needsUpdate) {
14695
- this.update();
14696
- }
14697
- target1.copy(point).applyMatrix4(this.invMatrix).clamp(this.min, this.max).applyMatrix4(this.matrix);
14698
- return target1;
14699
- };
14700
- })();
14701
- OrientedBox.prototype.distanceToPoint = (function() {
14702
- const target = new Vector3();
14703
- return function distanceToPoint(point) {
14704
- this.closestPointToPoint(point, target);
14705
- return point.distanceTo(target);
14706
- };
14707
- })();
14708
- OrientedBox.prototype.distanceToBox = (function() {
14709
- const xyzFields = ["x", "y", "z"];
14710
- const segments1 = new Array(12).fill().map(() => new Line3());
14711
- const segments2 = new Array(12).fill().map(() => new Line3());
14712
- const point1 = new Vector3();
14713
- const point2 = new Vector3();
14714
- return function distanceToBox(box2, threshold = 0, target1 = null, target2 = null) {
14715
- if (this.needsUpdate) {
14716
- this.update();
14717
- }
14718
- if (this.intersectsBox(box2)) {
14719
- if (target1 || target2) {
14720
- box2.getCenter(point2);
14721
- this.closestPointToPoint(point2, point1);
14722
- box2.closestPointToPoint(point1, point2);
14723
- if (target1) target1.copy(point1);
14724
- if (target2) target2.copy(point2);
14725
- }
14726
- return 0;
14727
- }
14728
- const threshold2 = threshold * threshold;
14729
- const min = box2.min;
14730
- const max2 = box2.max;
14731
- const points = this.points;
14732
- let closestDistanceSq = Infinity;
14733
- for (let i = 0; i < 8; i++) {
14734
- const p2 = points[i];
14735
- point2.copy(p2).clamp(min, max2);
14736
- const dist = p2.distanceToSquared(point2);
14737
- if (dist < closestDistanceSq) {
14738
- closestDistanceSq = dist;
14739
- if (target1) target1.copy(p2);
14740
- if (target2) target2.copy(point2);
14741
- if (dist < threshold2) return Math.sqrt(dist);
14742
- }
14743
- }
14744
- let count = 0;
14745
- for (let i = 0; i < 3; i++) {
14746
- for (let i1 = 0; i1 <= 1; i1++) {
14747
- for (let i2 = 0; i2 <= 1; i2++) {
14748
- const nextIndex = (i + 1) % 3;
14749
- const nextIndex2 = (i + 2) % 3;
14750
- const index = i1 << nextIndex | i2 << nextIndex2;
14751
- const index2 = 1 << i | i1 << nextIndex | i2 << nextIndex2;
14752
- const p1 = points[index];
14753
- const p2 = points[index2];
14754
- const line1 = segments1[count];
14755
- line1.set(p1, p2);
14756
- const f1 = xyzFields[i];
14757
- const f2 = xyzFields[nextIndex];
14758
- const f3 = xyzFields[nextIndex2];
14759
- const line2 = segments2[count];
14760
- const start = line2.start;
14761
- const end = line2.end;
14762
- start[f1] = min[f1];
14763
- start[f2] = i1 ? min[f2] : max2[f2];
14764
- start[f3] = i2 ? min[f3] : max2[f2];
14765
- end[f1] = max2[f1];
14766
- end[f2] = i1 ? min[f2] : max2[f2];
14767
- end[f3] = i2 ? min[f3] : max2[f2];
14768
- count++;
14769
- }
14770
- }
14771
- }
14772
- for (let x = 0; x <= 1; x++) {
14773
- for (let y = 0; y <= 1; y++) {
14774
- for (let z = 0; z <= 1; z++) {
14775
- point2.x = x ? max2.x : min.x;
14776
- point2.y = y ? max2.y : min.y;
14777
- point2.z = z ? max2.z : min.z;
14778
- this.closestPointToPoint(point2, point1);
14779
- const dist = point2.distanceToSquared(point1);
14780
- if (dist < closestDistanceSq) {
14781
- closestDistanceSq = dist;
14782
- if (target1) target1.copy(point1);
14783
- if (target2) target2.copy(point2);
14784
- if (dist < threshold2) return Math.sqrt(dist);
14785
- }
14786
- }
14787
- }
14788
- }
14789
- for (let i = 0; i < 12; i++) {
14790
- const l1 = segments1[i];
14791
- for (let i2 = 0; i2 < 12; i2++) {
14792
- const l2 = segments2[i2];
14793
- closestPointsSegmentToSegment(l1, l2, point1, point2);
14794
- const dist = point1.distanceToSquared(point2);
14795
- if (dist < closestDistanceSq) {
14796
- closestDistanceSq = dist;
14797
- if (target1) target1.copy(point1);
14798
- if (target2) target2.copy(point2);
14799
- if (dist < threshold2) return Math.sqrt(dist);
14800
- }
14801
- }
14802
- }
14803
- return Math.sqrt(closestDistanceSq);
14804
- };
14805
- })();
14806
- class PrimitivePool {
14807
- constructor(getNewPrimitive) {
14808
- this._getNewPrimitive = getNewPrimitive;
14809
- this._primitives = [];
14810
- }
14811
- getPrimitive() {
14812
- const primitives = this._primitives;
14813
- if (primitives.length === 0) {
14814
- return this._getNewPrimitive();
14815
- } else {
14816
- return primitives.pop();
14817
- }
14818
- }
14819
- releasePrimitive(primitive) {
14820
- this._primitives.push(primitive);
14821
- }
14822
- }
14823
- class ExtendedTrianglePoolBase extends PrimitivePool {
14824
- constructor() {
14825
- super(() => new ExtendedTriangle());
14826
- }
14827
- }
14828
- const ExtendedTrianglePool = /* @__PURE__ */ new ExtendedTrianglePoolBase();
14829
- class _BufferStack {
14830
- constructor() {
14831
- this.float32Array = null;
14832
- this.uint16Array = null;
14833
- this.uint32Array = null;
14834
- const stack = [];
14835
- let prevBuffer = null;
14836
- this.setBuffer = (buffer) => {
14837
- if (prevBuffer) {
14838
- stack.push(prevBuffer);
14839
- }
14840
- prevBuffer = buffer;
14841
- this.float32Array = new Float32Array(buffer);
14842
- this.uint16Array = new Uint16Array(buffer);
14843
- this.uint32Array = new Uint32Array(buffer);
14844
- };
14845
- this.clearBuffer = () => {
14846
- prevBuffer = null;
14847
- this.float32Array = null;
14848
- this.uint16Array = null;
14849
- this.uint32Array = null;
14850
- if (stack.length !== 0) {
14851
- this.setBuffer(stack.pop());
14852
- }
14853
- };
14854
- }
14855
- }
14856
- const BufferStack = new _BufferStack();
14857
- let _box1, _box2;
14858
- const boxStack = [];
14859
- const boxPool = /* @__PURE__ */ new PrimitivePool(() => new Box3());
14860
- function shapecast(bvh, root, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset) {
14861
- _box1 = boxPool.getPrimitive();
14862
- _box2 = boxPool.getPrimitive();
14863
- boxStack.push(_box1, _box2);
14864
- BufferStack.setBuffer(bvh._roots[root]);
14865
- const result = shapecastTraverse(0, bvh.geometry, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
14866
- BufferStack.clearBuffer();
14867
- boxPool.releasePrimitive(_box1);
14868
- boxPool.releasePrimitive(_box2);
14869
- boxStack.pop();
14870
- boxStack.pop();
14871
- const length = boxStack.length;
14872
- if (length > 0) {
14873
- _box2 = boxStack[length - 1];
14874
- _box1 = boxStack[length - 2];
14875
- }
14876
- return result;
14877
- }
14878
- function shapecastTraverse(nodeIndex32, geometry, intersectsBoundsFunc, intersectsRangeFunc, nodeScoreFunc = null, nodeIndexByteOffset = 0, depth = 0) {
14879
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
14880
- let nodeIndex16 = nodeIndex32 * 2;
14881
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
14882
- if (isLeaf) {
14883
- const offset = OFFSET(nodeIndex32, uint32Array2);
14884
- const count = COUNT(nodeIndex16, uint16Array2);
14885
- arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, _box1);
14886
- return intersectsRangeFunc(offset, count, false, depth, nodeIndexByteOffset + nodeIndex32, _box1);
14887
- } else {
14888
- let getLeftOffset = function(nodeIndex322) {
14889
- const { uint16Array: uint16Array3, uint32Array: uint32Array3 } = BufferStack;
14890
- let nodeIndex162 = nodeIndex322 * 2;
14891
- while (!IS_LEAF(nodeIndex162, uint16Array3)) {
14892
- nodeIndex322 = LEFT_NODE(nodeIndex322);
14893
- nodeIndex162 = nodeIndex322 * 2;
14894
- }
14895
- return OFFSET(nodeIndex322, uint32Array3);
14896
- }, getRightEndOffset = function(nodeIndex322) {
14897
- const { uint16Array: uint16Array3, uint32Array: uint32Array3 } = BufferStack;
14898
- let nodeIndex162 = nodeIndex322 * 2;
14899
- while (!IS_LEAF(nodeIndex162, uint16Array3)) {
14900
- nodeIndex322 = RIGHT_NODE(nodeIndex322, uint32Array3);
14901
- nodeIndex162 = nodeIndex322 * 2;
14902
- }
14903
- return OFFSET(nodeIndex322, uint32Array3) + COUNT(nodeIndex162, uint16Array3);
14904
- };
14905
- const left = LEFT_NODE(nodeIndex32);
14906
- const right = RIGHT_NODE(nodeIndex32, uint32Array2);
14907
- let c1 = left;
14908
- let c2 = right;
14909
- let score1, score2;
14910
- let box1, box2;
14911
- if (nodeScoreFunc) {
14912
- box1 = _box1;
14913
- box2 = _box2;
14914
- arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array2, box1);
14915
- arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array2, box2);
14916
- score1 = nodeScoreFunc(box1);
14917
- score2 = nodeScoreFunc(box2);
14918
- if (score2 < score1) {
14919
- c1 = right;
14920
- c2 = left;
14921
- const temp5 = score1;
14922
- score1 = score2;
14923
- score2 = temp5;
14924
- box1 = box2;
14925
- }
14926
- }
14927
- if (!box1) {
14928
- box1 = _box1;
14929
- arrayToBox(BOUNDING_DATA_INDEX(c1), float32Array2, box1);
14930
- }
14931
- const isC1Leaf = IS_LEAF(c1 * 2, uint16Array2);
14932
- const c1Intersection = intersectsBoundsFunc(box1, isC1Leaf, score1, depth + 1, nodeIndexByteOffset + c1);
14933
- let c1StopTraversal;
14934
- if (c1Intersection === CONTAINED) {
14935
- const offset = getLeftOffset(c1);
14936
- const end = getRightEndOffset(c1);
14937
- const count = end - offset;
14938
- c1StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c1, box1);
14939
- } else {
14940
- c1StopTraversal = c1Intersection && shapecastTraverse(
14941
- c1,
14942
- geometry,
14943
- intersectsBoundsFunc,
14944
- intersectsRangeFunc,
14945
- nodeScoreFunc,
14946
- nodeIndexByteOffset,
14947
- depth + 1
14948
- );
14949
- }
14950
- if (c1StopTraversal) return true;
14951
- box2 = _box2;
14952
- arrayToBox(BOUNDING_DATA_INDEX(c2), float32Array2, box2);
14953
- const isC2Leaf = IS_LEAF(c2 * 2, uint16Array2);
14954
- const c2Intersection = intersectsBoundsFunc(box2, isC2Leaf, score2, depth + 1, nodeIndexByteOffset + c2);
14955
- let c2StopTraversal;
14956
- if (c2Intersection === CONTAINED) {
14957
- const offset = getLeftOffset(c2);
14958
- const end = getRightEndOffset(c2);
14959
- const count = end - offset;
14960
- c2StopTraversal = intersectsRangeFunc(offset, count, true, depth + 1, nodeIndexByteOffset + c2, box2);
14961
- } else {
14962
- c2StopTraversal = c2Intersection && shapecastTraverse(
14963
- c2,
14964
- geometry,
14965
- intersectsBoundsFunc,
14966
- intersectsRangeFunc,
14967
- nodeScoreFunc,
14968
- nodeIndexByteOffset,
14969
- depth + 1
14970
- );
14971
- }
14972
- if (c2StopTraversal) return true;
14973
- return false;
14974
- }
14975
- }
14976
- const temp = /* @__PURE__ */ new Vector3();
14977
- const temp1$2 = /* @__PURE__ */ new Vector3();
14978
- function closestPointToPoint(bvh, point, target = {}, minThreshold = 0, maxThreshold = Infinity) {
14979
- const minThresholdSq = minThreshold * minThreshold;
14980
- const maxThresholdSq = maxThreshold * maxThreshold;
14981
- let closestDistanceSq = Infinity;
14982
- let closestDistanceTriIndex = null;
14983
- bvh.shapecast(
14984
- {
14985
- boundsTraverseOrder: (box2) => {
14986
- temp.copy(point).clamp(box2.min, box2.max);
14987
- return temp.distanceToSquared(point);
14988
- },
14989
- intersectsBounds: (box2, isLeaf, score) => {
14990
- return score < closestDistanceSq && score < maxThresholdSq;
14991
- },
14992
- intersectsTriangle: (tri, triIndex) => {
14993
- tri.closestPointToPoint(point, temp);
14994
- const distSq = point.distanceToSquared(temp);
14995
- if (distSq < closestDistanceSq) {
14996
- temp1$2.copy(temp);
14997
- closestDistanceSq = distSq;
14998
- closestDistanceTriIndex = triIndex;
14999
- }
15000
- if (distSq < minThresholdSq) {
15001
- return true;
15002
- } else {
15003
- return false;
15004
- }
15005
- }
15006
- }
15007
- );
15008
- if (closestDistanceSq === Infinity) return null;
15009
- const closestDistance = Math.sqrt(closestDistanceSq);
15010
- if (!target.point) target.point = temp1$2.clone();
15011
- else target.point.copy(temp1$2);
15012
- target.distance = closestDistance, target.faceIndex = closestDistanceTriIndex;
15013
- return target;
15014
- }
15015
- const IS_GT_REVISION_169 = parseInt(REVISION) >= 169;
15016
- const _vA = /* @__PURE__ */ new Vector3();
15017
- const _vB = /* @__PURE__ */ new Vector3();
15018
- const _vC = /* @__PURE__ */ new Vector3();
15019
- const _uvA = /* @__PURE__ */ new Vector2();
15020
- const _uvB = /* @__PURE__ */ new Vector2();
15021
- const _uvC = /* @__PURE__ */ new Vector2();
15022
- const _normalA = /* @__PURE__ */ new Vector3();
15023
- const _normalB = /* @__PURE__ */ new Vector3();
15024
- const _normalC = /* @__PURE__ */ new Vector3();
15025
- const _intersectionPoint = /* @__PURE__ */ new Vector3();
15026
- function checkIntersection(ray2, pA, pB, pC, point, side, near, far) {
15027
- let intersect;
15028
- if (side === BackSide) {
15029
- intersect = ray2.intersectTriangle(pC, pB, pA, true, point);
15030
- } else {
15031
- intersect = ray2.intersectTriangle(pA, pB, pC, side !== DoubleSide, point);
15032
- }
15033
- if (intersect === null) return null;
15034
- const distance = ray2.origin.distanceTo(point);
15035
- if (distance < near || distance > far) return null;
15036
- return {
15037
- distance,
15038
- point: point.clone()
15039
- };
15040
- }
15041
- function checkBufferGeometryIntersection(ray2, position, normal, uv, uv1, a2, b2, c2, side, near, far) {
15042
- _vA.fromBufferAttribute(position, a2);
15043
- _vB.fromBufferAttribute(position, b2);
15044
- _vC.fromBufferAttribute(position, c2);
15045
- const intersection = checkIntersection(ray2, _vA, _vB, _vC, _intersectionPoint, side, near, far);
15046
- if (intersection) {
15047
- const barycoord = new Vector3();
15048
- Triangle.getBarycoord(_intersectionPoint, _vA, _vB, _vC, barycoord);
15049
- if (uv) {
15050
- _uvA.fromBufferAttribute(uv, a2);
15051
- _uvB.fromBufferAttribute(uv, b2);
15052
- _uvC.fromBufferAttribute(uv, c2);
15053
- intersection.uv = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
15054
- }
15055
- if (uv1) {
15056
- _uvA.fromBufferAttribute(uv1, a2);
15057
- _uvB.fromBufferAttribute(uv1, b2);
15058
- _uvC.fromBufferAttribute(uv1, c2);
15059
- intersection.uv1 = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2());
15060
- }
15061
- if (normal) {
15062
- _normalA.fromBufferAttribute(normal, a2);
15063
- _normalB.fromBufferAttribute(normal, b2);
15064
- _normalC.fromBufferAttribute(normal, c2);
15065
- intersection.normal = Triangle.getInterpolation(_intersectionPoint, _vA, _vB, _vC, _normalA, _normalB, _normalC, new Vector3());
15066
- if (intersection.normal.dot(ray2.direction) > 0) {
15067
- intersection.normal.multiplyScalar(-1);
15068
- }
15069
- }
15070
- const face = {
15071
- a: a2,
15072
- b: b2,
15073
- c: c2,
15074
- normal: new Vector3(),
15075
- materialIndex: 0
15076
- };
15077
- Triangle.getNormal(_vA, _vB, _vC, face.normal);
15078
- intersection.face = face;
15079
- intersection.faceIndex = a2;
15080
- if (IS_GT_REVISION_169) {
15081
- intersection.barycoord = barycoord;
15082
- }
15083
- }
15084
- return intersection;
15085
- }
15086
- function intersectTri(geo, side, ray2, tri, intersections, near, far) {
15087
- const triOffset = tri * 3;
15088
- let a2 = triOffset + 0;
15089
- let b2 = triOffset + 1;
15090
- let c2 = triOffset + 2;
15091
- const index = geo.index;
15092
- if (geo.index) {
15093
- a2 = index.getX(a2);
15094
- b2 = index.getX(b2);
15095
- c2 = index.getX(c2);
15096
- }
15097
- const { position, normal, uv, uv1 } = geo.attributes;
15098
- const intersection = checkBufferGeometryIntersection(ray2, position, normal, uv, uv1, a2, b2, c2, side, near, far);
15099
- if (intersection) {
15100
- intersection.faceIndex = tri;
15101
- if (intersections) intersections.push(intersection);
15102
- return intersection;
15103
- }
15104
- return null;
15105
- }
15106
- function setTriangle(tri, i, index, pos) {
15107
- const ta = tri.a;
15108
- const tb = tri.b;
15109
- const tc = tri.c;
15110
- let i0 = i;
15111
- let i1 = i + 1;
15112
- let i2 = i + 2;
15113
- if (index) {
15114
- i0 = index.getX(i0);
15115
- i1 = index.getX(i1);
15116
- i2 = index.getX(i2);
15117
- }
15118
- ta.x = pos.getX(i0);
15119
- ta.y = pos.getY(i0);
15120
- ta.z = pos.getZ(i0);
15121
- tb.x = pos.getX(i1);
15122
- tb.y = pos.getY(i1);
15123
- tb.z = pos.getZ(i1);
15124
- tc.x = pos.getX(i2);
15125
- tc.y = pos.getY(i2);
15126
- tc.z = pos.getZ(i2);
15127
- }
15128
- function intersectTris(bvh, side, ray2, offset, count, intersections, near, far) {
15129
- const { geometry, _indirectBuffer } = bvh;
15130
- for (let i = offset, end = offset + count; i < end; i++) {
15131
- intersectTri(geometry, side, ray2, i, intersections, near, far);
15132
- }
15133
- }
15134
- function intersectClosestTri(bvh, side, ray2, offset, count, near, far) {
15135
- const { geometry, _indirectBuffer } = bvh;
15136
- let dist = Infinity;
15137
- let res = null;
15138
- for (let i = offset, end = offset + count; i < end; i++) {
15139
- let intersection;
15140
- intersection = intersectTri(geometry, side, ray2, i, null, near, far);
15141
- if (intersection && intersection.distance < dist) {
15142
- res = intersection;
15143
- dist = intersection.distance;
15144
- }
15145
- }
15146
- return res;
15147
- }
15148
- function iterateOverTriangles(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle3) {
15149
- const { geometry } = bvh;
15150
- const { index } = geometry;
15151
- const pos = geometry.attributes.position;
15152
- for (let i = offset, l2 = count + offset; i < l2; i++) {
15153
- let tri;
15154
- tri = i;
15155
- setTriangle(triangle3, tri * 3, index, pos);
15156
- triangle3.needsUpdate = true;
15157
- if (intersectsTriangleFunc(triangle3, tri, contained, depth)) {
15158
- return true;
15159
- }
15160
- }
15161
- return false;
15162
- }
15163
- function refit(bvh, nodeIndices = null) {
15164
- if (nodeIndices && Array.isArray(nodeIndices)) {
15165
- nodeIndices = new Set(nodeIndices);
15166
- }
15167
- const geometry = bvh.geometry;
15168
- const indexArr = geometry.index ? geometry.index.array : null;
15169
- const posAttr = geometry.attributes.position;
15170
- let buffer, uint32Array2, uint16Array2, float32Array2;
15171
- let byteOffset = 0;
15172
- const roots = bvh._roots;
15173
- for (let i = 0, l2 = roots.length; i < l2; i++) {
15174
- buffer = roots[i];
15175
- uint32Array2 = new Uint32Array(buffer);
15176
- uint16Array2 = new Uint16Array(buffer);
15177
- float32Array2 = new Float32Array(buffer);
15178
- _traverse2(0, byteOffset);
15179
- byteOffset += buffer.byteLength;
15180
- }
15181
- function _traverse2(node32Index, byteOffset2, force = false) {
15182
- const node16Index = node32Index * 2;
15183
- const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
15184
- if (isLeaf) {
15185
- const offset = uint32Array2[node32Index + 6];
15186
- const count = uint16Array2[node16Index + 14];
15187
- let minx = Infinity;
15188
- let miny = Infinity;
15189
- let minz = Infinity;
15190
- let maxx = -Infinity;
15191
- let maxy = -Infinity;
15192
- let maxz = -Infinity;
15193
- for (let i = 3 * offset, l2 = 3 * (offset + count); i < l2; i++) {
15194
- let index = indexArr[i];
15195
- const x = posAttr.getX(index);
15196
- const y = posAttr.getY(index);
15197
- const z = posAttr.getZ(index);
15198
- if (x < minx) minx = x;
15199
- if (x > maxx) maxx = x;
15200
- if (y < miny) miny = y;
15201
- if (y > maxy) maxy = y;
15202
- if (z < minz) minz = z;
15203
- if (z > maxz) maxz = z;
15204
- }
15205
- if (float32Array2[node32Index + 0] !== minx || float32Array2[node32Index + 1] !== miny || float32Array2[node32Index + 2] !== minz || float32Array2[node32Index + 3] !== maxx || float32Array2[node32Index + 4] !== maxy || float32Array2[node32Index + 5] !== maxz) {
15206
- float32Array2[node32Index + 0] = minx;
15207
- float32Array2[node32Index + 1] = miny;
15208
- float32Array2[node32Index + 2] = minz;
15209
- float32Array2[node32Index + 3] = maxx;
15210
- float32Array2[node32Index + 4] = maxy;
15211
- float32Array2[node32Index + 5] = maxz;
15212
- return true;
15213
- } else {
15214
- return false;
15215
- }
15216
- } else {
15217
- const left = node32Index + 8;
15218
- const right = uint32Array2[node32Index + 6];
15219
- const offsetLeft = left + byteOffset2;
15220
- const offsetRight = right + byteOffset2;
15221
- let forceChildren = force;
15222
- let includesLeft = false;
15223
- let includesRight = false;
15224
- if (nodeIndices) {
15225
- if (!forceChildren) {
15226
- includesLeft = nodeIndices.has(offsetLeft);
15227
- includesRight = nodeIndices.has(offsetRight);
15228
- forceChildren = !includesLeft && !includesRight;
15229
- }
15230
- } else {
15231
- includesLeft = true;
15232
- includesRight = true;
15233
- }
15234
- const traverseLeft = forceChildren || includesLeft;
15235
- const traverseRight = forceChildren || includesRight;
15236
- let leftChange = false;
15237
- if (traverseLeft) {
15238
- leftChange = _traverse2(left, byteOffset2, forceChildren);
15239
- }
15240
- let rightChange = false;
15241
- if (traverseRight) {
15242
- rightChange = _traverse2(right, byteOffset2, forceChildren);
15243
- }
15244
- const didChange = leftChange || rightChange;
15245
- if (didChange) {
15246
- for (let i = 0; i < 3; i++) {
15247
- const lefti = left + i;
15248
- const righti = right + i;
15249
- const minLeftValue = float32Array2[lefti];
15250
- const maxLeftValue = float32Array2[lefti + 3];
15251
- const minRightValue = float32Array2[righti];
15252
- const maxRightValue = float32Array2[righti + 3];
15253
- float32Array2[node32Index + i] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
15254
- float32Array2[node32Index + i + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
15255
- }
15256
- }
15257
- return didChange;
15258
- }
15259
- }
15260
- }
15261
- function intersectRay(nodeIndex32, array, ray2, near, far) {
15262
- let tmin, tmax, tymin, tymax, tzmin, tzmax;
15263
- const invdirx = 1 / ray2.direction.x, invdiry = 1 / ray2.direction.y, invdirz = 1 / ray2.direction.z;
15264
- const ox = ray2.origin.x;
15265
- const oy = ray2.origin.y;
15266
- const oz = ray2.origin.z;
15267
- let minx = array[nodeIndex32];
15268
- let maxx = array[nodeIndex32 + 3];
15269
- let miny = array[nodeIndex32 + 1];
15270
- let maxy = array[nodeIndex32 + 3 + 1];
15271
- let minz = array[nodeIndex32 + 2];
15272
- let maxz = array[nodeIndex32 + 3 + 2];
15273
- if (invdirx >= 0) {
15274
- tmin = (minx - ox) * invdirx;
15275
- tmax = (maxx - ox) * invdirx;
15276
- } else {
15277
- tmin = (maxx - ox) * invdirx;
15278
- tmax = (minx - ox) * invdirx;
15279
- }
15280
- if (invdiry >= 0) {
15281
- tymin = (miny - oy) * invdiry;
15282
- tymax = (maxy - oy) * invdiry;
15283
- } else {
15284
- tymin = (maxy - oy) * invdiry;
15285
- tymax = (miny - oy) * invdiry;
15286
- }
15287
- if (tmin > tymax || tymin > tmax) return false;
15288
- if (tymin > tmin || isNaN(tmin)) tmin = tymin;
15289
- if (tymax < tmax || isNaN(tmax)) tmax = tymax;
15290
- if (invdirz >= 0) {
15291
- tzmin = (minz - oz) * invdirz;
15292
- tzmax = (maxz - oz) * invdirz;
15293
- } else {
15294
- tzmin = (maxz - oz) * invdirz;
15295
- tzmax = (minz - oz) * invdirz;
15296
- }
15297
- if (tmin > tzmax || tzmin > tmax) return false;
15298
- if (tzmin > tmin || tmin !== tmin) tmin = tzmin;
15299
- if (tzmax < tmax || tmax !== tmax) tmax = tzmax;
15300
- return tmin <= far && tmax >= near;
15301
- }
15302
- function intersectTris_indirect(bvh, side, ray2, offset, count, intersections, near, far) {
15303
- const { geometry, _indirectBuffer } = bvh;
15304
- for (let i = offset, end = offset + count; i < end; i++) {
15305
- let vi = _indirectBuffer ? _indirectBuffer[i] : i;
15306
- intersectTri(geometry, side, ray2, vi, intersections, near, far);
15307
- }
15308
- }
15309
- function intersectClosestTri_indirect(bvh, side, ray2, offset, count, near, far) {
15310
- const { geometry, _indirectBuffer } = bvh;
15311
- let dist = Infinity;
15312
- let res = null;
15313
- for (let i = offset, end = offset + count; i < end; i++) {
15314
- let intersection;
15315
- intersection = intersectTri(geometry, side, ray2, _indirectBuffer ? _indirectBuffer[i] : i, null, near, far);
15316
- if (intersection && intersection.distance < dist) {
15317
- res = intersection;
15318
- dist = intersection.distance;
15319
- }
15320
- }
15321
- return res;
15322
- }
15323
- function iterateOverTriangles_indirect(offset, count, bvh, intersectsTriangleFunc, contained, depth, triangle3) {
15324
- const { geometry } = bvh;
15325
- const { index } = geometry;
15326
- const pos = geometry.attributes.position;
15327
- for (let i = offset, l2 = count + offset; i < l2; i++) {
15328
- let tri;
15329
- tri = bvh.resolveTriangleIndex(i);
15330
- setTriangle(triangle3, tri * 3, index, pos);
15331
- triangle3.needsUpdate = true;
15332
- if (intersectsTriangleFunc(triangle3, tri, contained, depth)) {
15333
- return true;
15334
- }
15335
- }
15336
- return false;
15337
- }
15338
- function raycast(bvh, root, side, ray2, intersects, near, far) {
15339
- BufferStack.setBuffer(bvh._roots[root]);
15340
- _raycast$1(0, bvh, side, ray2, intersects, near, far);
15341
- BufferStack.clearBuffer();
15342
- }
15343
- function _raycast$1(nodeIndex32, bvh, side, ray2, intersects, near, far) {
15344
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
15345
- const nodeIndex16 = nodeIndex32 * 2;
15346
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
15347
- if (isLeaf) {
15348
- const offset = OFFSET(nodeIndex32, uint32Array2);
15349
- const count = COUNT(nodeIndex16, uint16Array2);
15350
- intersectTris(bvh, side, ray2, offset, count, intersects, near, far);
15351
- } else {
15352
- const leftIndex = LEFT_NODE(nodeIndex32);
15353
- if (intersectRay(leftIndex, float32Array2, ray2, near, far)) {
15354
- _raycast$1(leftIndex, bvh, side, ray2, intersects, near, far);
15355
- }
15356
- const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array2);
15357
- if (intersectRay(rightIndex, float32Array2, ray2, near, far)) {
15358
- _raycast$1(rightIndex, bvh, side, ray2, intersects, near, far);
15359
- }
15360
- }
15361
- }
15362
- const _xyzFields$1 = ["x", "y", "z"];
15363
- function raycastFirst(bvh, root, side, ray2, near, far) {
15364
- BufferStack.setBuffer(bvh._roots[root]);
15365
- const result = _raycastFirst$1(0, bvh, side, ray2, near, far);
15366
- BufferStack.clearBuffer();
15367
- return result;
15368
- }
15369
- function _raycastFirst$1(nodeIndex32, bvh, side, ray2, near, far) {
15370
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
15371
- let nodeIndex16 = nodeIndex32 * 2;
15372
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
15373
- if (isLeaf) {
15374
- const offset = OFFSET(nodeIndex32, uint32Array2);
15375
- const count = COUNT(nodeIndex16, uint16Array2);
15376
- return intersectClosestTri(bvh, side, ray2, offset, count, near, far);
15377
- } else {
15378
- const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
15379
- const xyzAxis = _xyzFields$1[splitAxis];
15380
- const rayDir = ray2.direction[xyzAxis];
15381
- const leftToRight = rayDir >= 0;
15382
- let c1, c2;
15383
- if (leftToRight) {
15384
- c1 = LEFT_NODE(nodeIndex32);
15385
- c2 = RIGHT_NODE(nodeIndex32, uint32Array2);
15386
- } else {
15387
- c1 = RIGHT_NODE(nodeIndex32, uint32Array2);
15388
- c2 = LEFT_NODE(nodeIndex32);
15389
- }
15390
- const c1Intersection = intersectRay(c1, float32Array2, ray2, near, far);
15391
- const c1Result = c1Intersection ? _raycastFirst$1(c1, bvh, side, ray2, near, far) : null;
15392
- if (c1Result) {
15393
- const point = c1Result.point[xyzAxis];
15394
- const isOutside = leftToRight ? point <= float32Array2[c2 + splitAxis] : (
15395
- // min bounding data
15396
- point >= float32Array2[c2 + splitAxis + 3]
15397
- );
15398
- if (isOutside) {
15399
- return c1Result;
15400
- }
15401
- }
15402
- const c2Intersection = intersectRay(c2, float32Array2, ray2, near, far);
15403
- const c2Result = c2Intersection ? _raycastFirst$1(c2, bvh, side, ray2, near, far) : null;
15404
- if (c1Result && c2Result) {
15405
- return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
15406
- } else {
15407
- return c1Result || c2Result || null;
15408
- }
15409
- }
15410
- }
15411
- const boundingBox$1 = /* @__PURE__ */ new Box3();
15412
- const triangle$1 = /* @__PURE__ */ new ExtendedTriangle();
15413
- const triangle2$1 = /* @__PURE__ */ new ExtendedTriangle();
15414
- const invertedMat$1 = /* @__PURE__ */ new Matrix4();
15415
- const obb$4 = /* @__PURE__ */ new OrientedBox();
15416
- const obb2$3 = /* @__PURE__ */ new OrientedBox();
15417
- function intersectsGeometry(bvh, root, otherGeometry, geometryToBvh) {
15418
- BufferStack.setBuffer(bvh._roots[root]);
15419
- const result = _intersectsGeometry$1(0, bvh, otherGeometry, geometryToBvh);
15420
- BufferStack.clearBuffer();
15421
- return result;
15422
- }
15423
- function _intersectsGeometry$1(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
15424
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
15425
- let nodeIndex16 = nodeIndex32 * 2;
15426
- if (cachedObb === null) {
15427
- if (!otherGeometry.boundingBox) {
15428
- otherGeometry.computeBoundingBox();
15429
- }
15430
- obb$4.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
15431
- cachedObb = obb$4;
15432
- }
15433
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
15434
- if (isLeaf) {
15435
- const thisGeometry = bvh.geometry;
15436
- const thisIndex = thisGeometry.index;
15437
- const thisPos = thisGeometry.attributes.position;
15438
- const index = otherGeometry.index;
15439
- const pos = otherGeometry.attributes.position;
15440
- const offset = OFFSET(nodeIndex32, uint32Array2);
15441
- const count = COUNT(nodeIndex16, uint16Array2);
15442
- invertedMat$1.copy(geometryToBvh).invert();
15443
- if (otherGeometry.boundsTree) {
15444
- arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, obb2$3);
15445
- obb2$3.matrix.copy(invertedMat$1);
15446
- obb2$3.needsUpdate = true;
15447
- const res = otherGeometry.boundsTree.shapecast({
15448
- intersectsBounds: (box2) => obb2$3.intersectsBox(box2),
15449
- intersectsTriangle: (tri) => {
15450
- tri.a.applyMatrix4(geometryToBvh);
15451
- tri.b.applyMatrix4(geometryToBvh);
15452
- tri.c.applyMatrix4(geometryToBvh);
15453
- tri.needsUpdate = true;
15454
- for (let i = offset * 3, l2 = (count + offset) * 3; i < l2; i += 3) {
15455
- setTriangle(triangle2$1, i, thisIndex, thisPos);
15456
- triangle2$1.needsUpdate = true;
15457
- if (tri.intersectsTriangle(triangle2$1)) {
15458
- return true;
15459
- }
15460
- }
15461
- return false;
15462
- }
15463
- });
15464
- return res;
15465
- } else {
15466
- for (let i = offset * 3, l2 = (count + offset) * 3; i < l2; i += 3) {
15467
- setTriangle(triangle$1, i, thisIndex, thisPos);
15468
- triangle$1.a.applyMatrix4(invertedMat$1);
15469
- triangle$1.b.applyMatrix4(invertedMat$1);
15470
- triangle$1.c.applyMatrix4(invertedMat$1);
15471
- triangle$1.needsUpdate = true;
15472
- for (let i2 = 0, l22 = index.count; i2 < l22; i2 += 3) {
15473
- setTriangle(triangle2$1, i2, index, pos);
15474
- triangle2$1.needsUpdate = true;
15475
- if (triangle$1.intersectsTriangle(triangle2$1)) {
15476
- return true;
15477
- }
15478
- }
15479
- }
15480
- }
15481
- } else {
15482
- const left = nodeIndex32 + 8;
15483
- const right = uint32Array2[nodeIndex32 + 6];
15484
- arrayToBox(BOUNDING_DATA_INDEX(left), float32Array2, boundingBox$1);
15485
- const leftIntersection = cachedObb.intersectsBox(boundingBox$1) && _intersectsGeometry$1(left, bvh, otherGeometry, geometryToBvh, cachedObb);
15486
- if (leftIntersection) return true;
15487
- arrayToBox(BOUNDING_DATA_INDEX(right), float32Array2, boundingBox$1);
15488
- const rightIntersection = cachedObb.intersectsBox(boundingBox$1) && _intersectsGeometry$1(right, bvh, otherGeometry, geometryToBvh, cachedObb);
15489
- if (rightIntersection) return true;
15490
- return false;
15491
- }
15492
- }
15493
- const tempMatrix$1 = /* @__PURE__ */ new Matrix4();
15494
- const obb$3 = /* @__PURE__ */ new OrientedBox();
15495
- const obb2$2 = /* @__PURE__ */ new OrientedBox();
15496
- const temp1$1 = /* @__PURE__ */ new Vector3();
15497
- const temp2$1 = /* @__PURE__ */ new Vector3();
15498
- const temp3$1 = /* @__PURE__ */ new Vector3();
15499
- const temp4$1 = /* @__PURE__ */ new Vector3();
15500
- function closestPointToGeometry(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
15501
- if (!otherGeometry.boundingBox) {
15502
- otherGeometry.computeBoundingBox();
15503
- }
15504
- obb$3.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
15505
- obb$3.needsUpdate = true;
15506
- const geometry = bvh.geometry;
15507
- const pos = geometry.attributes.position;
15508
- const index = geometry.index;
15509
- const otherPos = otherGeometry.attributes.position;
15510
- const otherIndex = otherGeometry.index;
15511
- const triangle3 = ExtendedTrianglePool.getPrimitive();
15512
- const triangle22 = ExtendedTrianglePool.getPrimitive();
15513
- let tempTarget1 = temp1$1;
15514
- let tempTargetDest1 = temp2$1;
15515
- let tempTarget2 = null;
15516
- let tempTargetDest2 = null;
15517
- if (target2) {
15518
- tempTarget2 = temp3$1;
15519
- tempTargetDest2 = temp4$1;
15520
- }
15521
- let closestDistance = Infinity;
15522
- let closestDistanceTriIndex = null;
15523
- let closestDistanceOtherTriIndex = null;
15524
- tempMatrix$1.copy(geometryToBvh).invert();
15525
- obb2$2.matrix.copy(tempMatrix$1);
15526
- bvh.shapecast(
15527
- {
15528
- boundsTraverseOrder: (box2) => {
15529
- return obb$3.distanceToBox(box2);
15530
- },
15531
- intersectsBounds: (box2, isLeaf, score) => {
15532
- if (score < closestDistance && score < maxThreshold) {
15533
- if (isLeaf) {
15534
- obb2$2.min.copy(box2.min);
15535
- obb2$2.max.copy(box2.max);
15536
- obb2$2.needsUpdate = true;
15537
- }
15538
- return true;
15539
- }
15540
- return false;
15541
- },
15542
- intersectsRange: (offset, count) => {
15543
- if (otherGeometry.boundsTree) {
15544
- const otherBvh = otherGeometry.boundsTree;
15545
- return otherBvh.shapecast({
15546
- boundsTraverseOrder: (box2) => {
15547
- return obb2$2.distanceToBox(box2);
15548
- },
15549
- intersectsBounds: (box2, isLeaf, score) => {
15550
- return score < closestDistance && score < maxThreshold;
15551
- },
15552
- intersectsRange: (otherOffset, otherCount) => {
15553
- for (let i2 = otherOffset, l2 = otherOffset + otherCount; i2 < l2; i2++) {
15554
- setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
15555
- triangle22.a.applyMatrix4(geometryToBvh);
15556
- triangle22.b.applyMatrix4(geometryToBvh);
15557
- triangle22.c.applyMatrix4(geometryToBvh);
15558
- triangle22.needsUpdate = true;
15559
- for (let i = offset, l3 = offset + count; i < l3; i++) {
15560
- setTriangle(triangle3, 3 * i, index, pos);
15561
- triangle3.needsUpdate = true;
15562
- const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
15563
- if (dist < closestDistance) {
15564
- tempTargetDest1.copy(tempTarget1);
15565
- if (tempTargetDest2) {
15566
- tempTargetDest2.copy(tempTarget2);
15567
- }
15568
- closestDistance = dist;
15569
- closestDistanceTriIndex = i;
15570
- closestDistanceOtherTriIndex = i2;
15571
- }
15572
- if (dist < minThreshold) {
15573
- return true;
15574
- }
15575
- }
15576
- }
15577
- }
15578
- });
15579
- } else {
15580
- const triCount = getTriCount(otherGeometry);
15581
- for (let i2 = 0, l2 = triCount; i2 < l2; i2++) {
15582
- setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
15583
- triangle22.a.applyMatrix4(geometryToBvh);
15584
- triangle22.b.applyMatrix4(geometryToBvh);
15585
- triangle22.c.applyMatrix4(geometryToBvh);
15586
- triangle22.needsUpdate = true;
15587
- for (let i = offset, l3 = offset + count; i < l3; i++) {
15588
- setTriangle(triangle3, 3 * i, index, pos);
15589
- triangle3.needsUpdate = true;
15590
- const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
15591
- if (dist < closestDistance) {
15592
- tempTargetDest1.copy(tempTarget1);
15593
- if (tempTargetDest2) {
15594
- tempTargetDest2.copy(tempTarget2);
15595
- }
15596
- closestDistance = dist;
15597
- closestDistanceTriIndex = i;
15598
- closestDistanceOtherTriIndex = i2;
15599
- }
15600
- if (dist < minThreshold) {
15601
- return true;
15602
- }
15603
- }
15604
- }
15605
- }
15606
- }
15607
- }
15608
- );
15609
- ExtendedTrianglePool.releasePrimitive(triangle3);
15610
- ExtendedTrianglePool.releasePrimitive(triangle22);
15611
- if (closestDistance === Infinity) {
15612
- return null;
15613
- }
15614
- if (!target1.point) {
15615
- target1.point = tempTargetDest1.clone();
15616
- } else {
15617
- target1.point.copy(tempTargetDest1);
15618
- }
15619
- target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
15620
- if (target2) {
15621
- if (!target2.point) target2.point = tempTargetDest2.clone();
15622
- else target2.point.copy(tempTargetDest2);
15623
- target2.point.applyMatrix4(tempMatrix$1);
15624
- tempTargetDest1.applyMatrix4(tempMatrix$1);
15625
- target2.distance = tempTargetDest1.sub(target2.point).length();
15626
- target2.faceIndex = closestDistanceOtherTriIndex;
15627
- }
15628
- return target1;
15629
- }
15630
- function refit_indirect(bvh, nodeIndices = null) {
15631
- if (nodeIndices && Array.isArray(nodeIndices)) {
15632
- nodeIndices = new Set(nodeIndices);
15633
- }
15634
- const geometry = bvh.geometry;
15635
- const indexArr = geometry.index ? geometry.index.array : null;
15636
- const posAttr = geometry.attributes.position;
15637
- let buffer, uint32Array2, uint16Array2, float32Array2;
15638
- let byteOffset = 0;
15639
- const roots = bvh._roots;
15640
- for (let i = 0, l2 = roots.length; i < l2; i++) {
15641
- buffer = roots[i];
15642
- uint32Array2 = new Uint32Array(buffer);
15643
- uint16Array2 = new Uint16Array(buffer);
15644
- float32Array2 = new Float32Array(buffer);
15645
- _traverse2(0, byteOffset);
15646
- byteOffset += buffer.byteLength;
15647
- }
15648
- function _traverse2(node32Index, byteOffset2, force = false) {
15649
- const node16Index = node32Index * 2;
15650
- const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
15651
- if (isLeaf) {
15652
- const offset = uint32Array2[node32Index + 6];
15653
- const count = uint16Array2[node16Index + 14];
15654
- let minx = Infinity;
15655
- let miny = Infinity;
15656
- let minz = Infinity;
15657
- let maxx = -Infinity;
15658
- let maxy = -Infinity;
15659
- let maxz = -Infinity;
15660
- for (let i = offset, l2 = offset + count; i < l2; i++) {
15661
- const t2 = 3 * bvh.resolveTriangleIndex(i);
15662
- for (let j2 = 0; j2 < 3; j2++) {
15663
- let index = t2 + j2;
15664
- index = indexArr ? indexArr[index] : index;
15665
- const x = posAttr.getX(index);
15666
- const y = posAttr.getY(index);
15667
- const z = posAttr.getZ(index);
15668
- if (x < minx) minx = x;
15669
- if (x > maxx) maxx = x;
15670
- if (y < miny) miny = y;
15671
- if (y > maxy) maxy = y;
15672
- if (z < minz) minz = z;
15673
- if (z > maxz) maxz = z;
15674
- }
15675
- }
15676
- if (float32Array2[node32Index + 0] !== minx || float32Array2[node32Index + 1] !== miny || float32Array2[node32Index + 2] !== minz || float32Array2[node32Index + 3] !== maxx || float32Array2[node32Index + 4] !== maxy || float32Array2[node32Index + 5] !== maxz) {
15677
- float32Array2[node32Index + 0] = minx;
15678
- float32Array2[node32Index + 1] = miny;
15679
- float32Array2[node32Index + 2] = minz;
15680
- float32Array2[node32Index + 3] = maxx;
15681
- float32Array2[node32Index + 4] = maxy;
15682
- float32Array2[node32Index + 5] = maxz;
15683
- return true;
15684
- } else {
15685
- return false;
15686
- }
15687
- } else {
15688
- const left = node32Index + 8;
15689
- const right = uint32Array2[node32Index + 6];
15690
- const offsetLeft = left + byteOffset2;
15691
- const offsetRight = right + byteOffset2;
15692
- let forceChildren = force;
15693
- let includesLeft = false;
15694
- let includesRight = false;
15695
- if (nodeIndices) {
15696
- if (!forceChildren) {
15697
- includesLeft = nodeIndices.has(offsetLeft);
15698
- includesRight = nodeIndices.has(offsetRight);
15699
- forceChildren = !includesLeft && !includesRight;
15700
- }
15701
- } else {
15702
- includesLeft = true;
15703
- includesRight = true;
15704
- }
15705
- const traverseLeft = forceChildren || includesLeft;
15706
- const traverseRight = forceChildren || includesRight;
15707
- let leftChange = false;
15708
- if (traverseLeft) {
15709
- leftChange = _traverse2(left, byteOffset2, forceChildren);
15710
- }
15711
- let rightChange = false;
15712
- if (traverseRight) {
15713
- rightChange = _traverse2(right, byteOffset2, forceChildren);
15714
- }
15715
- const didChange = leftChange || rightChange;
15716
- if (didChange) {
15717
- for (let i = 0; i < 3; i++) {
15718
- const lefti = left + i;
15719
- const righti = right + i;
15720
- const minLeftValue = float32Array2[lefti];
15721
- const maxLeftValue = float32Array2[lefti + 3];
15722
- const minRightValue = float32Array2[righti];
15723
- const maxRightValue = float32Array2[righti + 3];
15724
- float32Array2[node32Index + i] = minLeftValue < minRightValue ? minLeftValue : minRightValue;
15725
- float32Array2[node32Index + i + 3] = maxLeftValue > maxRightValue ? maxLeftValue : maxRightValue;
15726
- }
15727
- }
15728
- return didChange;
15729
- }
15730
- }
15731
- }
15732
- function raycast_indirect(bvh, root, side, ray2, intersects, near, far) {
15733
- BufferStack.setBuffer(bvh._roots[root]);
15734
- _raycast(0, bvh, side, ray2, intersects, near, far);
15735
- BufferStack.clearBuffer();
15736
- }
15737
- function _raycast(nodeIndex32, bvh, side, ray2, intersects, near, far) {
15738
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
15739
- const nodeIndex16 = nodeIndex32 * 2;
15740
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
15741
- if (isLeaf) {
15742
- const offset = OFFSET(nodeIndex32, uint32Array2);
15743
- const count = COUNT(nodeIndex16, uint16Array2);
15744
- intersectTris_indirect(bvh, side, ray2, offset, count, intersects, near, far);
15745
- } else {
15746
- const leftIndex = LEFT_NODE(nodeIndex32);
15747
- if (intersectRay(leftIndex, float32Array2, ray2, near, far)) {
15748
- _raycast(leftIndex, bvh, side, ray2, intersects, near, far);
15749
- }
15750
- const rightIndex = RIGHT_NODE(nodeIndex32, uint32Array2);
15751
- if (intersectRay(rightIndex, float32Array2, ray2, near, far)) {
15752
- _raycast(rightIndex, bvh, side, ray2, intersects, near, far);
15753
- }
15754
- }
15755
- }
15756
- const _xyzFields = ["x", "y", "z"];
15757
- function raycastFirst_indirect(bvh, root, side, ray2, near, far) {
15758
- BufferStack.setBuffer(bvh._roots[root]);
15759
- const result = _raycastFirst(0, bvh, side, ray2, near, far);
15760
- BufferStack.clearBuffer();
15761
- return result;
15762
- }
15763
- function _raycastFirst(nodeIndex32, bvh, side, ray2, near, far) {
15764
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
15765
- let nodeIndex16 = nodeIndex32 * 2;
15766
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
15767
- if (isLeaf) {
15768
- const offset = OFFSET(nodeIndex32, uint32Array2);
15769
- const count = COUNT(nodeIndex16, uint16Array2);
15770
- return intersectClosestTri_indirect(bvh, side, ray2, offset, count, near, far);
15771
- } else {
15772
- const splitAxis = SPLIT_AXIS(nodeIndex32, uint32Array2);
15773
- const xyzAxis = _xyzFields[splitAxis];
15774
- const rayDir = ray2.direction[xyzAxis];
15775
- const leftToRight = rayDir >= 0;
15776
- let c1, c2;
15777
- if (leftToRight) {
15778
- c1 = LEFT_NODE(nodeIndex32);
15779
- c2 = RIGHT_NODE(nodeIndex32, uint32Array2);
15780
- } else {
15781
- c1 = RIGHT_NODE(nodeIndex32, uint32Array2);
15782
- c2 = LEFT_NODE(nodeIndex32);
15783
- }
15784
- const c1Intersection = intersectRay(c1, float32Array2, ray2, near, far);
15785
- const c1Result = c1Intersection ? _raycastFirst(c1, bvh, side, ray2, near, far) : null;
15786
- if (c1Result) {
15787
- const point = c1Result.point[xyzAxis];
15788
- const isOutside = leftToRight ? point <= float32Array2[c2 + splitAxis] : (
15789
- // min bounding data
15790
- point >= float32Array2[c2 + splitAxis + 3]
15791
- );
15792
- if (isOutside) {
15793
- return c1Result;
15794
- }
15795
- }
15796
- const c2Intersection = intersectRay(c2, float32Array2, ray2, near, far);
15797
- const c2Result = c2Intersection ? _raycastFirst(c2, bvh, side, ray2, near, far) : null;
15798
- if (c1Result && c2Result) {
15799
- return c1Result.distance <= c2Result.distance ? c1Result : c2Result;
15800
- } else {
15801
- return c1Result || c2Result || null;
15802
- }
15803
- }
15804
- }
15805
- const boundingBox = /* @__PURE__ */ new Box3();
15806
- const triangle = /* @__PURE__ */ new ExtendedTriangle();
15807
- const triangle2 = /* @__PURE__ */ new ExtendedTriangle();
15808
- const invertedMat = /* @__PURE__ */ new Matrix4();
15809
- const obb$2 = /* @__PURE__ */ new OrientedBox();
15810
- const obb2$1 = /* @__PURE__ */ new OrientedBox();
15811
- function intersectsGeometry_indirect(bvh, root, otherGeometry, geometryToBvh) {
15812
- BufferStack.setBuffer(bvh._roots[root]);
15813
- const result = _intersectsGeometry(0, bvh, otherGeometry, geometryToBvh);
15814
- BufferStack.clearBuffer();
15815
- return result;
15816
- }
15817
- function _intersectsGeometry(nodeIndex32, bvh, otherGeometry, geometryToBvh, cachedObb = null) {
15818
- const { float32Array: float32Array2, uint16Array: uint16Array2, uint32Array: uint32Array2 } = BufferStack;
15819
- let nodeIndex16 = nodeIndex32 * 2;
15820
- if (cachedObb === null) {
15821
- if (!otherGeometry.boundingBox) {
15822
- otherGeometry.computeBoundingBox();
15823
- }
15824
- obb$2.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
15825
- cachedObb = obb$2;
15826
- }
15827
- const isLeaf = IS_LEAF(nodeIndex16, uint16Array2);
15828
- if (isLeaf) {
15829
- const thisGeometry = bvh.geometry;
15830
- const thisIndex = thisGeometry.index;
15831
- const thisPos = thisGeometry.attributes.position;
15832
- const index = otherGeometry.index;
15833
- const pos = otherGeometry.attributes.position;
15834
- const offset = OFFSET(nodeIndex32, uint32Array2);
15835
- const count = COUNT(nodeIndex16, uint16Array2);
15836
- invertedMat.copy(geometryToBvh).invert();
15837
- if (otherGeometry.boundsTree) {
15838
- arrayToBox(BOUNDING_DATA_INDEX(nodeIndex32), float32Array2, obb2$1);
15839
- obb2$1.matrix.copy(invertedMat);
15840
- obb2$1.needsUpdate = true;
15841
- const res = otherGeometry.boundsTree.shapecast({
15842
- intersectsBounds: (box2) => obb2$1.intersectsBox(box2),
15843
- intersectsTriangle: (tri) => {
15844
- tri.a.applyMatrix4(geometryToBvh);
15845
- tri.b.applyMatrix4(geometryToBvh);
15846
- tri.c.applyMatrix4(geometryToBvh);
15847
- tri.needsUpdate = true;
15848
- for (let i = offset, l2 = count + offset; i < l2; i++) {
15849
- setTriangle(triangle2, 3 * bvh.resolveTriangleIndex(i), thisIndex, thisPos);
15850
- triangle2.needsUpdate = true;
15851
- if (tri.intersectsTriangle(triangle2)) {
15852
- return true;
15853
- }
15854
- }
15855
- return false;
15856
- }
15857
- });
15858
- return res;
15859
- } else {
15860
- for (let i = offset, l2 = count + offset; i < l2; i++) {
15861
- const ti = bvh.resolveTriangleIndex(i);
15862
- setTriangle(triangle, 3 * ti, thisIndex, thisPos);
15863
- triangle.a.applyMatrix4(invertedMat);
15864
- triangle.b.applyMatrix4(invertedMat);
15865
- triangle.c.applyMatrix4(invertedMat);
15866
- triangle.needsUpdate = true;
15867
- for (let i2 = 0, l22 = index.count; i2 < l22; i2 += 3) {
15868
- setTriangle(triangle2, i2, index, pos);
15869
- triangle2.needsUpdate = true;
15870
- if (triangle.intersectsTriangle(triangle2)) {
15871
- return true;
15872
- }
15873
- }
15874
- }
15875
- }
15876
- } else {
15877
- const left = nodeIndex32 + 8;
15878
- const right = uint32Array2[nodeIndex32 + 6];
15879
- arrayToBox(BOUNDING_DATA_INDEX(left), float32Array2, boundingBox);
15880
- const leftIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(left, bvh, otherGeometry, geometryToBvh, cachedObb);
15881
- if (leftIntersection) return true;
15882
- arrayToBox(BOUNDING_DATA_INDEX(right), float32Array2, boundingBox);
15883
- const rightIntersection = cachedObb.intersectsBox(boundingBox) && _intersectsGeometry(right, bvh, otherGeometry, geometryToBvh, cachedObb);
15884
- if (rightIntersection) return true;
15885
- return false;
15886
- }
15887
- }
15888
- const tempMatrix = /* @__PURE__ */ new Matrix4();
15889
- const obb$1 = /* @__PURE__ */ new OrientedBox();
15890
- const obb2 = /* @__PURE__ */ new OrientedBox();
15891
- const temp1 = /* @__PURE__ */ new Vector3();
15892
- const temp2 = /* @__PURE__ */ new Vector3();
15893
- const temp3 = /* @__PURE__ */ new Vector3();
15894
- const temp4 = /* @__PURE__ */ new Vector3();
15895
- function closestPointToGeometry_indirect(bvh, otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
15896
- if (!otherGeometry.boundingBox) {
15897
- otherGeometry.computeBoundingBox();
15898
- }
15899
- obb$1.set(otherGeometry.boundingBox.min, otherGeometry.boundingBox.max, geometryToBvh);
15900
- obb$1.needsUpdate = true;
15901
- const geometry = bvh.geometry;
15902
- const pos = geometry.attributes.position;
15903
- const index = geometry.index;
15904
- const otherPos = otherGeometry.attributes.position;
15905
- const otherIndex = otherGeometry.index;
15906
- const triangle3 = ExtendedTrianglePool.getPrimitive();
15907
- const triangle22 = ExtendedTrianglePool.getPrimitive();
15908
- let tempTarget1 = temp1;
15909
- let tempTargetDest1 = temp2;
15910
- let tempTarget2 = null;
15911
- let tempTargetDest2 = null;
15912
- if (target2) {
15913
- tempTarget2 = temp3;
15914
- tempTargetDest2 = temp4;
15915
- }
15916
- let closestDistance = Infinity;
15917
- let closestDistanceTriIndex = null;
15918
- let closestDistanceOtherTriIndex = null;
15919
- tempMatrix.copy(geometryToBvh).invert();
15920
- obb2.matrix.copy(tempMatrix);
15921
- bvh.shapecast(
15922
- {
15923
- boundsTraverseOrder: (box2) => {
15924
- return obb$1.distanceToBox(box2);
15925
- },
15926
- intersectsBounds: (box2, isLeaf, score) => {
15927
- if (score < closestDistance && score < maxThreshold) {
15928
- if (isLeaf) {
15929
- obb2.min.copy(box2.min);
15930
- obb2.max.copy(box2.max);
15931
- obb2.needsUpdate = true;
15932
- }
15933
- return true;
15934
- }
15935
- return false;
15936
- },
15937
- intersectsRange: (offset, count) => {
15938
- if (otherGeometry.boundsTree) {
15939
- const otherBvh = otherGeometry.boundsTree;
15940
- return otherBvh.shapecast({
15941
- boundsTraverseOrder: (box2) => {
15942
- return obb2.distanceToBox(box2);
15943
- },
15944
- intersectsBounds: (box2, isLeaf, score) => {
15945
- return score < closestDistance && score < maxThreshold;
15946
- },
15947
- intersectsRange: (otherOffset, otherCount) => {
15948
- for (let i2 = otherOffset, l2 = otherOffset + otherCount; i2 < l2; i2++) {
15949
- const ti2 = otherBvh.resolveTriangleIndex(i2);
15950
- setTriangle(triangle22, 3 * ti2, otherIndex, otherPos);
15951
- triangle22.a.applyMatrix4(geometryToBvh);
15952
- triangle22.b.applyMatrix4(geometryToBvh);
15953
- triangle22.c.applyMatrix4(geometryToBvh);
15954
- triangle22.needsUpdate = true;
15955
- for (let i = offset, l3 = offset + count; i < l3; i++) {
15956
- const ti = bvh.resolveTriangleIndex(i);
15957
- setTriangle(triangle3, 3 * ti, index, pos);
15958
- triangle3.needsUpdate = true;
15959
- const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
15960
- if (dist < closestDistance) {
15961
- tempTargetDest1.copy(tempTarget1);
15962
- if (tempTargetDest2) {
15963
- tempTargetDest2.copy(tempTarget2);
15964
- }
15965
- closestDistance = dist;
15966
- closestDistanceTriIndex = i;
15967
- closestDistanceOtherTriIndex = i2;
15968
- }
15969
- if (dist < minThreshold) {
15970
- return true;
15971
- }
15972
- }
15973
- }
15974
- }
15975
- });
15976
- } else {
15977
- const triCount = getTriCount(otherGeometry);
15978
- for (let i2 = 0, l2 = triCount; i2 < l2; i2++) {
15979
- setTriangle(triangle22, 3 * i2, otherIndex, otherPos);
15980
- triangle22.a.applyMatrix4(geometryToBvh);
15981
- triangle22.b.applyMatrix4(geometryToBvh);
15982
- triangle22.c.applyMatrix4(geometryToBvh);
15983
- triangle22.needsUpdate = true;
15984
- for (let i = offset, l3 = offset + count; i < l3; i++) {
15985
- const ti = bvh.resolveTriangleIndex(i);
15986
- setTriangle(triangle3, 3 * ti, index, pos);
15987
- triangle3.needsUpdate = true;
15988
- const dist = triangle3.distanceToTriangle(triangle22, tempTarget1, tempTarget2);
15989
- if (dist < closestDistance) {
15990
- tempTargetDest1.copy(tempTarget1);
15991
- if (tempTargetDest2) {
15992
- tempTargetDest2.copy(tempTarget2);
15993
- }
15994
- closestDistance = dist;
15995
- closestDistanceTriIndex = i;
15996
- closestDistanceOtherTriIndex = i2;
15997
- }
15998
- if (dist < minThreshold) {
15999
- return true;
16000
- }
16001
- }
16002
- }
16003
- }
16004
- }
16005
- }
16006
- );
16007
- ExtendedTrianglePool.releasePrimitive(triangle3);
16008
- ExtendedTrianglePool.releasePrimitive(triangle22);
16009
- if (closestDistance === Infinity) {
16010
- return null;
16011
- }
16012
- if (!target1.point) {
16013
- target1.point = tempTargetDest1.clone();
16014
- } else {
16015
- target1.point.copy(tempTargetDest1);
16016
- }
16017
- target1.distance = closestDistance, target1.faceIndex = closestDistanceTriIndex;
16018
- if (target2) {
16019
- if (!target2.point) target2.point = tempTargetDest2.clone();
16020
- else target2.point.copy(tempTargetDest2);
16021
- target2.point.applyMatrix4(tempMatrix);
16022
- tempTargetDest1.applyMatrix4(tempMatrix);
16023
- target2.distance = tempTargetDest1.sub(target2.point).length();
16024
- target2.faceIndex = closestDistanceOtherTriIndex;
16025
- }
16026
- return target1;
16027
- }
16028
- function isSharedArrayBufferSupported() {
16029
- return typeof SharedArrayBuffer !== "undefined";
16030
- }
16031
- const _bufferStack1 = new BufferStack.constructor();
16032
- const _bufferStack2 = new BufferStack.constructor();
16033
- const _boxPool = new PrimitivePool(() => new Box3());
16034
- const _leftBox1 = new Box3();
16035
- const _rightBox1 = new Box3();
16036
- const _leftBox2 = new Box3();
16037
- const _rightBox2 = new Box3();
16038
- let _active = false;
16039
- function bvhcast(bvh, otherBvh, matrixToLocal, intersectsRanges) {
16040
- if (_active) {
16041
- throw new Error("MeshBVH: Recursive calls to bvhcast not supported.");
16042
- }
16043
- _active = true;
16044
- const roots = bvh._roots;
16045
- const otherRoots = otherBvh._roots;
16046
- let result;
16047
- let offset1 = 0;
16048
- let offset2 = 0;
16049
- const invMat = new Matrix4().copy(matrixToLocal).invert();
16050
- for (let i = 0, il = roots.length; i < il; i++) {
16051
- _bufferStack1.setBuffer(roots[i]);
16052
- offset2 = 0;
16053
- const localBox = _boxPool.getPrimitive();
16054
- arrayToBox(BOUNDING_DATA_INDEX(0), _bufferStack1.float32Array, localBox);
16055
- localBox.applyMatrix4(invMat);
16056
- for (let j2 = 0, jl = otherRoots.length; j2 < jl; j2++) {
16057
- _bufferStack2.setBuffer(otherRoots[j2]);
16058
- result = _traverse(
16059
- 0,
16060
- 0,
16061
- matrixToLocal,
16062
- invMat,
16063
- intersectsRanges,
16064
- offset1,
16065
- offset2,
16066
- 0,
16067
- 0,
16068
- localBox
16069
- );
16070
- _bufferStack2.clearBuffer();
16071
- offset2 += otherRoots[j2].length;
16072
- if (result) {
16073
- break;
16074
- }
16075
- }
16076
- _boxPool.releasePrimitive(localBox);
16077
- _bufferStack1.clearBuffer();
16078
- offset1 += roots[i].length;
16079
- if (result) {
16080
- break;
16081
- }
16082
- }
16083
- _active = false;
16084
- return result;
16085
- }
16086
- function _traverse(node1Index32, node2Index32, matrix2to1, matrix1to2, intersectsRangesFunc, node1IndexByteOffset = 0, node2IndexByteOffset = 0, depth1 = 0, depth2 = 0, currBox = null, reversed = false) {
16087
- let bufferStack1, bufferStack2;
16088
- if (reversed) {
16089
- bufferStack1 = _bufferStack2;
16090
- bufferStack2 = _bufferStack1;
16091
- } else {
16092
- bufferStack1 = _bufferStack1;
16093
- bufferStack2 = _bufferStack2;
16094
- }
16095
- const float32Array1 = bufferStack1.float32Array, uint32Array1 = bufferStack1.uint32Array, uint16Array1 = bufferStack1.uint16Array, float32Array2 = bufferStack2.float32Array, uint32Array2 = bufferStack2.uint32Array, uint16Array2 = bufferStack2.uint16Array;
16096
- const node1Index16 = node1Index32 * 2;
16097
- const node2Index16 = node2Index32 * 2;
16098
- const isLeaf1 = IS_LEAF(node1Index16, uint16Array1);
16099
- const isLeaf2 = IS_LEAF(node2Index16, uint16Array2);
16100
- let result = false;
16101
- if (isLeaf2 && isLeaf1) {
16102
- if (reversed) {
16103
- result = intersectsRangesFunc(
16104
- OFFSET(node2Index32, uint32Array2),
16105
- COUNT(node2Index32 * 2, uint16Array2),
16106
- OFFSET(node1Index32, uint32Array1),
16107
- COUNT(node1Index32 * 2, uint16Array1),
16108
- depth2,
16109
- node2IndexByteOffset + node2Index32,
16110
- depth1,
16111
- node1IndexByteOffset + node1Index32
16112
- );
16113
- } else {
16114
- result = intersectsRangesFunc(
16115
- OFFSET(node1Index32, uint32Array1),
16116
- COUNT(node1Index32 * 2, uint16Array1),
16117
- OFFSET(node2Index32, uint32Array2),
16118
- COUNT(node2Index32 * 2, uint16Array2),
16119
- depth1,
16120
- node1IndexByteOffset + node1Index32,
16121
- depth2,
16122
- node2IndexByteOffset + node2Index32
16123
- );
16124
- }
16125
- } else if (isLeaf2) {
16126
- const newBox = _boxPool.getPrimitive();
16127
- arrayToBox(BOUNDING_DATA_INDEX(node2Index32), float32Array2, newBox);
16128
- newBox.applyMatrix4(matrix2to1);
16129
- const cl1 = LEFT_NODE(node1Index32);
16130
- const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
16131
- arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
16132
- arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
16133
- const intersectCl1 = newBox.intersectsBox(_leftBox1);
16134
- const intersectCr1 = newBox.intersectsBox(_rightBox1);
16135
- result = intersectCl1 && _traverse(
16136
- node2Index32,
16137
- cl1,
16138
- matrix1to2,
16139
- matrix2to1,
16140
- intersectsRangesFunc,
16141
- node2IndexByteOffset,
16142
- node1IndexByteOffset,
16143
- depth2,
16144
- depth1 + 1,
16145
- newBox,
16146
- !reversed
16147
- ) || intersectCr1 && _traverse(
16148
- node2Index32,
16149
- cr1,
16150
- matrix1to2,
16151
- matrix2to1,
16152
- intersectsRangesFunc,
16153
- node2IndexByteOffset,
16154
- node1IndexByteOffset,
16155
- depth2,
16156
- depth1 + 1,
16157
- newBox,
16158
- !reversed
16159
- );
16160
- _boxPool.releasePrimitive(newBox);
16161
- } else {
16162
- const cl2 = LEFT_NODE(node2Index32);
16163
- const cr2 = RIGHT_NODE(node2Index32, uint32Array2);
16164
- arrayToBox(BOUNDING_DATA_INDEX(cl2), float32Array2, _leftBox2);
16165
- arrayToBox(BOUNDING_DATA_INDEX(cr2), float32Array2, _rightBox2);
16166
- const leftIntersects = currBox.intersectsBox(_leftBox2);
16167
- const rightIntersects = currBox.intersectsBox(_rightBox2);
16168
- if (leftIntersects && rightIntersects) {
16169
- result = _traverse(
16170
- node1Index32,
16171
- cl2,
16172
- matrix2to1,
16173
- matrix1to2,
16174
- intersectsRangesFunc,
16175
- node1IndexByteOffset,
16176
- node2IndexByteOffset,
16177
- depth1,
16178
- depth2 + 1,
16179
- currBox,
16180
- reversed
16181
- ) || _traverse(
16182
- node1Index32,
16183
- cr2,
16184
- matrix2to1,
16185
- matrix1to2,
16186
- intersectsRangesFunc,
16187
- node1IndexByteOffset,
16188
- node2IndexByteOffset,
16189
- depth1,
16190
- depth2 + 1,
16191
- currBox,
16192
- reversed
16193
- );
16194
- } else if (leftIntersects) {
16195
- if (isLeaf1) {
16196
- result = _traverse(
16197
- node1Index32,
16198
- cl2,
16199
- matrix2to1,
16200
- matrix1to2,
16201
- intersectsRangesFunc,
16202
- node1IndexByteOffset,
16203
- node2IndexByteOffset,
16204
- depth1,
16205
- depth2 + 1,
16206
- currBox,
16207
- reversed
16208
- );
16209
- } else {
16210
- const newBox = _boxPool.getPrimitive();
16211
- newBox.copy(_leftBox2).applyMatrix4(matrix2to1);
16212
- const cl1 = LEFT_NODE(node1Index32);
16213
- const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
16214
- arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
16215
- arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
16216
- const intersectCl1 = newBox.intersectsBox(_leftBox1);
16217
- const intersectCr1 = newBox.intersectsBox(_rightBox1);
16218
- result = intersectCl1 && _traverse(
16219
- cl2,
16220
- cl1,
16221
- matrix1to2,
16222
- matrix2to1,
16223
- intersectsRangesFunc,
16224
- node2IndexByteOffset,
16225
- node1IndexByteOffset,
16226
- depth2,
16227
- depth1 + 1,
16228
- newBox,
16229
- !reversed
16230
- ) || intersectCr1 && _traverse(
16231
- cl2,
16232
- cr1,
16233
- matrix1to2,
16234
- matrix2to1,
16235
- intersectsRangesFunc,
16236
- node2IndexByteOffset,
16237
- node1IndexByteOffset,
16238
- depth2,
16239
- depth1 + 1,
16240
- newBox,
16241
- !reversed
16242
- );
16243
- _boxPool.releasePrimitive(newBox);
16244
- }
16245
- } else if (rightIntersects) {
16246
- if (isLeaf1) {
16247
- result = _traverse(
16248
- node1Index32,
16249
- cr2,
16250
- matrix2to1,
16251
- matrix1to2,
16252
- intersectsRangesFunc,
16253
- node1IndexByteOffset,
16254
- node2IndexByteOffset,
16255
- depth1,
16256
- depth2 + 1,
16257
- currBox,
16258
- reversed
16259
- );
16260
- } else {
16261
- const newBox = _boxPool.getPrimitive();
16262
- newBox.copy(_rightBox2).applyMatrix4(matrix2to1);
16263
- const cl1 = LEFT_NODE(node1Index32);
16264
- const cr1 = RIGHT_NODE(node1Index32, uint32Array1);
16265
- arrayToBox(BOUNDING_DATA_INDEX(cl1), float32Array1, _leftBox1);
16266
- arrayToBox(BOUNDING_DATA_INDEX(cr1), float32Array1, _rightBox1);
16267
- const intersectCl1 = newBox.intersectsBox(_leftBox1);
16268
- const intersectCr1 = newBox.intersectsBox(_rightBox1);
16269
- result = intersectCl1 && _traverse(
16270
- cr2,
16271
- cl1,
16272
- matrix1to2,
16273
- matrix2to1,
16274
- intersectsRangesFunc,
16275
- node2IndexByteOffset,
16276
- node1IndexByteOffset,
16277
- depth2,
16278
- depth1 + 1,
16279
- newBox,
16280
- !reversed
16281
- ) || intersectCr1 && _traverse(
16282
- cr2,
16283
- cr1,
16284
- matrix1to2,
16285
- matrix2to1,
16286
- intersectsRangesFunc,
16287
- node2IndexByteOffset,
16288
- node1IndexByteOffset,
16289
- depth2,
16290
- depth1 + 1,
16291
- newBox,
16292
- !reversed
16293
- );
16294
- _boxPool.releasePrimitive(newBox);
16295
- }
16296
- }
16297
- }
16298
- return result;
16299
- }
16300
- const obb = /* @__PURE__ */ new OrientedBox();
16301
- const tempBox = /* @__PURE__ */ new Box3();
16302
- const DEFAULT_OPTIONS = {
16303
- strategy: CENTER,
16304
- maxDepth: 40,
16305
- maxLeafTris: 10,
16306
- useSharedArrayBuffer: false,
16307
- setBoundingBox: true,
16308
- onProgress: null,
16309
- indirect: false,
16310
- verbose: true,
16311
- range: null
16312
- };
16313
- class MeshBVH {
16314
- static serialize(bvh, options = {}) {
16315
- options = {
16316
- cloneBuffers: true,
16317
- ...options
16318
- };
16319
- const geometry = bvh.geometry;
16320
- const rootData = bvh._roots;
16321
- const indirectBuffer = bvh._indirectBuffer;
16322
- const indexAttribute = geometry.getIndex();
16323
- let result;
16324
- if (options.cloneBuffers) {
16325
- result = {
16326
- roots: rootData.map((root) => root.slice()),
16327
- index: indexAttribute ? indexAttribute.array.slice() : null,
16328
- indirectBuffer: indirectBuffer ? indirectBuffer.slice() : null
16329
- };
16330
- } else {
16331
- result = {
16332
- roots: rootData,
16333
- index: indexAttribute ? indexAttribute.array : null,
16334
- indirectBuffer
16335
- };
16336
- }
16337
- return result;
16338
- }
16339
- static deserialize(data, geometry, options = {}) {
16340
- options = {
16341
- setIndex: true,
16342
- indirect: Boolean(data.indirectBuffer),
16343
- ...options
16344
- };
16345
- const { index, roots, indirectBuffer } = data;
16346
- const bvh = new MeshBVH(geometry, { ...options, [SKIP_GENERATION]: true });
16347
- bvh._roots = roots;
16348
- bvh._indirectBuffer = indirectBuffer || null;
16349
- if (options.setIndex) {
16350
- const indexAttribute = geometry.getIndex();
16351
- if (indexAttribute === null) {
16352
- const newIndex = new BufferAttribute(data.index, 1, false);
16353
- geometry.setIndex(newIndex);
16354
- } else if (indexAttribute.array !== index) {
16355
- indexAttribute.array.set(index);
16356
- indexAttribute.needsUpdate = true;
16357
- }
16358
- }
16359
- return bvh;
16360
- }
16361
- get indirect() {
16362
- return !!this._indirectBuffer;
16363
- }
16364
- constructor(geometry, options = {}) {
16365
- if (!geometry.isBufferGeometry) {
16366
- throw new Error("MeshBVH: Only BufferGeometries are supported.");
16367
- } else if (geometry.index && geometry.index.isInterleavedBufferAttribute) {
16368
- throw new Error("MeshBVH: InterleavedBufferAttribute is not supported for the index attribute.");
16369
- }
16370
- options = Object.assign({
16371
- ...DEFAULT_OPTIONS,
16372
- // undocumented options
16373
- // Whether to skip generating the tree. Used for deserialization.
16374
- [SKIP_GENERATION]: false
16375
- }, options);
16376
- if (options.useSharedArrayBuffer && !isSharedArrayBufferSupported()) {
16377
- throw new Error("MeshBVH: SharedArrayBuffer is not available.");
16378
- }
16379
- this.geometry = geometry;
16380
- this._roots = null;
16381
- this._indirectBuffer = null;
16382
- if (!options[SKIP_GENERATION]) {
16383
- buildPackedTree(this, options);
16384
- if (!geometry.boundingBox && options.setBoundingBox) {
16385
- geometry.boundingBox = this.getBoundingBox(new Box3());
16386
- }
16387
- }
16388
- this.resolveTriangleIndex = options.indirect ? (i) => this._indirectBuffer[i] : (i) => i;
16389
- }
16390
- refit(nodeIndices = null) {
16391
- const refitFunc = this.indirect ? refit_indirect : refit;
16392
- return refitFunc(this, nodeIndices);
16393
- }
16394
- traverse(callback, rootIndex = 0) {
16395
- const buffer = this._roots[rootIndex];
16396
- const uint32Array2 = new Uint32Array(buffer);
16397
- const uint16Array2 = new Uint16Array(buffer);
16398
- _traverse2(0);
16399
- function _traverse2(node32Index, depth = 0) {
16400
- const node16Index = node32Index * 2;
16401
- const isLeaf = uint16Array2[node16Index + 15] === IS_LEAFNODE_FLAG;
16402
- if (isLeaf) {
16403
- const offset = uint32Array2[node32Index + 6];
16404
- const count = uint16Array2[node16Index + 14];
16405
- callback(depth, isLeaf, new Float32Array(buffer, node32Index * 4, 6), offset, count);
16406
- } else {
16407
- const left = node32Index + BYTES_PER_NODE / 4;
16408
- const right = uint32Array2[node32Index + 6];
16409
- const splitAxis = uint32Array2[node32Index + 7];
16410
- const stopTraversal = callback(depth, isLeaf, new Float32Array(buffer, node32Index * 4, 6), splitAxis);
16411
- if (!stopTraversal) {
16412
- _traverse2(left, depth + 1);
16413
- _traverse2(right, depth + 1);
16414
- }
16415
- }
16416
- }
16417
- }
16418
- /* Core Cast Functions */
16419
- raycast(ray2, materialOrSide = FrontSide, near = 0, far = Infinity) {
16420
- const roots = this._roots;
16421
- const geometry = this.geometry;
16422
- const intersects = [];
16423
- const isMaterial = materialOrSide.isMaterial;
16424
- const isArrayMaterial = Array.isArray(materialOrSide);
16425
- const groups = geometry.groups;
16426
- const side = isMaterial ? materialOrSide.side : materialOrSide;
16427
- const raycastFunc = this.indirect ? raycast_indirect : raycast;
16428
- for (let i = 0, l2 = roots.length; i < l2; i++) {
16429
- const materialSide = isArrayMaterial ? materialOrSide[groups[i].materialIndex].side : side;
16430
- const startCount = intersects.length;
16431
- raycastFunc(this, i, materialSide, ray2, intersects, near, far);
16432
- if (isArrayMaterial) {
16433
- const materialIndex = groups[i].materialIndex;
16434
- for (let j2 = startCount, jl = intersects.length; j2 < jl; j2++) {
16435
- intersects[j2].face.materialIndex = materialIndex;
16436
- }
16437
- }
16438
- }
16439
- return intersects;
16440
- }
16441
- raycastFirst(ray2, materialOrSide = FrontSide, near = 0, far = Infinity) {
16442
- const roots = this._roots;
16443
- const geometry = this.geometry;
16444
- const isMaterial = materialOrSide.isMaterial;
16445
- const isArrayMaterial = Array.isArray(materialOrSide);
16446
- let closestResult = null;
16447
- const groups = geometry.groups;
16448
- const side = isMaterial ? materialOrSide.side : materialOrSide;
16449
- const raycastFirstFunc = this.indirect ? raycastFirst_indirect : raycastFirst;
16450
- for (let i = 0, l2 = roots.length; i < l2; i++) {
16451
- const materialSide = isArrayMaterial ? materialOrSide[groups[i].materialIndex].side : side;
16452
- const result = raycastFirstFunc(this, i, materialSide, ray2, near, far);
16453
- if (result != null && (closestResult == null || result.distance < closestResult.distance)) {
16454
- closestResult = result;
16455
- if (isArrayMaterial) {
16456
- result.face.materialIndex = groups[i].materialIndex;
16457
- }
16458
- }
16459
- }
16460
- return closestResult;
16461
- }
16462
- intersectsGeometry(otherGeometry, geomToMesh) {
16463
- let result = false;
16464
- const roots = this._roots;
16465
- const intersectsGeometryFunc = this.indirect ? intersectsGeometry_indirect : intersectsGeometry;
16466
- for (let i = 0, l2 = roots.length; i < l2; i++) {
16467
- result = intersectsGeometryFunc(this, i, otherGeometry, geomToMesh);
16468
- if (result) {
16469
- break;
16470
- }
16471
- }
16472
- return result;
16473
- }
16474
- shapecast(callbacks) {
16475
- const triangle3 = ExtendedTrianglePool.getPrimitive();
16476
- const iterateFunc = this.indirect ? iterateOverTriangles_indirect : iterateOverTriangles;
16477
- let {
16478
- boundsTraverseOrder,
16479
- intersectsBounds,
16480
- intersectsRange,
16481
- intersectsTriangle
16482
- } = callbacks;
16483
- if (intersectsRange && intersectsTriangle) {
16484
- const originalIntersectsRange = intersectsRange;
16485
- intersectsRange = (offset, count, contained, depth, nodeIndex) => {
16486
- if (!originalIntersectsRange(offset, count, contained, depth, nodeIndex)) {
16487
- return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle3);
16488
- }
16489
- return true;
16490
- };
16491
- } else if (!intersectsRange) {
16492
- if (intersectsTriangle) {
16493
- intersectsRange = (offset, count, contained, depth) => {
16494
- return iterateFunc(offset, count, this, intersectsTriangle, contained, depth, triangle3);
16495
- };
16496
- } else {
16497
- intersectsRange = (offset, count, contained) => {
16498
- return contained;
16499
- };
16500
- }
16501
- }
16502
- let result = false;
16503
- let byteOffset = 0;
16504
- const roots = this._roots;
16505
- for (let i = 0, l2 = roots.length; i < l2; i++) {
16506
- const root = roots[i];
16507
- result = shapecast(this, i, intersectsBounds, intersectsRange, boundsTraverseOrder, byteOffset);
16508
- if (result) {
16509
- break;
16510
- }
16511
- byteOffset += root.byteLength;
16512
- }
16513
- ExtendedTrianglePool.releasePrimitive(triangle3);
16514
- return result;
16515
- }
16516
- bvhcast(otherBvh, matrixToLocal, callbacks) {
16517
- let {
16518
- intersectsRanges,
16519
- intersectsTriangles
16520
- } = callbacks;
16521
- const triangle1 = ExtendedTrianglePool.getPrimitive();
16522
- const indexAttr1 = this.geometry.index;
16523
- const positionAttr1 = this.geometry.attributes.position;
16524
- const assignTriangle1 = this.indirect ? (i1) => {
16525
- const ti = this.resolveTriangleIndex(i1);
16526
- setTriangle(triangle1, ti * 3, indexAttr1, positionAttr1);
16527
- } : (i1) => {
16528
- setTriangle(triangle1, i1 * 3, indexAttr1, positionAttr1);
16529
- };
16530
- const triangle22 = ExtendedTrianglePool.getPrimitive();
16531
- const indexAttr2 = otherBvh.geometry.index;
16532
- const positionAttr2 = otherBvh.geometry.attributes.position;
16533
- const assignTriangle2 = otherBvh.indirect ? (i2) => {
16534
- const ti2 = otherBvh.resolveTriangleIndex(i2);
16535
- setTriangle(triangle22, ti2 * 3, indexAttr2, positionAttr2);
16536
- } : (i2) => {
16537
- setTriangle(triangle22, i2 * 3, indexAttr2, positionAttr2);
16538
- };
16539
- if (intersectsTriangles) {
16540
- const iterateOverDoubleTriangles = (offset1, count1, offset2, count2, depth1, index1, depth2, index2) => {
16541
- for (let i2 = offset2, l2 = offset2 + count2; i2 < l2; i2++) {
16542
- assignTriangle2(i2);
16543
- triangle22.a.applyMatrix4(matrixToLocal);
16544
- triangle22.b.applyMatrix4(matrixToLocal);
16545
- triangle22.c.applyMatrix4(matrixToLocal);
16546
- triangle22.needsUpdate = true;
16547
- for (let i1 = offset1, l1 = offset1 + count1; i1 < l1; i1++) {
16548
- assignTriangle1(i1);
16549
- triangle1.needsUpdate = true;
16550
- if (intersectsTriangles(triangle1, triangle22, i1, i2, depth1, index1, depth2, index2)) {
16551
- return true;
16552
- }
16553
- }
16554
- }
16555
- return false;
16556
- };
16557
- if (intersectsRanges) {
16558
- const originalIntersectsRanges = intersectsRanges;
16559
- intersectsRanges = function(offset1, count1, offset2, count2, depth1, index1, depth2, index2) {
16560
- if (!originalIntersectsRanges(offset1, count1, offset2, count2, depth1, index1, depth2, index2)) {
16561
- return iterateOverDoubleTriangles(offset1, count1, offset2, count2, depth1, index1, depth2, index2);
16562
- }
16563
- return true;
16564
- };
16565
- } else {
16566
- intersectsRanges = iterateOverDoubleTriangles;
16567
- }
16568
- }
16569
- return bvhcast(this, otherBvh, matrixToLocal, intersectsRanges);
16570
- }
16571
- /* Derived Cast Functions */
16572
- intersectsBox(box2, boxToMesh) {
16573
- obb.set(box2.min, box2.max, boxToMesh);
16574
- obb.needsUpdate = true;
16575
- return this.shapecast(
16576
- {
16577
- intersectsBounds: (box3) => obb.intersectsBox(box3),
16578
- intersectsTriangle: (tri) => obb.intersectsTriangle(tri)
16579
- }
16580
- );
16581
- }
16582
- intersectsSphere(sphere) {
16583
- return this.shapecast(
16584
- {
16585
- intersectsBounds: (box2) => sphere.intersectsBox(box2),
16586
- intersectsTriangle: (tri) => tri.intersectsSphere(sphere)
16587
- }
16588
- );
16589
- }
16590
- closestPointToGeometry(otherGeometry, geometryToBvh, target1 = {}, target2 = {}, minThreshold = 0, maxThreshold = Infinity) {
16591
- const closestPointToGeometryFunc = this.indirect ? closestPointToGeometry_indirect : closestPointToGeometry;
16592
- return closestPointToGeometryFunc(
16593
- this,
16594
- otherGeometry,
16595
- geometryToBvh,
16596
- target1,
16597
- target2,
16598
- minThreshold,
16599
- maxThreshold
16600
- );
16601
- }
16602
- closestPointToPoint(point, target = {}, minThreshold = 0, maxThreshold = Infinity) {
16603
- return closestPointToPoint(
16604
- this,
16605
- point,
16606
- target,
16607
- minThreshold,
16608
- maxThreshold
16609
- );
16610
- }
16611
- getBoundingBox(target) {
16612
- target.makeEmpty();
16613
- const roots = this._roots;
16614
- roots.forEach((buffer) => {
16615
- arrayToBox(0, new Float32Array(buffer), tempBox);
16616
- target.union(tempBox);
16617
- });
16618
- return target;
16619
- }
16620
- }
16621
- function convertRaycastIntersect(hit, object, raycaster) {
16622
- if (hit === null) {
16623
- return null;
16624
- }
16625
- hit.point.applyMatrix4(object.matrixWorld);
16626
- hit.distance = hit.point.distanceTo(raycaster.ray.origin);
16627
- hit.object = object;
16628
- return hit;
16629
- }
16630
- const ray = /* @__PURE__ */ new Ray();
16631
- const direction = /* @__PURE__ */ new Vector3();
16632
- const tmpInverseMatrix = /* @__PURE__ */ new Matrix4();
16633
- const origMeshRaycastFunc = Mesh.prototype.raycast;
16634
- const origBatchedRaycastFunc = BatchedMesh.prototype.raycast;
16635
- const _worldScale = /* @__PURE__ */ new Vector3();
16636
- const _mesh = /* @__PURE__ */ new Mesh();
16637
- const _batchIntersects = [];
16638
- function acceleratedRaycast(raycaster, intersects) {
16639
- if (this.isBatchedMesh) {
16640
- acceleratedBatchedMeshRaycast.call(this, raycaster, intersects);
16641
- } else {
16642
- acceleratedMeshRaycast.call(this, raycaster, intersects);
16643
- }
16644
- }
16645
- function acceleratedBatchedMeshRaycast(raycaster, intersects) {
16646
- if (this.boundsTrees) {
16647
- const boundsTrees = this.boundsTrees;
16648
- const drawInfo = this._drawInfo || this._instanceInfo;
16649
- const drawRanges = this._drawRanges || this._geometryInfo;
16650
- const matrixWorld = this.matrixWorld;
16651
- _mesh.material = this.material;
16652
- _mesh.geometry = this.geometry;
16653
- const oldBoundsTree = _mesh.geometry.boundsTree;
16654
- const oldDrawRange = _mesh.geometry.drawRange;
16655
- if (_mesh.geometry.boundingSphere === null) {
16656
- _mesh.geometry.boundingSphere = new Sphere();
16657
- }
16658
- for (let i = 0, l2 = drawInfo.length; i < l2; i++) {
16659
- if (!this.getVisibleAt(i)) {
16660
- continue;
16661
- }
16662
- const geometryId = drawInfo[i].geometryIndex;
16663
- _mesh.geometry.boundsTree = boundsTrees[geometryId];
16664
- this.getMatrixAt(i, _mesh.matrixWorld).premultiply(matrixWorld);
16665
- if (!_mesh.geometry.boundsTree) {
16666
- this.getBoundingBoxAt(geometryId, _mesh.geometry.boundingBox);
16667
- this.getBoundingSphereAt(geometryId, _mesh.geometry.boundingSphere);
16668
- const drawRange = drawRanges[geometryId];
16669
- _mesh.geometry.setDrawRange(drawRange.start, drawRange.count);
16670
- }
16671
- _mesh.raycast(raycaster, _batchIntersects);
16672
- for (let j2 = 0, l3 = _batchIntersects.length; j2 < l3; j2++) {
16673
- const intersect = _batchIntersects[j2];
16674
- intersect.object = this;
16675
- intersect.batchId = i;
16676
- intersects.push(intersect);
16677
- }
16678
- _batchIntersects.length = 0;
16679
- }
16680
- _mesh.geometry.boundsTree = oldBoundsTree;
16681
- _mesh.geometry.drawRange = oldDrawRange;
16682
- _mesh.material = null;
16683
- _mesh.geometry = null;
16684
- } else {
16685
- origBatchedRaycastFunc.call(this, raycaster, intersects);
16686
- }
16687
- }
16688
- function acceleratedMeshRaycast(raycaster, intersects) {
16689
- if (this.geometry.boundsTree) {
16690
- if (this.material === void 0) return;
16691
- tmpInverseMatrix.copy(this.matrixWorld).invert();
16692
- ray.copy(raycaster.ray).applyMatrix4(tmpInverseMatrix);
16693
- _worldScale.setFromMatrixScale(this.matrixWorld);
16694
- direction.copy(ray.direction).multiply(_worldScale);
16695
- const scaleFactor = direction.length();
16696
- const near = raycaster.near / scaleFactor;
16697
- const far = raycaster.far / scaleFactor;
16698
- const bvh = this.geometry.boundsTree;
16699
- if (raycaster.firstHitOnly === true) {
16700
- const hit = convertRaycastIntersect(bvh.raycastFirst(ray, this.material, near, far), this, raycaster);
16701
- if (hit) {
16702
- intersects.push(hit);
16703
- }
16704
- } else {
16705
- const hits = bvh.raycast(ray, this.material, near, far);
16706
- for (let i = 0, l2 = hits.length; i < l2; i++) {
16707
- const hit = convertRaycastIntersect(hits[i], this, raycaster);
16708
- if (hit) {
16709
- intersects.push(hit);
16710
- }
16711
- }
16712
- }
16713
- } else {
16714
- origMeshRaycastFunc.call(this, raycaster, intersects);
16715
- }
16716
- }
16717
13394
  const getBufferForType = (type, width, height) => {
16718
13395
  let out;
16719
13396
  switch (type) {
@@ -19042,7 +15719,7 @@ const movePath = (value, from, to) => {
19042
15719
  if (value.startsWith(`${from}/`)) return `${to}${value.slice(from.length)}`;
19043
15720
  return value;
19044
15721
  };
19045
- const FORGE_IMPORT_RE = /\b(?:importMesh|importStep|importSvgSketch|Import\.mesh|Import\.step|Import\.svgSketch|Import\.dxfSketch|compareWith)\s*\(\s*(?:"([^"]+)"|'([^']+)')/g;
15722
+ const FORGE_IMPORT_RE = /\b(?:importMesh|importStep|importSvgSketch|Import\.mesh|Import\.step|Import\.image|Import\.svgSketch|Import\.dxfSketch|compareWith)\s*\(\s*(?:"([^"]+)"|'([^']+)')/g;
19046
15723
  const REQUIRE_RE = /\brequire\s*\(\s*(?:"([^"]+)"|'([^']+)')/g;
19047
15724
  const ES_IMPORT_RE = /\bfrom\s+(?:"([^"]+)"|'([^']+)')/g;
19048
15725
  const VIRTUAL_MODULES = /* @__PURE__ */ new Set(["forgecad", "@forge/runtime", "@forgecad/runtime"]);
@@ -19062,6 +15739,7 @@ function extractImports(code) {
19062
15739
  importSvgSketch: "forgeSvg",
19063
15740
  "Import.mesh": "forgeMesh",
19064
15741
  "Import.step": "forgeMesh",
15742
+ "Import.image": "forgeMesh",
19065
15743
  "Import.svgSketch": "forgeSvg",
19066
15744
  "Import.dxfSketch": "forgeDxf",
19067
15745
  compareWith: "compareWith"
@@ -19071,7 +15749,7 @@ function extractImports(code) {
19071
15749
  while ((m2 = forgeRe.exec(code)) !== null) {
19072
15750
  const path = m2[1] ?? m2[2];
19073
15751
  const fn = (_a3 = m2[0].match(
19074
- /\b(importMesh|importStep|importSvgSketch|Import\.mesh|Import\.step|Import\.svgSketch|Import\.dxfSketch|compareWith)/
15752
+ /\b(importMesh|importStep|importSvgSketch|Import\.mesh|Import\.step|Import\.image|Import\.svgSketch|Import\.dxfSketch|compareWith)/
19075
15753
  )) == null ? void 0 : _a3[1];
19076
15754
  add(path, kindMap[fn] ?? "forgeMesh");
19077
15755
  }
@@ -19298,7 +15976,7 @@ const CRASH_COOLDOWN_MS = 2e3;
19298
15976
  class EvalWorkerClient {
19299
15977
  constructor(workerFactory = () => new Worker(new URL(
19300
15978
  /* @vite-ignore */
19301
- "/assets/evalWorker-CS63PfZu.js",
15979
+ "/assets/evalWorker-BssDYW9u.js",
19302
15980
  import.meta.url
19303
15981
  ), { type: "module" })) {
19304
15982
  __publicField(this, "worker", null);
@@ -20769,133 +17447,37 @@ function buildRunState(previewFile, runResult, state2) {
20769
17447
  nextObjectSettingsByFile
20770
17448
  };
20771
17449
  }
20772
- function computeBackendFromParts(activeBackend, computeTarget) {
20773
- return computeTarget === "server" ? "server-occt" : activeBackend;
17450
+ const KERNELS = [
17451
+ { id: "manifold", name: "manifold", location: "local", label: "Manifold" },
17452
+ { id: "occt", name: "occt", location: "local", label: "OCCT" },
17453
+ { id: "truck", name: "truck", location: "local", label: "Truck" },
17454
+ { id: "sdf", name: "sdf", location: "local", label: "SDF" },
17455
+ { id: "server-occt", name: "occt", location: "server", label: "Server OCCT" }
17456
+ ];
17457
+ function availableKernels(canUseServer) {
17458
+ return KERNELS.filter((kernel) => kernel.location === "local" || canUseServer);
17459
+ }
17460
+ function kernelId(kernel) {
17461
+ return kernel.location === "server" ? "server-occt" : kernel.name;
20774
17462
  }
20775
- function computeBackendParts(backend) {
20776
- return backend === "server-occt" ? { activeBackend: "occt", computeTarget: "server" } : { activeBackend: backend, computeTarget: "local" };
17463
+ function kernelFromId(id) {
17464
+ const kernel = KERNELS.find((entry) => entry.id === id);
17465
+ if (!kernel) throw new Error(`Unknown kernel: ${id}`);
17466
+ return kernel;
17467
+ }
17468
+ function resolveAvailableKernel(preferred, kernels) {
17469
+ if (kernels.length === 0) throw new Error("No kernels are available");
17470
+ const exact = kernels.find((kernel) => kernel.name === preferred.name && kernel.location === preferred.location);
17471
+ if (exact) return exact;
17472
+ return kernels.find((kernel) => kernel.name === "manifold" && kernel.location === "local") ?? kernels[0];
17473
+ }
17474
+ function computeBackendFromParts(activeBackend, computeTarget) {
17475
+ return kernelId({ name: activeBackend, location: computeTarget });
20777
17476
  }
20778
17477
  function formatComputeBackendLabel(backend) {
20779
- switch (backend) {
20780
- case "manifold":
20781
- return "Local Manifold";
20782
- case "occt":
20783
- return "Local OCCT";
20784
- case "truck":
20785
- return "Local Truck";
20786
- case "sdf":
20787
- return "Local SDF";
20788
- case "server-occt":
20789
- return "Server OCCT";
20790
- }
20791
- }
20792
- const VIEW_PREFERENCES_KEY = "fc-view-preferences-v1";
20793
- const INSPECT_POINT_SAMPLE_COUNT_MIN = 100;
20794
- const INSPECT_POINT_SAMPLE_COUNT_MAX = 2e4;
20795
- const DEFAULT_INSPECT_POINT_SAMPLE_COUNT = 15e3;
20796
- const DEFAULT_COMPARISON_INSPECT_MODE = "difference-only";
20797
- const DEFAULT_COMPARISON_CANDIDATE_OPACITY = 0.42;
20798
- const DEFAULT_COMPARISON_REFERENCE_OPACITY = 0.2;
20799
- const THICKNESS_COLOR_RANGE_MIN = 0;
20800
- const THICKNESS_COLOR_RANGE_MAX = 1e3;
20801
- const THICKNESS_COLOR_RANGE_MIN_SPAN = 1e-3;
20802
- const DEFAULT_THICKNESS_COLOR_RANGE = {
20803
- min: 0,
20804
- max: 6
20805
- };
20806
- const DEFAULT_INSPECT_ISOLINES_ENABLED = false;
20807
- const DEFAULT_INSPECT_ISOLINE_SPACING = 1;
20808
- const DEFAULT_INSPECT_CRITICAL_LINE_ENABLED = true;
20809
- const DEFAULT_MANUAL_SCENE_SETTINGS = {
20810
- enabled: false,
20811
- backgroundColor: "#f6f7f8",
20812
- groundVisible: true,
20813
- groundColor: "#eef0f2",
20814
- ambientIntensity: 0.3,
20815
- keyIntensity: 1.45,
20816
- fillIntensity: 0.55,
20817
- rimIntensity: 0.2,
20818
- environmentIntensity: 0.9
20819
- };
20820
- const resolveInspectPointSampleCount = (value) => {
20821
- const numeric = typeof value === "number" ? value : Number(value);
20822
- if (!Number.isFinite(numeric)) return DEFAULT_INSPECT_POINT_SAMPLE_COUNT;
20823
- return Math.max(INSPECT_POINT_SAMPLE_COUNT_MIN, Math.min(INSPECT_POINT_SAMPLE_COUNT_MAX, Math.round(numeric)));
20824
- };
20825
- const resolveComparisonInspectMode = (value) => value === "difference-only" ? value : DEFAULT_COMPARISON_INSPECT_MODE;
20826
- const resolveCameraControlMode = (value) => value === "fly" ? value : "orbit";
20827
- const HEX_COLOR_RE = /^#[0-9a-f]{6}$/i;
20828
- const resolveHexColor = (value, fallback) => {
20829
- return typeof value === "string" && HEX_COLOR_RE.test(value) ? value : fallback;
20830
- };
20831
- const resolveClampedNumber = (value, fallback, min, max2) => {
20832
- const numeric = typeof value === "number" ? value : Number(value);
20833
- if (!Number.isFinite(numeric)) return fallback;
20834
- return Math.max(min, Math.min(max2, numeric));
20835
- };
20836
- const resolveComparisonOpacity = (value, fallback) => resolveClampedNumber(value, fallback, 0, 1);
20837
- const resolveThicknessColorRange = (value) => {
20838
- if (!value || typeof value !== "object" || Array.isArray(value)) {
20839
- return DEFAULT_THICKNESS_COLOR_RANGE;
20840
- }
20841
- const raw = value;
20842
- const min = resolveClampedNumber(raw.min, DEFAULT_THICKNESS_COLOR_RANGE.min, THICKNESS_COLOR_RANGE_MIN, THICKNESS_COLOR_RANGE_MAX);
20843
- const max2 = resolveClampedNumber(raw.max, DEFAULT_THICKNESS_COLOR_RANGE.max, THICKNESS_COLOR_RANGE_MIN, THICKNESS_COLOR_RANGE_MAX);
20844
- if (max2 - min >= THICKNESS_COLOR_RANGE_MIN_SPAN) return { min, max: max2 };
20845
- const defaultSpan = DEFAULT_THICKNESS_COLOR_RANGE.max - DEFAULT_THICKNESS_COLOR_RANGE.min;
20846
- const expandedMax = Math.min(THICKNESS_COLOR_RANGE_MAX, min + defaultSpan);
20847
- if (expandedMax - min >= THICKNESS_COLOR_RANGE_MIN_SPAN) return { min, max: expandedMax };
20848
- const expandedMin = Math.max(THICKNESS_COLOR_RANGE_MIN, max2 - defaultSpan);
20849
- if (max2 - expandedMin >= THICKNESS_COLOR_RANGE_MIN_SPAN) return { min: expandedMin, max: max2 };
20850
- return DEFAULT_THICKNESS_COLOR_RANGE;
20851
- };
20852
- const resolveInspectColormap = (value) => resolveColormapName(value);
20853
- const resolveBooleanPref = (value, fallback) => typeof value === "boolean" ? value : fallback;
20854
- const resolveInspectIsolineSpacing = (value) => {
20855
- const numeric = typeof value === "number" ? value : Number(value);
20856
- if (!Number.isFinite(numeric) || numeric <= 0) return DEFAULT_INSPECT_ISOLINE_SPACING;
20857
- return numeric;
20858
- };
20859
- const resolveManualSceneSettings = (value) => {
20860
- if (!value || typeof value !== "object" || Array.isArray(value)) {
20861
- return DEFAULT_MANUAL_SCENE_SETTINGS;
20862
- }
20863
- const raw = value;
20864
- return {
20865
- enabled: typeof raw.enabled === "boolean" ? raw.enabled : DEFAULT_MANUAL_SCENE_SETTINGS.enabled,
20866
- backgroundColor: resolveHexColor(raw.backgroundColor, DEFAULT_MANUAL_SCENE_SETTINGS.backgroundColor),
20867
- groundVisible: typeof raw.groundVisible === "boolean" ? raw.groundVisible : DEFAULT_MANUAL_SCENE_SETTINGS.groundVisible,
20868
- groundColor: resolveHexColor(raw.groundColor, DEFAULT_MANUAL_SCENE_SETTINGS.groundColor),
20869
- ambientIntensity: resolveClampedNumber(raw.ambientIntensity, DEFAULT_MANUAL_SCENE_SETTINGS.ambientIntensity, 0, 3),
20870
- keyIntensity: resolveClampedNumber(raw.keyIntensity, DEFAULT_MANUAL_SCENE_SETTINGS.keyIntensity, 0, 5),
20871
- fillIntensity: resolveClampedNumber(raw.fillIntensity, DEFAULT_MANUAL_SCENE_SETTINGS.fillIntensity, 0, 3),
20872
- rimIntensity: resolveClampedNumber(raw.rimIntensity, DEFAULT_MANUAL_SCENE_SETTINGS.rimIntensity, 0, 3),
20873
- environmentIntensity: resolveClampedNumber(raw.environmentIntensity, DEFAULT_MANUAL_SCENE_SETTINGS.environmentIntensity, 0, 3)
20874
- };
20875
- };
20876
- const readViewPreferences = () => {
20877
- if (typeof window === "undefined") return {};
20878
- try {
20879
- const raw = localStorage.getItem(VIEW_PREFERENCES_KEY);
20880
- if (!raw) return {};
20881
- const parsed = JSON.parse(raw);
20882
- if (!parsed || typeof parsed !== "object") return {};
20883
- return parsed;
20884
- } catch {
20885
- return {};
20886
- }
20887
- };
20888
- const writeViewPreferences = (patch) => {
20889
- if (typeof window === "undefined") return;
20890
- try {
20891
- const next = { ...readViewPreferences(), ...patch };
20892
- if ("objectSettingsByFile" in patch) {
20893
- delete next.objectSettings;
20894
- }
20895
- localStorage.setItem(VIEW_PREFERENCES_KEY, JSON.stringify(next));
20896
- } catch {
20897
- }
20898
- };
17478
+ const kernel = kernelFromId(backend);
17479
+ return kernel.location === "server" ? kernel.label : `Local ${kernel.label}`;
17480
+ }
20899
17481
  function computeServerSnapshot(state2, serverFiles, serverFolders, sharedModel2, sharedBundle2, initialFile) {
20900
17482
  const nextState = computeServerSnapshot$1(state2, serverFiles, serverFolders, sharedModel2, sharedBundle2, STARTUP_HASH_FILE, initialFile);
20901
17483
  writeViewPreferences({ objectSettingsByFile: nextState.objectSettingsByFile });
@@ -21095,6 +17677,14 @@ function recordViewCommandDebug(command) {
21095
17677
  console.debug("[forgecad view-command]", entry);
21096
17678
  }
21097
17679
  const initialViewPreferences = readViewPreferences();
17680
+ function resolveInitialKernel() {
17681
+ const savedLocation = initialViewPreferences.computeTarget === "server" ? "server" : "local";
17682
+ return resolveAvailableKernel(
17683
+ { name: initialViewPreferences.activeBackend, location: savedLocation },
17684
+ availableKernels(canUseServerCompute())
17685
+ );
17686
+ }
17687
+ const initialKernel = resolveInitialKernel();
21098
17688
  const initialInspectChannel = resolveInitialViewInspectChannel(initialViewPreferences.inspectChannel);
21099
17689
  const initialInspectDisplayMode = resolveInspectDisplayMode(initialViewPreferences.inspectDisplayMode);
21100
17690
  const initialStoredRenderStyle = resolveForgeRenderStyle(initialViewPreferences.renderStyle);
@@ -21623,7 +18213,7 @@ const useForgeStore = create((set, get) => ({
21623
18213
  set({ meshPreviewFile: meshPath });
21624
18214
  if (meshPath) get().execute();
21625
18215
  },
21626
- activeBackend: initialViewPreferences.activeBackend || DEFAULT_ACTIVE_BACKEND,
18216
+ activeBackend: initialKernel.name,
21627
18217
  setActiveBackend: (backend) => {
21628
18218
  writeViewPreferences({ activeBackend: backend, computeTarget: "local" });
21629
18219
  clearRunResultCache();
@@ -21631,23 +18221,26 @@ const useForgeStore = create((set, get) => ({
21631
18221
  get().execute();
21632
18222
  },
21633
18223
  setComputeBackend: (backend) => {
21634
- const parts = computeBackendParts(backend);
21635
- writeViewPreferences({ activeBackend: parts.activeBackend, computeTarget: parts.computeTarget });
18224
+ const kernel = kernelFromId(backend);
18225
+ if (!availableKernels(canUseServerCompute()).some((available) => available.id === kernel.id)) return;
18226
+ writeViewPreferences({ activeBackend: kernel.name, computeTarget: kernel.location });
21636
18227
  clearRunResultCache();
21637
- set({ activeBackend: parts.activeBackend, computeTarget: parts.computeTarget });
21638
- if (parts.computeTarget === "server") {
18228
+ set({ activeBackend: kernel.name, computeTarget: kernel.location });
18229
+ if (kernel.location === "server") {
21639
18230
  startServerPolling();
21640
18231
  }
21641
18232
  get().execute();
21642
18233
  },
21643
- computeTarget: "local",
18234
+ computeTarget: initialKernel.location,
21644
18235
  setComputeTarget: (target) => {
21645
- const nextTarget = target;
21646
- const nextBackend = nextTarget === "server" ? "occt" : get().activeBackend;
21647
- writeViewPreferences({ activeBackend: nextBackend, computeTarget: nextTarget });
18236
+ const kernel = resolveAvailableKernel(
18237
+ { name: target === "server" ? "occt" : get().activeBackend, location: target },
18238
+ availableKernels(canUseServerCompute())
18239
+ );
18240
+ writeViewPreferences({ activeBackend: kernel.name, computeTarget: kernel.location });
21648
18241
  clearRunResultCache();
21649
- set({ activeBackend: nextBackend, computeTarget: nextTarget });
21650
- if (nextTarget === "server") {
18242
+ set({ activeBackend: kernel.name, computeTarget: kernel.location });
18243
+ if (kernel.location === "server") {
21651
18244
  startServerPolling();
21652
18245
  }
21653
18246
  get().execute();
@@ -22191,10 +18784,13 @@ const useForgeStore = create((set, get) => ({
22191
18784
  writeViewPreferences({ inspectIsolineSpacing: next });
22192
18785
  set({ inspectIsolineSpacing: next });
22193
18786
  },
22194
- inspectCriticalLineEnabled: resolveBooleanPref(
22195
- initialViewPreferences.inspectCriticalLineEnabled,
22196
- DEFAULT_INSPECT_CRITICAL_LINE_ENABLED
22197
- ),
18787
+ inspectQuantizeBands: resolveInspectQuantizeBands(initialViewPreferences.inspectQuantizeBands),
18788
+ setInspectQuantizeBands: (bands) => {
18789
+ const next = resolveInspectQuantizeBands(bands);
18790
+ writeViewPreferences({ inspectQuantizeBands: next });
18791
+ set({ inspectQuantizeBands: next });
18792
+ },
18793
+ inspectCriticalLineEnabled: resolveBooleanPref(initialViewPreferences.inspectCriticalLineEnabled, DEFAULT_INSPECT_CRITICAL_LINE_ENABLED),
22198
18794
  setInspectCriticalLineEnabled: (enabled) => {
22199
18795
  const next = resolveBooleanPref(enabled, DEFAULT_INSPECT_CRITICAL_LINE_ENABLED);
22200
18796
  writeViewPreferences({ inspectCriticalLineEnabled: next });
@@ -27104,7 +23700,7 @@ function OrbitTargetPulseLayer() {
27104
23700
  class ConstructionHistoryWorkerClient {
27105
23701
  constructor(workerFactory = () => new Worker(new URL(
27106
23702
  /* @vite-ignore */
27107
- "/assets/constructionHistoryWorker-PCwXrTDB.js",
23703
+ "/assets/constructionHistoryWorker-cTHWRJEi.js",
27108
23704
  import.meta.url
27109
23705
  ), { type: "module" })) {
27110
23706
  __publicField(this, "worker", null);
@@ -29616,7 +26212,7 @@ function generateReportInWorker(options) {
29616
26212
  return new Promise((resolve2, reject) => {
29617
26213
  const worker = new Worker(new URL(
29618
26214
  /* @vite-ignore */
29619
- "/assets/reportWorker-CWvn0CEv.js",
26215
+ "/assets/reportWorker-Cb5eyM7D.js",
29620
26216
  import.meta.url
29621
26217
  ), { type: "module" });
29622
26218
  const cleanup = () => {
@@ -29776,7 +26372,7 @@ function tessellateArc(center, start, end, radius, clockwise, segments) {
29776
26372
  const startAngle = Math.atan2(start[1] - center[1], start[0] - center[0]);
29777
26373
  const endAngle = Math.atan2(end[1] - center[1], end[0] - center[0]);
29778
26374
  let sweep = endAngle - startAngle;
29779
- const direction2 = clockwise ? -1 : 1;
26375
+ const direction = clockwise ? -1 : 1;
29780
26376
  if (clockwise) {
29781
26377
  if (sweep > 0) sweep -= 2 * Math.PI;
29782
26378
  sweep = -sweep;
@@ -29786,7 +26382,7 @@ function tessellateArc(center, start, end, radius, clockwise, segments) {
29786
26382
  const points = [start];
29787
26383
  for (let k2 = 1; k2 <= segments; k2++) {
29788
26384
  const t2 = k2 / segments * sweep;
29789
- const angle = startAngle + direction2 * t2;
26385
+ const angle = startAngle + direction * t2;
29790
26386
  points.push([center[0] + radius * Math.cos(angle), center[1] + radius * Math.sin(angle)]);
29791
26387
  }
29792
26388
  return points;
@@ -30471,8 +27067,8 @@ const applyOrbitPose = (camera, target, radius, turn, pitchDeg) => {
30471
27067
  const yaw = normalizedTurn * Math.PI * 2;
30472
27068
  const pitch = MathUtils.degToRad(clampedPitch);
30473
27069
  const cosPitch = Math.cos(pitch);
30474
- const direction2 = new Vector3(Math.sin(yaw) * cosPitch, -Math.cos(yaw) * cosPitch, Math.sin(pitch)).normalize();
30475
- camera.position.copy(target).addScaledVector(direction2, radius);
27070
+ const direction = new Vector3(Math.sin(yaw) * cosPitch, -Math.cos(yaw) * cosPitch, Math.sin(pitch)).normalize();
27071
+ camera.position.copy(target).addScaledVector(direction, radius);
30476
27072
  camera.up.set(0, 0, 1);
30477
27073
  camera.lookAt(target);
30478
27074
  if ("updateProjectionMatrix" in camera && typeof camera.updateProjectionMatrix === "function") {
@@ -30512,8 +27108,8 @@ function setOverrideOrbitCamera(session, turn, pitchDeg) {
30512
27108
  const yaw = normalizedTurn * Math.PI * 2;
30513
27109
  const pitch = MathUtils.degToRad(clampedPitch);
30514
27110
  const cosPitch = Math.cos(pitch);
30515
- const direction2 = new Vector3(Math.sin(yaw) * cosPitch, -Math.cos(yaw) * cosPitch, Math.sin(pitch)).normalize();
30516
- session.camera.position.copy(session.center).addScaledVector(direction2, session.distance);
27111
+ const direction = new Vector3(Math.sin(yaw) * cosPitch, -Math.cos(yaw) * cosPitch, Math.sin(pitch)).normalize();
27112
+ session.camera.position.copy(session.center).addScaledVector(direction, session.distance);
30517
27113
  session.camera.lookAt(session.center);
30518
27114
  session.camera.updateProjectionMatrix();
30519
27115
  }
@@ -33384,144 +29980,6 @@ function LedgerMetric({ label, value }) {
33384
29980
  }
33385
29981
  );
33386
29982
  }
33387
- const INSPECT_SCALAR_VERTEX_SHADER = `
33388
- attribute float aValue;
33389
- varying float vValue;
33390
- varying vec3 vViewNormal;
33391
- varying vec3 vViewDirection;
33392
- #include <clipping_planes_pars_vertex>
33393
-
33394
- void main() {
33395
- vValue = aValue;
33396
- vViewNormal = normalize(normalMatrix * normal);
33397
- vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
33398
- vViewDirection = normalize(-mvPosition.xyz);
33399
- gl_Position = projectionMatrix * mvPosition;
33400
- #include <clipping_planes_vertex>
33401
- }
33402
- `;
33403
- const INSPECT_SCALAR_FRAGMENT_SHADER = `
33404
- uniform sampler2D uColorScale;
33405
- uniform float uDomainMin;
33406
- uniform float uDomainMax;
33407
- uniform bool uIsoEnabled;
33408
- uniform float uIsoSpacing;
33409
- uniform bool uCriticalEnabled;
33410
- uniform float uCriticalThreshold;
33411
- uniform bool uShadingEnabled;
33412
- uniform vec3 uLightDirection;
33413
- uniform float uAmbient;
33414
- varying float vValue;
33415
- varying vec3 vViewNormal;
33416
- varying vec3 vViewDirection;
33417
- #include <clipping_planes_pars_fragment>
33418
-
33419
- void main() {
33420
- #include <clipping_planes_fragment>
33421
-
33422
- float span = max(uDomainMax - uDomainMin, 1e-6);
33423
- float t = clamp((vValue - uDomainMin) / span, 0.0, 1.0);
33424
- // LUT is pre-baked perceptual sRGB; the texture is NoColorSpace so this fetch
33425
- // is NOT decoded. Do not apply any further linearization here (critique M1).
33426
- vec3 color = texture2D(uColorScale, vec2(t, 0.5)).rgb;
33427
-
33428
- // Anti-aliased isolines / critical line via the fwidth contour trick.
33429
- if (uIsoEnabled || uCriticalEnabled) {
33430
- if (uIsoEnabled && uIsoSpacing > 1e-6) {
33431
- float f = vValue / uIsoSpacing;
33432
- float grad = fwidth(f);
33433
- // Distance (in cycles) to the nearest integer contour, anti-aliased by grad.
33434
- // grad * 1.3 matches the exact contour width of the validated lab preview
33435
- // (render.mjs) that the user signed off on.
33436
- float line = abs(fract(f - 0.5) - 0.5) / max(grad * 1.3, 1e-6);
33437
- float a = 1.0 - clamp(line, 0.0, 1.0);
33438
- color = mix(color, vec3(0.08, 0.094, 0.118), 0.85 * a);
33439
- }
33440
- if (uCriticalEnabled) {
33441
- float gradV = fwidth(vValue);
33442
- float dist = abs(vValue - uCriticalThreshold) / max(gradV * 1.6, 1e-6);
33443
- float a = 1.0 - clamp(dist, 0.0, 1.0);
33444
- color = mix(color, vec3(1.0, 0.235, 0.235), a);
33445
- }
33446
- }
33447
-
33448
- if (uShadingEnabled) {
33449
- vec3 n = normalize(vViewNormal);
33450
- // Two-sided Lambert: inspection surfaces are viewed from either face.
33451
- float lambert = abs(dot(n, normalize(uLightDirection)));
33452
- float shade = uAmbient + (1.0 - uAmbient) * lambert;
33453
- color *= shade;
33454
- float rim = pow(1.0 - clamp(dot(n, normalize(vViewDirection)), 0.0, 1.0), 2.0);
33455
- color += vec3(0.025, 0.04, 0.055) * rim;
33456
- }
33457
-
33458
- gl_FragColor = vec4(color, 1.0);
33459
- }
33460
- `;
33461
- const COLOR_SCALE_LUT_LENGTH = 256 * 4;
33462
- function makeColorScaleTexture(lut) {
33463
- if (!(lut instanceof Uint8Array)) {
33464
- throw new TypeError("makeColorScaleTexture: lut must be a Uint8Array of RGBA bytes.");
33465
- }
33466
- if (lut.length !== COLOR_SCALE_LUT_LENGTH) {
33467
- throw new RangeError(
33468
- `makeColorScaleTexture: lut must be exactly ${COLOR_SCALE_LUT_LENGTH} bytes (256 RGBA stops), got ${lut.length}.`
33469
- );
33470
- }
33471
- const texture = new DataTexture(lut, 256, 1, RGBAFormat, UnsignedByteType);
33472
- texture.colorSpace = NoColorSpace;
33473
- texture.minFilter = LinearFilter;
33474
- texture.magFilter = LinearFilter;
33475
- texture.wrapS = ClampToEdgeWrapping;
33476
- texture.wrapT = ClampToEdgeWrapping;
33477
- texture.generateMipmaps = false;
33478
- texture.unpackAlignment = 1;
33479
- texture.needsUpdate = true;
33480
- return texture;
33481
- }
33482
- const DEFAULT_LIGHT_DIRECTION = new Vector3(0.45, 0.55, 0.75).normalize();
33483
- const DEFAULT_AMBIENT = 0.42;
33484
- function makeInspectScalarUniforms(params) {
33485
- if (!Number.isFinite(params.domainMin) || !Number.isFinite(params.domainMax)) {
33486
- throw new RangeError(
33487
- `makeInspectScalarUniforms: domainMin/domainMax must be finite, got [${params.domainMin}, ${params.domainMax}].`
33488
- );
33489
- }
33490
- return {
33491
- uColorScale: { value: params.colorScale },
33492
- uDomainMin: { value: params.domainMin },
33493
- uDomainMax: { value: params.domainMax },
33494
- uIsoEnabled: { value: params.isoEnabled ?? false },
33495
- uIsoSpacing: { value: params.isoSpacing ?? 0 },
33496
- uCriticalEnabled: { value: params.criticalEnabled ?? false },
33497
- uCriticalThreshold: { value: params.criticalThreshold ?? 0 },
33498
- uShadingEnabled: { value: params.shadingEnabled ?? true },
33499
- uLightDirection: { value: (params.lightDirection ?? DEFAULT_LIGHT_DIRECTION).clone() },
33500
- uAmbient: { value: params.ambient ?? DEFAULT_AMBIENT }
33501
- };
33502
- }
33503
- function updateInspectScalarUniforms(uniforms, params) {
33504
- if (params.colorScale !== void 0) uniforms.uColorScale.value = params.colorScale;
33505
- if (params.domainMin !== void 0) {
33506
- if (!Number.isFinite(params.domainMin)) {
33507
- throw new RangeError(`updateInspectScalarUniforms: domainMin must be finite, got ${params.domainMin}.`);
33508
- }
33509
- uniforms.uDomainMin.value = params.domainMin;
33510
- }
33511
- if (params.domainMax !== void 0) {
33512
- if (!Number.isFinite(params.domainMax)) {
33513
- throw new RangeError(`updateInspectScalarUniforms: domainMax must be finite, got ${params.domainMax}.`);
33514
- }
33515
- uniforms.uDomainMax.value = params.domainMax;
33516
- }
33517
- if (params.isoEnabled !== void 0) uniforms.uIsoEnabled.value = params.isoEnabled;
33518
- if (params.isoSpacing !== void 0) uniforms.uIsoSpacing.value = params.isoSpacing;
33519
- if (params.criticalEnabled !== void 0) uniforms.uCriticalEnabled.value = params.criticalEnabled;
33520
- if (params.criticalThreshold !== void 0) uniforms.uCriticalThreshold.value = params.criticalThreshold;
33521
- if (params.shadingEnabled !== void 0) uniforms.uShadingEnabled.value = params.shadingEnabled;
33522
- if (params.lightDirection !== void 0) uniforms.uLightDirection.value.copy(params.lightDirection);
33523
- if (params.ambient !== void 0) uniforms.uAmbient.value = params.ambient;
33524
- }
33525
29983
  const PREVIEW_RENDER_ORDER_STEP = 1;
33526
29984
  const HATCH_DIRECTION_A = new Vector2(Math.cos(MathUtils.degToRad(35)), Math.sin(MathUtils.degToRad(35)));
33527
29985
  const HATCH_DIRECTION_B = new Vector2(Math.cos(MathUtils.degToRad(125)), Math.sin(MathUtils.degToRad(125)));
@@ -35054,7 +31512,7 @@ function ForgeObject({
35054
31512
  onDoubleClick,
35055
31513
  onContextMenu
35056
31514
  }) {
35057
- var _a3, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
31515
+ var _a3, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
35058
31516
  const wantsDirectSdf = Boolean(
35059
31517
  canRenderSdfDirectly(obj.sdf) && inspectChannel === "none" && renderStyle !== "scan" && renderStyle !== "matrix" && renderMode !== "wireframe" && !debugHighlightColor
35060
31518
  );
@@ -35147,6 +31605,7 @@ function ForgeObject({
35147
31605
  colorScale: inspectColormapTexture,
35148
31606
  domainMin: effectiveColorScale.domainMin,
35149
31607
  domainMax: effectiveColorScale.domainMax,
31608
+ quantizeBands: (inspectScalarParams == null ? void 0 : inspectScalarParams.quantizeBands) ?? 0,
35150
31609
  isoEnabled: (inspectScalarParams == null ? void 0 : inspectScalarParams.isolinesEnabled) ?? false,
35151
31610
  isoSpacing: (inspectScalarParams == null ? void 0 : inspectScalarParams.isolineSpacing) ?? 0,
35152
31611
  criticalEnabled: Boolean((inspectScalarParams == null ? void 0 : inspectScalarParams.criticalEnabled) && (inspectScalarParams == null ? void 0 : inspectScalarParams.criticalThreshold) != null),
@@ -35195,6 +31654,7 @@ function ForgeObject({
35195
31654
  updateInspectScalarUniforms(inspectScalarUniforms, {
35196
31655
  domainMin: effectiveColorScale.domainMin,
35197
31656
  domainMax: effectiveColorScale.domainMax,
31657
+ quantizeBands: inspectScalarParams.quantizeBands,
35198
31658
  isoEnabled: inspectScalarParams.isolinesEnabled,
35199
31659
  isoSpacing: inspectScalarParams.isolineSpacing,
35200
31660
  criticalEnabled: inspectScalarParams.criticalEnabled && inspectScalarParams.criticalThreshold != null,
@@ -35208,13 +31668,35 @@ function ForgeObject({
35208
31668
  Object.values(scanAnalysisGeometries ?? {}).forEach((geometry) => geometry == null ? void 0 : geometry.dispose());
35209
31669
  };
35210
31670
  }, [scanAnalysisGeometries]);
31671
+ const textureDescriptor = (_a3 = obj.materialProps) == null ? void 0 : _a3.texture;
31672
+ const projectedTexture = reactExports.useMemo(() => {
31673
+ if (!textureDescriptor) return null;
31674
+ return descriptorToThreeTexture(textureDescriptor.image, { colorSpace: "srgb" });
31675
+ }, [textureDescriptor]);
31676
+ const solidMaterialRef = reactExports.useRef(null);
31677
+ const setSolidMaterial = reactExports.useCallback(
31678
+ (material) => {
31679
+ solidMaterialRef.current = material;
31680
+ if (material && projectedTexture && textureDescriptor) {
31681
+ applyProjectedTexture(material, textureDescriptor.projection, projectedTexture);
31682
+ }
31683
+ },
31684
+ [projectedTexture, textureDescriptor]
31685
+ );
31686
+ reactExports.useEffect(() => {
31687
+ const material = solidMaterialRef.current;
31688
+ if (material && projectedTexture && textureDescriptor) {
31689
+ applyProjectedTexture(material, textureDescriptor.projection, projectedTexture);
31690
+ invalidate2();
31691
+ }
31692
+ }, [projectedTexture, textureDescriptor, invalidate2]);
35211
31693
  if (!settings.visible) return null;
35212
31694
  const effectiveRenderMode = isInteracting && renderMode === "overlay" ? "solid" : renderMode;
35213
31695
  const renderStylePreset = getRenderStylePreset(renderStyle);
35214
31696
  const materialDefaults = renderStylePreset.material;
35215
31697
  const surfaceField = renderStylePreset.surfaceField;
35216
- const authoredMaterialOpacity = (_a3 = obj.materialProps) == null ? void 0 : _a3.opacity;
35217
- const authoredMaterialTransmission = (_b2 = obj.materialProps) == null ? void 0 : _b2.transmission;
31698
+ const authoredMaterialOpacity = (_b2 = obj.materialProps) == null ? void 0 : _b2.opacity;
31699
+ const authoredMaterialTransmission = (_c = obj.materialProps) == null ? void 0 : _c.transmission;
35218
31700
  const hasAuthoredTransparency = authoredMaterialOpacity !== void 0 && authoredMaterialOpacity < 0.99 || authoredMaterialTransmission !== void 0 && authoredMaterialTransmission > 0;
35219
31701
  const transparentDefaults = hasAuthoredTransparency ? materialDefaults.authoredTransparent : materialDefaults;
35220
31702
  const meshOpacity = settings.opacity;
@@ -35307,7 +31789,8 @@ function ForgeObject({
35307
31789
  polygonOffset: inspectChannel === "floating",
35308
31790
  polygonOffsetFactor: -1,
35309
31791
  polygonOffsetUnits: -1
35310
- }
31792
+ },
31793
+ hasInspectMeshColors ? "inspect-vertex-colors" : "inspect-solid-color"
35311
31794
  ) }),
35312
31795
  showSolid && inspectChannel === "normals" && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, userData: { forgeMesh: true }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
35313
31796
  "meshNormalMaterial",
@@ -35492,25 +31975,26 @@ function ForgeObject({
35492
31975
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
35493
31976
  "meshPhysicalMaterial",
35494
31977
  {
31978
+ ref: setSolidMaterial,
35495
31979
  color: settings.color,
35496
- metalness: ((_c = obj.materialProps) == null ? void 0 : _c.metalness) ?? materialDefaults.metalness,
35497
- roughness: ((_d = obj.materialProps) == null ? void 0 : _d.roughness) ?? transparentDefaults.roughness,
35498
- clearcoat: ((_e = obj.materialProps) == null ? void 0 : _e.clearcoat) ?? transparentDefaults.clearcoat,
35499
- clearcoatRoughness: ((_f = obj.materialProps) == null ? void 0 : _f.clearcoatRoughness) ?? transparentDefaults.clearcoatRoughness,
31980
+ metalness: ((_d = obj.materialProps) == null ? void 0 : _d.metalness) ?? materialDefaults.metalness,
31981
+ roughness: ((_e = obj.materialProps) == null ? void 0 : _e.roughness) ?? transparentDefaults.roughness,
31982
+ clearcoat: ((_f = obj.materialProps) == null ? void 0 : _f.clearcoat) ?? transparentDefaults.clearcoat,
31983
+ clearcoatRoughness: ((_g = obj.materialProps) == null ? void 0 : _g.clearcoatRoughness) ?? transparentDefaults.clearcoatRoughness,
35500
31984
  transmission,
35501
- ior: ((_g = obj.materialProps) == null ? void 0 : _g.ior) ?? 1.5,
35502
- thickness: ((_h = obj.materialProps) == null ? void 0 : _h.thickness) ?? transparentDefaults.thickness,
35503
- reflectivity: ((_i = obj.materialProps) == null ? void 0 : _i.reflectivity) ?? transparentDefaults.reflectivity,
35504
- specularIntensity: ((_j = obj.materialProps) == null ? void 0 : _j.specularIntensity) ?? transparentDefaults.specularIntensity,
35505
- specularColor: ((_k = obj.materialProps) == null ? void 0 : _k.specularColor) ?? "#ffffff",
31985
+ ior: ((_h = obj.materialProps) == null ? void 0 : _h.ior) ?? 1.5,
31986
+ thickness: ((_i = obj.materialProps) == null ? void 0 : _i.thickness) ?? transparentDefaults.thickness,
31987
+ reflectivity: ((_j = obj.materialProps) == null ? void 0 : _j.reflectivity) ?? transparentDefaults.reflectivity,
31988
+ specularIntensity: ((_k = obj.materialProps) == null ? void 0 : _k.specularIntensity) ?? transparentDefaults.specularIntensity,
31989
+ specularColor: ((_l = obj.materialProps) == null ? void 0 : _l.specularColor) ?? "#ffffff",
35506
31990
  flatShading: !hasSmoothNormals,
35507
31991
  side: DoubleSide,
35508
31992
  transparent: isTransparent,
35509
31993
  opacity: materialOpacity,
35510
31994
  depthWrite: !isTransparent,
35511
- emissive: isHovered ? settings.color : ((_l = obj.materialProps) == null ? void 0 : _l.emissive) ?? "#000000",
35512
- emissiveIntensity: isHovered ? 0.3 : ((_m = obj.materialProps) == null ? void 0 : _m.emissiveIntensity) ?? 0,
35513
- wireframe: ((_n = obj.materialProps) == null ? void 0 : _n.wireframe) ?? false,
31995
+ emissive: isHovered ? settings.color : ((_m = obj.materialProps) == null ? void 0 : _m.emissive) ?? "#000000",
31996
+ emissiveIntensity: isHovered ? 0.3 : ((_n = obj.materialProps) == null ? void 0 : _n.emissiveIntensity) ?? 0,
31997
+ wireframe: ((_o = obj.materialProps) == null ? void 0 : _o.wireframe) ?? false,
35514
31998
  clippingPlanes: effectiveClippingPlanes
35515
31999
  }
35516
32000
  ) }),
@@ -35600,13 +32084,13 @@ const resolveArcReferenceDirection = (axisWorld) => {
35600
32084
  return fallback.normalize();
35601
32085
  };
35602
32086
  const resolveSegmentMeshTransform = (start, end) => {
35603
- const direction2 = end.clone().sub(start);
35604
- const length = direction2.length();
32087
+ const direction = end.clone().sub(start);
32088
+ const length = direction.length();
35605
32089
  if (length <= 1e-6) return null;
35606
- direction2.multiplyScalar(1 / length);
32090
+ direction.multiplyScalar(1 / length);
35607
32091
  return {
35608
32092
  midpoint: start.clone().add(end).multiplyScalar(0.5),
35609
- quaternion: new Quaternion().setFromUnitVectors(WORLD_UP$1, direction2),
32093
+ quaternion: new Quaternion().setFromUnitVectors(WORLD_UP$1, direction),
35610
32094
  length
35611
32095
  };
35612
32096
  };
@@ -35731,8 +32215,8 @@ function HoveredJointOverlay({ state: state2, config }) {
35731
32215
  const points = [];
35732
32216
  for (let i = 0; i <= steps; i += 1) {
35733
32217
  const theta = arcAngleRad * (i / steps);
35734
- const direction2 = arcStartDirection.clone().applyAxisAngle(state2.axisWorld, theta);
35735
- points.push(state2.pivotWorld.clone().addScaledVector(direction2, arcRadius));
32218
+ const direction = arcStartDirection.clone().applyAxisAngle(state2.axisWorld, theta);
32219
+ points.push(state2.pivotWorld.clone().addScaledVector(direction, arcRadius));
35736
32220
  }
35737
32221
  return points;
35738
32222
  }, [
@@ -36460,6 +32944,7 @@ function InspectionLegend({
36460
32944
  displayMode,
36461
32945
  warnings,
36462
32946
  details,
32947
+ swatches: liveSwatches,
36463
32948
  thicknessColorRange,
36464
32949
  onThicknessColorRangeChange,
36465
32950
  colorScale,
@@ -36474,6 +32959,7 @@ function InspectionLegend({
36474
32959
  unitLabel,
36475
32960
  criticalValue
36476
32961
  });
32962
+ const swatches = liveSwatches && liveSwatches.length > 0 ? liveSwatches : definition == null ? void 0 : definition.swatches;
36477
32963
  const sliderGradient = colorScaleHexStops((colorScale == null ? void 0 : colorScale.colormap) ?? "viridis");
36478
32964
  reactExports.useEffect(() => {
36479
32965
  var _a3;
@@ -36488,10 +32974,13 @@ function InspectionLegend({
36488
32974
  if (!definition) return null;
36489
32975
  const warning = warnings[0];
36490
32976
  const showThicknessControls = channel === "thickness" && thicknessColorRange !== void 0 && onThicknessColorRangeChange !== void 0;
32977
+ const swatchCount = (swatches == null ? void 0 : swatches.length) ?? 0;
32978
+ const hasScrollableSwatches = swatchCount > 10;
36491
32979
  const effectivePanelStyle = {
36492
32980
  ...panelStyle,
36493
32981
  ...compact ? { padding: "7px 8px" } : {},
36494
- ...showThicknessControls ? { pointerEvents: "auto" } : {}
32982
+ ...showThicknessControls || hasScrollableSwatches ? { pointerEvents: "auto" } : {},
32983
+ ...hasScrollableSwatches ? { maxHeight: "min(320px, calc(100vh - 24px))", overflowY: "auto" } : {}
36495
32984
  };
36496
32985
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: panelRef, className: "fc-viewport-floating-panel fc-inspection-legend", style: effectivePanelStyle, children: [
36497
32986
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: titleStyle, children: [
@@ -36513,14 +33002,14 @@ function InspectionLegend({
36513
33002
  "div",
36514
33003
  {
36515
33004
  style: {
36516
- marginBottom: definition.ramp || definition.swatches ? 8 : 0,
33005
+ marginBottom: definition.ramp || swatches ? 8 : 0,
36517
33006
  color: "var(--fc-text)",
36518
33007
  minWidth: 0
36519
33008
  },
36520
33009
  children: details
36521
33010
  }
36522
33011
  ),
36523
- definition.swatches && /* @__PURE__ */ jsxRuntimeExports.jsx(
33012
+ swatches && /* @__PURE__ */ jsxRuntimeExports.jsx(
36524
33013
  "div",
36525
33014
  {
36526
33015
  style: {
@@ -36528,7 +33017,7 @@ function InspectionLegend({
36528
33017
  gridTemplateColumns: compact ? "minmax(0, 1fr)" : swatchGridStyle.gridTemplateColumns,
36529
33018
  marginTop: definition.ramp ? 8 : 0
36530
33019
  },
36531
- children: definition.swatches.map((item) => /* @__PURE__ */ jsxRuntimeExports.jsx(Swatch, { item }, `${item.label}:${item.detail}`))
33020
+ children: swatches.map((item) => /* @__PURE__ */ jsxRuntimeExports.jsx(Swatch, { item }, `${item.label}:${item.detail}`))
36532
33021
  }
36533
33022
  ),
36534
33023
  warning && /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -37943,16 +34432,16 @@ function releasePointerCapture(event) {
37943
34432
  const target = event.target;
37944
34433
  (_a3 = target.releasePointerCapture) == null ? void 0 : _a3.call(target, event.pointerId);
37945
34434
  }
37946
- function calculateAxisDragDelta(clickPoint, axis, ray2) {
34435
+ function calculateAxisDragDelta(clickPoint, axis, ray) {
37947
34436
  const axisLenSq = axis.dot(axis);
37948
34437
  if (axisLenSq <= 1e-8) return 0;
37949
- const startOffset = axis.dot(clickPoint) - axis.dot(ray2.origin);
37950
- const rayAxisDot = axis.dot(ray2.direction);
34438
+ const startOffset = axis.dot(clickPoint) - axis.dot(ray.origin);
34439
+ const rayAxisDot = axis.dot(ray.direction);
37951
34440
  if (Math.abs(rayAxisDot) <= 1e-8) {
37952
34441
  return -startOffset / axisLenSq;
37953
34442
  }
37954
- dragAxisScratchA.copy(ray2.direction).multiplyScalar(axisLenSq / rayAxisDot).sub(axis);
37955
- dragAxisScratchB.copy(ray2.direction).multiplyScalar(startOffset / rayAxisDot).add(ray2.origin).sub(clickPoint);
34443
+ dragAxisScratchA.copy(ray.direction).multiplyScalar(axisLenSq / rayAxisDot).sub(axis);
34444
+ dragAxisScratchB.copy(ray.direction).multiplyScalar(startOffset / rayAxisDot).add(ray.origin).sub(clickPoint);
37956
34445
  const denom = dragAxisScratchA.dot(dragAxisScratchA);
37957
34446
  return denom <= 1e-8 ? 0 : -dragAxisScratchA.dot(dragAxisScratchB) / denom;
37958
34447
  }
@@ -38534,7 +35023,7 @@ function SectionCapMaterial({
38534
35023
  const objectColor = parseExportColor(color, 6003669);
38535
35024
  const baseColor = objectColor.clone().lerp(new Color("#f5f7fb"), 0.1);
38536
35025
  const lineColor = objectColor.clone().lerp(new Color("#111111"), 0.45);
38537
- const direction2 = new Vector2(Math.cos(hatchAngleRad), Math.sin(hatchAngleRad));
35026
+ const direction = new Vector2(Math.cos(hatchAngleRad), Math.sin(hatchAngleRad));
38538
35027
  const mat = new MeshStandardMaterial({
38539
35028
  color: baseColor,
38540
35029
  roughness: 0.48,
@@ -38551,7 +35040,7 @@ function SectionCapMaterial({
38551
35040
  });
38552
35041
  mat.onBeforeCompile = (shader) => {
38553
35042
  shader.uniforms.hatchLineColor = { value: lineColor };
38554
- shader.uniforms.hatchDirection = { value: direction2 };
35043
+ shader.uniforms.hatchDirection = { value: direction };
38555
35044
  shader.uniforms.hatchSpacing = { value: hatchSpacing };
38556
35045
  shader.uniforms.hatchLineWidth = { value: hatchLineWidth };
38557
35046
  shader.vertexShader = shader.vertexShader.replace("#include <common>", "#include <common>\nattribute vec2 planeUv;\nvarying vec2 vSectionPlaneUv;").replace("#include <begin_vertex>", "#include <begin_vertex>\nvSectionPlaneUv = planeUv;");
@@ -42045,11 +38534,11 @@ const computeExplodeTreeOffsets = (root, explodeAmount, explodeConfig) => {
42045
38534
  const center = explodeBoundsCenter(node.bounds) ?? parentCenter;
42046
38535
  const directive = resolveExplodeDirective([node.path.join("/")], node.label, void 0, config);
42047
38536
  const motion = depth > 1 && node.children.length === 0 && !hasExplodeOverride(directive) ? (() => {
42048
- const direction2 = resolveExplodeLocalFanDirection(center, parentCenter, parentDirection, node.key);
38537
+ const direction = resolveExplodeLocalFanDirection(center, parentCenter, parentDirection, node.key);
42049
38538
  return {
42050
- direction: direction2,
42051
- branchDirection: parentDirection ?? direction2,
42052
- offset: explodeMul(direction2, config.amount * explodeLeafFanStage(config, depth))
38539
+ direction,
38540
+ branchDirection: parentDirection ?? direction,
38541
+ offset: explodeMul(direction, config.amount * explodeLeafFanStage(config, depth))
42053
38542
  };
42054
38543
  })() : computeExplodeMotion({
42055
38544
  pathKeys: [node.path.join("/")],
@@ -42412,6 +38901,7 @@ function useViewportState() {
42412
38901
  const inspectColormap = useForgeStore((s) => s.inspectColormap);
42413
38902
  const inspectIsolinesEnabled = useForgeStore((s) => s.inspectIsolinesEnabled);
42414
38903
  const inspectIsolineSpacing = useForgeStore((s) => s.inspectIsolineSpacing);
38904
+ const inspectQuantizeBands = useForgeStore((s) => s.inspectQuantizeBands);
42415
38905
  const inspectCriticalLineEnabled = useForgeStore((s) => s.inspectCriticalLineEnabled);
42416
38906
  const comparisonInspectMode = useForgeStore((s) => s.comparisonInspectMode);
42417
38907
  const comparisonCandidateOpacity = useForgeStore((s) => s.comparisonCandidateOpacity);
@@ -42827,6 +39317,7 @@ function useViewportState() {
42827
39317
  inspectColormap,
42828
39318
  inspectIsolinesEnabled,
42829
39319
  inspectIsolineSpacing,
39320
+ inspectQuantizeBands,
42830
39321
  inspectCriticalLineEnabled,
42831
39322
  comparisonInspectMode,
42832
39323
  comparisonCandidateOpacity,
@@ -44513,6 +41004,7 @@ function mergeResults(results, channel, analysisId) {
44513
41004
  meshColorObjects: [],
44514
41005
  scalarSurfaceObjects: [],
44515
41006
  collisionGeometryObjects: [],
41007
+ legendSwatches: [],
44516
41008
  warnings: []
44517
41009
  };
44518
41010
  for (const result of results) {
@@ -44521,6 +41013,7 @@ function mergeResults(results, channel, analysisId) {
44521
41013
  merged.meshColorObjects.push(...result.meshColorObjects);
44522
41014
  merged.scalarSurfaceObjects.push(...result.scalarSurfaceObjects);
44523
41015
  merged.collisionGeometryObjects.push(...result.collisionGeometryObjects);
41016
+ merged.legendSwatches.push(...result.legendSwatches);
44524
41017
  merged.warnings.push(...result.warnings);
44525
41018
  }
44526
41019
  return merged;
@@ -44528,7 +41021,7 @@ function mergeResults(results, channel, analysisId) {
44528
41021
  class InspectWorkerClient {
44529
41022
  constructor(workerFactory = () => new Worker(new URL(
44530
41023
  /* @vite-ignore */
44531
- "/assets/inspectWorker-Y4cOzNyA.js",
41024
+ "/assets/inspectWorker-ymhBV4Ll.js",
44532
41025
  import.meta.url
44533
41026
  ), { type: "module" })) {
44534
41027
  __publicField(this, "reqId", 0);
@@ -44940,6 +41433,7 @@ function resultToState(channel, result) {
44940
41433
  }
44941
41434
  ])
44942
41435
  ),
41436
+ legendSwatches: result.legendSwatches,
44943
41437
  warnings: result.warnings,
44944
41438
  error: null
44945
41439
  };
@@ -44953,6 +41447,7 @@ function useInspectWorkerAnalysis(args) {
44953
41447
  pointClouds: {},
44954
41448
  scalarSurfaces: {},
44955
41449
  collisionGeometries: [],
41450
+ legendSwatches: [],
44956
41451
  warnings: [],
44957
41452
  error: null
44958
41453
  });
@@ -44967,6 +41462,7 @@ function useInspectWorkerAnalysis(args) {
44967
41462
  pointClouds: {},
44968
41463
  scalarSurfaces: {},
44969
41464
  collisionGeometries: [],
41465
+ legendSwatches: [],
44970
41466
  warnings: [],
44971
41467
  error: null
44972
41468
  });
@@ -44982,6 +41478,7 @@ function useInspectWorkerAnalysis(args) {
44982
41478
  pointClouds: {},
44983
41479
  scalarSurfaces: {},
44984
41480
  collisionGeometries: [],
41481
+ legendSwatches: [],
44985
41482
  warnings: [],
44986
41483
  error: null
44987
41484
  });
@@ -45021,6 +41518,7 @@ function useInspectWorkerAnalysis(args) {
45021
41518
  pointClouds: {},
45022
41519
  scalarSurfaces: {},
45023
41520
  collisionGeometries: [],
41521
+ legendSwatches: [],
45024
41522
  warnings: [],
45025
41523
  error: error instanceof Error ? error.message : String(error)
45026
41524
  });
@@ -45062,19 +41560,19 @@ function dominantAxis(normal) {
45062
41560
  if (ay >= ax && ay >= az) return "y";
45063
41561
  return "z";
45064
41562
  }
45065
- function anchoredCellIndex(value, cellSize, direction2) {
41563
+ function anchoredCellIndex(value, cellSize, direction) {
45066
41564
  const scaled = value / cellSize;
45067
41565
  const base = Math.floor(scaled);
45068
41566
  const onBoundary = Math.abs(scaled - Math.round(scaled)) < 1e-7;
45069
- return onBoundary && direction2 < 0 ? base - 1 : base;
41567
+ return onBoundary && direction < 0 ? base - 1 : base;
45070
41568
  }
45071
41569
  function voxelCellFromSurfaceAnchor(point, normal, cellSize, side) {
45072
41570
  const cell = voxelCellFromPoint(point, cellSize);
45073
41571
  const axis = dominantAxis(normal);
45074
41572
  const normalValue = normal[axis];
45075
41573
  const outsideDirection = normalValue < 0 ? -1 : 1;
45076
- const direction2 = side === "outside" ? outsideDirection : -outsideDirection;
45077
- cell[axis] = anchoredCellIndex(point[axis], cellSize, direction2);
41574
+ const direction = side === "outside" ? outsideDirection : -outsideDirection;
41575
+ cell[axis] = anchoredCellIndex(point[axis], cellSize, direction);
45078
41576
  return cell;
45079
41577
  }
45080
41578
  function parseVoxelCellKey(key) {
@@ -45526,6 +42024,7 @@ function Viewport() {
45526
42024
  inspectColormap,
45527
42025
  inspectIsolinesEnabled,
45528
42026
  inspectIsolineSpacing,
42027
+ inspectQuantizeBands,
45529
42028
  inspectCriticalLineEnabled,
45530
42029
  comparisonInspectMode,
45531
42030
  comparisonCandidateOpacity,
@@ -45691,13 +42190,21 @@ function Viewport() {
45691
42190
  if (!scalarChannelInfo) return void 0;
45692
42191
  return {
45693
42192
  colorScale: inspectColorScale,
42193
+ quantizeBands: inspectQuantizeBands,
45694
42194
  isolinesEnabled: inspectIsolinesEnabled,
45695
42195
  isolineSpacing: inspectIsolineSpacing,
45696
42196
  criticalEnabled: inspectCriticalLineEnabled,
45697
42197
  criticalThreshold: scalarChannelInfo.criticalThreshold,
45698
42198
  shadingEnabled: true
45699
42199
  };
45700
- }, [scalarChannelInfo, inspectColorScale, inspectIsolinesEnabled, inspectIsolineSpacing, inspectCriticalLineEnabled]);
42200
+ }, [
42201
+ scalarChannelInfo,
42202
+ inspectColorScale,
42203
+ inspectQuantizeBands,
42204
+ inspectIsolinesEnabled,
42205
+ inspectIsolineSpacing,
42206
+ inspectCriticalLineEnabled
42207
+ ]);
45701
42208
  const comparisonAnalysis = useGeometryComparison({
45702
42209
  enabled: comparisonInspectActive,
45703
42210
  candidate: result,
@@ -45709,6 +42216,23 @@ function Viewport() {
45709
42216
  const inspectLoading = inspectChannelActive && (comparisonInspectActive ? comparisonAnalysis.status === "loading" : inspectAnalysis.status === "loading");
45710
42217
  const inspectError = comparisonInspectActive ? comparisonAnalysis.error : inspectAnalysis.error;
45711
42218
  const inspectWarnings = comparisonInspectActive ? comparisonAnalysis.warnings : inspectAnalysis.warnings;
42219
+ const maskLegendSwatches = reactExports.useMemo(() => {
42220
+ const swatches = [];
42221
+ objects.forEach((obj, objIndex) => {
42222
+ const settings = objectSettings[obj.id] ?? DEFAULT_OBJECT_SETTINGS;
42223
+ if (settings.visible === false) return;
42224
+ swatches.push({
42225
+ label: obj.name || `Object ${objIndex + 1}`,
42226
+ detail: obj.id,
42227
+ color: maskColorForIndex(objIndex)
42228
+ });
42229
+ });
42230
+ return swatches;
42231
+ }, [objectSettings, objects]);
42232
+ const inspectLegendSwatches = reactExports.useMemo(() => {
42233
+ if (inspectChannel === "mask") return maskLegendSwatches;
42234
+ return inspectAnalysis.legendSwatches.length > 0 ? inspectAnalysis.legendSwatches : void 0;
42235
+ }, [inspectAnalysis.legendSwatches, inspectChannel, maskLegendSwatches]);
45712
42236
  const historyGeometryLoading = historyMode && historyGeometryStatus.status === "loading";
45713
42237
  const viewportBusyPhase = isEvaluating || evaluationPhase === "exporting" ? evaluationPhase : historyGeometryLoading ? "history" : inspectLoading ? "inspecting" : null;
45714
42238
  const viewportBusyLabel = historyGeometryLoading ? "Building timeline geometry" : inspectLoading ? `Generating ${inspectChannelLabel(inspectChannel)} inspect view` : void 0;
@@ -45779,7 +42303,7 @@ function Viewport() {
45779
42303
  candidates.sort((a2, b2) => a2.distance - b2.distance);
45780
42304
  return candidates[0].normal;
45781
42305
  };
45782
- const voxelBlockHitsOnRay = (ray2, cellSize) => {
42306
+ const voxelBlockHitsOnRay = (ray, cellSize) => {
45783
42307
  const hits = [];
45784
42308
  const halfExtent = cellSize * 0.55;
45785
42309
  const hitPoint = new Vector3();
@@ -45790,9 +42314,9 @@ function Viewport() {
45790
42314
  new Vector3(center.x - halfExtent, center.y - halfExtent, center.z - halfExtent),
45791
42315
  new Vector3(center.x + halfExtent, center.y + halfExtent, center.z + halfExtent)
45792
42316
  );
45793
- const intersection = ray2.intersectBox(bounds, hitPoint);
42317
+ const intersection = ray.intersectBox(bounds, hitPoint);
45794
42318
  if (!intersection) continue;
45795
- const alongRay = intersection.clone().sub(ray2.origin).dot(ray2.direction);
42319
+ const alongRay = intersection.clone().sub(ray.origin).dot(ray.direction);
45796
42320
  hits.push({ cell: { x, y, z }, normal: voxelNormalFromBoxHit(intersection, bounds), alongRay });
45797
42321
  }
45798
42322
  hits.sort((a2, b2) => a2.alongRay - b2.alongRay);
@@ -45915,6 +42439,7 @@ function Viewport() {
45915
42439
  channel: inspectChannel,
45916
42440
  displayMode: inspectDisplayMode,
45917
42441
  warnings: inspectWarnings,
42442
+ swatches: inspectLegendSwatches,
45918
42443
  thicknessColorRange,
45919
42444
  onThicknessColorRangeChange: setThicknessColorRange,
45920
42445
  colorScale: scalarChannelInfo ? inspectColorScale : void 0,
@@ -46969,7 +43494,7 @@ function Viewport() {
46969
43494
  }
46970
43495
  );
46971
43496
  }
46972
- const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-HLoKfe15.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
43497
+ const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-BWUGCdD5.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
46973
43498
  const PENDING_SHARE_COPY_KEY = "fc-pending-share-copy";
46974
43499
  function storePendingShareCopy(shareId) {
46975
43500
  sessionStorage.setItem(PENDING_SHARE_COPY_KEY, shareId);
@@ -47158,7 +43683,7 @@ const PublishedModelPage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Objec
47158
43683
  }, Symbol.toStringTag, { value: "Module" }));
47159
43684
  const siteUrl = "https://forgecad.io";
47160
43685
  const defaultImage = "https://forgecad.io/brand/social-card.png";
47161
- const pages$1 = [{ "path": "/", "title": "ForgeCAD - AI-Native CAD for Manufacturable Models", "description": "ForgeCAD turns prompts, JavaScript, and product ideas into editable parametric CAD with agent validation, manufacturing feedback, and STEP/STL exports.", "priority": "1.0", "changefreq": "weekly" }, { "path": "/docs", "title": "ForgeCAD Documentation - AI-Native Parametric CAD", "description": "Learn ForgeCAD's JavaScript CAD API, agent workflow, validation loop, exports, assemblies, sketches, and manufacturing-ready model checks.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/ai-native-cad", "title": "AI-Native CAD Workflow - ForgeCAD", "description": "How ForgeCAD supports AI-driven CAD: editable code, validation evidence, manufacturing feedback, and parallel product idea iteration.", "priority": "0.9", "changefreq": "weekly" }, { "path": "/docs/ai-usage", "title": "AI CAD Agent Setup - ForgeCAD", "description": "Set up Codex, Claude Code, OpenCode, or another agent to build, validate, inspect, export, and publish ForgeCAD models.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/cli", "title": "ForgeCAD CLI - Validate, Inspect, Export, Publish", "description": "Use the ForgeCAD CLI to run .forge.js models, render evidence, inspect manufacturability, export STEP/STL/3MF, and sync projects.", "priority": "0.7", "changefreq": "weekly" }, { "path": "/docs/simready-quickstart", "title": "ForgeCAD SimReady Quickstart - Source-Authored Simulation Metadata", "description": "Author ForgeCAD assemblies with physical bodies, materials, colliders, joints, controllers, offline SimReady checks, and simulator exports.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/simulation-workflow", "title": "ForgeCAD Simulation Workflow - MuJoCo, Gym, and Isaac Lab Handoff", "description": "Take a ForgeCAD robot through MJCF export, MuJoCo playback, Gymnasium training, force-push interaction tests, and Isaac Lab integration planning.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/skills/forgecad-make-a-model", "title": "AI CAD Model-Making Skill - ForgeCAD", "description": "A workflow for AI agents to create manufacture-realistic ForgeCAD models with validation, renders, inspection evidence, and exports.", "priority": "0.7", "changefreq": "weekly" }, { "path": "/benchmark", "title": "ForgeCAD Benchmark - AI CAD Model Generation", "description": "Benchmark AI agents generating real ForgeCAD models with executable code, visual evidence, validation output, and geometry checks.", "priority": "0.7", "changefreq": "weekly" }, { "path": "/blog", "title": "ForgeCAD Blog - AI-Native CAD and Manufacturing Workflows", "description": "Product notes, tutorials, examples, and technical updates on AI-native CAD, parametric modeling, validation, and manufacturing exports.", "priority": "0.6", "changefreq": "weekly" }, { "path": "/pricing", "title": "ForgeCAD Pricing", "description": "ForgeCAD plans for browser CAD, local CLI workflows, AI agent model generation, project publishing, and commercial use.", "priority": "0.5", "changefreq": "monthly" }, { "path": "/terms", "title": "ForgeCAD Terms of Service", "description": "Terms for ForgeCAD accounts, projects, hosted services, CLI use, commercial use, automation, and AI-assisted workflows.", "priority": "0.3", "changefreq": "yearly" }, { "path": "/privacy", "title": "ForgeCAD Privacy Policy", "description": "How ForgeCAD handles account, project, billing, analytics, and service data for the website, CLI, and hosted app.", "priority": "0.3", "changefreq": "yearly" }, { "path": "/license", "title": "ForgeCAD Software License", "description": "ForgeCAD license terms for Free, Pro, Enterprise, embedded, backend, local CLI, and AI workflow usage.", "priority": "0.3", "changefreq": "yearly" }];
43686
+ const pages$1 = [{ "path": "/", "title": "ForgeCAD - AI-Native CAD for Products, Manufacturing, and Robotics", "description": "ForgeCAD generates editable parametric CAD for real products, manufacturing components, robotics simulation assets, and AI training data with validation evidence and STEP/STL/3MF exports.", "priority": "1.0", "changefreq": "weekly" }, { "path": "/docs", "title": "ForgeCAD Documentation - AI-Native Parametric CAD", "description": "Learn ForgeCAD's AI-native CAD API, agent workflow, validation loop, exports, assemblies, sketches, simulation metadata, and manufacturing-ready model checks.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/ai-native-cad", "title": "AI-Native CAD Workflow - ForgeCAD", "description": "How ForgeCAD supports AI-driven CAD: editable code, validation evidence, manufacturing feedback, and parallel product idea iteration.", "priority": "0.9", "changefreq": "weekly" }, { "path": "/docs/ai-usage", "title": "AI CAD Agent Setup - ForgeCAD", "description": "Set up Codex, Claude Code, OpenCode, or another agent to build, validate, inspect, export, and publish ForgeCAD models.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/cli", "title": "ForgeCAD CLI - Validate, Inspect, Export, Publish", "description": "Use the ForgeCAD CLI to run .forge.js models, render evidence, inspect manufacturability, export STEP/STL/3MF, and sync projects.", "priority": "0.7", "changefreq": "weekly" }, { "path": "/docs/simready-quickstart", "title": "ForgeCAD SimReady Quickstart - Source-Authored Simulation Metadata", "description": "Author ForgeCAD assemblies with physical bodies, materials, colliders, joints, controllers, offline SimReady checks, and simulator exports.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/simulation-workflow", "title": "ForgeCAD Simulation Workflow - MuJoCo, Gym, and Isaac Lab Handoff", "description": "Take a ForgeCAD robot through MJCF export, MuJoCo playback, Gymnasium training, force-push interaction tests, and Isaac Lab integration planning.", "priority": "0.8", "changefreq": "weekly" }, { "path": "/docs/skills/forgecad-build-model", "title": "AI CAD Model-Making Skill - ForgeCAD", "description": "A workflow for AI agents to create manufacture-realistic ForgeCAD models with validation, renders, inspection evidence, and exports.", "priority": "0.7", "changefreq": "weekly" }, { "path": "/benchmark", "title": "ForgeCAD Benchmark - AI CAD Model Generation", "description": "Benchmark AI agents generating real ForgeCAD models with executable code, visual evidence, validation output, and geometry checks.", "priority": "0.7", "changefreq": "weekly" }, { "path": "/blog", "title": "ForgeCAD Blog - AI-Native CAD and Manufacturing Workflows", "description": "Product notes, tutorials, examples, and technical updates on AI-native CAD, parametric modeling, validation, and manufacturing exports.", "priority": "0.6", "changefreq": "weekly" }, { "path": "/pricing", "title": "ForgeCAD Pricing", "description": "ForgeCAD plans for browser CAD, local CLI workflows, AI agent model generation, project publishing, and commercial use.", "priority": "0.5", "changefreq": "monthly" }, { "path": "/terms", "title": "ForgeCAD Terms of Service", "description": "Terms for ForgeCAD accounts, projects, hosted services, CLI use, commercial use, automation, and AI-assisted workflows.", "priority": "0.3", "changefreq": "yearly" }, { "path": "/privacy", "title": "ForgeCAD Privacy Policy", "description": "How ForgeCAD handles account, project, billing, analytics, and service data for the website, CLI, and hosted app.", "priority": "0.3", "changefreq": "yearly" }, { "path": "/license", "title": "ForgeCAD Software License", "description": "ForgeCAD license terms for Free, Pro, Enterprise, embedded, backend, local CLI, and AI workflow usage.", "priority": "0.3", "changefreq": "yearly" }];
47162
43687
  const seoConfig = {
47163
43688
  siteUrl,
47164
43689
  defaultImage,
@@ -47235,17 +43760,17 @@ function SeoMetadata() {
47235
43760
  }, [location.pathname]);
47236
43761
  return null;
47237
43762
  }
47238
- reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-C_LssmnA.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
47239
- const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-vZb3b3Y0.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
47240
- reactExports.lazy(() => __vitePreload(() => import("./BlogPage-DlPbpt6A.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
47241
- reactExports.lazy(() => __vitePreload(() => import("./BenchmarkPage-Ds7Z2doN.js"), true ? __vite__mapDeps([1,2]) : void 0).then((m2) => ({ default: m2.BenchmarkPage })));
47242
- reactExports.lazy(() => __vitePreload(() => import("./AdminPage-CK7ObBz3.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
43763
+ reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-BoVE7JGY.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
43764
+ const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-BPGGwht1.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
43765
+ reactExports.lazy(() => __vitePreload(() => import("./BlogPage-B7BWxOCg.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
43766
+ reactExports.lazy(() => __vitePreload(() => import("./BenchmarkPage-DXKVXMrJ.js"), true ? __vite__mapDeps([1,2]) : void 0).then((m2) => ({ default: m2.BenchmarkPage })));
43767
+ reactExports.lazy(() => __vitePreload(() => import("./AdminPage-B3L3W1Uo.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
47243
43768
  reactExports.lazy(() => __vitePreload(() => Promise.resolve().then(() => PublishedModelPage$1), true ? void 0 : void 0).then((m2) => ({ default: m2.PublishedModelPage })));
47244
- reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-f47cnk39.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
47245
- reactExports.lazy(() => __vitePreload(() => import("./PricingPage-BOE27B-R.js"), true ? __vite__mapDeps([1,3]) : void 0).then((m2) => ({ default: m2.PricingPage })));
47246
- reactExports.lazy(() => __vitePreload(() => import("./LegalPage-DGsyo4n1.js"), true ? __vite__mapDeps([1,4]) : void 0).then((m2) => ({ default: m2.LegalPage })));
47247
- const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-HLoKfe15.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
47248
- const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer--KnqBKrJ.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
43769
+ reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-BlJDCRe8.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
43770
+ reactExports.lazy(() => __vitePreload(() => import("./PricingPage-C2PMzmDc.js"), true ? __vite__mapDeps([1,3]) : void 0).then((m2) => ({ default: m2.PricingPage })));
43771
+ reactExports.lazy(() => __vitePreload(() => import("./LegalPage-Din8wv8d.js"), true ? __vite__mapDeps([1,4]) : void 0).then((m2) => ({ default: m2.LegalPage })));
43772
+ const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-BWUGCdD5.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
43773
+ const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-DygByZS2.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
47249
43774
  const embedMode = isEmbedMode() && !window.location.pathname.startsWith("/m/");
47250
43775
  const EDITABLE_CRASH_FILE = /\.(?:forge\.js|[cm]?[jt]sx?|json|md|txt|svg|dxf)$/i;
47251
43776
  function firstMeaningfulLine(text) {
@@ -47465,7 +43990,7 @@ function App() {
47465
43990
  applyTheme(localStorage.getItem("fc-theme") || "dark");
47466
43991
  clientExports.createRoot(document.getElementById("root")).render(/* @__PURE__ */ jsxRuntimeExports.jsx(App, {}));
47467
43992
  export {
47468
- INSPECT_POINT_SAMPLE_COUNT_MIN as $,
43993
+ VOXEL_INTENT_TOOL_ORDER as $,
47469
43994
  AuthApiError as A,
47470
43995
  BrandMark as B,
47471
43996
  captureViewportImageBlobFromStore as C,
@@ -47490,49 +44015,48 @@ export {
47490
44015
  animationSpeedToSlider as V,
47491
44016
  formatAnimationSpeed as W,
47492
44017
  resolveJointRange as X,
47493
- useJointsConfig as Y,
47494
- useJointAnimationValues as Z,
47495
- INSPECT_POINT_SAMPLE_COUNT_MAX as _,
44018
+ availableKernels as Y,
44019
+ useJointsConfig as Z,
44020
+ useJointAnimationValues as _,
47496
44021
  applyTheme as a,
47497
- VOXEL_INTENT_TOOL_ORDER as a0,
47498
- VOXEL_INTENT_TOOL_LABELS as a1,
47499
- VOXEL_INTENT_TOOL_COLORS as a2,
47500
- VOXEL_INTENT_PLACEMENT_ORDER as a3,
47501
- VOXEL_INTENT_PLACEMENT_LABELS as a4,
47502
- highlightLanguageForProjectFile as a5,
47503
- hasProjectTextFileExtension as a6,
47504
- expandBoundsByTransformedAabb as a7,
47505
- Canvas as a8,
47506
- ActiveCameraBridge as a9,
47507
- storePendingShareCopy as aA,
47508
- buildShareUrl as aB,
47509
- share as aC,
47510
- PerspectiveCamera as aa,
47511
- ControlsInteractionBridge as ab,
47512
- SceneConfigurator as ac,
47513
- LocalEnvironment as ad,
47514
- ForgeObject as ae,
47515
- RenderLabelsOverlay as af,
47516
- Grid as ag,
47517
- OrbitControls2 as ah,
47518
- TOUCH_GESTURES_3D as ai,
47519
- MOUSE_BUTTONS_3D as aj,
47520
- ViewController as ak,
47521
- ModelJourneyBar as al,
47522
- useJointAnimationLoop as am,
47523
- computeJointNodeMatrices as an,
47524
- computeObjectJointMatrices as ao,
47525
- readLastActiveFileForUser as ap,
47526
- ToastContainer as aq,
47527
- isMobile as ar,
47528
- useFeatureFlag as as,
47529
- decodeSharedHash as at,
47530
- decodeSharedBundle as au,
47531
- getExternalUrl as av,
47532
- getGistId as aw,
47533
- Viewport as ax,
47534
- shouldBlockBrowserShortcut as ay,
47535
- useDrawStore as az,
44022
+ VOXEL_INTENT_TOOL_LABELS as a0,
44023
+ VOXEL_INTENT_TOOL_COLORS as a1,
44024
+ VOXEL_INTENT_PLACEMENT_ORDER as a2,
44025
+ VOXEL_INTENT_PLACEMENT_LABELS as a3,
44026
+ highlightLanguageForProjectFile as a4,
44027
+ hasProjectTextFileExtension as a5,
44028
+ expandBoundsByTransformedAabb as a6,
44029
+ Canvas as a7,
44030
+ ActiveCameraBridge as a8,
44031
+ PerspectiveCamera as a9,
44032
+ buildShareUrl as aA,
44033
+ share as aB,
44034
+ ControlsInteractionBridge as aa,
44035
+ SceneConfigurator as ab,
44036
+ LocalEnvironment as ac,
44037
+ ForgeObject as ad,
44038
+ RenderLabelsOverlay as ae,
44039
+ Grid as af,
44040
+ OrbitControls2 as ag,
44041
+ TOUCH_GESTURES_3D as ah,
44042
+ MOUSE_BUTTONS_3D as ai,
44043
+ ViewController as aj,
44044
+ ModelJourneyBar as ak,
44045
+ useJointAnimationLoop as al,
44046
+ computeJointNodeMatrices as am,
44047
+ computeObjectJointMatrices as an,
44048
+ readLastActiveFileForUser as ao,
44049
+ ToastContainer as ap,
44050
+ isMobile as aq,
44051
+ useFeatureFlag as ar,
44052
+ decodeSharedHash as as,
44053
+ decodeSharedBundle as at,
44054
+ getExternalUrl as au,
44055
+ getGistId as av,
44056
+ Viewport as aw,
44057
+ shouldBlockBrowserShortcut as ax,
44058
+ useDrawStore as ay,
44059
+ storePendingShareCopy as az,
47536
44060
  authFetch as b,
47537
44061
  authApi as c,
47538
44062
  showToast as d,