@babylonjs/lite 1.6.0 → 1.8.0

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 (88) hide show
  1. package/CHANGELOG.md +735 -0
  2. package/README.md +26 -1
  3. package/THIRD_PARTY_NOTICES.txt +139 -0
  4. package/dist/index.js +321 -301
  5. package/dist/index.js.map +1 -1
  6. package/index.d.ts +294 -13
  7. package/lib/_chunks/vendor/{manifold-Sh8xE2da.js → manifold-DtI3BJoR.js} +2 -2
  8. package/lib/_chunks/vendor/{manifold-Sh8xE2da.js.map → manifold-DtI3BJoR.js.map} +1 -1
  9. package/lib/animation/animation-group-task.js +1 -1
  10. package/lib/animation/animation-group-task.js.map +1 -1
  11. package/lib/animation/animation-group.js +20 -15
  12. package/lib/animation/animation-group.js.map +1 -1
  13. package/lib/animation/animation-tick.js +10 -0
  14. package/lib/animation/animation-tick.js.map +1 -0
  15. package/lib/animation/property-animation.js +2 -1
  16. package/lib/animation/property-animation.js.map +1 -1
  17. package/lib/animation/weighted-gltf-mixer.js +1 -1
  18. package/lib/animation/weighted-gltf-mixer.js.map +1 -1
  19. package/lib/animation/weighted-pointer-mixer.js +1 -1
  20. package/lib/animation/weighted-pointer-mixer.js.map +1 -1
  21. package/lib/engine/device-lost-recovery.js +1 -0
  22. package/lib/engine/device-lost-recovery.js.map +1 -1
  23. package/lib/engine/engine.js +1 -1
  24. package/lib/engine/null-engine.js +29 -0
  25. package/lib/engine/null-engine.js.map +1 -0
  26. package/lib/frame-graph/depth-pyramid.js +158 -0
  27. package/lib/frame-graph/depth-pyramid.js.map +1 -0
  28. package/lib/frame-graph/depth-resolve-task.js +117 -0
  29. package/lib/frame-graph/depth-resolve-task.js.map +1 -0
  30. package/lib/frame-graph/frame-graph-actions.js +10 -1
  31. package/lib/frame-graph/frame-graph-actions.js.map +1 -1
  32. package/lib/frame-graph/render-task.js +7 -0
  33. package/lib/frame-graph/render-task.js.map +1 -1
  34. package/lib/frame-graph/transmission-depth-grab.js +88 -0
  35. package/lib/frame-graph/transmission-depth-grab.js.map +1 -0
  36. package/lib/frame-graph/transmission.js +34 -4
  37. package/lib/frame-graph/transmission.js.map +1 -1
  38. package/lib/gizmo/bounding-box-gizmo.js +1 -1
  39. package/lib/index.js +9 -6
  40. package/lib/index.js.map +1 -1
  41. package/lib/loader-gltf/gltf-feature-gpu-instancing.js +1 -1
  42. package/lib/loader-gltf/gltf-interleave.js +1 -1
  43. package/lib/loader-gltf/load-gltf.js +1 -1
  44. package/lib/material/shader/shader-material.js +4 -2
  45. package/lib/material/shader/shader-material.js.map +1 -1
  46. package/lib/material/shader/shader-pipeline.js +11 -1
  47. package/lib/material/shader/shader-pipeline.js.map +1 -1
  48. package/lib/material/shader/shader-renderable.js +42 -14
  49. package/lib/material/shader/shader-renderable.js.map +1 -1
  50. package/lib/material/shader/shader-thin-instance.js +1 -1
  51. package/lib/material/shader/shader-thin-instance.js.map +1 -1
  52. package/lib/math/aabb.js +1 -1
  53. package/lib/math/compute-aabb.js +63 -1
  54. package/lib/math/compute-aabb.js.map +1 -1
  55. package/lib/math/index.js +1 -1
  56. package/lib/mesh/csg2.js +3 -2
  57. package/lib/mesh/csg2.js.map +1 -1
  58. package/lib/mesh/mesh-factories.js +1 -1
  59. package/lib/mesh/thin-instance-gpu-culling.js +4 -2
  60. package/lib/mesh/thin-instance-gpu-culling.js.map +1 -1
  61. package/lib/mesh/thin-instance.js +8 -1
  62. package/lib/mesh/thin-instance.js.map +1 -1
  63. package/lib/navigation/index.js +1 -1
  64. package/lib/navigation/navigation.js +9 -1
  65. package/lib/navigation/navigation.js.map +1 -1
  66. package/lib/physics/character-controller.js +2 -2
  67. package/lib/physics/character-controller.js.map +1 -1
  68. package/lib/physics/havok-floating-origin.js +2 -2
  69. package/lib/physics/havok-floating-origin.js.map +1 -1
  70. package/lib/physics/havok.js +40 -13
  71. package/lib/physics/havok.js.map +1 -1
  72. package/lib/picking/gpu-picker.js +16 -2
  73. package/lib/picking/gpu-picker.js.map +1 -1
  74. package/lib/scene/scene-core.js +14 -5
  75. package/lib/scene/scene-core.js.map +1 -1
  76. package/lib/scene/scene-remove.js +8 -0
  77. package/lib/scene/scene-remove.js.map +1 -1
  78. package/lib/shadow/csm-shadow-task-hooks.js +14 -6
  79. package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
  80. package/lib/shadow/pcf-shadow-task-hooks.js +6 -0
  81. package/lib/shadow/pcf-shadow-task-hooks.js.map +1 -1
  82. package/lib/texture/pixels-texture.js +31 -1
  83. package/lib/texture/pixels-texture.js.map +1 -1
  84. package/lib/vat/vat-baker.js +41 -2
  85. package/lib/vat/vat-baker.js.map +1 -1
  86. package/package.json +15 -3
  87. package/lib/_chunks/__vite-browser-external-BFTKbDcV.js +0 -68
  88. package/lib/_chunks/__vite-browser-external-BFTKbDcV.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"thin-instance-gpu-culling.js","sources":["../../../src/mesh/thin-instance-gpu-culling.ts"],"sourcesContent":["/** GPU frustum culling for opt-in thin instances.\n *\n * Dynamically imported only when a scene enables thin-instance GPU culling.\n * Each render binding owns its own state so render tasks with different cameras\n * never clobber one another's compacted instance buffers or indirect args.\n */\n\nimport { F32, U32 } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport { getViewProjectionMatrix } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DrawUpdateContext } from \"../render/renderable.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh, MeshGPU } from \"./mesh.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport { syncThinInstanceGpuData } from \"./thin-instance-gpu.js\";\nimport type { ThinInstanceDrawBuffers } from \"./thin-instance-gpu.js\";\n\nconst WORKGROUP_SIZE = 64;\nconst PARAM_BYTES = 192;\nconst COUNT_U32_OFFSET = 44;\nconst MESH_WORLD_FLOAT_OFFSET = 24;\nconst LOCAL_SPHERE_FLOAT_OFFSET = 40;\nconst INDIRECT_ARGS_BYTES = 20;\n\nconst CULL_WGSL_NO_COLOR = /* wgsl */ `\nstruct CullParams{planes:array<vec4<f32>,6>,meshWorld:mat4x4<f32>,localSphere:vec4<f32>,count:u32};\n@group(0)@binding(0)var<storage,read> srcMatrices:array<mat4x4<f32>>;\n@group(0)@binding(1)var<storage,read_write> dstMatrices:array<mat4x4<f32>>;\n@group(0)@binding(2)var<storage,read_write> args:array<atomic<u32>>;\n@group(0)@binding(3)var<uniform> params:CullParams;\nfn visible(world:mat4x4<f32>)->bool{\nlet center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;\nlet sx=length(world[0].xyz);\nlet sy=length(world[1].xyz);\nlet sz=length(world[2].xyz);\nlet radius=params.localSphere.w*max(max(sx,sy),sz)+0.0001;\nfor(var i=0u;i<6u;i++){\nlet p=params.planes[i];\nif(dot(p.xyz,center)+p.w < -radius){return false;}\n}\nreturn true;\n}\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\n}`;\n\nconst CULL_WGSL_COLOR = `${CULL_WGSL_NO_COLOR}\n@group(0)@binding(4)var<storage,read> srcColors:array<vec4<f32>>;\n@group(0)@binding(5)var<storage,read_write> dstColors:array<vec4<f32>>;\n@compute @workgroup_size(64)\nfn mainColor(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\ndstColors[outIndex]=srcColors[i];\n}`;\n\n/** Per-render-binding GPU culling state. */\nexport interface ThinInstanceGpuCullState {\n /** @internal */\n _capacity: number;\n /** @internal */\n _visibleMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _visibleColorBuffer: GPUBuffer | null;\n /** @internal */\n _argsBuffer: GPUBuffer | null;\n /** @internal */\n _paramsBuffer: GPUBuffer | null;\n /** @internal */\n _bindGroup: GPUBindGroup | null;\n /** @internal */\n _srcMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _srcColorBuffer: GPUBuffer | null;\n /** @internal */\n _hasColor: boolean;\n /** @internal */\n _localSphereReady: boolean;\n /** @internal */\n _localSphere: Float32Array;\n /** @internal */\n _paramsBytes: ArrayBuffer;\n /** @internal */\n _paramsF32: Float32Array;\n /** @internal */\n _paramsU32: Uint32Array;\n /** @internal */\n _argsData: Uint32Array;\n /** @internal */\n _drawBuffers: ThinInstanceDrawBuffers | null;\n}\n\n/** Result consumed by a material draw closure after culling has run for the active pass. */\nexport interface ThinInstanceGpuCullResult {\n readonly drawBuffers: ThinInstanceDrawBuffers;\n readonly argsBuffer: GPUBuffer;\n}\n\nlet _cachedDevice: GPUDevice | null = null;\nlet _pipelineNoColor: GPUComputePipeline | null = null;\nlet _pipelineColor: GPUComputePipeline | null = null;\n\n/** Create per-binding culling state. */\nexport function createTiCullState(): ThinInstanceGpuCullState {\n const paramsBytes = new ArrayBuffer(PARAM_BYTES);\n return {\n _capacity: 0,\n _visibleMatrixBuffer: null,\n _visibleColorBuffer: null,\n _argsBuffer: null,\n _paramsBuffer: null,\n _bindGroup: null,\n _srcMatrixBuffer: null,\n _srcColorBuffer: null,\n _hasColor: false,\n _localSphereReady: false,\n _localSphere: new F32(4),\n _paramsBytes: paramsBytes,\n _paramsF32: new F32(paramsBytes),\n _paramsU32: new U32(paramsBytes),\n _argsData: new U32(5),\n _drawBuffers: null,\n };\n}\n\n/** Destroy GPU resources owned by a per-binding cull state. */\nexport function destroyTiCullState(state: ThinInstanceGpuCullState): void {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._argsBuffer?.destroy();\n state._paramsBuffer?.destroy();\n state._visibleMatrixBuffer = null;\n state._visibleColorBuffer = null;\n state._argsBuffer = null;\n state._paramsBuffer = null;\n state._bindGroup = null;\n state._drawBuffers = null;\n}\n\n/** Run culling for one render binding and return buffers for the subsequent indirect draw. */\nexport function prepareTiCull(\n engine: EngineContext,\n state: ThinInstanceGpuCullState,\n mesh: Mesh,\n gpu: MeshGPU,\n ti: ThinInstanceData,\n hasColor: boolean,\n context: DrawUpdateContext\n): ThinInstanceGpuCullResult | null {\n const camera = context._camera;\n if (!ti._gpuCullingEnabled || !camera || mesh.visible === false || ti.count === 0) {\n state._drawBuffers = null;\n return null;\n }\n if (hasColor && !ti.colors) {\n state._drawBuffers = null;\n return null;\n }\n if (!state._localSphereReady && !computeLocalSphere(mesh as Mesh, state._localSphere)) {\n state._drawBuffers = null;\n return null;\n }\n state._localSphereReady = true;\n\n syncThinInstanceGpuData(engine, ti, hasColor);\n const sourceMatrixBuffer = ti._gpuBuffer;\n const sourceColorBuffer = hasColor ? ti._colorGpuBuffer : null;\n if (!sourceMatrixBuffer || (hasColor && !sourceColorBuffer)) {\n state._drawBuffers = null;\n return null;\n }\n\n ensureCullBuffers(engine, state, ti._capacity, hasColor);\n const visibleMatrixBuffer = state._visibleMatrixBuffer!;\n const visibleColorBuffer = hasColor ? state._visibleColorBuffer! : null;\n const argsBuffer = state._argsBuffer!;\n const paramsBuffer = state._paramsBuffer!;\n const pipeline = getCullPipeline(engine, hasColor);\n\n if (state._bindGroup === null || state._srcMatrixBuffer !== sourceMatrixBuffer || state._srcColorBuffer !== sourceColorBuffer || state._hasColor !== hasColor) {\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: sourceMatrixBuffer } },\n { binding: 1, resource: { buffer: visibleMatrixBuffer } },\n { binding: 2, resource: { buffer: argsBuffer } },\n { binding: 3, resource: { buffer: paramsBuffer } },\n ];\n if (hasColor) {\n entries.push({ binding: 4, resource: { buffer: sourceColorBuffer! } }, { binding: 5, resource: { buffer: visibleColorBuffer! } });\n }\n state._bindGroup = engine._device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries });\n state._srcMatrixBuffer = sourceMatrixBuffer;\n state._srcColorBuffer = sourceColorBuffer;\n state._hasColor = hasColor;\n }\n\n const v = camera.viewport;\n const aspect = (context.targetWidth / context.targetHeight) * (v ? v.width / v.height : 1);\n writeCullParams(engine, state, mesh, gpu.indexCount, ti.count, camera, aspect);\n\n const pass = engine._currentEncoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, state._bindGroup);\n pass.dispatchWorkgroups(Math.ceil(ti.count / WORKGROUP_SIZE));\n pass.end();\n\n state._drawBuffers = { matrixBuffer: visibleMatrixBuffer, colorBuffer: visibleColorBuffer };\n return { drawBuffers: state._drawBuffers, argsBuffer };\n}\n\nfunction ensureCullBuffers(engine: EngineContext, state: ThinInstanceGpuCullState, capacity: number, hasColor: boolean): void {\n const device = engine._device;\n if (state._capacity < capacity) {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._visibleMatrixBuffer = device.createBuffer({\n size: Math.max(capacity * 64, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._visibleColorBuffer = hasColor\n ? device.createBuffer({\n size: Math.max(capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n })\n : null;\n state._capacity = capacity;\n state._bindGroup = null;\n state._drawBuffers = null;\n } else if (hasColor && !state._visibleColorBuffer) {\n state._visibleColorBuffer = device.createBuffer({\n size: Math.max(state._capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._bindGroup = null;\n state._drawBuffers = null;\n }\n if (!state._argsBuffer) {\n state._argsBuffer = device.createBuffer({\n size: INDIRECT_ARGS_BYTES,\n usage: BU.INDIRECT | BU.STORAGE | BU.COPY_DST,\n });\n }\n if (!state._paramsBuffer) {\n state._paramsBuffer = device.createBuffer({\n size: PARAM_BYTES,\n usage: BU.UNIFORM | BU.COPY_DST,\n });\n }\n}\n\nfunction getCullPipeline(engine: EngineContext, hasColor: boolean): GPUComputePipeline {\n const device = engine._device;\n if (_cachedDevice !== device) {\n _cachedDevice = device;\n _pipelineNoColor = null;\n _pipelineColor = null;\n }\n if (hasColor) {\n _pipelineColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_COLOR }), entryPoint: \"mainColor\" },\n });\n return _pipelineColor;\n }\n _pipelineNoColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_NO_COLOR }), entryPoint: \"main\" },\n });\n return _pipelineNoColor;\n}\n\nfunction writeCullParams(engine: EngineContext, state: ThinInstanceGpuCullState, mesh: Mesh, indexCount: number, instanceCount: number, camera: Camera, aspect: number): void {\n const params = state._paramsF32;\n const viewProjection = getViewProjectionMatrix(camera, aspect);\n writeFrustumPlanes(params, viewProjection);\n params.set(mesh.worldMatrix, MESH_WORLD_FLOAT_OFFSET);\n params.set(state._localSphere, LOCAL_SPHERE_FLOAT_OFFSET);\n state._paramsU32[COUNT_U32_OFFSET] = instanceCount;\n\n const args = state._argsData;\n args[0] = indexCount;\n args[1] = 0;\n args[2] = 0;\n args[3] = 0;\n args[4] = 0;\n\n engine._device.queue.writeBuffer(state._argsBuffer!, 0, args.buffer, args.byteOffset, args.byteLength);\n engine._device.queue.writeBuffer(state._paramsBuffer!, 0, state._paramsBytes);\n}\n\nfunction writeFrustumPlanes(out: Float32Array, m: Mat4): void {\n writePlane(out, 0, m[3]! + m[0]!, m[7]! + m[4]!, m[11]! + m[8]!, m[15]! + m[12]!);\n writePlane(out, 4, m[3]! - m[0]!, m[7]! - m[4]!, m[11]! - m[8]!, m[15]! - m[12]!);\n writePlane(out, 8, m[3]! + m[1]!, m[7]! + m[5]!, m[11]! + m[9]!, m[15]! + m[13]!);\n writePlane(out, 12, m[3]! - m[1]!, m[7]! - m[5]!, m[11]! - m[9]!, m[15]! - m[13]!);\n writePlane(out, 16, m[2]!, m[6]!, m[10]!, m[14]!);\n writePlane(out, 20, m[3]! - m[2]!, m[7]! - m[6]!, m[11]! - m[10]!, m[15]! - m[14]!);\n}\n\nfunction writePlane(out: Float32Array, offset: number, x: number, y: number, z: number, w: number): void {\n const invLen = 1 / Math.hypot(x, y, z);\n out[offset] = x * invLen;\n out[offset + 1] = y * invLen;\n out[offset + 2] = z * invLen;\n out[offset + 3] = w * invLen;\n}\n\nfunction computeLocalSphere(mesh: Mesh, out: Float32Array): boolean {\n const positions = mesh._cpuPositions;\n if (!positions || positions.length < 3) {\n return false;\n }\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let i = 0; i < positions.length; i += 3) {\n const x = positions[i]!;\n const y = positions[i + 1]!;\n const z = positions[i + 2]!;\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n if (!isFinite(minX)) {\n return false;\n }\n const cx = (minX + maxX) * 0.5;\n const cy = (minY + maxY) * 0.5;\n const cz = (minZ + maxZ) * 0.5;\n const dx = maxX - cx;\n const dy = maxY - cy;\n const dz = maxZ - cz;\n out[0] = cx;\n out[1] = cy;\n out[2] = cz;\n out[3] = Math.hypot(dx, dy, dz);\n return true;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"thin-instance-gpu-culling.js","sources":["../../../src/mesh/thin-instance-gpu-culling.ts"],"sourcesContent":["/** GPU frustum culling for opt-in thin instances.\n *\n * Dynamically imported only when a scene enables thin-instance GPU culling.\n * Each render binding owns its own state so render tasks with different cameras\n * never clobber one another's compacted instance buffers or indirect args.\n */\n\nimport { F32, U32 } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport { getViewProjectionMatrix } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DrawUpdateContext } from \"../render/renderable.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh, MeshGPU } from \"./mesh.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport { syncThinInstanceGpuData } from \"./thin-instance-gpu.js\";\nimport type { ThinInstanceDrawBuffers } from \"./thin-instance-gpu.js\";\n\nconst WORKGROUP_SIZE = 64;\nconst PARAM_BYTES = 192;\nconst COUNT_U32_OFFSET = 44;\nconst MESH_WORLD_FLOAT_OFFSET = 24;\nconst LOCAL_SPHERE_FLOAT_OFFSET = 40;\nconst BOUNDS_PAD_F32_OFFSET = 45;\nconst INDIRECT_ARGS_BYTES = 20;\n\nconst CULL_WGSL_NO_COLOR = /* wgsl */ `\nstruct CullParams{planes:array<vec4<f32>,6>,meshWorld:mat4x4<f32>,localSphere:vec4<f32>,count:u32,boundsPad:f32};\n@group(0)@binding(0)var<storage,read> srcMatrices:array<mat4x4<f32>>;\n@group(0)@binding(1)var<storage,read_write> dstMatrices:array<mat4x4<f32>>;\n@group(0)@binding(2)var<storage,read_write> args:array<atomic<u32>>;\n@group(0)@binding(3)var<uniform> params:CullParams;\nfn visible(world:mat4x4<f32>)->bool{\nlet center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;\nlet sx=length(world[0].xyz);\nlet sy=length(world[1].xyz);\nlet sz=length(world[2].xyz);\nlet radius=params.localSphere.w*max(max(sx,sy),sz)+params.boundsPad+0.0001;\nfor(var i=0u;i<6u;i++){\nlet p=params.planes[i];\nif(dot(p.xyz,center)+p.w < -radius){return false;}\n}\nreturn true;\n}\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\n}`;\n\nconst CULL_WGSL_COLOR = `${CULL_WGSL_NO_COLOR}\n@group(0)@binding(4)var<storage,read> srcColors:array<vec4<f32>>;\n@group(0)@binding(5)var<storage,read_write> dstColors:array<vec4<f32>>;\n@compute @workgroup_size(64)\nfn mainColor(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\ndstColors[outIndex]=srcColors[i];\n}`;\n\n/** Per-render-binding GPU culling state. */\nexport interface ThinInstanceGpuCullState {\n /** @internal */\n _capacity: number;\n /** @internal */\n _visibleMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _visibleColorBuffer: GPUBuffer | null;\n /** @internal */\n _argsBuffer: GPUBuffer | null;\n /** @internal */\n _paramsBuffer: GPUBuffer | null;\n /** @internal */\n _bindGroup: GPUBindGroup | null;\n /** @internal */\n _srcMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _srcColorBuffer: GPUBuffer | null;\n /** @internal */\n _hasColor: boolean;\n /** @internal */\n _localSphereReady: boolean;\n /** @internal */\n _localSphere: Float32Array;\n /** @internal */\n _paramsBytes: ArrayBuffer;\n /** @internal */\n _paramsF32: Float32Array;\n /** @internal */\n _paramsU32: Uint32Array;\n /** @internal */\n _argsData: Uint32Array;\n /** @internal */\n _drawBuffers: ThinInstanceDrawBuffers | null;\n}\n\n/** Result consumed by a material draw closure after culling has run for the active pass. */\nexport interface ThinInstanceGpuCullResult {\n readonly drawBuffers: ThinInstanceDrawBuffers;\n readonly argsBuffer: GPUBuffer;\n}\n\nlet _cachedDevice: GPUDevice | null = null;\nlet _pipelineNoColor: GPUComputePipeline | null = null;\nlet _pipelineColor: GPUComputePipeline | null = null;\n\n/** Create per-binding culling state. */\nexport function createTiCullState(): ThinInstanceGpuCullState {\n const paramsBytes = new ArrayBuffer(PARAM_BYTES);\n return {\n _capacity: 0,\n _visibleMatrixBuffer: null,\n _visibleColorBuffer: null,\n _argsBuffer: null,\n _paramsBuffer: null,\n _bindGroup: null,\n _srcMatrixBuffer: null,\n _srcColorBuffer: null,\n _hasColor: false,\n _localSphereReady: false,\n _localSphere: new F32(4),\n _paramsBytes: paramsBytes,\n _paramsF32: new F32(paramsBytes),\n _paramsU32: new U32(paramsBytes),\n _argsData: new U32(5),\n _drawBuffers: null,\n };\n}\n\n/** Destroy GPU resources owned by a per-binding cull state. */\nexport function destroyTiCullState(state: ThinInstanceGpuCullState): void {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._argsBuffer?.destroy();\n state._paramsBuffer?.destroy();\n state._visibleMatrixBuffer = null;\n state._visibleColorBuffer = null;\n state._argsBuffer = null;\n state._paramsBuffer = null;\n state._bindGroup = null;\n state._drawBuffers = null;\n}\n\n/** Run culling for one render binding and return buffers for the subsequent indirect draw. */\nexport function prepareTiCull(\n engine: EngineContext,\n state: ThinInstanceGpuCullState,\n mesh: Mesh,\n gpu: MeshGPU,\n ti: ThinInstanceData,\n hasColor: boolean,\n context: DrawUpdateContext\n): ThinInstanceGpuCullResult | null {\n const camera = context._camera;\n if (!ti._gpuCullingEnabled || !camera || mesh.visible === false || ti.count === 0) {\n state._drawBuffers = null;\n return null;\n }\n if (hasColor && !ti.colors) {\n state._drawBuffers = null;\n return null;\n }\n if (!state._localSphereReady && !computeLocalSphere(mesh as Mesh, state._localSphere)) {\n state._drawBuffers = null;\n return null;\n }\n state._localSphereReady = true;\n\n syncThinInstanceGpuData(engine, ti, hasColor);\n const sourceMatrixBuffer = ti._gpuBuffer;\n const sourceColorBuffer = hasColor ? ti._colorGpuBuffer : null;\n if (!sourceMatrixBuffer || (hasColor && !sourceColorBuffer)) {\n state._drawBuffers = null;\n return null;\n }\n\n ensureCullBuffers(engine, state, ti._capacity, hasColor);\n const visibleMatrixBuffer = state._visibleMatrixBuffer!;\n const visibleColorBuffer = hasColor ? state._visibleColorBuffer! : null;\n const argsBuffer = state._argsBuffer!;\n const paramsBuffer = state._paramsBuffer!;\n const pipeline = getCullPipeline(engine, hasColor);\n\n if (state._bindGroup === null || state._srcMatrixBuffer !== sourceMatrixBuffer || state._srcColorBuffer !== sourceColorBuffer || state._hasColor !== hasColor) {\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: sourceMatrixBuffer } },\n { binding: 1, resource: { buffer: visibleMatrixBuffer } },\n { binding: 2, resource: { buffer: argsBuffer } },\n { binding: 3, resource: { buffer: paramsBuffer } },\n ];\n if (hasColor) {\n entries.push({ binding: 4, resource: { buffer: sourceColorBuffer! } }, { binding: 5, resource: { buffer: visibleColorBuffer! } });\n }\n state._bindGroup = engine._device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries });\n state._srcMatrixBuffer = sourceMatrixBuffer;\n state._srcColorBuffer = sourceColorBuffer;\n state._hasColor = hasColor;\n }\n\n const v = camera.viewport;\n const aspect = (context.targetWidth / context.targetHeight) * (v ? v.width / v.height : 1);\n writeCullParams(engine, state, mesh, gpu.indexCount, ti.count, camera, aspect);\n\n const pass = engine._currentEncoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, state._bindGroup);\n pass.dispatchWorkgroups(Math.ceil(ti.count / WORKGROUP_SIZE));\n pass.end();\n\n state._drawBuffers = { matrixBuffer: visibleMatrixBuffer, colorBuffer: visibleColorBuffer };\n return { drawBuffers: state._drawBuffers, argsBuffer };\n}\n\nfunction ensureCullBuffers(engine: EngineContext, state: ThinInstanceGpuCullState, capacity: number, hasColor: boolean): void {\n const device = engine._device;\n if (state._capacity < capacity) {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._visibleMatrixBuffer = device.createBuffer({\n size: Math.max(capacity * 64, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._visibleColorBuffer = hasColor\n ? device.createBuffer({\n size: Math.max(capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n })\n : null;\n state._capacity = capacity;\n state._bindGroup = null;\n state._drawBuffers = null;\n } else if (hasColor && !state._visibleColorBuffer) {\n state._visibleColorBuffer = device.createBuffer({\n size: Math.max(state._capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._bindGroup = null;\n state._drawBuffers = null;\n }\n if (!state._argsBuffer) {\n state._argsBuffer = device.createBuffer({\n size: INDIRECT_ARGS_BYTES,\n usage: BU.INDIRECT | BU.STORAGE | BU.COPY_DST,\n });\n }\n if (!state._paramsBuffer) {\n state._paramsBuffer = device.createBuffer({\n size: PARAM_BYTES,\n usage: BU.UNIFORM | BU.COPY_DST,\n });\n }\n}\n\nfunction getCullPipeline(engine: EngineContext, hasColor: boolean): GPUComputePipeline {\n const device = engine._device;\n if (_cachedDevice !== device) {\n _cachedDevice = device;\n _pipelineNoColor = null;\n _pipelineColor = null;\n }\n if (hasColor) {\n _pipelineColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_COLOR }), entryPoint: \"mainColor\" },\n });\n return _pipelineColor;\n }\n _pipelineNoColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_NO_COLOR }), entryPoint: \"main\" },\n });\n return _pipelineNoColor;\n}\n\nfunction writeCullParams(engine: EngineContext, state: ThinInstanceGpuCullState, mesh: Mesh, indexCount: number, instanceCount: number, camera: Camera, aspect: number): void {\n const params = state._paramsF32;\n const viewProjection = getViewProjectionMatrix(camera, aspect);\n writeFrustumPlanes(params, viewProjection);\n params.set(mesh.worldMatrix, MESH_WORLD_FLOAT_OFFSET);\n params.set(state._localSphere, LOCAL_SPHERE_FLOAT_OFFSET);\n state._paramsU32[COUNT_U32_OFFSET] = instanceCount;\n params[BOUNDS_PAD_F32_OFFSET] = mesh.thinInstances?._cullBoundsPad ?? 0;\n\n const args = state._argsData;\n args[0] = indexCount;\n args[1] = 0;\n args[2] = 0;\n args[3] = 0;\n args[4] = 0;\n\n engine._device.queue.writeBuffer(state._argsBuffer!, 0, args.buffer, args.byteOffset, args.byteLength);\n engine._device.queue.writeBuffer(state._paramsBuffer!, 0, state._paramsBytes);\n}\n\nfunction writeFrustumPlanes(out: Float32Array, m: Mat4): void {\n writePlane(out, 0, m[3]! + m[0]!, m[7]! + m[4]!, m[11]! + m[8]!, m[15]! + m[12]!);\n writePlane(out, 4, m[3]! - m[0]!, m[7]! - m[4]!, m[11]! - m[8]!, m[15]! - m[12]!);\n writePlane(out, 8, m[3]! + m[1]!, m[7]! + m[5]!, m[11]! + m[9]!, m[15]! + m[13]!);\n writePlane(out, 12, m[3]! - m[1]!, m[7]! - m[5]!, m[11]! - m[9]!, m[15]! - m[13]!);\n writePlane(out, 16, m[2]!, m[6]!, m[10]!, m[14]!);\n writePlane(out, 20, m[3]! - m[2]!, m[7]! - m[6]!, m[11]! - m[10]!, m[15]! - m[14]!);\n}\n\nfunction writePlane(out: Float32Array, offset: number, x: number, y: number, z: number, w: number): void {\n const invLen = 1 / Math.hypot(x, y, z);\n out[offset] = x * invLen;\n out[offset + 1] = y * invLen;\n out[offset + 2] = z * invLen;\n out[offset + 3] = w * invLen;\n}\n\nfunction computeLocalSphere(mesh: Mesh, out: Float32Array): boolean {\n const positions = mesh._cpuPositions;\n if (!positions || positions.length < 3) {\n return false;\n }\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let i = 0; i < positions.length; i += 3) {\n const x = positions[i]!;\n const y = positions[i + 1]!;\n const z = positions[i + 2]!;\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n if (!isFinite(minX)) {\n return false;\n }\n const cx = (minX + maxX) * 0.5;\n const cy = (minY + maxY) * 0.5;\n const cz = (minZ + maxZ) * 0.5;\n const dx = maxX - cx;\n const dy = maxY - cy;\n const dz = maxZ - cz;\n out[0] = cx;\n out[1] = cy;\n out[2] = cz;\n out[3] = Math.hypot(dx, dy, dz);\n return true;\n}\n"],"names":[],"mappings":"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"}
