@woosh/meep-engine 2.138.17 → 2.138.19

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 (449) hide show
  1. package/README.md +2 -2
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/editor/actions/concrete/ActionUpdateTexture.d.ts +12 -0
  4. package/editor/actions/concrete/ActionUpdateTexture.d.ts.map +1 -0
  5. package/editor/actions/concrete/ArrayCopyAction.d.ts +20 -0
  6. package/editor/actions/concrete/ArrayCopyAction.d.ts.map +1 -0
  7. package/editor/actions/concrete/ComponentRemoveAction.d.ts +11 -0
  8. package/editor/actions/concrete/ComponentRemoveAction.d.ts.map +1 -0
  9. package/editor/actions/concrete/ModifyPatchSampler2DAction.d.ts +47 -0
  10. package/editor/actions/concrete/ModifyPatchSampler2DAction.d.ts.map +1 -0
  11. package/editor/actions/concrete/ModifyPatchTextureArray2DAction.d.ts +38 -0
  12. package/editor/actions/concrete/ModifyPatchTextureArray2DAction.d.ts.map +1 -0
  13. package/editor/actions/concrete/PaintTerrainOverlayAction.d.ts +23 -0
  14. package/editor/actions/concrete/PaintTerrainOverlayAction.d.ts.map +1 -0
  15. package/editor/actions/concrete/PatchTerrainHeightAction.d.ts +19 -0
  16. package/editor/actions/concrete/PatchTerrainHeightAction.d.ts.map +1 -0
  17. package/editor/actions/concrete/SelectionRemoveAction.d.ts +10 -0
  18. package/editor/actions/concrete/SelectionRemoveAction.d.ts.map +1 -0
  19. package/editor/actions/concrete/WriteGridValueAction.d.ts +15 -0
  20. package/editor/actions/concrete/WriteGridValueAction.d.ts.map +1 -0
  21. package/editor/ecs/component/FieldDescriptor.d.ts +27 -0
  22. package/editor/ecs/component/FieldDescriptor.d.ts.map +1 -0
  23. package/editor/ecs/component/FieldValueAdapter.d.ts +7 -0
  24. package/editor/ecs/component/FieldValueAdapter.d.ts.map +1 -0
  25. package/editor/ecs/component/createFieldEditor.d.ts +9 -0
  26. package/editor/ecs/component/createFieldEditor.d.ts.map +1 -0
  27. package/editor/ecs/component/createObjectEditor.d.ts +14 -0
  28. package/editor/ecs/component/createObjectEditor.d.ts.map +1 -0
  29. package/editor/ecs/component/editors/geom/QuaternionEditor.d.ts.map +1 -1
  30. package/editor/ecs/component/findNearestRegisteredType.d.ts +8 -0
  31. package/editor/ecs/component/findNearestRegisteredType.d.ts.map +1 -0
  32. package/editor/process/ObstacleGridDisplayProcess.d.ts.map +1 -1
  33. package/editor/process/symbolic/makeGridPositionSymbolDisplay.d.ts.map +1 -1
  34. package/editor/tools/GridPaintTool.d.ts +17 -0
  35. package/editor/tools/GridPaintTool.d.ts.map +1 -0
  36. package/editor/tools/SelectionTool.d.ts +27 -0
  37. package/editor/tools/SelectionTool.d.ts.map +1 -0
  38. package/editor/tools/TopDownCameraControlTool.d.ts +13 -0
  39. package/editor/tools/TopDownCameraControlTool.d.ts.map +1 -0
  40. package/editor/view/ecs/ComponentControlFactory.d.ts.map +1 -0
  41. package/editor/view/ecs/ComponentControlView.d.ts.map +1 -1
  42. package/editor/view/ecs/EntityEditor.d.ts.map +1 -0
  43. package/editor/view/ecs/EntityList.d.ts.map +1 -0
  44. package/editor/view/ecs/HierarchicalEntityListView.d.ts.map +1 -0
  45. package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
  46. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  47. package/editor/view/node-graph/NodeView.d.ts.map +1 -1
  48. package/editor/view/node-graph/PortView.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/core/binary/BinaryBuffer.d.ts +1 -1
  51. package/src/core/binary/BinaryBuffer.js +1 -1
  52. package/src/core/binary/BitSet.d.ts +1 -1
  53. package/src/core/binary/BitSet.js +1 -1
  54. package/src/core/cache/Cache.js +1 -1
  55. package/src/core/cache/LoadingCache.js +1 -1
  56. package/src/core/collection/list/List.js +1 -1
  57. package/src/core/collection/map/HashMap.js +1 -1
  58. package/src/core/collection/table/RowFirstTable.d.ts +1 -1
  59. package/src/core/collection/table/RowFirstTable.js +1 -1
  60. package/src/core/collection/table/RowFirstTableSpec.d.ts +1 -1
  61. package/src/core/collection/table/RowFirstTableSpec.js +1 -1
  62. package/src/core/color/oklab/compute_max_saturation.d.ts +1 -1
  63. package/src/core/color/oklab/compute_max_saturation.js +1 -1
  64. package/src/core/color/oklab/find_cusp.d.ts +1 -1
  65. package/src/core/color/oklab/find_cusp.js +1 -1
  66. package/src/core/color/oklab/find_gamut_intersection.d.ts +1 -1
  67. package/src/core/color/oklab/find_gamut_intersection.js +1 -1
  68. package/src/core/color/oklab/okhsv_to_linear_srgb.d.ts +1 -1
  69. package/src/core/color/oklab/okhsv_to_linear_srgb.js +1 -1
  70. package/src/core/color/oklab/oklab_to_linear_srgb.d.ts +1 -1
  71. package/src/core/color/oklab/oklab_to_linear_srgb.js +1 -1
  72. package/src/core/color/oklab/oklab_to_xyz.d.ts +1 -1
  73. package/src/core/color/oklab/oklab_to_xyz.js +1 -1
  74. package/src/core/color/oklab/xyz_to_oklab.d.ts +1 -1
  75. package/src/core/color/oklab/xyz_to_oklab.js +1 -1
  76. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.d.ts +1 -1
  77. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +1 -1
  78. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.d.ts.map +1 -1
  79. package/src/core/geom/3d/aabb/aabb3_nearest_point_on_surface.js +57 -65
  80. package/src/core/geom/3d/octahedra/octahedral_uv_wrap.d.ts +1 -1
  81. package/src/core/geom/3d/octahedra/octahedral_uv_wrap.js +1 -1
  82. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.d.ts +1 -1
  83. package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +1 -1
  84. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.d.ts +1 -1
  85. package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +1 -1
  86. package/src/core/geom/3d/shape/AbstractShape3D.d.ts +74 -3
  87. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +37 -0
  88. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -0
  89. package/src/core/geom/3d/shape/CapsuleShape3D.js +210 -0
  90. package/src/core/geom/3d/shape/PointShape3D.d.ts +5 -0
  91. package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
  92. package/src/core/geom/3d/shape/PointShape3D.js +52 -14
  93. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +75 -12
  94. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  95. package/src/core/geom/3d/shape/TransformedShape3D.js +12 -3
  96. package/src/core/geom/3d/shape/UnionShape3D.d.ts +47 -5
  97. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  98. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +12 -5
  99. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
  100. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +17 -5
  101. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
  102. package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
  103. package/src/core/geom/3d/shape/json/shape_to_type.js +4 -1
  104. package/src/core/geom/3d/shape/json/type_adapters.d.ts +17 -2
  105. package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
  106. package/src/core/geom/3d/shape/json/type_adapters.js +18 -2
  107. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.d.ts.map +1 -1
  108. package/src/core/geom/3d/shape/util/compute_signed_distance_gradient_by_sampling.js +51 -48
  109. package/src/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.d.ts +1 -1
  110. package/src/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +1 -1
  111. package/src/core/geom/ConicRay.d.ts +1 -1
  112. package/src/core/geom/ConicRay.js +1 -1
  113. package/src/core/geom/Quaternion.d.ts +2 -2
  114. package/src/core/geom/Quaternion.js +2 -2
  115. package/src/core/geom/Vector1.d.ts +1 -1
  116. package/src/core/geom/Vector1.js +1 -1
  117. package/src/core/geom/Vector2.d.ts +1 -1
  118. package/src/core/geom/Vector2.js +1 -1
  119. package/src/core/geom/Vector3.d.ts +1 -1
  120. package/src/core/geom/Vector3.js +1 -1
  121. package/src/core/geom/packing/miniball/Miniball.d.ts +1 -1
  122. package/src/core/geom/packing/miniball/Miniball.js +1 -1
  123. package/src/core/geom/vec3/serialization/v3_binary_equality_decode.d.ts +1 -1
  124. package/src/core/geom/vec3/serialization/v3_binary_equality_decode.js +1 -1
  125. package/src/core/geom/vec3/serialization/v3_binary_equality_encode.d.ts +1 -1
  126. package/src/core/geom/vec3/serialization/v3_binary_equality_encode.js +1 -1
  127. package/src/core/math/spline/spline3_hermite.d.ts +1 -1
  128. package/src/core/math/spline/spline3_hermite.js +1 -1
  129. package/src/core/math/spline/spline3_hermite_bounds.d.ts +1 -1
  130. package/src/core/math/spline/spline3_hermite_bounds.js +1 -1
  131. package/src/core/math/spline/spline3_hermite_bounds_t.d.ts +1 -1
  132. package/src/core/math/spline/spline3_hermite_bounds_t.js +1 -1
  133. package/src/core/math/spline/spline3_hermite_to_monomial.d.ts +1 -1
  134. package/src/core/math/spline/spline3_hermite_to_monomial.js +1 -1
  135. package/src/core/model/ObservedBoolean.d.ts +1 -1
  136. package/src/core/model/ObservedBoolean.js +1 -1
  137. package/src/core/model/ObservedString.d.ts +1 -1
  138. package/src/core/model/ObservedString.js +1 -1
  139. package/src/core/process/undo/Action.js +1 -1
  140. package/src/core/process/undo/ActionProcessor.js +1 -1
  141. package/src/engine/animation/curve/AnimationCurve.d.ts +1 -1
  142. package/src/engine/animation/curve/AnimationCurve.js +1 -1
  143. package/src/engine/animation/curve/Keyframe.d.ts +1 -1
  144. package/src/engine/animation/curve/Keyframe.js +1 -1
  145. package/src/engine/animation/curve/animation_curve_compute_aabb.d.ts +1 -1
  146. package/src/engine/animation/curve/animation_curve_compute_aabb.js +1 -1
  147. package/src/engine/animation/curve/animation_curve_optimize.d.ts +1 -1
  148. package/src/engine/animation/curve/animation_curve_optimize.js +2 -2
  149. package/src/engine/asset/loaders/image/jpeg/JpegImage.js +1 -1
  150. package/src/engine/asset/loaders/image/png/PNGReader.d.ts.map +1 -1
  151. package/src/engine/asset/loaders/image/png/PNGReader.js +27 -7
  152. package/src/engine/asset/loaders/image/png/crc32.d.ts +1 -1
  153. package/src/engine/asset/loaders/image/png/crc32.js +1 -1
  154. package/src/engine/control/first-person/DESIGN.md +616 -0
  155. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +229 -0
  156. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -0
  157. package/src/engine/control/first-person/FirstPersonPlayerController.js +176 -0
  158. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +251 -0
  159. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -0
  160. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +205 -0
  161. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +151 -0
  162. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -0
  163. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +799 -0
  164. package/src/engine/control/first-person/math/computeJumpFromApex.d.ts +23 -0
  165. package/src/engine/control/first-person/math/computeJumpFromApex.d.ts.map +1 -0
  166. package/src/engine/control/first-person/math/computeJumpFromApex.js +23 -0
  167. package/src/engine/control/first-person/math/criticallyDampedSpring.d.ts +23 -0
  168. package/src/engine/control/first-person/math/criticallyDampedSpring.d.ts.map +1 -0
  169. package/src/engine/control/first-person/math/criticallyDampedSpring.js +34 -0
  170. package/src/engine/control/first-person/math/dampedSpringStep.d.ts +23 -0
  171. package/src/engine/control/first-person/math/dampedSpringStep.d.ts.map +1 -0
  172. package/src/engine/control/first-person/math/dampedSpringStep.js +72 -0
  173. package/src/engine/control/first-person/math/stepTowards.d.ts +12 -0
  174. package/src/engine/control/first-person/math/stepTowards.d.ts.map +1 -0
  175. package/src/engine/control/first-person/math/stepTowards.js +20 -0
  176. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +69 -0
  177. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -0
  178. package/src/engine/control/first-person/pose/FirstPersonPose.js +91 -0
  179. package/src/engine/control/first-person/prototype_first_person_controller.d.ts +2 -0
  180. package/src/engine/control/first-person/prototype_first_person_controller.d.ts.map +1 -0
  181. package/src/engine/control/first-person/prototype_first_person_controller.js +314 -0
  182. package/src/engine/ecs/Entity.js +1 -1
  183. package/src/engine/ecs/EntityComponentDataset.js +1 -1
  184. package/src/engine/ecs/EntityManager.d.ts +1 -1
  185. package/src/engine/ecs/EntityManager.js +1 -1
  186. package/src/engine/ecs/EntityObserver.js +1 -1
  187. package/src/engine/ecs/EntityReference.d.ts +1 -1
  188. package/src/engine/ecs/EntityReference.js +1 -1
  189. package/src/engine/ecs/System.js +1 -1
  190. package/src/engine/ecs/attachment/AttachmentSystem.d.ts +2 -2
  191. package/src/engine/ecs/attachment/AttachmentSystem.d.ts.map +1 -1
  192. package/src/engine/ecs/grid/HeightMap2AOMap.d.ts.map +1 -1
  193. package/src/engine/ecs/grid/HeightMap2AOMap.js +3 -2
  194. package/src/engine/ecs/guid/UUID.d.ts +1 -1
  195. package/src/engine/ecs/guid/UUID.js +1 -1
  196. package/src/engine/ecs/name/Name.d.ts +1 -1
  197. package/src/engine/ecs/name/Name.js +1 -1
  198. package/src/engine/ecs/parent/ParentEntity.js +1 -1
  199. package/src/engine/ecs/storage/BinaryBufferDeSerializer.d.ts +1 -1
  200. package/src/engine/ecs/storage/BinaryBufferDeSerializer.js +1 -1
  201. package/src/engine/ecs/storage/BinaryBufferSerializer.d.ts +1 -1
  202. package/src/engine/ecs/storage/BinaryBufferSerializer.js +1 -1
  203. package/src/engine/ecs/storage/binary/BinaryClassSerializationAdapter.js +1 -1
  204. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.d.ts +1 -1
  205. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.js +1 -1
  206. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.d.ts +1 -1
  207. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.js +1 -1
  208. package/src/engine/ecs/transform/Transform.d.ts +1 -1
  209. package/src/engine/ecs/transform/Transform.js +1 -1
  210. package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
  211. package/src/engine/graphics/impostors/octahedral/ImpostorBaker.d.ts.map +1 -1
  212. package/src/engine/graphics/impostors/octahedral/ImpostorBaker.js +10 -1
  213. package/src/engine/graphics/impostors/voxel/README.md +149 -0
  214. package/src/engine/graphics/impostors/voxel/VoxelImpostorBaker.d.ts +91 -0
  215. package/src/engine/graphics/impostors/voxel/VoxelImpostorBaker.d.ts.map +1 -0
  216. package/src/engine/graphics/impostors/voxel/VoxelImpostorBaker.js +376 -0
  217. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.d.ts +128 -0
  218. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.d.ts.map +1 -0
  219. package/src/engine/graphics/impostors/voxel/VoxelImpostorDescription.js +141 -0
  220. package/src/engine/graphics/impostors/voxel/bake/read_atlas_to_samples.d.ts +38 -0
  221. package/src/engine/graphics/impostors/voxel/bake/read_atlas_to_samples.d.ts.map +1 -0
  222. package/src/engine/graphics/impostors/voxel/bake/read_atlas_to_samples.js +338 -0
  223. package/src/engine/graphics/impostors/voxel/bake/voxelize_samples.d.ts +43 -0
  224. package/src/engine/graphics/impostors/voxel/bake/voxelize_samples.d.ts.map +1 -0
  225. package/src/engine/graphics/impostors/voxel/bake/voxelize_samples.js +192 -0
  226. package/src/engine/graphics/impostors/voxel/prototype_voxel_impostors.d.ts +2 -0
  227. package/src/engine/graphics/impostors/voxel/prototype_voxel_impostors.d.ts.map +1 -0
  228. package/src/engine/graphics/impostors/voxel/prototype_voxel_impostors.js +343 -0
  229. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderDepthV0.d.ts +13 -0
  230. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderDepthV0.d.ts.map +1 -0
  231. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderDepthV0.js +99 -0
  232. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderLitV0.d.ts +19 -0
  233. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderLitV0.d.ts.map +1 -0
  234. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderLitV0.js +231 -0
  235. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderNormalsV0.d.ts +5 -0
  236. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderNormalsV0.d.ts.map +1 -0
  237. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderNormalsV0.js +70 -0
  238. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderV0.d.ts +13 -0
  239. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderV0.d.ts.map +1 -0
  240. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderV0.js +127 -0
  241. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderViewportDepthV0.d.ts +5 -0
  242. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderViewportDepthV0.d.ts.map +1 -0
  243. package/src/engine/graphics/impostors/voxel/shader/VoxelImpostorShaderViewportDepthV0.js +68 -0
  244. package/src/engine/graphics/impostors/voxel/util/make_voxel_impostor_geometry.d.ts +27 -0
  245. package/src/engine/graphics/impostors/voxel/util/make_voxel_impostor_geometry.d.ts.map +1 -0
  246. package/src/engine/graphics/impostors/voxel/util/make_voxel_impostor_geometry.js +96 -0
  247. package/src/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.d.ts +113 -29
  248. package/src/engine/graphics/render/forward_plus/SPECIFICATION.md +1 -1
  249. package/src/engine/graphics/shaders/AmbientOcclusionShader.d.ts.map +1 -1
  250. package/src/engine/graphics/shaders/AmbientOcclusionShader.js +20 -5
  251. package/src/engine/graphics/texture/sampler/Sampler2D.d.ts +1 -1
  252. package/src/engine/graphics/texture/sampler/Sampler2D.js +1 -1
  253. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_NaiveFlood.d.ts +1 -1
  254. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_NaiveFlood.js +1 -1
  255. package/src/engine/graphics/util/build_max_height_pyramid.d.ts +21 -14
  256. package/src/engine/graphics/util/build_max_height_pyramid.d.ts.map +1 -1
  257. package/src/engine/graphics/util/build_max_height_pyramid.js +107 -70
  258. package/src/engine/input/devices/InputDeviceSwitch.js +1 -1
  259. package/src/engine/input/devices/KeyboardDevice.js +1 -1
  260. package/src/engine/input/devices/PointerDevice.js +1 -1
  261. package/src/engine/intelligence/behavior/Behavior.js +1 -1
  262. package/src/engine/intelligence/behavior/SelectorBehavior.d.ts +1 -1
  263. package/src/engine/intelligence/behavior/SelectorBehavior.js +1 -1
  264. package/src/engine/intelligence/behavior/behavior_to_dot.d.ts +1 -1
  265. package/src/engine/intelligence/behavior/behavior_to_dot.js +1 -1
  266. package/src/engine/intelligence/behavior/composite/CompositeBehavior.d.ts +1 -1
  267. package/src/engine/intelligence/behavior/composite/CompositeBehavior.js +1 -1
  268. package/src/engine/intelligence/behavior/composite/ParallelBehavior.d.ts +1 -1
  269. package/src/engine/intelligence/behavior/composite/ParallelBehavior.js +1 -1
  270. package/src/engine/intelligence/behavior/composite/SequenceBehavior.d.ts +1 -1
  271. package/src/engine/intelligence/behavior/composite/SequenceBehavior.js +1 -1
  272. package/src/engine/intelligence/behavior/decorator/AbstractDecoratorBehavior.d.ts +1 -1
  273. package/src/engine/intelligence/behavior/decorator/AbstractDecoratorBehavior.js +1 -1
  274. package/src/engine/intelligence/behavior/decorator/IgnoreFailureBehavior.d.ts +1 -1
  275. package/src/engine/intelligence/behavior/decorator/IgnoreFailureBehavior.js +1 -1
  276. package/src/engine/intelligence/behavior/decorator/InvertStatusBehavior.d.ts +1 -1
  277. package/src/engine/intelligence/behavior/decorator/InvertStatusBehavior.js +1 -1
  278. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.d.ts +1 -1
  279. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.js +1 -1
  280. package/src/engine/intelligence/behavior/decorator/RepeatUntilSuccessBehavior.d.ts +1 -1
  281. package/src/engine/intelligence/behavior/decorator/RepeatUntilSuccessBehavior.js +1 -1
  282. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts +1 -1
  283. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.js +1 -1
  284. package/src/engine/intelligence/behavior/ecs/BehaviorSystem.d.ts +1 -1
  285. package/src/engine/intelligence/behavior/ecs/BehaviorSystem.js +1 -1
  286. package/src/engine/intelligence/behavior/ecs/DieBehavior.d.ts +1 -1
  287. package/src/engine/intelligence/behavior/ecs/DieBehavior.js +1 -1
  288. package/src/engine/intelligence/behavior/ecs/EntityBehavior.d.ts +1 -1
  289. package/src/engine/intelligence/behavior/ecs/EntityBehavior.js +1 -1
  290. package/src/engine/intelligence/behavior/ecs/KillBehavior.d.ts +1 -1
  291. package/src/engine/intelligence/behavior/ecs/KillBehavior.js +1 -1
  292. package/src/engine/intelligence/behavior/ecs/SendEventBehavior.d.ts +1 -1
  293. package/src/engine/intelligence/behavior/ecs/SendEventBehavior.js +1 -1
  294. package/src/engine/intelligence/behavior/ecs/WaitForEventBehavior.d.ts +1 -1
  295. package/src/engine/intelligence/behavior/ecs/WaitForEventBehavior.js +1 -1
  296. package/src/engine/intelligence/behavior/primitive/ActionBehavior.d.ts +1 -1
  297. package/src/engine/intelligence/behavior/primitive/ActionBehavior.js +1 -1
  298. package/src/engine/intelligence/behavior/primitive/FailingBehavior.d.ts +1 -1
  299. package/src/engine/intelligence/behavior/primitive/FailingBehavior.js +1 -1
  300. package/src/engine/intelligence/behavior/primitive/PromiseBehavior.d.ts +1 -1
  301. package/src/engine/intelligence/behavior/primitive/PromiseBehavior.js +1 -1
  302. package/src/engine/intelligence/behavior/primitive/SucceedingBehavior.d.ts +1 -1
  303. package/src/engine/intelligence/behavior/primitive/SucceedingBehavior.js +1 -1
  304. package/src/engine/intelligence/behavior/selector/WeightedElement.d.ts +1 -1
  305. package/src/engine/intelligence/behavior/selector/WeightedElement.js +1 -1
  306. package/src/engine/intelligence/behavior/selector/WeightedRandomBehavior.d.ts +1 -1
  307. package/src/engine/intelligence/behavior/selector/WeightedRandomBehavior.js +1 -1
  308. package/src/engine/intelligence/behavior/util/BranchBehavior.d.ts +1 -1
  309. package/src/engine/intelligence/behavior/util/BranchBehavior.js +1 -1
  310. package/src/engine/intelligence/behavior/util/DelayBehavior.d.ts +1 -1
  311. package/src/engine/intelligence/behavior/util/DelayBehavior.js +1 -1
  312. package/src/engine/intelligence/behavior/util/LogMessageBehavior.d.ts +1 -1
  313. package/src/engine/intelligence/behavior/util/LogMessageBehavior.js +1 -1
  314. package/src/engine/intelligence/behavior/util/RandomDelayBehavior.d.ts +1 -1
  315. package/src/engine/intelligence/behavior/util/RandomDelayBehavior.js +1 -1
  316. package/src/engine/intelligence/blackboard/Blackboard.js +1 -1
  317. package/src/engine/intelligence/mcts/MonteCarlo.d.ts +1 -1
  318. package/src/engine/intelligence/mcts/MonteCarlo.js +1 -1
  319. package/src/engine/intelligence/mcts/MoveEdge.d.ts +1 -1
  320. package/src/engine/intelligence/mcts/MoveEdge.js +1 -1
  321. package/src/engine/intelligence/mcts/StateNode.d.ts +1 -1
  322. package/src/engine/intelligence/mcts/StateNode.js +1 -1
  323. package/src/engine/intelligence/resource/ActionSequence.d.ts +1 -1
  324. package/src/engine/intelligence/resource/ActionSequence.js +1 -1
  325. package/src/engine/intelligence/resource/Resource.d.ts +1 -1
  326. package/src/engine/intelligence/resource/Resource.js +1 -1
  327. package/src/engine/intelligence/resource/ResourceAllocation.d.ts +1 -1
  328. package/src/engine/intelligence/resource/ResourceAllocation.js +1 -1
  329. package/src/engine/intelligence/resource/ResourceAllocationBid.d.ts +1 -1
  330. package/src/engine/intelligence/resource/ResourceAllocationBid.js +1 -1
  331. package/src/engine/intelligence/resource/ResourceAllocationSolver.d.ts +1 -1
  332. package/src/engine/intelligence/resource/ResourceAllocationSolver.js +1 -1
  333. package/src/engine/intelligence/resource/StrategicResourceAllocator.d.ts +1 -1
  334. package/src/engine/intelligence/resource/StrategicResourceAllocator.js +1 -1
  335. package/src/engine/intelligence/resource/TacticalModule.d.ts +1 -1
  336. package/src/engine/intelligence/resource/TacticalModule.js +1 -1
  337. package/src/engine/network/NetworkSession.d.ts +1 -1
  338. package/src/engine/network/NetworkSession.js +1 -1
  339. package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts +1 -1
  340. package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +1 -1
  341. package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts +1 -1
  342. package/src/engine/network/adapters/TransformInterpolationAdapter.js +1 -1
  343. package/src/engine/network/adapters/TransformReplicationAdapter.d.ts +1 -1
  344. package/src/engine/network/adapters/TransformReplicationAdapter.js +1 -1
  345. package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts +1 -1
  346. package/src/engine/network/adapters/Vector3InterpolationAdapter.js +1 -1
  347. package/src/engine/network/core/quantize/quantize_float.d.ts +1 -1
  348. package/src/engine/network/core/quantize/quantize_float.js +1 -1
  349. package/src/engine/network/core/quantize/quantize_position.d.ts +1 -1
  350. package/src/engine/network/core/quantize/quantize_position.js +1 -1
  351. package/src/engine/network/core/sequence/ack_bitfield.d.ts +1 -1
  352. package/src/engine/network/core/sequence/ack_bitfield.js +1 -1
  353. package/src/engine/network/core/sequence/seq16.d.ts +1 -1
  354. package/src/engine/network/core/sequence/seq16.js +1 -1
  355. package/src/engine/network/core/sequence/seq32.d.ts +1 -1
  356. package/src/engine/network/core/sequence/seq32.js +1 -1
  357. package/src/engine/network/diagnostics/BandwidthMeter.d.ts +1 -1
  358. package/src/engine/network/diagnostics/BandwidthMeter.js +1 -1
  359. package/src/engine/network/diagnostics/ReplayLog.d.ts +1 -1
  360. package/src/engine/network/diagnostics/ReplayLog.js +1 -1
  361. package/src/engine/network/diagnostics/SyncTest.d.ts +1 -1
  362. package/src/engine/network/diagnostics/SyncTest.js +1 -1
  363. package/src/engine/network/ecs/NetworkSystem.d.ts +1 -1
  364. package/src/engine/network/ecs/NetworkSystem.js +1 -1
  365. package/src/engine/network/ecs/components/NetworkIdentity.d.ts +1 -1
  366. package/src/engine/network/ecs/components/NetworkIdentity.js +1 -1
  367. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.d.ts +1 -1
  368. package/src/engine/network/ecs/serialization/NetworkIdentitySerializationAdapter.js +1 -1
  369. package/src/engine/network/orchestrator/NetworkPeer.d.ts +1 -1
  370. package/src/engine/network/orchestrator/NetworkPeer.js +1 -1
  371. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts +1 -1
  372. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +1 -1
  373. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +1 -1
  374. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +1 -1
  375. package/src/engine/network/replication/Replicator.d.ts +1 -1
  376. package/src/engine/network/replication/Replicator.js +1 -1
  377. package/src/engine/network/replication/ScopeFilter.d.ts +2 -2
  378. package/src/engine/network/replication/ScopeFilter.js +2 -2
  379. package/src/engine/network/sim/ActionLog.d.ts +1 -1
  380. package/src/engine/network/sim/ActionLog.js +1 -1
  381. package/src/engine/network/sim/BinaryInterpolationAdapter.d.ts +1 -1
  382. package/src/engine/network/sim/BinaryInterpolationAdapter.js +1 -1
  383. package/src/engine/network/sim/InterpolationLog.d.ts +1 -1
  384. package/src/engine/network/sim/InterpolationLog.js +1 -1
  385. package/src/engine/network/sim/ReplicatedComponentRegistry.d.ts +1 -1
  386. package/src/engine/network/sim/ReplicatedComponentRegistry.js +1 -1
  387. package/src/engine/network/sim/RewindEngine.d.ts +1 -1
  388. package/src/engine/network/sim/RewindEngine.js +1 -1
  389. package/src/engine/network/sim/SimAction.d.ts +1 -1
  390. package/src/engine/network/sim/SimAction.js +1 -1
  391. package/src/engine/network/sim/SimActionExecutor.d.ts +1 -1
  392. package/src/engine/network/sim/SimActionExecutor.js +1 -1
  393. package/src/engine/network/sim/SimActionRegistry.d.ts +1 -1
  394. package/src/engine/network/sim/SimActionRegistry.js +1 -1
  395. package/src/engine/network/sim/SmoothingState.js +1 -1
  396. package/src/engine/network/sim/Snapshotter.d.ts +1 -1
  397. package/src/engine/network/sim/Snapshotter.js +1 -1
  398. package/src/engine/network/sim/SpeculationLog.d.ts +1 -1
  399. package/src/engine/network/sim/SpeculationLog.js +1 -1
  400. package/src/engine/network/state/Baseline.d.ts +1 -1
  401. package/src/engine/network/state/Baseline.js +1 -1
  402. package/src/engine/network/state/ChangedEntitySet.d.ts +1 -1
  403. package/src/engine/network/state/ChangedEntitySet.js +1 -1
  404. package/src/engine/network/state/InputRing.d.ts +1 -1
  405. package/src/engine/network/state/InputRing.js +1 -1
  406. package/src/engine/network/state/MutationLedger.d.ts +1 -1
  407. package/src/engine/network/state/MutationLedger.js +1 -1
  408. package/src/engine/network/state/PriorityAccumulator.d.ts +1 -1
  409. package/src/engine/network/state/PriorityAccumulator.js +1 -1
  410. package/src/engine/network/state/ReplicationSlotTable.d.ts +1 -1
  411. package/src/engine/network/state/ReplicationSlotTable.js +1 -1
  412. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +1 -1
  413. package/src/engine/network/time/AdaptiveRenderDelay.js +1 -1
  414. package/src/engine/network/time/JitterBuffer.d.ts +1 -1
  415. package/src/engine/network/time/JitterBuffer.js +1 -1
  416. package/src/engine/network/time/TimeDilation.d.ts +1 -1
  417. package/src/engine/network/time/TimeDilation.js +1 -1
  418. package/src/engine/network/time/TimeSync.d.ts +1 -1
  419. package/src/engine/network/time/TimeSync.js +1 -1
  420. package/src/engine/network/transport/Channel.d.ts.map +1 -1
  421. package/src/engine/network/transport/Channel.js +3 -6
  422. package/src/engine/network/transport/LoopbackTransport.d.ts +1 -1
  423. package/src/engine/network/transport/LoopbackTransport.js +1 -1
  424. package/src/engine/network/transport/ReliableCommandPipeline.d.ts +1 -1
  425. package/src/engine/network/transport/ReliableCommandPipeline.js +1 -1
  426. package/src/engine/network/transport/Transport.d.ts +1 -1
  427. package/src/engine/network/transport/Transport.js +1 -1
  428. package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts +1 -1
  429. package/src/engine/network/transport/adapters/NodeUDPTransport.js +2 -2
  430. package/src/engine/network/transport/adapters/SimulatedTransport.d.ts +1 -1
  431. package/src/engine/network/transport/adapters/SimulatedTransport.js +1 -1
  432. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.d.ts +1 -1
  433. package/src/engine/network/transport/adapters/WebRTCDataChannelTransport.js +1 -1
  434. package/src/engine/network/transport/adapters/WebSocketTransport.d.ts +1 -1
  435. package/src/engine/network/transport/adapters/WebSocketTransport.js +1 -1
  436. package/src/engine/network/transport/adapters/WebTransportTransport.d.ts +1 -1
  437. package/src/engine/network/transport/adapters/WebTransportTransport.js +1 -1
  438. package/src/engine/network/transport/fragments/FragmentAssembler.d.ts +1 -1
  439. package/src/engine/network/transport/fragments/FragmentAssembler.js +1 -1
  440. package/src/engine/network/transport/fragments/FragmentRetention.d.ts +1 -1
  441. package/src/engine/network/transport/fragments/FragmentRetention.js +1 -1
  442. package/src/engine/network/transport/fragments/packet_size.d.ts +1 -1
  443. package/src/engine/network/transport/fragments/packet_size.js +1 -1
  444. package/src/engine/simulation/Ticker.d.ts +1 -1
  445. package/src/engine/simulation/Ticker.js +1 -1
  446. package/src/engine/sound/SoundEngine.js +1 -1
  447. package/src/engine/ui/DraggableAspect.d.ts +1 -1
  448. package/src/engine/ui/DraggableAspect.js +1 -1
  449. package/src/view/View.js +1 -1
