@fps-games/editor 0.1.4-beta.5 → 0.1.5-beta.1

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 (227) hide show
  1. package/dist/build-info.json +16 -16
  2. package/dist/local-editor-harness.d.ts +24 -5
  3. package/dist/local-editor-harness.d.ts.map +1 -1
  4. package/dist/local-editor-harness.js +456 -90
  5. package/dist/local-editor-harness.js.map +1 -1
  6. package/dist/local-editor-performance-stats.d.ts +12 -0
  7. package/dist/local-editor-performance-stats.d.ts.map +1 -0
  8. package/dist/local-editor-performance-stats.js +46 -0
  9. package/dist/local-editor-performance-stats.js.map +1 -0
  10. package/dist/playable-babylon-facade.d.ts +2 -2
  11. package/dist/playable-babylon-facade.d.ts.map +1 -1
  12. package/dist/playable-babylon-facade.js +1 -1
  13. package/dist/playable-babylon-facade.js.map +1 -1
  14. package/dist/playable-babylon-rendering.d.ts +57 -12
  15. package/dist/playable-babylon-rendering.d.ts.map +1 -1
  16. package/dist/playable-babylon-rendering.js +529 -20
  17. package/dist/playable-babylon-rendering.js.map +1 -1
  18. package/dist/playable-local-editor-host.d.ts +10 -9
  19. package/dist/playable-local-editor-host.d.ts.map +1 -1
  20. package/dist/playable-local-editor-host.js.map +1 -1
  21. package/dist/playable-sdk.d.ts +5 -3
  22. package/dist/playable-sdk.d.ts.map +1 -1
  23. package/dist/playable-sdk.js +3 -2
  24. package/dist/playable-sdk.js.map +1 -1
  25. package/dist/static-shadow-cpu-worker.d.ts +7 -0
  26. package/dist/static-shadow-cpu-worker.d.ts.map +1 -0
  27. package/dist/static-shadow-cpu-worker.js +221 -0
  28. package/dist/static-shadow-cpu-worker.js.map +1 -0
  29. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts +3 -1
  30. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts.map +1 -1
  31. package/node_modules/@fps-games/babylon-renderer/dist/index.js +3 -1
  32. package/node_modules/@fps-games/babylon-renderer/dist/index.js.map +1 -1
  33. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts +4 -0
  34. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts.map +1 -0
  35. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js +584 -0
  36. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js.map +1 -0
  37. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts +61 -0
  38. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts.map +1 -0
  39. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js +382 -0
  40. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js.map +1 -0
  41. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts +47 -0
  42. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts.map +1 -0
  43. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js +285 -0
  44. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js.map +1 -0
  45. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts +88 -0
  46. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts.map +1 -0
  47. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js +813 -0
  48. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js.map +1 -0
  49. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts +27 -0
  50. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts.map +1 -0
  51. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js +220 -0
  52. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js.map +1 -0
  53. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts +35 -3
  54. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts.map +1 -1
  55. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js +65 -609
  56. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js.map +1 -1
  57. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts +169 -14
  58. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts.map +1 -1
  59. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js +9 -3
  60. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js.map +1 -1
  61. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  62. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +2 -0
  63. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
  64. package/node_modules/@fps-games/editor-babylon/dist/index.js +2 -0
  65. package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
  66. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts +34 -0
  67. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts.map +1 -0
  68. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js +272 -0
  69. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js.map +1 -0
  70. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +6 -0
  71. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  72. package/node_modules/@fps-games/editor-babylon/dist/projection.js +65 -1
  73. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  74. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts +19 -0
  75. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts.map +1 -0
  76. package/node_modules/@fps-games/editor-babylon/dist/rendering.js +66 -0
  77. package/node_modules/@fps-games/editor-babylon/dist/rendering.js.map +1 -0
  78. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts +5 -2
  79. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts.map +1 -1
  80. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js +65 -32
  81. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js.map +1 -1
  82. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
  83. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +19 -2
  84. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
  85. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  86. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +1 -1
  87. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  88. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  89. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts +8 -0
  90. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts.map +1 -0
  91. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js +14 -0
  92. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js.map +1 -0
  93. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  94. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +10 -2
  95. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
  96. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
  97. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
  98. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +17 -0
  99. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
  100. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
  101. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +466 -42
  102. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
  103. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +70 -5
  104. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  105. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +1 -1
  106. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  107. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +595 -5
  108. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  109. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  110. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +14 -1
  111. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
  112. package/node_modules/@fps-games/editor-core/dist/editor-session.js +34 -10
  113. package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
  114. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts +2 -1
  115. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts.map +1 -1
  116. package/node_modules/@fps-games/editor-core/dist/inspector.js +11 -1
  117. package/node_modules/@fps-games/editor-core/dist/inspector.js.map +1 -1
  118. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts +7 -0
  119. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts.map +1 -1
  120. package/node_modules/@fps-games/editor-core/dist/serialized-object.js +1 -0
  121. package/node_modules/@fps-games/editor-core/dist/serialized-object.js.map +1 -1
  122. package/node_modules/@fps-games/editor-core/package.json +2 -2
  123. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  124. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
  125. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +10 -5
  126. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
  127. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.d.ts.map +1 -1
  128. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js +3 -1
  129. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js.map +1 -1
  130. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +4 -1
  131. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
  132. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +29 -0
  133. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
  134. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +10 -0
  135. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
  136. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
  137. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +3 -0
  138. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
  139. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts +1 -0
  140. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts.map +1 -1
  141. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js +1 -0
  142. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js.map +1 -1
  143. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts +33 -2
  144. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts.map +1 -1
  145. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js +232 -16
  146. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js.map +1 -1
  147. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts +1 -1
  148. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts.map +1 -1
  149. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js +1 -1
  150. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js.map +1 -1
  151. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts +12 -1
  152. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
  153. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +153 -0
  154. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
  155. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts +4 -2
  156. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts.map +1 -1
  157. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js +2 -1
  158. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js.map +1 -1
  159. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.d.ts.map +1 -1
  160. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js +4 -1
  161. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js.map +1 -1
  162. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts +19 -0
  163. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts.map +1 -0
  164. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js +57 -0
  165. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js.map +1 -0
  166. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts +7 -1
  167. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts.map +1 -1
  168. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.d.ts.map +1 -1
  169. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js +620 -36
  170. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js.map +1 -1
  171. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts +8 -3
  172. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts.map +1 -1
  173. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js +258 -10
  174. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js.map +1 -1
  175. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts +110 -3
  176. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts.map +1 -1
  177. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
  178. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +25 -0
  179. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
  180. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +2 -1
  181. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
  182. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
  183. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +4 -0
  184. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
  185. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts +9 -1
  186. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts.map +1 -1
  187. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js +12 -1
  188. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js.map +1 -1
  189. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +2 -0
  190. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
  191. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
  192. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
  193. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +75 -0
  194. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
  195. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts +1 -0
  196. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts.map +1 -1
  197. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js +1 -0
  198. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js.map +1 -1
  199. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts +17 -0
  200. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -0
  201. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +262 -0
  202. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -0
  203. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
  204. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -3
  205. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
  206. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts +6 -0
  207. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts.map +1 -1
  208. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js +31 -0
  209. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js.map +1 -1
  210. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts +2 -1
  211. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts.map +1 -1
  212. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js +1 -1
  213. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js.map +1 -1
  214. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.d.ts.map +1 -1
  215. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js +21 -9
  216. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js.map +1 -1
  217. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts +151 -0
  218. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts.map +1 -0
  219. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js +445 -0
  220. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js.map +1 -0
  221. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts +2 -0
  222. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts.map +1 -0
  223. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js +2 -0
  224. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js.map +1 -0
  225. package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
  226. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  227. package/package.json +8 -8