@@ -135,6 +135,13 @@ function enableThinInstanceGpuCulling(mesh, enabled = true) {
135
135
  ti._gpuVersion = -1;
136
136
  ti._colorGpuVersion = -1;
137
137
  }
138
+ function setThinInstanceCullBoundsPad(mesh, pad) {
139
+ const ti = mesh.thinInstances;
140
+ if (!ti) {
141
+ throw new Error("setThinInstanceCullBoundsPad requires mesh.thinInstances");
142
+ }
143
+ ti._cullBoundsPad = pad;
144
+ }
138
145
 
139
- export { addThinInstance, enableThinInstanceGpuCulling, flushThinInstances, removeThinInstance, setThinInstanceColor, setThinInstanceColors, setThinInstanceCount, setThinInstanceMatrix, setThinInstances };
146
+ export { addThinInstance, enableThinInstanceGpuCulling, flushThinInstances, removeThinInstance, setThinInstanceColor, setThinInstanceColors, setThinInstanceCount, setThinInstanceCullBoundsPad, setThinInstanceMatrix, setThinInstances };
140
147
  //# sourceMappingURL=thin-instance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thin-instance.js","sources":["../../../src/mesh/thin-instance.ts"],"sourcesContent":["/** Thin instances — CPU-side data for hardware-instanced rendering.\n * Each instance carries a world matrix (16 floats) and optionally a\n * per-instance color (4 floats). The render system creates and syncs\n * GPU buffers automatically via version tracking. */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"./mesh.js\";\n\n/** CPU-side data backing a thin-instanced mesh: world matrices, optional colors, and GPU sync state. */\nexport interface ThinInstanceData {\n /** CPU-side instance world matrices (16 floats per instance). Storage may\n * be Float32Array (default) or Float64Array (after an HPM engine is\n * constructed; the caller built the slab via `allocateMat4()`). The GPU\n * upload path in thin-instance-gpu.ts handles both (REQ-API-3, D5). */\n matrices: Float32Array | Float64Array;\n /** Active instance count. */\n count: number;\n /** @internal Allocated capacity (in instances). */\n _capacity: number;\n /** @internal Version counter — bumped by helpers, checked by render system. */\n _version: number;\n /** @internal GPU buffer — created and managed by render system, not user. */\n _gpuBuffer: GPUBuffer | null;\n /** @internal Whether the current matrix GPU buffer was created with STORAGE usage. */\n _gpuBufferStorage: boolean;\n /** @internal Last version uploaded to GPU. */\n _gpuVersion: number;\n\n /** @internal Min dirty instance index (inclusive). */\n _dirtyMin: number;\n /** @internal Max dirty instance index (exclusive). */\n _dirtyMax: number;\n\n /** Optional per-instance RGBA colors (4 floats per instance). */\n colors?: Float32Array | null;\n /** @internal Color version counter — independent of matrix version. */\n _colorVersion: number;\n /** @internal Min dirty color instance index (inclusive) — mirrors the matrix dirty range so\n * per-instance color updates (setThinInstanceColor) upload only the touched span. */\n _colorDirtyMin: number;\n /** @internal Max dirty color instance index (exclusive). */\n _colorDirtyMax: number;\n /** @internal GPU buffer for per-instance colors. */\n _colorGpuBuffer: GPUBuffer | null;\n /** @internal Whether the current color GPU buffer was created with STORAGE usage. */\n _colorGpuBufferStorage: boolean;\n /** @internal Last color version uploaded to GPU. */\n _colorGpuVersion: number;\n\n /** @internal Lazy per-mesh F32 upload scratch. Allocated by thin-instance-gpu.ts only\n * when `matrices` is F64-backed (HPM-on); F32-backed input takes a direct\n * writeBuffer fast-path. Sized in floats = `_capacity * 16`. */\n _uploadF32?: Float32Array;\n\n /** @internal Opt-in flag for GPU frustum culling + indirect drawing. */\n _gpuCullingEnabled: boolean;\n}\n\n/** Set all instances from a pre-built matrix array. */\nexport function setThinInstances(mesh: Mesh, matrices: Float32Array | Float64Array, count: number): void {\n if (!mesh.thinInstances) {\n mesh.thinInstances = {\n matrices,\n count,\n _capacity: count,\n _version: 1,\n _gpuBuffer: null,\n _gpuBufferStorage: false,\n _gpuVersion: 0,\n _dirtyMin: 0,\n _dirtyMax: count,\n _colorVersion: 0,\n _colorDirtyMin: 0,\n _colorDirtyMax: 0,\n _colorGpuBuffer: null,\n _colorGpuBufferStorage: false,\n _colorGpuVersion: 0,\n _gpuCullingEnabled: false,\n };\n } else {\n mesh.thinInstances.matrices = matrices;\n mesh.thinInstances.count = count;\n mesh.thinInstances._capacity = count;\n mesh.thinInstances._version++;\n mesh.thinInstances._dirtyMin = 0;\n mesh.thinInstances._dirtyMax = count;\n }\n}\n\n/** Update ONLY the active instance count (and re-upload the [0,count) matrix range), leaving `_capacity`\n * — and therefore the already-allocated GPU buffer — untouched. This is the way to vary how many instances\n * draw FRAME-TO-FRAME on an established thin-instanced mesh WITHOUT recreating the GPU buffer (which would\n * invalidate any cached render/shadow bundle that captured the old buffer handle). Pre-size the buffer once\n * with `setThinInstances(mesh, matrices, capacity)`, then call this each update with `count <= capacity`.\n * The draw reads `count` live, so the bundle stays valid. Caller must keep writing into the SAME `matrices`\n * array the mesh already references. No-op if the mesh isn't thin-instanced yet. */\nexport function setThinInstanceCount(mesh: Mesh, count: number): void {\n const ti = mesh.thinInstances;\n if (!ti) {\n return;\n }\n ti.count = count;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = count;\n}\n\n/** Add one instance. Returns its index. Grows capacity as needed. */\nexport function addThinInstance(mesh: Mesh, matrix: Mat4): number {\n const ti = mesh.thinInstances;\n if (!ti) {\n const capacity = 16;\n const matrices = new F32(capacity * 16);\n matrices.set(matrix, 0);\n mesh.thinInstances = {\n matrices,\n count: 1,\n _capacity: capacity,\n _version: 1,\n _gpuBuffer: null,\n _gpuBufferStorage: false,\n _gpuVersion: 0,\n _dirtyMin: 0,\n _dirtyMax: 1,\n _colorVersion: 0,\n _colorDirtyMin: 0,\n _colorDirtyMax: 0,\n _colorGpuBuffer: null,\n _colorGpuBufferStorage: false,\n _colorGpuVersion: 0,\n _gpuCullingEnabled: false,\n };\n return 0;\n }\n\n const index = ti.count;\n if (index >= ti._capacity) {\n const newCap = ti._capacity * 2;\n const newData = new F32(newCap * 16);\n newData.set(ti.matrices);\n ti.matrices = newData;\n ti._capacity = newCap;\n }\n\n ti.matrices.set(matrix, index * 16);\n ti.count++;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n return index;\n}\n\n/** Update one instance's matrix. */\nexport function setThinInstanceMatrix(mesh: Mesh, index: number, matrix: Mat4): void {\n const ti = mesh.thinInstances!;\n ti.matrices.set(matrix, index * 16);\n ti._version++;\n ti._dirtyMin = Math.min(ti._dirtyMin, index);\n ti._dirtyMax = Math.max(ti._dirtyMax, index + 1);\n}\n\n/** Remove instance by index. Swap-removes: last instance fills the gap. */\nexport function removeThinInstance(mesh: Mesh, index: number): void {\n const ti = mesh.thinInstances!;\n const last = ti.count - 1;\n if (index !== last) {\n ti.matrices.copyWithin(index * 16, last * 16, last * 16 + 16);\n }\n ti.count--;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n}\n\n/** Mark thin instance data dirty after direct array manipulation. */\nexport function flushThinInstances(mesh: Mesh): void {\n const ti = mesh.thinInstances!;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n}\n\n/** Set per-instance RGBA colors for a thin-instanced mesh. */\nexport function setThinInstanceColors(mesh: Mesh, colors: Float32Array): void {\n const ti = mesh.thinInstances!;\n ti.colors = colors;\n ti._colorVersion++;\n ti._colorDirtyMin = 0;\n ti._colorDirtyMax = ti.count;\n}\n\n/** Update ONE instance's RGBA color in place — the color twin of `setThinInstanceMatrix`. Only the\n * touched span re-uploads (dirty-range), so per-instance color churn (e.g. streamed instances carrying\n * per-slot animation timestamps) stays cheap on large pools. Requires colors to have been set via\n * `setThinInstanceColors` first. */\nexport function setThinInstanceColor(mesh: Mesh, index: number, r: number, g: number, b: number, a: number): void {\n const ti = mesh.thinInstances!;\n const c = ti.colors!;\n const o = index * 4;\n c[o] = r;\n c[o + 1] = g;\n c[o + 2] = b;\n c[o + 3] = a;\n ti._colorVersion++;\n ti._colorDirtyMin = Math.min(ti._colorDirtyMin, index);\n ti._colorDirtyMax = Math.max(ti._colorDirtyMax, index + 1);\n}\n\n/** Enable or disable GPU frustum culling for an existing thin-instanced mesh.\n *\n * Call this after `setThinInstances()`/`addThinInstance()` and before `registerScene()`.\n * The render system keeps the feature opt-in so non-culled thin-instance scenes do not\n * fetch the compute-culling module or allocate compacted visible-instance buffers.\n */\nexport function enableThinInstanceGpuCulling(mesh: Mesh, enabled = true): void {\n const ti = mesh.thinInstances;\n if (!ti) {\n throw new Error(\"enableThinInstanceGpuCulling requires mesh.thinInstances\");\n }\n if (ti._gpuCullingEnabled === enabled) {\n return;\n }\n ti._gpuCullingEnabled = enabled;\n ti._gpuVersion = -1;\n ti._colorGpuVersion = -1;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"thin-instance.js","sources":["../../../src/mesh/thin-instance.ts"],"sourcesContent":["/** Thin instances — CPU-side data for hardware-instanced rendering.\n * Each instance carries a world matrix (16 floats) and optionally a\n * per-instance color (4 floats). The render system creates and syncs\n * GPU buffers automatically via version tracking. */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"./mesh.js\";\n\n/** CPU-side data backing a thin-instanced mesh: world matrices, optional colors, and GPU sync state. */\nexport interface ThinInstanceData {\n /** CPU-side instance world matrices (16 floats per instance). Storage may\n * be Float32Array (default) or Float64Array (after an HPM engine is\n * constructed; the caller built the slab via `allocateMat4()`). The GPU\n * upload path in thin-instance-gpu.ts handles both (REQ-API-3, D5). */\n matrices: Float32Array | Float64Array;\n /** Active instance count. */\n count: number;\n /** @internal Allocated capacity (in instances). */\n _capacity: number;\n /** @internal Version counter — bumped by helpers, checked by render system. */\n _version: number;\n /** @internal GPU buffer — created and managed by render system, not user. */\n _gpuBuffer: GPUBuffer | null;\n /** @internal Whether the current matrix GPU buffer was created with STORAGE usage. */\n _gpuBufferStorage: boolean;\n /** @internal Last version uploaded to GPU. */\n _gpuVersion: number;\n\n /** @internal Min dirty instance index (inclusive). */\n _dirtyMin: number;\n /** @internal Max dirty instance index (exclusive). */\n _dirtyMax: number;\n\n /** Optional per-instance RGBA colors (4 floats per instance). */\n colors?: Float32Array | null;\n /** @internal Color version counter — independent of matrix version. */\n _colorVersion: number;\n /** @internal Min dirty color instance index (inclusive) — mirrors the matrix dirty range so\n * per-instance color updates (setThinInstanceColor) upload only the touched span. */\n _colorDirtyMin: number;\n /** @internal Max dirty color instance index (exclusive). */\n _colorDirtyMax: number;\n /** @internal GPU buffer for per-instance colors. */\n _colorGpuBuffer: GPUBuffer | null;\n /** @internal Whether the current color GPU buffer was created with STORAGE usage. */\n _colorGpuBufferStorage: boolean;\n /** @internal Last color version uploaded to GPU. */\n _colorGpuVersion: number;\n\n /** @internal Lazy per-mesh F32 upload scratch. Allocated by thin-instance-gpu.ts only\n * when `matrices` is F64-backed (HPM-on); F32-backed input takes a direct\n * writeBuffer fast-path. Sized in floats = `_capacity * 16`. */\n _uploadF32?: Float32Array;\n\n /** @internal Opt-in flag for GPU frustum culling + indirect drawing. */\n _gpuCullingEnabled: boolean;\n\n /** @internal Extra world-space radius added to every instance's culling sphere\n * (see `setThinInstanceCullBoundsPad`). Undefined reads as 0. */\n _cullBoundsPad?: number;\n}\n\n/** Set all instances from a pre-built matrix array. */\nexport function setThinInstances(mesh: Mesh, matrices: Float32Array | Float64Array, count: number): void {\n if (!mesh.thinInstances) {\n mesh.thinInstances = {\n matrices,\n count,\n _capacity: count,\n _version: 1,\n _gpuBuffer: null,\n _gpuBufferStorage: false,\n _gpuVersion: 0,\n _dirtyMin: 0,\n _dirtyMax: count,\n _colorVersion: 0,\n _colorDirtyMin: 0,\n _colorDirtyMax: 0,\n _colorGpuBuffer: null,\n _colorGpuBufferStorage: false,\n _colorGpuVersion: 0,\n _gpuCullingEnabled: false,\n };\n } else {\n mesh.thinInstances.matrices = matrices;\n mesh.thinInstances.count = count;\n mesh.thinInstances._capacity = count;\n mesh.thinInstances._version++;\n mesh.thinInstances._dirtyMin = 0;\n mesh.thinInstances._dirtyMax = count;\n }\n}\n\n/** Update ONLY the active instance count (and re-upload the [0,count) matrix range), leaving `_capacity`\n * — and therefore the already-allocated GPU buffer — untouched. This is the way to vary how many instances\n * draw FRAME-TO-FRAME on an established thin-instanced mesh WITHOUT recreating the GPU buffer (which would\n * invalidate any cached render/shadow bundle that captured the old buffer handle). Pre-size the buffer once\n * with `setThinInstances(mesh, matrices, capacity)`, then call this each update with `count <= capacity`.\n * The draw reads `count` live, so the bundle stays valid. Caller must keep writing into the SAME `matrices`\n * array the mesh already references. No-op if the mesh isn't thin-instanced yet. */\nexport function setThinInstanceCount(mesh: Mesh, count: number): void {\n const ti = mesh.thinInstances;\n if (!ti) {\n return;\n }\n ti.count = count;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = count;\n}\n\n/** Add one instance. Returns its index. Grows capacity as needed. */\nexport function addThinInstance(mesh: Mesh, matrix: Mat4): number {\n const ti = mesh.thinInstances;\n if (!ti) {\n const capacity = 16;\n const matrices = new F32(capacity * 16);\n matrices.set(matrix, 0);\n mesh.thinInstances = {\n matrices,\n count: 1,\n _capacity: capacity,\n _version: 1,\n _gpuBuffer: null,\n _gpuBufferStorage: false,\n _gpuVersion: 0,\n _dirtyMin: 0,\n _dirtyMax: 1,\n _colorVersion: 0,\n _colorDirtyMin: 0,\n _colorDirtyMax: 0,\n _colorGpuBuffer: null,\n _colorGpuBufferStorage: false,\n _colorGpuVersion: 0,\n _gpuCullingEnabled: false,\n };\n return 0;\n }\n\n const index = ti.count;\n if (index >= ti._capacity) {\n const newCap = ti._capacity * 2;\n const newData = new F32(newCap * 16);\n newData.set(ti.matrices);\n ti.matrices = newData;\n ti._capacity = newCap;\n }\n\n ti.matrices.set(matrix, index * 16);\n ti.count++;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n return index;\n}\n\n/** Update one instance's matrix. */\nexport function setThinInstanceMatrix(mesh: Mesh, index: number, matrix: Mat4): void {\n const ti = mesh.thinInstances!;\n ti.matrices.set(matrix, index * 16);\n ti._version++;\n ti._dirtyMin = Math.min(ti._dirtyMin, index);\n ti._dirtyMax = Math.max(ti._dirtyMax, index + 1);\n}\n\n/** Remove instance by index. Swap-removes: last instance fills the gap. */\nexport function removeThinInstance(mesh: Mesh, index: number): void {\n const ti = mesh.thinInstances!;\n const last = ti.count - 1;\n if (index !== last) {\n ti.matrices.copyWithin(index * 16, last * 16, last * 16 + 16);\n }\n ti.count--;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n}\n\n/** Mark thin instance data dirty after direct array manipulation. */\nexport function flushThinInstances(mesh: Mesh): void {\n const ti = mesh.thinInstances!;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n}\n\n/** Set per-instance RGBA colors for a thin-instanced mesh. */\nexport function setThinInstanceColors(mesh: Mesh, colors: Float32Array): void {\n const ti = mesh.thinInstances!;\n ti.colors = colors;\n ti._colorVersion++;\n ti._colorDirtyMin = 0;\n ti._colorDirtyMax = ti.count;\n}\n\n/** Update ONE instance's RGBA color in place — the color twin of `setThinInstanceMatrix`. Only the\n * touched span re-uploads (dirty-range), so per-instance color churn (e.g. streamed instances carrying\n * per-slot animation timestamps) stays cheap on large pools. Requires colors to have been set via\n * `setThinInstanceColors` first. */\nexport function setThinInstanceColor(mesh: Mesh, index: number, r: number, g: number, b: number, a: number): void {\n const ti = mesh.thinInstances!;\n const c = ti.colors!;\n const o = index * 4;\n c[o] = r;\n c[o + 1] = g;\n c[o + 2] = b;\n c[o + 3] = a;\n ti._colorVersion++;\n ti._colorDirtyMin = Math.min(ti._colorDirtyMin, index);\n ti._colorDirtyMax = Math.max(ti._colorDirtyMax, index + 1);\n}\n\n/** Enable or disable GPU frustum culling for an existing thin-instanced mesh.\n *\n * Call this after `setThinInstances()`/`addThinInstance()` and before `registerScene()`.\n * The render system keeps the feature opt-in so non-culled thin-instance scenes do not\n * fetch the compute-culling module or allocate compacted visible-instance buffers.\n */\nexport function enableThinInstanceGpuCulling(mesh: Mesh, enabled = true): void {\n const ti = mesh.thinInstances;\n if (!ti) {\n throw new Error(\"enableThinInstanceGpuCulling requires mesh.thinInstances\");\n }\n if (ti._gpuCullingEnabled === enabled) {\n return;\n }\n ti._gpuCullingEnabled = enabled;\n ti._gpuVersion = -1;\n ti._colorGpuVersion = -1;\n}\n\n/** Set an extra WORLD-SPACE radius added to every instance's GPU-culling sphere.\n *\n * The culler derives each instance's sphere from the prototype's authored vertex bounds, so a\n * vertex shader that DISPLACES geometry beyond them — terrain-following height offsets, tall wind\n * sway, growth animations — can move a visible instance outside its sphere and pop it at the\n * screen edge. The usual workaround is disabling culling for the whole mesh; padding the sphere\n * by the maximum shader displacement instead keeps culling both correct and enabled.\n *\n * The pad is in world units, applied after per-instance scaling. 0 restores the exact authored\n * bounds. Takes effect on the next culled pass (the culler reads it when writing its per-pass\n * params), so it can be changed live.\n */\nexport function setThinInstanceCullBoundsPad(mesh: Mesh, pad: number): void {\n const ti = mesh.thinInstances;\n if (!ti) {\n throw new Error(\"setThinInstanceCullBoundsPad requires mesh.thinInstances\");\n }\n ti._cullBoundsPad = pad;\n}\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { addAgent, addBoxObstacle, addCylinderObstacle, agentGoto, computePath, createDebugNavMeshGeometry, createNavCrowd, createNavMesh, createNavMeshFromSources, createNavigationPluginAsync, disposeNavigationPlugin, findRandomPoint, findRandomPointAroundCircle, getAgentPosition, getAgentVelocity, getClosestPoint, getNavigationRandomSeed, raycast, removeObstacle, setNavigationRandomSeed, updateNavCrowd, updateNavMeshObstacles } from './navigation.js';
