@zephyr3d/scene 0.9.27 → 0.10.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 (502) hide show
  1. package/README.md +60 -27
  2. package/dist/animation/animation_bank.js +634 -0
  3. package/dist/animation/animation_bank.js.map +1 -0
  4. package/dist/animation/animation_bank_gpu.js +256 -0
  5. package/dist/animation/animation_bank_gpu.js.map +1 -0
  6. package/dist/animation/animationset.js +54 -0
  7. package/dist/animation/animationset.js.map +1 -1
  8. package/dist/animation/cloth/gpu_cloth_component.js +406 -0
  9. package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
  10. package/dist/animation/cloth/gpu_cloth_system.js +332 -202
  11. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
  12. package/dist/animation/gpu_animation_driver.js +289 -0
  13. package/dist/animation/gpu_animation_driver.js.map +1 -0
  14. package/dist/animation/joint_dynamics/collision.js +112 -1
  15. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  16. package/dist/animation/joint_dynamics/controller.js +6 -0
  17. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
  19. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  20. package/dist/animation/joint_dynamics/solver.js +50 -12
  21. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  22. package/dist/animation/joint_dynamics/types.js.map +1 -1
  23. package/dist/animation/skeleton.js +279 -55
  24. package/dist/animation/skeleton.js.map +1 -1
  25. package/dist/animation/skin_palette_atlas.js +252 -0
  26. package/dist/animation/skin_palette_atlas.js.map +1 -0
  27. package/dist/animation/spring/multi_chain_spring_system.js +298 -38
  28. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  29. package/dist/animation/spring/spring_chain.js +2 -0
  30. package/dist/animation/spring/spring_chain.js.map +1 -1
  31. package/dist/animation/spring/spring_collider.js +159 -21
  32. package/dist/animation/spring/spring_collider.js.map +1 -1
  33. package/dist/animation/spring/spring_particle.js +1 -0
  34. package/dist/animation/spring/spring_particle.js.map +1 -1
  35. package/dist/animation/spring/spring_solver.js +173 -0
  36. package/dist/animation/spring/spring_solver.js.map +1 -0
  37. package/dist/animation/spring/spring_system.js +249 -24
  38. package/dist/animation/spring/spring_system.js.map +1 -1
  39. package/dist/animation/spring_modifier.js +32 -1
  40. package/dist/animation/spring_modifier.js.map +1 -1
  41. package/dist/app/app.js +26 -0
  42. package/dist/app/app.js.map +1 -1
  43. package/dist/app/engine.js +86 -15
  44. package/dist/app/engine.js.map +1 -1
  45. package/dist/app/gamepad.js +191 -0
  46. package/dist/app/gamepad.js.map +1 -0
  47. package/dist/app/inputactions.js +271 -0
  48. package/dist/app/inputactions.js.map +1 -0
  49. package/dist/app/inputmgr.js +331 -22
  50. package/dist/app/inputmgr.js.map +1 -1
  51. package/dist/app/loading.js +138 -0
  52. package/dist/app/loading.js.map +1 -0
  53. package/dist/app/pipelinecache.js +209 -0
  54. package/dist/app/pipelinecache.js.map +1 -0
  55. package/dist/app/runtimescript.js +25 -0
  56. package/dist/app/runtimescript.js.map +1 -1
  57. package/dist/app/scriptingsystem.js +54 -0
  58. package/dist/app/scriptingsystem.js.map +1 -1
  59. package/dist/app/scriptregistry.js +7 -2
  60. package/dist/app/scriptregistry.js.map +1 -1
  61. package/dist/asset/asset_manifest.js +59 -0
  62. package/dist/asset/asset_manifest.js.map +1 -0
  63. package/dist/asset/asset_preload.js +258 -0
  64. package/dist/asset/asset_preload.js.map +1 -0
  65. package/dist/asset/assetmanager.js +117 -65
  66. package/dist/asset/assetmanager.js.map +1 -1
  67. package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
  68. package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  69. package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  70. package/dist/asset/loaders/ktx2/basis_location.js +17 -0
  71. package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
  72. package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
  73. package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
  74. package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
  75. package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
  76. package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
  77. package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
  78. package/dist/asset/mesh_lod_builder.js +104 -0
  79. package/dist/asset/mesh_lod_builder.js.map +1 -0
  80. package/dist/asset/mesh_settings.js +111 -0
  81. package/dist/asset/mesh_settings.js.map +1 -0
  82. package/dist/asset/meshopt_decoder.js +18 -0
  83. package/dist/asset/meshopt_decoder.js.map +1 -0
  84. package/dist/asset/meshopt_simplifier.js +26 -0
  85. package/dist/asset/meshopt_simplifier.js.map +1 -0
  86. package/dist/asset/model.js +171 -1
  87. package/dist/asset/model.js.map +1 -1
  88. package/dist/asset/texture_settings.js +231 -0
  89. package/dist/asset/texture_settings.js.map +1 -0
  90. package/dist/asset/zmsh_binary.js +131 -0
  91. package/dist/asset/zmsh_binary.js.map +1 -0
  92. package/dist/asset/zsdf_binary.js +111 -0
  93. package/dist/asset/zsdf_binary.js.map +1 -0
  94. package/dist/blitter/bilateralblur.js +1 -2
  95. package/dist/blitter/bilateralblur.js.map +1 -1
  96. package/dist/blitter/gaussianblur.js +1 -6
  97. package/dist/blitter/gaussianblur.js.map +1 -1
  98. package/dist/camera/base.js +31 -10
  99. package/dist/camera/base.js.map +1 -1
  100. package/dist/camera/camera.js +104 -178
  101. package/dist/camera/camera.js.map +1 -1
  102. package/dist/camera/follow.js +342 -0
  103. package/dist/camera/follow.js.map +1 -0
  104. package/dist/camera/fps.js +9 -7
  105. package/dist/camera/fps.js.map +1 -1
  106. package/dist/camera/orbit.js +46 -19
  107. package/dist/camera/orbit.js.map +1 -1
  108. package/dist/index.d.ts +25436 -15990
  109. package/dist/index.js +65 -11
  110. package/dist/index.js.map +1 -1
  111. package/dist/material/blinn.js +3 -0
  112. package/dist/material/blinn.js.map +1 -1
  113. package/dist/material/eye.js +1 -1
  114. package/dist/material/eye.js.map +1 -1
  115. package/dist/material/hair.js +2 -3
  116. package/dist/material/hair.js.map +1 -1
  117. package/dist/material/lambert.js +4 -1
  118. package/dist/material/lambert.js.map +1 -1
  119. package/dist/material/material.js +66 -4
  120. package/dist/material/material.js.map +1 -1
  121. package/dist/material/meshmaterial.js +118 -45
  122. package/dist/material/meshmaterial.js.map +1 -1
  123. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  124. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  126. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  128. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  130. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  132. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  133. package/dist/material/mixins/lit.js +191 -83
  134. package/dist/material/mixins/lit.js.map +1 -1
  135. package/dist/material/mixins/pbr/common.js +31 -206
  136. package/dist/material/mixins/pbr/common.js.map +1 -1
  137. package/dist/material/mtoon.js +1 -1
  138. package/dist/material/mtoon.js.map +1 -1
  139. package/dist/material/pbrmr.js +3 -0
  140. package/dist/material/pbrmr.js.map +1 -1
  141. package/dist/material/pbrsg.js +3 -0
  142. package/dist/material/pbrsg.js.map +1 -1
  143. package/dist/material/sdf_debug.js +78 -0
  144. package/dist/material/sdf_debug.js.map +1 -0
  145. package/dist/material/shader/helper.js +333 -191
  146. package/dist/material/shader/helper.js.map +1 -1
  147. package/dist/material/shader/terrain_blend.js +204 -43
  148. package/dist/material/shader/terrain_blend.js.map +1 -1
  149. package/dist/material/skin.js +331 -297
  150. package/dist/material/skin.js.map +1 -1
  151. package/dist/material/skinprofile.js +1058 -0
  152. package/dist/material/skinprofile.js.map +1 -0
  153. package/dist/material/sss.js +353 -0
  154. package/dist/material/sss.js.map +1 -0
  155. package/dist/material/sss_kernel.js +265 -0
  156. package/dist/material/sss_kernel.js.map +1 -0
  157. package/dist/material/sssprofile.js +879 -0
  158. package/dist/material/sssprofile.js.map +1 -0
  159. package/dist/material/subsurfaceprofile.js +4 -8
  160. package/dist/material/subsurfaceprofile.js.map +1 -1
  161. package/dist/material/terrain-cm.js +464 -188
  162. package/dist/material/terrain-cm.js.map +1 -1
  163. package/dist/material/unlit.js +3 -0
  164. package/dist/material/unlit.js.map +1 -1
  165. package/dist/material/water.js +1261 -1438
  166. package/dist/material/water.js.map +1 -1
  167. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  168. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  169. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  172. package/dist/physics/character.js +226 -0
  173. package/dist/physics/character.js.map +1 -0
  174. package/dist/physics/collider.js +209 -0
  175. package/dist/physics/collider.js.map +1 -0
  176. package/dist/physics/events.js +79 -0
  177. package/dist/physics/events.js.map +1 -0
  178. package/dist/physics/joint.js +272 -0
  179. package/dist/physics/joint.js.map +1 -0
  180. package/dist/physics/node_physics.js +234 -0
  181. package/dist/physics/node_physics.js.map +1 -0
  182. package/dist/physics/part.js +91 -0
  183. package/dist/physics/part.js.map +1 -0
  184. package/dist/physics/rigid_body.js +379 -0
  185. package/dist/physics/rigid_body.js.map +1 -0
  186. package/dist/physics/vehicle.js +335 -0
  187. package/dist/physics/vehicle.js.map +1 -0
  188. package/dist/physics/world.js +25 -0
  189. package/dist/physics/world.js.map +1 -0
  190. package/dist/posteffect/bloom.js +49 -14
  191. package/dist/posteffect/bloom.js.map +1 -1
  192. package/dist/posteffect/motionblur.js +106 -106
  193. package/dist/posteffect/motionblur.js.map +1 -1
  194. package/dist/posteffect/postsss.js +572 -0
  195. package/dist/posteffect/postsss.js.map +1 -0
  196. package/dist/posteffect/sao.js +2 -6
  197. package/dist/posteffect/sao.js.map +1 -1
  198. package/dist/posteffect/skinsss.js +605 -355
  199. package/dist/posteffect/skinsss.js.map +1 -1
  200. package/dist/posteffect/ssgi.js +91 -162
  201. package/dist/posteffect/ssgi.js.map +1 -1
  202. package/dist/posteffect/ssr.js +3 -11
  203. package/dist/posteffect/ssr.js.map +1 -1
  204. package/dist/posteffect/sss.js +4 -13
  205. package/dist/posteffect/sss.js.map +1 -1
  206. package/dist/posteffect/taa.js +1 -0
  207. package/dist/posteffect/taa.js.map +1 -1
  208. package/dist/render/abuffer_oit.js +3 -2
  209. package/dist/render/abuffer_oit.js.map +1 -1
  210. package/dist/render/clipmap.js +179 -64
  211. package/dist/render/clipmap.js.map +1 -1
  212. package/dist/render/cluster_light.js +958 -224
  213. package/dist/render/cluster_light.js.map +1 -1
  214. package/dist/render/cull_visitor.js +25 -5
  215. package/dist/render/cull_visitor.js.map +1 -1
  216. package/dist/render/debug_views.js +37 -0
  217. package/dist/render/debug_views.js.map +1 -0
  218. package/dist/render/depthpass.js +5 -1
  219. package/dist/render/depthpass.js.map +1 -1
  220. package/dist/render/drawable_mixin.js +53 -6
  221. package/dist/render/drawable_mixin.js.map +1 -1
  222. package/dist/render/dualdepthpeeling_oit.js +5 -5
  223. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  224. package/dist/render/envlight.js +196 -113
  225. package/dist/render/envlight.js.map +1 -1
  226. package/dist/render/fbm_wavegenerator.js +5 -10
  227. package/dist/render/fbm_wavegenerator.js.map +1 -1
  228. package/dist/render/fft_wavegenerator.js +247 -157
  229. package/dist/render/fft_wavegenerator.js.map +1 -1
  230. package/dist/render/gerstner_wavegenerator.js +16 -38
  231. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  232. package/dist/render/gi/probe_volume.js +1334 -0
  233. package/dist/render/gi/probe_volume.js.map +1 -0
  234. package/dist/render/gi/scene_gi.js +282 -0
  235. package/dist/render/gi/scene_gi.js.map +1 -0
  236. package/dist/render/gi/voxel_atlas.js +198 -0
  237. package/dist/render/gi/voxel_atlas.js.map +1 -0
  238. package/dist/render/gi/voxel_lighting.js +652 -0
  239. package/dist/render/gi/voxel_lighting.js.map +1 -0
  240. package/dist/render/gi/voxel_scene.js +642 -0
  241. package/dist/render/gi/voxel_scene.js.map +1 -0
  242. package/dist/render/gi/voxelize_pass.js +223 -0
  243. package/dist/render/gi/voxelize_pass.js.map +1 -0
  244. package/dist/render/globalbindgroup_allocator.js +3 -2
  245. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  246. package/dist/render/gpu_picking.js +9 -36
  247. package/dist/render/gpu_picking.js.map +1 -1
  248. package/dist/render/instance_culling.js +499 -0
  249. package/dist/render/instance_culling.js.map +1 -0
  250. package/dist/render/lightpass.js +19 -8
  251. package/dist/render/lightpass.js.map +1 -1
  252. package/dist/render/lod.js +46 -0
  253. package/dist/render/lod.js.map +1 -0
  254. package/dist/render/primitive.js +301 -9
  255. package/dist/render/primitive.js.map +1 -1
  256. package/dist/render/primitive_readback.js +209 -0
  257. package/dist/render/primitive_readback.js.map +1 -0
  258. package/dist/render/render_queue.js +162 -11
  259. package/dist/render/render_queue.js.map +1 -1
  260. package/dist/render/renderer.js +10 -7
  261. package/dist/render/renderer.js.map +1 -1
  262. package/dist/render/rendergraph/blackboard.js +14 -1
  263. package/dist/render/rendergraph/blackboard.js.map +1 -1
  264. package/dist/render/rendergraph/executor.js +136 -0
  265. package/dist/render/rendergraph/executor.js.map +1 -1
  266. package/dist/render/rendergraph/forward_plus_builder.js +272 -55
  267. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  268. package/dist/render/rendergraph/frame_graph_context.js +41 -0
  269. package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
  270. package/dist/render/rendergraph/scene_render_context.js +31 -2
  271. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  272. package/dist/render/rendergraph/types.js.map +1 -1
  273. package/dist/render/renderpass.js +28 -5
  274. package/dist/render/renderpass.js.map +1 -1
  275. package/dist/render/sdf/box_allocator.js +98 -0
  276. package/dist/render/sdf/box_allocator.js.map +1 -0
  277. package/dist/render/sdf/global_sdf.js +865 -0
  278. package/dist/render/sdf/global_sdf.js.map +1 -0
  279. package/dist/render/sdf/scene_sdf.js +562 -0
  280. package/dist/render/sdf/scene_sdf.js.map +1 -0
  281. package/dist/render/sdf/sdf_atlas.js +227 -0
  282. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  283. package/dist/render/sdf/sdf_programs.js +42 -0
  284. package/dist/render/sdf/sdf_programs.js.map +1 -0
  285. package/dist/render/sdf/sdf_view.js +199 -0
  286. package/dist/render/sdf/sdf_view.js.map +1 -0
  287. package/dist/render/sdf/waterline.js +610 -0
  288. package/dist/render/sdf/waterline.js.map +1 -0
  289. package/dist/render/shadow_mask_pass.js +142 -25
  290. package/dist/render/shadow_mask_pass.js.map +1 -1
  291. package/dist/render/shore_wave_generator.js +1193 -0
  292. package/dist/render/shore_wave_generator.js.map +1 -0
  293. package/dist/render/sky.js +516 -86
  294. package/dist/render/sky.js.map +1 -1
  295. package/dist/render/transmission_thickness_pass.js +477 -0
  296. package/dist/render/transmission_thickness_pass.js.map +1 -0
  297. package/dist/render/underwater.js +58 -158
  298. package/dist/render/underwater.js.map +1 -1
  299. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  300. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  301. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  302. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  303. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  304. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  305. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  306. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  307. package/dist/render/volumetric_cloud/resources.js +380 -0
  308. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  309. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  310. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  311. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  312. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  313. package/dist/render/water_caustics.js +134 -319
  314. package/dist/render/water_caustics.js.map +1 -1
  315. package/dist/render/water_foam.js +627 -0
  316. package/dist/render/water_foam.js.map +1 -0
  317. package/dist/render/water_interaction.js +1795 -0
  318. package/dist/render/water_interaction.js.map +1 -0
  319. package/dist/render/weightedblended_oit.js +3 -3
  320. package/dist/render/weightedblended_oit.js.map +1 -1
  321. package/dist/scene/basesprite.js +9 -4
  322. package/dist/scene/basesprite.js.map +1 -1
  323. package/dist/scene/batchgroup.js +108 -12
  324. package/dist/scene/batchgroup.js.map +1 -1
  325. package/dist/scene/environment.js +28 -7
  326. package/dist/scene/environment.js.map +1 -1
  327. package/dist/scene/foliage.js +1020 -0
  328. package/dist/scene/foliage.js.map +1 -0
  329. package/dist/scene/foliage_buckets.js +147 -0
  330. package/dist/scene/foliage_buckets.js.map +1 -0
  331. package/dist/scene/foliage_mask.js +358 -0
  332. package/dist/scene/foliage_mask.js.map +1 -0
  333. package/dist/scene/hair.js +15 -4
  334. package/dist/scene/hair.js.map +1 -1
  335. package/dist/scene/light.js +179 -13
  336. package/dist/scene/light.js.map +1 -1
  337. package/dist/scene/mesh.js +327 -45
  338. package/dist/scene/mesh.js.map +1 -1
  339. package/dist/scene/meshdrawable.js +6 -0
  340. package/dist/scene/meshdrawable.js.map +1 -1
  341. package/dist/scene/msdftext.js +9 -3
  342. package/dist/scene/msdftext.js.map +1 -1
  343. package/dist/scene/msdftextsprite.js +9 -3
  344. package/dist/scene/msdftextsprite.js.map +1 -1
  345. package/dist/scene/particlesys.js +8 -2
  346. package/dist/scene/particlesys.js.map +1 -1
  347. package/dist/scene/physics_settings.js +157 -0
  348. package/dist/scene/physics_settings.js.map +1 -0
  349. package/dist/scene/scene.js +190 -44
  350. package/dist/scene/scene.js.map +1 -1
  351. package/dist/scene/scene_node.js +147 -6
  352. package/dist/scene/scene_node.js.map +1 -1
  353. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  354. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  355. package/dist/scene/terrain-cm/grass.js +881 -42
  356. package/dist/scene/terrain-cm/grass.js.map +1 -1
  357. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  358. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  359. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  360. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  361. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  362. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  363. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  364. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  365. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  366. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  367. package/dist/scene/update_queue.js +54 -0
  368. package/dist/scene/update_queue.js.map +1 -0
  369. package/dist/scene/water.js +633 -268
  370. package/dist/scene/water.js.map +1 -1
  371. package/dist/scene/water_surface_sampler.js +324 -0
  372. package/dist/scene/water_surface_sampler.js.map +1 -0
  373. package/dist/scene/wind.js +317 -0
  374. package/dist/scene/wind.js.map +1 -0
  375. package/dist/shaders/atmosphere.js +388 -166
  376. package/dist/shaders/atmosphere.js.map +1 -1
  377. package/dist/shaders/fog.js +100 -32
  378. package/dist/shaders/fog.js.map +1 -1
  379. package/dist/shaders/gi.js +365 -0
  380. package/dist/shaders/gi.js.map +1 -0
  381. package/dist/shaders/ltc_rect.js +202 -0
  382. package/dist/shaders/ltc_rect.js.map +1 -0
  383. package/dist/shaders/misc.js +1 -10
  384. package/dist/shaders/misc.js.map +1 -1
  385. package/dist/shaders/noise.js +5 -1
  386. package/dist/shaders/noise.js.map +1 -1
  387. package/dist/shaders/probes.js +309 -0
  388. package/dist/shaders/probes.js.map +1 -0
  389. package/dist/shaders/sdf.js +537 -0
  390. package/dist/shaders/sdf.js.map +1 -0
  391. package/dist/shaders/shadow.js +104 -70
  392. package/dist/shaders/shadow.js.map +1 -1
  393. package/dist/shaders/skin_brdf.js +243 -0
  394. package/dist/shaders/skin_brdf.js.map +1 -0
  395. package/dist/shaders/ssgi.js +63 -0
  396. package/dist/shaders/ssgi.js.map +1 -0
  397. package/dist/shaders/ssgi_reprojection.js +118 -0
  398. package/dist/shaders/ssgi_reprojection.js.map +1 -0
  399. package/dist/shaders/ssr.js +6 -159
  400. package/dist/shaders/ssr.js.map +1 -1
  401. package/dist/shaders/temporal.js +38 -27
  402. package/dist/shaders/temporal.js.map +1 -1
  403. package/dist/shaders/water.js +32 -82
  404. package/dist/shaders/water.js.map +1 -1
  405. package/dist/shaders/water_medium.js +7 -21
  406. package/dist/shaders/water_medium.js.map +1 -1
  407. package/dist/shadow/dom.js +110 -19
  408. package/dist/shadow/dom.js.map +1 -1
  409. package/dist/shadow/esm.js +3 -3
  410. package/dist/shadow/esm.js.map +1 -1
  411. package/dist/shadow/pcf_opt.js +15 -48
  412. package/dist/shadow/pcf_opt.js.map +1 -1
  413. package/dist/shadow/pcf_pd.js +15 -53
  414. package/dist/shadow/pcf_pd.js.map +1 -1
  415. package/dist/shadow/pcss.js +34 -9
  416. package/dist/shadow/pcss.js.map +1 -1
  417. package/dist/shadow/shadow_impl.js +3 -8
  418. package/dist/shadow/shadow_impl.js.map +1 -1
  419. package/dist/shadow/shadow_region.js +40 -2
  420. package/dist/shadow/shadow_region.js.map +1 -1
  421. package/dist/shadow/shadowmapper.js +93 -53
  422. package/dist/shadow/shadowmapper.js.map +1 -1
  423. package/dist/shadow/ssm.js +18 -72
  424. package/dist/shadow/ssm.js.map +1 -1
  425. package/dist/shadow/vsm.js +3 -3
  426. package/dist/shadow/vsm.js.map +1 -1
  427. package/dist/shapes/shape.js +44 -1
  428. package/dist/shapes/shape.js.map +1 -1
  429. package/dist/utility/buoyancy.js +287 -0
  430. package/dist/utility/buoyancy.js.map +1 -0
  431. package/dist/utility/physical.js +10 -1
  432. package/dist/utility/physical.js.map +1 -1
  433. package/dist/utility/pmrem.js +17 -43
  434. package/dist/utility/pmrem.js.map +1 -1
  435. package/dist/utility/sdf/bake.js +435 -0
  436. package/dist/utility/sdf/bake.js.map +1 -0
  437. package/dist/utility/sdf/bvh.js +576 -0
  438. package/dist/utility/sdf/bvh.js.map +1 -0
  439. package/dist/utility/serialization/manager.js +34 -6
  440. package/dist/utility/serialization/manager.js.map +1 -1
  441. package/dist/utility/serialization/scene/animation.js +46 -5
  442. package/dist/utility/serialization/scene/animation.js.map +1 -1
  443. package/dist/utility/serialization/scene/batch.js +11 -4
  444. package/dist/utility/serialization/scene/batch.js.map +1 -1
  445. package/dist/utility/serialization/scene/camera.js +87 -254
  446. package/dist/utility/serialization/scene/camera.js.map +1 -1
  447. package/dist/utility/serialization/scene/cloth.js +25 -0
  448. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  449. package/dist/utility/serialization/scene/common.js +14 -6
  450. package/dist/utility/serialization/scene/common.js.map +1 -1
  451. package/dist/utility/serialization/scene/foliage.js +821 -0
  452. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  453. package/dist/utility/serialization/scene/hair.js +11 -4
  454. package/dist/utility/serialization/scene/hair.js.map +1 -1
  455. package/dist/utility/serialization/scene/light.js +115 -7
  456. package/dist/utility/serialization/scene/light.js.map +1 -1
  457. package/dist/utility/serialization/scene/material.js +388 -220
  458. package/dist/utility/serialization/scene/material.js.map +1 -1
  459. package/dist/utility/serialization/scene/mesh.js +69 -4
  460. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  461. package/dist/utility/serialization/scene/node.js +140 -5
  462. package/dist/utility/serialization/scene/node.js.map +1 -1
  463. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  464. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  465. package/dist/utility/serialization/scene/particle.js +11 -4
  466. package/dist/utility/serialization/scene/particle.js.map +1 -1
  467. package/dist/utility/serialization/scene/physics.js +120 -0
  468. package/dist/utility/serialization/scene/physics.js.map +1 -0
  469. package/dist/utility/serialization/scene/primitive.js +124 -10
  470. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  471. package/dist/utility/serialization/scene/scene.js +1687 -51
  472. package/dist/utility/serialization/scene/scene.js.map +1 -1
  473. package/dist/utility/serialization/scene/sprite.js +11 -4
  474. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  475. package/dist/utility/serialization/scene/terrain.js +163 -33
  476. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  477. package/dist/utility/serialization/scene/text.js +11 -4
  478. package/dist/utility/serialization/scene/text.js.map +1 -1
  479. package/dist/utility/serialization/scene/water.js +1543 -264
  480. package/dist/utility/serialization/scene/water.js.map +1 -1
  481. package/dist/utility/serialization/types.js.map +1 -1
  482. package/dist/utility/shprojector.js +10 -22
  483. package/dist/utility/shprojector.js.map +1 -1
  484. package/dist/utility/textures/foam.js +170 -0
  485. package/dist/utility/textures/foam.js.map +1 -0
  486. package/dist/utility/textures/ggxlut.js +17 -43
  487. package/dist/utility/textures/ggxlut.js.map +1 -1
  488. package/dist/utility/textures/ltcdata.js +4 -4
  489. package/dist/utility/textures/ltcdata.js.map +1 -1
  490. package/dist/utility/textures/ltclut.js +16 -6
  491. package/dist/utility/textures/ltclut.js.map +1 -1
  492. package/dist/utility/unsupported.js +24 -0
  493. package/dist/utility/unsupported.js.map +1 -0
  494. package/dist/values.js +13 -1
  495. package/dist/values.js.map +1 -1
  496. package/package.json +25 -12
  497. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  498. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  499. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  500. package/src/asset/meshoptimizer/LICENSE +21 -0
  501. package/dist/animation/joint_dynamics/convex_collider.js +0 -320
  502. package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
