@babylonjs/lite 1.7.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 (78) 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 +292 -277
  5. package/dist/index.js.map +1 -1
  6. package/index.d.ts +277 -11
  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/frame-graph-actions.js +10 -1
  29. package/lib/frame-graph/frame-graph-actions.js.map +1 -1
  30. package/lib/frame-graph/render-task.js +7 -0
  31. package/lib/frame-graph/render-task.js.map +1 -1
  32. package/lib/frame-graph/transmission-depth-grab.js +88 -0
  33. package/lib/frame-graph/transmission-depth-grab.js.map +1 -0
  34. package/lib/frame-graph/transmission.js +30 -1
  35. package/lib/frame-graph/transmission.js.map +1 -1
  36. package/lib/gizmo/bounding-box-gizmo.js +1 -1
  37. package/lib/index.js +8 -6
  38. package/lib/index.js.map +1 -1
  39. package/lib/loader-gltf/gltf-feature-gpu-instancing.js +1 -1
  40. package/lib/loader-gltf/gltf-interleave.js +1 -1
  41. package/lib/loader-gltf/load-gltf.js +1 -1
  42. package/lib/material/shader/shader-pipeline.js +1 -1
  43. package/lib/material/shader/shader-pipeline.js.map +1 -1
  44. package/lib/material/shader/shader-renderable.js +23 -8
  45. package/lib/material/shader/shader-renderable.js.map +1 -1
  46. package/lib/math/aabb.js +1 -1
  47. package/lib/math/compute-aabb.js +63 -1
  48. package/lib/math/compute-aabb.js.map +1 -1
  49. package/lib/math/index.js +1 -1
  50. package/lib/mesh/csg2.js +3 -2
  51. package/lib/mesh/csg2.js.map +1 -1
  52. package/lib/mesh/mesh-factories.js +1 -1
  53. package/lib/mesh/thin-instance-gpu-culling.js +4 -2
  54. package/lib/mesh/thin-instance-gpu-culling.js.map +1 -1
  55. package/lib/mesh/thin-instance.js +8 -1
  56. package/lib/mesh/thin-instance.js.map +1 -1
  57. package/lib/navigation/index.js +1 -1
  58. package/lib/navigation/navigation.js +9 -1
  59. package/lib/navigation/navigation.js.map +1 -1
  60. package/lib/physics/character-controller.js +2 -2
  61. package/lib/physics/character-controller.js.map +1 -1
  62. package/lib/physics/havok-floating-origin.js +2 -2
  63. package/lib/physics/havok-floating-origin.js.map +1 -1
  64. package/lib/physics/havok.js +40 -13
  65. package/lib/physics/havok.js.map +1 -1
  66. package/lib/picking/gpu-picker.js +16 -2
  67. package/lib/picking/gpu-picker.js.map +1 -1
  68. package/lib/scene/scene-core.js +9 -3
  69. package/lib/scene/scene-core.js.map +1 -1
  70. package/lib/scene/scene-remove.js +8 -0
  71. package/lib/scene/scene-remove.js.map +1 -1
  72. package/lib/texture/pixels-texture.js +31 -1
  73. package/lib/texture/pixels-texture.js.map +1 -1
  74. package/lib/vat/vat-baker.js +41 -2
  75. package/lib/vat/vat-baker.js.map +1 -1
  76. package/package.json +15 -3
  77. package/lib/_chunks/__vite-browser-external-BFTKbDcV.js +0 -68
  78. package/lib/_chunks/__vite-browser-external-BFTKbDcV.js.map +0 -1
@@ -1,4 +1,5 @@
1
1
  import { goToFrame, stopAnimation } from '../animation/animation-group.js';
2
+ import { mat4Invert } from '../math/mat4-invert.js';
2
3
  import { _registerPbrExt } from '../material/pbr/pbr-flags.js';
3
4
  import { pbrExt } from '../material/pbr/fragments/vat-fragment.js';
4
5
 