1
+ export { addAgent, addBoxObstacle, addCylinderObstacle, agentGoto, computePath, createDebugNavMeshGeometry, createNavCrowd, createNavMesh, createNavMeshFromSources, createNavigationPluginAsync, disposeNavigationPlugin, findClosestPointWithin, findRandomPoint, findRandomPointAroundCircle, getAgentPosition, getAgentVelocity, getClosestPoint, getNavigationRandomSeed, raycast, removeObstacle, setNavigationRandomSeed, updateNavCrowd, updateNavMeshObstacles } from './navigation.js';
2
2
  //# sourceMappingURL=index.js.map
@@ -277,6 +277,14 @@ function getClosestPoint(plugin, position) {
277
277
  const res = plugin._navMeshQuery.findClosestPoint(position, { halfExtents: _tmpHalfExtents });
278
278
  return { x: res.point.x, y: res.point.y, z: res.point.z };
279
279
  }
280
+ function findClosestPointWithin(plugin, position, halfExtents) {
281
+ _assertReady(plugin);
282
+ const res = plugin._navMeshQuery.findClosestPoint(position, { halfExtents });
283
+ if (!res.success) {
284
+ return null;
285
+ }
286
+ return { x: res.point.x, y: res.point.y, z: res.point.z };
287
+ }
280
288
  function computePath(plugin, start, end) {
281
289
  _assertReady(plugin);
282
290
  const q = plugin._navMeshQuery;
@@ -412,5 +420,5 @@ function _assertTileCache(plugin) {
412
420
  }
413
421
  }