@@ -0,0 +1,149 @@
1
+ # Voxel Impostor system
2
+
3
+ Point-based ("voxel" / surfel) impostor inspired by the **Nanite Voxels**
4
+ representation Epic and CD Projekt RED showed in the Witcher 4 / Unreal
5
+ Engine 5 tech demo (Unreal Fest Stockholm 2025). At distance, dense
6
+ alpha-tested foliage cards stop scaling cleanly — the new technique
7
+ replaces them with a cloud of near-pixel-sized splats, each carrying a
8
+ full G-buffer slice, so the LOD never has to fall back to a flat card.
9
+
10
+ This implementation is much simpler than UE's production system (we
11
+ don't do streaming, meshlet hierarchy, or front-to-back depth binning),
12
+ but the data model and rendering approach are the same:
13
+
14
+ - Each "voxel" is a single splat with the same world-space size.
15
+ - Per-splat attributes: position, normal, albedo, ORM (occlusion,
16
+ roughness, metalness). **No alpha.**
17
+ - Render as a camera-facing instanced quad; the splat's normal drives
18
+ the lighting equations, not the quad's geometry.
19
+
20
+ Conceptually the system mirrors the octahedral impostor's two phases:
21
+
22
+ 1. **Baking** (CPU-heavy, offline) — produce a point cloud from a
23
+ source mesh.
24
+ 2. **Drawing** (GPU, every frame) — render the points with a small set
25
+ of shaders (unlit / lit / debug / depth caster).
26
+
27
+ ---
28
+
29
+ ## Baking
30
+
31
+ Implemented in [`VoxelImpostorBaker`](./VoxelImpostorBaker.js). Strategy:
32
+
33
+ 1. Reuse the existing octahedral baker — it already renders the mesh
34
+ from many directions into a 3-channel MRT atlas (albedo+alpha,
35
+ normal+depth, ORM) with supersampling, anisotropic filtering, vertex
36
+ colours, and normal-map evaluation. We don't reimplement any of that.
37
+
38
+ 2. Read the atlas back to CPU. Every opaque pixel becomes one
39
+ object-space sample:
40
+ - position is reconstructed from `(D_frame, frame_local_uv, depth)`
41
+ - normal is decoded from the atlas's view-space-encoded bytes through
42
+ the bake camera's basis
43
+ - albedo / ORM are taken directly from the atlas
44
+
45
+ 3. Bin samples into a sparse axis-aligned voxel grid. Each cell
46
+ averages position, sums-and-normalises normal, averages albedo and
47
+ ORM. Empty cells are dropped — the surviving set IS the output point
48
+ cloud.
49
+
50
+ 4. The grid resolution is chosen iteratively to stay under a
51
+ user-specified `point_budget`. Geometric shrink (halving) converges in
52
+ `O(log resolution)` even on pathological inputs.
53
+
54
+ ### Why CPU-side voxelisation
55
+
56
+ The mesh is fixed, the bake is offline, and the whole voxelisation
57
+ runs in a few hundred ms on a million samples. Doing it on CPU keeps the
58
+ code path one-shot deterministic and lets the engine's CPU path tracer
59
+ be layered in later (for high-quality baked AO replacing the O channel,
60
+ or for indirect-lighting hints in albedo) without changing anything on
61
+ the runtime rendering side.
62
+
63
+ ### Why multi-view atlas sampling and not direct triangle sampling
64
+
65
+ A triangle area-weighted sampler would be cleaner in principle, but
66
+ would also re-implement everything `BakeShaderStandard` does — texture
67
+ filtering, supersampling, normal-map TBN, vertex-colour multiply,
68
+ material colour multiply, anisotropic filtering. The multi-view path
69
+ gets all of that for free, AND naturally weighs surfaces by visibility:
70
+ a surface visible from many angles gets many votes per voxel, which is
71
+ exactly what the impostor's job depends on.
72
+
73
+ ---
74
+
75
+ ## Drawing
76
+
77
+ One `InstancedBufferGeometry`, one instance per point, with the point
78
+ buffer wrapped directly as an `InstancedInterleavedBuffer` (zero copy
79
+ between baker and GPU). Each shader takes the per-instance attributes
80
+ and:
81
+
82
+ - expands a unit quad in view-space XY, scaled by
83
+ `VoxelImpostorDescription.point_radius`, to keep it camera-facing;
84
+ - uses the per-instance normal (not the quad's geometry normal) for
85
+ shading.
86
+
87
+ Shader set:
88
+
89
+ | File | Purpose |
90
+ |------|---------|
91
+ | `VoxelImpostorShaderV0` | Unlit. Writes baked albedo. Fast sanity check. |
92
+ | `VoxelImpostorShaderLitV0` | PBR-lit. Integrates three.js's standard pipeline; casts & receives shadows. |
93
+ | `VoxelImpostorShaderDepthV0` | Shadow-cast depth pass paired with the lit shader. |
94
+ | `VoxelImpostorShaderNormalsV0` | Debug — per-splat object-space normal as RGB. |
95
+ | `VoxelImpostorShaderViewportDepthV0` | Debug — viewport depth as grayscale. |
96
+
97
+ A `uDiscMask` uniform toggles between square and circular splats; the
98
+ prototype harness uses square for slot 0 (matches the Witcher 4 "voxel"
99
+ look) and disc for slot 1 (clearer view of the point distribution).
100
+
101
+ ---
102
+
103
+ ## Limitations
104
+
105
+ Same trade-offs as any pre-baked impostor:
106
+
107
+ - **No animation.** Position / normal / colour are frozen at bake time.
108
+ - **Static materials.** Roughness, metalness, AO, albedo are baked
109
+ averages, not procedural.
110
+ - **View-bias.** Surfaces never visible from the bake's sphere of
111
+ directions (eg the inside of a sealed cavity) don't get sampled.
112
+ Increase `frames` to capture more directions, but there's a hard limit:
113
+ if the original mesh's surface can't be hit by an external ray, the
114
+ impostor won't show it.
115
+ - **Splat overlap at close range.** Camera-facing quads with radius
116
+ ≈ voxel size will overlap noticeably at the edge of the visible range
117
+ before the impostor would normally be used. Use as a distant LOD, not
118
+ as a close-up replacement.
119
+
120
+ ---
121
+
122
+ ## Parameter recommendations
123
+
124
+ | Asset type | `point_budget` | `frames` | `resolution` |
125
+ |------------|---------------:|---------:|-------------:|
126
+ | Small prop (barrel, crate) | 2 048 | 12 | 512 |
127
+ | Building / house | 16 384 | 16 | 1024 |
128
+ | Vegetation (tree, large) | 32 768 | 24 | 2048 |
129
+ | Hero / detailed mesh | 65 536 | 32 | 2048 |
130
+
131
+ The budget is the **maximum** output; the baker may produce fewer
132
+ points if the bounding box is small or the surface area limited. Bump
133
+ `frames` if you see gaps in deep concavities; bump `resolution` if
134
+ per-voxel colour looks noisy (more samples per voxel → cleaner average).
135
+
136
+ ---
137
+
138
+ ## References
139
+
140
+ - [2025] [Large Scale Animated Foliage in The Witcher 4 UE5 Tech Demo —
141
+ Unreal Fest Stockholm 2025](https://www.youtube.com/watch?v=EdNkm0ezP0o)
142
+ - [2025] [Nanite Foliage — Unreal Engine 5.7 docs](https://dev.epicgames.com/documentation/unreal-engine/nanite-foliage)
143
+ - [2025] [Get a glimpse of Nanite Foliage with voxel representation in
144
+ UE 5.7 — 80.lv](https://80.lv/articles/get-a-glimpse-of-nanite-foliage-with-voxel-representation-in-ue5-7)
145
+ - Surface-splatting fundamentals: Pfister et al, "Surfels: Surface
146
+ Elements as Rendering Primitives" (SIGGRAPH 2000)
147
+ - Octahedral encoding (used in atlas sampling): Cigolle et al, "A
148
+ Survey of Efficient Representations for Independent Unit Vectors"
149
+ (JCGT 2014)
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Voxel ("Nanite voxel") impostor baker.
3
+ *
4
+ * Inspiration: the Witcher 4 / UE5.6+ "Nanite Foliage" tech demo, which
5
+ * swaps alpha-tested cards for a near-pixel-sized voxel representation
6
+ * at distance. Each "voxel" is a point with a world-space size, carrying
7
+ * a baked G-buffer (position, normal, albedo, ORM) — no alpha. Targeted
8
+ * at very low point counts (128–2048), where each voxel projects to
9
+ * around one screen pixel at the impostor's design viewing distance.
10
+ *
11
+ * Bake strategy: control the point count by **atlas resolution**, not
12
+ * by varying the voxel grid resolution at a fixed atlas. Reason: varying
13
+ * the voxel grid at fixed atlas biases each cell's centroid toward
14
+ * whichever views happened to land more atlas pixels in that cell — a
15
+ * systematic directional bias that grows with coarser grids. Re-baking
16
+ * the atlas at the right resolution avoids that, because each bake
17
+ * produces fresh, evenly-distributed samples in the target frequency
18
+ * range.
19
+ *
20
+ * Search algorithm:
21
+ *
22
+ * PHASE 1 — coarse halving. Start at `resolution`, halve atlas
23
+ * resolution each iteration until the point count fits budget.
24
+ * O(log) iterations, each a full GPU bake.
25
+ *
26
+ * PHASE 2 — binary-search refinement. Between the last over-budget
27
+ * resolution and the first under-budget one, binary-search in
28
+ * steps of `frames` (the smallest atlas-resolution granularity
29
+ * that keeps each per-frame tile integer-sized). Pick the
30
+ * largest atlas resolution that still fits — that gives the most
31
+ * points up to budget = best detail.
32
+ *
33
+ * Each iteration:
34
+ * 1. Re-bake atlas at candidate resolution via {@link ImpostorBaker}.
35
+ * 2. Read back samples on CPU.
36
+ * 3. Voxelise at grid_res = atlas_res / frames (matched 1:1 so each
37
+ * atlas pixel maps to roughly one voxel cell).
38
+ * 4. Count, compare to budget, advance search.
39
+ *
40
+ * Re-baking costs a GPU pass per iteration (~250 draws for 16² frames),
41
+ * so a full search is ~10 bakes ≈ a couple seconds on modern hardware.
42
+ * Acceptable for one-shot offline impostor prep where quality
43
+ * dominates.
44
+ */
45
+ export class VoxelImpostorBaker {
46
+ /**
47
+ * @type {THREE.WebGLRenderer|null}
48
+ * @private
49
+ */
50
+ private _renderer;
51
+ /**
52
+ *
53
+ * @param {THREE.WebGLRenderer} v
54
+ */
55
+ set renderer(arg: import("three").WebGLRenderer);
56
+ /**
57
+ * @param {object} params
58
+ * @param {{mesh:ShadedGeometry, transform:mat4}[]} params.objects
59
+ * @param {number} [params.point_budget] target maximum point count.
60
+ * The baker may produce fewer if the input is too small for the
61
+ * target, but never more.
62
+ * @param {ImpostorCaptureType} [params.capture_type]
63
+ * @param {number} [params.frames] atlas frame count per axis
64
+ * (total sampled views = frames²). Also the granularity of the
65
+ * atlas-resolution binary search: candidates must be multiples
66
+ * of `frames` so each per-frame tile stays integer-sized.
67
+ * Default 16.
68
+ * @param {number} [params.resolution] maximum atlas resolution.
69
+ * Upper bound of the search; the baker may pick a smaller value
70
+ * to fit the budget. Default 1024.
71
+ * @returns {VoxelImpostorDescription}
72
+ */
73
+ bake({ objects, point_budget, capture_type, frames, resolution }: {
74
+ objects: {
75
+ mesh: ShadedGeometry;
76
+ transform: mat4;
77
+ }[];
78
+ point_budget?: number;
79
+ capture_type?: ImpostorCaptureType;
80
+ frames?: number;
81
+ resolution?: number;
82
+ }): VoxelImpostorDescription;
83
+ /**
84
+ * Pack the search result into a final VoxelImpostorDescription.
85
+ * @private
86
+ */
87
+ private _compose_result;
88
+ }
89
+ import { ImpostorCaptureType } from "../octahedral/ImpostorCaptureType.js";
90
+ import { VoxelImpostorDescription } from "./VoxelImpostorDescription.js";
91
+ //# sourceMappingURL=VoxelImpostorBaker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoxelImpostorBaker.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/impostors/voxel/VoxelImpostorBaker.js"],"names":[],"mappings":"AAsDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH;IAEI;;;OAGG;IACH,kBAAiB;IAEjB;;;OAGG;IACH,iDAEC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH;QAf2D,OAAO,EAAvD;YAAC,IAAI,iBAAgB;YAAC,SAAS,OAAK;SAAC,EAAE;QACvB,YAAY,GAA5B,MAAM;QAGuB,YAAY,GAAzC,mBAAmB;QACH,MAAM,GAAtB,MAAM;QAKU,UAAU,GAA1B,MAAM;QAGJ,wBAAwB,CA4MpC;IAGD;;;OAGG;IACH,wBAkCC;CACJ;oCApXmC,sCAAsC;yCAGjC,+BAA+B"}
@@ -0,0 +1,376 @@
1
+ import { vec3 } from "gl-matrix";
2
+ import { assert } from "../../../../core/assert.js";
3
+ import { ImpostorBaker } from "../octahedral/ImpostorBaker.js";
4
+ import { ImpostorCaptureType } from "../octahedral/ImpostorCaptureType.js";
5
+ import { read_atlas_to_samples } from "./bake/read_atlas_to_samples.js";
6
+ import { voxelize_samples } from "./bake/voxelize_samples.js";
7
+ import { VoxelImpostorDescription } from "./VoxelImpostorDescription.js";
8
+
9
+
10
+ /**
11
+ * Compute an axis-aligned bounding box over every input mesh's positions
12
+ * after applying its world transform. We need this in addition to the
13
+ * bounding sphere (which the underlying ImpostorBaker already computes)
14
+ * because the voxel grid is axis-aligned, not spherical — a sphere bound
15
+ * would waste cells in the corners.
16
+ *
17
+ * @param {{mesh:ShadedGeometry, transform:mat4}[]} objects
18
+ * @returns {{min:number[], max:number[]}}
19
+ */
20
+ function compute_bounding_box(objects) {
21
+ const min = [Infinity, Infinity, Infinity];
22
+ const max = [-Infinity, -Infinity, -Infinity];
23
+
24
+ for (let k = 0; k < objects.length; k++) {
25
+ const object = objects[k];
26
+
27
+ const positions = object.mesh.geometry.getAttribute('position');
28
+ const arr = positions.array;
29
+ const m = object.transform;
30
+
31
+ for (let i = 0; i < positions.count; i++) {
32
+ const ix = i * positions.itemSize;
33
+ const x = arr[ix];
34
+ const y = arr[ix + 1];
35
+ const z = arr[ix + 2];
36
+
37
+ // Manual mat4 * vec3 (point) — Float32Array-friendly.
38
+ const wx = m[0] * x + m[4] * y + m[8] * z + m[12];
39
+ const wy = m[1] * x + m[5] * y + m[9] * z + m[13];
40
+ const wz = m[2] * x + m[6] * y + m[10] * z + m[14];
41
+
42
+ if (wx < min[0]) min[0] = wx;
43
+ if (wy < min[1]) min[1] = wy;
44
+ if (wz < min[2]) min[2] = wz;
45
+ if (wx > max[0]) max[0] = wx;
46
+ if (wy > max[1]) max[1] = wy;
47
+ if (wz > max[2]) max[2] = wz;
48
+ }
49
+ }
50
+
51
+ return { min, max };
52
+ }
53
+
54
+
55
+ /**
56
+ * Voxel ("Nanite voxel") impostor baker.
57
+ *
58
+ * Inspiration: the Witcher 4 / UE5.6+ "Nanite Foliage" tech demo, which
59
+ * swaps alpha-tested cards for a near-pixel-sized voxel representation
60
+ * at distance. Each "voxel" is a point with a world-space size, carrying
61
+ * a baked G-buffer (position, normal, albedo, ORM) — no alpha. Targeted
62
+ * at very low point counts (128–2048), where each voxel projects to
63
+ * around one screen pixel at the impostor's design viewing distance.
64
+ *
65
+ * Bake strategy: control the point count by **atlas resolution**, not
66
+ * by varying the voxel grid resolution at a fixed atlas. Reason: varying
67
+ * the voxel grid at fixed atlas biases each cell's centroid toward
68
+ * whichever views happened to land more atlas pixels in that cell — a
69
+ * systematic directional bias that grows with coarser grids. Re-baking
70
+ * the atlas at the right resolution avoids that, because each bake
71
+ * produces fresh, evenly-distributed samples in the target frequency
72
+ * range.
73
+ *
74
+ * Search algorithm:
75
+ *
76
+ * PHASE 1 — coarse halving. Start at `resolution`, halve atlas
77
+ * resolution each iteration until the point count fits budget.
78
+ * O(log) iterations, each a full GPU bake.
79
+ *
80
+ * PHASE 2 — binary-search refinement. Between the last over-budget
81
+ * resolution and the first under-budget one, binary-search in
82
+ * steps of `frames` (the smallest atlas-resolution granularity
83
+ * that keeps each per-frame tile integer-sized). Pick the
84
+ * largest atlas resolution that still fits — that gives the most
85
+ * points up to budget = best detail.
86
+ *
87
+ * Each iteration:
88
+ * 1. Re-bake atlas at candidate resolution via {@link ImpostorBaker}.
89
+ * 2. Read back samples on CPU.
90
+ * 3. Voxelise at grid_res = atlas_res / frames (matched 1:1 so each
91
+ * atlas pixel maps to roughly one voxel cell).
92
+ * 4. Count, compare to budget, advance search.
93
+ *
94
+ * Re-baking costs a GPU pass per iteration (~250 draws for 16² frames),
95
+ * so a full search is ~10 bakes ≈ a couple seconds on modern hardware.
96
+ * Acceptable for one-shot offline impostor prep where quality
97
+ * dominates.
98
+ */
99
+ export class VoxelImpostorBaker {
100
+
101
+ /**
102
+ * @type {THREE.WebGLRenderer|null}
103
+ * @private
104
+ */
105
+ _renderer = null;
106
+
107
+ /**
108
+ *
109
+ * @param {THREE.WebGLRenderer} v
110
+ */
111
+ set renderer(v) {
112
+ this._renderer = v;
113
+ }
114
+
115
+ /**
116
+ * @param {object} params
117
+ * @param {{mesh:ShadedGeometry, transform:mat4}[]} params.objects
118
+ * @param {number} [params.point_budget] target maximum point count.
119
+ * The baker may produce fewer if the input is too small for the
120
+ * target, but never more.
121
+ * @param {ImpostorCaptureType} [params.capture_type]
122
+ * @param {number} [params.frames] atlas frame count per axis
123
+ * (total sampled views = frames²). Also the granularity of the
124
+ * atlas-resolution binary search: candidates must be multiples
125
+ * of `frames` so each per-frame tile stays integer-sized.
126
+ * Default 16.
127
+ * @param {number} [params.resolution] maximum atlas resolution.
128
+ * Upper bound of the search; the baker may pick a smaller value
129
+ * to fit the budget. Default 1024.
130
+ * @returns {VoxelImpostorDescription}
131
+ */
132
+ bake({
133
+ objects,
134
+ point_budget = 16384,
135
+ capture_type = ImpostorCaptureType.FullSphere,
136
+ frames = 16,
137
+ resolution = 1024
138
+ }) {
139
+
140
+ console.time('voxel bake');
141
+
142
+ assert.defined(objects, 'objects');
143
+ assert.isNonNegativeInteger(point_budget, 'point_budget');
144
+ assert.greaterThanOrEqual(point_budget, 1, 'point_budget must be >= 1');
145
+
146
+ if (this._renderer === null) {
147
+ throw new Error('No renderer attached. Renderer is required for baking.');
148
+ }
149
+
150
+ const renderer = this._renderer;
151
+
152
+ // Bounding box stays the same across re-bakes — compute once.
153
+ const aabb = compute_bounding_box(objects);
154
+
155
+ const octa_baker = new ImpostorBaker();
156
+ octa_baker.renderer = renderer;
157
+
158
+ // Minimum meaningful atlas resolution: 2 pixels per frame
159
+ // (1 pixel per frame is rasteriser-deadtime; 2 gives some
160
+ // content per view). Below this, the search is degenerate.
161
+ const min_resolution = Math.max(frames * 2, frames);
162
+
163
+ // Floor max resolution to a multiple of `frames` so the very
164
+ // first iteration is already a valid candidate.
165
+ const max_resolution = Math.floor(resolution / frames) * frames;
166
+ if (max_resolution < min_resolution) {
167
+ throw new Error(`resolution (=${resolution}) is too small for frames (=${frames}); need at least ${min_resolution}`);
168
+ }
169
+
170
+ /**
171
+ * One bake-and-voxelise iteration at a given atlas resolution.
172
+ * Each call is a full GPU bake + CPU readback + voxelise; the
173
+ * atlas is disposed immediately after voxelising since the
174
+ * point cloud carries everything we need.
175
+ *
176
+ * @param {number} atlas_res
177
+ * @returns {{
178
+ * atlas_res: number,
179
+ * voxelised: {points: Float32Array, point_count: number, voxel_size: number},
180
+ * sample_count: number,
181
+ * sphere_radius: number,
182
+ * offset: number[],
183
+ * source_geometry_polygon_count: number,
184
+ * source_geometry_vertex_count: number,
185
+ * source_material_count: number,
186
+ * source_instance_count: number
187
+ * }}
188
+ */
189
+ const bake_and_voxelise_at = (atlas_res) => {
190
+ console.time(`voxel bake / iter ${atlas_res}`);
191
+
192
+ const atlas = octa_baker.bake({
193
+ objects,
194
+ frames,
195
+ resolution: atlas_res,
196
+ type: capture_type
197
+ });
198
+
199
+ const { samples, sample_count } = read_atlas_to_samples({
200
+ impostor: atlas,
201
+ renderer
202
+ });
203
+
204
+ // grid_res = atlas pixels per frame, matched 1:1 so each
205
+ // atlas pixel maps to roughly one voxel cell. With many
206
+ // views (frames²), each cell still gets multiple samples
207
+ // for noise-averaging — just fewer than at higher atlas
208
+ // resolutions.
209
+ const grid_resolution = atlas_res / frames;
210
+
211
+ // Use the AABB plus a small margin (1% of bounding-sphere
212
+ // radius) so depth-quantisation jitter at the AABB
213
+ // boundary doesn't get rejected by the voxeliser.
214
+ const margin = atlas.sphere_radius * 0.01;
215
+ const bounds_min = [aabb.min[0] - margin, aabb.min[1] - margin, aabb.min[2] - margin];
216
+ const bounds_max = [aabb.max[0] + margin, aabb.max[1] + margin, aabb.max[2] + margin];
217
+
218
+ const voxelised = voxelize_samples({
219
+ samples,
220
+ sample_count,
221
+ bounds_min,
222
+ bounds_max,
223
+ grid_resolution
224
+ });
225
+
226
+ const sphere_radius = atlas.sphere_radius;
227
+ const offset = [atlas.offset[0], atlas.offset[1], atlas.offset[2]];
228
+ const source_geometry_polygon_count = atlas.source_geometry_polygon_count;
229
+ const source_geometry_vertex_count = atlas.source_geometry_vertex_count;
230
+ const source_material_count = atlas.source_material_count;
231
+ const source_instance_count = atlas.source_instance_count;
232
+
233
+ // Free GPU MRT — we have everything we need on CPU now.
234
+ atlas.rt.dispose();
235
+
236
+ console.timeEnd(`voxel bake / iter ${atlas_res}`);
237
+ console.log(` atlas ${atlas_res} (grid ${grid_resolution}): ${voxelised.point_count} points from ${sample_count} samples`);
238
+
239
+ return {
240
+ atlas_res,
241
+ voxelised,
242
+ sample_count,
243
+ sphere_radius,
244
+ offset,
245
+ source_geometry_polygon_count,
246
+ source_geometry_vertex_count,
247
+ source_material_count,
248
+ source_instance_count
249
+ };
250
+ };
251
+
252
+
253
+ // --- PHASE 1: coarse halving ---
254
+ // Find the largest power-of-two-halving of max_resolution that
255
+ // fits the budget, plus the smallest one that doesn't. These
256
+ // bracket the optimal atlas resolution for phase 2.
257
+ let coarse_under = null;
258
+ let coarse_over_res = null;
259
+
260
+ let res = max_resolution;
261
+
262
+ while (true) {
263
+ const result = bake_and_voxelise_at(res);
264
+
265
+ if (result.voxelised.point_count <= point_budget) {
266
+ coarse_under = result;
267
+ break;
268
+ }
269
+
270
+ coarse_over_res = res;
271
+
272
+ const next = Math.max(
273
+ min_resolution,
274
+ Math.floor((res / 2) / frames) * frames
275
+ );
276
+
277
+ if (next >= res) {
278
+ // Halving would not make progress — accept the floor.
279
+ return this._compose_result({
280
+ bake_result: bake_and_voxelise_at(min_resolution),
281
+ capture_type,
282
+ grid_resolution: min_resolution / frames,
283
+ source_atlas_frames: frames,
284
+ source_atlas_resolution: min_resolution
285
+ });
286
+ }
287
+
288
+ res = next;
289
+ }
290
+
291
+
292
+ // --- PHASE 2: binary-search refinement ---
293
+ // Between (coarse_over_res, coarse_under.atlas_res], find the
294
+ // largest atlas resolution that still fits the budget. Step
295
+ // granularity is `frames` so per-frame tiles stay integer-sized.
296
+ let best = coarse_under;
297
+
298
+ if (coarse_over_res !== null) {
299
+ let lo = coarse_under.atlas_res; // confirmed fits budget
300
+ let hi = coarse_over_res; // confirmed overflows
301
+
302
+ while (hi - lo > frames) {
303
+ // Round mid down to a multiple of `frames`.
304
+ const mid_raw = Math.floor((lo + hi) / 2);
305
+ const mid = Math.floor(mid_raw / frames) * frames;
306
+
307
+ if (mid <= lo || mid >= hi) {
308
+ // No more integer-step candidates between lo and hi.
309
+ break;
310
+ }
311
+
312
+ const result = bake_and_voxelise_at(mid);
313
+
314
+ if (result.voxelised.point_count <= point_budget) {
315
+ lo = mid;
316
+ best = result;
317
+ } else {
318
+ hi = mid;
319
+ }
320
+ }
321
+ }
322
+
323
+
324
+ console.timeEnd('voxel bake');
325
+ console.log(`VoxelImpostorBaker: settled on atlas ${best.atlas_res} → ${best.voxelised.point_count} points (budget ${point_budget})`);
326
+
327
+ return this._compose_result({
328
+ bake_result: best,
329
+ capture_type,
330
+ grid_resolution: best.atlas_res / frames,
331
+ source_atlas_frames: frames,
332
+ source_atlas_resolution: best.atlas_res
333
+ });
334
+ }
335
+
336
+
337
+ /**
338
+ * Pack the search result into a final VoxelImpostorDescription.
339
+ * @private
340
+ */
341
+ _compose_result({
342
+ bake_result,
343
+ capture_type,
344
+ grid_resolution,
345
+ source_atlas_frames,
346
+ source_atlas_resolution
347
+ }) {
348
+ const result = new VoxelImpostorDescription();
349
+
350
+ result.capture_type = capture_type;
351
+ result.sphere_radius = bake_result.sphere_radius;
352
+ vec3.copy(result.offset, bake_result.offset);
353
+
354
+ result.points = bake_result.voxelised.points;
355
+ result.point_count = bake_result.voxelised.point_count;
356
+ result.voxel_size = bake_result.voxelised.voxel_size;
357
+ result.grid_resolution = grid_resolution;
358
+
359
+ // Auto-tuned splat diameter — sqrt(2) covers the worst-case
360
+ // oblique projection of a voxel cell (a 45°-to-view face is
361
+ // sqrt(2)x wider in screen than its on-axis projection). Less-
362
+ // oblique angles get overlap, depth-test resolves the
363
+ // stacking. Render-time inward-shift (see shaders) keeps the
364
+ // silhouette tight regardless.
365
+ result.point_diameter = bake_result.voxelised.voxel_size * Math.SQRT2;
366
+
367
+ result.source_atlas_resolution = source_atlas_resolution;
368
+ result.source_atlas_frames = source_atlas_frames;
369
+ result.source_geometry_polygon_count = bake_result.source_geometry_polygon_count;
370
+ result.source_geometry_vertex_count = bake_result.source_geometry_vertex_count;
371
+ result.source_material_count = bake_result.source_material_count;
372
+ result.source_instance_count = bake_result.source_instance_count;
373
+
374
+ return result;
375
+ }
376
+ }