@@ -10,7 +11,7 @@ function clipFrameCount(group) {
10
11
  function bindingsOf(group) {
11
12
  return group._gltfMixer?.[2];
12
13
  }
13
- function bakeVat(engine, mesh, groups) {
14
+ function bakeVat(engine, mesh, groups, opts) {
14
15
  const skel = mesh.skeleton;
15
16
  if (!skel) {
16
17
  throw new Error("bakeVat: mesh has no skeleton to bake.");
@@ -25,17 +26,37 @@ function bakeVat(engine, mesh, groups) {
25
26
  frameCount = Math.max(1, frameCount);
26
27
  const data = new Float32Array(frameCount * floatsPerFrame);
27
28
  const clips = {};
29
+ const captureBones = opts?.captureBoneOrigins;
30
+ const boneOrigins = captureBones ? {} : void 0;
31
+ let restOrigins = null;
32
+ if (captureBones && boneOrigins) {
33
+ for (const b of captureBones) {
34
+ boneOrigins[b] = new Float32Array(frameCount * 3);
35
+ }
36
+ }
28
37
  let row = 0;
29
38
  for (const g of groups) {
30
39
  const frames = clipFrameCount(g);
31
40
  const fps = g.frameRate || DEFAULT_FRAME_RATE;
32
41
  clips[g.name] = { fromRow: row, frameCount: frames, fps };
33
42
  const binding = bindingsOf(g)?.[0];
43
+ if (captureBones && !restOrigins && binding) {
44
+ restOrigins = computeRestOrigins(captureBones, binding.inverseBindMatrices, boneCount);
45
+ }
34
46
  for (let f = 0; f < frames; f++) {
35
47
  goToFrame(g, f, engine);
36
48
  const m = binding?.boneMatrices;
37
49
  if (m) {
38
50
  data.set(m.subarray(0, floatsPerFrame), row * floatsPerFrame);
51
+ if (captureBones && boneOrigins && restOrigins) {
52
+ for (const b of captureBones) {
53
+ const o = restOrigins.get(b);
54
+ const dst = boneOrigins[b];
55
+ if (o && dst && b < boneCount) {
56
+ transformPointInto(dst, row * 3, m, b * 16, o[0], o[1], o[2]);
57
+ }
58
+ }
59
+ }
39
60
  }
40
61
  row++;
41
62
  }
@@ -48,7 +69,25 @@ function bakeVat(engine, mesh, groups) {
48
69
  usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST
49
70
  });
50
71
  device.queue.writeTexture({ texture }, data.buffer, { bytesPerRow: texWidth * 16, rowsPerImage: frameCount }, { width: texWidth, height: frameCount });
51
- return { texture, boneCount, frameCount, clips };
72
+ return boneOrigins ? { texture, boneCount, frameCount, clips, boneOrigins } : { texture, boneCount, frameCount, clips };
73
+ }
74
+ function computeRestOrigins(bones, ibm, boneCount) {
75
+ const out = /* @__PURE__ */ new Map();
76
+ for (const b of bones) {
77
+ if (b < 0 || b >= boneCount) {
78
+ continue;
79
+ }
80
+ const inv = mat4Invert(ibm.subarray(b * 16, b * 16 + 16));
81
+ if (inv) {
82
+ out.set(b, [inv[12], inv[13], inv[14]]);
83
+ }
84
+ }
85
+ return out;
86
+ }
87
+ function transformPointInto(dst, di, m, mo, px, py, pz) {
88
+ dst[di] = m[mo] * px + m[mo + 4] * py + m[mo + 8] * pz + m[mo + 12];
89
+ dst[di + 1] = m[mo + 1] * px + m[mo + 5] * py + m[mo + 9] * pz + m[mo + 13];
90
+ dst[di + 2] = m[mo + 2] * px + m[mo + 6] * py + m[mo + 10] * pz + m[mo + 14];
52
91
  }
53
92
  function attachVat(engine, mesh, baked, clip) {
54
93
  const skel = mesh.skeleton;
@@ -1 +1 @@
1
- {"version":3,"file":"vat-baker.js","sources":["../../../src/vat/vat-baker.ts"],"sourcesContent":["/**\n * VAT (Vertex Animation Texture) baker + runtime manager.\n *\n * Pre-evaluates a skinned mesh's skeletal animation on the CPU and stacks every frame's bone matrices\n * into ONE rgba32float texture (the per-row layout is identical to the live bone texture in\n * skeleton/create-skeleton.ts — 4 texels per bone — just `frameCount` rows tall). The mesh then renders\n * through the VAT vertex path (material/pbr/fragments/vat-fragment.ts), which reads bone matrices from the\n * baked texture at the current frame row instead of a live per-frame upload. With the CPU skeleton gone\n * the mesh can be GPU thin-instanced — each instance playing its own clip/frame.\n *\n * Mirrors the BJS VertexAnimationBaker / BakedVertexAnimationManager API shape, adapted to Lite/WebGPU.\n *\n * This module has ZERO module-level side effects and is only reached when a scene bakes a VAT, so it (and\n * the VAT shader fragment) cost nothing for scenes that don't use vertex animation.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { AnimationGroup } from \"../animation/animation-group.js\";\nimport { goToFrame, stopAnimation } from \"../animation/animation-group.js\";\nimport type { SkeletonBinding, VatData } from \"../animation/types.js\";\nimport { _registerPbrExt } from \"../material/pbr/pbr-flags.js\";\nimport { pbrExt as vatPbrExt } from \"../material/pbr/fragments/vat-fragment.js\";\n\n/** Where one clip landed in the baked texture: its first row, its frame count, and its native fps. */\nexport interface VatClip {\n readonly fromRow: number;\n readonly frameCount: number;\n readonly fps: number;\n}\n\n/** Result of baking — the GPU texture plus a per-clip row map for choosing playback params. */\nexport interface VatBakeResult {\n readonly texture: GPUTexture;\n readonly boneCount: number;\n readonly frameCount: number;\n /** Clip name → row range, for building the per-mesh/per-instance (fromRow,toRow,offset,fps) params. */\n readonly clips: Record<string, VatClip>;\n}\n\nconst DEFAULT_FRAME_RATE = 60;\n\n/** Number of baked frames for a clip (inclusive of frame 0). */\nfunction clipFrameCount(group: AnimationGroup): number {\n const fps = group.frameRate || DEFAULT_FRAME_RATE;\n return Math.max(1, Math.round(group.duration * fps) + 1);\n}\n\nfunction bindingsOf(group: AnimationGroup): readonly SkeletonBinding[] | undefined {\n return group._gltfMixer?.[2];\n}\n\n/**\n * Bake the given animation clips of a skinned mesh into a VAT texture. The clips are laid out as\n * contiguous row blocks (clip 0 first), one texture row per frame. The mesh must still have its live\n * `skeleton` at bake time (the bone matrices are read from it as each frame is evaluated).\n *\n * @param engine - Engine context.\n * @param mesh - The skinned source mesh (must have `mesh.skeleton`).\n * @param groups - The animation clips to bake (e.g. a creature's gait clips).\n */\nexport function bakeVat(engine: EngineContext, mesh: Mesh, groups: AnimationGroup[]): VatBakeResult {\n const skel = mesh.skeleton;\n if (!skel) {\n throw new Error(\"bakeVat: mesh has no skeleton to bake.\");\n }\n const boneCount = skel.boneCount;\n const texWidth = boneCount * 4; // 4 texels per bone (one mat4 column each), same as the live bone texture\n const floatsPerFrame = boneCount * 16;\n\n let frameCount = 0;\n for (const g of groups) {\n frameCount += clipFrameCount(g);\n }\n frameCount = Math.max(1, frameCount);\n\n const data = new Float32Array(frameCount * floatsPerFrame);\n const clips: Record<string, VatClip> = {};\n\n let row = 0;\n for (const g of groups) {\n const frames = clipFrameCount(g);\n const fps = g.frameRate || DEFAULT_FRAME_RATE;\n clips[g.name] = { fromRow: row, frameCount: frames, fps };\n const binding = bindingsOf(g)?.[0];\n for (let f = 0; f < frames; f++) {\n goToFrame(g, f, engine); // evaluates the pose → binding.boneMatrices holds this frame's matrices\n const m = binding?.boneMatrices;\n if (m) {\n data.set(m.subarray(0, floatsPerFrame), row * floatsPerFrame);\n }\n row++;\n }\n stopAnimation(g); // we never want this clip ticking live again — VAT replaces it\n }\n\n const device = engine._device;\n const texture = device.createTexture({\n size: [texWidth, frameCount],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture({ texture }, data.buffer, { bytesPerRow: texWidth * 16, rowsPerImage: frameCount }, { width: texWidth, height: frameCount });\n\n return { texture, boneCount, frameCount, clips };\n}\n\n/** Runtime VAT playback handle for one mesh (the analogue of BJS BakedVertexAnimationManager + the\n * per-mesh settings). Advance `update()` each frame; set the active clip with `play()`. */\nexport interface VatHandle {\n /** The mesh this drives (its `mesh.vat` is set). */\n readonly mesh: Mesh;\n /** Baked clip row map. */\n readonly clips: Record<string, VatClip>;\n /** Select the clip to play (by name) or set explicit playback params. */\n play(clip: string, opts?: { offset?: number; fps?: number }): void;\n /** Advance the animation clock by `dtSeconds` and upload it. */\n update(dtSeconds: number): void;\n /** Enable/refresh PER-INSTANCE VAT: upload one vec4 (fromRow, toRow, timeOffset, fps) per thin-instance,\n * so every instance plays its own clip + phase from the one shared baked texture (all instances in a\n * single draw call). `params.length` must be `4 * instanceCount`. Call this BEFORE registerScene the\n * first time — it sets `mesh.vat.instanceTexture`; a VAT mesh that is thin-instanced then takes the\n * per-instance vertex path. Later calls re-upload in place. Use `clips` to look up each clip's\n * fromRow/toRow/fps when building `params`. (Internally expanded to the dual-clip layout, blend 0.) */\n setInstances(params: Float32Array): void;\n /** PER-INSTANCE DUAL-CLIP VAT: like setInstances, but each instance carries TWO clips that are blended,\n * so gait cross-fades stay smooth. `params.length` must be `8 * instanceCount` — two vec4s per instance:\n * A = (fromRowA, toRowA, timeOffset, fpsA), B = (fromRowB, toRowB, blendWeight, fpsB), where blendWeight\n * in [0,1] lerps A→B and B reuses A's timeOffset. Same per-instance VAT path as setInstances. */\n setInstancesBlend(params: Float32Array): void;\n}\n\n/**\n * Attach a baked VAT to a mesh: builds the settings UBO, sets `mesh.vat` (reusing the skeleton's\n * joints/weights vertex buffers), and DROPS the live skeleton so it's no longer CPU-updated. Returns a\n * handle that advances the animation clock.\n *\n * @param engine - Engine context.\n * @param mesh - The mesh that was baked (still has `mesh.skeleton`).\n * @param baked - The result of `bakeVat`.\n * @param clip - Initial clip name to play (defaults to the first baked clip).\n */\nexport function attachVat(engine: EngineContext, mesh: Mesh, baked: VatBakeResult, clip?: string): VatHandle {\n const skel = mesh.skeleton;\n if (!skel) {\n throw new Error(\"attachVat: mesh has no skeleton (bake first, attach before clearing it).\");\n }\n // Self-register the VAT PBR extension into the global registry (mirrors enableMaterialPlugins): this\n // is what keeps non-VAT scenes byte-identical — the shared PBR renderable carries NO VAT-specific\n // code (no dynamic-import tuple), it just walks the generic ext registry, which this populates only\n // when a scene actually bakes + attaches a VAT. Idempotent (keyed by ext id).\n _registerPbrExt(vatPbrExt);\n const device = engine._device;\n // UBO: params vec4 (fromRow, toRow, frameOffset, fps) + clock vec4 (.x = seconds). 32 bytes.\n const settingsBuffer = device.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });\n const ubo = new Float32Array(8);\n\n const vat: VatData = {\n boneCount: baked.boneCount,\n texture: baked.texture,\n frameCount: baked.frameCount,\n settingsBuffer,\n jointsBuffer: skel.jointsBuffer,\n weightsBuffer: skel.weightsBuffer,\n joints1Buffer: skel.joints1Buffer,\n weights1Buffer: skel.weights1Buffer,\n };\n mesh.vat = vat;\n mesh.skeleton = null; // baked: no live skinning, no skeleton fragment, no per-frame bone upload\n\n let time = 0;\n let instanceTex: GPUTexture | null = null;\n let instanceTexCap = 0; // capacity in TEXELS (always 2 per instance — the dual-clip layout)\n const writeUbo = (): void => {\n device.queue.writeBuffer(settingsBuffer, 0, ubo.buffer, ubo.byteOffset, 32);\n };\n // Upload per-instance VAT params (TWO texels per instance — clip A then clip B) into a (texels x 1)\n // rgba32float texture the VAT vertex path reads by instance_index.\n const uploadInstances = (params: Float32Array): void => {\n const texels = Math.max(2, params.length >> 2); // 4 floats per texel\n if (!instanceTex || texels > instanceTexCap) {\n instanceTex?.destroy();\n instanceTex = device.createTexture({\n size: [texels, 1],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n instanceTexCap = texels;\n vat.instanceTexture = instanceTex;\n }\n device.queue.writeTexture({ texture: instanceTex }, params.buffer, { offset: params.byteOffset, bytesPerRow: texels * 16, rowsPerImage: 1 }, { width: texels, height: 1 });\n };\n const handle: VatHandle = {\n mesh,\n clips: baked.clips,\n play(name, opts) {\n const c = baked.clips[name];\n if (!c) {\n return;\n }\n ubo[0] = c.fromRow;\n ubo[1] = c.fromRow + c.frameCount - 1;\n ubo[2] = opts?.offset ?? 0;\n ubo[3] = opts?.fps ?? c.fps;\n writeUbo();\n },\n update(dt) {\n time += dt;\n ubo[4] = time;\n writeUbo();\n },\n setInstances(params) {\n // Single clip per instance (4 floats: fromRow,toRow,offset,fps) expanded to the dual-clip\n // layout (clip B == A, blend 0) so the one instanced shader variant renders it.\n const n = params.length >> 2;\n const dual = new Float32Array(n * 8);\n for (let i = 0; i < n; i++) {\n const s = i * 4;\n const o = i * 8;\n dual[o] = params[s]!;\n dual[o + 1] = params[s + 1]!;\n dual[o + 2] = params[s + 2]!;\n dual[o + 3] = params[s + 3]!;\n dual[o + 4] = params[s]!;\n dual[o + 5] = params[s + 1]!;\n dual[o + 6] = 0;\n dual[o + 7] = params[s + 3]!;\n }\n uploadInstances(dual);\n },\n setInstancesBlend(params) {\n uploadInstances(params);\n },\n };\n handle.play(clip ?? Object.keys(baked.clips)[0] ?? \"\");\n return handle;\n}\n"],"names":["vatPbrExt"],"mappings":";;;;AAwCA,MAAM,kBAAA,GAAqB,EAAA;AAG3B,SAAS,eAAe,KAAA,EAA+B;AACnD,EAAA,MAAM,GAAA,GAAM,MAAM,SAAA,IAAa,kBAAA;AAC/B,EAAA,OAAO,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,MAAM,KAAA,CAAM,QAAA,GAAW,GAAG,CAAA,GAAI,CAAC,CAAA;AAC3D;AAEA,SAAS,WAAW,KAAA,EAA+D;AAC/E,EAAA,OAAO,KAAA,CAAM,aAAa,CAAC,CAAA;AAC/B;AAWO,SAAS,OAAA,CAAQ,MAAA,EAAuB,IAAA,EAAY,MAAA,EAAyC;AAChG,EAAA,MAAM,OAAO,IAAA,CAAK,QAAA;AAClB,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,EAC5D;AACA,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,EAAA,MAAM,WAAW,SAAA,GAAY,CAAA;AAC7B,EAAA,MAAM,iBAAiB,SAAA,GAAY,EAAA;AAEnC,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACpB,IAAA,UAAA,IAAc,eAAe,CAAC,CAAA;AAAA,EAClC;AACA,EAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAA;AAEnC,EAAA,MAAM,IAAA,GAAO,IAAI,YAAA,CAAa,UAAA,GAAa,cAAc,CAAA;AACzD,EAAA,MAAM,QAAiC,EAAC;AAExC,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACpB,IAAA,MAAM,MAAA,GAAS,eAAe,CAAC,CAAA;AAC/B,IAAA,MAAM,GAAA,GAAM,EAAE,SAAA,IAAa,kBAAA;AAC3B,IAAA,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,EAAE,SAAS,GAAA,EAAK,UAAA,EAAY,QAAQ,GAAA,EAAI;AACxD,IAAA,MAAM,OAAA,GAAU,UAAA,CAAW,CAAC,CAAA,GAAI,CAAC,CAAA;AACjC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,CAAA,EAAA,EAAK;AAC7B,MAAA,SAAA,CAAU,CAAA,EAAG,GAAG,MAAM,CAAA;AACtB,MAAA,MAAM,IAAI,OAAA,EAAS,YAAA;AACnB,MAAA,IAAI,CAAA,EAAG;AACH,QAAA,IAAA,CAAK,IAAI,CAAA,CAAE,QAAA,CAAS,GAAG,cAAc,CAAA,EAAG,MAAM,cAAc,CAAA;AAAA,MAChE;AACA,MAAA,GAAA,EAAA;AAAA,IACJ;AACA,IAAA,aAAA,CAAc,CAAC,CAAA;AAAA,EACnB;AAEA,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,MAAM,OAAA,GAAU,OAAO,aAAA,CAAc;AAAA,IACjC,IAAA,EAAM,CAAC,QAAA,EAAU,UAAU,CAAA;AAAA,IAC3B,MAAA,EAAQ,aAAA;AAAA,IACR,KAAA,EAAO,eAAA,CAAgB,eAAA,GAAkB,eAAA,CAAgB;AAAA,GAC5D,CAAA;AACD,EAAA,MAAA,CAAO,MAAM,YAAA,CAAa,EAAE,SAAQ,EAAG,IAAA,CAAK,QAAQ,EAAE,WAAA,EAAa,WAAW,EAAA,EAAI,YAAA,EAAc,YAAW,EAAG,EAAE,OAAO,QAAA,EAAU,MAAA,EAAQ,YAAY,CAAA;AAErJ,EAAA,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,KAAA,EAAM;AACnD;AAqCO,SAAS,SAAA,CAAU,MAAA,EAAuB,IAAA,EAAY,KAAA,EAAsB,IAAA,EAA0B;AACzG,EAAA,MAAM,OAAO,IAAA,CAAK,QAAA;AAClB,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,MAAM,0EAA0E,CAAA;AAAA,EAC9F;AAKA,EAAA,eAAA,CAAgBA,MAAS,CAAA;AACzB,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AAEtB,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,YAAA,CAAa,EAAE,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,cAAA,CAAe,OAAA,GAAU,cAAA,CAAe,QAAA,EAAU,CAAA;AAChH,EAAA,MAAM,GAAA,GAAM,IAAI,YAAA,CAAa,CAAC,CAAA;AAE9B,EAAA,MAAM,GAAA,GAAe;AAAA,IACjB,WAAW,KAAA,CAAM,SAAA;AAAA,IACjB,SAAS,KAAA,CAAM,OAAA;AAAA,IACf,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,cAAA;AAAA,IACA,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,gBAAgB,IAAA,CAAK;AAAA,GACzB;AACA,EAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,EAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAEhB,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,WAAA,GAAiC,IAAA;AACrC,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,MAAM,WAAW,MAAY;AACzB,IAAA,MAAA,CAAO,KAAA,CAAM,YAAY,cAAA,EAAgB,CAAA,EAAG,IAAI,MAAA,EAAQ,GAAA,CAAI,YAAY,EAAE,CAAA;AAAA,EAC9E,CAAA;AAGA,EAAA,MAAM,eAAA,GAAkB,CAAC,MAAA,KAA+B;AACpD,IAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,UAAU,CAAC,CAAA;AAC7C,IAAA,IAAI,CAAC,WAAA,IAAe,MAAA,GAAS,cAAA,EAAgB;AACzC,MAAA,WAAA,EAAa,OAAA,EAAQ;AACrB,MAAA,WAAA,GAAc,OAAO,aAAA,CAAc;AAAA,QAC/B,IAAA,EAAM,CAAC,MAAA,EAAQ,CAAC,CAAA;AAAA,QAChB,MAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,eAAA,CAAgB,eAAA,GAAkB,eAAA,CAAgB;AAAA,OAC5D,CAAA;AACD,MAAA,cAAA,GAAiB,MAAA;AACjB,MAAA,GAAA,CAAI,eAAA,GAAkB,WAAA;AAAA,IAC1B;AACA,IAAA,MAAA,CAAO,KAAA,CAAM,aAAa,EAAE,OAAA,EAAS,aAAY,EAAG,MAAA,CAAO,MAAA,EAAQ,EAAE,MAAA,EAAQ,MAAA,CAAO,YAAY,WAAA,EAAa,MAAA,GAAS,EAAA,EAAI,YAAA,EAAc,CAAA,EAAE,EAAG,EAAE,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,CAAA,EAAG,CAAA;AAAA,EAC7K,CAAA;AACA,EAAA,MAAM,MAAA,GAAoB;AAAA,IACtB,IAAA;AAAA,IACA,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,IAAA,CAAK,MAAM,IAAA,EAAM;AACb,MAAA,MAAM,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAC1B,MAAA,IAAI,CAAC,CAAA,EAAG;AACJ,QAAA;AAAA,MACJ;AACA,MAAA,GAAA,CAAI,CAAC,IAAI,CAAA,CAAE,OAAA;AACX,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,CAAA,CAAE,OAAA,GAAU,EAAE,UAAA,GAAa,CAAA;AACpC,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,EAAM,MAAA,IAAU,CAAA;AACzB,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,EAAM,GAAA,IAAO,CAAA,CAAE,GAAA;AACxB,MAAA,QAAA,EAAS;AAAA,IACb,CAAA;AAAA,IACA,OAAO,EAAA,EAAI;AACP,MAAA,IAAA,IAAQ,EAAA;AACR,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA;AACT,MAAA,QAAA,EAAS;AAAA,IACb,CAAA;AAAA,IACA,aAAa,MAAA,EAAQ;AAGjB,MAAA,MAAM,CAAA,GAAI,OAAO,MAAA,IAAU,CAAA;AAC3B,MAAA,MAAM,IAAA,GAAO,IAAI,YAAA,CAAa,CAAA,GAAI,CAAC,CAAA;AACnC,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AACxB,QAAA,MAAM,IAAI,CAAA,GAAI,CAAA;AACd,QAAA,MAAM,IAAI,CAAA,GAAI,CAAA;AACd,QAAA,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AAClB,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAC1B,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAC1B,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAC1B,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACtB,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAC1B,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA;AACd,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,MAC9B;AACA,MAAA,eAAA,CAAgB,IAAI,CAAA;AAAA,IACxB,CAAA;AAAA,IACA,kBAAkB,MAAA,EAAQ;AACtB,MAAA,eAAA,CAAgB,MAAM,CAAA;AAAA,IAC1B;AAAA,GACJ;AACA,EAAA,MAAA,CAAO,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,KAAK,CAAA,CAAE,CAAC,CAAA,IAAK,EAAE,CAAA;AACrD,EAAA,OAAO,MAAA;AACX;;;;"}
1
+ {"version":3,"file":"vat-baker.js","sources":["../../../src/vat/vat-baker.ts"],"sourcesContent":["/**\n * VAT (Vertex Animation Texture) baker + runtime manager.\n *\n * Pre-evaluates a skinned mesh's skeletal animation on the CPU and stacks every frame's bone matrices\n * into ONE rgba32float texture (the per-row layout is identical to the live bone texture in\n * skeleton/create-skeleton.ts — 4 texels per bone — just `frameCount` rows tall). The mesh then renders\n * through the VAT vertex path (material/pbr/fragments/vat-fragment.ts), which reads bone matrices from the\n * baked texture at the current frame row instead of a live per-frame upload. With the CPU skeleton gone\n * the mesh can be GPU thin-instanced — each instance playing its own clip/frame.\n *\n * Mirrors the BJS VertexAnimationBaker / BakedVertexAnimationManager API shape, adapted to Lite/WebGPU.\n *\n * This module has ZERO module-level side effects and is only reached when a scene bakes a VAT, so it (and\n * the VAT shader fragment) cost nothing for scenes that don't use vertex animation.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { AnimationGroup } from \"../animation/animation-group.js\";\nimport { goToFrame, stopAnimation } from \"../animation/animation-group.js\";\nimport type { SkeletonBinding, VatData } from \"../animation/types.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport { _registerPbrExt } from \"../material/pbr/pbr-flags.js\";\nimport { pbrExt as vatPbrExt } from \"../material/pbr/fragments/vat-fragment.js\";\n\n/** Where one clip landed in the baked texture: its first row, its frame count, and its native fps. */\nexport interface VatClip {\n readonly fromRow: number;\n readonly frameCount: number;\n readonly fps: number;\n}\n\n/** Optional extras to capture while baking (nothing is captured unless requested). */\nexport interface VatBakeOptions {\n /** Bone indices whose posed ORIGIN should be sampled per baked frame (e.g. a hand joint for a held\n * item, a muzzle, an FX socket). Bone index = position in the skeleton's joint list = the bone's row\n * block in the baked texture. See {@link VatBakeResult.boneOrigins}. */\n readonly captureBoneOrigins?: readonly number[];\n}\n\n/** Result of baking — the GPU texture plus a per-clip row map for choosing playback params. */\nexport interface VatBakeResult {\n readonly texture: GPUTexture;\n readonly boneCount: number;\n readonly frameCount: number;\n /** Clip name → row range, for building the per-mesh/per-instance (fromRow,toRow,offset,fps) params. */\n readonly clips: Record<string, VatClip>;\n /** Present only when `captureBoneOrigins` was passed: bone index → the bone's posed origin per baked\n * frame, as `frameCount * 3` xyz floats (frame `row` at offset `row*3`, matching the texture rows /\n * `clips[].fromRow`). The point is in the mesh's SKIN output space — i.e. the space the VAT vertex path\n * produces before the `world` uniform — so a consumer gets world space with `instance · mesh.world · p`.\n * Lets a caller attach geometry to a moving joint (a carried prop, a socketed effect) without a live\n * skeleton. */\n readonly boneOrigins?: Record<number, Float32Array>;\n}\n\nconst DEFAULT_FRAME_RATE = 60;\n\n/** Number of baked frames for a clip (inclusive of frame 0). */\nfunction clipFrameCount(group: AnimationGroup): number {\n const fps = group.frameRate || DEFAULT_FRAME_RATE;\n return Math.max(1, Math.round(group.duration * fps) + 1);\n}\n\nfunction bindingsOf(group: AnimationGroup): readonly SkeletonBinding[] | undefined {\n return group._gltfMixer?.[2];\n}\n\n/**\n * Bake the given animation clips of a skinned mesh into a VAT texture. The clips are laid out as\n * contiguous row blocks (clip 0 first), one texture row per frame. The mesh must still have its live\n * `skeleton` at bake time (the bone matrices are read from it as each frame is evaluated).\n *\n * @param engine - Engine context.\n * @param mesh - The skinned source mesh (must have `mesh.skeleton`).\n * @param groups - The animation clips to bake (e.g. a creature's gait clips).\n * @param opts - Optional extras to capture during the bake (e.g. per-frame bone origins).\n */\nexport function bakeVat(engine: EngineContext, mesh: Mesh, groups: AnimationGroup[], opts?: VatBakeOptions): VatBakeResult {\n const skel = mesh.skeleton;\n if (!skel) {\n throw new Error(\"bakeVat: mesh has no skeleton to bake.\");\n }\n const boneCount = skel.boneCount;\n const texWidth = boneCount * 4; // 4 texels per bone (one mat4 column each), same as the live bone texture\n const floatsPerFrame = boneCount * 16;\n\n let frameCount = 0;\n for (const g of groups) {\n frameCount += clipFrameCount(g);\n }\n frameCount = Math.max(1, frameCount);\n\n const data = new Float32Array(frameCount * floatsPerFrame);\n const clips: Record<string, VatClip> = {};\n\n // Optional per-frame bone-origin capture. Each bone matrix Lite bakes is `invMeshWorld · jointWorld · IBM`\n // (skeleton-pose.ts), so a bone's posed origin in skin-output space is `boneMatrix · restOrigin`, where\n // `restOrigin = translation(inverse(IBM))`. We capture rest origins lazily from the first binding, then\n // transform them each frame — the result lines up with the texture rows.\n const captureBones = opts?.captureBoneOrigins;\n const boneOrigins: Record<number, Float32Array> | undefined = captureBones ? {} : undefined;\n let restOrigins: Map<number, [number, number, number]> | null = null;\n if (captureBones && boneOrigins) {\n for (const b of captureBones) {\n boneOrigins[b] = new Float32Array(frameCount * 3);\n }\n }\n\n let row = 0;\n for (const g of groups) {\n const frames = clipFrameCount(g);\n const fps = g.frameRate || DEFAULT_FRAME_RATE;\n clips[g.name] = { fromRow: row, frameCount: frames, fps };\n const binding = bindingsOf(g)?.[0];\n if (captureBones && !restOrigins && binding) {\n restOrigins = computeRestOrigins(captureBones, binding.inverseBindMatrices, boneCount);\n }\n for (let f = 0; f < frames; f++) {\n goToFrame(g, f, engine); // evaluates the pose → binding.boneMatrices holds this frame's matrices\n const m = binding?.boneMatrices;\n if (m) {\n data.set(m.subarray(0, floatsPerFrame), row * floatsPerFrame);\n if (captureBones && boneOrigins && restOrigins) {\n for (const b of captureBones) {\n const o = restOrigins.get(b);\n const dst = boneOrigins[b];\n if (o && dst && b < boneCount) {\n transformPointInto(dst, row * 3, m, b * 16, o[0], o[1], o[2]);\n }\n }\n }\n }\n row++;\n }\n stopAnimation(g); // we never want this clip ticking live again — VAT replaces it\n }\n\n const device = engine._device;\n const texture = device.createTexture({\n size: [texWidth, frameCount],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture({ texture }, data.buffer, { bytesPerRow: texWidth * 16, rowsPerImage: frameCount }, { width: texWidth, height: frameCount });\n\n return boneOrigins ? { texture, boneCount, frameCount, clips, boneOrigins } : { texture, boneCount, frameCount, clips };\n}\n\n/** Rest origin of each requested bone = translation of `inverse(IBM_bone)` (its bind-pose world origin, in\n * the skinned mesh's local space). Column-major, so translation is elements 12/13/14. */\nfunction computeRestOrigins(bones: readonly number[], ibm: Float32Array, boneCount: number): Map<number, [number, number, number]> {\n const out = new Map<number, [number, number, number]>();\n for (const b of bones) {\n if (b < 0 || b >= boneCount) {\n continue;\n }\n const inv = mat4Invert(ibm.subarray(b * 16, b * 16 + 16) as unknown as Mat4);\n if (inv) {\n out.set(b, [inv[12]!, inv[13]!, inv[14]!]);\n }\n }\n return out;\n}\n\n/** Transform a point (px,py,pz,1) by the column-major mat4 stored in `m` at `mo`, writing xyz to `dst[di..]`. */\nfunction transformPointInto(dst: Float32Array, di: number, m: Float32Array, mo: number, px: number, py: number, pz: number): void {\n dst[di] = m[mo]! * px + m[mo + 4]! * py + m[mo + 8]! * pz + m[mo + 12]!;\n dst[di + 1] = m[mo + 1]! * px + m[mo + 5]! * py + m[mo + 9]! * pz + m[mo + 13]!;\n dst[di + 2] = m[mo + 2]! * px + m[mo + 6]! * py + m[mo + 10]! * pz + m[mo + 14]!;\n}\n\n/** Runtime VAT playback handle for one mesh (the analogue of BJS BakedVertexAnimationManager + the\n * per-mesh settings). Advance `update()` each frame; set the active clip with `play()`. */\nexport interface VatHandle {\n /** The mesh this drives (its `mesh.vat` is set). */\n readonly mesh: Mesh;\n /** Baked clip row map. */\n readonly clips: Record<string, VatClip>;\n /** Select the clip to play (by name) or set explicit playback params. */\n play(clip: string, opts?: { offset?: number; fps?: number }): void;\n /** Advance the animation clock by `dtSeconds` and upload it. */\n update(dtSeconds: number): void;\n /** Enable/refresh PER-INSTANCE VAT: upload one vec4 (fromRow, toRow, timeOffset, fps) per thin-instance,\n * so every instance plays its own clip + phase from the one shared baked texture (all instances in a\n * single draw call). `params.length` must be `4 * instanceCount`. Call this BEFORE registerScene the\n * first time — it sets `mesh.vat.instanceTexture`; a VAT mesh that is thin-instanced then takes the\n * per-instance vertex path. Later calls re-upload in place. Use `clips` to look up each clip's\n * fromRow/toRow/fps when building `params`. (Internally expanded to the dual-clip layout, blend 0.) */\n setInstances(params: Float32Array): void;\n /** PER-INSTANCE DUAL-CLIP VAT: like setInstances, but each instance carries TWO clips that are blended,\n * so gait cross-fades stay smooth. `params.length` must be `8 * instanceCount` — two vec4s per instance:\n * A = (fromRowA, toRowA, timeOffset, fpsA), B = (fromRowB, toRowB, blendWeight, fpsB), where blendWeight\n * in [0,1] lerps A→B and B reuses A's timeOffset. Same per-instance VAT path as setInstances. */\n setInstancesBlend(params: Float32Array): void;\n}\n\n/**\n * Attach a baked VAT to a mesh: builds the settings UBO, sets `mesh.vat` (reusing the skeleton's\n * joints/weights vertex buffers), and DROPS the live skeleton so it's no longer CPU-updated. Returns a\n * handle that advances the animation clock.\n *\n * @param engine - Engine context.\n * @param mesh - The mesh that was baked (still has `mesh.skeleton`).\n * @param baked - The result of `bakeVat`.\n * @param clip - Initial clip name to play (defaults to the first baked clip).\n */\nexport function attachVat(engine: EngineContext, mesh: Mesh, baked: VatBakeResult, clip?: string): VatHandle {\n const skel = mesh.skeleton;\n if (!skel) {\n throw new Error(\"attachVat: mesh has no skeleton (bake first, attach before clearing it).\");\n }\n // Self-register the VAT PBR extension into the global registry (mirrors enableMaterialPlugins): this\n // is what keeps non-VAT scenes byte-identical — the shared PBR renderable carries NO VAT-specific\n // code (no dynamic-import tuple), it just walks the generic ext registry, which this populates only\n // when a scene actually bakes + attaches a VAT. Idempotent (keyed by ext id).\n _registerPbrExt(vatPbrExt);\n const device = engine._device;\n // UBO: params vec4 (fromRow, toRow, frameOffset, fps) + clock vec4 (.x = seconds). 32 bytes.\n const settingsBuffer = device.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });\n const ubo = new Float32Array(8);\n\n const vat: VatData = {\n boneCount: baked.boneCount,\n texture: baked.texture,\n frameCount: baked.frameCount,\n settingsBuffer,\n jointsBuffer: skel.jointsBuffer,\n weightsBuffer: skel.weightsBuffer,\n joints1Buffer: skel.joints1Buffer,\n weights1Buffer: skel.weights1Buffer,\n };\n mesh.vat = vat;\n mesh.skeleton = null; // baked: no live skinning, no skeleton fragment, no per-frame bone upload\n\n let time = 0;\n let instanceTex: GPUTexture | null = null;\n let instanceTexCap = 0; // capacity in TEXELS (always 2 per instance — the dual-clip layout)\n const writeUbo = (): void => {\n device.queue.writeBuffer(settingsBuffer, 0, ubo.buffer, ubo.byteOffset, 32);\n };\n // Upload per-instance VAT params (TWO texels per instance — clip A then clip B) into a (texels x 1)\n // rgba32float texture the VAT vertex path reads by instance_index.\n const uploadInstances = (params: Float32Array): void => {\n const texels = Math.max(2, params.length >> 2); // 4 floats per texel\n if (!instanceTex || texels > instanceTexCap) {\n instanceTex?.destroy();\n instanceTex = device.createTexture({\n size: [texels, 1],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n instanceTexCap = texels;\n vat.instanceTexture = instanceTex;\n }\n device.queue.writeTexture({ texture: instanceTex }, params.buffer, { offset: params.byteOffset, bytesPerRow: texels * 16, rowsPerImage: 1 }, { width: texels, height: 1 });\n };\n const handle: VatHandle = {\n mesh,\n clips: baked.clips,\n play(name, opts) {\n const c = baked.clips[name];\n if (!c) {\n return;\n }\n ubo[0] = c.fromRow;\n ubo[1] = c.fromRow + c.frameCount - 1;\n ubo[2] = opts?.offset ?? 0;\n ubo[3] = opts?.fps ?? c.fps;\n writeUbo();\n },\n update(dt) {\n time += dt;\n ubo[4] = time;\n writeUbo();\n },\n setInstances(params) {\n // Single clip per instance (4 floats: fromRow,toRow,offset,fps) expanded to the dual-clip\n // layout (clip B == A, blend 0) so the one instanced shader variant renders it.\n const n = params.length >> 2;\n const dual = new Float32Array(n * 8);\n for (let i = 0; i < n; i++) {\n const s = i * 4;\n const o = i * 8;\n dual[o] = params[s]!;\n dual[o + 1] = params[s + 1]!;\n dual[o + 2] = params[s + 2]!;\n dual[o + 3] = params[s + 3]!;\n dual[o + 4] = params[s]!;\n dual[o + 5] = params[s + 1]!;\n dual[o + 6] = 0;\n dual[o + 7] = params[s + 3]!;\n }\n uploadInstances(dual);\n },\n setInstancesBlend(params) {\n uploadInstances(params);\n },\n };\n handle.play(clip ?? Object.keys(baked.clips)[0] ?? \"\");\n return handle;\n}\n"],"names":["vatPbrExt"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjs/lite",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "A lightweight, tree-shakable, WebGPU-first rendering library derived from Babylon.js.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://doc.babylonjs.com/lite/",
@@ -21,8 +21,20 @@
21
21
  "jsdelivr": "./dist/index.js",
22
22
  "unpkg": "./dist/index.js",
23
23
  "sideEffects": false,
24
+ "peerDependencies": {
25
+ "@babylonjs/havok": "^1.3.0",
26
+ "@webgpu/types": "^0.1.52"
27
+ },
28
+ "peerDependenciesMeta": {
29
+ "@babylonjs/havok": {
30
+ "optional": true
31
+ },
32
+ "@webgpu/types": {
33
+ "optional": true
34
+ }
35
+ },
24
36
  "babylonLiteRelease": {
25
- "azureBuildId": "55470",
26
- "sourceVersion": "de70048c4d652302d4eb5f5b74c158a20b2015af"
37
+ "azureBuildId": "55784",
38
+ "sourceVersion": "202de479c36ada33c0385d2f0036a859948f66a5"
27
39
  }
28
40
  }
@@ -1,68 +0,0 @@
1
- function computeAabb(positions, world) {
2
- let minX = Infinity, minY = Infinity, minZ = Infinity;
3
- let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
4
- if (world) {
5
- const m0 = world[0], m1 = world[1], m2 = world[2], m4 = world[4], m5 = world[5], m6 = world[6], m8 = world[8], m9 = world[9], m10 = world[10], m12 = world[12], m13 = world[13], m14 = world[14];
6
- for (let i = 0; i < positions.length; i += 3) {
7
- const lx = positions[i];
8
- const ly = positions[i + 1];
9
- const lz = positions[i + 2];
10
- const x = m0 * lx + m4 * ly + m8 * lz + m12;
11
- const y = m1 * lx + m5 * ly + m9 * lz + m13;
12
- const z = m2 * lx + m6 * ly + m10 * lz + m14;
13
- if (x < minX) {
14
- minX = x;
15
- }
16
- if (x > maxX) {
17
- maxX = x;
18
- }
19
- if (y < minY) {
20
- minY = y;
21
- }
22
- if (y > maxY) {
23
- maxY = y;
24
- }
25
- if (z < minZ) {
26
- minZ = z;
27
- }
28
- if (z > maxZ) {
29
- maxZ = z;
30
- }
31
- }
32
- } else {
33
- for (let i = 0; i < positions.length; i += 3) {
34
- const x = positions[i];
35
- const y = positions[i + 1];
36
- const z = positions[i + 2];
37
- if (x < minX) {
38
- minX = x;
39
- }
40
- if (x > maxX) {
41
- maxX = x;
42
- }
43
- if (y < minY) {
44
- minY = y;
45
- }
46
- if (y > maxY) {
47
- maxY = y;
48
- }
49
- if (z < minZ) {
50
- minZ = z;
51
- }
52
- if (z > maxZ) {
53
- maxZ = z;
54
- }
55
- }
56
- }
57
- return [
58
- [minX, minY, minZ],
59
- [maxX, maxY, maxZ]
60
- ];
61
- }
62
-
63
- const __viteBrowserExternal = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
64
- __proto__: null
65
- }, Symbol.toStringTag, { value: 'Module' }));
66
-
67
- export { __viteBrowserExternal as _, computeAabb as c };
68
- //# sourceMappingURL=__vite-browser-external-BFTKbDcV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"__vite-browser-external-BFTKbDcV.js","sources":["../../../src/math/compute-aabb.ts"],"sourcesContent":["/** Axis-aligned bounding box helpers. */\n\nimport type { Aabb } from \"./aabb.js\";\nimport type { Mat4 } from \"./types.js\";\n\n/** Compute an AABB by folding XYZ min/max over a positions buffer.\n *\n * When `world` is provided each position is transformed by it before being\n * folded (column-major Mat4: m[col*4+row]). Otherwise the AABB is computed\n * in the positions' own space.\n *\n * Returns `[[+Inf,+Inf,+Inf],[-Inf,-Inf,-Inf]]` for empty input — callers\n * that care can check `isFinite(min[0])`. */\nexport function computeAabb(positions: Float32Array, world?: Mat4): Aabb {\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n if (world) {\n const m0 = world[0]!,\n m1 = world[1]!,\n m2 = world[2]!,\n m4 = world[4]!,\n m5 = world[5]!,\n m6 = world[6]!,\n m8 = world[8]!,\n m9 = world[9]!,\n m10 = world[10]!,\n m12 = world[12]!,\n m13 = world[13]!,\n m14 = world[14]!;\n for (let i = 0; i < positions.length; i += 3) {\n const lx = positions[i]!;\n const ly = positions[i + 1]!;\n const lz = positions[i + 2]!;\n const x = m0 * lx + m4 * ly + m8 * lz + m12;\n const y = m1 * lx + m5 * ly + m9 * lz + m13;\n const z = m2 * lx + m6 * ly + m10 * lz + m14;\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 } else {\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 }\n\n return [\n [minX, minY, minZ],\n [maxX, maxY, maxZ],\n ];\n}\n"],"names":[],"mappings":"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"}