@bloomengine/engine 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (562) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/native/android/Cargo.lock +1848 -0
  4. package/native/android/Cargo.toml +20 -0
  5. package/native/android/src/lib.rs +1747 -0
  6. package/native/ios/Cargo.lock +1688 -0
  7. package/native/ios/Cargo.toml +19 -0
  8. package/native/ios/src/lib.rs +2258 -0
  9. package/native/linux/Cargo.lock +1719 -0
  10. package/native/linux/Cargo.toml +22 -0
  11. package/native/linux/src/lib.rs +2236 -0
  12. package/native/macos/Cargo.lock +3310 -0
  13. package/native/macos/Cargo.toml +29 -0
  14. package/native/macos/src/lib.rs +3444 -0
  15. package/native/shared/Cargo.lock +1898 -0
  16. package/native/shared/Cargo.toml +42 -0
  17. package/native/shared/assets/default_font.ttf +0 -0
  18. package/native/shared/build.rs +77 -0
  19. package/native/shared/shaders/common/fog.wgsl +16 -0
  20. package/native/shared/shaders/common/imposter.wgsl +112 -0
  21. package/native/shared/shaders/common/pbr.wgsl +186 -0
  22. package/native/shared/shaders/common/shadows.wgsl +77 -0
  23. package/native/shared/shaders/common/sky.wgsl +8 -0
  24. package/native/shared/shaders/common/tonemap.wgsl +25 -0
  25. package/native/shared/shaders/impulse_field.wgsl +53 -0
  26. package/native/shared/shaders/material_abi.wgsl +360 -0
  27. package/native/shared/shaders/materials/test_minimal.wgsl +42 -0
  28. package/native/shared/src/audio.rs +363 -0
  29. package/native/shared/src/custom_shaders.rs +104 -0
  30. package/native/shared/src/drs.rs +211 -0
  31. package/native/shared/src/engine.rs +186 -0
  32. package/native/shared/src/frame_callbacks.rs +88 -0
  33. package/native/shared/src/geometry.rs +236 -0
  34. package/native/shared/src/handles.rs +76 -0
  35. package/native/shared/src/input.rs +273 -0
  36. package/native/shared/src/jolt_sys.rs +822 -0
  37. package/native/shared/src/lib.rs +43 -0
  38. package/native/shared/src/models.rs +1941 -0
  39. package/native/shared/src/physics_jolt.rs +1528 -0
  40. package/native/shared/src/picking.rs +298 -0
  41. package/native/shared/src/postfx.rs +339 -0
  42. package/native/shared/src/profiler.rs +416 -0
  43. package/native/shared/src/renderer/atmosphere_lut.rs +573 -0
  44. package/native/shared/src/renderer/brdf_lut.rs +154 -0
  45. package/native/shared/src/renderer/formats.rs +778 -0
  46. package/native/shared/src/renderer/graph.rs +465 -0
  47. package/native/shared/src/renderer/hot_reload.rs +390 -0
  48. package/native/shared/src/renderer/impulse_field.rs +455 -0
  49. package/native/shared/src/renderer/material_pipeline.rs +604 -0
  50. package/native/shared/src/renderer/material_system.rs +2106 -0
  51. package/native/shared/src/renderer/mod.rs +13923 -0
  52. package/native/shared/src/renderer/planar_reflection.rs +458 -0
  53. package/native/shared/src/renderer/post_pass.rs +249 -0
  54. package/native/shared/src/renderer/shader_include.rs +205 -0
  55. package/native/shared/src/renderer/shader_library.rs +134 -0
  56. package/native/shared/src/renderer/shaders.rs +5855 -0
  57. package/native/shared/src/renderer/transient.rs +576 -0
  58. package/native/shared/src/renderer/types.rs +259 -0
  59. package/native/shared/src/renderer/util.rs +151 -0
  60. package/native/shared/src/scene.rs +1066 -0
  61. package/native/shared/src/sdf_cache.rs +274 -0
  62. package/native/shared/src/shadows.rs +551 -0
  63. package/native/shared/src/staging.rs +90 -0
  64. package/native/shared/src/string_header.rs +35 -0
  65. package/native/shared/src/text_renderer.rs +456 -0
  66. package/native/shared/src/textures.rs +154 -0
  67. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.cpp +242 -0
  68. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeBuilder.h +121 -0
  69. package/native/third_party/JoltPhysics/Jolt/AABBTree/AABBTreeToBuffer.h +296 -0
  70. package/native/third_party/JoltPhysics/Jolt/AABBTree/NodeCodec/NodeCodecQuadTreeHalfFloat.h +323 -0
  71. package/native/third_party/JoltPhysics/Jolt/AABBTree/TriangleCodec/TriangleCodecIndexed8BitPackSOA4Flags.h +555 -0
  72. package/native/third_party/JoltPhysics/Jolt/ConfigurationString.h +112 -0
  73. package/native/third_party/JoltPhysics/Jolt/Core/ARMNeon.h +94 -0
  74. package/native/third_party/JoltPhysics/Jolt/Core/Array.h +713 -0
  75. package/native/third_party/JoltPhysics/Jolt/Core/Atomics.h +44 -0
  76. package/native/third_party/JoltPhysics/Jolt/Core/BinaryHeap.h +96 -0
  77. package/native/third_party/JoltPhysics/Jolt/Core/ByteBuffer.h +74 -0
  78. package/native/third_party/JoltPhysics/Jolt/Core/Color.cpp +38 -0
  79. package/native/third_party/JoltPhysics/Jolt/Core/Color.h +98 -0
  80. package/native/third_party/JoltPhysics/Jolt/Core/Core.h +652 -0
  81. package/native/third_party/JoltPhysics/Jolt/Core/FPControlWord.h +143 -0
  82. package/native/third_party/JoltPhysics/Jolt/Core/FPException.h +96 -0
  83. package/native/third_party/JoltPhysics/Jolt/Core/FPFlushDenormals.h +43 -0
  84. package/native/third_party/JoltPhysics/Jolt/Core/Factory.cpp +92 -0
  85. package/native/third_party/JoltPhysics/Jolt/Core/Factory.h +54 -0
  86. package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.h +122 -0
  87. package/native/third_party/JoltPhysics/Jolt/Core/FixedSizeFreeList.inl +215 -0
  88. package/native/third_party/JoltPhysics/Jolt/Core/HashCombine.h +234 -0
  89. package/native/third_party/JoltPhysics/Jolt/Core/HashTable.h +876 -0
  90. package/native/third_party/JoltPhysics/Jolt/Core/InsertionSort.h +58 -0
  91. package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.cpp +27 -0
  92. package/native/third_party/JoltPhysics/Jolt/Core/IssueReporting.h +38 -0
  93. package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.h +311 -0
  94. package/native/third_party/JoltPhysics/Jolt/Core/JobSystem.inl +56 -0
  95. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.cpp +65 -0
  96. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemSingleThreaded.h +62 -0
  97. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.cpp +364 -0
  98. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemThreadPool.h +101 -0
  99. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.cpp +230 -0
  100. package/native/third_party/JoltPhysics/Jolt/Core/JobSystemWithBarrier.h +85 -0
  101. package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.cpp +51 -0
  102. package/native/third_party/JoltPhysics/Jolt/Core/LinearCurve.h +67 -0
  103. package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.h +182 -0
  104. package/native/third_party/JoltPhysics/Jolt/Core/LockFreeHashMap.inl +351 -0
  105. package/native/third_party/JoltPhysics/Jolt/Core/Memory.cpp +85 -0
  106. package/native/third_party/JoltPhysics/Jolt/Core/Memory.h +85 -0
  107. package/native/third_party/JoltPhysics/Jolt/Core/Mutex.h +223 -0
  108. package/native/third_party/JoltPhysics/Jolt/Core/MutexArray.h +98 -0
  109. package/native/third_party/JoltPhysics/Jolt/Core/NonCopyable.h +18 -0
  110. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.cpp +677 -0
  111. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.h +301 -0
  112. package/native/third_party/JoltPhysics/Jolt/Core/Profiler.inl +90 -0
  113. package/native/third_party/JoltPhysics/Jolt/Core/QuickSort.h +137 -0
  114. package/native/third_party/JoltPhysics/Jolt/Core/RTTI.cpp +149 -0
  115. package/native/third_party/JoltPhysics/Jolt/Core/RTTI.h +436 -0
  116. package/native/third_party/JoltPhysics/Jolt/Core/Reference.h +244 -0
  117. package/native/third_party/JoltPhysics/Jolt/Core/Result.h +174 -0
  118. package/native/third_party/JoltPhysics/Jolt/Core/STLAlignedAllocator.h +72 -0
  119. package/native/third_party/JoltPhysics/Jolt/Core/STLAllocator.h +127 -0
  120. package/native/third_party/JoltPhysics/Jolt/Core/STLLocalAllocator.h +170 -0
  121. package/native/third_party/JoltPhysics/Jolt/Core/STLTempAllocator.h +80 -0
  122. package/native/third_party/JoltPhysics/Jolt/Core/ScopeExit.h +49 -0
  123. package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.cpp +135 -0
  124. package/native/third_party/JoltPhysics/Jolt/Core/Semaphore.h +68 -0
  125. package/native/third_party/JoltPhysics/Jolt/Core/StaticArray.h +329 -0
  126. package/native/third_party/JoltPhysics/Jolt/Core/StreamIn.h +120 -0
  127. package/native/third_party/JoltPhysics/Jolt/Core/StreamOut.h +97 -0
  128. package/native/third_party/JoltPhysics/Jolt/Core/StreamUtils.h +168 -0
  129. package/native/third_party/JoltPhysics/Jolt/Core/StreamWrapper.h +53 -0
  130. package/native/third_party/JoltPhysics/Jolt/Core/StridedPtr.h +63 -0
  131. package/native/third_party/JoltPhysics/Jolt/Core/StringTools.cpp +101 -0
  132. package/native/third_party/JoltPhysics/Jolt/Core/StringTools.h +38 -0
  133. package/native/third_party/JoltPhysics/Jolt/Core/TempAllocator.h +209 -0
  134. package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.cpp +37 -0
  135. package/native/third_party/JoltPhysics/Jolt/Core/TickCounter.h +58 -0
  136. package/native/third_party/JoltPhysics/Jolt/Core/UnorderedMap.h +80 -0
  137. package/native/third_party/JoltPhysics/Jolt/Core/UnorderedSet.h +32 -0
  138. package/native/third_party/JoltPhysics/Jolt/Geometry/AABox.h +313 -0
  139. package/native/third_party/JoltPhysics/Jolt/Geometry/AABox4.h +224 -0
  140. package/native/third_party/JoltPhysics/Jolt/Geometry/ClipPoly.h +200 -0
  141. package/native/third_party/JoltPhysics/Jolt/Geometry/ClosestPoint.h +498 -0
  142. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.cpp +1467 -0
  143. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder.h +276 -0
  144. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.cpp +335 -0
  145. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexHullBuilder2D.h +105 -0
  146. package/native/third_party/JoltPhysics/Jolt/Geometry/ConvexSupport.h +188 -0
  147. package/native/third_party/JoltPhysics/Jolt/Geometry/EPAConvexHullBuilder.h +845 -0
  148. package/native/third_party/JoltPhysics/Jolt/Geometry/EPAPenetrationDepth.h +557 -0
  149. package/native/third_party/JoltPhysics/Jolt/Geometry/Ellipse.h +77 -0
  150. package/native/third_party/JoltPhysics/Jolt/Geometry/GJKClosestPoint.h +945 -0
  151. package/native/third_party/JoltPhysics/Jolt/Geometry/IndexedTriangle.h +130 -0
  152. package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.cpp +222 -0
  153. package/native/third_party/JoltPhysics/Jolt/Geometry/Indexify.h +19 -0
  154. package/native/third_party/JoltPhysics/Jolt/Geometry/MortonCode.h +40 -0
  155. package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.cpp +178 -0
  156. package/native/third_party/JoltPhysics/Jolt/Geometry/OrientedBox.h +39 -0
  157. package/native/third_party/JoltPhysics/Jolt/Geometry/Plane.h +104 -0
  158. package/native/third_party/JoltPhysics/Jolt/Geometry/RayAABox.h +241 -0
  159. package/native/third_party/JoltPhysics/Jolt/Geometry/RayCapsule.h +37 -0
  160. package/native/third_party/JoltPhysics/Jolt/Geometry/RayCylinder.h +101 -0
  161. package/native/third_party/JoltPhysics/Jolt/Geometry/RaySphere.h +96 -0
  162. package/native/third_party/JoltPhysics/Jolt/Geometry/RayTriangle.h +158 -0
  163. package/native/third_party/JoltPhysics/Jolt/Geometry/Sphere.h +72 -0
  164. package/native/third_party/JoltPhysics/Jolt/Geometry/Triangle.h +34 -0
  165. package/native/third_party/JoltPhysics/Jolt/Jolt.cmake +703 -0
  166. package/native/third_party/JoltPhysics/Jolt/Jolt.h +16 -0
  167. package/native/third_party/JoltPhysics/Jolt/Jolt.natvis +116 -0
  168. package/native/third_party/JoltPhysics/Jolt/Math/BVec16.h +99 -0
  169. package/native/third_party/JoltPhysics/Jolt/Math/BVec16.inl +177 -0
  170. package/native/third_party/JoltPhysics/Jolt/Math/DMat44.h +158 -0
  171. package/native/third_party/JoltPhysics/Jolt/Math/DMat44.inl +310 -0
  172. package/native/third_party/JoltPhysics/Jolt/Math/DVec3.h +291 -0
  173. package/native/third_party/JoltPhysics/Jolt/Math/DVec3.inl +941 -0
  174. package/native/third_party/JoltPhysics/Jolt/Math/Double3.h +48 -0
  175. package/native/third_party/JoltPhysics/Jolt/Math/DynMatrix.h +31 -0
  176. package/native/third_party/JoltPhysics/Jolt/Math/EigenValueSymmetric.h +177 -0
  177. package/native/third_party/JoltPhysics/Jolt/Math/FindRoot.h +42 -0
  178. package/native/third_party/JoltPhysics/Jolt/Math/Float2.h +36 -0
  179. package/native/third_party/JoltPhysics/Jolt/Math/Float3.h +50 -0
  180. package/native/third_party/JoltPhysics/Jolt/Math/Float4.h +44 -0
  181. package/native/third_party/JoltPhysics/Jolt/Math/GaussianElimination.h +102 -0
  182. package/native/third_party/JoltPhysics/Jolt/Math/HalfFloat.h +208 -0
  183. package/native/third_party/JoltPhysics/Jolt/Math/Mat44.h +243 -0
  184. package/native/third_party/JoltPhysics/Jolt/Math/Mat44.inl +952 -0
  185. package/native/third_party/JoltPhysics/Jolt/Math/Math.h +208 -0
  186. package/native/third_party/JoltPhysics/Jolt/Math/MathTypes.h +32 -0
  187. package/native/third_party/JoltPhysics/Jolt/Math/Matrix.h +259 -0
  188. package/native/third_party/JoltPhysics/Jolt/Math/Quat.h +268 -0
  189. package/native/third_party/JoltPhysics/Jolt/Math/Quat.inl +406 -0
  190. package/native/third_party/JoltPhysics/Jolt/Math/Real.h +44 -0
  191. package/native/third_party/JoltPhysics/Jolt/Math/Swizzle.h +19 -0
  192. package/native/third_party/JoltPhysics/Jolt/Math/Trigonometry.h +79 -0
  193. package/native/third_party/JoltPhysics/Jolt/Math/UVec4.h +232 -0
  194. package/native/third_party/JoltPhysics/Jolt/Math/UVec4.inl +636 -0
  195. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.cpp +71 -0
  196. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.h +308 -0
  197. package/native/third_party/JoltPhysics/Jolt/Math/Vec3.inl +942 -0
  198. package/native/third_party/JoltPhysics/Jolt/Math/Vec4.h +320 -0
  199. package/native/third_party/JoltPhysics/Jolt/Math/Vec4.inl +1152 -0
  200. package/native/third_party/JoltPhysics/Jolt/Math/Vector.h +211 -0
  201. package/native/third_party/JoltPhysics/Jolt/ObjectStream/GetPrimitiveTypeOfType.h +54 -0
  202. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.cpp +38 -0
  203. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStream.h +337 -0
  204. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.cpp +252 -0
  205. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryIn.h +57 -0
  206. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.cpp +165 -0
  207. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamBinaryOut.h +57 -0
  208. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.cpp +635 -0
  209. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamIn.h +148 -0
  210. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.cpp +166 -0
  211. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamOut.h +101 -0
  212. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.cpp +418 -0
  213. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextIn.h +55 -0
  214. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.cpp +255 -0
  215. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTextOut.h +62 -0
  216. package/native/third_party/JoltPhysics/Jolt/ObjectStream/ObjectStreamTypes.h +26 -0
  217. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttribute.h +111 -0
  218. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeEnum.h +67 -0
  219. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableAttributeTyped.h +60 -0
  220. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.cpp +15 -0
  221. package/native/third_party/JoltPhysics/Jolt/ObjectStream/SerializableObject.h +170 -0
  222. package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.cpp +70 -0
  223. package/native/third_party/JoltPhysics/Jolt/ObjectStream/TypeDeclarations.h +45 -0
  224. package/native/third_party/JoltPhysics/Jolt/Physics/Body/AllowedDOFs.h +68 -0
  225. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.cpp +426 -0
  226. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.h +452 -0
  227. package/native/third_party/JoltPhysics/Jolt/Physics/Body/Body.inl +197 -0
  228. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyAccess.h +68 -0
  229. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyActivationListener.h +28 -0
  230. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.cpp +234 -0
  231. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyCreationSettings.h +124 -0
  232. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyFilter.h +130 -0
  233. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyID.h +101 -0
  234. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.cpp +1099 -0
  235. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyInterface.h +324 -0
  236. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLock.h +111 -0
  237. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockInterface.h +134 -0
  238. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyLockMulti.h +120 -0
  239. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.cpp +1220 -0
  240. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyManager.h +403 -0
  241. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyPair.h +36 -0
  242. package/native/third_party/JoltPhysics/Jolt/Physics/Body/BodyType.h +19 -0
  243. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.cpp +185 -0
  244. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MassProperties.h +58 -0
  245. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.cpp +92 -0
  246. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.h +308 -0
  247. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionProperties.inl +178 -0
  248. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionQuality.h +31 -0
  249. package/native/third_party/JoltPhysics/Jolt/Physics/Body/MotionType.h +17 -0
  250. package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.cpp +354 -0
  251. package/native/third_party/JoltPhysics/Jolt/Physics/Character/Character.h +159 -0
  252. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.cpp +59 -0
  253. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterBase.h +157 -0
  254. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterID.h +98 -0
  255. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.cpp +1933 -0
  256. package/native/third_party/JoltPhysics/Jolt/Physics/Character/CharacterVirtual.h +752 -0
  257. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/AABoxCast.h +20 -0
  258. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdgeMode.h +17 -0
  259. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ActiveEdges.h +114 -0
  260. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BackFaceMode.h +16 -0
  261. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.cpp +16 -0
  262. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhase.h +109 -0
  263. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp +313 -0
  264. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h +38 -0
  265. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h +148 -0
  266. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceMask.h +92 -0
  267. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseLayerInterfaceTable.h +64 -0
  268. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp +629 -0
  269. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h +108 -0
  270. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/BroadPhaseQuery.h +56 -0
  271. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterMask.h +35 -0
  272. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/ObjectVsBroadPhaseLayerFilterTable.h +66 -0
  273. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.cpp +1768 -0
  274. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/BroadPhase/QuadTree.h +389 -0
  275. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.cpp +107 -0
  276. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastConvexVsTriangles.h +46 -0
  277. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastResult.h +37 -0
  278. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.cpp +223 -0
  279. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CastSphereVsTriangles.h +49 -0
  280. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollectFacesMode.h +16 -0
  281. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.cpp +155 -0
  282. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideConvexVsTriangles.h +56 -0
  283. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollidePointResult.h +25 -0
  284. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShape.h +106 -0
  285. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideShapeVsShapePerLeaf.h +94 -0
  286. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVertexIterator.h +110 -0
  287. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSoftBodyVerticesVsTriangles.h +102 -0
  288. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.cpp +121 -0
  289. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollideSphereVsTriangles.h +50 -0
  290. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollector.h +109 -0
  291. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionCollectorImpl.h +219 -0
  292. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.cpp +107 -0
  293. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionDispatch.h +97 -0
  294. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.cpp +35 -0
  295. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/CollisionGroup.h +97 -0
  296. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ContactListener.h +143 -0
  297. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.cpp +213 -0
  298. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/EstimateCollisionResponse.h +48 -0
  299. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.cpp +32 -0
  300. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilter.h +46 -0
  301. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.cpp +38 -0
  302. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/GroupFilterTable.h +130 -0
  303. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/InternalEdgeRemovingCollector.h +279 -0
  304. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.cpp +271 -0
  305. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.h +44 -0
  306. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.cpp +448 -0
  307. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseQuery.h +77 -0
  308. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.cpp +62 -0
  309. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/NarrowPhaseStats.h +110 -0
  310. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayer.h +111 -0
  311. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterMask.h +52 -0
  312. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ObjectLayerPairFilterTable.h +78 -0
  313. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.cpp +35 -0
  314. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterial.h +57 -0
  315. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.cpp +38 -0
  316. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/PhysicsMaterialSimple.h +37 -0
  317. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/RayCast.h +87 -0
  318. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.cpp +318 -0
  319. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/BoxShape.h +115 -0
  320. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.cpp +438 -0
  321. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CapsuleShape.h +129 -0
  322. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.cpp +433 -0
  323. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShape.h +354 -0
  324. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CompoundShapeVisitors.h +461 -0
  325. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.cpp +1311 -0
  326. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexHullShape.h +202 -0
  327. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.cpp +566 -0
  328. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ConvexShape.h +150 -0
  329. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.cpp +418 -0
  330. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/CylinderShape.h +126 -0
  331. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.cpp +87 -0
  332. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/DecoratedShape.h +80 -0
  333. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.cpp +64 -0
  334. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/EmptyShape.h +75 -0
  335. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/GetTrianglesContext.h +248 -0
  336. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.cpp +2754 -0
  337. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/HeightFieldShape.h +380 -0
  338. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.cpp +1305 -0
  339. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MeshShape.h +228 -0
  340. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.cpp +596 -0
  341. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/MutableCompoundShape.h +176 -0
  342. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.cpp +217 -0
  343. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h +140 -0
  344. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.cpp +541 -0
  345. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PlaneShape.h +147 -0
  346. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/PolyhedronSubmergedVolumeCalculator.h +319 -0
  347. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp +333 -0
  348. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h +161 -0
  349. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaleHelpers.h +83 -0
  350. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.cpp +238 -0
  351. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/ScaledShape.h +145 -0
  352. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.cpp +325 -0
  353. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/Shape.h +466 -0
  354. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.cpp +347 -0
  355. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SphereShape.h +125 -0
  356. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.cpp +674 -0
  357. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/StaticCompoundShape.h +139 -0
  358. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeID.h +138 -0
  359. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/SubShapeIDPair.h +65 -0
  360. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.cpp +453 -0
  361. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.gliffy +1 -0
  362. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h +135 -0
  363. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.cpp +691 -0
  364. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TaperedCylinderShape.h +132 -0
  365. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.cpp +430 -0
  366. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/Shape/TriangleShape.h +143 -0
  367. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeCast.h +173 -0
  368. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/ShapeFilter.h +73 -0
  369. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilter.h +40 -0
  370. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SimShapeFilterWrapper.h +58 -0
  371. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/SortReverseAndStore.h +48 -0
  372. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.cpp +180 -0
  373. package/native/third_party/JoltPhysics/Jolt/Physics/Collision/TransformedShape.h +194 -0
  374. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/CalculateSolverSteps.h +70 -0
  375. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.cpp +246 -0
  376. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConeConstraint.h +133 -0
  377. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.cpp +73 -0
  378. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/Constraint.h +243 -0
  379. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.cpp +289 -0
  380. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintManager.h +100 -0
  381. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AngleConstraintPart.h +257 -0
  382. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h +682 -0
  383. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h +276 -0
  384. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/GearConstraintPart.h +195 -0
  385. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h +222 -0
  386. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/IndependentAxisConstraintPart.h +246 -0
  387. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/PointConstraintPart.h +239 -0
  388. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RackAndPinionConstraintPart.h +196 -0
  389. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h +283 -0
  390. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/RotationQuatConstraintPart.h +246 -0
  391. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SpringPart.h +169 -0
  392. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h +597 -0
  393. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.cpp +1804 -0
  394. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/ContactConstraintManager.h +524 -0
  395. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.cpp +266 -0
  396. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/DistanceConstraint.h +120 -0
  397. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.cpp +215 -0
  398. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/FixedConstraint.h +96 -0
  399. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.cpp +188 -0
  400. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/GearConstraint.h +116 -0
  401. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.cpp +443 -0
  402. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/HingeConstraint.h +205 -0
  403. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.cpp +43 -0
  404. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/MotorSettings.h +66 -0
  405. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.cpp +458 -0
  406. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraint.h +191 -0
  407. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.cpp +85 -0
  408. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPath.h +76 -0
  409. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.cpp +308 -0
  410. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PathConstraintPathHermite.h +54 -0
  411. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.cpp +157 -0
  412. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PointConstraint.h +94 -0
  413. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.cpp +253 -0
  414. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/PulleyConstraint.h +137 -0
  415. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.cpp +189 -0
  416. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/RackAndPinionConstraint.h +118 -0
  417. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.cpp +900 -0
  418. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SixDOFConstraint.h +289 -0
  419. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.cpp +501 -0
  420. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SliderConstraint.h +198 -0
  421. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.cpp +35 -0
  422. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SpringSettings.h +70 -0
  423. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.cpp +524 -0
  424. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/SwingTwistConstraint.h +197 -0
  425. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.cpp +56 -0
  426. package/native/third_party/JoltPhysics/Jolt/Physics/Constraints/TwoBodyConstraint.h +65 -0
  427. package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.cpp +17 -0
  428. package/native/third_party/JoltPhysics/Jolt/Physics/DeterminismLog.h +159 -0
  429. package/native/third_party/JoltPhysics/Jolt/Physics/EActivation.h +16 -0
  430. package/native/third_party/JoltPhysics/Jolt/Physics/EPhysicsUpdateError.h +37 -0
  431. package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.cpp +492 -0
  432. package/native/third_party/JoltPhysics/Jolt/Physics/IslandBuilder.h +144 -0
  433. package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.cpp +582 -0
  434. package/native/third_party/JoltPhysics/Jolt/Physics/LargeIslandSplitter.h +187 -0
  435. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsLock.h +169 -0
  436. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.cpp +261 -0
  437. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsScene.h +104 -0
  438. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSettings.h +125 -0
  439. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsStepListener.h +37 -0
  440. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.cpp +2915 -0
  441. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsSystem.h +391 -0
  442. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.cpp +25 -0
  443. package/native/third_party/JoltPhysics/Jolt/Physics/PhysicsUpdateContext.h +176 -0
  444. package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.cpp +744 -0
  445. package/native/third_party/JoltPhysics/Jolt/Physics/Ragdoll/Ragdoll.h +245 -0
  446. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyContactListener.h +55 -0
  447. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.cpp +128 -0
  448. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyCreationSettings.h +75 -0
  449. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyManifold.h +74 -0
  450. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.cpp +1501 -0
  451. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyMotionProperties.h +333 -0
  452. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.cpp +354 -0
  453. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyShape.h +73 -0
  454. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.cpp +1487 -0
  455. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h +390 -0
  456. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyUpdateContext.h +63 -0
  457. package/native/third_party/JoltPhysics/Jolt/Physics/SoftBody/SoftBodyVertex.h +36 -0
  458. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorder.h +136 -0
  459. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.cpp +90 -0
  460. package/native/third_party/JoltPhysics/Jolt/Physics/StateRecorderImpl.h +50 -0
  461. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.cpp +306 -0
  462. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/MotorcycleController.h +119 -0
  463. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.cpp +547 -0
  464. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/TrackedVehicleController.h +169 -0
  465. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.cpp +33 -0
  466. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleAntiRollBar.h +33 -0
  467. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.cpp +376 -0
  468. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleCollisionTester.h +146 -0
  469. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.cpp +703 -0
  470. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleConstraint.h +252 -0
  471. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.cpp +17 -0
  472. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleController.h +87 -0
  473. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.cpp +81 -0
  474. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleDifferential.h +39 -0
  475. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.cpp +122 -0
  476. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleEngine.h +93 -0
  477. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.cpp +52 -0
  478. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTrack.h +56 -0
  479. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.cpp +159 -0
  480. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/VehicleTransmission.h +87 -0
  481. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.cpp +93 -0
  482. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/Wheel.h +148 -0
  483. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.cpp +866 -0
  484. package/native/third_party/JoltPhysics/Jolt/Physics/Vehicle/WheeledVehicleController.h +205 -0
  485. package/native/third_party/JoltPhysics/Jolt/RegisterTypes.cpp +204 -0
  486. package/native/third_party/JoltPhysics/Jolt/RegisterTypes.h +29 -0
  487. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.cpp +1107 -0
  488. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRenderer.h +383 -0
  489. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.cpp +168 -0
  490. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererPlayback.h +48 -0
  491. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.cpp +158 -0
  492. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererRecorder.h +130 -0
  493. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.cpp +80 -0
  494. package/native/third_party/JoltPhysics/Jolt/Renderer/DebugRendererSimple.h +88 -0
  495. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.cpp +165 -0
  496. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletalAnimation.h +91 -0
  497. package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.cpp +82 -0
  498. package/native/third_party/JoltPhysics/Jolt/Skeleton/Skeleton.h +72 -0
  499. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.cpp +237 -0
  500. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonMapper.h +145 -0
  501. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.cpp +87 -0
  502. package/native/third_party/JoltPhysics/Jolt/Skeleton/SkeletonPose.h +82 -0
  503. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.cpp +73 -0
  504. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitter.h +84 -0
  505. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.cpp +139 -0
  506. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterBinning.h +52 -0
  507. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.cpp +43 -0
  508. package/native/third_party/JoltPhysics/Jolt/TriangleSplitter/TriangleSplitterMean.h +28 -0
  509. package/native/third_party/JoltPhysics/LICENSE +7 -0
  510. package/native/third_party/JoltPhysics/README.md +173 -0
  511. package/native/third_party/bloom_jolt/CMakeLists.txt +78 -0
  512. package/native/third_party/bloom_jolt/include/bloom_jolt.h +519 -0
  513. package/native/third_party/bloom_jolt/src/bloom_jolt.cpp +1780 -0
  514. package/native/tvos/Cargo.lock +1692 -0
  515. package/native/tvos/Cargo.toml +22 -0
  516. package/native/tvos/src/lib.rs +3179 -0
  517. package/native/watchos/Cargo.lock +16 -0
  518. package/native/watchos/Cargo.toml +19 -0
  519. package/native/watchos/shaders/bloom_postfx.metal +99 -0
  520. package/native/watchos/src/BloomWatchApp.swift +1236 -0
  521. package/native/watchos/src/BloomWatchAudio.swift +179 -0
  522. package/native/watchos/src/audio.rs +55 -0
  523. package/native/watchos/src/draw_list.rs +223 -0
  524. package/native/watchos/src/ffi_stubs.rs +454 -0
  525. package/native/watchos/src/lib.rs +1013 -0
  526. package/native/watchos/src/models.rs +746 -0
  527. package/native/watchos/src/postfx.rs +91 -0
  528. package/native/watchos/src/scene.rs +534 -0
  529. package/native/watchos/src/textures.rs +184 -0
  530. package/native/web/Cargo.lock +1656 -0
  531. package/native/web/Cargo.toml +38 -0
  532. package/native/web/bloom_glue.js +218 -0
  533. package/native/web/build.sh +101 -0
  534. package/native/web/index.html +390 -0
  535. package/native/web/jolt_bridge.js +1311 -0
  536. package/native/web/src/lib.rs +2739 -0
  537. package/native/windows/Cargo.lock +1813 -0
  538. package/native/windows/Cargo.toml +31 -0
  539. package/native/windows/src/lib.rs +1933 -0
  540. package/package.json +558 -0
  541. package/src/audio/index.ts +151 -0
  542. package/src/core/colors.ts +56 -0
  543. package/src/core/index.ts +903 -0
  544. package/src/core/keys.ts +63 -0
  545. package/src/core/types.ts +102 -0
  546. package/src/index.ts +158 -0
  547. package/src/math/index.ts +502 -0
  548. package/src/mobile/index.ts +294 -0
  549. package/src/models/index.ts +859 -0
  550. package/src/physics/index.ts +1072 -0
  551. package/src/scene/index.ts +570 -0
  552. package/src/shapes/index.ts +120 -0
  553. package/src/text/index.ts +48 -0
  554. package/src/textures/index.ts +173 -0
  555. package/src/world/index.ts +22 -0
  556. package/src/world/loader.ts +385 -0
  557. package/src/world/prefab.ts +205 -0
  558. package/src/world/saver.ts +61 -0
  559. package/src/world/terrain.ts +254 -0
  560. package/src/world/types.ts +136 -0
  561. package/src/world/validate.ts +202 -0
  562. package/src/world/version.ts +47 -0