@@ -0,0 +1,813 @@
1
+ import { DirectionalLight } from '@babylonjs/core/Lights/directionalLight.js';
2
+ import { Matrix, Vector3 } from '@babylonjs/core/Maths/math.vector.js';
3
+ import { RenderTargetTexture } from '@babylonjs/core/Materials/Textures/renderTargetTexture.js';
4
+ import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh.js';
5
+ import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh.js';
6
+ import { Mesh } from '@babylonjs/core/Meshes/mesh.js';
7
+ import { buildStaticProjectedShadowBounds, collectStaticProjectedShadowNodeMeshes, createStaticProjectedShadowMaskTexture, } from './static-projected-shadow-bake.js';
8
+ import { copyStaticProjectedShadowSdfTileToAtlas, createStaticProjectedShadowAtlasPixels, createStaticProjectedShadowSdfTileFromMaskPixels, packStaticProjectedShadowAtlasTiles, } from './static-projected-shadow-atlas.js';
9
+ import { resolveStaticProjectedShadowOptions } from './static-projected-shadow-system.js';
10
+ import { DEFAULT_STATIC_PROJECTED_SHADOW_OPTIONS, } from './types.js';
11
+ const DEFAULT_SHADOW_DIRECTION = new Vector3(-0.3, -1, -0.2).normalize();
12
+ export function createStaticProjectedShadowBaker(options) {
13
+ return new BabylonStaticProjectedShadowBaker(options);
14
+ }
15
+ export function collectStaticProjectedShadowBakeRoots(scene) {
16
+ const candidates = scene.meshes.filter(isExplicitStaticProjectedShadowRoot);
17
+ const candidateSet = new Set(candidates);
18
+ return candidates.filter(mesh => !hasSelectedAncestor(mesh, candidateSet));
19
+ }
20
+ export function createStaticProjectedShadowBakeHashes(input) {
21
+ const options = resolveStaticProjectedShadowOptions(input.options ?? {});
22
+ const planeY = options.plane.height + options.plane.yOffset;
23
+ const lightDir = resolveBakeLightDirection(input.directionalLight);
24
+ const roots = createBakeRoots(input.roots ?? collectStaticProjectedShadowBakeRoots(input.scene), {
25
+ lightDir,
26
+ planeY,
27
+ padding: options.bake.padding,
28
+ });
29
+ return createBakeHashes({ roots, lightDir, planeY, options });
30
+ }
31
+ export function createStaticProjectedShadowProfileHash(options = {}) {
32
+ return createBakeProfileHash(resolveStaticProjectedShadowOptions(options));
33
+ }
34
+ class BabylonStaticProjectedShadowBaker {
35
+ constructor(config) {
36
+ this.config = config;
37
+ this.readMaskTexturePixels = config.readMaskTexturePixels ?? defaultReadMaskTexturePixels;
38
+ this.processSdfTile = config.processSdfTile ?? defaultProcessSdfTile;
39
+ this.encodeAtlasTexture = config.encodeAtlasTexture ?? defaultEncodeAtlasTexture;
40
+ this.yieldToMainThread = config.yieldToMainThread;
41
+ this.now = config.now ?? (() => new Date().toISOString());
42
+ }
43
+ async bake(input = {}) {
44
+ const startedAt = nowMs();
45
+ const options = resolveStaticProjectedShadowOptions(this.config.options ?? {});
46
+ const planeY = options.plane.height + options.plane.yOffset;
47
+ const lightDir = resolveBakeLightDirection(this.config.directionalLight);
48
+ const roots = createBakeRoots(input.roots ?? this.config.roots ?? collectStaticProjectedShadowBakeRoots(this.config.scene), {
49
+ lightDir,
50
+ planeY,
51
+ padding: options.bake.padding,
52
+ });
53
+ const sourceMeshCount = roots.reduce((sum, root) => sum + root.meshes.length, 0);
54
+ const { sourceHash, lightHash, profileHash } = createBakeHashes({ roots, lightDir, planeY, options });
55
+ const chunkPlan = createBakeChunkPlan(roots, {
56
+ chunkSize: options.bake.spatialChunkSize,
57
+ targetChunkCount: options.bake.targetChunkCount,
58
+ planeY,
59
+ });
60
+ const chunks = chunkPlan.chunks;
61
+ const previousArtifact = input.previousArtifact ?? this.config.previousArtifact ?? null;
62
+ let chunkWorks = chunks.map(createBakeChunkWork);
63
+ let reusedChunks = collectReusableArtifactChunks(previousArtifact, chunkWorks, {
64
+ lightHash,
65
+ profileHash,
66
+ planeHeight: options.plane.height,
67
+ planeYOffset: options.plane.yOffset,
68
+ });
69
+ let dirtyChunkWorks = chunkWorks.filter(work => !reusedChunks.chunkIds.has(work.chunk.id));
70
+ let packing = packDirtyChunkWorks(dirtyChunkWorks, options.bake, Math.max(1, options.bake.maxAtlasPages - reusedChunks.pages.length));
71
+ if (dirtyChunkWorks.length > 0
72
+ && reusedChunks.chunks.length > 0
73
+ && reusedChunks.pages.length + packing.pages.length > options.bake.maxAtlasPages) {
74
+ reusedChunks = createEmptyReusableArtifactChunks();
75
+ dirtyChunkWorks = chunkWorks;
76
+ packing = packDirtyChunkWorks(dirtyChunkWorks, options.bake, options.bake.maxAtlasPages);
77
+ }
78
+ await this.reportProgress({
79
+ phase: 'collect',
80
+ sourceRootCount: roots.length,
81
+ sourceMeshCount,
82
+ completedChunkCount: reusedChunks.chunks.length,
83
+ totalChunkCount: chunks.length,
84
+ encodedTextureCount: 0,
85
+ atlasPageCount: packing.pages.length,
86
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
87
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
88
+ bakedChunkCount: 0,
89
+ reusedChunkCount: reusedChunks.chunks.length,
90
+ });
91
+ await this.yieldProgress({
92
+ phase: 'reuse',
93
+ sourceRootCount: roots.length,
94
+ sourceMeshCount,
95
+ completedChunkCount: reusedChunks.chunks.length,
96
+ totalChunkCount: chunks.length,
97
+ encodedTextureCount: 0,
98
+ atlasPageCount: packing.pages.length,
99
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
100
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
101
+ bakedChunkCount: 0,
102
+ reusedChunkCount: reusedChunks.chunks.length,
103
+ });
104
+ const atlasPixelsByPageId = new Map();
105
+ const pageLayoutsById = new Map(packing.pages.map(page => [page.id, page]));
106
+ const reusedPageIds = new Set(reusedChunks.pages.map(page => page.id));
107
+ const bakedPageIds = createBakedPageIds(packing.pages.map(page => page.id), reusedPageIds);
108
+ for (const page of packing.pages) {
109
+ atlasPixelsByPageId.set(page.id, createStaticProjectedShadowAtlasPixels(page.width, page.height));
110
+ }
111
+ const pendingChunks = [];
112
+ for (let index = 0; index < dirtyChunkWorks.length; index += 1) {
113
+ const work = dirtyChunkWorks[index];
114
+ const chunk = work.chunk;
115
+ const layout = packing.layoutsByTileId.get(chunk.id);
116
+ if (!layout)
117
+ continue;
118
+ const completedBefore = reusedChunks.chunks.length + index;
119
+ await this.reportProgress({
120
+ phase: 'chunk',
121
+ sourceRootCount: roots.length,
122
+ sourceMeshCount,
123
+ completedChunkCount: completedBefore,
124
+ totalChunkCount: chunks.length,
125
+ encodedTextureCount: pendingChunks.length,
126
+ currentChunkId: chunk.id,
127
+ atlasPageCount: packing.pages.length,
128
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
129
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
130
+ bakedChunkCount: pendingChunks.length,
131
+ reusedChunkCount: reusedChunks.chunks.length,
132
+ });
133
+ const mask = await createStaticProjectedShadowMaskTexture(chunk.roots.flatMap(root => root.meshes), {
134
+ scene: this.config.scene,
135
+ name: chunk.id,
136
+ bounds: chunk.bounds,
137
+ lightDir,
138
+ planeY,
139
+ resolution: {
140
+ width: layout.width,
141
+ height: layout.height,
142
+ },
143
+ });
144
+ if (!mask) {
145
+ await this.reportProgress({
146
+ phase: 'chunk',
147
+ sourceRootCount: roots.length,
148
+ sourceMeshCount,
149
+ completedChunkCount: completedBefore + 1,
150
+ totalChunkCount: chunks.length,
151
+ encodedTextureCount: pendingChunks.length,
152
+ currentChunkId: chunk.id,
153
+ atlasPageCount: packing.pages.length,
154
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
155
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
156
+ bakedChunkCount: pendingChunks.length,
157
+ reusedChunkCount: reusedChunks.chunks.length,
158
+ });
159
+ await this.yieldProgress({
160
+ phase: 'chunk',
161
+ sourceRootCount: roots.length,
162
+ sourceMeshCount,
163
+ completedChunkCount: completedBefore + 1,
164
+ totalChunkCount: chunks.length,
165
+ encodedTextureCount: pendingChunks.length,
166
+ currentChunkId: chunk.id,
167
+ atlasPageCount: packing.pages.length,
168
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
169
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
170
+ bakedChunkCount: pendingChunks.length,
171
+ reusedChunkCount: reusedChunks.chunks.length,
172
+ });
173
+ continue;
174
+ }
175
+ try {
176
+ await this.reportProgress({
177
+ phase: 'sdf',
178
+ sourceRootCount: roots.length,
179
+ sourceMeshCount,
180
+ completedChunkCount: completedBefore,
181
+ totalChunkCount: chunks.length,
182
+ encodedTextureCount: pendingChunks.length,
183
+ currentChunkId: chunk.id,
184
+ atlasPageCount: packing.pages.length,
185
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
186
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
187
+ bakedChunkCount: pendingChunks.length,
188
+ reusedChunkCount: reusedChunks.chunks.length,
189
+ });
190
+ const maskPixels = await this.readMaskTexturePixels({
191
+ texture: mask.texture,
192
+ chunkId: chunk.id,
193
+ bounds: chunk.bounds,
194
+ width: layout.width,
195
+ height: layout.height,
196
+ });
197
+ if (!maskPixels || maskPixels.width !== layout.width || maskPixels.height !== layout.height)
198
+ continue;
199
+ const sdfTile = await this.processSdfTile({
200
+ chunkId: chunk.id,
201
+ pixels: maskPixels.pixels,
202
+ width: maskPixels.width,
203
+ height: maskPixels.height,
204
+ sdfRadiusPx: options.bake.sdfRadiusPx,
205
+ });
206
+ if (!sdfTile?.hasCoverage || sdfTile.width !== maskPixels.width || sdfTile.height !== maskPixels.height)
207
+ continue;
208
+ const atlasPixels = atlasPixelsByPageId.get(layout.pageId);
209
+ const pageLayout = pageLayoutsById.get(layout.pageId);
210
+ if (!atlasPixels)
211
+ continue;
212
+ if (!pageLayout)
213
+ continue;
214
+ copyStaticProjectedShadowSdfTileToAtlas(atlasPixels, pageLayout.width, sdfTile.sdfAlpha, maskPixels.width, maskPixels.height, layout.copyX, layout.copyY);
215
+ const pageId = bakedPageIds.get(layout.pageId) ?? layout.pageId;
216
+ pendingChunks.push({
217
+ id: chunk.id,
218
+ bounds: {
219
+ minX: roundNumber(chunk.bounds.minX),
220
+ maxX: roundNumber(chunk.bounds.maxX),
221
+ minZ: roundNumber(chunk.bounds.minZ),
222
+ maxZ: roundNumber(chunk.bounds.maxZ),
223
+ y: roundNumber(chunk.bounds.center.y),
224
+ },
225
+ plane: {
226
+ height: roundNumber(options.plane.height),
227
+ yOffset: roundNumber(options.plane.yOffset),
228
+ },
229
+ pageId,
230
+ atlasRect: layout.atlasRect,
231
+ atlasUv: layout.atlasUv,
232
+ sourceNodeIds: work.sourceNodeIds,
233
+ sourceHash: work.sourceHash,
234
+ lightHash,
235
+ profileHash,
236
+ });
237
+ }
238
+ finally {
239
+ mask.dispose();
240
+ }
241
+ await this.reportProgress({
242
+ phase: 'chunk',
243
+ sourceRootCount: roots.length,
244
+ sourceMeshCount,
245
+ completedChunkCount: completedBefore + 1,
246
+ totalChunkCount: chunks.length,
247
+ encodedTextureCount: pendingChunks.length,
248
+ currentChunkId: chunk.id,
249
+ atlasPageCount: packing.pages.length,
250
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
251
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
252
+ bakedChunkCount: pendingChunks.length,
253
+ reusedChunkCount: reusedChunks.chunks.length,
254
+ });
255
+ await this.yieldProgress({
256
+ phase: 'chunk',
257
+ sourceRootCount: roots.length,
258
+ sourceMeshCount,
259
+ completedChunkCount: completedBefore + 1,
260
+ totalChunkCount: chunks.length,
261
+ encodedTextureCount: pendingChunks.length,
262
+ currentChunkId: chunk.id,
263
+ atlasPageCount: packing.pages.length,
264
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
265
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
266
+ bakedChunkCount: pendingChunks.length,
267
+ reusedChunkCount: reusedChunks.chunks.length,
268
+ });
269
+ }
270
+ await this.reportProgress({
271
+ phase: 'pack',
272
+ sourceRootCount: roots.length,
273
+ sourceMeshCount,
274
+ completedChunkCount: chunks.length,
275
+ totalChunkCount: chunks.length,
276
+ encodedTextureCount: pendingChunks.length,
277
+ atlasPageCount: reusedChunks.pages.length + packing.pages.length,
278
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
279
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
280
+ bakedChunkCount: pendingChunks.length,
281
+ reusedChunkCount: reusedChunks.chunks.length,
282
+ });
283
+ const usedPageIds = new Set(pendingChunks.map(chunk => chunk.pageId));
284
+ const pages = [...reusedChunks.pages];
285
+ const encodedPageIds = new Set();
286
+ for (const page of packing.pages) {
287
+ const pageId = bakedPageIds.get(page.id) ?? page.id;
288
+ if (!usedPageIds.has(pageId))
289
+ continue;
290
+ const pixels = atlasPixelsByPageId.get(page.id);
291
+ if (!pixels)
292
+ continue;
293
+ await this.reportProgress({
294
+ phase: 'encode',
295
+ sourceRootCount: roots.length,
296
+ sourceMeshCount,
297
+ completedChunkCount: chunks.length,
298
+ totalChunkCount: chunks.length,
299
+ encodedTextureCount: pages.length,
300
+ currentChunkId: pageId,
301
+ atlasPageCount: reusedChunks.pages.length + packing.pages.length,
302
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
303
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
304
+ bakedChunkCount: pendingChunks.length,
305
+ reusedChunkCount: reusedChunks.chunks.length,
306
+ });
307
+ const sdfTextureDataUrl = await this.encodeAtlasTexture({
308
+ pageId,
309
+ pixels,
310
+ width: page.width,
311
+ height: page.height,
312
+ });
313
+ if (!isPngDataUrl(sdfTextureDataUrl))
314
+ continue;
315
+ pages.push({
316
+ id: pageId,
317
+ width: page.width,
318
+ height: page.height,
319
+ sdfTextureDataUrl,
320
+ });
321
+ encodedPageIds.add(pageId);
322
+ await this.yieldProgress({
323
+ phase: 'encode',
324
+ sourceRootCount: roots.length,
325
+ sourceMeshCount,
326
+ completedChunkCount: chunks.length,
327
+ totalChunkCount: chunks.length,
328
+ encodedTextureCount: pages.length,
329
+ currentChunkId: pageId,
330
+ atlasPageCount: reusedChunks.pages.length + packing.pages.length,
331
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
332
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
333
+ bakedChunkCount: pendingChunks.length,
334
+ reusedChunkCount: reusedChunks.chunks.length,
335
+ });
336
+ }
337
+ const artifactChunks = [...reusedChunks.chunks, ...pendingChunks.filter(chunk => encodedPageIds.has(chunk.pageId))]
338
+ .sort((left, right) => left.id.localeCompare(right.id));
339
+ const durationMs = Math.max(0, Math.round(nowMs() - startedAt));
340
+ const atlasUsage = calculateArtifactAtlasUsage(pages, artifactChunks);
341
+ await this.reportProgress({
342
+ phase: 'complete',
343
+ sourceRootCount: roots.length,
344
+ sourceMeshCount,
345
+ completedChunkCount: chunks.length,
346
+ totalChunkCount: chunks.length,
347
+ encodedTextureCount: pages.length,
348
+ atlasPageCount: pages.length,
349
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
350
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
351
+ bakedChunkCount: pendingChunks.length,
352
+ reusedChunkCount: reusedChunks.chunks.length,
353
+ });
354
+ return {
355
+ version: 2,
356
+ format: 'sdf-atlas',
357
+ pages,
358
+ chunks: artifactChunks,
359
+ sourceHash,
360
+ lightHash,
361
+ profileHash,
362
+ generatedAt: this.now(),
363
+ stats: {
364
+ sourceRootCount: roots.length,
365
+ sourceMeshCount,
366
+ attemptedChunkCount: chunks.length,
367
+ chunkCount: artifactChunks.length,
368
+ textureCount: pages.length,
369
+ pageCount: pages.length,
370
+ skippedChunkCount: Math.max(0, chunks.length - artifactChunks.length),
371
+ resolution: options.bake.resolution,
372
+ chunkSize: chunkPlan.effectiveChunkSize,
373
+ atlasSize: packing.atlasSize,
374
+ atlasUsedPixels: atlasUsage.usedPixels,
375
+ atlasAllocatedPixels: atlasUsage.allocatedPixels,
376
+ atlasOccupancy: atlasUsage.occupancy,
377
+ texelsPerMeter: options.bake.texelsPerMeter,
378
+ effectiveTexelsPerMeter: packing.effectiveTexelsPerMeter,
379
+ maxAtlasPages: options.bake.maxAtlasPages,
380
+ sdfRadiusPx: options.bake.sdfRadiusPx,
381
+ spatialChunkSize: options.bake.spatialChunkSize,
382
+ effectiveSpatialChunkSize: chunkPlan.effectiveChunkSize,
383
+ targetChunkCount: options.bake.targetChunkCount,
384
+ bakedChunkCount: pendingChunks.length,
385
+ reusedChunkCount: reusedChunks.chunks.length,
386
+ durationMs,
387
+ },
388
+ };
389
+ }
390
+ async reportProgress(progress) {
391
+ await this.config.onProgress?.(progress);
392
+ }
393
+ async yieldProgress(progress) {
394
+ await this.yieldToMainThread?.(progress);
395
+ }
396
+ }
397
+ function calculateArtifactAtlasUsage(pages, chunks) {
398
+ const pageIds = new Set(pages.map(page => page.id));
399
+ const usedPixels = chunks.reduce((sum, chunk) => (pageIds.has(chunk.pageId)
400
+ ? sum + Math.max(0, chunk.atlasRect.width) * Math.max(0, chunk.atlasRect.height)
401
+ : sum), 0);
402
+ const allocatedPixels = pages.reduce((sum, page) => (sum + Math.max(0, page.width) * Math.max(0, page.height)), 0);
403
+ return {
404
+ usedPixels,
405
+ allocatedPixels,
406
+ occupancy: roundNumber(allocatedPixels > 0 ? usedPixels / allocatedPixels : 0),
407
+ };
408
+ }
409
+ function createBakeHashes(input) {
410
+ return {
411
+ sourceHash: createBakeSourceHash(input.roots),
412
+ lightHash: createBakeLightHash(input.lightDir, input.planeY),
413
+ profileHash: createBakeProfileHash(input.options),
414
+ };
415
+ }
416
+ function createBakeChunkWork(chunk) {
417
+ const sourceNodeIds = uniqueStrings(chunk.roots.map(root => root.sourceNodeId));
418
+ return {
419
+ chunk,
420
+ sourceNodeIds,
421
+ sourceHash: createBakeHash(sourceNodeIds),
422
+ };
423
+ }
424
+ function packDirtyChunkWorks(works, bakeOptions, maxAtlasPages) {
425
+ return packStaticProjectedShadowAtlasTiles(works.map(work => ({
426
+ id: work.chunk.id,
427
+ width: Math.max(1e-6, work.chunk.bounds.width),
428
+ height: Math.max(1e-6, work.chunk.bounds.depth),
429
+ })), {
430
+ texelsPerMeter: bakeOptions.texelsPerMeter,
431
+ atlasSize: bakeOptions.atlasSize,
432
+ maxAtlasPages: Math.max(1, maxAtlasPages),
433
+ paddingPx: Math.min(2, Math.max(0, Math.round(bakeOptions.sdfRadiusPx))),
434
+ });
435
+ }
436
+ function createEmptyReusableArtifactChunks() {
437
+ return {
438
+ chunks: [],
439
+ pages: [],
440
+ chunkIds: new Set(),
441
+ };
442
+ }
443
+ function collectReusableArtifactChunks(artifact, works, hashes) {
444
+ if (!artifact || artifact.version !== 2)
445
+ return createEmptyReusableArtifactChunks();
446
+ const pagesById = new Map(artifact.pages
447
+ .filter(page => isPngDataUrl(page.sdfTextureDataUrl))
448
+ .map(page => [page.id, page]));
449
+ if (pagesById.size === 0)
450
+ return createEmptyReusableArtifactChunks();
451
+ const worksById = new Map(works.map(work => [work.chunk.id, work]));
452
+ const reusableChunks = [];
453
+ const reusablePages = new Map();
454
+ const reusableChunkIds = new Set();
455
+ for (const previousChunk of artifact.chunks) {
456
+ const work = worksById.get(previousChunk.id);
457
+ const page = pagesById.get(previousChunk.pageId);
458
+ if (!work || !page)
459
+ continue;
460
+ if (previousChunk.sourceHash !== work.sourceHash)
461
+ continue;
462
+ if (previousChunk.lightHash !== hashes.lightHash || previousChunk.profileHash !== hashes.profileHash)
463
+ continue;
464
+ if (!matchesChunkBounds(previousChunk, work.chunk.bounds))
465
+ continue;
466
+ if (!matchesChunkPlane(previousChunk, hashes.planeHeight, hashes.planeYOffset))
467
+ continue;
468
+ reusableChunks.push({ ...previousChunk, sourceNodeIds: [...previousChunk.sourceNodeIds] });
469
+ reusablePages.set(page.id, { ...page });
470
+ reusableChunkIds.add(previousChunk.id);
471
+ }
472
+ return {
473
+ chunks: reusableChunks,
474
+ pages: [...reusablePages.values()],
475
+ chunkIds: reusableChunkIds,
476
+ };
477
+ }
478
+ function matchesChunkBounds(chunk, bounds) {
479
+ return chunk.bounds.minX === roundNumber(bounds.minX)
480
+ && chunk.bounds.maxX === roundNumber(bounds.maxX)
481
+ && chunk.bounds.minZ === roundNumber(bounds.minZ)
482
+ && chunk.bounds.maxZ === roundNumber(bounds.maxZ)
483
+ && chunk.bounds.y === roundNumber(bounds.center.y);
484
+ }
485
+ function matchesChunkPlane(chunk, height, yOffset) {
486
+ return chunk.plane.height === roundNumber(height)
487
+ && chunk.plane.yOffset === roundNumber(yOffset);
488
+ }
489
+ function createBakedPageIds(pageIds, existingPageIds) {
490
+ const used = new Set(existingPageIds);
491
+ const result = new Map();
492
+ for (const pageId of pageIds) {
493
+ let next = pageId;
494
+ if (used.has(next)) {
495
+ let suffix = 0;
496
+ do {
497
+ next = `bake_${suffix}_${pageId}`;
498
+ suffix += 1;
499
+ } while (used.has(next));
500
+ }
501
+ used.add(next);
502
+ result.set(pageId, next);
503
+ }
504
+ return result;
505
+ }
506
+ function createBakeSourceHash(roots) {
507
+ return createBakeHash(roots.map(root => ({
508
+ id: root.sourceNodeId,
509
+ name: root.root.name,
510
+ matrix: serializeMatrix(root.root.getWorldMatrix()),
511
+ bounds: serializeBounds(root.bounds),
512
+ })));
513
+ }
514
+ function createBakeLightHash(lightDir, planeY) {
515
+ return createBakeHash({
516
+ direction: serializeVector(lightDir),
517
+ planeY: roundNumber(planeY),
518
+ });
519
+ }
520
+ function createBakeProfileHash(options) {
521
+ return createBakeHash({
522
+ plane: {
523
+ height: roundNumber(options.plane.height),
524
+ yOffset: roundNumber(options.plane.yOffset),
525
+ },
526
+ bake: {
527
+ padding: roundNumber(options.bake.padding),
528
+ maxSize: roundNumber(options.bake.maxSize),
529
+ texelsPerMeter: roundNumber(options.bake.texelsPerMeter),
530
+ atlasSize: roundNumber(options.bake.atlasSize),
531
+ maxAtlasPages: roundNumber(options.bake.maxAtlasPages),
532
+ sdfRadiusPx: roundNumber(options.bake.sdfRadiusPx),
533
+ spatialChunkSize: roundNumber(options.bake.spatialChunkSize),
534
+ },
535
+ });
536
+ }
537
+ function createBakeRoots(roots, options) {
538
+ const result = [];
539
+ for (const root of roots) {
540
+ if (root.isDisposed() || !root.isEnabled(false) || isStaticProjectedShadowInternal(root))
541
+ continue;
542
+ const meshes = collectStaticProjectedShadowNodeMeshes(root).filter(isBakeMesh);
543
+ if (meshes.length === 0)
544
+ continue;
545
+ const bounds = buildStaticProjectedShadowBounds(meshes, {
546
+ lightDir: options.lightDir,
547
+ planeY: options.planeY,
548
+ padding: options.padding,
549
+ });
550
+ if (!bounds)
551
+ continue;
552
+ result.push({
553
+ root,
554
+ sourceNodeId: readEditorProjectionNodeId(root) ?? root.id ?? root.name,
555
+ meshes,
556
+ bounds,
557
+ });
558
+ }
559
+ return result;
560
+ }
561
+ function createBakeChunkPlan(roots, options) {
562
+ const requestedChunkSize = Math.max(options.chunkSize || DEFAULT_STATIC_PROJECTED_SHADOW_OPTIONS.bake.spatialChunkSize, 1);
563
+ const targetChunkCount = Math.max(1, Math.floor(options.targetChunkCount || DEFAULT_STATIC_PROJECTED_SHADOW_OPTIONS.bake.targetChunkCount));
564
+ let effectiveChunkSize = requestedChunkSize;
565
+ let chunks = createBakeChunksAtSize(roots, {
566
+ chunkSize: effectiveChunkSize,
567
+ planeY: options.planeY,
568
+ });
569
+ for (let attempt = 0; attempt < 6 && chunks.length > targetChunkCount; attempt += 1) {
570
+ const scale = Math.sqrt(chunks.length / targetChunkCount) * 1.05;
571
+ effectiveChunkSize = Math.max(effectiveChunkSize + 1e-6, effectiveChunkSize * scale);
572
+ chunks = createBakeChunksAtSize(roots, {
573
+ chunkSize: effectiveChunkSize,
574
+ planeY: options.planeY,
575
+ });
576
+ }
577
+ return {
578
+ chunks,
579
+ requestedChunkSize: roundNumber(requestedChunkSize),
580
+ effectiveChunkSize: roundNumber(effectiveChunkSize),
581
+ };
582
+ }
583
+ function createBakeChunksAtSize(roots, options) {
584
+ const chunkSize = Math.max(options.chunkSize || DEFAULT_STATIC_PROJECTED_SHADOW_OPTIONS.bake.maxSize, 1);
585
+ const chunks = new Map();
586
+ for (const root of roots) {
587
+ const minGridX = Math.floor(root.bounds.minX / chunkSize);
588
+ const maxGridX = Math.floor((root.bounds.maxX - 1e-6) / chunkSize);
589
+ const minGridZ = Math.floor(root.bounds.minZ / chunkSize);
590
+ const maxGridZ = Math.floor((root.bounds.maxZ - 1e-6) / chunkSize);
591
+ for (let gridX = minGridX; gridX <= maxGridX; gridX += 1) {
592
+ for (let gridZ = minGridZ; gridZ <= maxGridZ; gridZ += 1) {
593
+ const id = `chunk_${gridX}_${gridZ}`;
594
+ let chunk = chunks.get(id);
595
+ if (!chunk) {
596
+ chunk = {
597
+ id,
598
+ gridX,
599
+ gridZ,
600
+ bounds: createChunkBounds(gridX, gridZ, chunkSize, options.planeY),
601
+ roots: [],
602
+ };
603
+ chunks.set(id, chunk);
604
+ }
605
+ chunk.roots.push(root);
606
+ }
607
+ }
608
+ }
609
+ for (const chunk of chunks.values()) {
610
+ chunk.bounds = createTightChunkBounds(chunk.roots, chunk.bounds);
611
+ }
612
+ return [...chunks.values()].sort((left, right) => left.gridX - right.gridX || left.gridZ - right.gridZ);
613
+ }
614
+ function createChunkBounds(gridX, gridZ, chunkSize, planeY) {
615
+ const minX = gridX * chunkSize;
616
+ const maxX = minX + chunkSize;
617
+ const minZ = gridZ * chunkSize;
618
+ const maxZ = minZ + chunkSize;
619
+ return {
620
+ center: new Vector3((minX + maxX) * 0.5, planeY, (minZ + maxZ) * 0.5),
621
+ width: chunkSize,
622
+ depth: chunkSize,
623
+ minX,
624
+ maxX,
625
+ minZ,
626
+ maxZ,
627
+ };
628
+ }
629
+ function createTightChunkBounds(roots, gridBounds) {
630
+ let minX = Infinity;
631
+ let maxX = -Infinity;
632
+ let minZ = Infinity;
633
+ let maxZ = -Infinity;
634
+ for (const root of roots) {
635
+ const clippedMinX = Math.max(root.bounds.minX, gridBounds.minX);
636
+ const clippedMaxX = Math.min(root.bounds.maxX, gridBounds.maxX);
637
+ const clippedMinZ = Math.max(root.bounds.minZ, gridBounds.minZ);
638
+ const clippedMaxZ = Math.min(root.bounds.maxZ, gridBounds.maxZ);
639
+ if (clippedMaxX <= clippedMinX || clippedMaxZ <= clippedMinZ)
640
+ continue;
641
+ minX = Math.min(minX, clippedMinX);
642
+ maxX = Math.max(maxX, clippedMaxX);
643
+ minZ = Math.min(minZ, clippedMinZ);
644
+ maxZ = Math.max(maxZ, clippedMaxZ);
645
+ }
646
+ if (![minX, maxX, minZ, maxZ].every(Number.isFinite))
647
+ return gridBounds;
648
+ return {
649
+ center: new Vector3((minX + maxX) * 0.5, gridBounds.center.y, (minZ + maxZ) * 0.5),
650
+ width: maxX - minX,
651
+ depth: maxZ - minZ,
652
+ minX,
653
+ maxX,
654
+ minZ,
655
+ maxZ,
656
+ };
657
+ }
658
+ function isBakeMesh(mesh) {
659
+ if (mesh.isDisposed() || !mesh.isEnabled(false))
660
+ return false;
661
+ if (!(mesh instanceof Mesh) && !(mesh instanceof InstancedMesh))
662
+ return false;
663
+ const geometrySource = mesh instanceof InstancedMesh ? mesh.sourceMesh : mesh;
664
+ if (!(geometrySource instanceof Mesh) || !geometrySource.geometry)
665
+ return false;
666
+ return mesh.isVisible && !isStaticProjectedShadowInternal(mesh);
667
+ }
668
+ function isExplicitStaticProjectedShadowRoot(mesh) {
669
+ if (mesh.isDisposed() || !mesh.isEnabled(false) || isStaticProjectedShadowInternal(mesh))
670
+ return false;
671
+ const projection = readEditorProjectionMetadata(mesh);
672
+ if (projection?.runtimeKind === 'camera' || projection?.runtimeKind === 'light')
673
+ return false;
674
+ return projection?.shadowMode === 'static';
675
+ }
676
+ function hasSelectedAncestor(mesh, selected) {
677
+ let cursor = mesh.parent;
678
+ while (cursor) {
679
+ if (cursor instanceof AbstractMesh && selected.has(cursor))
680
+ return true;
681
+ cursor = cursor.parent;
682
+ }
683
+ return false;
684
+ }
685
+ function isStaticProjectedShadowInternal(mesh) {
686
+ const metadata = mesh.metadata;
687
+ return !!metadata
688
+ && typeof metadata === 'object'
689
+ && (metadata.disableStaticProjectedShadow === true
690
+ || metadata.staticProjectedShadowInternal === true
691
+ || metadata.disableBlobShadow === true
692
+ || metadata.blobShadowInternal === true
693
+ || metadata.disablePlanarShadow === true
694
+ || metadata.planarShadowInternal === true);
695
+ }
696
+ function readEditorProjectionNodeId(mesh) {
697
+ const nodeId = readEditorProjectionMetadata(mesh)?.nodeId;
698
+ return typeof nodeId === 'string' && nodeId.trim() ? nodeId.trim() : null;
699
+ }
700
+ function readEditorProjectionMetadata(mesh) {
701
+ const metadata = mesh.metadata;
702
+ if (!metadata || typeof metadata !== 'object')
703
+ return null;
704
+ const editorProjection = metadata.editorProjection;
705
+ return editorProjection && typeof editorProjection === 'object' && !Array.isArray(editorProjection)
706
+ ? editorProjection
707
+ : null;
708
+ }
709
+ function resolveBakeLightDirection(light) {
710
+ const direction = light?.direction;
711
+ return direction?.lengthSquared?.() && direction.lengthSquared() > 1e-6
712
+ ? direction.clone().normalize()
713
+ : DEFAULT_SHADOW_DIRECTION.clone();
714
+ }
715
+ async function defaultReadMaskTexturePixels(input) {
716
+ const pixels = await input.texture.readPixels();
717
+ if (!pixels)
718
+ return null;
719
+ const size = input.texture.getSize();
720
+ return {
721
+ pixels,
722
+ width: Math.max(1, Math.round(size.width || input.width)),
723
+ height: Math.max(1, Math.round(size.height || input.height)),
724
+ };
725
+ }
726
+ async function defaultEncodeAtlasTexture(input) {
727
+ return encodeRgbaPixelsAsPngDataUrl(input.pixels, input.width, input.height);
728
+ }
729
+ function defaultProcessSdfTile(input) {
730
+ return createStaticProjectedShadowSdfTileFromMaskPixels(input.pixels, input.width, input.height, input.sdfRadiusPx);
731
+ }
732
+ function encodeRgbaPixelsAsPngDataUrl(pixels, width, height) {
733
+ const canvas = createCanvas(width, height);
734
+ const context = canvas?.getContext('2d');
735
+ if (!canvas || !context)
736
+ return null;
737
+ const imageData = context.createImageData(width, height);
738
+ const source = pixels instanceof Uint8Array || pixels instanceof Uint8ClampedArray
739
+ ? pixels
740
+ : new Uint8Array(pixels.buffer, pixels.byteOffset, pixels.byteLength);
741
+ const target = imageData.data;
742
+ const length = Math.min(source.length, target.length);
743
+ for (let index = 0; index < length; index += 4) {
744
+ const alpha = source[index + 3] ?? 0;
745
+ target[index] = alpha > 0 ? 255 : 0;
746
+ target[index + 1] = alpha > 0 ? 255 : 0;
747
+ target[index + 2] = alpha > 0 ? 255 : 0;
748
+ target[index + 3] = alpha;
749
+ }
750
+ context.putImageData(imageData, 0, 0);
751
+ return typeof canvas.toDataURL === 'function' ? canvas.toDataURL('image/png') : null;
752
+ }
753
+ function createCanvas(width, height) {
754
+ const documentRef = typeof document === 'undefined' ? null : document;
755
+ if (!documentRef?.createElement)
756
+ return null;
757
+ const canvas = documentRef.createElement('canvas');
758
+ canvas.width = width;
759
+ canvas.height = height;
760
+ return canvas;
761
+ }
762
+ function createBakeHash(value) {
763
+ const text = stableStringify(value);
764
+ let hash = 0x811c9dc5;
765
+ for (let index = 0; index < text.length; index += 1) {
766
+ hash ^= text.charCodeAt(index);
767
+ hash = Math.imul(hash, 0x01000193);
768
+ }
769
+ return `fnv1a:${(hash >>> 0).toString(16).padStart(8, '0')}`;
770
+ }
771
+ function stableStringify(value) {
772
+ if (value == null || typeof value !== 'object')
773
+ return JSON.stringify(value);
774
+ if (Array.isArray(value))
775
+ return `[${value.map(stableStringify).join(',')}]`;
776
+ const entries = Object.entries(value)
777
+ .sort(([left], [right]) => left.localeCompare(right));
778
+ return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(',')}}`;
779
+ }
780
+ function serializeMatrix(matrix) {
781
+ return matrix.asArray().map(roundNumber);
782
+ }
783
+ function serializeVector(vector) {
784
+ return {
785
+ x: roundNumber(vector.x),
786
+ y: roundNumber(vector.y),
787
+ z: roundNumber(vector.z),
788
+ };
789
+ }
790
+ function serializeBounds(bounds) {
791
+ return {
792
+ minX: roundNumber(bounds.minX),
793
+ maxX: roundNumber(bounds.maxX),
794
+ minZ: roundNumber(bounds.minZ),
795
+ maxZ: roundNumber(bounds.maxZ),
796
+ y: roundNumber(bounds.center.y),
797
+ };
798
+ }
799
+ function roundNumber(value) {
800
+ return Math.round(value * 1000000) / 1000000;
801
+ }
802
+ function nowMs() {
803
+ return typeof performance !== 'undefined' && typeof performance.now === 'function'
804
+ ? performance.now()
805
+ : Date.now();
806
+ }
807
+ function uniqueStrings(values) {
808
+ return [...new Set(values.map(value => value.trim()).filter(Boolean))];
809
+ }
810
+ function isPngDataUrl(value) {
811
+ return typeof value === 'string' && /^data:image\/png[;,]/i.test(value);
812
+ }
813
+ //# sourceMappingURL=static-projected-shadow-baker.js.map