@woosh/meep-engine 2.33.21 → 2.33.25

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 (285) hide show
  1. package/core/assert.js +3 -1
  2. package/core/bvh2/BinaryNode.js +1 -1
  3. package/core/bvh2/aabb3/AABB3.js +18 -0
  4. package/core/bvh2/aabb3/AABB3Math.js +1 -1
  5. package/core/bvh2/binary/2/BinaryUint32BVH.js +498 -0
  6. package/core/bvh2/binary/2/BinaryUint32BVH.spec.js +54 -0
  7. package/core/bvh2/binary/IndexedBinaryBVH.js +22 -26
  8. package/core/bvh2/traversal/ThreeClippingPlaneComputingBVHVisitor.js +5 -1
  9. package/core/bvh2/traversal/__detailed_box_volume_intersection.js +31 -11
  10. package/core/collection/ArrayUtils.js +1 -1
  11. package/core/collection/array/arrayQuickSort.js +9 -6
  12. package/core/collection/array/array_swap.js +22 -0
  13. package/core/collection/array/binarySearchHighIndex.js +1 -1
  14. package/core/collection/array/computeHashArray.js +22 -0
  15. package/core/collection/array/computeHashIntegerArray.js +15 -0
  16. package/core/collection/array/copyArray.js +2 -2
  17. package/core/collection/table/DataType2TypedArrayConstructorMapping.js +15 -0
  18. package/core/color/Color.js +2 -1
  19. package/core/function/FunctionCompiler.js +2 -1
  20. package/core/geom/3d/aabb/aabb3_computeDistanceAbovePlane.js +9 -33
  21. package/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +10 -2
  22. package/core/geom/3d/line/line3_computeSegmentPointDistance_sqr.js +41 -0
  23. package/core/geom/3d/morton/mortonEncode_magicbits.js +2 -1
  24. package/core/geom/3d/morton/reinterpret_float32_as_int32.js +13 -0
  25. package/core/geom/3d/morton/v3_morton_encode_transformed.js +33 -0
  26. package/core/geom/3d/normal/hemioct/unit_hemioct.spec.js +1 -1
  27. package/core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js +13 -14
  28. package/core/geom/3d/ray/ray_computeNearestPointToPoint.js +37 -0
  29. package/core/geom/3d/shape/AbstractShape3D.js +38 -0
  30. package/core/geom/3d/shape/CompositeShape.js +240 -0
  31. package/core/geom/3d/shape/TransformedShape3D.js +126 -0
  32. package/core/geom/3d/shape/UnitCubeShape3D.js +24 -0
  33. package/core/geom/3d/shape/UnitSphereShape3D.js +24 -0
  34. package/core/geom/3d/shape/util/shape_to_visual_entity.js +159 -0
  35. package/core/geom/3d/voxel/DenseBitVolume3D.js +87 -0
  36. package/core/geom/3d/voxel/buildVolumeFromProjectedGeometry.js +23 -0
  37. package/core/geom/AABB2.js +1 -1
  38. package/core/geom/ConicRay.js +3 -1
  39. package/core/geom/LineSegment.js +0 -78
  40. package/core/geom/Matrix4.js +7 -8
  41. package/core/geom/Plane.js +14 -9
  42. package/core/geom/Rectangle.js +2 -1
  43. package/core/geom/Vector1.js +1 -1
  44. package/core/geom/Vector3.js +2 -1
  45. package/core/geom/Vector4.js +2 -1
  46. package/core/geom/random/randomPointInBox.js +7 -3
  47. package/core/geom/random/randomPointInPoint.js +6 -3
  48. package/core/geom/random/randomPointInSphere.js +9 -5
  49. package/core/geom/random/randomPointOnBox.js +7 -3
  50. package/core/geom/random/randomPointOnSphere.js +6 -3
  51. package/core/geom/v3_length.js +8 -3
  52. package/core/graph/graph_k_means_cluster.js +1 -1
  53. package/core/json/resolvePathByArray.js +2 -2
  54. package/core/math/MathUtils.js +0 -354
  55. package/core/math/MathUtils.spec.js +7 -1
  56. package/core/math/gaussian.js +9 -0
  57. package/core/math/hash/computeHashFloat.js +17 -0
  58. package/core/math/hash/computeHashFloatArray.js +34 -0
  59. package/core/math/hash/computeObjectHash.js +54 -0
  60. package/core/math/intersects1D.js +19 -0
  61. package/core/math/interval/NumericInterval.js +2 -2
  62. package/core/math/isValueBetween.js +10 -0
  63. package/core/math/isValueBetweenInclusive.js +10 -0
  64. package/core/math/noise/curl_noise_3dt.js +1 -1
  65. package/core/math/noise/sdnoise.js +10 -10
  66. package/core/math/overlap1D.js +19 -0
  67. package/core/math/pingpong.js +17 -0
  68. package/core/math/random/makeRangedRandom.js +19 -0
  69. package/core/math/random/randomFloatBetween.js +14 -0
  70. package/core/math/random/randomFromArray.js +19 -0
  71. package/core/math/random/randomGaussian.js +15 -0
  72. package/core/math/random/randomIntegerBetween.js +14 -0
  73. package/core/math/random/roundFair.js +15 -0
  74. package/core/math/separation1D.js +21 -0
  75. package/core/math/solveQuadratic.js +25 -0
  76. package/core/model/BoundedValue.js +1 -1
  77. package/core/model/node-graph/node/NodeInstancePortReference.js +1 -1
  78. package/core/model/node-graph/node/Port.js +1 -1
  79. package/core/model/reactive/evaluation/MultiPredicateEvaluator.spec.js +3 -1
  80. package/core/model/reactive/model/ReactiveBinaryExpression.js +1 -1
  81. package/core/model/reactive/model/terminal/ReactiveLiteralNumber.js +1 -1
  82. package/core/model/reactive/model/terminal/ReactiveReference.js +1 -1
  83. package/core/model/reactive/model/util/createRandomReactiveExpression.js +1 -1
  84. package/core/model/stat/LinearModifier.js +1 -1
  85. package/core/primitives/array/computeIntegerArrayHash.js +1 -1
  86. package/{engine/graphics/render/forward_plus/materials → core/primitives/strings}/insert_after.js +3 -0
  87. package/core/primitives/strings/insert_after_or_replace.js +27 -0
  88. package/editor/process/symbolic/makeHelperBoxGeometry.js +44 -0
  89. package/editor/view/ecs/EntityEditor.js +2 -2
  90. package/editor/view/ecs/components/particles/ParticleEmitterController.js +2 -2
  91. package/engine/EngineHarness.js +1 -0
  92. package/engine/animation/AnimationUtils.js +5 -5
  93. package/engine/animation/curve/AnimationCurve.js +72 -0
  94. package/engine/animation/curve/Keyframe.js +27 -0
  95. package/engine/animation/keyed2/AnimationTrack.js +27 -3
  96. package/engine/asset/Asset.js +1 -1
  97. package/engine/asset/loaders/GLTFAssetLoader.d.ts +1 -1
  98. package/engine/asset/loaders/GLTFAssetLoader.js +10 -0
  99. package/engine/asset/loaders/image/ImageRGBADataAsset.js +8 -1
  100. package/engine/asset/loaders/material/computeImageBitmapEquality.js +11 -0
  101. package/engine/asset/loaders/material/computeImageBitmapHash.js +22 -28
  102. package/engine/asset/loaders/material/computeMaterialHash.js +3 -1
  103. package/engine/asset/loaders/material/computeTextureHash.js +2 -1
  104. package/engine/ecs/EntityBuilder.js +25 -5
  105. package/engine/ecs/animation/Animation.js +2 -1
  106. package/engine/ecs/animation/InverseKinematics.js +2 -1
  107. package/engine/ecs/attachment/AttachmentBinding.js +8 -0
  108. package/engine/ecs/attachment/AttachmentSystem.js +4 -0
  109. package/engine/ecs/attachment/TransformAttachmentBinding.js +14 -44
  110. package/engine/ecs/components/Tag.js +27 -6
  111. package/engine/ecs/dynamic_actions/DynamicActorSystem.js +2 -1
  112. package/engine/ecs/dynamic_actions/DynamicRuleDescriptionTable.spec.js +3 -5
  113. package/engine/ecs/dynamic_actions/actions/definition/WeightedRandomActionDescription.js +1 -1
  114. package/engine/ecs/evaluation/complex/PointFitnessGaussianBlur.js +1 -1
  115. package/engine/ecs/foliage/ecs/Foliage2.js +1 -1
  116. package/engine/ecs/fow/FogOfWar.js +4 -0
  117. package/engine/ecs/fow/FogOfWarSystem.js +2 -0
  118. package/engine/ecs/fow/shader/FogOfWarRenderer.js +1 -1
  119. package/engine/ecs/gui/GUIElement.js +1 -1
  120. package/engine/ecs/gui/hud/HeadsUpDisplay.js +1 -1
  121. package/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +2 -0
  122. package/engine/ecs/gui/position/ViewportPosition.js +2 -1
  123. package/engine/ecs/system/AbstractContextSystem.js +1 -1
  124. package/engine/ecs/systems/RangedAttackSystem.js +1 -1
  125. package/engine/ecs/systems/SteeringSystem.js +1 -1
  126. package/engine/ecs/systems/TagSystem.js +17 -0
  127. package/engine/ecs/terrain/tiles/TerrainTileManager.js +1 -1
  128. package/engine/ecs/tooltip/TooltipComponent.js +15 -0
  129. package/engine/ecs/transform/Transform.js +19 -6
  130. package/engine/ecs/util/hideEntityGracefully.js +18 -0
  131. package/engine/graphics/GraphicsEngine.js +11 -23
  132. package/engine/graphics/camera/testClippingPlaneComputation.js +2 -2
  133. package/engine/graphics/composit/CompositLayer.js +17 -4
  134. package/engine/graphics/composit/CompositingStages.js +8 -0
  135. package/engine/graphics/composit/LayerCompositer.js +35 -6
  136. package/engine/graphics/ecs/animation/animator/AnimationClip.js +2 -1
  137. package/engine/graphics/ecs/animation/animator/AnimationClipDefinition.js +2 -1
  138. package/engine/graphics/ecs/animation/animator/AnimationNotification.js +2 -1
  139. package/engine/graphics/ecs/animation/animator/AnimationNotificationDefinition.js +2 -1
  140. package/engine/graphics/ecs/animation/animator/graph/AnimationGraph.js +2 -1
  141. package/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.js +2 -1
  142. package/engine/graphics/ecs/animation/animator/graph/definition/AnimationStateDefinition.js +1 -1
  143. package/engine/graphics/ecs/animation/animator/graph/definition/AnimationTransitionDefinition.js +2 -1
  144. package/engine/graphics/ecs/camera/CameraClippingPlaneComputer.js +1 -1
  145. package/engine/graphics/ecs/highlight/HighlightDefinition.js +2 -1
  146. package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +11 -7
  147. package/engine/graphics/ecs/light/Light.d.ts +1 -1
  148. package/engine/graphics/ecs/light/Light.js +5 -0
  149. package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +5 -1
  150. package/engine/graphics/ecs/mesh/Mesh.js +2 -1
  151. package/engine/graphics/ecs/mesh-v2/DrawMode.js +5 -0
  152. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +13 -0
  153. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +32 -18
  154. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.d.ts +6 -0
  155. package/engine/graphics/ecs/path/testPathDisplaySystem.js +98 -98
  156. package/engine/graphics/ecs/trail2d/Trail2D.js +17 -4
  157. package/engine/graphics/ecs/trail2d/Trail2DSystem.d.ts +2 -3
  158. package/engine/graphics/ecs/trail2d/Trail2DSystem.js +34 -118
  159. package/engine/graphics/geometry/AttributeSpec.js +105 -0
  160. package/engine/graphics/{micron/format/MicronVertexDataSpec.js → geometry/VertexDataSpec.js} +56 -25
  161. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +7 -7
  162. package/engine/graphics/micron/build/fill_patch_geometry_data.js +1 -1
  163. package/engine/graphics/micron/buildPatchwork.js +1 -1
  164. package/engine/graphics/micron/format/MicronGeometry.js +3 -3
  165. package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +2 -2
  166. package/engine/graphics/micron/format/serialization/deserialize_attribute_spec.js +1 -1
  167. package/engine/graphics/micron/format/serialization/serialize_attribute_spec.js +1 -1
  168. package/engine/graphics/micron/render/PatchCacheKey.js +1 -1
  169. package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +5 -5
  170. package/engine/graphics/micron/render/v1/ThreeVirtualGeometryAdapter.js +1 -1
  171. package/engine/graphics/particles/ParticleEmitterLibrary.js +3 -0
  172. package/engine/graphics/particles/ecs/{ParticleEmitterSystem2.js → ParticleEmitterSystem.js} +17 -9
  173. package/engine/graphics/particles/particular/engine/ParticularEngine.js +12 -4
  174. package/engine/graphics/particles/particular/engine/emitter/PARTICULAR_PARTICLE_SPECIFICATION.js +84 -0
  175. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +106 -169
  176. package/engine/graphics/particles/particular/engine/emitter/ParticleEmitterFlag.js +5 -0
  177. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +14 -3
  178. package/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +141 -14
  179. package/engine/graphics/particles/particular/engine/emitter/ParticlePool.spec.js +8 -7
  180. package/engine/graphics/particles/particular/engine/emitter/computeEmissionFunction.js +37 -0
  181. package/engine/graphics/particles/particular/engine/emitter/distance_to_camera.js +25 -0
  182. package/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.js +8 -2
  183. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -1
  184. package/engine/graphics/particles/particular/engine/parameter/ParameterTrack.js +1 -1
  185. package/engine/graphics/particles/particular/engine/parameter/ParticleParameter.js +1 -1
  186. package/engine/graphics/particles/particular/engine/renderers/billboard/BILLBOARD_PARTICLE_SPECIFICATION.js +24 -0
  187. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +262 -71
  188. package/engine/graphics/particles/particular/engine/renderers/billboard/prototypeBillboardRenderer.js +9 -9
  189. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +80 -46
  190. package/engine/graphics/particles/particular/engine/shader/debugAtlas.js +14 -0
  191. package/engine/graphics/particles/particular/engine/simulator/SimulationStepApplyForce.js +2 -5
  192. package/engine/graphics/particles/particular/engine/simulator/SimulationStepCurlNoiseAcceleration.js +2 -6
  193. package/engine/graphics/particles/particular/engine/simulator/SimulationStepCurlNoiseVelocity.js +2 -7
  194. package/engine/graphics/particles/particular/engine/simulator/SimulationStepFixedPhysics.js +2 -5
  195. package/engine/graphics/particles/particular/engine/simulator/update_parameters.js +1 -1
  196. package/engine/graphics/particles/particular/engine/utils/distributeParticlesOnObject3D.js +1 -1
  197. package/engine/graphics/particles/particular/engine/utils/distrubuteParticlesOnMesh.js +1 -1
  198. package/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +141 -0
  199. package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +478 -0
  200. package/engine/graphics/particles/particular/engine/utils/volume/lut_to_sampler.js +27 -0
  201. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +935 -0
  202. package/engine/graphics/particles/particular/group/Operation.js +18 -0
  203. package/engine/graphics/particles/particular/group/OperationType.js +9 -0
  204. package/engine/graphics/particles/particular/group/ParticleAttribute.js +2 -1
  205. package/engine/graphics/particles/particular/group/ParticleAttributeType.js +11 -0
  206. package/engine/graphics/particles/particular/group/ParticleDataType.js +10 -0
  207. package/engine/graphics/particles/particular/group/ParticleGroup.js +7 -245
  208. package/engine/graphics/particles/particular/group/ParticleGroup.spec.js +3 -1
  209. package/engine/graphics/particles/particular/group/ParticleSpecification.js +21 -14
  210. package/engine/graphics/particles/particular/group/itemSizeFromAttributeType.js +20 -0
  211. package/engine/graphics/particles/particular/group/optimizeCommandQueue.js +162 -0
  212. package/engine/graphics/particles/particular/group/typedArrayConstructorFromDataType.js +19 -0
  213. package/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +2 -2
  214. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +13 -7
  215. package/engine/graphics/render/buffer/slot/parameter/ProgramValueSlotParameter.js +2 -1
  216. package/engine/graphics/render/buffer/slot/parameter/ProgramValueSlotParameterSet.js +1 -1
  217. package/engine/graphics/render/forward_plus/LightManager.js +126 -95
  218. package/engine/graphics/render/forward_plus/PointLight.js +9 -0
  219. package/engine/graphics/render/forward_plus/PointLightData.js +1 -1
  220. package/engine/graphics/render/forward_plus/SpotLight.js +9 -0
  221. package/engine/graphics/render/forward_plus/cluster/compute_light_data_hash_0.js +2 -2
  222. package/engine/graphics/render/forward_plus/computeFrustumCorners.js +14 -32
  223. package/engine/graphics/render/forward_plus/materials/FP_INJECTION_POINT_ACCUMULATION.js +1 -0
  224. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +32 -0
  225. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_DECODE_PARS.js +51 -0
  226. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +25 -0
  227. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +31 -120
  228. package/engine/graphics/render/forward_plus/materials/fp_build_vertex_lighting_shared.js +35 -0
  229. package/engine/graphics/render/forward_plus/materials/fp_build_vertex_shader.js +4 -5
  230. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +1 -1
  231. package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +10 -3
  232. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +595 -60
  233. package/engine/graphics/render/forward_plus/prototypeLightManager.js +256 -136
  234. package/engine/graphics/render/forward_plus/query/analytical_triplanar_corner_mapping.js +8 -0
  235. package/engine/graphics/render/forward_plus/query/cube_mapping.js +38 -0
  236. package/engine/graphics/render/forward_plus/query/detailed_sphere_frustum_intersection_test.js +86 -0
  237. package/engine/graphics/render/forward_plus/query/point_light_inside_volume.js +73 -0
  238. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_objects.js +131 -0
  239. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +129 -0
  240. package/engine/graphics/render/forward_plus/query/spot_light_inside_volume.js +33 -0
  241. package/engine/graphics/render/forward_plus/read_frustum_corner.js +14 -0
  242. package/engine/graphics/render/forward_plus/testClusterEquality.js +22 -0
  243. package/engine/graphics/render/layers/RenderLayerUtils.js +7 -4
  244. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +11 -0
  245. package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +2 -2
  246. package/engine/graphics/shaders/TerrainShader.js +4 -5
  247. package/engine/graphics/texture/atlas/AtlasPatch.js +7 -2
  248. package/engine/graphics/texture/atlas/TextureAtlas.js +2 -2
  249. package/engine/graphics/texture/sampler/HarmonicDiffusionGrid.spec.js +1 -1
  250. package/engine/graphics/texture/sampler/SampleTraverser.js +1 -1
  251. package/engine/graphics/texture/sampler/Sampler2D.js +8 -7
  252. package/engine/graphics/texture/sampler/distanceField.spec.js +1 -1
  253. package/engine/graphics/texture/sampler/scaleSampler2D.js +7 -10
  254. package/engine/graphics/trail/x/RibbonMaterialX.js +3 -3
  255. package/engine/graphics/trail/x/RibbonX.js +17 -2
  256. package/engine/graphics/trail/x/RibbonXPlugin.js +51 -1
  257. package/engine/graphics/util/composeMatrix4.js +33 -23
  258. package/engine/graphics/util/decompose_matrix_4_array.js +61 -0
  259. package/engine/grid/components/GridObstacle.js +3 -10
  260. package/engine/intelligence/behavior/ecs/BehaviorComponent.js +30 -14
  261. package/engine/intelligence/behavior/selector/WeightedElement.js +2 -1
  262. package/engine/intelligence/optimization/RandomOptimizer.js +1 -1
  263. package/engine/knowledge/database/StaticKnowledgeDataTable.js +6 -1
  264. package/engine/navigation/ecs/components/Path.js +1 -6
  265. package/engine/navigation/grid/FastBinaryHeap.spec.js +1 -1
  266. package/engine/reference/v2/Reference.js +6 -0
  267. package/engine/sound/ecs/emitter/SoundEmitter.js +2 -1
  268. package/engine/sound/ecs/emitter/SoundTrack.js +2 -1
  269. package/engine/sound/material/concrete/RandomSoundMaterial.js +1 -1
  270. package/engine/ui/notification/notificationGenerator.js +1 -1
  271. package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +1 -1
  272. package/generation/grid/generation/GridTaskExecuteRuleTimes.js +2 -1
  273. package/generation/markers/actions/MarkerNodeActionSelectRandom.js +1 -1
  274. package/generation/markers/transform/MarkerNodeTransformerRecordUniqueRandomEnum.js +1 -1
  275. package/generation/placement/action/random/CellActionSelectRandom.js +1 -1
  276. package/generation/theme/ThemeEngine.js +2 -2
  277. package/misc/makeMaterialIconCached.js +2 -2
  278. package/package.json +3 -3
  279. package/view/View.js +4 -2
  280. package/view/elements/image/HTMLElementCacheKey.js +2 -1
  281. package/view/elements/radial/RadialText.js +2 -1
  282. package/view/minimap/gl/MinimapMarkersGL.js +6 -100
  283. package/view/minimap/gl/buildMaterial.js +94 -0
  284. package/engine/graphics/micron/format/MicronGeometryBufferAttributeSpec.js +0 -71
  285. package/engine/graphics/render/forward_plus/queryBVH_Frustum.js +0 -345