@@ -0,0 +1,259 @@
1
+ import { defaultBasisTranscoderPath } from './basis_location.js';
2
+
3
+ // Runs inside each worker, appended after basis_transcoder.js which defines the
4
+ // BASIS module factory. Kept as plain source text so the bundler cannot rewrite
5
+ // it into something that depends on helpers living in the main bundle.
6
+ //
7
+ // The transcode loop follows three.js KTX2Loader (r180): startTranscoding() once,
8
+ // then getImageTranscodedSizeInBytes() + transcodeImage() per level/layer/face.
9
+ const WORKER_SOURCE = `
10
+ (function () {
11
+ var ready = null;
12
+ function transcode(module, buffer, targets) {
13
+ var file = new module.KTX2File(new Uint8Array(buffer));
14
+ try {
15
+ if (!file.isValid()) {
16
+ throw new Error('Invalid KTX2 file, or not Basis Universal encoded');
17
+ }
18
+ if (file.isHDR()) {
19
+ throw new Error('HDR KTX2 textures are not supported yet');
20
+ }
21
+ var width = file.getWidth();
22
+ var height = file.getHeight();
23
+ var levels = Math.max(1, file.getLevels());
24
+ var faces = file.getFaces();
25
+ var layers = file.getLayers();
26
+ var hasAlpha = !!file.getHasAlpha();
27
+ var group = file.isETC1S() ? targets.etc1s : targets.uastc;
28
+ var target = hasAlpha ? group.alpha : group.opaque;
29
+ if (target.compressed && (width % 4 !== 0 || height % 4 !== 0)) {
30
+ target = targets.fallback;
31
+ }
32
+ if (!file.startTranscoding()) {
33
+ throw new Error('startTranscoding() failed');
34
+ }
35
+ var images = [];
36
+ var levelWidths = [];
37
+ var levelHeights = [];
38
+ var slices = faces * Math.max(1, layers);
39
+ for (var slice = 0; slice < slices; slice++) {
40
+ var face = slice % faces;
41
+ var layer = Math.floor(slice / faces);
42
+ for (var level = 0; level < levels; level++) {
43
+ var info = file.getImageLevelInfo(level, layer, face);
44
+ var dst = new Uint8Array(file.getImageTranscodedSizeInBytes(level, layer, face, target.transcoderFormat));
45
+ if (!file.transcodeImage(dst, level, layer, face, target.transcoderFormat, 0, -1, -1)) {
46
+ throw new Error('transcodeImage() failed at level ' + level + ', layer ' + layer + ', face ' + face);
47
+ }
48
+ images.push(dst);
49
+ if (slice === 0) {
50
+ levelWidths.push(info.origWidth);
51
+ levelHeights.push(info.origHeight);
52
+ }
53
+ }
54
+ }
55
+ return {
56
+ width: width,
57
+ height: height,
58
+ levels: levels,
59
+ faces: faces,
60
+ layers: layers,
61
+ textureFormat: target.textureFormat,
62
+ compressed: target.compressed,
63
+ images: images,
64
+ levelWidths: levelWidths,
65
+ levelHeights: levelHeights
66
+ };
67
+ } finally {
68
+ file.close();
69
+ file.delete();
70
+ }
71
+ }
72
+ self.onmessage = function (e) {
73
+ var msg = e.data;
74
+ if (msg.type === 'init') {
75
+ ready = BASIS({ wasmBinary: msg.wasm }).then(function (module) {
76
+ module.initializeBasis();
77
+ return module;
78
+ });
79
+ } else if (msg.type === 'transcode') {
80
+ ready
81
+ .then(function (module) {
82
+ var result = transcode(module, msg.buffer, msg.targets);
83
+ self.postMessage(
84
+ { type: 'result', id: msg.id, result: result },
85
+ result.images.map(function (img) { return img.buffer; })
86
+ );
87
+ })
88
+ .catch(function (err) {
89
+ self.postMessage({ type: 'error', id: msg.id, message: String((err && err.message) || err) });
90
+ });
91
+ }
92
+ };
93
+ })();
94
+ `;
95
+ function assertWasm(data, url) {
96
+ // A dev server or SPA host answering a missing file with index.html still
97
+ // returns 200; catch that here instead of as an opaque CompileError
98
+ const head = new Uint8Array(data, 0, Math.min(4, data.byteLength));
99
+ if (head.length < 4 || head[0] !== 0x00 || head[1] !== 0x61 || head[2] !== 0x73 || head[3] !== 0x6d) {
100
+ throw new Error(`${url} is not a WebAssembly file; is it deployed at that location?`);
101
+ }
102
+ }
103
+ /**
104
+ * Pool of web workers running the Basis Universal transcoder.
105
+ *
106
+ * Nothing is downloaded or spawned until the first transcode request, so pages
107
+ * that never load a KTX2 texture pay nothing for it.
108
+ *
109
+ * @internal
110
+ */ class BasisTranscoder {
111
+ static _instance = null;
112
+ static _path = null;
113
+ static _workerCount = 0;
114
+ _workers;
115
+ _requests;
116
+ _nextId;
117
+ constructor(){
118
+ this._workers = null;
119
+ this._requests = new Map();
120
+ this._nextId = 1;
121
+ }
122
+ /** Directory URL holding basis_transcoder.js and basis_transcoder.wasm, null for the bundled copy */ static get path() {
123
+ return this._path;
124
+ }
125
+ static set path(url) {
126
+ if (url !== this._path) {
127
+ this._path = url;
128
+ this.reset();
129
+ }
130
+ }
131
+ /** Number of workers, 0 picks one from the hardware concurrency */ static get workerCount() {
132
+ return this._workerCount;
133
+ }
134
+ static set workerCount(n) {
135
+ if (n !== this._workerCount) {
136
+ this._workerCount = Math.max(0, n >>> 0);
137
+ this.reset();
138
+ }
139
+ }
140
+ static get instance() {
141
+ if (!this._instance) {
142
+ this._instance = new BasisTranscoder();
143
+ }
144
+ return this._instance;
145
+ }
146
+ /** Terminates the workers; they are recreated with the current settings on next use */ static reset() {
147
+ if (this._instance) {
148
+ this._instance.dispose();
149
+ this._instance = null;
150
+ }
151
+ }
152
+ transcode(data, targets) {
153
+ return this.getWorkers().then((workers)=>new Promise((resolve, reject)=>{
154
+ const entry = workers.reduce((a, b)=>b.pending < a.pending ? b : a);
155
+ const id = this._nextId++;
156
+ entry.pending++;
157
+ this._requests.set(id, {
158
+ resolve: (result)=>{
159
+ entry.pending--;
160
+ resolve(result);
161
+ },
162
+ reject: (err)=>{
163
+ entry.pending--;
164
+ reject(err);
165
+ }
166
+ });
167
+ // Copy so the caller keeps its data and a view into a larger buffer (a .glb
168
+ // chunk) does not ship the whole buffer to the worker
169
+ const buffer = data.slice().buffer;
170
+ entry.worker.postMessage({
171
+ type: 'transcode',
172
+ id,
173
+ buffer,
174
+ targets
175
+ }, [
176
+ buffer
177
+ ]);
178
+ }));
179
+ }
180
+ dispose() {
181
+ const workers = this._workers;
182
+ this._workers = null;
183
+ workers?.then((list)=>{
184
+ list.forEach((w)=>w.worker.terminate());
185
+ if (list.length > 0) {
186
+ URL.revokeObjectURL(list[0].scriptUrl);
187
+ }
188
+ }, ()=>{});
189
+ for (const req of this._requests.values()){
190
+ req.reject(new Error('Basis transcoder was reset'));
191
+ }
192
+ this._requests.clear();
193
+ }
194
+ getWorkers() {
195
+ if (!this._workers) {
196
+ this._workers = this.createWorkers();
197
+ // Allow a retry after a failed download instead of caching the failure forever
198
+ this._workers.catch(()=>{
199
+ this._workers = null;
200
+ });
201
+ }
202
+ return this._workers;
203
+ }
204
+ async createWorkers() {
205
+ const base = BasisTranscoder._path ?? defaultBasisTranscoderPath();
206
+ const dir = base.endsWith('/') ? base : `${base}/`;
207
+ const [jsResponse, wasmResponse] = await Promise.all([
208
+ fetch(`${dir}basis_transcoder.js`),
209
+ fetch(`${dir}basis_transcoder.wasm`)
210
+ ]);
211
+ if (!jsResponse.ok || !wasmResponse.ok) {
212
+ throw new Error(`Failed to load the Basis transcoder from ${dir} (HTTP ${jsResponse.status}/${wasmResponse.status}). ` + 'Set KTX2Loader.transcoderPath to the directory that holds basis_transcoder.js and basis_transcoder.wasm.');
213
+ }
214
+ const [jsSource, wasm] = await Promise.all([
215
+ jsResponse.text(),
216
+ wasmResponse.arrayBuffer()
217
+ ]);
218
+ assertWasm(wasm, `${dir}basis_transcoder.wasm`);
219
+ const blobUrl = URL.createObjectURL(new Blob([
220
+ jsSource,
221
+ WORKER_SOURCE
222
+ ], {
223
+ type: 'application/javascript'
224
+ }));
225
+ const count = BasisTranscoder._workerCount || Math.max(1, Math.min(4, (globalThis.navigator?.hardwareConcurrency ?? 4) - 1));
226
+ const workers = [];
227
+ for(let i = 0; i < count; i++){
228
+ const worker = new Worker(blobUrl);
229
+ worker.onmessage = (e)=>this.onMessage(e.data);
230
+ worker.onerror = (e)=>console.error(`Basis transcoder worker error: ${e.message}`);
231
+ // Each worker gets its own copy, a transferred buffer could only go to one
232
+ worker.postMessage({
233
+ type: 'init',
234
+ wasm: wasm.slice(0)
235
+ });
236
+ workers.push({
237
+ worker,
238
+ pending: 0,
239
+ scriptUrl: blobUrl
240
+ });
241
+ }
242
+ return workers;
243
+ }
244
+ onMessage(msg) {
245
+ const req = this._requests.get(msg.id);
246
+ if (!req) {
247
+ return;
248
+ }
249
+ this._requests.delete(msg.id);
250
+ if (msg.type === 'result') {
251
+ req.resolve(msg.result);
252
+ } else {
253
+ req.reject(new Error(`KTX2 transcode failed: ${msg.message}`));
254
+ }
255
+ }
256
+ }
257
+
258
+ export { BasisTranscoder };
259
+ //# sourceMappingURL=transcoder_pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcoder_pool.js","sources":["../../../../src/asset/loaders/ktx2/transcoder_pool.ts"],"sourcesContent":["import type { TextureFormat } from '@zephyr3d/device';\r\nimport type { KTX2TranscodeTargets } from './ktx2_targets';\r\nimport { defaultBasisTranscoderPath } from './basis_location';\r\n\r\n/**\r\n * Result of transcoding one KTX2 file. `images` is ordered slice-major: every\r\n * mip level of face/layer 0, then every level of face/layer 1, and so on.\r\n * @internal\r\n */\r\nexport interface KTX2TranscodeResult {\r\n width: number;\r\n height: number;\r\n levels: number;\r\n faces: number;\r\n /** Raw KTX2 layer count, 0 when the texture is not an array */\r\n layers: number;\r\n textureFormat: TextureFormat;\r\n compressed: boolean;\r\n images: Uint8Array<ArrayBuffer>[];\r\n levelWidths: number[];\r\n levelHeights: number[];\r\n}\r\n\r\n// Runs inside each worker, appended after basis_transcoder.js which defines the\r\n// BASIS module factory. Kept as plain source text so the bundler cannot rewrite\r\n// it into something that depends on helpers living in the main bundle.\r\n//\r\n// The transcode loop follows three.js KTX2Loader (r180): startTranscoding() once,\r\n// then getImageTranscodedSizeInBytes() + transcodeImage() per level/layer/face.\r\nconst WORKER_SOURCE = `\r\n(function () {\r\n var ready = null;\r\n function transcode(module, buffer, targets) {\r\n var file = new module.KTX2File(new Uint8Array(buffer));\r\n try {\r\n if (!file.isValid()) {\r\n throw new Error('Invalid KTX2 file, or not Basis Universal encoded');\r\n }\r\n if (file.isHDR()) {\r\n throw new Error('HDR KTX2 textures are not supported yet');\r\n }\r\n var width = file.getWidth();\r\n var height = file.getHeight();\r\n var levels = Math.max(1, file.getLevels());\r\n var faces = file.getFaces();\r\n var layers = file.getLayers();\r\n var hasAlpha = !!file.getHasAlpha();\r\n var group = file.isETC1S() ? targets.etc1s : targets.uastc;\r\n var target = hasAlpha ? group.alpha : group.opaque;\r\n if (target.compressed && (width % 4 !== 0 || height % 4 !== 0)) {\r\n target = targets.fallback;\r\n }\r\n if (!file.startTranscoding()) {\r\n throw new Error('startTranscoding() failed');\r\n }\r\n var images = [];\r\n var levelWidths = [];\r\n var levelHeights = [];\r\n var slices = faces * Math.max(1, layers);\r\n for (var slice = 0; slice < slices; slice++) {\r\n var face = slice % faces;\r\n var layer = Math.floor(slice / faces);\r\n for (var level = 0; level < levels; level++) {\r\n var info = file.getImageLevelInfo(level, layer, face);\r\n var dst = new Uint8Array(file.getImageTranscodedSizeInBytes(level, layer, face, target.transcoderFormat));\r\n if (!file.transcodeImage(dst, level, layer, face, target.transcoderFormat, 0, -1, -1)) {\r\n throw new Error('transcodeImage() failed at level ' + level + ', layer ' + layer + ', face ' + face);\r\n }\r\n images.push(dst);\r\n if (slice === 0) {\r\n levelWidths.push(info.origWidth);\r\n levelHeights.push(info.origHeight);\r\n }\r\n }\r\n }\r\n return {\r\n width: width,\r\n height: height,\r\n levels: levels,\r\n faces: faces,\r\n layers: layers,\r\n textureFormat: target.textureFormat,\r\n compressed: target.compressed,\r\n images: images,\r\n levelWidths: levelWidths,\r\n levelHeights: levelHeights\r\n };\r\n } finally {\r\n file.close();\r\n file.delete();\r\n }\r\n }\r\n self.onmessage = function (e) {\r\n var msg = e.data;\r\n if (msg.type === 'init') {\r\n ready = BASIS({ wasmBinary: msg.wasm }).then(function (module) {\r\n module.initializeBasis();\r\n return module;\r\n });\r\n } else if (msg.type === 'transcode') {\r\n ready\r\n .then(function (module) {\r\n var result = transcode(module, msg.buffer, msg.targets);\r\n self.postMessage(\r\n { type: 'result', id: msg.id, result: result },\r\n result.images.map(function (img) { return img.buffer; })\r\n );\r\n })\r\n .catch(function (err) {\r\n self.postMessage({ type: 'error', id: msg.id, message: String((err && err.message) || err) });\r\n });\r\n }\r\n };\r\n})();\r\n`;\r\n\r\ninterface PendingRequest {\r\n resolve: (result: KTX2TranscodeResult) => void;\r\n reject: (err: Error) => void;\r\n}\r\n\r\ninterface TranscoderWorker {\r\n worker: Worker;\r\n pending: number;\r\n /** Blob URL of the worker script, shared by the pool and revoked with it */\r\n scriptUrl: string;\r\n}\r\n\r\nfunction assertWasm(data: ArrayBuffer, url: string) {\r\n // A dev server or SPA host answering a missing file with index.html still\r\n // returns 200; catch that here instead of as an opaque CompileError\r\n const head = new Uint8Array(data, 0, Math.min(4, data.byteLength));\r\n if (head.length < 4 || head[0] !== 0x00 || head[1] !== 0x61 || head[2] !== 0x73 || head[3] !== 0x6d) {\r\n throw new Error(`${url} is not a WebAssembly file; is it deployed at that location?`);\r\n }\r\n}\r\n\r\n/**\r\n * Pool of web workers running the Basis Universal transcoder.\r\n *\r\n * Nothing is downloaded or spawned until the first transcode request, so pages\r\n * that never load a KTX2 texture pay nothing for it.\r\n *\r\n * @internal\r\n */\r\nexport class BasisTranscoder {\r\n private static _instance: BasisTranscoder | null = null;\r\n private static _path: string | null = null;\r\n private static _workerCount = 0;\r\n private _workers: Promise<TranscoderWorker[]> | null;\r\n private readonly _requests: Map<number, PendingRequest>;\r\n private _nextId: number;\r\n private constructor() {\r\n this._workers = null;\r\n this._requests = new Map();\r\n this._nextId = 1;\r\n }\r\n /** Directory URL holding basis_transcoder.js and basis_transcoder.wasm, null for the bundled copy */\r\n static get path() {\r\n return this._path;\r\n }\r\n static set path(url: string | null) {\r\n if (url !== this._path) {\r\n this._path = url;\r\n this.reset();\r\n }\r\n }\r\n /** Number of workers, 0 picks one from the hardware concurrency */\r\n static get workerCount() {\r\n return this._workerCount;\r\n }\r\n static set workerCount(n: number) {\r\n if (n !== this._workerCount) {\r\n this._workerCount = Math.max(0, n >>> 0);\r\n this.reset();\r\n }\r\n }\r\n static get instance() {\r\n if (!this._instance) {\r\n this._instance = new BasisTranscoder();\r\n }\r\n return this._instance;\r\n }\r\n /** Terminates the workers; they are recreated with the current settings on next use */\r\n static reset() {\r\n if (this._instance) {\r\n this._instance.dispose();\r\n this._instance = null;\r\n }\r\n }\r\n transcode(data: Uint8Array<ArrayBuffer>, targets: KTX2TranscodeTargets): Promise<KTX2TranscodeResult> {\r\n return this.getWorkers().then(\r\n (workers) =>\r\n new Promise<KTX2TranscodeResult>((resolve, reject) => {\r\n const entry = workers.reduce((a, b) => (b.pending < a.pending ? b : a));\r\n const id = this._nextId++;\r\n entry.pending++;\r\n this._requests.set(id, {\r\n resolve: (result) => {\r\n entry.pending--;\r\n resolve(result);\r\n },\r\n reject: (err) => {\r\n entry.pending--;\r\n reject(err);\r\n }\r\n });\r\n // Copy so the caller keeps its data and a view into a larger buffer (a .glb\r\n // chunk) does not ship the whole buffer to the worker\r\n const buffer = data.slice().buffer;\r\n entry.worker.postMessage({ type: 'transcode', id, buffer, targets }, [buffer]);\r\n })\r\n );\r\n }\r\n private dispose() {\r\n const workers = this._workers;\r\n this._workers = null;\r\n workers?.then(\r\n (list) => {\r\n list.forEach((w) => w.worker.terminate());\r\n if (list.length > 0) {\r\n URL.revokeObjectURL(list[0].scriptUrl);\r\n }\r\n },\r\n () => {}\r\n );\r\n for (const req of this._requests.values()) {\r\n req.reject(new Error('Basis transcoder was reset'));\r\n }\r\n this._requests.clear();\r\n }\r\n private getWorkers() {\r\n if (!this._workers) {\r\n this._workers = this.createWorkers();\r\n // Allow a retry after a failed download instead of caching the failure forever\r\n this._workers.catch(() => {\r\n this._workers = null;\r\n });\r\n }\r\n return this._workers;\r\n }\r\n private async createWorkers(): Promise<TranscoderWorker[]> {\r\n const base = BasisTranscoder._path ?? defaultBasisTranscoderPath();\r\n const dir = base.endsWith('/') ? base : `${base}/`;\r\n const [jsResponse, wasmResponse] = await Promise.all([\r\n fetch(`${dir}basis_transcoder.js`),\r\n fetch(`${dir}basis_transcoder.wasm`)\r\n ]);\r\n if (!jsResponse.ok || !wasmResponse.ok) {\r\n throw new Error(\r\n `Failed to load the Basis transcoder from ${dir} (HTTP ${jsResponse.status}/${wasmResponse.status}). ` +\r\n 'Set KTX2Loader.transcoderPath to the directory that holds basis_transcoder.js and basis_transcoder.wasm.'\r\n );\r\n }\r\n const [jsSource, wasm] = await Promise.all([jsResponse.text(), wasmResponse.arrayBuffer()]);\r\n assertWasm(wasm, `${dir}basis_transcoder.wasm`);\r\n const blobUrl = URL.createObjectURL(\r\n new Blob([jsSource, WORKER_SOURCE], { type: 'application/javascript' })\r\n );\r\n const count =\r\n BasisTranscoder._workerCount ||\r\n Math.max(1, Math.min(4, (globalThis.navigator?.hardwareConcurrency ?? 4) - 1));\r\n const workers: TranscoderWorker[] = [];\r\n for (let i = 0; i < count; i++) {\r\n const worker = new Worker(blobUrl);\r\n worker.onmessage = (e: MessageEvent) => this.onMessage(e.data);\r\n worker.onerror = (e: ErrorEvent) => console.error(`Basis transcoder worker error: ${e.message}`);\r\n // Each worker gets its own copy, a transferred buffer could only go to one\r\n worker.postMessage({ type: 'init', wasm: wasm.slice(0) });\r\n workers.push({ worker, pending: 0, scriptUrl: blobUrl });\r\n }\r\n return workers;\r\n }\r\n private onMessage(msg: { type: string; id: number; result?: KTX2TranscodeResult; message?: string }) {\r\n const req = this._requests.get(msg.id);\r\n if (!req) {\r\n return;\r\n }\r\n this._requests.delete(msg.id);\r\n if (msg.type === 'result') {\r\n req.resolve(msg.result!);\r\n } else {\r\n req.reject(new Error(`KTX2 transcode failed: ${msg.message}`));\r\n }\r\n }\r\n}\r\n"],"names":["WORKER_SOURCE","assertWasm","data","url","head","Uint8Array","Math","min","byteLength","length","Error","BasisTranscoder","_instance","_path","_workerCount","_workers","_requests","_nextId","Map","path","reset","workerCount","n","max","instance","dispose","transcode","targets","getWorkers","then","workers","Promise","resolve","reject","entry","reduce","a","b","pending","id","set","result","err","buffer","slice","worker","postMessage","type","list","forEach","w","terminate","URL","revokeObjectURL","scriptUrl","req","values","clear","createWorkers","catch","base","defaultBasisTranscoderPath","dir","endsWith","jsResponse","wasmResponse","all","fetch","ok","status","jsSource","wasm","text","arrayBuffer","blobUrl","createObjectURL","Blob","count","globalThis","navigator","hardwareConcurrency","i","Worker","onmessage","e","onMessage","onerror","console","error","message","push","msg","get","delete"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ // Builds the level of detail chain of a mesh, for the editor's derived mesh cache and
2
+ // for SharedModel.generateLods at runtime. Pure data work with the simplifier passed in,
3
+ // no other engine module imported, so it also runs in the editor's encoding worker.
4
+ /**
5
+ * The subset of meshoptimizer's MeshoptSimplifier the level of detail generation uses. The engine
6
+ * does not ship the simplifier: pass meshoptimizer's, which `loadMeshoptSimplifier()` of the
7
+ * loaders package returns.
8
+ * @public
9
+ */ const MAX_LEVELS = 8;
10
+ const LOD0_SCREEN_SIZE = 2;
11
+ const AUTO_LOD_POWER_BASE = 0.75;
12
+ const LOD_HYSTERESIS = 0.02;
13
+ /**
14
+ * Weight of the vertex normals in the simplification error. The meshoptimizer README advises
15
+ * "around 1.0" for normalized attributes; texture seams are kept from the index topology alone.
16
+ */ const NORMAL_WEIGHT = 1;
17
+ /** An error bound the simplifier never reaches, within float range */ const NO_ERROR_LIMIT = 1e30;
18
+ function calculateViewDistance(maxDeviation, pixelError) {
19
+ return maxDeviation * 960 / Math.max(pixelError, Number.EPSILON);
20
+ }
21
+ function autoScreenSize(sphereRadius, viewDistance) {
22
+ const screenMultiple = Math.max(0.5, 0.5 * 1920 / 1080);
23
+ const screenRadius = screenMultiple * sphereRadius / Math.max(0.01, viewDistance);
24
+ return screenRadius * 2;
25
+ }
26
+ /**
27
+ * Simplifies a triangle list into a level of detail chain. Returns the indices of every level
28
+ * back to back, the source first, and the level table. Levels are added while the next target
29
+ * keeps at least `lodMinTriangles` triangles, as getMeshLodTargets in the engine predicts; the
30
+ * chain ends early when simplification stops removing triangles or falls below that minimum.
31
+ *
32
+ * @param simplifier - meshoptimizer's simplifier, ready
33
+ * @param indices - Source triangle list
34
+ * @param positions - 3 floats per vertex
35
+ * @param normals - 3 floats per vertex, or null
36
+ * @param sphereRadius - Radius of the sphere around the mesh bounds, as the runtime measures it
37
+ * @param settings - Level settings
38
+ * @public
39
+ */ function buildLodChain(simplifier, indices, positions, normals, sphereRadius, settings) {
40
+ const chains = [
41
+ indices
42
+ ];
43
+ const levels = [
44
+ {
45
+ indexStart: 0,
46
+ indexCount: indices.length,
47
+ screenSize: LOD0_SCREEN_SIZE,
48
+ hysteresis: 0,
49
+ error: 0
50
+ }
51
+ ];
52
+ let indexStart = indices.length;
53
+ const minIndices = Math.max(settings.lodMinTriangles, 1) * 3;
54
+ for(let i = 1; i < MAX_LEVELS; i++){
55
+ const target = Math.floor(indices.length * settings.lodReduction ** i / 3) * 3;
56
+ if (target < minIndices) {
57
+ break;
58
+ }
59
+ const flags = [
60
+ 'ErrorAbsolute',
61
+ 'Prune'
62
+ ];
63
+ const [lod, error] = normals ? simplifier.simplifyWithAttributes(indices, positions, 3, normals, 3, [
64
+ NORMAL_WEIGHT,
65
+ NORMAL_WEIGHT,
66
+ NORMAL_WEIGHT
67
+ ], null, target, NO_ERROR_LIMIT, flags) : simplifier.simplify(indices, positions, 3, target, NO_ERROR_LIMIT, flags);
68
+ // No progress over the previous level: nothing coarser can follow either
69
+ if (lod.length === 0 || lod.length >= chains[chains.length - 1].length) {
70
+ break;
71
+ }
72
+ // Pruning disconnected parts can overshoot the target; every later target is smaller still
73
+ if (lod.length < minIndices) {
74
+ break;
75
+ }
76
+ const previous = levels[levels.length - 1];
77
+ let screenSize = error > 0 ? autoScreenSize(sphereRadius, calculateViewDistance(error, settings.lodPixelError) + sphereRadius) : AUTO_LOD_POWER_BASE ** i;
78
+ if (screenSize > previous.screenSize) {
79
+ screenSize = previous.screenSize / 2;
80
+ }
81
+ chains.push(lod);
82
+ levels.push({
83
+ indexStart,
84
+ indexCount: lod.length,
85
+ screenSize,
86
+ hysteresis: LOD_HYSTERESIS,
87
+ error
88
+ });
89
+ indexStart += lod.length;
90
+ }
91
+ const all = new Uint32Array(indexStart);
92
+ let offset = 0;
93
+ for (const chain of chains){
94
+ all.set(chain, offset);
95
+ offset += chain.length;
96
+ }
97
+ return {
98
+ indices: all,
99
+ levels
100
+ };
101
+ }
102
+
103
+ export { buildLodChain };
104
+ //# sourceMappingURL=mesh_lod_builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh_lod_builder.js","sources":["../../src/asset/mesh_lod_builder.ts"],"sourcesContent":["// Builds the level of detail chain of a mesh, for the editor's derived mesh cache and\r\n// for SharedModel.generateLods at runtime. Pure data work with the simplifier passed in,\r\n// no other engine module imported, so it also runs in the editor's encoding worker.\r\n\r\n/**\r\n * The subset of meshoptimizer's MeshoptSimplifier the level of detail generation uses. The engine\r\n * does not ship the simplifier: pass meshoptimizer's, which `loadMeshoptSimplifier()` of the\r\n * loaders package returns.\r\n * @public\r\n */\r\nexport interface MeshSimplifier {\r\n simplify(\r\n indices: Uint32Array,\r\n positions: Float32Array,\r\n positionsStride: number,\r\n targetIndexCount: number,\r\n targetError: number,\r\n flags?: string[]\r\n ): [Uint32Array, number];\r\n simplifyWithAttributes(\r\n indices: Uint32Array,\r\n positions: Float32Array,\r\n positionsStride: number,\r\n attributes: Float32Array,\r\n attributesStride: number,\r\n attributeWeights: number[],\r\n vertexLock: Uint8Array | null,\r\n targetIndexCount: number,\r\n targetError: number,\r\n flags?: string[]\r\n ): [Uint32Array, number];\r\n}\r\n\r\n/**\r\n * How levels of detail are generated, see {@link MeshImportSettings} for the same settings of the\r\n * editor.\r\n * @public\r\n */\r\nexport interface MeshLodSettings {\r\n /** Fewest triangles a generated level may have; the level count follows from it */\r\n lodMinTriangles: number;\r\n /** Fraction of the source triangles kept per level step */\r\n lodReduction: number;\r\n /** Pixel error the automatic switch distances allow */\r\n lodPixelError: number;\r\n}\r\n\r\n/**\r\n * A generated level of detail.\r\n * @public\r\n */\r\nexport interface MeshLodLevel {\r\n indexStart: number;\r\n indexCount: number;\r\n screenSize: number;\r\n hysteresis: number;\r\n /** Largest distance between the level and the source surface, in mesh units */\r\n error: number;\r\n}\r\n\r\nconst MAX_LEVELS = 8;\r\nconst LOD0_SCREEN_SIZE = 2;\r\nconst AUTO_LOD_POWER_BASE = 0.75;\r\nconst LOD_HYSTERESIS = 0.02;\r\n/**\r\n * Weight of the vertex normals in the simplification error. The meshoptimizer README advises\r\n * \"around 1.0\" for normalized attributes; texture seams are kept from the index topology alone.\r\n */\r\nconst NORMAL_WEIGHT = 1;\r\n/** An error bound the simplifier never reaches, within float range */\r\nconst NO_ERROR_LIMIT = 1e30;\r\n\r\nfunction calculateViewDistance(maxDeviation: number, pixelError: number) {\r\n return (maxDeviation * 960) / Math.max(pixelError, Number.EPSILON);\r\n}\r\n\r\nfunction autoScreenSize(sphereRadius: number, viewDistance: number) {\r\n const screenMultiple = Math.max(0.5, (0.5 * 1920) / 1080);\r\n const screenRadius = (screenMultiple * sphereRadius) / Math.max(0.01, viewDistance);\r\n return screenRadius * 2;\r\n}\r\n\r\n/**\r\n * Simplifies a triangle list into a level of detail chain. Returns the indices of every level\r\n * back to back, the source first, and the level table. Levels are added while the next target\r\n * keeps at least `lodMinTriangles` triangles, as getMeshLodTargets in the engine predicts; the\r\n * chain ends early when simplification stops removing triangles or falls below that minimum.\r\n *\r\n * @param simplifier - meshoptimizer's simplifier, ready\r\n * @param indices - Source triangle list\r\n * @param positions - 3 floats per vertex\r\n * @param normals - 3 floats per vertex, or null\r\n * @param sphereRadius - Radius of the sphere around the mesh bounds, as the runtime measures it\r\n * @param settings - Level settings\r\n * @public\r\n */\r\nexport function buildLodChain(\r\n simplifier: MeshSimplifier,\r\n indices: Uint32Array,\r\n positions: Float32Array,\r\n normals: Float32Array | null,\r\n sphereRadius: number,\r\n settings: MeshLodSettings\r\n) {\r\n const chains: Uint32Array[] = [indices];\r\n const levels: MeshLodLevel[] = [\r\n { indexStart: 0, indexCount: indices.length, screenSize: LOD0_SCREEN_SIZE, hysteresis: 0, error: 0 }\r\n ];\r\n let indexStart = indices.length;\r\n const minIndices = Math.max(settings.lodMinTriangles, 1) * 3;\r\n for (let i = 1; i < MAX_LEVELS; i++) {\r\n const target = Math.floor((indices.length * settings.lodReduction ** i) / 3) * 3;\r\n if (target < minIndices) {\r\n break;\r\n }\r\n const flags = ['ErrorAbsolute', 'Prune'];\r\n const [lod, error] = normals\r\n ? simplifier.simplifyWithAttributes(\r\n indices,\r\n positions,\r\n 3,\r\n normals,\r\n 3,\r\n [NORMAL_WEIGHT, NORMAL_WEIGHT, NORMAL_WEIGHT],\r\n null,\r\n target,\r\n NO_ERROR_LIMIT,\r\n flags\r\n )\r\n : simplifier.simplify(indices, positions, 3, target, NO_ERROR_LIMIT, flags);\r\n // No progress over the previous level: nothing coarser can follow either\r\n if (lod.length === 0 || lod.length >= chains[chains.length - 1].length) {\r\n break;\r\n }\r\n // Pruning disconnected parts can overshoot the target; every later target is smaller still\r\n if (lod.length < minIndices) {\r\n break;\r\n }\r\n const previous = levels[levels.length - 1];\r\n let screenSize =\r\n error > 0\r\n ? autoScreenSize(sphereRadius, calculateViewDistance(error, settings.lodPixelError) + sphereRadius)\r\n : AUTO_LOD_POWER_BASE ** i;\r\n if (screenSize > previous.screenSize) {\r\n screenSize = previous.screenSize / 2;\r\n }\r\n chains.push(lod);\r\n levels.push({ indexStart, indexCount: lod.length, screenSize, hysteresis: LOD_HYSTERESIS, error });\r\n indexStart += lod.length;\r\n }\r\n const all = new Uint32Array(indexStart);\r\n let offset = 0;\r\n for (const chain of chains) {\r\n all.set(chain, offset);\r\n offset += chain.length;\r\n }\r\n return { indices: all, levels };\r\n}\r\n"],"names":["MAX_LEVELS","LOD0_SCREEN_SIZE","AUTO_LOD_POWER_BASE","LOD_HYSTERESIS","NORMAL_WEIGHT","NO_ERROR_LIMIT","calculateViewDistance","maxDeviation","pixelError","Math","max","Number","EPSILON","autoScreenSize","sphereRadius","viewDistance","screenMultiple","screenRadius","buildLodChain","simplifier","indices","positions","normals","settings","chains","levels","indexStart","indexCount","length","screenSize","hysteresis","error","minIndices","lodMinTriangles","i","target","floor","lodReduction","flags","lod","simplifyWithAttributes","simplify","previous","lodPixelError","push","all","Uint32Array","offset","chain","set"],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ import { ASSET_META_VERSION, getAssetMetaPath } from './texture_settings.js';
2
+
3
+ /** Most levels of detail a mesh can have */ const MAX_MESH_LODS = 8;
4
+ const COMPRESSIONS = [
5
+ 'none',
6
+ 'meshopt'
7
+ ];
8
+ const NORMAL_BITS = [
9
+ 0,
10
+ 8,
11
+ 12,
12
+ 16
13
+ ];
14
+ /**
15
+ * Default mesh settings. Like textures, compression is opt-in. Normals default
16
+ * to 12 bits: 8-bit error shows on smooth surfaces near the light terminator.
17
+ * @public
18
+ */ function defaultMeshImportSettings(compression = 'none') {
19
+ return {
20
+ compression,
21
+ normalBits: 12,
22
+ lodEnabled: false,
23
+ lodMinTriangles: 100,
24
+ lodReduction: 0.5,
25
+ lodPixelError: 8,
26
+ sdfResolutionScale: 1,
27
+ sdfUnitScale: 1,
28
+ sdfTwoSided: false
29
+ };
30
+ }
31
+ /**
32
+ * Triangle count each level of detail aims for, the source first: level i keeps
33
+ * `lodReduction^i` of the source triangles, and levels stop before one would fall below
34
+ * `lodMinTriangles` or at {@link MAX_MESH_LODS}. Simplification may end the chain earlier when it
35
+ * cannot reach a target, so this is the most levels the settings can give.
36
+ * @public
37
+ */ function getMeshLodTargets(triangles, settings) {
38
+ const targets = [
39
+ triangles
40
+ ];
41
+ if (settings.lodEnabled) {
42
+ for(let i = 1; i < MAX_MESH_LODS; i++){
43
+ const target = Math.floor(triangles * settings.lodReduction ** i);
44
+ if (target < settings.lodMinTriangles || target < 1) {
45
+ break;
46
+ }
47
+ targets.push(target);
48
+ }
49
+ }
50
+ return targets;
51
+ }
52
+ /**
53
+ * Whether a mesh with these settings ships a derived copy instead of its source: when compressed
54
+ * or when its source has enough triangles for a level of detail.
55
+ * @param settings - Mesh settings
56
+ * @param sourceTriangles - Triangles of the source mesh
57
+ * @public
58
+ */ function meshNeedsDerivedCopy(settings, sourceTriangles) {
59
+ return settings.compression !== 'none' || getMeshLodTargets(sourceTriangles, settings).length > 1;
60
+ }
61
+ /**
62
+ * Validates parsed settings; anything missing or invalid falls back to the defaults.
63
+ * @public
64
+ */ function normalizeMeshImportSettings(value) {
65
+ const v = value && typeof value === 'object' ? value : {};
66
+ const defaults = defaultMeshImportSettings();
67
+ return {
68
+ compression: COMPRESSIONS.includes(v.compression) ? v.compression : defaults.compression,
69
+ normalBits: NORMAL_BITS.includes(v.normalBits) ? v.normalBits : defaults.normalBits,
70
+ lodEnabled: typeof v.lodEnabled === 'boolean' ? v.lodEnabled : defaults.lodEnabled,
71
+ lodMinTriangles: Number.isInteger(v.lodMinTriangles) && v.lodMinTriangles >= 1 ? v.lodMinTriangles : defaults.lodMinTriangles,
72
+ lodReduction: typeof v.lodReduction === 'number' && v.lodReduction > 0 && v.lodReduction < 1 ? v.lodReduction : defaults.lodReduction,
73
+ lodPixelError: typeof v.lodPixelError === 'number' && v.lodPixelError > 0 ? v.lodPixelError : defaults.lodPixelError,
74
+ sdfResolutionScale: typeof v.sdfResolutionScale === 'number' && v.sdfResolutionScale > 0 ? v.sdfResolutionScale : defaults.sdfResolutionScale,
75
+ sdfUnitScale: typeof v.sdfUnitScale === 'number' && v.sdfUnitScale > 0 ? v.sdfUnitScale : defaults.sdfUnitScale,
76
+ sdfTwoSided: typeof v.sdfTwoSided === 'boolean' ? v.sdfTwoSided : defaults.sdfTwoSided
77
+ };
78
+ }
79
+ /**
80
+ * Reads the import settings of a mesh; without a `.zmeta` the mesh is not compressed.
81
+ * @public
82
+ */ async function readMeshImportSettings(vfs, path) {
83
+ const metaPath = getAssetMetaPath(path);
84
+ try {
85
+ if (await vfs.exists(metaPath)) {
86
+ const meta = JSON.parse(await vfs.readFile(metaPath, {
87
+ encoding: 'utf8'
88
+ }));
89
+ return normalizeMeshImportSettings(meta?.mesh);
90
+ }
91
+ } catch (err) {
92
+ console.warn(`Ignoring unreadable asset meta ${metaPath}: ${err}`);
93
+ }
94
+ return defaultMeshImportSettings();
95
+ }
96
+ /**
97
+ * Writes the import settings of a mesh to its `.zmeta` file.
98
+ * @public
99
+ */ async function writeMeshImportSettings(vfs, path, settings) {
100
+ const content = JSON.stringify({
101
+ version: ASSET_META_VERSION,
102
+ mesh: settings
103
+ }, null, 2);
104
+ await vfs.writeFile(getAssetMetaPath(path), content, {
105
+ encoding: 'utf8',
106
+ create: true
107
+ });
108
+ }
109
+
110
+ export { MAX_MESH_LODS, defaultMeshImportSettings, getMeshLodTargets, meshNeedsDerivedCopy, normalizeMeshImportSettings, readMeshImportSettings, writeMeshImportSettings };
111
+ //# sourceMappingURL=mesh_settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh_settings.js","sources":["../../src/asset/mesh_settings.ts"],"sourcesContent":["import type { VFS } from '@zephyr3d/base';\r\nimport { ASSET_META_VERSION, getAssetMetaPath } from './texture_settings';\r\n\r\n/**\r\n * Vertex data encoding of a mesh: `none` ships the vertex buffers as they are,\r\n * `meshopt` stores them meshoptimizer-compressed with quantized attributes.\r\n * @public\r\n */\r\nexport type MeshCompression = 'none' | 'meshopt';\r\n\r\n/**\r\n * Per-mesh import settings, stored in the `.zmeta` file beside a `.zmsh`.\r\n * @public\r\n */\r\nexport interface MeshImportSettings {\r\n compression: MeshCompression;\r\n /**\r\n * Precision of normals and tangents when compressed, or 0 to keep them as floats.\r\n * 8 bits ships them as snorm8 (4 bytes, up to 0.8 degrees off, visible as a\r\n * ragged terminator on smooth surfaces); 12 and 16 ship as snorm16 (8 bytes,\r\n * 0.05 and 0.004 degrees), 12 encoding notably smaller than 16.\r\n */\r\n normalBits: 0 | 8 | 12 | 16;\r\n /**\r\n * Generate levels of detail: coarser levels simplified from the source, stored as extra index\r\n * ranges over the same vertices. How many follows from {@link MeshImportSettings.lodMinTriangles}.\r\n */\r\n lodEnabled: boolean;\r\n /**\r\n * Fewest triangles a generated level may have. Levels are added while the next one keeps at\r\n * least this many, up to {@link MAX_MESH_LODS} levels including the source.\r\n */\r\n lodMinTriangles: number;\r\n /** Fraction of the source triangles each level keeps over the previous one */\r\n lodReduction: number;\r\n /**\r\n * Pixel error the automatic switch distances allow: a level is used once its\r\n * simplification error projects to fewer pixels on a 1920 wide, 90 degree view\r\n */\r\n lodPixelError: number;\r\n /**\r\n * Scale on the density of the baked signed distance field: 1 gives 20 voxels\r\n * per world unit (at most 128 per axis; 256 above 1), see SDF_VOXELS_PER_UNIT.\r\n */\r\n sdfResolutionScale: number;\r\n /**\r\n * World units one local unit of the mesh spans where it is used, so the\r\n * density of the baked field is per world unit: a model authored in\r\n * centimetres and scaled down by its nodes would otherwise get a hundred\r\n * times the voxels it needs. Set when the model is imported, from the\r\n * largest scale of the nodes using the mesh, and when the meshes of a scene\r\n * are baked, from the largest scale of their instances.\r\n */\r\n sdfUnitScale: number;\r\n /** Bake the field as a thin open surface, unsigned, rather than a closed solid. */\r\n sdfTwoSided: boolean;\r\n}\r\n\r\n/** Most levels of detail a mesh can have */\r\nexport const MAX_MESH_LODS = 8;\r\n\r\nconst COMPRESSIONS: readonly MeshCompression[] = ['none', 'meshopt'];\r\nconst NORMAL_BITS: readonly MeshImportSettings['normalBits'][] = [0, 8, 12, 16];\r\n\r\n/**\r\n * Default mesh settings. Like textures, compression is opt-in. Normals default\r\n * to 12 bits: 8-bit error shows on smooth surfaces near the light terminator.\r\n * @public\r\n */\r\nexport function defaultMeshImportSettings(compression: MeshCompression = 'none'): MeshImportSettings {\r\n return {\r\n compression,\r\n normalBits: 12,\r\n lodEnabled: false,\r\n lodMinTriangles: 100,\r\n lodReduction: 0.5,\r\n lodPixelError: 8,\r\n sdfResolutionScale: 1,\r\n sdfUnitScale: 1,\r\n sdfTwoSided: false\r\n };\r\n}\r\n\r\n/**\r\n * Triangle count each level of detail aims for, the source first: level i keeps\r\n * `lodReduction^i` of the source triangles, and levels stop before one would fall below\r\n * `lodMinTriangles` or at {@link MAX_MESH_LODS}. Simplification may end the chain earlier when it\r\n * cannot reach a target, so this is the most levels the settings can give.\r\n * @public\r\n */\r\nexport function getMeshLodTargets(\r\n triangles: number,\r\n settings: Pick<MeshImportSettings, 'lodEnabled' | 'lodMinTriangles' | 'lodReduction'>\r\n) {\r\n const targets = [triangles];\r\n if (settings.lodEnabled) {\r\n for (let i = 1; i < MAX_MESH_LODS; i++) {\r\n const target = Math.floor(triangles * settings.lodReduction ** i);\r\n if (target < settings.lodMinTriangles || target < 1) {\r\n break;\r\n }\r\n targets.push(target);\r\n }\r\n }\r\n return targets;\r\n}\r\n\r\n/**\r\n * Whether a mesh with these settings ships a derived copy instead of its source: when compressed\r\n * or when its source has enough triangles for a level of detail.\r\n * @param settings - Mesh settings\r\n * @param sourceTriangles - Triangles of the source mesh\r\n * @public\r\n */\r\nexport function meshNeedsDerivedCopy(settings: MeshImportSettings, sourceTriangles: number) {\r\n return settings.compression !== 'none' || getMeshLodTargets(sourceTriangles, settings).length > 1;\r\n}\r\n\r\n/**\r\n * Validates parsed settings; anything missing or invalid falls back to the defaults.\r\n * @public\r\n */\r\nexport function normalizeMeshImportSettings(value: unknown): MeshImportSettings {\r\n const v = (value && typeof value === 'object' ? value : {}) as Record<string, unknown>;\r\n const defaults = defaultMeshImportSettings();\r\n return {\r\n compression: COMPRESSIONS.includes(v.compression as MeshCompression)\r\n ? (v.compression as MeshCompression)\r\n : defaults.compression,\r\n normalBits: NORMAL_BITS.includes(v.normalBits as MeshImportSettings['normalBits'])\r\n ? (v.normalBits as MeshImportSettings['normalBits'])\r\n : defaults.normalBits,\r\n lodEnabled: typeof v.lodEnabled === 'boolean' ? v.lodEnabled : defaults.lodEnabled,\r\n lodMinTriangles:\r\n Number.isInteger(v.lodMinTriangles) && (v.lodMinTriangles as number) >= 1\r\n ? (v.lodMinTriangles as number)\r\n : defaults.lodMinTriangles,\r\n lodReduction:\r\n typeof v.lodReduction === 'number' && v.lodReduction > 0 && v.lodReduction < 1\r\n ? v.lodReduction\r\n : defaults.lodReduction,\r\n lodPixelError:\r\n typeof v.lodPixelError === 'number' && v.lodPixelError > 0 ? v.lodPixelError : defaults.lodPixelError,\r\n sdfResolutionScale:\r\n typeof v.sdfResolutionScale === 'number' && v.sdfResolutionScale > 0\r\n ? v.sdfResolutionScale\r\n : defaults.sdfResolutionScale,\r\n sdfUnitScale:\r\n typeof v.sdfUnitScale === 'number' && v.sdfUnitScale > 0 ? v.sdfUnitScale : defaults.sdfUnitScale,\r\n sdfTwoSided: typeof v.sdfTwoSided === 'boolean' ? v.sdfTwoSided : defaults.sdfTwoSided\r\n };\r\n}\r\n\r\n/**\r\n * Reads the import settings of a mesh; without a `.zmeta` the mesh is not compressed.\r\n * @public\r\n */\r\nexport async function readMeshImportSettings(vfs: VFS, path: string): Promise<MeshImportSettings> {\r\n const metaPath = getAssetMetaPath(path);\r\n try {\r\n if (await vfs.exists(metaPath)) {\r\n const meta = JSON.parse((await vfs.readFile(metaPath, { encoding: 'utf8' })) as string);\r\n return normalizeMeshImportSettings(meta?.mesh);\r\n }\r\n } catch (err) {\r\n console.warn(`Ignoring unreadable asset meta ${metaPath}: ${err}`);\r\n }\r\n return defaultMeshImportSettings();\r\n}\r\n\r\n/**\r\n * Writes the import settings of a mesh to its `.zmeta` file.\r\n * @public\r\n */\r\nexport async function writeMeshImportSettings(vfs: VFS, path: string, settings: MeshImportSettings) {\r\n const content = JSON.stringify({ version: ASSET_META_VERSION, mesh: settings }, null, 2);\r\n await vfs.writeFile(getAssetMetaPath(path), content, { encoding: 'utf8', create: true });\r\n}\r\n"],"names":["MAX_MESH_LODS","COMPRESSIONS","NORMAL_BITS","defaultMeshImportSettings","compression","normalBits","lodEnabled","lodMinTriangles","lodReduction","lodPixelError","sdfResolutionScale","sdfUnitScale","sdfTwoSided","getMeshLodTargets","triangles","settings","targets","i","target","Math","floor","push","meshNeedsDerivedCopy","sourceTriangles","length","normalizeMeshImportSettings","value","v","defaults","includes","Number","isInteger","readMeshImportSettings","vfs","path","metaPath","getAssetMetaPath","exists","meta","JSON","parse","readFile","encoding","mesh","err","console","warn","writeMeshImportSettings","content","stringify","version","ASSET_META_VERSION","writeFile","create"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { MeshoptDecoder } from '../node_modules/meshoptimizer/meshopt_decoder.js';
2
+
3
+ /**
4
+ * meshoptimizer's decoder once its WebAssembly module is ready. Shared by the
5
+ * engine's binary .zmsh reader and the glTF meshopt extensions in the loaders
6
+ * package, so one copy serves both.
7
+ *
8
+ * Imported statically: the decoder is about 8 KB gzipped with the WebAssembly
9
+ * embedded, and a lazy import() would force every downstream single-file Rollup
10
+ * build to change its output options.
11
+ * @public
12
+ */ async function getMeshoptDecoder() {
13
+ await MeshoptDecoder.ready;
14
+ return MeshoptDecoder;
15
+ }
16
+
17
+ export { getMeshoptDecoder };
18
+ //# sourceMappingURL=meshopt_decoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meshopt_decoder.js","sources":["../../src/asset/meshopt_decoder.ts"],"sourcesContent":["import { MeshoptDecoder } from 'meshoptimizer/decoder';\r\nimport type { MeshoptDecoderModule } from './zmsh_binary';\r\n\r\n/**\r\n * meshoptimizer's decoder once its WebAssembly module is ready. Shared by the\r\n * engine's binary .zmsh reader and the glTF meshopt extensions in the loaders\r\n * package, so one copy serves both.\r\n *\r\n * Imported statically: the decoder is about 8 KB gzipped with the WebAssembly\r\n * embedded, and a lazy import() would force every downstream single-file Rollup\r\n * build to change its output options.\r\n * @public\r\n */\r\nexport async function getMeshoptDecoder(): Promise<MeshoptDecoderModule> {\r\n await MeshoptDecoder.ready;\r\n return MeshoptDecoder;\r\n}\r\n"],"names":["getMeshoptDecoder","MeshoptDecoder","ready"],"mappings":";;AAGA;;;;;;;;;AASC,IACM,eAAeA,iBAAAA,GAAAA;AACpB,IAAA,MAAMC,eAAeC,KAAK;IAC1B,OAAOD,cAAAA;AACT;;;;"}
@@ -0,0 +1,26 @@
1
+ import { MeshoptSimplifier } from '../node_modules/meshoptimizer/meshopt_simplifier.js';
2
+
3
+ let ready = false;
4
+ /**
5
+ * meshoptimizer's simplifier once its WebAssembly module is ready, for generating levels of
6
+ * detail (SharedModel.generateLods, shapes with LOD settings).
7
+ *
8
+ * Imported statically like the decoder (see getMeshoptDecoder): a lazy import() would force every
9
+ * downstream single-file Rollup build to change its output options.
10
+ * @public
11
+ */ async function getMeshoptSimplifier() {
12
+ await MeshoptSimplifier.ready;
13
+ ready = true;
14
+ return MeshoptSimplifier;
15
+ }
16
+ /**
17
+ * meshoptimizer's simplifier if its WebAssembly module is ready, null otherwise; for code that
18
+ * must generate levels of detail synchronously and can wait for {@link getMeshoptSimplifier}
19
+ * the first time.
20
+ * @public
21
+ */ function getMeshoptSimplifierIfReady() {
22
+ return ready ? MeshoptSimplifier : null;
23
+ }
24
+
25
+ export { getMeshoptSimplifier, getMeshoptSimplifierIfReady };
26
+ //# sourceMappingURL=meshopt_simplifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meshopt_simplifier.js","sources":["../../src/asset/meshopt_simplifier.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\r\nimport { MeshoptSimplifier } from 'meshoptimizer/simplifier';\r\nimport type { MeshSimplifier } from './mesh_lod_builder';\r\n\r\nlet ready = false;\r\n\r\n/**\r\n * meshoptimizer's simplifier once its WebAssembly module is ready, for generating levels of\r\n * detail (SharedModel.generateLods, shapes with LOD settings).\r\n *\r\n * Imported statically like the decoder (see getMeshoptDecoder): a lazy import() would force every\r\n * downstream single-file Rollup build to change its output options.\r\n * @public\r\n */\r\nexport async function getMeshoptSimplifier(): Promise<MeshSimplifier> {\r\n await MeshoptSimplifier.ready;\r\n ready = true;\r\n return MeshoptSimplifier as unknown as MeshSimplifier;\r\n}\r\n\r\n/**\r\n * meshoptimizer's simplifier if its WebAssembly module is ready, null otherwise; for code that\r\n * must generate levels of detail synchronously and can wait for {@link getMeshoptSimplifier}\r\n * the first time.\r\n * @public\r\n */\r\nexport function getMeshoptSimplifierIfReady(): Nullable<MeshSimplifier> {\r\n return ready ? (MeshoptSimplifier as unknown as MeshSimplifier) : null;\r\n}\r\n"],"names":["ready","getMeshoptSimplifier","MeshoptSimplifier","getMeshoptSimplifierIfReady"],"mappings":";;AAIA,IAAIA,KAAQ,GAAA,KAAA;AAEZ;;;;;;;AAOC,IACM,eAAeC,oBAAAA,GAAAA;AACpB,IAAA,MAAMC,kBAAkBF,KAAK;IAC7BA,KAAQ,GAAA,IAAA;IACR,OAAOE,iBAAAA;AACT;AAEA;;;;;AAKC,IACM,SAASC,2BAAAA,GAAAA;AACd,IAAA,OAAOH,QAASE,iBAAkD,GAAA,IAAA;AACpE;;;;"}