414
422
 
415
- export { addAgent, addBoxObstacle, addCylinderObstacle, agentGoto, computePath, createDebugNavMeshGeometry, createNavCrowd, createNavMesh, createNavMeshFromSources, createNavigationPluginAsync, disposeNavigationPlugin, findRandomPoint, findRandomPointAroundCircle, getAgentPosition, getAgentVelocity, getClosestPoint, getNavigationRandomSeed, raycast, removeObstacle, setNavigationRandomSeed, updateNavCrowd, updateNavMeshObstacles };
423
+ export { addAgent, addBoxObstacle, addCylinderObstacle, agentGoto, computePath, createDebugNavMeshGeometry, createNavCrowd, createNavMesh, createNavMeshFromSources, createNavigationPluginAsync, disposeNavigationPlugin, findClosestPointWithin, findRandomPoint, findRandomPointAroundCircle, getAgentPosition, getAgentVelocity, getClosestPoint, getNavigationRandomSeed, raycast, removeObstacle, setNavigationRandomSeed, updateNavCrowd, updateNavMeshObstacles };
416
424
  //# sourceMappingURL=navigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sources":["../../../src/navigation/navigation.ts"],"sourcesContent":["/**\n * Recast Navigation V2 integration for Babylon Lite.\n *\n * Pure-state interfaces + standalone factory functions, matching Lite conventions.\n * The recast wasm is loaded lazily inside `createNavigationPluginAsync` so scenes\n * that do not use navigation pay zero bundle cost.\n *\n * Usage:\n * ```ts\n * const nav = await createNavigationPluginAsync();\n * createNavMesh(nav, [ground, sphere, box], params);\n * const debug = createDebugNavMeshGeometry(nav);\n * const closest = getClosestPoint(nav, { x, y, z });\n * const crowd = createNavCrowd(nav, 10, 0.1);\n * const idx = addAgent(crowd, spawnPos, agentParams);\n * updateNavCrowd(crowd, 1 / 60);\n * ```\n *\n * For obstacles (tile-cache navmesh):\n * ```ts\n * createNavMesh(nav, [...], { ..., maxObstacles: 32, tileSize: 32 });\n * const ref = addBoxObstacle(nav, { x, y, z }, { x: 1, y: 1, z: 1 }, angle);\n * removeObstacle(nav, ref);\n * ```\n *\n * For off-mesh connections:\n * ```ts\n * createNavMesh(nav, [...], { ..., offMeshConnections: [...] });\n * ```\n *\n * For raycast:\n * ```ts\n * const r = raycast(nav, start, end);\n * if (r.hit) console.log(r.hitPoint);\n * ```\n */\n\nimport { F32, U32 } from \"../engine/typed-arrays.js\";\nimport type { Vec3 } from \"../math/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\n\n// ─── Public types ────────────────────────────────────────────────────\n\n/** NavMesh build parameters (Recast solo / tiled / tile-cache navmesh config). */\nexport interface NavMeshParameters {\n cs?: number;\n ch?: number;\n walkableSlopeAngle?: number;\n walkableHeight?: number;\n walkableClimb?: number;\n walkableRadius?: number;\n maxEdgeLen?: number;\n maxSimplificationError?: number;\n minRegionArea?: number;\n mergeRegionArea?: number;\n maxVertsPerPoly?: number;\n detailSampleDist?: number;\n detailSampleMaxError?: number;\n /** Skip reversing winding when extracting positions (right-handed input). */\n doNotReverseIndices?: boolean;\n /** Tile size for tiled / tile-cache navmesh. Recommended 32-64 for tile cache. */\n tileSize?: number;\n /**\n * Maximum number of obstacles. If `> 0` the navmesh is built with a tile cache\n * so obstacles can be added/removed dynamically.\n */\n maxObstacles?: number;\n /** Expected layers per tile for tile-cache navmesh. Default 1. */\n expectedLayersPerTile?: number;\n /** Off-mesh connection segments (teleports) baked into the navmesh. */\n offMeshConnections?: OffMeshConnection[];\n /** Keep intermediates for debug visualization. */\n keepIntermediates?: boolean;\n}\n\n/** Off-mesh connection (teleport segment) baked into the navmesh. */\nexport interface OffMeshConnection {\n startPosition: Vec3;\n endPosition: Vec3;\n radius: number;\n bidirectional: boolean;\n /** @defaultValue 0 */\n area?: number;\n /** @defaultValue 1 */\n flags?: number;\n userId?: number;\n}\n\n/** Crowd agent parameters. */\nexport interface AgentParameters {\n radius: number;\n height: number;\n maxAcceleration: number;\n maxSpeed: number;\n collisionQueryRange: number;\n pathOptimizationRange: number;\n separationWeight: number;\n updateFlags?: number;\n obstacleAvoidanceType?: number;\n queryFilterType?: number;\n reachRadius?: number;\n}\n\n/** A single mesh source for navmesh construction. */\nexport interface NavMeshSource {\n positions: ArrayLike<number>;\n indices: ArrayLike<number>;\n}\n\n/** Pure-state handle for the navigation plugin. */\nexport interface NavigationPlugin {\n /** @internal */ readonly _recast: any;\n /** @internal */ readonly _generators: any;\n /** @internal */ _navMesh?: any;\n /** @internal */ _navMeshQuery?: any;\n /** @internal */ _tileCache?: any;\n}\n\n/** Opaque handle returned by `addBoxObstacle` / `addCylinderObstacle`. */\nexport interface ObstacleHandle {\n /** @internal */ readonly _obstacle: any;\n}\n\n/** Pure-state handle for a crowd. */\nexport interface NavCrowd {\n /** @internal */ readonly _plugin: NavigationPlugin;\n /** @internal */ readonly _crowd: any;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────\n\nlet _coreModule: any = null;\nlet _generatorsModule: any = null;\nlet _initPromise: Promise<void> | null = null;\n\nasync function _ensureRecast(locateFile?: (url: string) => string): Promise<{ core: any; gens: any }> {\n if (!_coreModule || !_generatorsModule) {\n if (!_initPromise) {\n _initPromise = (async () => {\n const core = await import(\"@recast-navigation/core\");\n const gens = await import(\"@recast-navigation/generators\");\n if (locateFile) {\n const wasmFactory = (await import(\"@recast-navigation/wasm/wasm\")).default;\n // core.init types impl as typeof Recast but calls it as impl() at runtime;\n // bind pre-fills locateFile and cast to satisfy the declaration.\n await core.init(wasmFactory.bind(null, { locateFile }) as typeof wasmFactory);\n } else {\n await core.init();\n }\n _coreModule = core;\n _generatorsModule = gens;\n })();\n }\n await _initPromise;\n }\n return { core: _coreModule, gens: _generatorsModule };\n}\n\n/**\n * Create a navigation plugin. Loads the Recast wasm internally on first call;\n * subsequent calls reuse the loaded module.\n *\n * Pass `locateFile` to serve the wasm from a public path instead of bundling\n * it inline — same pattern as `HavokPhysics({ locateFile: () => \"/HavokPhysics.wasm\" })`.\n *\n * @example\n * ```ts\n * const nav = await createNavigationPluginAsync({ locateFile: () => \"/recast-navigation.wasm\" });\n * ```\n */\nexport async function createNavigationPluginAsync(options?: { locateFile?: (url: string) => string }): Promise<NavigationPlugin> {\n const { core, gens } = await _ensureRecast(options?.locateFile);\n return {\n _recast: core,\n _generators: gens,\n };\n}\n\n/**\n * Release the native navmesh resources a plugin holds: the navmesh query, the navmesh, and the tile cache (if\n * one was built). These are Detour objects living on the wasm heap — they are NOT reclaimed by JS garbage\n * collection, so dropping the plugin reference alone leaks them. Call this when a navmesh is rebuilt or a\n * plugin is discarded. Idempotent and safe on a plugin that never built a navmesh.\n */\nexport function disposeNavigationPlugin(plugin: NavigationPlugin): void {\n const internal = plugin as { _navMesh?: any; _navMeshQuery?: any; _tileCache?: any };\n internal._navMeshQuery?.destroy?.();\n internal._tileCache?.destroy?.();\n internal._navMesh?.destroy?.();\n internal._navMeshQuery = undefined;\n internal._tileCache = undefined;\n internal._navMesh = undefined;\n}\n\n// ─── NavMesh ─────────────────────────────────────────────────────────\n\n/**\n * Build a navmesh from one or more meshes. Each mesh's CPU positions are\n * transformed by its worldMatrix (matching BJS GetPositionsAndIndices), merged\n * into a single stream, and index winding is reversed (left-handed convention)\n * unless `doNotReverseIndices` is set.\n *\n * - Solo navmesh by default.\n * - If `maxObstacles > 0`, builds a tile-cache navmesh so obstacles can be\n * added/removed dynamically.\n * - Off-mesh connections can be supplied for either solo or tile-cache.\n */\nexport function createNavMesh(plugin: NavigationPlugin, meshes: Mesh[], params: NavMeshParameters): void {\n const { positions, indices } = _mergeMeshes(meshes, params.doNotReverseIndices === true);\n _createNavMeshFromMerged(plugin, positions, indices, params);\n}\n\n/** Build a navmesh from raw CPU geometry sources. This is the non-rendering twin of\n * `createNavMesh`: callers that already own procedural navigation geometry can avoid\n * creating hidden GPU meshes just to feed Recast. */\nexport function createNavMeshFromSources(plugin: NavigationPlugin, sources: NavMeshSource[], params: NavMeshParameters): void {\n const { positions, indices } = _mergeSources(sources, params.doNotReverseIndices === true);\n _createNavMeshFromMerged(plugin, positions, indices, params);\n}\n\nfunction _createNavMeshFromMerged(plugin: NavigationPlugin, positions: Float32Array, indices: Uint32Array, params: NavMeshParameters): void {\n const cfg: Record<string, unknown> = {};\n if (params.cs !== undefined) {\n cfg.cs = params.cs;\n }\n if (params.ch !== undefined) {\n cfg.ch = params.ch;\n }\n if (params.walkableSlopeAngle !== undefined) {\n cfg.walkableSlopeAngle = params.walkableSlopeAngle;\n }\n if (params.walkableHeight !== undefined) {\n cfg.walkableHeight = params.walkableHeight;\n }\n if (params.walkableClimb !== undefined) {\n cfg.walkableClimb = params.walkableClimb;\n }\n if (params.walkableRadius !== undefined) {\n cfg.walkableRadius = params.walkableRadius;\n }\n if (params.maxEdgeLen !== undefined) {\n cfg.maxEdgeLen = params.maxEdgeLen;\n }\n if (params.maxSimplificationError !== undefined) {\n cfg.maxSimplificationError = params.maxSimplificationError;\n }\n if (params.minRegionArea !== undefined) {\n cfg.minRegionArea = params.minRegionArea;\n }\n if (params.mergeRegionArea !== undefined) {\n cfg.mergeRegionArea = params.mergeRegionArea;\n }\n if (params.maxVertsPerPoly !== undefined) {\n cfg.maxVertsPerPoly = params.maxVertsPerPoly;\n }\n if (params.detailSampleDist !== undefined) {\n cfg.detailSampleDist = params.detailSampleDist;\n }\n if (params.detailSampleMaxError !== undefined) {\n cfg.detailSampleMaxError = params.detailSampleMaxError;\n }\n if (params.offMeshConnections !== undefined && params.offMeshConnections.length > 0) {\n cfg.offMeshConnections = params.offMeshConnections;\n }\n\n const internal = plugin as { _navMesh: any; _navMeshQuery: any; _tileCache?: any };\n const needsTileCache = (params.maxObstacles ?? 0) > 0;\n const needsTiled = (params.tileSize ?? 0) > 0;\n\n if (needsTileCache) {\n // Tile cache config: requires tileSize, expectedLayersPerTile, maxObstacles,\n // and a tile cache mesh process. Mirrors BJS Addons CreateTileCacheNavMeshConfig.\n cfg.tileSize = params.tileSize ?? 32;\n cfg.expectedLayersPerTile = params.expectedLayersPerTile ?? 1;\n cfg.maxObstacles = params.maxObstacles!;\n\n if (params.offMeshConnections !== undefined && params.offMeshConnections.length > 0) {\n cfg.tileCacheMeshProcess = _createDefaultTileCacheMeshProcess(plugin._recast, params.offMeshConnections);\n }\n\n const result = plugin._generators.generateTileCache(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh (tile cache) failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._tileCache = result.tileCache;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n return;\n }\n\n if (needsTiled) {\n cfg.tileSize = params.tileSize;\n const result = plugin._generators.generateTiledNavMesh(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh (tiled) failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n return;\n }\n\n const result = plugin._generators.generateSoloNavMesh(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n}\n\n/**\n * Default tile-cache mesh process that copies area/flags from input polys and\n * appends off-mesh connections. Mirrors BJS Addons CreateDefaultTileCacheMeshProcess.\n */\nfunction _createDefaultTileCacheMeshProcess(recast: any, offMeshConnections: OffMeshConnection[]): any {\n const area = 0;\n const flags = 1;\n return new recast.TileCacheMeshProcess((navMeshCreateParams: any, polyAreas: any, polyFlags: any) => {\n for (let i = 0; i < navMeshCreateParams.polyCount(); ++i) {\n polyAreas.set(i, area);\n polyFlags.set(i, flags);\n }\n if (offMeshConnections.length > 0) {\n navMeshCreateParams.setOffMeshConnections(offMeshConnections);\n }\n });\n}\n\nfunction _mergeMeshes(meshes: Mesh[], doNotReverseIndices: boolean): { positions: Float32Array; indices: Uint32Array } {\n let totalVerts = 0;\n let totalIdx = 0;\n for (const mesh of meshes) {\n if (!mesh._cpuPositions || !mesh._cpuIndices) {\n throw new Error(`Mesh \"${mesh.name}\" missing CPU geometry for navmesh`);\n }\n totalVerts += mesh._cpuPositions.length;\n totalIdx += mesh._cpuIndices.length;\n }\n const positions = new F32(totalVerts);\n const indices = new U32(totalIdx);\n\n let pOff = 0;\n let iOff = 0;\n let vertBase = 0;\n for (const mesh of meshes) {\n const src = mesh._cpuPositions!;\n const wm = mesh.worldMatrix;\n\n for (let i = 0; i < src.length; i += 3) {\n const x = src[i]!,\n y = src[i + 1]!,\n z = src[i + 2]!;\n positions[pOff++] = x * wm[0]! + y * wm[4]! + z * wm[8]! + wm[12]!;\n positions[pOff++] = x * wm[1]! + y * wm[5]! + z * wm[9]! + wm[13]!;\n positions[pOff++] = x * wm[2]! + y * wm[6]! + z * wm[10]! + wm[14]!;\n }\n\n const meshIdx = mesh._cpuIndices!;\n const n = meshIdx.length;\n if (doNotReverseIndices) {\n for (let i = 0; i < n; i++) {\n indices[iOff++] = meshIdx[i]! + vertBase;\n }\n } else {\n for (let i = 0; i < n; i += 3) {\n indices[iOff++] = meshIdx[i]! + vertBase;\n indices[iOff++] = meshIdx[i + 2]! + vertBase;\n indices[iOff++] = meshIdx[i + 1]! + vertBase;\n }\n }\n vertBase += src.length / 3;\n }\n\n return { positions, indices };\n}\n\nfunction _mergeSources(sources: NavMeshSource[], doNotReverseIndices: boolean): { positions: Float32Array; indices: Uint32Array } {\n let totalVerts = 0;\n let totalIdx = 0;\n for (const source of sources) {\n totalVerts += source.positions.length;\n totalIdx += source.indices.length;\n }\n const positions = new F32(totalVerts);\n const indices = new U32(totalIdx);\n\n let pOff = 0;\n let iOff = 0;\n let vertBase = 0;\n for (const source of sources) {\n for (let i = 0; i < source.positions.length; i++) {\n positions[pOff++] = source.positions[i]!;\n }\n if (doNotReverseIndices) {\n for (let i = 0; i < source.indices.length; i++) {\n indices[iOff++] = source.indices[i]! + vertBase;\n }\n } else {\n for (let i = 0; i < source.indices.length; i += 3) {\n indices[iOff++] = source.indices[i]! + vertBase;\n indices[iOff++] = source.indices[i + 2]! + vertBase;\n indices[iOff++] = source.indices[i + 1]! + vertBase;\n }\n }\n vertBase += source.positions.length / 3;\n }\n\n return { positions, indices };\n}\n\n// ─── Debug navmesh geometry ──────────────────────────────────────────\n\n/**\n * Extract debug visualization geometry from the generated navmesh.\n * Faces are detached (each triangle gets its own 3 vertices) and per-vertex\n * normals are set to the face normal — yielding flat shading without the need\n * for a separate normal-computation pass in callers.\n * Returns positions, normals, indices, and a hash of the positions for\n * cross-engine parity checks.\n */\nexport function createDebugNavMeshGeometry(plugin: NavigationPlugin): { positions: Float32Array; normals: Float32Array; indices: Uint32Array; positionsHash: number } {\n if (!plugin._navMesh) {\n throw new Error(\"No navmesh generated. Call createNavMesh first.\");\n }\n const [positionsArr, indicesArr] = plugin._recast.getNavMeshPositionsAndIndices(plugin._navMesh);\n const triCount = (indicesArr.length / 3) | 0;\n const vertCount = triCount * 3;\n const positions = new F32(vertCount * 3);\n const normals = new F32(vertCount * 3);\n const indices = new U32(vertCount);\n\n for (let t = 0; t < triCount; t++) {\n // Recast outputs triangles with original winding such that the face\n // normal computed from (i0,i1,i2) order points UP. We reverse the\n // stored winding to match BJS CreateDebugNavMesh for back-face culling\n // parity (stored as i0,i2,i1) — but compute the face normal from the\n // ORIGINAL winding so it still points UP.\n const i0 = indicesArr[t * 3]! * 3;\n const i1Orig = indicesArr[t * 3 + 1]! * 3;\n const i2Orig = indicesArr[t * 3 + 2]! * 3;\n\n const ax = positionsArr[i0]!,\n ay = positionsArr[i0 + 1]!,\n az = positionsArr[i0 + 2]!;\n const b1x = positionsArr[i1Orig]!,\n b1y = positionsArr[i1Orig + 1]!,\n b1z = positionsArr[i1Orig + 2]!;\n const c1x = positionsArr[i2Orig]!,\n c1y = positionsArr[i2Orig + 1]!,\n c1z = positionsArr[i2Orig + 2]!;\n\n const e1x = b1x - ax,\n e1y = b1y - ay,\n e1z = b1z - az;\n const e2x = c1x - ax,\n e2y = c1y - ay,\n e2z = c1z - az;\n let nx = e1y * e2z - e1z * e2y;\n let ny = e1z * e2x - e1x * e2z;\n let nz = e1x * e2y - e1y * e2x;\n const len = Math.hypot(nx, ny, nz);\n if (len > 0) {\n nx /= len;\n ny /= len;\n nz /= len;\n }\n\n // Store positions in reversed winding (i0, i2, i1) for back-face parity.\n const v = t * 9;\n positions[v] = ax;\n positions[v + 1] = ay;\n positions[v + 2] = az;\n positions[v + 3] = c1x;\n positions[v + 4] = c1y;\n positions[v + 5] = c1z;\n positions[v + 6] = b1x;\n positions[v + 7] = b1y;\n positions[v + 8] = b1z;\n\n normals[v] = nx;\n normals[v + 1] = ny;\n normals[v + 2] = nz;\n normals[v + 3] = nx;\n normals[v + 4] = ny;\n normals[v + 5] = nz;\n normals[v + 6] = nx;\n normals[v + 7] = ny;\n normals[v + 8] = nz;\n\n const idx = t * 3;\n indices[idx] = idx;\n indices[idx + 1] = idx + 1;\n indices[idx + 2] = idx + 2;\n }\n\n let hash = 0x811c9dc5;\n for (let i = 0; i < positions.length; i++) {\n hash ^= Math.round(positions[i]! * 100000);\n hash = Math.imul(hash, 0x01000193);\n }\n\n return { positions, normals, indices, positionsHash: hash };\n}\n\n// ─── Queries ─────────────────────────────────────────────────────────\n\nconst _tmpHalfExtents = { x: 1, y: 1, z: 1 };\n\n/** Snap a position to the closest point on the navmesh. */\nexport function getClosestPoint(plugin: NavigationPlugin, position: Vec3): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findClosestPoint(position, { halfExtents: _tmpHalfExtents });\n return { x: res.point.x, y: res.point.y, z: res.point.z };\n}\n\n/** Compute a path between two world positions, snapped to the navmesh. */\nexport function computePath(plugin: NavigationPlugin, start: Vec3, end: Vec3): Vec3[] {\n _assertReady(plugin);\n const q = plugin._navMeshQuery;\n const startSnap = q.findClosestPoint(start, { halfExtents: _tmpHalfExtents });\n const endSnap = q.findClosestPoint(end, { halfExtents: _tmpHalfExtents });\n const res = q.computePath(startSnap.point, endSnap.point);\n if (!res.success) {\n return [];\n }\n const out: Vec3[] = [];\n for (const p of res.path) {\n out.push({ x: p.x, y: p.y, z: p.z });\n }\n return out;\n}\n\nfunction _assertReady(plugin: NavigationPlugin): void {\n if (!plugin._navMesh || !plugin._navMeshQuery) {\n throw new Error(\"Navmesh not ready. Call createNavMesh first.\");\n }\n}\n\n// ─── Crowd ───────────────────────────────────────────────────────────\n\n/**\n * Create a crowd attached to the navmesh. The crowd is NOT auto-updated;\n * call `updateNavCrowd(crowd, dt)` each frame for full determinism.\n */\nexport function createNavCrowd(plugin: NavigationPlugin, maxAgents: number, maxAgentRadius: number): NavCrowd {\n _assertReady(plugin);\n const Crowd = plugin._recast.Crowd;\n const crowd = new Crowd(plugin._navMesh, { maxAgents, maxAgentRadius });\n return { _plugin: plugin, _crowd: crowd };\n}\n\n/** Add an agent to the crowd. Returns the agent index. */\nexport function addAgent(crowd: NavCrowd, position: Vec3, params: AgentParameters): number {\n const agentParams = {\n radius: params.radius,\n height: params.height,\n maxAcceleration: params.maxAcceleration,\n maxSpeed: params.maxSpeed,\n collisionQueryRange: params.collisionQueryRange,\n pathOptimizationRange: params.pathOptimizationRange,\n separationWeight: params.separationWeight,\n updateFlags: params.updateFlags ?? 7,\n obstacleAvoidanceType: params.obstacleAvoidanceType ?? 0,\n queryFilterType: params.queryFilterType ?? 0,\n userData: 0,\n };\n const agent = crowd._crowd.addAgent({ x: position.x, y: position.y, z: position.z }, agentParams);\n return agent.agentIndex;\n}\n\n/** Get the current world position of an agent. */\nexport function getAgentPosition(crowd: NavCrowd, index: number): Vec3 {\n const p = crowd._crowd.getAgent(index)?.position();\n return p ? { x: p.x, y: p.y, z: p.z } : { x: 0, y: 0, z: 0 };\n}\n\n/** Get the current world-space velocity of an agent. */\nexport function getAgentVelocity(crowd: NavCrowd, index: number): Vec3 {\n const v = crowd._crowd.getAgent(index)?.velocity();\n return v ? { x: v.x, y: v.y, z: v.z } : { x: 0, y: 0, z: 0 };\n}\n\n/** Request the agent to move toward a world target (constrained by navmesh). */\nexport function agentGoto(crowd: NavCrowd, index: number, destination: Vec3): void {\n crowd._crowd.getAgent(index)?.requestMoveTarget(destination);\n}\n\n/** Advance the crowd simulation by `dt` seconds. */\nexport function updateNavCrowd(crowd: NavCrowd, dt: number): void {\n crowd._crowd.update(dt);\n}\n\n// ─── Random queries ──────────────────────────────────────────────────\n\n/**\n * Return a random point on the navmesh inside a circle of `radius` around `position`.\n * Determinism: seeded by Recast's internal RNG; call `setNavigationRandomSeed`\n * to make results reproducible across runs.\n */\nexport function findRandomPointAroundCircle(plugin: NavigationPlugin, position: Vec3, radius: number): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findRandomPointAroundCircle(position, radius, { halfExtents: _tmpHalfExtents });\n return { x: res.randomPoint.x, y: res.randomPoint.y, z: res.randomPoint.z };\n}\n\n/** Return any random point on the navmesh. */\nexport function findRandomPoint(plugin: NavigationPlugin): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findRandomPoint();\n return { x: res.randomPoint.x, y: res.randomPoint.y, z: res.randomPoint.z };\n}\n\n/** Set the seed used by Recast's randomized queries (e.g. `findRandomPointAroundCircle`). */\nexport function setNavigationRandomSeed(plugin: NavigationPlugin, seed: number): void {\n plugin._recast.setRandomSeed(seed);\n}\n\n/** Get the current seed used by Recast's randomized queries. */\nexport function getNavigationRandomSeed(plugin: NavigationPlugin): number {\n return plugin._recast.getRandomSeed();\n}\n\n// ─── Raycast ────────────────────────────────────────────────────────\n\n/**\n * Cast a 'walkability' ray on the navmesh from `start` to `end`.\n * Matches BJS Addons semantics: `hit` is true only when `0 < t < 1` and\n * `hitPoint` is the linear interpolation between start and end at parameter t.\n *\n * Recast's raycast ignores the y component of the end position (2D check).\n */\nexport function raycast(plugin: NavigationPlugin, start: Vec3, end: Vec3): { hit: boolean; hitPoint?: Vec3 } {\n _assertReady(plugin);\n const q = plugin._navMeshQuery;\n const nearest = q.findNearestPoly(start, { halfExtents: _tmpHalfExtents });\n if (!nearest.success || nearest.nearestRef === 0) {\n return { hit: false };\n }\n const r = q.raycast(nearest.nearestRef, start, end);\n const t = r?.t ?? 0;\n if (!(t > 0 && t < 1)) {\n return { hit: false };\n }\n return {\n hit: true,\n hitPoint: {\n x: start.x + (end.x - start.x) * t,\n y: start.y + (end.y - start.y) * t,\n z: start.z + (end.z - start.z) * t,\n },\n };\n}\n\n// ─── Obstacles (tile-cache navmeshes only) ───────────────────────────\n\n/**\n * Add a box obstacle to a tile-cache navmesh. The navmesh must have been\n * built with `maxObstacles > 0`. The tile cache is fully updated before\n * returning (matching BJS Addons default behavior).\n *\n * @param halfExtents - box half-size on each axis\n * @param angle - rotation around the Y axis, in radians\n */\nexport function addBoxObstacle(plugin: NavigationPlugin, position: Vec3, halfExtents: Vec3, angle: number): ObstacleHandle | null {\n _assertTileCache(plugin);\n const r = plugin._tileCache.addBoxObstacle(position, halfExtents, angle);\n if (!r.success) {\n return null;\n }\n _waitForFullTileCacheUpdate(plugin);\n return { _obstacle: r.obstacle };\n}\n\n/**\n * Add a cylinder obstacle to a tile-cache navmesh.\n *\n * @param radius - cylinder radius\n * @param height - cylinder height\n */\nexport function addCylinderObstacle(plugin: NavigationPlugin, position: Vec3, radius: number, height: number): ObstacleHandle | null {\n _assertTileCache(plugin);\n const r = plugin._tileCache.addCylinderObstacle(position, radius, height);\n if (!r.success) {\n return null;\n }\n _waitForFullTileCacheUpdate(plugin);\n return { _obstacle: r.obstacle };\n}\n\n/** Remove an obstacle previously added by `addBoxObstacle` / `addCylinderObstacle`. */\nexport function removeObstacle(plugin: NavigationPlugin, obstacle: ObstacleHandle): void {\n _assertTileCache(plugin);\n plugin._tileCache.removeObstacle(obstacle._obstacle);\n _waitForFullTileCacheUpdate(plugin);\n}\n\n/** Run `tileCache.update()` until all pending obstacle requests are resolved. */\nexport function updateNavMeshObstacles(plugin: NavigationPlugin): void {\n _assertTileCache(plugin);\n _waitForFullTileCacheUpdate(plugin);\n}\n\nfunction _waitForFullTileCacheUpdate(plugin: NavigationPlugin): void {\n let upToDate = false;\n while (!upToDate) {\n const r = plugin._tileCache.update(plugin._navMesh);\n upToDate = r.upToDate;\n }\n}\n\nfunction _assertTileCache(plugin: NavigationPlugin): void {\n _assertReady(plugin);\n if (!plugin._tileCache) {\n throw new Error(\"Navmesh has no tile cache. Build with `maxObstacles > 0` to enable obstacles.\");\n }\n}\n"],"names":["result"],"mappings":"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"}