package/core/assert.js CHANGED
@@ -332,7 +332,9 @@ assert.notNull = function (value, name = "value") {
332
332
  * @param {string} name
333
333
  */
334
334
  assert.notNaN = function (value, name = "value") {
335
- assert.ok(!Number.isNaN(value), `${name} must be a valid number, instead was NaN`);
335
+ if (Number.isNaN(value)) {
336
+ throw new Error(`${name} must be a valid number, instead was NaN`);
337
+ }
336
338
  };
337
339
 
338
340
  /**
@@ -657,7 +657,7 @@ BinaryNode.prototype.insertManyBoxes2 = function (leafFactory, numNodes) {
657
657
  }
658
658
 
659
659
  //sort leaves
660
- arrayQuickSort(nodes, n => n.computeMortonCode(), 0, max2(0, numNodes - 1));
660
+ arrayQuickSort(nodes, n => n.computeMortonCode(), null, 0, max2(0, numNodes - 1));
661
661
 
662
662
  let remaining_nodes = numNodes;
663
663
 
@@ -870,6 +870,20 @@ AABB3.prototype.intersectFrustum = function intersectFrustum(frustum) {
870
870
  return true;
871
871
  };
872
872
 
873
+ /**
874
+ *
875
+ * @param {number} v
876
+ */
877
+ AABB3.prototype.grow = function (v) {
878
+ this.x0 -= v;
879
+ this.y0 -= v;
880
+ this.z0 -= v;
881
+
882
+ this.x1 += v;
883
+ this.y1 += v;
884
+ this.z1 += v;
885
+ };
886
+
873
887
  /**
874
888
  *
875
889
  * @returns {AABB3}
@@ -882,6 +896,10 @@ AABB3.prototype.clone = function () {
882
896
  return clone;
883
897
  };
884
898
 
899
+ AABB3.prototype.fromJSON = function ({ x0, y0, z0, x1, y1, z1 }) {
900
+ this.setBounds(x0, y0, z0, x1, y1, z1);
901
+ };
902
+
885
903
  /**
886
904
  *
887
905
  * @param {BinaryBuffer} buffer
@@ -3,9 +3,9 @@
3
3
  */
4
4
 
5
5
 
6
- import { intersects1D } from "../../math/MathUtils.js";
7
6
  import { max2 } from "../../math/max2.js";
8
7
  import { min2 } from "../../math/min2.js";
8
+ import { intersects1D } from "../../math/intersects1D.js";
9
9
 
10
10
  /**
11
11
  * Float ABS, from standard C lib
@@ -0,0 +1,498 @@
1
+ import { array_copy } from "../../../collection/array/copyArray.js";
2
+ import { min2 } from "../../../math/min2.js";
3
+ import { max2 } from "../../../math/max2.js";
4
+ import { ceilPowerOfTwo } from "../../../binary/operations/ceilPowerOfTwo.js";
5
+ import { array_swap } from "../../../collection/array/array_swap.js";
6
+ import { _boxSurfaceArea2 } from "../../aabb3/AABB3Math.js";
7
+ import { mortonEncode_magicbits } from "../../../geom/3d/morton/mortonEncode_magicbits.js";
8
+ import { min3 } from "../../../math/min3.js";
9
+ import { max3 } from "../../../math/max3.js";
10
+
11
+ /**
12
+ * @readonly
13
+ * @type {number}
14
+ */
15
+ export const BVH_BOX_BYTE_SIZE = 24;
16
+
17
+ /**
18
+ * In bytes
19
+ * @readonly
20
+ * @type {number}
21
+ */
22
+ export const BVH_BINARY_NODE_SIZE = 24;
23
+ /**
24
+ * @readonly
25
+ * @type {number}
26
+ */
27
+ export const BVH_LEAF_NODE_SIZE = 28;
28
+
29
+ /**
30
+ *
31
+ * @param {DataView} data
32
+ * @param {number} destination
33
+ * @param {number} source_a
34
+ * @param {number} source_b
35
+ */
36
+ function refit_binary(data, destination, source_a, source_b) {
37
+ const ax0 = data.getFloat32(source_a);
38
+ const ay0 = data.getFloat32(source_a + 4);
39
+ const az0 = data.getFloat32(source_a + 8);
40
+ const ax1 = data.getFloat32(source_a + 12);
41
+ const ay1 = data.getFloat32(source_a + 16);
42
+ const az1 = data.getFloat32(source_a + 20);
43
+
44
+ const bx0 = data.getFloat32(source_b);
45
+ const by0 = data.getFloat32(source_b + 4);
46
+ const bz0 = data.getFloat32(source_b + 8);
47
+ const bx1 = data.getFloat32(source_b + 12);
48
+ const by1 = data.getFloat32(source_b + 16);
49
+ const bz1 = data.getFloat32(source_b + 20);
50
+
51
+ const x0 = min2(ax0, bx0);
52
+ const y0 = min2(ay0, by0);
53
+ const z0 = min2(az0, bz0);
54
+
55
+ const x1 = max2(ax1, bx1);
56
+ const y1 = max2(ay1, by1);
57
+ const z1 = max2(az1, bz1);
58
+
59
+ data.setFloat32(destination, x0);
60
+ data.setFloat32(destination + 4, y0);
61
+ data.setFloat32(destination + 8, z0);
62
+ data.setFloat32(destination + 12, x1);
63
+ data.setFloat32(destination + 16, y1);
64
+ data.setFloat32(destination + 20, z1);
65
+ }
66
+
67
+ /**
68
+ *
69
+ * @param {Uint8Array} data
70
+ * @param {number} destination
71
+ * @param {number} source
72
+ */
73
+ function copy_box(data, destination, source) {
74
+ array_copy(data, source, data, destination, 24);
75
+ }
76
+
77
+ /**
78
+ *
79
+ * @param {DataView} data
80
+ * @param {number} destination
81
+ * @param {number} source
82
+ */
83
+ function copy_box_zero_size(data, destination, source) {
84
+ const x = data.getFloat32(source);
85
+ const y = data.getFloat32(source + 4);
86
+ const z = data.getFloat32(source + 8);
87
+
88
+ data.setFloat32(destination, x);
89
+ data.setFloat32(destination + 4, y);
90
+ data.setFloat32(destination + 8, z);
91
+
92
+ data.setFloat32(destination + 12, x);
93
+ data.setFloat32(destination + 16, y);
94
+ data.setFloat32(destination + 20, z);
95
+ }
96
+
97
+ /**
98
+ * Assumes data will be normalized to 0...1 value range
99
+ * @param {DataView} data
100
+ * @param {number} address
101
+ * @param {number[]} matrix
102
+ * @returns {number}
103
+ */
104
+ function build_morton(data, address, matrix) {
105
+
106
+ const x0 = data.getFloat32(address);
107
+ const y0 = data.getFloat32(address + 4);
108
+ const z0 = data.getFloat32(address + 8);
109
+ const x1 = data.getFloat32(address + 12);
110
+ const y1 = data.getFloat32(address + 16);
111
+ const z1 = data.getFloat32(address + 20);
112
+
113
+ const cx = (x0 + x1) / 2;
114
+ const cy = (y0 + y1) / 2;
115
+ const cz = (z0 + z1) / 2;
116
+
117
+ return mortonEncode_magicbits(cx, cy, cz);
118
+ // return v3_morton_encode_transformed(cx, cy, cz, matrix);
119
+
120
+ }
121
+
122
+ const scratch_box_0 = [];
123
+ const scratch_box_1 = [];
124
+ const scratch_box_2 = [];
125
+
126
+ const stack = [];
127
+
128
+ export class BinaryUint32BVH {
129
+ constructor() {
130
+ this.__data_buffer = new ArrayBuffer(320);
131
+ this.__data_uint8 = new Uint8Array(this.__data_buffer);
132
+
133
+ /**
134
+ * @readonly
135
+ * @type {DataView}
136
+ * @private
137
+ */
138
+ this.__data_view = new DataView(this.__data_buffer);
139
+
140
+ /**
141
+ *
142
+ * @type {number}
143
+ * @private
144
+ */
145
+ this.__node_count_binary = 0;
146
+
147
+ /**
148
+ *
149
+ * @type {number}
150
+ * @private
151
+ */
152
+ this.__node_count_leaf = 0;
153
+ }
154
+
155
+ getTotalBoxCount() {
156
+ return this.__node_count_binary + this.__node_count_leaf;
157
+ }
158
+
159
+ getBinaryNodeCount() {
160
+ return this.__node_count_binary;
161
+ }
162
+
163
+ getLeafNodeCount() {
164
+ return this.__node_count_leaf;
165
+ }
166
+
167
+ /**
168
+ *
169
+ * @returns {number}
170
+ */
171
+ getLeafBlockAddress() {
172
+ return this.__node_count_binary * BVH_BINARY_NODE_SIZE;
173
+ }
174
+
175
+ /**
176
+ *
177
+ * @returns {DataView}
178
+ */
179
+ getDataView() {
180
+ return this.__data_view;
181
+ }
182
+
183
+ initialize_structure() {
184
+ // compute memory requirements
185
+ const storage_size = this.__node_count_binary * BVH_BINARY_NODE_SIZE + this.__node_count_leaf * BVH_LEAF_NODE_SIZE;
186
+
187
+ // possibly resize the storage
188
+ if (this.__data_buffer.byteLength < storage_size) {
189
+ this.__data_buffer = new ArrayBuffer(storage_size);
190
+ this.__data_uint8 = new Uint8Array(this.__data_buffer);
191
+ this.__data_view = new DataView(this.__data_buffer);
192
+ }
193
+ }
194
+
195
+ /**
196
+ *
197
+ * @param {number} count
198
+ */
199
+ setLeafCount(count) {
200
+ this.__node_count_leaf = count;
201
+
202
+ const twoLeafLimit = ceilPowerOfTwo(count);
203
+
204
+ this.__node_count_binary = twoLeafLimit - 1;
205
+ }
206
+
207
+ /**
208
+ *
209
+ * @param {number} index
210
+ * @param {number} payload
211
+ * @param {number} x0
212
+ * @param {number} y0
213
+ * @param {number} z0
214
+ * @param {number} x1
215
+ * @param {number} y1
216
+ * @param {number} z1
217
+ */
218
+ setLeafData(index, payload, x0, y0, z0, x1, y1, z1) {
219
+ const address = index * BVH_LEAF_NODE_SIZE + this.__node_count_binary * BVH_BINARY_NODE_SIZE;
220
+
221
+ const view = this.__data_view;
222
+
223
+ view.setFloat32(address, x0);
224
+ view.setFloat32(address + 4, y0);
225
+ view.setFloat32(address + 8, z0);
226
+ view.setFloat32(address + 12, x1);
227
+ view.setFloat32(address + 16, y1);
228
+ view.setFloat32(address + 20, z1);
229
+
230
+ view.setUint32(address + 24, payload);
231
+ }
232
+
233
+ /**
234
+ * Read bounds of a box at the given address
235
+ * @param {number} address where the box is found
236
+ * @param {number[]|Float32Array} destination where to write the box coordinates (x0,y0,z0,x1,y1,z1)
237
+ * @param {number} destination_offset offset within the destination array where to start writing results
238
+ */
239
+ readBounds(address, destination, destination_offset) {
240
+ const v = this.__data_view;
241
+ for (let i = 0; i < 6; i++) {
242
+ destination[destination_offset + i] = v.getFloat32(address + i * 4);
243
+ }
244
+ }
245
+
246
+ /**
247
+ *
248
+ * @param {number} leaf_index
249
+ * @returns {number}
250
+ */
251
+ readLeafPayload(leaf_index) {
252
+ const block_address = this.getLeafBlockAddress();
253
+
254
+ const address = block_address + leaf_index * BVH_LEAF_NODE_SIZE + BVH_BOX_BYTE_SIZE;
255
+
256
+ return this.__data_view.getUint32(address);
257
+ }
258
+
259
+ compute_total_surface_area() {
260
+ let result = 0;
261
+
262
+ const box = new Float32Array(6);
263
+
264
+ for (let i = 0; i < this.getTotalBoxCount(); i++) {
265
+ let address;
266
+
267
+ if (i < this.__node_count_binary) {
268
+ address = i * BVH_BINARY_NODE_SIZE;
269
+ } else {
270
+ const li = i - this.__node_count_binary;
271
+ address = li * BVH_LEAF_NODE_SIZE + this.getLeafBlockAddress();
272
+ }
273
+
274
+ this.readBounds(address, box, 0);
275
+ result += _boxSurfaceArea2(box[0], box[1], box[2], box[3], box[4], box[5]);
276
+ }
277
+
278
+ return result;
279
+ }
280
+
281
+ /**
282
+ *
283
+ * @param {number} a address
284
+ * @param {number} b address
285
+ * @param {number} c address
286
+ * @returns {number}
287
+ * @private
288
+ */
289
+ __compute_bounds_area_of_3_boxes(a, b, c) {
290
+ this.readBounds(a, scratch_box_0, 0);
291
+ this.readBounds(b, scratch_box_1, 0);
292
+ this.readBounds(c, scratch_box_2, 0);
293
+
294
+ const x0 = min3(scratch_box_0[0], scratch_box_1[0], scratch_box_2[0]);
295
+ const y0 = min3(scratch_box_0[1], scratch_box_1[1], scratch_box_2[1]);
296
+ const z0 = min3(scratch_box_0[2], scratch_box_1[2], scratch_box_2[2]);
297
+
298
+ const x1 = max3(scratch_box_0[3], scratch_box_1[3], scratch_box_2[3]);
299
+ const y1 = max3(scratch_box_0[4], scratch_box_1[4], scratch_box_2[4]);
300
+ const z1 = max3(scratch_box_0[5], scratch_box_1[5], scratch_box_2[5]);
301
+
302
+ return _boxSurfaceArea2(x0, y0, z0, x1, y1, z1);
303
+ }
304
+
305
+ /**
306
+ *
307
+ * @param {number} a
308
+ * @param {number} b
309
+ * @returns {number}
310
+ * @private
311
+ */
312
+ __fitness_function_should_swap_leaves_sah(a, b) {
313
+ const a_0 = max2(a - 1, 0);
314
+ const a_1 = min2(a + 1, this.__node_count_leaf - 1);
315
+
316
+ const leaf_block_offset = this.getLeafBlockAddress();
317
+
318
+ const a_c_address = a * BVH_LEAF_NODE_SIZE + leaf_block_offset;
319
+ const a_0_address = a_0 * BVH_LEAF_NODE_SIZE + leaf_block_offset;
320
+ const a_1_address = a_1 * BVH_LEAF_NODE_SIZE + leaf_block_offset;
321
+
322
+
323
+ const b_0 = max2(b - 1, 0);
324
+ const b_1 = min2(b + 1, this.__node_count_leaf - 1);
325
+
326
+ const b_c_address = b * BVH_LEAF_NODE_SIZE + leaf_block_offset;
327
+ const b_0_address = b_0 * BVH_LEAF_NODE_SIZE + leaf_block_offset;
328
+ const b_1_address = b_1 * BVH_LEAF_NODE_SIZE + leaf_block_offset;
329
+
330
+
331
+ const current_area = this.__compute_bounds_area_of_3_boxes(a_0_address, a_c_address, a_1_address) + this.__compute_bounds_area_of_3_boxes(b_0_address, b_c_address, b_1_address);
332
+ const swap_area = this.__compute_bounds_area_of_3_boxes(a_0_address, b_c_address, a_1_address) + this.__compute_bounds_area_of_3_boxes(b_0_address, a_c_address, b_1_address);
333
+
334
+ return current_area - swap_area;
335
+ }
336
+
337
+ sort_bubble_sah() {
338
+ const n = this.__node_count_leaf;
339
+
340
+ for (let i = 0; i < n; i++) {
341
+ for (let j = i + 1; j < n; j++) {
342
+ if (this.__fitness_function_should_swap_leaves_sah(i, j) > 0) {
343
+ this.__swap_leaves(i, j);
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+
350
+ /**
351
+ * Sort leaf nodes according to their morton codes
352
+ * @param {number[]} projection
353
+ */
354
+ sort_morton(projection) {
355
+
356
+ const leaf_block_address = this.__node_count_binary * BVH_BINARY_NODE_SIZE;
357
+
358
+ if (this.__node_count_leaf < 2) {
359
+ // no swaps available
360
+ return;
361
+ }
362
+
363
+ let stackPointer = 2;
364
+ let i, j;
365
+
366
+ stack[0] = 0; // first node
367
+ stack[1] = this.__node_count_leaf - 1; // last node
368
+
369
+ const data = this.__data_view;
370
+
371
+ while (stackPointer > 0) {
372
+ stackPointer -= 2;
373
+
374
+ const right = stack[stackPointer + 1];
375
+ const left = stack[stackPointer];
376
+
377
+ i = left;
378
+ j = right;
379
+
380
+ const pivotIndex = (left + right) >> 1;
381
+
382
+ const pivot = build_morton(data, pivotIndex * BVH_LEAF_NODE_SIZE + leaf_block_address, projection);
383
+
384
+ /* partition */
385
+ while (i <= j) {
386
+ while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address, projection) < pivot) {
387
+ i++;
388
+ }
389
+
390
+ while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address, projection) > pivot) {
391
+ j--;
392
+ }
393
+
394
+ if (i <= j) {
395
+
396
+ if (i !== j) {
397
+ //do swap
398
+ this.__swap_leaves(i, j);
399
+ }
400
+
401
+ i++;
402
+ j--;
403
+ }
404
+ }
405
+
406
+ /* recursion */
407
+ if (left < j) {
408
+ stack[stackPointer++] = left;
409
+ stack[stackPointer++] = j;
410
+ }
411
+ if (i < right) {
412
+ stack[stackPointer++] = i;
413
+ stack[stackPointer++] = right;
414
+ }
415
+ }
416
+ }
417
+
418
+ /**
419
+ *
420
+ * @param {number} i
421
+ * @param {number} j
422
+ * @private
423
+ */
424
+ __swap_leaves(i, j) {
425
+ const leaf_block_address = this.getLeafBlockAddress();
426
+ array_swap(
427
+ this.__data_uint8, i * BVH_LEAF_NODE_SIZE + leaf_block_address,
428
+ this.__data_uint8, j * BVH_LEAF_NODE_SIZE + leaf_block_address,
429
+ BVH_LEAF_NODE_SIZE
430
+ );
431
+ }
432
+
433
+ /**
434
+ * Assemble leaf nodes into hierarchy, set binary node bounds iteratively bottom up
435
+ */
436
+ build() {
437
+ const nodeCount = this.__node_count_binary;
438
+
439
+ const leaf_node_block_address = this.__node_count_binary * BVH_BINARY_NODE_SIZE;
440
+
441
+ let level = Math.floor(Math.log(nodeCount) / Math.log(2));
442
+
443
+ let i, offset, level_node_count;
444
+ //NOTE: building first level separately allows to avoid some switching logic needed to determine what is the type of lower level node
445
+ //build one level above leaf nodes
446
+ level_node_count = Math.pow(2, level);
447
+ offset = (level_node_count - 1) * BVH_BINARY_NODE_SIZE;
448
+
449
+ let parentIndex;
450
+
451
+ const node_count_leaf = this.__node_count_leaf;
452
+
453
+ // build bottom-most level, just above the leaves
454
+ for (i = 0; i < level_node_count; i++) {
455
+ const leafIndex0 = i * 2;
456
+ const leafIndex1 = leafIndex0 + 1;
457
+
458
+ const leafOffset0 = leaf_node_block_address + leafIndex0 * BVH_LEAF_NODE_SIZE;
459
+ const leafOffset1 = leaf_node_block_address + leafIndex1 * BVH_LEAF_NODE_SIZE;
460
+
461
+ if (leafIndex1 < node_count_leaf) {
462
+ // both children nodes are valid
463
+ refit_binary(this.__data_view, offset, leafOffset0, leafOffset1);
464
+ } else if (leafIndex0 < node_count_leaf) {
465
+ // only left child node is valid
466
+ copy_box(this.__data_uint8, offset, leafOffset0);
467
+ } else {
468
+ //initialize to 0-size box same position as previous node
469
+ copy_box_zero_size(this.__data_view, offset, offset - BVH_BINARY_NODE_SIZE);
470
+ }
471
+
472
+ offset += BVH_BINARY_NODE_SIZE;
473
+ }
474
+
475
+ level--;
476
+
477
+ //build intermediate nodes
478
+ for (; level >= 0; level--) {
479
+ level_node_count = Math.pow(2, level);
480
+ parentIndex = (level_node_count - 1);
481
+
482
+ for (i = 0; i < level_node_count; i++) {
483
+
484
+ const childIndex0 = (parentIndex << 1) + 1;
485
+ const childIndex1 = childIndex0 + 1;
486
+
487
+ const address_parent = parentIndex * BVH_BINARY_NODE_SIZE;
488
+
489
+ const address_child_0 = childIndex0 * BVH_BINARY_NODE_SIZE;
490
+ const address_child_1 = childIndex1 * BVH_BINARY_NODE_SIZE;
491
+
492
+ refit_binary(this.__data_view, address_parent, address_child_0, address_child_1);
493
+
494
+ parentIndex++;
495
+ }
496
+ }
497
+ }
498
+ }
@@ -0,0 +1,54 @@
1
+ import { BinaryUint32BVH } from "./BinaryUint32BVH.js";
2
+
3
+ test('constructor does not throw', () => {
4
+ new BinaryUint32BVH();
5
+ });
6
+
7
+ test('1 leaf build does not throw', () => {
8
+ const bvh = new BinaryUint32BVH();
9
+
10
+ bvh.setLeafCount(1);
11
+ bvh.initialize_structure();
12
+ bvh.build();
13
+ });
14
+
15
+ test('read/write 1 leaf', () => {
16
+ const bvh = new BinaryUint32BVH();
17
+
18
+ bvh.setLeafCount(1);
19
+ bvh.initialize_structure();
20
+
21
+ bvh.setLeafData(0, 7, -3, -7, -11, 13, 17, 23);
22
+
23
+ expect(bvh.readLeafPayload(0)).toBe(7);
24
+
25
+ const bounds = [];
26
+ bvh.readBounds(0, bounds, 0);
27
+
28
+ expect(bounds[0]).toBeCloseTo(-3);
29
+ expect(bounds[1]).toBeCloseTo(-7);
30
+ expect(bounds[2]).toBeCloseTo(-11);
31
+ expect(bounds[3]).toBeCloseTo(13);
32
+ expect(bounds[4]).toBeCloseTo(17);
33
+ expect(bounds[5]).toBeCloseTo(23);
34
+ });
35
+
36
+ test('4 node sorted build', () => {
37
+ const bvh = new BinaryUint32BVH();
38
+
39
+ bvh.setLeafCount(4);
40
+ bvh.initialize_structure();
41
+
42
+ bvh.setLeafData(0, 3, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6);
43
+ bvh.setLeafData(1, 7, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6);
44
+ bvh.setLeafData(2, 11, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6);
45
+ bvh.setLeafData(3, 13, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6);
46
+
47
+ bvh.sort_morton([
48
+ 1, 0, 0, 0,
49
+ 0, 1, 0, 0,
50
+ 0, 0, 1, 0,
51
+ 0, 0, 0, 1
52
+ ]);
53
+ bvh.build();
54
+ });