@@ -0,0 +1,1066 @@
1
+ //! Retained scene graph for Bloom Engine.
2
+ //!
3
+ //! Unlike immediate-mode drawing (drawCube, drawModel), the scene graph holds
4
+ //! persistent meshes that survive across frames. Systems update geometry and
5
+ //! transforms; the renderer draws all visible nodes each frame automatically.
6
+
7
+ use wgpu::util::DeviceExt;
8
+ use crate::handles::HandleRegistry;
9
+ use crate::renderer::Vertex3D;
10
+
11
+ // ============================================================
12
+ // PBR Material
13
+ // ============================================================
14
+
15
+ #[derive(Clone, Debug)]
16
+ pub struct PbrMaterial {
17
+ pub color: [f32; 3],
18
+ pub roughness: f32,
19
+ pub metalness: f32,
20
+ pub opacity: f32,
21
+ pub emissive: [f32; 3],
22
+ pub double_sided: bool,
23
+ pub texture_idx: u32,
24
+ /// Normal-map texture. 0 means "no normal map" — scene shader falls
25
+ /// back to the geometric normal. Stored as a texture index rather
26
+ /// than bind group so the renderer can build per-material bind
27
+ /// groups lazily without SceneGraph holding GPU references.
28
+ pub normal_texture_idx: u32,
29
+ pub metallic_roughness_texture_idx: u32,
30
+ pub emissive_texture_idx: u32,
31
+ pub occlusion_texture_idx: u32,
32
+ }
33
+
34
+ impl Default for PbrMaterial {
35
+ fn default() -> Self {
36
+ Self {
37
+ color: [1.0, 1.0, 1.0],
38
+ roughness: 0.8,
39
+ metalness: 0.0,
40
+ opacity: 1.0,
41
+ emissive: [0.0, 0.0, 0.0],
42
+ double_sided: false,
43
+ texture_idx: 0,
44
+ normal_texture_idx: 0,
45
+ metallic_roughness_texture_idx: 0,
46
+ emissive_texture_idx: 0,
47
+ occlusion_texture_idx: 0,
48
+ }
49
+ }
50
+ }
51
+
52
+ // ============================================================
53
+ // Scene Node Uniforms (matches Uniforms3D in renderer)
54
+ // ============================================================
55
+
56
+ #[repr(C)]
57
+ #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
58
+ struct NodeUniforms {
59
+ mvp: [[f32; 4]; 4],
60
+ model: [[f32; 4]; 4],
61
+ prev_mvp: [[f32; 4]; 4],
62
+ model_tint: [f32; 4],
63
+ }
64
+
65
+ // ============================================================
66
+ // Scene Node
67
+ // ============================================================
68
+
69
+ pub struct SceneNode {
70
+ // Geometry (CPU-side, updated by systems)
71
+ pub vertices: Vec<Vertex3D>,
72
+ pub indices: Vec<u32>,
73
+ // Material
74
+ pub material: PbrMaterial,
75
+ // Transform
76
+ pub transform: [[f32; 4]; 4],
77
+ /// Previous frame's world transform — used to compute per-mesh
78
+ /// screen-space velocity for motion blur and TAA reprojection.
79
+ pub prev_transform: [[f32; 4]; 4],
80
+ // Flags
81
+ pub visible: bool,
82
+ pub cast_shadow: bool,
83
+ pub receive_shadow: bool,
84
+ pub parent: f64,
85
+ // Editor user data — an arbitrary i64 attached to the node. The editor
86
+ // uses this to store the entity id directly on the scene node so picking
87
+ // can return the entity id without a handle → id map lookup (Q7).
88
+ pub user_data: i64,
89
+ // Cached world-space AABB, recomputed when geometry changes (Q5).
90
+ pub bounds_min: [f32; 3],
91
+ pub bounds_max: [f32; 3],
92
+ /// World-space AABB cached each frame by `prepare()` — the result of
93
+ /// transforming the local `bounds_min`/`bounds_max` box by the node
94
+ /// transform. Consumed by the shadow pass for per-cascade frustum
95
+ /// culling so it doesn't repeat the 8-corner transform. Sentinel
96
+ /// `world_bounds_min[0] > world_bounds_max[0]` means "not yet valid"
97
+ /// (node never passed through `prepare()`, or local bounds empty).
98
+ pub world_bounds_min: [f32; 3],
99
+ pub world_bounds_max: [f32; 3],
100
+ // GPU resources (lazily created)
101
+ pub gpu_vb: Option<wgpu::Buffer>,
102
+ pub gpu_ib: Option<wgpu::Buffer>,
103
+ pub gpu_index_count: u32,
104
+ /// Vertex count, cached at VB upload so the ray-tracing BLAS build
105
+ /// can reference it without re-reading the full `vertices` Vec.
106
+ pub gpu_vertex_count: u32,
107
+ /// Ticket 007b — bottom-level acceleration structure built at the
108
+ /// same geo_dirty flush that creates `gpu_vb`/`gpu_ib`. `None` on
109
+ /// non-RT adapters or until the first upload. Build is scheduled
110
+ /// by `prepare()`, committed to the GPU by the renderer's main
111
+ /// encoder in `build_acceleration_structures`.
112
+ pub blas: Option<wgpu::Blas>,
113
+ /// Ticket 013 — first of 6 consecutive card-atlas slots assigned
114
+ /// at BLAS creation. Slots are laid out per axis:
115
+ /// first_slot + 0 → +X, +1 → -X, +2 → +Y,
116
+ /// +3 → -Y, +4 → +Z, +5 → -Z.
117
+ /// `None` until the capture pass has allocated the run.
118
+ pub card_first_slot: Option<u32>,
119
+ /// Ticket 013 V3 — when true, the mesh is re-queued into
120
+ /// `pending_card_captures` every frame so the card atlas stays
121
+ /// in sync with animated geometry. Off by default — static meshes
122
+ /// pay the capture cost once and never again.
123
+ pub card_dynamic: bool,
124
+ /// Ticket 014 — per-mesh unsigned distance field baked by a
125
+ /// compute pass at geo-upload time. 3D R16Float texture, fixed
126
+ /// resolution (`MESH_SDF_RES`³). Used later by the SW probe
127
+ /// trace for sphere-marching when the adapter lacks HW RT.
128
+ /// `None` on non-RT-capable adapters or until the bake lands.
129
+ pub mesh_sdf: Option<wgpu::Texture>,
130
+ pub mesh_sdf_view: Option<wgpu::TextureView>,
131
+ /// Content hash of (positions, indices) computed at upload time.
132
+ /// Set whenever `mesh_sdf` exists; the renderer reads it back when
133
+ /// flushing cache writes after a fresh bake. `None` until the
134
+ /// first geo upload — and on non-RT-capable adapters that never
135
+ /// allocate a per-mesh SDF.
136
+ pub mesh_hash: Option<crate::sdf_cache::MeshHash>,
137
+ /// Flat mesh-average world-space normal, cached on BLAS build so
138
+ /// the per-instance GI data buffer can be populated without
139
+ /// re-reading the vertex array. Rough heuristic — for walls and
140
+ /// floors this tracks the surface closely; for radially-symmetric
141
+ /// meshes (columns) it averages to near-zero and the trace falls
142
+ /// back to a fixed up-vector. Phase-2 Mesh Cards (ticket 013)
143
+ /// upgrades this to textured per-hit normals.
144
+ pub flat_normal_ws: [f32; 3],
145
+ /// Mean world-space albedo cached alongside `flat_normal_ws`.
146
+ /// For the hit-lighting-lite path in 007b HW trace.
147
+ pub flat_albedo: [f32; 3],
148
+ /// Index into the scene-graph's shared node-uniform pool. `None`
149
+ /// until this node's first `prepare()` assigns a slot. Cleared when
150
+ /// the pool reallocates so the next prepare re-assigns + rebuilds
151
+ /// `gpu_uniform_bg`.
152
+ uniform_slot: Option<u32>,
153
+ gpu_uniform_bg: Option<wgpu::BindGroup>,
154
+ /// Transient: set by `prepare()` based on the camera frustum, read
155
+ /// by `render()` to skip off-screen nodes. Shadow pass ignores this
156
+ /// flag — off-screen geometry can still cast shadows into view.
157
+ in_view_frustum: bool,
158
+ /// Material bind group for the scene pipeline — holds base color,
159
+ /// normal, metallic-roughness and emissive texture views in one
160
+ /// group. Rebuilt whenever one of the material texture indices
161
+ /// changes (tracked via `mat_dirty`).
162
+ pub gpu_material_bg: Option<wgpu::BindGroup>,
163
+ pub gpu_material_uniform_buf: Option<wgpu::Buffer>,
164
+ pub mat_dirty: bool,
165
+ geo_dirty: bool,
166
+ }
167
+
168
+ impl SceneNode {
169
+ fn new() -> Self {
170
+ Self {
171
+ vertices: Vec::new(),
172
+ indices: Vec::new(),
173
+ material: PbrMaterial::default(),
174
+ transform: crate::renderer::IDENTITY_MAT4,
175
+ prev_transform: crate::renderer::IDENTITY_MAT4,
176
+ visible: true,
177
+ cast_shadow: true,
178
+ receive_shadow: true,
179
+ parent: 0.0,
180
+ user_data: 0,
181
+ bounds_min: [0.0; 3],
182
+ bounds_max: [0.0; 3],
183
+ world_bounds_min: [f32::MAX; 3],
184
+ world_bounds_max: [f32::MIN; 3],
185
+ gpu_vb: None,
186
+ gpu_ib: None,
187
+ gpu_index_count: 0,
188
+ gpu_vertex_count: 0,
189
+ blas: None,
190
+ card_first_slot: None,
191
+ card_dynamic: false,
192
+ mesh_sdf: None,
193
+ mesh_sdf_view: None,
194
+ mesh_hash: None,
195
+ flat_normal_ws: [0.0, 1.0, 0.0],
196
+ flat_albedo: [1.0, 1.0, 1.0],
197
+ uniform_slot: None,
198
+ gpu_uniform_bg: None,
199
+ in_view_frustum: true,
200
+ gpu_material_bg: None,
201
+ gpu_material_uniform_buf: None,
202
+ mat_dirty: true,
203
+ geo_dirty: true,
204
+ }
205
+ }
206
+ }
207
+
208
+ // ============================================================
209
+ // Scene Graph
210
+ // ============================================================
211
+
212
+ /// Stride between per-node uniform slots in the shared pool buffer.
213
+ /// Must be >= sizeof(NodeUniforms) (208B) and a multiple of the device's
214
+ /// `min_uniform_buffer_offset_alignment`. 256 is safe on every platform.
215
+ const NODE_UNIFORM_STRIDE: u64 = 256;
216
+
217
+ pub struct SceneGraph {
218
+ pub nodes: HandleRegistry<SceneNode>,
219
+ /// Shared uniform buffer holding one 256B slot per scene node. All
220
+ /// per-node uniforms get written to this buffer in a single
221
+ /// `queue.write_buffer` call per frame, replacing what used to be
222
+ /// one write per node. Grows on demand; bind groups referencing
223
+ /// the old buffer get invalidated when that happens.
224
+ uniform_pool: Option<wgpu::Buffer>,
225
+ uniform_pool_capacity: u32,
226
+ /// Next free slot index. Slots are never released — they only grow
227
+ /// with the high-water-mark node count. Sufficient for the current
228
+ /// workload (scenes with < 10k retained nodes).
229
+ next_slot: u32,
230
+ /// Scratch buffer reused across frames for building the packed
231
+ /// uniform payload. Sized to `uniform_pool_capacity * STRIDE`.
232
+ scratch: Vec<u8>,
233
+ /// Monotonic counter bumped whenever a change lands that affects
234
+ /// what gets drawn into the directional shadow map — transform,
235
+ /// cast_shadow toggle, visibility (of a caster), geometry update,
236
+ /// or destruction of a visible caster. The renderer's shadow-map
237
+ /// cache compares this against its last-rendered version to decide
238
+ /// if it can reuse the cached cascades. Writes that can't affect
239
+ /// shadows (materials, user_data, etc.) deliberately don't bump it.
240
+ pub shadow_version: u64,
241
+
242
+ /// Ticket 007b — true when the host renderer's device was created
243
+ /// with `Features::EXPERIMENTAL_RAY_QUERY`. Controls whether the
244
+ /// scene bakes `BLAS_INPUT` buffer usage + a per-node BLAS at
245
+ /// `prepare()` time. Off on non-RT adapters (web, most Android,
246
+ /// Intel integrated GPUs) so the cost is never paid there.
247
+ pub hw_rt_enabled: bool,
248
+ /// Monotonic counter bumped when any change that would require a
249
+ /// TLAS rebuild lands — geometry upload, transform, visibility
250
+ /// toggle, node add/destroy. The renderer compares against its
251
+ /// cached `tlas_built_version` and rebuilds TLAS + instance-data
252
+ /// buffer when they differ. Mirror of `shadow_version`'s pattern.
253
+ pub tlas_version: u64,
254
+ /// Node handles whose BLAS was (re)created this frame and has not
255
+ /// been built yet. `prepare()` pushes entries; the renderer drains
256
+ /// this list and submits the builds in its main frame encoder via
257
+ /// `CommandEncoder::build_acceleration_structures`.
258
+ pub pending_blas_builds: Vec<f64>,
259
+ /// Ticket 013 — node handles waiting for their mesh card to be
260
+ /// rasterised into the shared atlas. Renderer drains this list
261
+ /// at frame start (via a dedicated capture pass) before the
262
+ /// probe chain runs. Populated alongside BLAS creation so each
263
+ /// new mesh gets exactly one card.
264
+ pub pending_card_captures: Vec<f64>,
265
+ /// Bump allocator for card-atlas slots. Grows monotonically
266
+ /// across the lifetime of the scene — free'd slots aren't
267
+ /// reclaimed in V1 (Sponza fits comfortably in 1024 slots; loop
268
+ /// back when scenes start exceeding capacity).
269
+ pub next_card_slot: u32,
270
+ /// Ticket 014 — node handles whose per-mesh SDF still needs to
271
+ /// be baked. Populated alongside BLAS creation; renderer drains
272
+ /// in a per-frame budget via a compute pass. Static meshes
273
+ /// never re-bake once their SDF lands.
274
+ pub pending_sdf_bakes: Vec<f64>,
275
+ }
276
+
277
+ impl SceneGraph {
278
+ pub fn new() -> Self {
279
+ Self {
280
+ nodes: HandleRegistry::new(),
281
+ uniform_pool: None,
282
+ uniform_pool_capacity: 0,
283
+ next_slot: 0,
284
+ scratch: Vec::new(),
285
+ // Start at 1 so the shadow-cache's initial 0 always differs
286
+ // on the first frame and forces an initial render.
287
+ shadow_version: 1,
288
+ hw_rt_enabled: false,
289
+ tlas_version: 1,
290
+ pending_blas_builds: Vec::new(),
291
+ pending_card_captures: Vec::new(),
292
+ next_card_slot: 0,
293
+ pending_sdf_bakes: Vec::new(),
294
+ }
295
+ }
296
+
297
+ pub fn create_node(&mut self) -> f64 {
298
+ // New nodes default to `cast_shadow = true`, so the first
299
+ // `set_transform` + `update_geometry` will dirty shadows
300
+ // anyway. Bumping here too costs nothing and keeps the
301
+ // invalidation story simple.
302
+ self.shadow_version = self.shadow_version.wrapping_add(1);
303
+ self.tlas_version = self.tlas_version.wrapping_add(1);
304
+ self.nodes.alloc(SceneNode::new())
305
+ }
306
+
307
+ pub fn destroy_node(&mut self, handle: f64) {
308
+ if let Some(node) = self.nodes.get(handle) {
309
+ if node.visible && node.cast_shadow {
310
+ self.shadow_version = self.shadow_version.wrapping_add(1);
311
+ }
312
+ if node.visible {
313
+ self.tlas_version = self.tlas_version.wrapping_add(1);
314
+ }
315
+ }
316
+ self.nodes.free(handle);
317
+ }
318
+
319
+ pub fn set_transform(&mut self, handle: f64, matrix: [[f32; 4]; 4]) {
320
+ if let Some(node) = self.nodes.get_mut(handle) {
321
+ // Only dirty shadows when the transform actually changed on
322
+ // a shadow-casting node. Skeletal animation leaves the node
323
+ // transform untouched (joints drive the mesh), so static
324
+ // scenes with animated characters still cache well.
325
+ let changed = node.transform != matrix;
326
+ if changed && node.cast_shadow && node.visible {
327
+ self.shadow_version = self.shadow_version.wrapping_add(1);
328
+ }
329
+ if changed && node.visible {
330
+ self.tlas_version = self.tlas_version.wrapping_add(1);
331
+ }
332
+ node.transform = matrix;
333
+ }
334
+ }
335
+
336
+ pub fn set_visible(&mut self, handle: f64, visible: bool) {
337
+ if let Some(node) = self.nodes.get_mut(handle) {
338
+ if node.visible != visible {
339
+ self.tlas_version = self.tlas_version.wrapping_add(1);
340
+ }
341
+ if node.cast_shadow && node.visible != visible {
342
+ self.shadow_version = self.shadow_version.wrapping_add(1);
343
+ }
344
+ node.visible = visible;
345
+ }
346
+ }
347
+
348
+ pub fn set_cast_shadow(&mut self, handle: f64, cast: bool) {
349
+ if let Some(node) = self.nodes.get_mut(handle) {
350
+ if node.visible && node.cast_shadow != cast {
351
+ self.shadow_version = self.shadow_version.wrapping_add(1);
352
+ }
353
+ node.cast_shadow = cast;
354
+ }
355
+ }
356
+
357
+ pub fn set_receive_shadow(&mut self, handle: f64, receive: bool) {
358
+ if let Some(node) = self.nodes.get_mut(handle) {
359
+ node.receive_shadow = receive;
360
+ }
361
+ }
362
+
363
+ /// Ticket 013 V3 — mark a mesh as dynamic so its card atlas slots
364
+ /// get re-captured every frame. Off by default; call once per
365
+ /// skeletal / morph-target / procedurally-animated node so its
366
+ /// indirect-bounce contribution tracks the animation.
367
+ pub fn set_mesh_dynamic(&mut self, handle: f64, dynamic: bool) {
368
+ if let Some(node) = self.nodes.get_mut(handle) {
369
+ node.card_dynamic = dynamic;
370
+ }
371
+ }
372
+
373
+ /// Ticket 014 V2 — gather every visible mesh's triangles into a
374
+ /// single world-space buffer so the scene-wide SDF clipmap bake
375
+ /// can treat them as one big mesh. Vertex layout matches the
376
+ /// shader's hard-coded 12-f32 Vertex3D stride; only position is
377
+ /// meaningful for the UDF (normals/colour/UV are left zero).
378
+ /// Returns (vertex_buf, index_buf, total_triangle_count).
379
+ pub fn build_world_triangles(&self) -> (Vec<f32>, Vec<u32>, u32) {
380
+ // 12 floats per vertex to match `Vertex3D` stride the bake
381
+ // shader indexes with. position + zero-padding.
382
+ const STRIDE: usize = 12;
383
+ let mut vbuf: Vec<f32> = Vec::new();
384
+ let mut ibuf: Vec<u32> = Vec::new();
385
+ let mut tri_count: u32 = 0;
386
+ for (_, node) in self.nodes.iter() {
387
+ if !node.visible || node.vertices.is_empty() || node.indices.is_empty() {
388
+ continue;
389
+ }
390
+ let base = (vbuf.len() / STRIDE) as u32;
391
+ let t = &node.transform;
392
+ for v in &node.vertices {
393
+ let px = v.position[0];
394
+ let py = v.position[1];
395
+ let pz = v.position[2];
396
+ let wx = t[0][0]*px + t[1][0]*py + t[2][0]*pz + t[3][0];
397
+ let wy = t[0][1]*px + t[1][1]*py + t[2][1]*pz + t[3][1];
398
+ let wz = t[0][2]*px + t[1][2]*py + t[2][2]*pz + t[3][2];
399
+ // Zero-pad the remaining 9 floats — only position is
400
+ // read by `SDF_BAKE_WGSL`.
401
+ vbuf.extend_from_slice(&[wx, wy, wz, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
402
+ }
403
+ for &idx in &node.indices {
404
+ ibuf.push(base + idx);
405
+ }
406
+ tri_count += (node.indices.len() / 3) as u32;
407
+ }
408
+ (vbuf, ibuf, tri_count)
409
+ }
410
+
411
+ pub fn set_parent(&mut self, handle: f64, parent: f64) {
412
+ if let Some(node) = self.nodes.get_mut(handle) {
413
+ node.parent = parent;
414
+ }
415
+ }
416
+
417
+ pub fn update_geometry(&mut self, handle: f64, vertices: Vec<Vertex3D>, indices: Vec<u32>) {
418
+ if let Some(node) = self.nodes.get_mut(handle) {
419
+ // Recompute bounds from vertex positions (Q5).
420
+ let mut bmin = [f32::MAX; 3];
421
+ let mut bmax = [f32::MIN; 3];
422
+ for v in &vertices {
423
+ for k in 0..3 {
424
+ if v.position[k] < bmin[k] { bmin[k] = v.position[k]; }
425
+ if v.position[k] > bmax[k] { bmax[k] = v.position[k]; }
426
+ }
427
+ }
428
+ if vertices.is_empty() {
429
+ bmin = [0.0; 3];
430
+ bmax = [0.0; 3];
431
+ }
432
+ node.bounds_min = bmin;
433
+ node.bounds_max = bmax;
434
+ node.vertices = vertices;
435
+ node.indices = indices;
436
+ node.geo_dirty = true;
437
+ if node.cast_shadow && node.visible {
438
+ self.shadow_version = self.shadow_version.wrapping_add(1);
439
+ }
440
+ if node.visible {
441
+ self.tlas_version = self.tlas_version.wrapping_add(1);
442
+ }
443
+ }
444
+ }
445
+
446
+ // ---- Q4: transform read-back -------------------------------------------
447
+
448
+ /// Read back the current 4x4 transform matrix of a scene node.
449
+ pub fn get_transform(&self, handle: f64) -> [[f32; 4]; 4] {
450
+ match self.nodes.get(handle) {
451
+ Some(node) => node.transform,
452
+ None => crate::renderer::IDENTITY_MAT4,
453
+ }
454
+ }
455
+
456
+ // ---- Q5: world-space bounds query --------------------------------------
457
+
458
+ /// Return the cached AABB of a scene node's geometry (local space).
459
+ pub fn get_bounds(&self, handle: f64) -> ([f32; 3], [f32; 3]) {
460
+ match self.nodes.get(handle) {
461
+ Some(node) => (node.bounds_min, node.bounds_max),
462
+ None => ([0.0; 3], [0.0; 3]),
463
+ }
464
+ }
465
+
466
+ /// World-space AABB of every visible, shadow-casting node.
467
+ /// Used to auto-fit the directional shadow ortho volume — no
468
+ /// scene-specific magic numbers, works for Sponza / Bistro /
469
+ /// anything a user loads.
470
+ ///
471
+ /// Returns `None` if the scene is empty (caller should fall back
472
+ /// to a safe default).
473
+ pub fn compute_shadow_bounds(&self) -> Option<([f32; 3], [f32; 3])> {
474
+ let mut bmin = [f32::MAX; 3];
475
+ let mut bmax = [f32::MIN; 3];
476
+ let mut any = false;
477
+ for (_h, node) in self.nodes.iter() {
478
+ if !node.visible || !node.cast_shadow {
479
+ continue;
480
+ }
481
+ if node.bounds_min[0] > node.bounds_max[0] {
482
+ continue; // empty bounds
483
+ }
484
+ // Transform the 8 local-AABB corners by the node's world matrix
485
+ // and union into the running bounds.
486
+ let t = &node.transform;
487
+ for ix in 0..2 {
488
+ for iy in 0..2 {
489
+ for iz in 0..2 {
490
+ let lx = if ix == 0 { node.bounds_min[0] } else { node.bounds_max[0] };
491
+ let ly = if iy == 0 { node.bounds_min[1] } else { node.bounds_max[1] };
492
+ let lz = if iz == 0 { node.bounds_min[2] } else { node.bounds_max[2] };
493
+ // column-major mat4 * vec4(x,y,z,1)
494
+ let wx = t[0][0]*lx + t[1][0]*ly + t[2][0]*lz + t[3][0];
495
+ let wy = t[0][1]*lx + t[1][1]*ly + t[2][1]*lz + t[3][1];
496
+ let wz = t[0][2]*lx + t[1][2]*ly + t[2][2]*lz + t[3][2];
497
+ if wx < bmin[0] { bmin[0] = wx; }
498
+ if wy < bmin[1] { bmin[1] = wy; }
499
+ if wz < bmin[2] { bmin[2] = wz; }
500
+ if wx > bmax[0] { bmax[0] = wx; }
501
+ if wy > bmax[1] { bmax[1] = wy; }
502
+ if wz > bmax[2] { bmax[2] = wz; }
503
+ any = true;
504
+ }
505
+ }
506
+ }
507
+ }
508
+ if any { Some((bmin, bmax)) } else { None }
509
+ }
510
+
511
+ // ---- Q7: user data -----------------------------------------------------
512
+
513
+ pub fn set_user_data(&mut self, handle: f64, data: i64) {
514
+ if let Some(node) = self.nodes.get_mut(handle) {
515
+ node.user_data = data;
516
+ }
517
+ }
518
+
519
+ pub fn get_user_data(&self, handle: f64) -> i64 {
520
+ match self.nodes.get(handle) {
521
+ Some(node) => node.user_data,
522
+ None => 0,
523
+ }
524
+ }
525
+
526
+ pub fn set_material_color(&mut self, handle: f64, r: f32, g: f32, b: f32, a: f32) {
527
+ if let Some(node) = self.nodes.get_mut(handle) {
528
+ node.material.color = [r, g, b];
529
+ node.material.opacity = a;
530
+ }
531
+ }
532
+
533
+ pub fn set_material_pbr(&mut self, handle: f64, roughness: f32, metalness: f32) {
534
+ if let Some(node) = self.nodes.get_mut(handle) {
535
+ node.material.roughness = roughness;
536
+ node.material.metalness = metalness;
537
+ }
538
+ }
539
+
540
+ /// Q8: Set a water-like material on a scene node. The actual animated
541
+ /// wave shader requires a dedicated WGSL pipeline pass (deferred).
542
+ /// For now, this sets a translucent tinted material that approximates water.
543
+ pub fn set_material_water(&mut self, handle: f64, _wave_amp: f32, _wave_speed: f32, r: f32, g: f32, b: f32, a: f32) {
544
+ if let Some(node) = self.nodes.get_mut(handle) {
545
+ node.material.color = [r, g, b];
546
+ node.material.opacity = a;
547
+ node.material.roughness = 0.1;
548
+ node.material.metalness = 0.3;
549
+ }
550
+ }
551
+
552
+ pub fn set_material_texture(&mut self, handle: f64, texture_idx: u32) {
553
+ if let Some(node) = self.nodes.get_mut(handle) {
554
+ node.material.texture_idx = texture_idx;
555
+ node.mat_dirty = true;
556
+ }
557
+ }
558
+
559
+ pub fn set_material_normal_texture(&mut self, handle: f64, texture_idx: u32) {
560
+ if let Some(node) = self.nodes.get_mut(handle) {
561
+ node.material.normal_texture_idx = texture_idx;
562
+ node.mat_dirty = true;
563
+ }
564
+ }
565
+
566
+ pub fn set_material_metallic_roughness_texture(&mut self, handle: f64, texture_idx: u32) {
567
+ if let Some(node) = self.nodes.get_mut(handle) {
568
+ node.material.metallic_roughness_texture_idx = texture_idx;
569
+ node.mat_dirty = true;
570
+ }
571
+ }
572
+
573
+ pub fn set_material_emissive_texture(&mut self, handle: f64, texture_idx: u32) {
574
+ if let Some(node) = self.nodes.get_mut(handle) {
575
+ node.material.emissive_texture_idx = texture_idx;
576
+ node.mat_dirty = true;
577
+ }
578
+ }
579
+
580
+ pub fn set_material_emissive_factor(&mut self, handle: f64, r: f32, g: f32, b: f32) {
581
+ if let Some(node) = self.nodes.get_mut(handle) {
582
+ node.material.emissive = [r, g, b];
583
+ node.mat_dirty = true;
584
+ }
585
+ }
586
+
587
+ /// Prepare GPU resources for all visible nodes. Must be called before render().
588
+ /// Creates/updates vertex buffers, index buffers, and uniform bind groups.
589
+ /// `prev_vp_matrix` is the previous frame's view-projection — used together
590
+ /// with each node's `prev_transform` to compute `prev_mvp` for the velocity
591
+ /// buffer (motion blur + TAA per-object reprojection).
592
+ pub fn prepare(
593
+ &mut self,
594
+ device: &wgpu::Device,
595
+ queue: &wgpu::Queue,
596
+ vp_matrix: &[[f32; 4]; 4],
597
+ prev_vp_matrix: &[[f32; 4]; 4],
598
+ uniform_layout: &wgpu::BindGroupLayout,
599
+ ) {
600
+ let frustum = extract_frustum_planes(vp_matrix);
601
+
602
+ // Phase 1: upload geometry for any freshly-added or dirty nodes,
603
+ // assign uniform slots, and count how many nodes we'll draw.
604
+ // Borrow splits so we can push to `pending_blas_builds` while
605
+ // iterating `nodes` mutably.
606
+ let hw_rt = self.hw_rt_enabled;
607
+ let pending_blas = &mut self.pending_blas_builds;
608
+ let pending_cards = &mut self.pending_card_captures;
609
+ let pending_sdf = &mut self.pending_sdf_bakes;
610
+ let next_card_slot = &mut self.next_card_slot;
611
+ let mut visible_count: u32 = 0;
612
+ for (handle, node) in self.nodes.iter_mut() {
613
+ if !node.visible || node.indices.is_empty() {
614
+ continue;
615
+ }
616
+ // Frustum cull against world-space AABB. Transform the local
617
+ // bounds into world space by applying the node's transform
618
+ // to the 8 corners; use the min/max of the result.
619
+ if node.bounds_min[0] <= node.bounds_max[0] {
620
+ let t = &node.transform;
621
+ let mut wmin = [f32::MAX; 3];
622
+ let mut wmax = [f32::MIN; 3];
623
+ for ix in 0..2 {
624
+ for iy in 0..2 {
625
+ for iz in 0..2 {
626
+ let lx = if ix == 0 { node.bounds_min[0] } else { node.bounds_max[0] };
627
+ let ly = if iy == 0 { node.bounds_min[1] } else { node.bounds_max[1] };
628
+ let lz = if iz == 0 { node.bounds_min[2] } else { node.bounds_max[2] };
629
+ let wx = t[0][0]*lx + t[1][0]*ly + t[2][0]*lz + t[3][0];
630
+ let wy = t[0][1]*lx + t[1][1]*ly + t[2][1]*lz + t[3][1];
631
+ let wz = t[0][2]*lx + t[1][2]*ly + t[2][2]*lz + t[3][2];
632
+ if wx < wmin[0] { wmin[0] = wx; }
633
+ if wy < wmin[1] { wmin[1] = wy; }
634
+ if wz < wmin[2] { wmin[2] = wz; }
635
+ if wx > wmax[0] { wmax[0] = wx; }
636
+ if wy > wmax[1] { wmax[1] = wy; }
637
+ if wz > wmax[2] { wmax[2] = wz; }
638
+ }
639
+ }
640
+ }
641
+ node.in_view_frustum = !aabb_outside_frustum(&frustum, wmin, wmax);
642
+ node.world_bounds_min = wmin;
643
+ node.world_bounds_max = wmax;
644
+ } else {
645
+ // Empty or uninitialized bounds — can't cull, play safe.
646
+ node.in_view_frustum = true;
647
+ node.world_bounds_min = [f32::MAX; 3];
648
+ node.world_bounds_max = [f32::MIN; 3];
649
+ }
650
+ if node.geo_dirty || node.gpu_vb.is_none() {
651
+ // Ticket 007b: widen buffer usage when HW RT is on so
652
+ // the same buffer can back both the raster draw and
653
+ // the BLAS build. Cheap — no measurable cost when RT
654
+ // is off.
655
+ // Ticket 014 V3 — STORAGE is unconditional now so the
656
+ // scene-wide SDF clipmap can be baked on SW-only
657
+ // adapters too (web, older Android, Intel iGPUs). The
658
+ // cost is a buffer-usage-flag bit — no runtime
659
+ // overhead on non-RT adapters that don't read it.
660
+ // BLAS_INPUT stays gated on `hw_rt` since it's wgpu-29
661
+ // ray-tracing-only.
662
+ let vb_usage = if hw_rt {
663
+ wgpu::BufferUsages::VERTEX
664
+ | wgpu::BufferUsages::BLAS_INPUT
665
+ | wgpu::BufferUsages::STORAGE
666
+ } else {
667
+ wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::STORAGE
668
+ };
669
+ let ib_usage = if hw_rt {
670
+ wgpu::BufferUsages::INDEX
671
+ | wgpu::BufferUsages::BLAS_INPUT
672
+ | wgpu::BufferUsages::STORAGE
673
+ } else {
674
+ wgpu::BufferUsages::INDEX | wgpu::BufferUsages::STORAGE
675
+ };
676
+ node.gpu_vb = Some(device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
677
+ label: Some("scene_node_vb"),
678
+ contents: bytemuck::cast_slice(&node.vertices),
679
+ usage: vb_usage,
680
+ }));
681
+ node.gpu_ib = Some(device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
682
+ label: Some("scene_node_ib"),
683
+ contents: bytemuck::cast_slice(&node.indices),
684
+ usage: ib_usage,
685
+ }));
686
+ node.gpu_index_count = node.indices.len() as u32;
687
+ node.gpu_vertex_count = node.vertices.len() as u32;
688
+ node.geo_dirty = false;
689
+
690
+ // Ticket 014 V4 — flat normal/albedo + card-slot
691
+ // allocation now happen regardless of `hw_rt`. The SW
692
+ // SDF sphere-trace's broad-phase hit uses these same
693
+ // per-instance fields to sample the card radiance
694
+ // atlas, so they need to be populated even when no
695
+ // BLAS / TLAS is built. BLAS + per-mesh SDF bake
696
+ // remain hw-rt-gated because only the HW trace reads
697
+ // those (and the per-mesh SDFs are currently dormant).
698
+ if !node.indices.is_empty() {
699
+ let mut n_sum = [0.0_f32; 3];
700
+ for v in &node.vertices {
701
+ n_sum[0] += v.normal[0];
702
+ n_sum[1] += v.normal[1];
703
+ n_sum[2] += v.normal[2];
704
+ }
705
+ let t = &node.transform;
706
+ let nx = t[0][0]*n_sum[0] + t[1][0]*n_sum[1] + t[2][0]*n_sum[2];
707
+ let ny = t[0][1]*n_sum[0] + t[1][1]*n_sum[1] + t[2][1]*n_sum[2];
708
+ let nz = t[0][2]*n_sum[0] + t[1][2]*n_sum[1] + t[2][2]*n_sum[2];
709
+ let len = (nx*nx + ny*ny + nz*nz).sqrt();
710
+ if len > 1e-4 {
711
+ node.flat_normal_ws = [nx / len, ny / len, nz / len];
712
+ } else {
713
+ // Radially symmetric — fall back to world-up.
714
+ node.flat_normal_ws = [0.0, 1.0, 0.0];
715
+ }
716
+ node.flat_albedo = node.material.color;
717
+
718
+ // Ticket 013 V2 — allocate 6 consecutive slots per
719
+ // signed AABB axis and schedule the capture pass.
720
+ // Runs on both HW and SW paths so the SDF trace's
721
+ // broad-phase hit can sample textured radiance.
722
+ if node.card_first_slot.is_none() {
723
+ let first = *next_card_slot;
724
+ *next_card_slot += 6;
725
+ node.card_first_slot = Some(first);
726
+ pending_cards.push(handle);
727
+ }
728
+
729
+ if hw_rt {
730
+ // BLAS creation only on HW-RT adapters.
731
+ let size_desc = wgpu::BlasTriangleGeometrySizeDescriptor {
732
+ vertex_format: wgpu::VertexFormat::Float32x3,
733
+ vertex_count: node.gpu_vertex_count,
734
+ index_format: Some(wgpu::IndexFormat::Uint32),
735
+ index_count: Some(node.gpu_index_count),
736
+ flags: wgpu::AccelerationStructureGeometryFlags::OPAQUE,
737
+ };
738
+ node.blas = Some(device.create_blas(
739
+ &wgpu::CreateBlasDescriptor {
740
+ label: Some("scene_node_blas"),
741
+ flags: wgpu::AccelerationStructureFlags::PREFER_FAST_TRACE,
742
+ update_mode: wgpu::AccelerationStructureUpdateMode::Build,
743
+ },
744
+ wgpu::BlasGeometrySizeDescriptors::Triangles {
745
+ descriptors: vec![size_desc],
746
+ },
747
+ ));
748
+ pending_blas.push(handle);
749
+
750
+ // Per-mesh SDF texture — currently dormant (V4
751
+ // dynamic-scene merge will consume it), but
752
+ // cheap to allocate alongside the BLAS.
753
+ if node.mesh_sdf.is_none()
754
+ && node.bounds_min[0] < node.bounds_max[0]
755
+ && node.bounds_min[1] < node.bounds_max[1]
756
+ && node.bounds_min[2] < node.bounds_max[2]
757
+ {
758
+ let (sdf_tex, sdf_view) = crate::renderer::create_mesh_sdf_texture_public(
759
+ device,
760
+ "scene_node_sdf",
761
+ );
762
+
763
+ // Ticket 022 — content-hash the geometry and
764
+ // try the on-disk SDF cache before scheduling
765
+ // a GPU bake. Vertex layout is interleaved;
766
+ // pull the position prefix out as a
767
+ // [[f32; 3]] slice so the hash only sees
768
+ // geometry-relevant bytes.
769
+ let positions: Vec<[f32; 3]> =
770
+ node.vertices.iter().map(|v| v.position).collect();
771
+ let hash = crate::sdf_cache::compute_mesh_hash(
772
+ &positions, &node.indices,
773
+ );
774
+ node.mesh_hash = Some(hash);
775
+
776
+ if let Some(bytes) = crate::sdf_cache::load(hash) {
777
+ // Cache hit — pad the tightly-packed
778
+ // 128 B/row payload to 256 B/row so it
779
+ // clears wgpu's COPY_BYTES_PER_ROW
780
+ // alignment, then upload directly and
781
+ // skip the bake. Native cache size
782
+ // stays compact (128 KB/mesh on disk);
783
+ // the 128 KB padding allocation is
784
+ // free'd immediately after the call.
785
+ const RES: u32 = crate::sdf_cache::VOXEL_RES;
786
+ let row_tight = (RES * 4) as usize;
787
+ let row_padded = ((row_tight + 255) & !255) as u32;
788
+ let mut padded = vec![
789
+ 0u8;
790
+ (row_padded as usize) * (RES as usize) * (RES as usize)
791
+ ];
792
+ for z in 0..RES as usize {
793
+ for y in 0..RES as usize {
794
+ let src_off = (z * RES as usize + y) * row_tight;
795
+ let dst_off = (z * RES as usize + y) * row_padded as usize;
796
+ padded[dst_off..dst_off + row_tight]
797
+ .copy_from_slice(&bytes[src_off..src_off + row_tight]);
798
+ }
799
+ }
800
+ queue.write_texture(
801
+ wgpu::TexelCopyTextureInfo {
802
+ texture: &sdf_tex,
803
+ mip_level: 0,
804
+ origin: wgpu::Origin3d::ZERO,
805
+ aspect: wgpu::TextureAspect::All,
806
+ },
807
+ &padded,
808
+ wgpu::TexelCopyBufferLayout {
809
+ offset: 0,
810
+ bytes_per_row: Some(row_padded),
811
+ rows_per_image: Some(RES),
812
+ },
813
+ wgpu::Extent3d {
814
+ width: RES,
815
+ height: RES,
816
+ depth_or_array_layers: RES,
817
+ },
818
+ );
819
+ } else {
820
+ pending_sdf.push(handle);
821
+ }
822
+
823
+ node.mesh_sdf = Some(sdf_tex);
824
+ node.mesh_sdf_view = Some(sdf_view);
825
+ }
826
+ }
827
+ }
828
+ }
829
+ if node.uniform_slot.is_none() {
830
+ node.uniform_slot = Some(self.next_slot);
831
+ self.next_slot += 1;
832
+ }
833
+
834
+ // Ticket 013 V3 — re-queue dynamic meshes every frame so
835
+ // their card atlas slots get re-captured to track
836
+ // animated geometry. Static meshes (default) stay out of
837
+ // the queue after their one-shot first-frame capture.
838
+ if node.card_dynamic && node.card_first_slot.is_some() {
839
+ pending_cards.push(handle);
840
+ }
841
+
842
+ visible_count += 1;
843
+ }
844
+
845
+ // Phase 2: ensure pool is large enough. Grow with 2x + padding
846
+ // so this branch is rare once the scene has stabilized.
847
+ let needed_capacity = self.next_slot.max(32);
848
+ if needed_capacity > self.uniform_pool_capacity {
849
+ let new_cap = needed_capacity.next_power_of_two().max(64);
850
+ let byte_size = (new_cap as u64) * NODE_UNIFORM_STRIDE;
851
+ self.uniform_pool = Some(device.create_buffer(&wgpu::BufferDescriptor {
852
+ label: Some("scene_node_uniform_pool"),
853
+ size: byte_size,
854
+ usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
855
+ mapped_at_creation: false,
856
+ }));
857
+ self.uniform_pool_capacity = new_cap;
858
+ self.scratch.resize(byte_size as usize, 0);
859
+ // Invalidate every per-node bind group — they reference
860
+ // the old buffer.
861
+ for (_handle, node) in self.nodes.iter_mut() {
862
+ node.gpu_uniform_bg = None;
863
+ }
864
+ }
865
+
866
+ let Some(pool_buf) = self.uniform_pool.as_ref() else { return };
867
+ let uniform_size = std::mem::size_of::<NodeUniforms>();
868
+ let stride = NODE_UNIFORM_STRIDE as usize;
869
+
870
+ // Phase 3: build the packed payload + create any missing bind
871
+ // groups. Bind-group creation is rare (only on first sight of
872
+ // a slot or after pool grow); the hot per-frame path is just
873
+ // the memcpy into scratch.
874
+ let mut max_byte_offset: usize = 0;
875
+ for (_handle, node) in self.nodes.iter_mut() {
876
+ if !node.visible || node.indices.is_empty() {
877
+ continue;
878
+ }
879
+ let Some(slot) = node.uniform_slot else { continue };
880
+
881
+ let mvp = mat4_mul(vp_matrix, &node.transform);
882
+ let prev_mvp = mat4_mul(prev_vp_matrix, &node.prev_transform);
883
+ // Guard against NaN/Inf opacity (Perry TS passes NaN
884
+ // when a default-arg alpha isn't provided) — a single
885
+ // NaN in model_tint.w propagates through every shader
886
+ // output.
887
+ let opacity = if node.material.opacity.is_finite() {
888
+ node.material.opacity
889
+ } else {
890
+ 1.0
891
+ };
892
+ let tint = [
893
+ node.material.color[0],
894
+ node.material.color[1],
895
+ node.material.color[2],
896
+ opacity,
897
+ ];
898
+ let uniforms = NodeUniforms { mvp, model: node.transform, prev_mvp, model_tint: tint };
899
+ node.prev_transform = node.transform;
900
+
901
+ let off = (slot as usize) * stride;
902
+ self.scratch[off..off + uniform_size].copy_from_slice(bytemuck::bytes_of(&uniforms));
903
+ max_byte_offset = max_byte_offset.max(off + stride);
904
+
905
+ if node.gpu_uniform_bg.is_none() {
906
+ node.gpu_uniform_bg = Some(device.create_bind_group(&wgpu::BindGroupDescriptor {
907
+ label: Some("scene_node_uniform_bg"),
908
+ layout: uniform_layout,
909
+ entries: &[wgpu::BindGroupEntry {
910
+ binding: 0,
911
+ resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
912
+ buffer: pool_buf,
913
+ offset: (slot as u64) * NODE_UNIFORM_STRIDE,
914
+ size: std::num::NonZeroU64::new(uniform_size as u64),
915
+ }),
916
+ }],
917
+ }));
918
+ }
919
+ }
920
+
921
+ // Phase 4: single write — replaces what used to be N per-node
922
+ // queue.write_buffer calls. On sponza (68 nodes) this cut
923
+ // scene_prepare from ~1.7 ms to ~0.3 ms.
924
+ if visible_count > 0 && max_byte_offset > 0 {
925
+ queue.write_buffer(pool_buf, 0, &self.scratch[..max_byte_offset]);
926
+ }
927
+ }
928
+
929
+ /// Build / refresh per-node material bind groups for the scene
930
+ /// pipeline. Must be called every frame after `prepare` and before
931
+ /// `render`. Only rebuilds when a material changed (mat_dirty).
932
+ pub fn prepare_materials(&mut self, renderer: &crate::renderer::Renderer) {
933
+ for (_handle, node) in self.nodes.iter_mut() {
934
+ if !node.visible || node.indices.is_empty() {
935
+ continue;
936
+ }
937
+ if node.mat_dirty || node.gpu_material_bg.is_none() {
938
+ // Allocate or reuse the per-material uniform buffer.
939
+ // (Could be updated in place when factors change, but
940
+ // the current path always rebuilds together with the
941
+ // bind group — cheap and simpler.)
942
+ let uniform = renderer.create_scene_material_uniform(
943
+ node.material.metalness,
944
+ node.material.roughness,
945
+ node.material.emissive,
946
+ node.material.metallic_roughness_texture_idx != 0,
947
+ // Scene-graph materials don't yet carry an alpha
948
+ // mode — user code builds them via setMaterial(),
949
+ // not from glTF. Default to OPAQUE.
950
+ 0.0,
951
+ );
952
+ let bg = renderer.create_scene_material_bg(
953
+ node.material.texture_idx,
954
+ node.material.normal_texture_idx,
955
+ node.material.metallic_roughness_texture_idx,
956
+ node.material.emissive_texture_idx,
957
+ node.material.occlusion_texture_idx,
958
+ &uniform,
959
+ );
960
+ node.gpu_material_bg = Some(bg);
961
+ node.gpu_material_uniform_buf = Some(uniform);
962
+ node.mat_dirty = false;
963
+ }
964
+ }
965
+ }
966
+
967
+ /// Render all visible scene nodes into the given render pass.
968
+ /// Must be called after prepare() and after the pipeline/lighting/joints are set.
969
+ pub fn render<'a>(
970
+ &'a self,
971
+ pass: &mut wgpu::RenderPass<'a>,
972
+ ) {
973
+ for (_handle, node) in self.nodes.iter() {
974
+ if !node.visible || node.indices.is_empty() || !node.in_view_frustum {
975
+ continue;
976
+ }
977
+ let Some(vb) = &node.gpu_vb else { continue };
978
+ let Some(ib) = &node.gpu_ib else { continue };
979
+ let Some(bg) = &node.gpu_uniform_bg else { continue };
980
+ let Some(mat_bg) = &node.gpu_material_bg else { continue };
981
+ pass.set_bind_group(0, bg, &[]);
982
+ pass.set_bind_group(2, mat_bg, &[]);
983
+ pass.set_vertex_buffer(0, vb.slice(..));
984
+ pass.set_index_buffer(ib.slice(..), wgpu::IndexFormat::Uint32);
985
+ pass.draw_indexed(0..node.gpu_index_count, 0, 0..1);
986
+ }
987
+ }
988
+
989
+ pub fn node_count(&self) -> usize {
990
+ self.nodes.iter().count()
991
+ }
992
+ }
993
+
994
+ // ============================================================
995
+ // Matrix math (4x4, column-major)
996
+ // ============================================================
997
+
998
+ // ============================================================
999
+ // Frustum culling
1000
+ // ============================================================
1001
+ // Gribb-Hartmann plane extraction: for a column-major clip matrix M,
1002
+ // each plane = ±row_i + row_3. We build 6 planes (left/right/bottom/
1003
+ // top/near/far) in world space directly from the VP matrix, so every
1004
+ // plane-test below is a world-space dot product.
1005
+ //
1006
+ // A node's world-space AABB is outside the frustum if ALL 8 of its
1007
+ // corners are on the negative side of ANY single plane. The standard
1008
+ // "positive-vertex-only" optimization is skipped here — testing 8
1009
+ // corners is still a few dozen multiplies per node, trivial compared
1010
+ // to the per-node GPU cost we skip on a cull hit.
1011
+ //
1012
+ // Plane format: [nx, ny, nz, d] where `nx*x + ny*y + nz*z + d >= 0`
1013
+ // means the point is inside that plane's half-space. No normalization
1014
+ // — we only care about the sign.
1015
+
1016
+ pub(crate) fn extract_frustum_planes(vp: &[[f32; 4]; 4]) -> [[f32; 4]; 6] {
1017
+ // Row vectors of the column-major matrix: row_i[col] = vp[col][i].
1018
+ let row = |i: usize| [vp[0][i], vp[1][i], vp[2][i], vp[3][i]];
1019
+ let r0 = row(0); let r1 = row(1); let r2 = row(2); let r3 = row(3);
1020
+ let add = |a: [f32;4], b: [f32;4]| [a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3]+b[3]];
1021
+ let sub = |a: [f32;4], b: [f32;4]| [a[0]-b[0], a[1]-b[1], a[2]-b[2], a[3]-b[3]];
1022
+ [
1023
+ add(r3, r0), // left
1024
+ sub(r3, r0), // right
1025
+ add(r3, r1), // bottom
1026
+ sub(r3, r1), // top
1027
+ r2, // near (wgpu uses 0..1 depth → near = row_2)
1028
+ sub(r3, r2), // far
1029
+ ]
1030
+ }
1031
+
1032
+ pub(crate) fn aabb_outside_frustum(planes: &[[f32; 4]; 6], bmin: [f32; 3], bmax: [f32; 3]) -> bool {
1033
+ for p in planes.iter() {
1034
+ let mut all_outside = true;
1035
+ for ix in 0..2 {
1036
+ let x = if ix == 0 { bmin[0] } else { bmax[0] };
1037
+ for iy in 0..2 {
1038
+ let y = if iy == 0 { bmin[1] } else { bmax[1] };
1039
+ for iz in 0..2 {
1040
+ let z = if iz == 0 { bmin[2] } else { bmax[2] };
1041
+ if p[0]*x + p[1]*y + p[2]*z + p[3] >= 0.0 {
1042
+ all_outside = false;
1043
+ break;
1044
+ }
1045
+ }
1046
+ if !all_outside { break; }
1047
+ }
1048
+ if !all_outside { break; }
1049
+ }
1050
+ if all_outside { return true; }
1051
+ }
1052
+ false
1053
+ }
1054
+
1055
+ fn mat4_mul(a: &[[f32; 4]; 4], b: &[[f32; 4]; 4]) -> [[f32; 4]; 4] {
1056
+ let mut result = [[0.0f32; 4]; 4];
1057
+ for col in 0..4 {
1058
+ for row in 0..4 {
1059
+ result[col][row] = a[0][row] * b[col][0]
1060
+ + a[1][row] * b[col][1]
1061
+ + a[2][row] * b[col][2]
1062
+ + a[3][row] * b[col][3];
1063
+ }
1064
+ }
1065
+ result
1066
+ }