1
+ {"version":3,"file":"navigation.js","sources":["../../../src/navigation/navigation.ts"],"sourcesContent":["/**\n * Recast Navigation V2 integration for Babylon Lite.\n *\n * Pure-state interfaces + standalone factory functions, matching Lite conventions.\n * The recast wasm is loaded lazily inside `createNavigationPluginAsync` so scenes\n * that do not use navigation pay zero bundle cost.\n *\n * Usage:\n * ```ts\n * const nav = await createNavigationPluginAsync();\n * createNavMesh(nav, [ground, sphere, box], params);\n * const debug = createDebugNavMeshGeometry(nav);\n * const closest = getClosestPoint(nav, { x, y, z });\n * const crowd = createNavCrowd(nav, 10, 0.1);\n * const idx = addAgent(crowd, spawnPos, agentParams);\n * updateNavCrowd(crowd, 1 / 60);\n * ```\n *\n * For obstacles (tile-cache navmesh):\n * ```ts\n * createNavMesh(nav, [...], { ..., maxObstacles: 32, tileSize: 32 });\n * const ref = addBoxObstacle(nav, { x, y, z }, { x: 1, y: 1, z: 1 }, angle);\n * removeObstacle(nav, ref);\n * ```\n *\n * For off-mesh connections:\n * ```ts\n * createNavMesh(nav, [...], { ..., offMeshConnections: [...] });\n * ```\n *\n * For raycast:\n * ```ts\n * const r = raycast(nav, start, end);\n * if (r.hit) console.log(r.hitPoint);\n * ```\n */\n\nimport { F32, U32 } from \"../engine/typed-arrays.js\";\nimport type { Vec3 } from \"../math/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\n\n// ─── Public types ────────────────────────────────────────────────────\n\n/** NavMesh build parameters (Recast solo / tiled / tile-cache navmesh config). */\nexport interface NavMeshParameters {\n cs?: number;\n ch?: number;\n walkableSlopeAngle?: number;\n walkableHeight?: number;\n walkableClimb?: number;\n walkableRadius?: number;\n maxEdgeLen?: number;\n maxSimplificationError?: number;\n minRegionArea?: number;\n mergeRegionArea?: number;\n maxVertsPerPoly?: number;\n detailSampleDist?: number;\n detailSampleMaxError?: number;\n /** Skip reversing winding when extracting positions (right-handed input). */\n doNotReverseIndices?: boolean;\n /** Tile size for tiled / tile-cache navmesh. Recommended 32-64 for tile cache. */\n tileSize?: number;\n /**\n * Maximum number of obstacles. If `> 0` the navmesh is built with a tile cache\n * so obstacles can be added/removed dynamically.\n */\n maxObstacles?: number;\n /** Expected layers per tile for tile-cache navmesh. Default 1. */\n expectedLayersPerTile?: number;\n /** Off-mesh connection segments (teleports) baked into the navmesh. */\n offMeshConnections?: OffMeshConnection[];\n /** Keep intermediates for debug visualization. */\n keepIntermediates?: boolean;\n}\n\n/** Off-mesh connection (teleport segment) baked into the navmesh. */\nexport interface OffMeshConnection {\n startPosition: Vec3;\n endPosition: Vec3;\n radius: number;\n bidirectional: boolean;\n /** @defaultValue 0 */\n area?: number;\n /** @defaultValue 1 */\n flags?: number;\n userId?: number;\n}\n\n/** Crowd agent parameters. */\nexport interface AgentParameters {\n radius: number;\n height: number;\n maxAcceleration: number;\n maxSpeed: number;\n collisionQueryRange: number;\n pathOptimizationRange: number;\n separationWeight: number;\n updateFlags?: number;\n obstacleAvoidanceType?: number;\n queryFilterType?: number;\n reachRadius?: number;\n}\n\n/** A single mesh source for navmesh construction. */\nexport interface NavMeshSource {\n positions: ArrayLike<number>;\n indices: ArrayLike<number>;\n}\n\n/** Pure-state handle for the navigation plugin. */\nexport interface NavigationPlugin {\n /** @internal */ readonly _recast: any;\n /** @internal */ readonly _generators: any;\n /** @internal */ _navMesh?: any;\n /** @internal */ _navMeshQuery?: any;\n /** @internal */ _tileCache?: any;\n}\n\n/** Opaque handle returned by `addBoxObstacle` / `addCylinderObstacle`. */\nexport interface ObstacleHandle {\n /** @internal */ readonly _obstacle: any;\n}\n\n/** Pure-state handle for a crowd. */\nexport interface NavCrowd {\n /** @internal */ readonly _plugin: NavigationPlugin;\n /** @internal */ readonly _crowd: any;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────\n\nlet _coreModule: any = null;\nlet _generatorsModule: any = null;\nlet _initPromise: Promise<void> | null = null;\n\nasync function _ensureRecast(locateFile?: (url: string) => string): Promise<{ core: any; gens: any }> {\n if (!_coreModule || !_generatorsModule) {\n if (!_initPromise) {\n _initPromise = (async () => {\n const core = await import(\"@recast-navigation/core\");\n const gens = await import(\"@recast-navigation/generators\");\n if (locateFile) {\n const wasmFactory = (await import(\"@recast-navigation/wasm/wasm\")).default;\n // core.init types impl as typeof Recast but calls it as impl() at runtime;\n // bind pre-fills locateFile and cast to satisfy the declaration.\n await core.init(wasmFactory.bind(null, { locateFile }) as typeof wasmFactory);\n } else {\n await core.init();\n }\n _coreModule = core;\n _generatorsModule = gens;\n })();\n }\n await _initPromise;\n }\n return { core: _coreModule, gens: _generatorsModule };\n}\n\n/**\n * Create a navigation plugin. Loads the Recast wasm internally on first call;\n * subsequent calls reuse the loaded module.\n *\n * Pass `locateFile` to serve the wasm from a public path instead of bundling\n * it inline — same pattern as `HavokPhysics({ locateFile: () => \"/HavokPhysics.wasm\" })`.\n *\n * @example\n * ```ts\n * const nav = await createNavigationPluginAsync({ locateFile: () => \"/recast-navigation.wasm\" });\n * ```\n */\nexport async function createNavigationPluginAsync(options?: { locateFile?: (url: string) => string }): Promise<NavigationPlugin> {\n const { core, gens } = await _ensureRecast(options?.locateFile);\n return {\n _recast: core,\n _generators: gens,\n };\n}\n\n/**\n * Release the native navmesh resources a plugin holds: the navmesh query, the navmesh, and the tile cache (if\n * one was built). These are Detour objects living on the wasm heap — they are NOT reclaimed by JS garbage\n * collection, so dropping the plugin reference alone leaks them. Call this when a navmesh is rebuilt or a\n * plugin is discarded. Idempotent and safe on a plugin that never built a navmesh.\n */\nexport function disposeNavigationPlugin(plugin: NavigationPlugin): void {\n const internal = plugin as { _navMesh?: any; _navMeshQuery?: any; _tileCache?: any };\n internal._navMeshQuery?.destroy?.();\n internal._tileCache?.destroy?.();\n internal._navMesh?.destroy?.();\n internal._navMeshQuery = undefined;\n internal._tileCache = undefined;\n internal._navMesh = undefined;\n}\n\n// ─── NavMesh ─────────────────────────────────────────────────────────\n\n/**\n * Build a navmesh from one or more meshes. Each mesh's CPU positions are\n * transformed by its worldMatrix (matching BJS GetPositionsAndIndices), merged\n * into a single stream, and index winding is reversed (left-handed convention)\n * unless `doNotReverseIndices` is set.\n *\n * - Solo navmesh by default.\n * - If `maxObstacles > 0`, builds a tile-cache navmesh so obstacles can be\n * added/removed dynamically.\n * - Off-mesh connections can be supplied for either solo or tile-cache.\n */\nexport function createNavMesh(plugin: NavigationPlugin, meshes: Mesh[], params: NavMeshParameters): void {\n const { positions, indices } = _mergeMeshes(meshes, params.doNotReverseIndices === true);\n _createNavMeshFromMerged(plugin, positions, indices, params);\n}\n\n/** Build a navmesh from raw CPU geometry sources. This is the non-rendering twin of\n * `createNavMesh`: callers that already own procedural navigation geometry can avoid\n * creating hidden GPU meshes just to feed Recast. */\nexport function createNavMeshFromSources(plugin: NavigationPlugin, sources: NavMeshSource[], params: NavMeshParameters): void {\n const { positions, indices } = _mergeSources(sources, params.doNotReverseIndices === true);\n _createNavMeshFromMerged(plugin, positions, indices, params);\n}\n\nfunction _createNavMeshFromMerged(plugin: NavigationPlugin, positions: Float32Array, indices: Uint32Array, params: NavMeshParameters): void {\n const cfg: Record<string, unknown> = {};\n if (params.cs !== undefined) {\n cfg.cs = params.cs;\n }\n if (params.ch !== undefined) {\n cfg.ch = params.ch;\n }\n if (params.walkableSlopeAngle !== undefined) {\n cfg.walkableSlopeAngle = params.walkableSlopeAngle;\n }\n if (params.walkableHeight !== undefined) {\n cfg.walkableHeight = params.walkableHeight;\n }\n if (params.walkableClimb !== undefined) {\n cfg.walkableClimb = params.walkableClimb;\n }\n if (params.walkableRadius !== undefined) {\n cfg.walkableRadius = params.walkableRadius;\n }\n if (params.maxEdgeLen !== undefined) {\n cfg.maxEdgeLen = params.maxEdgeLen;\n }\n if (params.maxSimplificationError !== undefined) {\n cfg.maxSimplificationError = params.maxSimplificationError;\n }\n if (params.minRegionArea !== undefined) {\n cfg.minRegionArea = params.minRegionArea;\n }\n if (params.mergeRegionArea !== undefined) {\n cfg.mergeRegionArea = params.mergeRegionArea;\n }\n if (params.maxVertsPerPoly !== undefined) {\n cfg.maxVertsPerPoly = params.maxVertsPerPoly;\n }\n if (params.detailSampleDist !== undefined) {\n cfg.detailSampleDist = params.detailSampleDist;\n }\n if (params.detailSampleMaxError !== undefined) {\n cfg.detailSampleMaxError = params.detailSampleMaxError;\n }\n if (params.offMeshConnections !== undefined && params.offMeshConnections.length > 0) {\n cfg.offMeshConnections = params.offMeshConnections;\n }\n\n const internal = plugin as { _navMesh: any; _navMeshQuery: any; _tileCache?: any };\n const needsTileCache = (params.maxObstacles ?? 0) > 0;\n const needsTiled = (params.tileSize ?? 0) > 0;\n\n if (needsTileCache) {\n // Tile cache config: requires tileSize, expectedLayersPerTile, maxObstacles,\n // and a tile cache mesh process. Mirrors BJS Addons CreateTileCacheNavMeshConfig.\n cfg.tileSize = params.tileSize ?? 32;\n cfg.expectedLayersPerTile = params.expectedLayersPerTile ?? 1;\n cfg.maxObstacles = params.maxObstacles!;\n\n if (params.offMeshConnections !== undefined && params.offMeshConnections.length > 0) {\n cfg.tileCacheMeshProcess = _createDefaultTileCacheMeshProcess(plugin._recast, params.offMeshConnections);\n }\n\n const result = plugin._generators.generateTileCache(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh (tile cache) failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._tileCache = result.tileCache;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n return;\n }\n\n if (needsTiled) {\n cfg.tileSize = params.tileSize;\n const result = plugin._generators.generateTiledNavMesh(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh (tiled) failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n return;\n }\n\n const result = plugin._generators.generateSoloNavMesh(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n}\n\n/**\n * Default tile-cache mesh process that copies area/flags from input polys and\n * appends off-mesh connections. Mirrors BJS Addons CreateDefaultTileCacheMeshProcess.\n */\nfunction _createDefaultTileCacheMeshProcess(recast: any, offMeshConnections: OffMeshConnection[]): any {\n const area = 0;\n const flags = 1;\n return new recast.TileCacheMeshProcess((navMeshCreateParams: any, polyAreas: any, polyFlags: any) => {\n for (let i = 0; i < navMeshCreateParams.polyCount(); ++i) {\n polyAreas.set(i, area);\n polyFlags.set(i, flags);\n }\n if (offMeshConnections.length > 0) {\n navMeshCreateParams.setOffMeshConnections(offMeshConnections);\n }\n });\n}\n\nfunction _mergeMeshes(meshes: Mesh[], doNotReverseIndices: boolean): { positions: Float32Array; indices: Uint32Array } {\n let totalVerts = 0;\n let totalIdx = 0;\n for (const mesh of meshes) {\n if (!mesh._cpuPositions || !mesh._cpuIndices) {\n throw new Error(`Mesh \"${mesh.name}\" missing CPU geometry for navmesh`);\n }\n totalVerts += mesh._cpuPositions.length;\n totalIdx += mesh._cpuIndices.length;\n }\n const positions = new F32(totalVerts);\n const indices = new U32(totalIdx);\n\n let pOff = 0;\n let iOff = 0;\n let vertBase = 0;\n for (const mesh of meshes) {\n const src = mesh._cpuPositions!;\n const wm = mesh.worldMatrix;\n\n for (let i = 0; i < src.length; i += 3) {\n const x = src[i]!,\n y = src[i + 1]!,\n z = src[i + 2]!;\n positions[pOff++] = x * wm[0]! + y * wm[4]! + z * wm[8]! + wm[12]!;\n positions[pOff++] = x * wm[1]! + y * wm[5]! + z * wm[9]! + wm[13]!;\n positions[pOff++] = x * wm[2]! + y * wm[6]! + z * wm[10]! + wm[14]!;\n }\n\n const meshIdx = mesh._cpuIndices!;\n const n = meshIdx.length;\n if (doNotReverseIndices) {\n for (let i = 0; i < n; i++) {\n indices[iOff++] = meshIdx[i]! + vertBase;\n }\n } else {\n for (let i = 0; i < n; i += 3) {\n indices[iOff++] = meshIdx[i]! + vertBase;\n indices[iOff++] = meshIdx[i + 2]! + vertBase;\n indices[iOff++] = meshIdx[i + 1]! + vertBase;\n }\n }\n vertBase += src.length / 3;\n }\n\n return { positions, indices };\n}\n\nfunction _mergeSources(sources: NavMeshSource[], doNotReverseIndices: boolean): { positions: Float32Array; indices: Uint32Array } {\n let totalVerts = 0;\n let totalIdx = 0;\n for (const source of sources) {\n totalVerts += source.positions.length;\n totalIdx += source.indices.length;\n }\n const positions = new F32(totalVerts);\n const indices = new U32(totalIdx);\n\n let pOff = 0;\n let iOff = 0;\n let vertBase = 0;\n for (const source of sources) {\n for (let i = 0; i < source.positions.length; i++) {\n positions[pOff++] = source.positions[i]!;\n }\n if (doNotReverseIndices) {\n for (let i = 0; i < source.indices.length; i++) {\n indices[iOff++] = source.indices[i]! + vertBase;\n }\n } else {\n for (let i = 0; i < source.indices.length; i += 3) {\n indices[iOff++] = source.indices[i]! + vertBase;\n indices[iOff++] = source.indices[i + 2]! + vertBase;\n indices[iOff++] = source.indices[i + 1]! + vertBase;\n }\n }\n vertBase += source.positions.length / 3;\n }\n\n return { positions, indices };\n}\n\n// ─── Debug navmesh geometry ──────────────────────────────────────────\n\n/**\n * Extract debug visualization geometry from the generated navmesh.\n * Faces are detached (each triangle gets its own 3 vertices) and per-vertex\n * normals are set to the face normal — yielding flat shading without the need\n * for a separate normal-computation pass in callers.\n * Returns positions, normals, indices, and a hash of the positions for\n * cross-engine parity checks.\n */\nexport function createDebugNavMeshGeometry(plugin: NavigationPlugin): { positions: Float32Array; normals: Float32Array; indices: Uint32Array; positionsHash: number } {\n if (!plugin._navMesh) {\n throw new Error(\"No navmesh generated. Call createNavMesh first.\");\n }\n const [positionsArr, indicesArr] = plugin._recast.getNavMeshPositionsAndIndices(plugin._navMesh);\n const triCount = (indicesArr.length / 3) | 0;\n const vertCount = triCount * 3;\n const positions = new F32(vertCount * 3);\n const normals = new F32(vertCount * 3);\n const indices = new U32(vertCount);\n\n for (let t = 0; t < triCount; t++) {\n // Recast outputs triangles with original winding such that the face\n // normal computed from (i0,i1,i2) order points UP. We reverse the\n // stored winding to match BJS CreateDebugNavMesh for back-face culling\n // parity (stored as i0,i2,i1) — but compute the face normal from the\n // ORIGINAL winding so it still points UP.\n const i0 = indicesArr[t * 3]! * 3;\n const i1Orig = indicesArr[t * 3 + 1]! * 3;\n const i2Orig = indicesArr[t * 3 + 2]! * 3;\n\n const ax = positionsArr[i0]!,\n ay = positionsArr[i0 + 1]!,\n az = positionsArr[i0 + 2]!;\n const b1x = positionsArr[i1Orig]!,\n b1y = positionsArr[i1Orig + 1]!,\n b1z = positionsArr[i1Orig + 2]!;\n const c1x = positionsArr[i2Orig]!,\n c1y = positionsArr[i2Orig + 1]!,\n c1z = positionsArr[i2Orig + 2]!;\n\n const e1x = b1x - ax,\n e1y = b1y - ay,\n e1z = b1z - az;\n const e2x = c1x - ax,\n e2y = c1y - ay,\n e2z = c1z - az;\n let nx = e1y * e2z - e1z * e2y;\n let ny = e1z * e2x - e1x * e2z;\n let nz = e1x * e2y - e1y * e2x;\n const len = Math.hypot(nx, ny, nz);\n if (len > 0) {\n nx /= len;\n ny /= len;\n nz /= len;\n }\n\n // Store positions in reversed winding (i0, i2, i1) for back-face parity.\n const v = t * 9;\n positions[v] = ax;\n positions[v + 1] = ay;\n positions[v + 2] = az;\n positions[v + 3] = c1x;\n positions[v + 4] = c1y;\n positions[v + 5] = c1z;\n positions[v + 6] = b1x;\n positions[v + 7] = b1y;\n positions[v + 8] = b1z;\n\n normals[v] = nx;\n normals[v + 1] = ny;\n normals[v + 2] = nz;\n normals[v + 3] = nx;\n normals[v + 4] = ny;\n normals[v + 5] = nz;\n normals[v + 6] = nx;\n normals[v + 7] = ny;\n normals[v + 8] = nz;\n\n const idx = t * 3;\n indices[idx] = idx;\n indices[idx + 1] = idx + 1;\n indices[idx + 2] = idx + 2;\n }\n\n let hash = 0x811c9dc5;\n for (let i = 0; i < positions.length; i++) {\n hash ^= Math.round(positions[i]! * 100000);\n hash = Math.imul(hash, 0x01000193);\n }\n\n return { positions, normals, indices, positionsHash: hash };\n}\n\n// ─── Queries ─────────────────────────────────────────────────────────\n\nconst _tmpHalfExtents = { x: 1, y: 1, z: 1 };\n\n/** Snap a position to the closest point on the navmesh. */\nexport function getClosestPoint(plugin: NavigationPlugin, position: Vec3): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findClosestPoint(position, { halfExtents: _tmpHalfExtents });\n return { x: res.point.x, y: res.point.y, z: res.point.z };\n}\n\n/** Snap a position to the closest point on the navmesh within a search box, or null when no part of the\n * mesh lies inside it. Unlike getClosestPoint — which does not inspect the query's success flag, so a\n * position outside its fixed ±1-unit box returns an UNSPECIFIED point (whatever the query left in its\n * output) rather than signalling a miss — the search extent is explicit here and a failed query is\n * reported as null, so callers can distinguish \"snapped\" from \"nothing nearby\". */\nexport function findClosestPointWithin(plugin: NavigationPlugin, position: Vec3, halfExtents: Vec3): Vec3 | null {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findClosestPoint(position, { halfExtents });\n if (!res.success) {\n return null;\n }\n return { x: res.point.x, y: res.point.y, z: res.point.z };\n}\n\n/** Compute a path between two world positions, snapped to the navmesh. */\nexport function computePath(plugin: NavigationPlugin, start: Vec3, end: Vec3): Vec3[] {\n _assertReady(plugin);\n const q = plugin._navMeshQuery;\n const startSnap = q.findClosestPoint(start, { halfExtents: _tmpHalfExtents });\n const endSnap = q.findClosestPoint(end, { halfExtents: _tmpHalfExtents });\n const res = q.computePath(startSnap.point, endSnap.point);\n if (!res.success) {\n return [];\n }\n const out: Vec3[] = [];\n for (const p of res.path) {\n out.push({ x: p.x, y: p.y, z: p.z });\n }\n return out;\n}\n\nfunction _assertReady(plugin: NavigationPlugin): void {\n if (!plugin._navMesh || !plugin._navMeshQuery) {\n throw new Error(\"Navmesh not ready. Call createNavMesh first.\");\n }\n}\n\n// ─── Crowd ───────────────────────────────────────────────────────────\n\n/**\n * Create a crowd attached to the navmesh. The crowd is NOT auto-updated;\n * call `updateNavCrowd(crowd, dt)` each frame for full determinism.\n */\nexport function createNavCrowd(plugin: NavigationPlugin, maxAgents: number, maxAgentRadius: number): NavCrowd {\n _assertReady(plugin);\n const Crowd = plugin._recast.Crowd;\n const crowd = new Crowd(plugin._navMesh, { maxAgents, maxAgentRadius });\n return { _plugin: plugin, _crowd: crowd };\n}\n\n/** Add an agent to the crowd. Returns the agent index. */\nexport function addAgent(crowd: NavCrowd, position: Vec3, params: AgentParameters): number {\n const agentParams = {\n radius: params.radius,\n height: params.height,\n maxAcceleration: params.maxAcceleration,\n maxSpeed: params.maxSpeed,\n collisionQueryRange: params.collisionQueryRange,\n pathOptimizationRange: params.pathOptimizationRange,\n separationWeight: params.separationWeight,\n updateFlags: params.updateFlags ?? 7,\n obstacleAvoidanceType: params.obstacleAvoidanceType ?? 0,\n queryFilterType: params.queryFilterType ?? 0,\n userData: 0,\n };\n const agent = crowd._crowd.addAgent({ x: position.x, y: position.y, z: position.z }, agentParams);\n return agent.agentIndex;\n}\n\n/** Get the current world position of an agent. */\nexport function getAgentPosition(crowd: NavCrowd, index: number): Vec3 {\n const p = crowd._crowd.getAgent(index)?.position();\n return p ? { x: p.x, y: p.y, z: p.z } : { x: 0, y: 0, z: 0 };\n}\n\n/** Get the current world-space velocity of an agent. */\nexport function getAgentVelocity(crowd: NavCrowd, index: number): Vec3 {\n const v = crowd._crowd.getAgent(index)?.velocity();\n return v ? { x: v.x, y: v.y, z: v.z } : { x: 0, y: 0, z: 0 };\n}\n\n/** Request the agent to move toward a world target (constrained by navmesh). */\nexport function agentGoto(crowd: NavCrowd, index: number, destination: Vec3): void {\n crowd._crowd.getAgent(index)?.requestMoveTarget(destination);\n}\n\n/** Advance the crowd simulation by `dt` seconds. */\nexport function updateNavCrowd(crowd: NavCrowd, dt: number): void {\n crowd._crowd.update(dt);\n}\n\n// ─── Random queries ──────────────────────────────────────────────────\n\n/**\n * Return a random point on the navmesh inside a circle of `radius` around `position`.\n * Determinism: seeded by Recast's internal RNG; call `setNavigationRandomSeed`\n * to make results reproducible across runs.\n */\nexport function findRandomPointAroundCircle(plugin: NavigationPlugin, position: Vec3, radius: number): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findRandomPointAroundCircle(position, radius, { halfExtents: _tmpHalfExtents });\n return { x: res.randomPoint.x, y: res.randomPoint.y, z: res.randomPoint.z };\n}\n\n/** Return any random point on the navmesh. */\nexport function findRandomPoint(plugin: NavigationPlugin): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findRandomPoint();\n return { x: res.randomPoint.x, y: res.randomPoint.y, z: res.randomPoint.z };\n}\n\n/** Set the seed used by Recast's randomized queries (e.g. `findRandomPointAroundCircle`). */\nexport function setNavigationRandomSeed(plugin: NavigationPlugin, seed: number): void {\n plugin._recast.setRandomSeed(seed);\n}\n\n/** Get the current seed used by Recast's randomized queries. */\nexport function getNavigationRandomSeed(plugin: NavigationPlugin): number {\n return plugin._recast.getRandomSeed();\n}\n\n// ─── Raycast ────────────────────────────────────────────────────────\n\n/**\n * Cast a 'walkability' ray on the navmesh from `start` to `end`.\n * Matches BJS Addons semantics: `hit` is true only when `0 < t < 1` and\n * `hitPoint` is the linear interpolation between start and end at parameter t.\n *\n * Recast's raycast ignores the y component of the end position (2D check).\n */\nexport function raycast(plugin: NavigationPlugin, start: Vec3, end: Vec3): { hit: boolean; hitPoint?: Vec3 } {\n _assertReady(plugin);\n const q = plugin._navMeshQuery;\n const nearest = q.findNearestPoly(start, { halfExtents: _tmpHalfExtents });\n if (!nearest.success || nearest.nearestRef === 0) {\n return { hit: false };\n }\n const r = q.raycast(nearest.nearestRef, start, end);\n const t = r?.t ?? 0;\n if (!(t > 0 && t < 1)) {\n return { hit: false };\n }\n return {\n hit: true,\n hitPoint: {\n x: start.x + (end.x - start.x) * t,\n y: start.y + (end.y - start.y) * t,\n z: start.z + (end.z - start.z) * t,\n },\n };\n}\n\n// ─── Obstacles (tile-cache navmeshes only) ───────────────────────────\n\n/**\n * Add a box obstacle to a tile-cache navmesh. The navmesh must have been\n * built with `maxObstacles > 0`. The tile cache is fully updated before\n * returning (matching BJS Addons default behavior).\n *\n * @param halfExtents - box half-size on each axis\n * @param angle - rotation around the Y axis, in radians\n */\nexport function addBoxObstacle(plugin: NavigationPlugin, position: Vec3, halfExtents: Vec3, angle: number): ObstacleHandle | null {\n _assertTileCache(plugin);\n const r = plugin._tileCache.addBoxObstacle(position, halfExtents, angle);\n if (!r.success) {\n return null;\n }\n _waitForFullTileCacheUpdate(plugin);\n return { _obstacle: r.obstacle };\n}\n\n/**\n * Add a cylinder obstacle to a tile-cache navmesh.\n *\n * @param radius - cylinder radius\n * @param height - cylinder height\n */\nexport function addCylinderObstacle(plugin: NavigationPlugin, position: Vec3, radius: number, height: number): ObstacleHandle | null {\n _assertTileCache(plugin);\n const r = plugin._tileCache.addCylinderObstacle(position, radius, height);\n if (!r.success) {\n return null;\n }\n _waitForFullTileCacheUpdate(plugin);\n return { _obstacle: r.obstacle };\n}\n\n/** Remove an obstacle previously added by `addBoxObstacle` / `addCylinderObstacle`. */\nexport function removeObstacle(plugin: NavigationPlugin, obstacle: ObstacleHandle): void {\n _assertTileCache(plugin);\n plugin._tileCache.removeObstacle(obstacle._obstacle);\n _waitForFullTileCacheUpdate(plugin);\n}\n\n/** Run `tileCache.update()` until all pending obstacle requests are resolved. */\nexport function updateNavMeshObstacles(plugin: NavigationPlugin): void {\n _assertTileCache(plugin);\n _waitForFullTileCacheUpdate(plugin);\n}\n\nfunction _waitForFullTileCacheUpdate(plugin: NavigationPlugin): void {\n let upToDate = false;\n while (!upToDate) {\n const r = plugin._tileCache.update(plugin._navMesh);\n upToDate = r.upToDate;\n }\n}\n\nfunction _assertTileCache(plugin: NavigationPlugin): void {\n _assertReady(plugin);\n if (!plugin._tileCache) {\n throw new Error(\"Navmesh has no tile cache. Build with `maxObstacles > 0` to enable obstacles.\");\n }\n}\n"],"names":["result"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { mat4Invert } from '../math/mat4-invert.js';
2
2
  import { createTransformNode } from '../scene/transform-node.js';
3
- import { createPhysicsShape, PhysicsShapeType, createPhysicsBody, PhysicsMotionType, setPhysicsBodyShape, setPhysicsBodyMassProperties, setPhysicsBodyPreStep, removePhysicsBody } from './havok.js';
3
+ import { createPhysicsShape, PhysicsShapeType, createPhysicsBody, PhysicsMotionType, setPhysicsBodyShape, setPhysicsBodyMassProperties, setPhysicsBodyPreStep, removePhysicsBody, worldStepSeconds } from './havok.js';
4
4
 
5
5
  var CharacterSupportedState = /* @__PURE__ */ ((CharacterSupportedState2) => {
6
6
  CharacterSupportedState2[CharacterSupportedState2["UNSUPPORTED"] = 0] = "UNSUPPORTED";
@@ -207,7 +207,7 @@ class PhysicsCharacterController {
207
207
  * @param displacement - Requested world-space displacement for this step.
208
208
  */
209
209
  moveWithCollisions(displacement) {
210
- const deltaTime = this._world._timestep;
210
+ const deltaTime = worldStepSeconds(this._world);
211
211
  if (!deltaTime || deltaTime <= 0) {
212
212
  return;
213
213
  }