@gnsx/three 0.185.16 → 0.186.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 (417) hide show
  1. package/build/three.cjs +10 -82600
  2. package/build/three.core.js +1303 -728
  3. package/build/three.module.js +439 -338
  4. package/build/three.tsl.js +74 -44
  5. package/build/three.webgpu.js +6036 -2184
  6. package/build/three.webgpu.nodes.js +6020 -2184
  7. package/examples/jsm/Addons.js +6 -6
  8. package/examples/jsm/controls/ArcballControls.js +1 -1
  9. package/examples/jsm/controls/FirstPersonControls.js +44 -20
  10. package/examples/jsm/controls/OrbitControls.js +9 -0
  11. package/examples/jsm/controls/TrackballControls.js +109 -4
  12. package/examples/jsm/csm/CSMShadowNode.js +13 -0
  13. package/examples/jsm/exporters/GLTFExporter.js +23 -7
  14. package/examples/jsm/exporters/USDZExporter.js +2 -2
  15. package/examples/jsm/generators/CityGenerator.js +377 -45
  16. package/examples/jsm/generators/ForestGenerator.js +12 -12
  17. package/examples/jsm/generators/TerrainGenerator.js +49 -37
  18. package/examples/jsm/generators/TreeGenerator.js +70 -76
  19. package/examples/jsm/generators/city/BenchGenerator.js +127 -0
  20. package/examples/jsm/generators/city/CarGenerator.js +479 -0
  21. package/examples/jsm/generators/city/CityGeneratorUtils.js +31 -0
  22. package/examples/jsm/generators/city/HydrantGenerator.js +106 -0
  23. package/examples/jsm/generators/city/InstancedMeshGenerator.js +86 -0
  24. package/examples/jsm/generators/city/PersonGenerator.js +447 -0
  25. package/examples/jsm/generators/city/SidewalkGenerator.js +33 -38
  26. package/examples/jsm/generators/city/SkyscraperGenerator.js +448 -48
  27. package/examples/jsm/generators/city/StreetTreeGenerator.js +231 -0
  28. package/examples/jsm/generators/city/StreetlightGenerator.js +100 -0
  29. package/examples/jsm/generators/city/TrafficlightGenerator.js +106 -0
  30. package/examples/jsm/generators/city/TrashcanGenerator.js +100 -0
  31. package/examples/jsm/geometries/BoxLineGeometry.js +1 -1
  32. package/examples/jsm/geometries/ParametricGeometry.js +1 -1
  33. package/examples/jsm/geometries/RoundedBoxGeometry.js +1 -1
  34. package/examples/jsm/gpgpu/CountingSort.js +271 -0
  35. package/examples/jsm/helpers/LightProbeGridHelper.js +60 -239
  36. package/examples/jsm/helpers/LightProbeGridHelperWebGL.js +221 -0
  37. package/examples/jsm/inspector/Extension.js +94 -0
  38. package/examples/jsm/inspector/Inspector.js +145 -41
  39. package/examples/jsm/inspector/RendererInspector.js +100 -52
  40. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +2609 -0
  41. package/examples/jsm/inspector/extensions/color-grading/ColorWheel.js +352 -0
  42. package/examples/jsm/inspector/extensions/color-grading/CurveEditor.js +599 -0
  43. package/examples/jsm/inspector/extensions/color-grading/LUT3DStyle.js +1201 -0
  44. package/examples/jsm/inspector/extensions/color-grading/LUTMath.js +788 -0
  45. package/examples/jsm/inspector/extensions/color-grading/modules/BrightnessModule.js +72 -0
  46. package/examples/jsm/inspector/extensions/color-grading/modules/ColorWheelModule.js +112 -0
  47. package/examples/jsm/inspector/extensions/color-grading/modules/ContrastModule.js +82 -0
  48. package/examples/jsm/inspector/extensions/color-grading/modules/CurvesModule.js +109 -0
  49. package/examples/jsm/inspector/extensions/color-grading/modules/ExposureHueModule.js +110 -0
  50. package/examples/jsm/inspector/extensions/color-grading/modules/ExposureModule.js +73 -0
  51. package/examples/jsm/inspector/extensions/color-grading/modules/HueModule.js +78 -0
  52. package/examples/jsm/inspector/extensions/color-grading/modules/ImportedCubeModule.js +89 -0
  53. package/examples/jsm/inspector/extensions/color-grading/modules/Module.js +285 -0
  54. package/examples/jsm/inspector/extensions/color-grading/modules/OutputModule.js +101 -0
  55. package/examples/jsm/inspector/extensions/color-grading/modules/RendererModule.js +225 -0
  56. package/examples/jsm/inspector/extensions/color-grading/modules/SatVibranceModule.js +102 -0
  57. package/examples/jsm/inspector/extensions/color-grading/modules/SaturationModule.js +76 -0
  58. package/examples/jsm/inspector/extensions/color-grading/modules/VibranceModule.js +76 -0
  59. package/examples/jsm/inspector/extensions/color-grading/modules/WhiteBalanceModule.js +86 -0
  60. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +26 -31
  61. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +1 -0
  62. package/examples/jsm/inspector/tabs/Memory.js +0 -2
  63. package/examples/jsm/inspector/tabs/Settings.js +4 -0
  64. package/examples/jsm/inspector/tabs/Timeline.js +223 -171
  65. package/examples/jsm/inspector/tabs/Viewer.js +515 -21
  66. package/examples/jsm/inspector/ui/List.js +15 -9
  67. package/examples/jsm/inspector/ui/Profiler.js +170 -14
  68. package/examples/jsm/inspector/ui/Style.js +269 -23
  69. package/examples/jsm/inspector/ui/Tab.js +2 -0
  70. package/examples/jsm/inspector/ui/Values.js +14 -2
  71. package/examples/jsm/interactive/HTMLMesh.js +19 -3
  72. package/examples/jsm/lighting/LightProbeGrid.js +484 -889
  73. package/examples/jsm/lighting/LightProbeGridUtils.js +107 -0
  74. package/examples/jsm/lighting/LightProbeGridWebGL.js +841 -0
  75. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +194 -0
  76. package/examples/jsm/lighting/vxgi/VXGINode.js +660 -0
  77. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +478 -0
  78. package/examples/jsm/lighting/vxgi/VXGIVolume.js +1430 -0
  79. package/examples/jsm/lights/SunLight.js +95 -0
  80. package/examples/jsm/lights/SunLightNode.js +56 -0
  81. package/examples/jsm/lights/SunLightShadow.js +319 -0
  82. package/examples/jsm/lights/SunShadowNode.js +312 -0
  83. package/examples/jsm/loaders/3DMLoader.js +150 -49
  84. package/examples/jsm/loaders/3MFLoader.js +202 -1
  85. package/examples/jsm/loaders/FBXLoader.js +81 -5
  86. package/examples/jsm/loaders/GLTFGaussianSplatLoaderExtension.js +330 -0
  87. package/examples/jsm/loaders/GLTFLoader.js +79 -14
  88. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +386 -0
  89. package/examples/jsm/loaders/KSPLATLoader.js +463 -0
  90. package/examples/jsm/loaders/MaterialXLoader.js +111 -1010
  91. package/examples/jsm/loaders/PCDLoader.js +1 -1
  92. package/examples/jsm/loaders/SPLATLoader.js +139 -0
  93. package/examples/jsm/loaders/SPZLoader.js +561 -0
  94. package/examples/jsm/loaders/materialx/MaterialXArchive.js +108 -0
  95. package/examples/jsm/loaders/materialx/MaterialXDocument.js +878 -0
  96. package/examples/jsm/loaders/materialx/MaterialXHextile.js +183 -0
  97. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +376 -0
  98. package/examples/jsm/loaders/materialx/MaterialXLog.js +75 -0
  99. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +4 -0
  100. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +1021 -0
  101. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +661 -0
  102. package/examples/jsm/loaders/materialx/MaterialXUtils.js +57 -0
  103. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +997 -0
  104. package/examples/jsm/loaders/materialx/parse/MaterialXParser.js +28 -0
  105. package/examples/jsm/loaders/usd/USDAParser.js +15 -2
  106. package/examples/jsm/loaders/usd/USDCParser.js +1 -4
  107. package/examples/jsm/loaders/usd/USDComposer.js +80 -42
  108. package/examples/jsm/materials/WoodNodeMaterial.js +6 -108
  109. package/examples/jsm/misc/RollerCoaster.js +2 -2
  110. package/examples/jsm/misc/SculptGL.LICENSE.txt +21 -0
  111. package/examples/jsm/misc/Sculptor.js +1679 -0
  112. package/examples/jsm/misc/SculptorMesh.js +1504 -0
  113. package/examples/jsm/misc/SculptorTools.js +1180 -0
  114. package/examples/jsm/misc/SculptorUtils.js +345 -0
  115. package/examples/jsm/misc/TubePainter.js +28 -16
  116. package/examples/jsm/misc/VolumeSlice.js +24 -24
  117. package/examples/jsm/modifiers/SimplifyModifier.js +63 -556
  118. package/examples/jsm/objects/GaussianSplat.js +1039 -0
  119. package/examples/jsm/objects/Sky.js +66 -45
  120. package/examples/jsm/objects/SkyMesh.js +70 -51
  121. package/examples/jsm/physics/JoltPhysics.js +1 -1
  122. package/examples/jsm/postprocessing/AfterimagePass.js +4 -2
  123. package/examples/jsm/postprocessing/BloomPass.js +2 -2
  124. package/examples/jsm/postprocessing/GTAOPass.js +1 -1
  125. package/examples/jsm/postprocessing/OutlinePass.js +5 -5
  126. package/examples/jsm/postprocessing/SAOPass.js +1 -1
  127. package/examples/jsm/postprocessing/SSAOPass.js +1 -1
  128. package/examples/jsm/postprocessing/SSRPass.js +4 -2
  129. package/examples/jsm/postprocessing/SavePass.js +1 -1
  130. package/examples/jsm/postprocessing/TAARenderPass.js +1 -1
  131. package/examples/jsm/postprocessing/UnrealBloomPass.js +30 -13
  132. package/examples/jsm/renderers/CSS2DRenderer.js +29 -5
  133. package/examples/jsm/shaders/DepthLimitedBlurShader.js +4 -1
  134. package/examples/jsm/shaders/ExposureShader.js +1 -1
  135. package/examples/jsm/shaders/FilmShader.js +2 -1
  136. package/examples/jsm/transpiler/AST.js +21 -2
  137. package/examples/jsm/transpiler/GLSLDecoder.js +498 -8
  138. package/examples/jsm/transpiler/TSLEncoder.js +82 -10
  139. package/examples/jsm/transpiler/WGSLEncoder.js +33 -4
  140. package/examples/jsm/tsl/WebGLNodesHandler.js +29 -39
  141. package/examples/jsm/tsl/display/AfterImageNode.js +2 -0
  142. package/examples/jsm/tsl/display/AnaglyphPassNode.js +3 -2
  143. package/examples/jsm/tsl/display/BilateralBlurNode.js +5 -2
  144. package/examples/jsm/tsl/display/BloomNode.js +55 -30
  145. package/examples/jsm/tsl/display/DenoiseNode.js +21 -1
  146. package/examples/jsm/tsl/display/DepthOfFieldNode.js +24 -6
  147. package/examples/jsm/tsl/display/DotScreenNode.js +11 -11
  148. package/examples/jsm/tsl/display/FSR1Node.js +8 -4
  149. package/examples/jsm/tsl/display/GTAONode.js +199 -86
  150. package/examples/jsm/tsl/display/GaussianBlurNode.js +65 -52
  151. package/examples/jsm/tsl/display/GodraysNode.js +5 -2
  152. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +2 -2
  153. package/examples/jsm/tsl/display/LensflareNode.js +5 -2
  154. package/examples/jsm/tsl/display/OITPassNode.js +352 -0
  155. package/examples/jsm/tsl/display/OutlineNode.js +2 -0
  156. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +3 -2
  157. package/examples/jsm/tsl/display/RGBShiftNode.js +9 -9
  158. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +7 -4
  159. package/examples/jsm/tsl/display/RetroPassNode.js +1 -1
  160. package/examples/jsm/tsl/display/SMAANode.js +22 -61
  161. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -4
  162. package/examples/jsm/tsl/display/SSAONode.js +436 -0
  163. package/examples/jsm/tsl/display/SSGINode.js +5 -2
  164. package/examples/jsm/tsl/display/SSRNode.js +7 -2
  165. package/examples/jsm/tsl/display/SSSNode.js +5 -2
  166. package/examples/jsm/tsl/display/SharpenNode.js +5 -4
  167. package/examples/jsm/tsl/display/StereoCompositePassNode.js +1 -3
  168. package/examples/jsm/tsl/display/StereoPassNode.js +1 -3
  169. package/examples/jsm/tsl/display/TAAUNode.js +22 -125
  170. package/examples/jsm/tsl/display/TRAANode.js +16 -142
  171. package/examples/jsm/tsl/display/TemporalReprojectNode.js +21 -15
  172. package/examples/jsm/tsl/display/depthAwareBlur.js +63 -0
  173. package/examples/jsm/tsl/display/hashBlur.js +3 -2
  174. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +38 -27
  175. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +136 -0
  176. package/examples/jsm/tsl/math/voronoiNoise.js +112 -0
  177. package/examples/jsm/tsl/shadows/TileShadowNode.js +4 -6
  178. package/examples/jsm/tsl/utils/Raymarching.js +5 -5
  179. package/examples/jsm/tsl/utils/SoftParticles.js +60 -0
  180. package/examples/jsm/tsl/utils/TAAUtils.js +195 -0
  181. package/examples/jsm/utils/BufferGeometryUtils.js +14 -14
  182. package/examples/jsm/utils/GaussianSplatUtils.js +229 -0
  183. package/examples/jsm/utils/WebGLTextureUtils.js +1 -1
  184. package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
  185. package/examples/jsm/webxr/WebGLXRFallback.js +2 -16
  186. package/examples/jsm/webxr/XRControllerModelFactory.js +16 -4
  187. package/package.json +9 -16
  188. package/src/Three.Core.js +2 -1
  189. package/src/Three.TSL.js +73 -43
  190. package/src/Three.WebGPU.Nodes.js +1 -0
  191. package/src/Three.WebGPU.js +1 -0
  192. package/src/animation/AnimationClip.js +15 -2
  193. package/src/animation/AnimationObjectGroup.js +18 -6
  194. package/src/animation/AnimationUtils.js +26 -0
  195. package/src/animation/KeyframeTrack.js +37 -0
  196. package/src/constants.js +23 -1
  197. package/src/core/BufferAttribute.js +3 -2
  198. package/src/core/BufferGeometry.js +1 -1
  199. package/src/core/InterleavedBuffer.js +5 -1
  200. package/src/core/Object3D.js +40 -12
  201. package/src/core/Raycaster.js +4 -0
  202. package/src/core/RenderTarget.js +99 -9
  203. package/src/core/RenderTarget3D.js +12 -8
  204. package/src/extras/Controls.js +0 -8
  205. package/src/extras/PMREMGenerator.js +99 -205
  206. package/src/geometries/TorusGeometry.js +1 -1
  207. package/src/helpers/ArrowHelper.js +2 -0
  208. package/src/helpers/AxesHelper.js +2 -0
  209. package/src/helpers/Box3Helper.js +2 -0
  210. package/src/helpers/BoxHelper.js +2 -0
  211. package/src/helpers/CameraHelper.js +2 -0
  212. package/src/helpers/DirectionalLightHelper.js +2 -0
  213. package/src/helpers/GridHelper.js +2 -0
  214. package/src/helpers/HemisphereLightHelper.js +2 -0
  215. package/src/helpers/PlaneHelper.js +2 -0
  216. package/src/helpers/PointLightHelper.js +2 -0
  217. package/src/helpers/PolarGridHelper.js +2 -0
  218. package/src/helpers/SkeletonHelper.js +2 -0
  219. package/src/helpers/SpotLightHelper.js +2 -0
  220. package/src/lights/Light.js +0 -10
  221. package/src/lights/LightShadow.js +43 -12
  222. package/src/lights/SpotLightShadow.js +18 -0
  223. package/src/loaders/BufferGeometryLoader.js +5 -0
  224. package/src/loaders/ImageBitmapLoader.js +3 -1
  225. package/src/loaders/ObjectLoader.js +8 -5
  226. package/src/materials/Material.js +80 -57
  227. package/src/materials/MeshPhysicalMaterial.js +32 -0
  228. package/src/materials/nodes/Line2NodeMaterial.js +17 -8
  229. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +42 -5
  230. package/src/materials/nodes/NodeMaterial.js +19 -13
  231. package/src/materials/nodes/PointsNodeMaterial.js +2 -1
  232. package/src/materials/nodes/manager/NodeMaterialObserver.js +282 -55
  233. package/src/math/Frustum.js +9 -0
  234. package/src/math/FrustumArray.js +1 -1
  235. package/src/math/MathUtils.js +5 -3
  236. package/src/math/Matrix4.js +2 -9
  237. package/src/math/Plane.js +30 -1
  238. package/src/math/Quaternion.js +0 -10
  239. package/src/math/Ray.js +95 -45
  240. package/src/math/Triangle.js +0 -2
  241. package/src/math/Vector3.js +2 -2
  242. package/src/math/Vector4.js +0 -4
  243. package/src/math/interpolants/BezierInterpolant.js +36 -23
  244. package/src/nodes/Nodes.js +2 -0
  245. package/src/nodes/TSL.js +11 -3
  246. package/src/nodes/accessors/Batch.js +85 -13
  247. package/src/nodes/accessors/BufferAttributeNode.js +1 -1
  248. package/src/nodes/accessors/BuiltinNode.js +1 -1
  249. package/src/nodes/accessors/Instance.js +19 -18
  250. package/src/nodes/accessors/MaterialNode.js +9 -0
  251. package/src/nodes/accessors/ModelNode.js +85 -9
  252. package/src/nodes/accessors/ReferenceBaseNode.js +1 -70
  253. package/src/nodes/accessors/ReferenceElementNode.js +72 -0
  254. package/src/nodes/accessors/ReferenceNode.js +1 -70
  255. package/src/nodes/accessors/Skinning.js +124 -12
  256. package/src/nodes/accessors/StorageTextureNode.js +7 -3
  257. package/src/nodes/accessors/Texture3DNode.js +1 -1
  258. package/src/nodes/accessors/TextureNode.js +51 -21
  259. package/src/nodes/accessors/TextureSizeNode.js +4 -2
  260. package/src/nodes/accessors/UniformArrayNode.js +30 -5
  261. package/src/nodes/code/CodeNode.js +1 -1
  262. package/src/nodes/code/FunctionNode.js +12 -2
  263. package/src/nodes/core/ArrayNode.js +2 -2
  264. package/src/nodes/core/ContextNode.js +57 -4
  265. package/src/nodes/core/IndexNode.js +69 -4
  266. package/src/nodes/core/InspectorNode.js +2 -2
  267. package/src/nodes/core/MRTNode.js +44 -2
  268. package/src/nodes/core/Node.js +6 -3
  269. package/src/nodes/core/NodeBuilder.js +65 -50
  270. package/src/nodes/core/NodeFrame.js +11 -3
  271. package/src/nodes/core/NodeUtils.js +88 -0
  272. package/src/nodes/core/PropertyNode.js +8 -0
  273. package/src/nodes/core/StackNode.js +0 -1
  274. package/src/nodes/core/StructNode.js +4 -3
  275. package/src/nodes/core/UniformGroupNode.js +3 -2
  276. package/src/nodes/core/UniformNode.js +26 -12
  277. package/src/nodes/core/VarNode.js +0 -1
  278. package/src/nodes/display/BumpMapNode.js +2 -2
  279. package/src/nodes/display/ColorAdjustment.js +1 -1
  280. package/src/nodes/display/PassNode.js +76 -15
  281. package/src/nodes/display/ScreenNode.js +22 -65
  282. package/src/nodes/fog/Fog.js +4 -4
  283. package/src/nodes/functions/BSDF/BRDF_GGX.js +6 -6
  284. package/src/nodes/functions/BSDF/BRDF_Sheen.js +1 -1
  285. package/src/nodes/functions/BSDF/DFGLUT.js +2 -1
  286. package/src/nodes/functions/BSDF/LTC.js +1 -1
  287. package/src/nodes/functions/PhongLightingModel.js +1 -1
  288. package/src/nodes/functions/PhysicalLightingModel.js +83 -25
  289. package/src/nodes/functions/ToonLightingModel.js +2 -2
  290. package/src/nodes/functions/material/getParallaxCorrectNormal.js +3 -3
  291. package/src/nodes/gpgpu/AtomicFunctionNode.js +64 -13
  292. package/src/nodes/gpgpu/BarrierNode.js +13 -4
  293. package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -1
  294. package/src/nodes/gpgpu/ComputeNode.js +20 -17
  295. package/src/nodes/gpgpu/SubgroupFunctionNode.js +165 -37
  296. package/src/nodes/gpgpu/WorkgroupInfoNode.js +44 -6
  297. package/src/nodes/lighting/EnvironmentNode.js +40 -4
  298. package/src/nodes/lighting/LightsNode.js +20 -4
  299. package/src/nodes/lighting/ShadowBaseNode.js +158 -1
  300. package/src/nodes/lighting/ShadowFilterNode.js +2 -106
  301. package/src/nodes/lighting/ShadowNode.js +22 -91
  302. package/src/nodes/materialx/{lib/mx_hsv.js → MaterialXColor.js} +3 -6
  303. package/src/nodes/materialx/{lib/mx_transform_color.js → MaterialXColorTransform.js} +3 -6
  304. package/src/nodes/materialx/MaterialXCore.js +37 -0
  305. package/src/nodes/materialx/MaterialXNodes.js +64 -72
  306. package/src/nodes/materialx/{lib/mx_noise.js → MaterialXNoise.js} +426 -197
  307. package/src/nodes/math/BitcountNode.js +24 -4
  308. package/src/nodes/math/MathNode.js +4 -4
  309. package/src/nodes/math/MathUtils.js +15 -4
  310. package/src/nodes/math/OperatorNode.js +2 -2
  311. package/src/nodes/math/PackFloatNode.js +29 -1
  312. package/src/nodes/math/Packed4x8IntegerNode.js +433 -0
  313. package/src/nodes/math/UnpackFloatNode.js +30 -2
  314. package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
  315. package/src/nodes/pmrem/PMREMNode.js +1 -1
  316. package/src/nodes/pmrem/PMREMUtils.js +31 -74
  317. package/src/nodes/shapes/Shapes.js +1 -1
  318. package/src/nodes/tsl/TSLCore.js +1 -31
  319. package/src/nodes/utils/EventNode.js +75 -0
  320. package/src/nodes/utils/LoopNode.js +54 -13
  321. package/src/nodes/utils/PostProcessingUtils.js +23 -2
  322. package/src/nodes/utils/RTTNode.js +97 -32
  323. package/src/nodes/utils/ReflectorNode.js +8 -4
  324. package/src/nodes/utils/RotateNode.js +85 -8
  325. package/src/nodes/utils/SpriteUtils.js +58 -23
  326. package/src/objects/BatchedMesh.js +6 -0
  327. package/src/objects/InstancedMesh.js +1 -1
  328. package/src/objects/LOD.js +1 -1
  329. package/src/objects/Line.js +12 -0
  330. package/src/objects/Mesh.js +12 -0
  331. package/src/objects/Points.js +12 -0
  332. package/src/objects/Sprite.js +12 -0
  333. package/src/renderers/WebGLRenderer.js +93 -27
  334. package/src/renderers/common/Animation.js +12 -2
  335. package/src/renderers/common/Backend.js +38 -10
  336. package/src/renderers/common/BindGroup.js +0 -1
  337. package/src/renderers/common/Bindings.js +50 -4
  338. package/src/renderers/common/BundleGroup.js +4 -0
  339. package/src/renderers/common/ClippingContext.js +11 -1
  340. package/src/renderers/common/Color4.js +9 -0
  341. package/src/renderers/common/Constants.js +0 -5
  342. package/src/renderers/common/DirectRenderPipeline.js +233 -0
  343. package/src/renderers/common/Geometries.js +24 -3
  344. package/src/renderers/common/Info.js +3 -3
  345. package/src/renderers/common/InspectorBase.js +37 -8
  346. package/src/renderers/common/Lighting.js +11 -4
  347. package/src/renderers/common/Pipelines.js +6 -4
  348. package/src/renderers/common/QuadMesh.js +16 -2
  349. package/src/renderers/common/RenderContext.js +8 -0
  350. package/src/renderers/common/RenderList.js +53 -19
  351. package/src/renderers/common/RenderLists.js +58 -11
  352. package/src/renderers/common/RenderObject.js +14 -0
  353. package/src/renderers/common/RenderObjects.js +14 -9
  354. package/src/renderers/common/RenderPipeline.js +52 -44
  355. package/src/renderers/common/Renderer.js +226 -55
  356. package/src/renderers/common/Storage3DTexture.js +16 -0
  357. package/src/renderers/common/Textures.js +3 -3
  358. package/src/renderers/common/XRManager.js +79 -72
  359. package/src/renderers/common/extras/PMREMGenerator.js +76 -144
  360. package/src/renderers/common/nodes/NodeManager.js +144 -6
  361. package/src/renderers/common/nodes/NodeStorageBuffer.js +3 -1
  362. package/src/renderers/common/nodes/NodeUniformBuffer.js +3 -1
  363. package/src/renderers/shaders/DFGLUTData.js +2 -1
  364. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +4 -2
  365. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +48 -0
  366. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +53 -4
  367. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +20 -2
  368. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +20 -0
  369. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +6 -0
  370. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +61 -57
  371. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +82 -0
  372. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +9 -0
  373. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +8 -1
  374. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +15 -0
  375. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -0
  376. package/src/renderers/shaders/ShaderLib.js +1 -0
  377. package/src/renderers/shaders/UniformsLib.js +16 -0
  378. package/src/renderers/webgl/WebGLAnimation.js +2 -2
  379. package/src/renderers/webgl/WebGLCapabilities.js +2 -2
  380. package/src/renderers/webgl/WebGLLights.js +74 -4
  381. package/src/renderers/webgl/WebGLMaterials.js +6 -0
  382. package/src/renderers/webgl/WebGLOutput.js +36 -24
  383. package/src/renderers/webgl/WebGLProgram.js +3 -0
  384. package/src/renderers/webgl/WebGLPrograms.js +8 -0
  385. package/src/renderers/webgl/WebGLRenderLists.js +6 -10
  386. package/src/renderers/webgl/WebGLShadowMap.js +47 -44
  387. package/src/renderers/webgl/WebGLTextures.js +7 -7
  388. package/src/renderers/webgl-fallback/WebGLBackend.js +153 -45
  389. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +83 -29
  390. package/src/renderers/webgl-fallback/utils/WebGLState.js +163 -17
  391. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +32 -5
  392. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +11 -4
  393. package/src/renderers/webgpu/WebGPUBackend.js +513 -145
  394. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +99 -20
  395. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +2 -1
  396. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +3 -12
  397. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +24 -14
  398. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +80 -14
  399. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +62 -7
  400. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +9 -3
  401. package/src/renderers/webgpu/utils/WebGPUUtils.js +16 -4
  402. package/src/renderers/webxr/WebXRManager.js +25 -2
  403. package/src/scenes/Scene.js +3 -3
  404. package/src/textures/CompressedArrayTexture.js +16 -0
  405. package/src/textures/Data3DTexture.js +16 -0
  406. package/src/textures/DataArrayTexture.js +16 -0
  407. package/src/textures/DepthTexture.js +3 -3
  408. package/src/textures/Texture.js +3 -3
  409. package/src/textures/{Source.js → TextureSource.js} +39 -8
  410. package/build/three.core.min.js +0 -6
  411. package/build/three.module.min.js +0 -6
  412. package/build/three.tsl.min.js +0 -6
  413. package/build/three.webgpu.min.js +0 -6
  414. package/build/three.webgpu.nodes.min.js +0 -6
  415. package/examples/jsm/libs/ecsy.module.js +0 -1792
  416. package/examples/jsm/loaders/LottieLoader.js +0 -130
  417. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +0 -52
@@ -0,0 +1,1504 @@
1
+ /*!
2
+ * Portions adapted from SculptGL by Stéphane Ginier.
3
+ * Copyright (c) 2019 Stéphane GINIER
4
+ * Licensed under the MIT License; see ./SculptGL.LICENSE.txt.
5
+ */
6
+
7
+ import {
8
+ TRI_INDEX,
9
+ MAX_FLAG,
10
+ getMemory
11
+ } from './SculptorUtils.js';
12
+
13
+ const OCTREE_MAX_DEPTH = 8;
14
+ const OCTREE_MAX_FACES = 100;
15
+ // A depth-first walk retains at most seven siblings for each level.
16
+ const OCTREE_STACK = new Array( 1 + 7 * OCTREE_MAX_DEPTH ).fill( null );
17
+ const RELATIVE_WELD_TOLERANCE = 1e-7;
18
+
19
+ function queueLeaf( leaves, leaf ) {
20
+
21
+ if ( leaves === undefined || leaf._queuedForUpdate ) return;
22
+ leaf._queuedForUpdate = true;
23
+ leaves.push( leaf );
24
+
25
+ }
26
+
27
+ function hashPosition( x, y, z ) {
28
+
29
+ let hash = Math.imul( x, 0x85ebca6b );
30
+ hash = Math.imul( hash ^ ( hash >>> 13 ) ^ y, 0xc2b2ae35 );
31
+ hash = Math.imul( hash ^ ( hash >>> 16 ) ^ z, 0x27d4eb2d );
32
+ return ( hash ^ ( hash >>> 15 ) ) >>> 0;
33
+
34
+ }
35
+
36
+ function resetTagFlags( flags, activeCount ) {
37
+
38
+ for ( let i = 0; i < activeCount; i ++ ) {
39
+
40
+ if ( flags[ i ] >= 0 ) flags[ i ] = 0;
41
+
42
+ }
43
+
44
+ flags.fill( 0, activeCount );
45
+
46
+ }
47
+
48
+ function readSourceElements( index, sourceVertexCount ) {
49
+
50
+ const elementCount = index ? index.count : sourceVertexCount;
51
+
52
+ if ( index && ( index.itemSize !== 1 || index.normalized ) ) {
53
+
54
+ throw new Error( 'SculptorMesh: The index must be a non-normalized scalar attribute.' );
55
+
56
+ }
57
+
58
+ if ( index && typeof index.getX !== 'function' ) {
59
+
60
+ throw new Error( 'SculptorMesh: The index attribute must be CPU-accessible.' );
61
+
62
+ }
63
+
64
+ if ( elementCount === 0 || elementCount % 3 !== 0 ) {
65
+
66
+ throw new Error( 'SculptorMesh: The geometry must contain triangles with a complete, non-empty element list.' );
67
+
68
+ }
69
+
70
+ if ( index === null ) {
71
+
72
+ return { elementCount, sourceIndices: null, referencedVertices: null };
73
+
74
+ }
75
+
76
+ const sourceIndices = new Uint32Array( elementCount );
77
+ const referencedVertices = new Uint8Array( sourceVertexCount );
78
+
79
+ for ( let i = 0; i < elementCount; i ++ ) {
80
+
81
+ const sourceIndex = index.getX( i );
82
+
83
+ if ( Number.isInteger( sourceIndex ) === false || sourceIndex < 0 || sourceIndex >= sourceVertexCount ) {
84
+
85
+ throw new Error( 'SculptorMesh: Triangle indices must reference valid positions.' );
86
+
87
+ }
88
+
89
+ sourceIndices[ i ] = sourceIndex;
90
+ referencedVertices[ sourceIndex ] = 1;
91
+
92
+ }
93
+
94
+ return { elementCount, sourceIndices, referencedVertices };
95
+
96
+ }
97
+
98
+ function readSourcePositions( position, referencedVertices ) {
99
+
100
+ const sourceVertexCount = position.count;
101
+ const positions = new Float32Array( sourceVertexCount * 3 );
102
+ let minX = Infinity, minY = Infinity, minZ = Infinity;
103
+ let maxX = - Infinity, maxY = - Infinity, maxZ = - Infinity;
104
+
105
+ for ( let i = 0; i < sourceVertexCount; i ++ ) {
106
+
107
+ if ( referencedVertices !== null && referencedVertices[ i ] === 0 ) continue;
108
+
109
+ const sourceX = position.getX( i );
110
+ const sourceY = position.getY( i );
111
+ const sourceZ = position.getZ( i );
112
+
113
+ if ( Number.isFinite( sourceX ) === false || Number.isFinite( sourceY ) === false || Number.isFinite( sourceZ ) === false ) {
114
+
115
+ throw new Error( 'SculptorMesh: Position values must be finite.' );
116
+
117
+ }
118
+
119
+ const x = Math.fround( sourceX );
120
+ const y = Math.fround( sourceY );
121
+ const z = Math.fround( sourceZ );
122
+
123
+ if ( Number.isFinite( x ) === false || Number.isFinite( y ) === false || Number.isFinite( z ) === false ) {
124
+
125
+ throw new Error( 'SculptorMesh: Position values must fit in Float32 storage.' );
126
+
127
+ }
128
+
129
+ const offset = i * 3;
130
+ positions[ offset ] = x;
131
+ positions[ offset + 1 ] = y;
132
+ positions[ offset + 2 ] = z;
133
+
134
+ if ( x < minX ) minX = x;
135
+ if ( y < minY ) minY = y;
136
+ if ( z < minZ ) minZ = z;
137
+ if ( x > maxX ) maxX = x;
138
+ if ( y > maxY ) maxY = y;
139
+ if ( z > maxZ ) maxZ = z;
140
+
141
+ }
142
+
143
+ return { positions, bounds: [ minX, minY, minZ, maxX, maxY, maxZ ] };
144
+
145
+ }
146
+
147
+ function weldPositions( sourcePositions, referencedVertices, bounds ) {
148
+
149
+ const sourceVertexCount = sourcePositions.length / 3;
150
+ const extent = Math.max( bounds[ 3 ] - bounds[ 0 ], bounds[ 4 ] - bounds[ 1 ], bounds[ 5 ] - bounds[ 2 ] );
151
+ const tolerance = extent * RELATIVE_WELD_TOLERANCE;
152
+ const toleranceSquared = tolerance * tolerance;
153
+
154
+ // Cells twice the weld radius only need the current and nearest neighboring
155
+ // cell in each dimension. Exact distances resolve spatial-hash collisions.
156
+ const inverseCellSize = tolerance > 0 ? 0.5 / tolerance : 0;
157
+ const cellHeads = new Map();
158
+ const nextHashEntry = [];
159
+ const mergedPositions = [];
160
+ const vertexMap = new Uint32Array( sourceVertexCount );
161
+ const searchCellCount = inverseCellSize > 0 ? 2 : 1;
162
+
163
+ for ( let i = 0; i < sourceVertexCount; i ++ ) {
164
+
165
+ if ( referencedVertices !== null && referencedVertices[ i ] === 0 ) continue;
166
+
167
+ const offset = i * 3;
168
+ const x = sourcePositions[ offset ];
169
+ const y = sourcePositions[ offset + 1 ];
170
+ const z = sourcePositions[ offset + 2 ];
171
+ const gridX = ( x - bounds[ 0 ] ) * inverseCellSize;
172
+ const gridY = ( y - bounds[ 1 ] ) * inverseCellSize;
173
+ const gridZ = ( z - bounds[ 2 ] ) * inverseCellSize;
174
+ const cellX = Math.floor( gridX );
175
+ const cellY = Math.floor( gridY );
176
+ const cellZ = Math.floor( gridZ );
177
+ const neighborX = cellX + ( gridX - cellX < 0.5 ? - 1 : 1 );
178
+ const neighborY = cellY + ( gridY - cellY < 0.5 ? - 1 : 1 );
179
+ const neighborZ = cellZ + ( gridZ - cellZ < 0.5 ? - 1 : 1 );
180
+ let mergedIndex;
181
+ let closestDistanceSquared = Infinity;
182
+
183
+ searchCells: for ( let iz = 0; iz < searchCellCount; iz ++ ) {
184
+
185
+ const searchZ = iz === 0 ? cellZ : neighborZ;
186
+
187
+ for ( let iy = 0; iy < searchCellCount; iy ++ ) {
188
+
189
+ const searchY = iy === 0 ? cellY : neighborY;
190
+
191
+ for ( let ix = 0; ix < searchCellCount; ix ++ ) {
192
+
193
+ const searchX = ix === 0 ? cellX : neighborX;
194
+ let candidate = cellHeads.get( hashPosition( searchX, searchY, searchZ ) );
195
+
196
+ while ( candidate !== undefined ) {
197
+
198
+ const candidateOffset = candidate * 3;
199
+ const dx = mergedPositions[ candidateOffset ] - x;
200
+ const dy = mergedPositions[ candidateOffset + 1 ] - y;
201
+ const dz = mergedPositions[ candidateOffset + 2 ] - z;
202
+ const distanceSquared = dx * dx + dy * dy + dz * dz;
203
+
204
+ if ( distanceSquared === 0 ) {
205
+
206
+ mergedIndex = candidate;
207
+ break searchCells;
208
+
209
+ }
210
+
211
+ if ( distanceSquared <= toleranceSquared && distanceSquared < closestDistanceSquared ) {
212
+
213
+ mergedIndex = candidate;
214
+ closestDistanceSquared = distanceSquared;
215
+
216
+ }
217
+
218
+ candidate = nextHashEntry[ candidate ];
219
+
220
+ }
221
+
222
+ }
223
+
224
+ }
225
+
226
+ }
227
+
228
+ if ( mergedIndex === undefined ) {
229
+
230
+ mergedIndex = mergedPositions.length / 3;
231
+ const hash = hashPosition( cellX, cellY, cellZ );
232
+ nextHashEntry[ mergedIndex ] = cellHeads.get( hash );
233
+ cellHeads.set( hash, mergedIndex );
234
+ mergedPositions.push( x, y, z );
235
+
236
+ }
237
+
238
+ vertexMap[ i ] = mergedIndex;
239
+
240
+ }
241
+
242
+ return { positions: mergedPositions, vertexMap };
243
+
244
+ }
245
+
246
+ function buildTriangleBuffers( elementCount, sourceIndices, vertexMap, positions ) {
247
+
248
+ const triangleCount = elementCount / 3;
249
+ const faces = new Uint32Array( triangleCount * 4 );
250
+ const triangles = new Uint32Array( elementCount );
251
+
252
+ for ( let i = 0; i < triangleCount; i ++ ) {
253
+
254
+ const triangleOffset = i * 3;
255
+ let a, b, c;
256
+
257
+ if ( sourceIndices === null ) {
258
+
259
+ a = vertexMap[ triangleOffset ];
260
+ b = vertexMap[ triangleOffset + 1 ];
261
+ c = vertexMap[ triangleOffset + 2 ];
262
+
263
+ } else {
264
+
265
+ a = vertexMap[ sourceIndices[ triangleOffset ] ];
266
+ b = vertexMap[ sourceIndices[ triangleOffset + 1 ] ];
267
+ c = vertexMap[ sourceIndices[ triangleOffset + 2 ] ];
268
+
269
+ }
270
+
271
+ if ( a === b || b === c || c === a ) {
272
+
273
+ throw new Error( 'SculptorMesh: Welding produced a degenerate triangle.' );
274
+
275
+ }
276
+
277
+ const a3 = a * 3;
278
+ const b3 = b * 3;
279
+ const c3 = c * 3;
280
+ const abx = positions[ b3 ] - positions[ a3 ];
281
+ const aby = positions[ b3 + 1 ] - positions[ a3 + 1 ];
282
+ const abz = positions[ b3 + 2 ] - positions[ a3 + 2 ];
283
+ const acx = positions[ c3 ] - positions[ a3 ];
284
+ const acy = positions[ c3 + 1 ] - positions[ a3 + 1 ];
285
+ const acz = positions[ c3 + 2 ] - positions[ a3 + 2 ];
286
+ const normalX = Math.fround( aby * acz - abz * acy );
287
+ const normalY = Math.fround( abz * acx - abx * acz );
288
+ const normalZ = Math.fround( abx * acy - aby * acx );
289
+
290
+ if ( Number.isFinite( normalX ) === false || Number.isFinite( normalY ) === false || Number.isFinite( normalZ ) === false ) {
291
+
292
+ throw new Error( 'SculptorMesh: Triangle normals must fit in Float32 storage.' );
293
+
294
+ }
295
+
296
+ if ( normalX === 0 && normalY === 0 && normalZ === 0 ) {
297
+
298
+ throw new Error( 'SculptorMesh: The geometry contains a zero-area triangle at Float32 precision after welding.' );
299
+
300
+ }
301
+
302
+ const faceOffset = i * 4;
303
+ faces[ faceOffset ] = a;
304
+ faces[ faceOffset + 1 ] = b;
305
+ faces[ faceOffset + 2 ] = c;
306
+ faces[ faceOffset + 3 ] = TRI_INDEX;
307
+ triangles[ triangleOffset ] = a;
308
+ triangles[ triangleOffset + 1 ] = b;
309
+ triangles[ triangleOffset + 2 ] = c;
310
+
311
+ }
312
+
313
+ return { faces, triangles };
314
+
315
+ }
316
+
317
+ // Octree
318
+
319
+ class OctreeCell {
320
+
321
+ constructor( parent ) {
322
+
323
+ this._parent = parent ?? null;
324
+ this._depth = parent ? parent._depth + 1 : 0;
325
+ this._children = [];
326
+ this._aabbLoose = [ Infinity, Infinity, Infinity, - Infinity, - Infinity, - Infinity ];
327
+ this._aabbSplit = [ Infinity, Infinity, Infinity, - Infinity, - Infinity, - Infinity ];
328
+ this._iFaces = [];
329
+ this._queuedForUpdate = false;
330
+
331
+ }
332
+
333
+ resetNbFaces( nbFaces ) {
334
+
335
+ const f = this._iFaces;
336
+ f.length = nbFaces;
337
+ for ( let i = 0; i < nbFaces; ++ i ) f[ i ] = i;
338
+
339
+ }
340
+
341
+ build( mesh ) {
342
+
343
+ const stack = OCTREE_STACK;
344
+ stack[ 0 ] = this;
345
+ let curStack = 1;
346
+ const leaves = [];
347
+ while ( curStack > 0 ) {
348
+
349
+ const cell = stack[ -- curStack ];
350
+ const nbFaces = cell._iFaces.length;
351
+ if ( nbFaces > OCTREE_MAX_FACES && cell._depth < OCTREE_MAX_DEPTH ) {
352
+
353
+ cell._constructChildren( mesh );
354
+ const children = cell._children;
355
+ for ( let i = 0; i < 8; ++ i ) stack[ curStack + i ] = children[ i ];
356
+ curStack += 8;
357
+
358
+ } else if ( nbFaces > 0 ) {
359
+
360
+ leaves.push( cell );
361
+
362
+ }
363
+
364
+ }
365
+
366
+ for ( let i = 0, l = leaves.length; i < l; ++ i ) leaves[ i ]._constructLeaf( mesh );
367
+ stack.fill( null );
368
+
369
+ }
370
+
371
+ _constructLeaf( mesh ) {
372
+
373
+ const iFaces = this._iFaces;
374
+ const nbFaces = iFaces.length;
375
+ let bxmin = Infinity, bymin = Infinity, bzmin = Infinity;
376
+ let bxmax = - Infinity, bymax = - Infinity, bzmax = - Infinity;
377
+ const faceBoxes = mesh._faceBoxes;
378
+ const facePosInLeaf = mesh._facePosInLeaf;
379
+ const faceLeaf = mesh._faceLeaf;
380
+ for ( let i = 0; i < nbFaces; ++ i ) {
381
+
382
+ const id = iFaces[ i ];
383
+ faceLeaf[ id ] = this;
384
+ facePosInLeaf[ id ] = i;
385
+ const id6 = id * 6;
386
+ if ( faceBoxes[ id6 ] < bxmin ) bxmin = faceBoxes[ id6 ];
387
+ if ( faceBoxes[ id6 + 1 ] < bymin ) bymin = faceBoxes[ id6 + 1 ];
388
+ if ( faceBoxes[ id6 + 2 ] < bzmin ) bzmin = faceBoxes[ id6 + 2 ];
389
+ if ( faceBoxes[ id6 + 3 ] > bxmax ) bxmax = faceBoxes[ id6 + 3 ];
390
+ if ( faceBoxes[ id6 + 4 ] > bymax ) bymax = faceBoxes[ id6 + 4 ];
391
+ if ( faceBoxes[ id6 + 5 ] > bzmax ) bzmax = faceBoxes[ id6 + 5 ];
392
+
393
+ }
394
+
395
+ this._expandAabbLoose( bxmin, bymin, bzmin, bxmax, bymax, bzmax );
396
+
397
+ }
398
+
399
+ _constructChildren( mesh ) {
400
+
401
+ const split = this._aabbSplit;
402
+ const xmin = split[ 0 ], ymin = split[ 1 ], zmin = split[ 2 ];
403
+ const xmax = split[ 3 ], ymax = split[ 4 ], zmax = split[ 5 ];
404
+ const xcen = ( xmax + xmin ) * 0.5, ycen = ( ymax + ymin ) * 0.5, zcen = ( zmax + zmin ) * 0.5;
405
+
406
+ const children = new Array( 8 );
407
+ for ( let i = 0; i < 8; i ++ ) children[ i ] = new OctreeCell( this );
408
+
409
+ const faceCenters = mesh._faceCenters;
410
+ const iFaces = this._iFaces;
411
+ for ( let i = 0, l = iFaces.length; i < l; ++ i ) {
412
+
413
+ const iFace = iFaces[ i ];
414
+ const id = iFace * 3;
415
+ const cx = faceCenters[ id ], cy = faceCenters[ id + 1 ], cz = faceCenters[ id + 2 ];
416
+ if ( cx > xcen ) {
417
+
418
+ if ( cy > ycen ) children[ cz > zcen ? 6 : 5 ]._iFaces.push( iFace );
419
+ else children[ cz > zcen ? 2 : 1 ]._iFaces.push( iFace );
420
+
421
+ } else {
422
+
423
+ if ( cy > ycen ) children[ cz > zcen ? 7 : 4 ]._iFaces.push( iFace );
424
+ else children[ cz > zcen ? 3 : 0 ]._iFaces.push( iFace );
425
+
426
+ }
427
+
428
+ }
429
+
430
+ children[ 0 ]._setAabbSplit( xmin, ymin, zmin, xcen, ycen, zcen );
431
+ children[ 1 ]._setAabbSplit( xcen, ymin, zmin, xmax, ycen, zcen );
432
+ children[ 2 ]._setAabbSplit( xcen, ymin, zcen, xmax, ycen, zmax );
433
+ children[ 3 ]._setAabbSplit( xmin, ymin, zcen, xcen, ycen, zmax );
434
+ children[ 4 ]._setAabbSplit( xmin, ycen, zmin, xcen, ymax, zcen );
435
+ children[ 5 ]._setAabbSplit( xcen, ycen, zmin, xmax, ymax, zcen );
436
+ children[ 6 ]._setAabbSplit( xcen, ycen, zcen, xmax, ymax, zmax );
437
+ children[ 7 ]._setAabbSplit( xmin, ycen, zcen, xcen, ymax, zmax );
438
+
439
+ this._children = children;
440
+ this._iFaces.length = 0;
441
+
442
+ }
443
+
444
+ _setAabbSplit( xmin, ymin, zmin, xmax, ymax, zmax ) {
445
+
446
+ const a = this._aabbSplit;
447
+ a[ 0 ] = xmin; a[ 1 ] = ymin; a[ 2 ] = zmin;
448
+ a[ 3 ] = xmax; a[ 4 ] = ymax; a[ 5 ] = zmax;
449
+
450
+ }
451
+
452
+ _setAabbLoose( xmin, ymin, zmin, xmax, ymax, zmax ) {
453
+
454
+ const a = this._aabbLoose;
455
+ a[ 0 ] = xmin; a[ 1 ] = ymin; a[ 2 ] = zmin;
456
+ a[ 3 ] = xmax; a[ 4 ] = ymax; a[ 5 ] = zmax;
457
+
458
+ }
459
+
460
+ collectIntersectRay( vNear, eyeDir, collectFaces, leavesHit ) {
461
+
462
+ const vx = vNear[ 0 ], vy = vNear[ 1 ], vz = vNear[ 2 ];
463
+ const irx = 1.0 / eyeDir[ 0 ], iry = 1.0 / eyeDir[ 1 ], irz = 1.0 / eyeDir[ 2 ];
464
+ let acc = 0;
465
+ const stack = OCTREE_STACK;
466
+ stack[ 0 ] = this;
467
+ let curStack = 1;
468
+ while ( curStack > 0 ) {
469
+
470
+ const cell = stack[ -- curStack ];
471
+ const loose = cell._aabbLoose;
472
+ const t1 = ( loose[ 0 ] - vx ) * irx, t2 = ( loose[ 3 ] - vx ) * irx;
473
+ const t3 = ( loose[ 1 ] - vy ) * iry, t4 = ( loose[ 4 ] - vy ) * iry;
474
+ const t5 = ( loose[ 2 ] - vz ) * irz, t6 = ( loose[ 5 ] - vz ) * irz;
475
+ const tmin = Math.max( Math.min( t1, t2 ), Math.min( t3, t4 ), Math.min( t5, t6 ) );
476
+ const tmax = Math.min( Math.max( t1, t2 ), Math.max( t3, t4 ), Math.max( t5, t6 ) );
477
+ if ( tmax < 0 || tmin > tmax ) continue;
478
+ const children = cell._children;
479
+ if ( children.length === 8 ) {
480
+
481
+ for ( let i = 0; i < 8; ++ i ) stack[ curStack + i ] = children[ i ];
482
+ curStack += 8;
483
+
484
+ } else {
485
+
486
+ queueLeaf( leavesHit, cell );
487
+ const iFaces = cell._iFaces;
488
+ collectFaces.set( iFaces, acc );
489
+ acc += iFaces.length;
490
+
491
+ }
492
+
493
+ }
494
+
495
+ stack.fill( null );
496
+ return collectFaces.slice( 0, acc );
497
+
498
+ }
499
+
500
+ collectIntersectSphere( vert, radiusSquared, collectFaces, leavesHit ) {
501
+
502
+ const vx = vert[ 0 ], vy = vert[ 1 ], vz = vert[ 2 ];
503
+ let acc = 0;
504
+ const stack = OCTREE_STACK;
505
+ stack[ 0 ] = this;
506
+ let curStack = 1;
507
+ while ( curStack > 0 ) {
508
+
509
+ const cell = stack[ -- curStack ];
510
+ const loose = cell._aabbLoose;
511
+ let dx = 0, dy = 0, dz = 0;
512
+ if ( loose[ 0 ] > vx ) dx = loose[ 0 ] - vx;
513
+ else if ( loose[ 3 ] < vx ) dx = loose[ 3 ] - vx;
514
+ if ( loose[ 1 ] > vy ) dy = loose[ 1 ] - vy;
515
+ else if ( loose[ 4 ] < vy ) dy = loose[ 4 ] - vy;
516
+ if ( loose[ 2 ] > vz ) dz = loose[ 2 ] - vz;
517
+ else if ( loose[ 5 ] < vz ) dz = loose[ 5 ] - vz;
518
+ if ( dx * dx + dy * dy + dz * dz > radiusSquared ) continue;
519
+ const children = cell._children;
520
+ if ( children.length === 8 ) {
521
+
522
+ for ( let i = 0; i < 8; ++ i ) stack[ curStack + i ] = children[ i ];
523
+ curStack += 8;
524
+
525
+ } else {
526
+
527
+ queueLeaf( leavesHit, cell );
528
+ const iFaces = cell._iFaces;
529
+ collectFaces.set( iFaces, acc );
530
+ acc += iFaces.length;
531
+
532
+ }
533
+
534
+ }
535
+
536
+ stack.fill( null );
537
+ return collectFaces.slice( 0, acc );
538
+
539
+ }
540
+
541
+ addFace( faceId, bxmin, bymin, bzmin, bxmax, bymax, bzmax, cx, cy, cz ) {
542
+
543
+ const stack = OCTREE_STACK;
544
+ stack[ 0 ] = this;
545
+ let curStack = 1;
546
+ while ( curStack > 0 ) {
547
+
548
+ const cell = stack[ -- curStack ];
549
+ const s = cell._aabbSplit;
550
+ if ( cx <= s[ 0 ] || cy <= s[ 1 ] || cz <= s[ 2 ] || cx > s[ 3 ] || cy > s[ 4 ] || cz > s[ 5 ] ) continue;
551
+ const loose = cell._aabbLoose;
552
+ if ( bxmin < loose[ 0 ] ) loose[ 0 ] = bxmin;
553
+ if ( bymin < loose[ 1 ] ) loose[ 1 ] = bymin;
554
+ if ( bzmin < loose[ 2 ] ) loose[ 2 ] = bzmin;
555
+ if ( bxmax > loose[ 3 ] ) loose[ 3 ] = bxmax;
556
+ if ( bymax > loose[ 4 ] ) loose[ 4 ] = bymax;
557
+ if ( bzmax > loose[ 5 ] ) loose[ 5 ] = bzmax;
558
+ const children = cell._children;
559
+ if ( children.length === 8 ) {
560
+
561
+ for ( let i = 0; i < 8; ++ i ) stack[ curStack + i ] = children[ i ];
562
+ curStack += 8;
563
+
564
+ } else {
565
+
566
+ cell._iFaces.push( faceId );
567
+ stack.fill( null );
568
+ return cell;
569
+
570
+ }
571
+
572
+ }
573
+
574
+ stack.fill( null );
575
+
576
+ }
577
+
578
+ _expandAabbLoose( bxmin, bymin, bzmin, bxmax, bymax, bzmax ) {
579
+
580
+ let parent = this;
581
+ while ( parent ) {
582
+
583
+ const p = parent._aabbLoose;
584
+ let proceed = false;
585
+ if ( bxmin < p[ 0 ] ) {
586
+
587
+ p[ 0 ] = bxmin; proceed = true;
588
+
589
+ }
590
+
591
+ if ( bymin < p[ 1 ] ) {
592
+
593
+ p[ 1 ] = bymin; proceed = true;
594
+
595
+ }
596
+
597
+ if ( bzmin < p[ 2 ] ) {
598
+
599
+ p[ 2 ] = bzmin; proceed = true;
600
+
601
+ }
602
+
603
+ if ( bxmax > p[ 3 ] ) {
604
+
605
+ p[ 3 ] = bxmax; proceed = true;
606
+
607
+ }
608
+
609
+ if ( bymax > p[ 4 ] ) {
610
+
611
+ p[ 4 ] = bymax; proceed = true;
612
+
613
+ }
614
+
615
+ if ( bzmax > p[ 5 ] ) {
616
+
617
+ p[ 5 ] = bzmax; proceed = true;
618
+
619
+ }
620
+
621
+ parent = proceed ? parent._parent : null;
622
+
623
+ }
624
+
625
+ }
626
+
627
+ pruneIfPossible() {
628
+
629
+ let cell = this;
630
+ while ( cell._parent ) {
631
+
632
+ const parent = cell._parent;
633
+ const children = parent._children;
634
+ if ( children.length === 0 ) return;
635
+ for ( let i = 0; i < 8; ++ i ) {
636
+
637
+ if ( children[ i ]._iFaces.length > 0 || children[ i ]._children.length === 8 ) return;
638
+
639
+ }
640
+
641
+ children.length = 0;
642
+ cell = parent;
643
+
644
+ }
645
+
646
+ }
647
+
648
+ }
649
+
650
+ // Mesh topology and spatial queries
651
+
652
+ class SculptorMesh {
653
+
654
+ constructor() {
655
+
656
+ this._nbVertices = 0;
657
+ this._nbFaces = 0;
658
+
659
+ this._verticesXYZ = null;
660
+ this._normalsXYZ = null;
661
+ this._renderNormalsXYZ = null;
662
+
663
+ this._facesABCD = null;
664
+ this._trianglesABC = null;
665
+
666
+ this._vertRingVert = [];
667
+ this._vertRingFace = [];
668
+ this._vertOnEdge = null;
669
+
670
+ this._faceNormals = null;
671
+ this._faceBoxes = null;
672
+ this._faceCenters = null;
673
+ this._facePosInLeaf = null;
674
+ this._faceLeaf = [];
675
+
676
+ this._vertTagFlags = null;
677
+ this._vertSculptFlags = null;
678
+ this._facesTagFlags = null;
679
+
680
+ this._octree = null;
681
+ this._leavesToUpdate = [];
682
+ this._topologyVersion = 0;
683
+ this._tagFlag = 1;
684
+ this._sculptFlag = 1;
685
+
686
+ }
687
+
688
+ getNbVertices() {
689
+
690
+ return this._nbVertices;
691
+
692
+ }
693
+ getNbFaces() {
694
+
695
+ return this._nbFaces;
696
+
697
+ }
698
+ getNbTriangles() {
699
+
700
+ return this._nbFaces;
701
+
702
+ }
703
+ getVertices() {
704
+
705
+ return this._verticesXYZ;
706
+
707
+ }
708
+ getNormals() {
709
+
710
+ return this._normalsXYZ;
711
+
712
+ }
713
+ getRenderNormals() {
714
+
715
+ return this._renderNormalsXYZ;
716
+
717
+ }
718
+ getFaces() {
719
+
720
+ return this._facesABCD;
721
+
722
+ }
723
+ getTriangles() {
724
+
725
+ return this._trianglesABC;
726
+
727
+ }
728
+ getVerticesRingVert() {
729
+
730
+ return this._vertRingVert;
731
+
732
+ }
733
+ getVerticesRingFace() {
734
+
735
+ return this._vertRingFace;
736
+
737
+ }
738
+ getVerticesOnEdge() {
739
+
740
+ return this._vertOnEdge;
741
+
742
+ }
743
+ getVerticesTagFlags() {
744
+
745
+ return this._vertTagFlags;
746
+
747
+ }
748
+ getVerticesSculptFlags() {
749
+
750
+ return this._vertSculptFlags;
751
+
752
+ }
753
+ getFaceNormals() {
754
+
755
+ return this._faceNormals;
756
+
757
+ }
758
+ getFaceBoxes() {
759
+
760
+ return this._faceBoxes;
761
+
762
+ }
763
+ getFaceCenters() {
764
+
765
+ return this._faceCenters;
766
+
767
+ }
768
+ getFacePosInLeaf() {
769
+
770
+ return this._facePosInLeaf;
771
+
772
+ }
773
+ getFaceLeaf() {
774
+
775
+ return this._faceLeaf;
776
+
777
+ }
778
+ getFacesTagFlags() {
779
+
780
+ return this._facesTagFlags;
781
+
782
+ }
783
+ getTopologyVersion() {
784
+
785
+ return this._topologyVersion;
786
+
787
+ }
788
+ getSculptFlag() {
789
+
790
+ return this._sculptFlag;
791
+
792
+ }
793
+ nextTagFlag() {
794
+
795
+ if ( this._tagFlag >= MAX_FLAG ) {
796
+
797
+ // Preserve pending deletion sentinels across tag rollover.
798
+ resetTagFlags( this._vertTagFlags, this._nbVertices );
799
+ resetTagFlags( this._facesTagFlags, this._nbFaces );
800
+ this._tagFlag = 1;
801
+
802
+ } else {
803
+
804
+ this._tagFlag ++;
805
+
806
+ }
807
+
808
+ return this._tagFlag;
809
+
810
+ }
811
+ nextSculptFlag() {
812
+
813
+ if ( this._sculptFlag >= MAX_FLAG ) {
814
+
815
+ this._vertSculptFlags.fill( 0 );
816
+ this._sculptFlag = 1;
817
+
818
+ } else {
819
+
820
+ this._sculptFlag ++;
821
+
822
+ }
823
+
824
+ return this._sculptFlag;
825
+
826
+ }
827
+
828
+ addNbVertice( nb ) {
829
+
830
+ this._nbVertices += nb;
831
+
832
+ }
833
+ addNbFace( nb ) {
834
+
835
+ this._nbFaces += nb;
836
+ this._topologyVersion ++;
837
+
838
+ }
839
+ markTopologyChanged() {
840
+
841
+ this._topologyVersion ++;
842
+
843
+ }
844
+
845
+ initFromGeometry( geometry ) {
846
+
847
+ this._tagFlag = 1;
848
+ this._sculptFlag = 1;
849
+
850
+ const posAttr = geometry.getAttribute( 'position' );
851
+
852
+ if ( posAttr === undefined || posAttr.itemSize !== 3 || posAttr.count === 0 ) {
853
+
854
+ throw new Error( 'SculptorMesh: A non-empty position attribute with itemSize 3 is required.' );
855
+
856
+ }
857
+
858
+ if ( typeof posAttr.getX !== 'function' || typeof posAttr.getY !== 'function' || typeof posAttr.getZ !== 'function' ) {
859
+
860
+ throw new Error( 'SculptorMesh: The position attribute must be CPU-accessible.' );
861
+
862
+ }
863
+
864
+ const index = geometry.getIndex();
865
+ const sourceVertexCount = posAttr.count;
866
+ const { elementCount, sourceIndices, referencedVertices } = readSourceElements( index, sourceVertexCount );
867
+ const { positions: sourcePositions, bounds } = readSourcePositions( posAttr, referencedVertices );
868
+ const { positions: weldedPositions, vertexMap } = weldPositions( sourcePositions, referencedVertices, bounds );
869
+ const { faces, triangles } = buildTriangleBuffers( elementCount, sourceIndices, vertexMap, weldedPositions );
870
+ const vertexCount = weldedPositions.length / 3;
871
+ const triangleCount = elementCount / 3;
872
+ const vertexDataLength = vertexCount * 3;
873
+
874
+ this._nbVertices = vertexCount;
875
+ this._nbFaces = triangleCount;
876
+ this._topologyVersion = 0;
877
+ this._leavesToUpdate.length = 0;
878
+
879
+ this._verticesXYZ = new Float32Array( weldedPositions );
880
+ this._normalsXYZ = new Float32Array( vertexDataLength );
881
+ this._renderNormalsXYZ = new Float32Array( vertexDataLength );
882
+
883
+ this._facesABCD = faces;
884
+ this._trianglesABC = triangles;
885
+ this._vertOnEdge = new Uint8Array( vertexCount );
886
+ this._vertTagFlags = new Int32Array( vertexCount );
887
+ this._vertSculptFlags = new Int32Array( vertexCount );
888
+ this._facesTagFlags = new Int32Array( triangleCount );
889
+ this._faceBoxes = new Float32Array( triangleCount * 6 );
890
+ this._faceNormals = new Float32Array( triangleCount * 3 );
891
+ this._faceCenters = new Float32Array( triangleCount * 3 );
892
+ this._facePosInLeaf = new Uint32Array( triangleCount );
893
+ this._faceLeaf = new Array( triangleCount ).fill( null );
894
+
895
+ this._initTopology();
896
+ this._updateGeometry();
897
+
898
+ }
899
+
900
+ _initTopology() {
901
+
902
+ const vrings = this._vertRingVert;
903
+ const frings = this._vertRingFace;
904
+ const nbVertices = this._nbVertices;
905
+ vrings.length = frings.length = nbVertices;
906
+ for ( let i = 0; i < nbVertices; ++ i ) {
907
+
908
+ vrings[ i ] = [];
909
+ frings[ i ] = [];
910
+
911
+ }
912
+
913
+ const nbTriangles = this._nbFaces;
914
+ const tAr = this._trianglesABC;
915
+ for ( let i = 0; i < nbTriangles; ++ i ) {
916
+
917
+ const j = i * 3;
918
+ frings[ tAr[ j ] ].push( i );
919
+ frings[ tAr[ j + 1 ] ].push( i );
920
+ frings[ tAr[ j + 2 ] ].push( i );
921
+
922
+ }
923
+
924
+ const vOnEdge = this._vertOnEdge;
925
+ for ( let i = 0; i < nbVertices; ++ i ) {
926
+
927
+ this._computeRingVertices( i );
928
+ vOnEdge[ i ] = frings[ i ].length !== vrings[ i ].length ? 1 : 0;
929
+
930
+ }
931
+
932
+ }
933
+
934
+ _computeRingVertices( iVert ) {
935
+
936
+ const tagFlag = this.nextTagFlag();
937
+ const fAr = this._facesABCD;
938
+ const vflags = this._vertTagFlags;
939
+ const vring = this._vertRingVert[ iVert ];
940
+ const fring = this._vertRingFace[ iVert ];
941
+ vring.length = 0;
942
+ for ( let i = 0, l = fring.length; i < l; ++ i ) {
943
+
944
+ const ind = fring[ i ] * 4;
945
+ let iVer1 = fAr[ ind ];
946
+ let iVer2 = fAr[ ind + 1 ];
947
+ if ( iVer1 === iVert ) iVer1 = fAr[ ind + 2 ];
948
+ else if ( iVer2 === iVert ) iVer2 = fAr[ ind + 2 ];
949
+ if ( vflags[ iVer1 ] !== tagFlag ) {
950
+
951
+ vflags[ iVer1 ] = tagFlag; vring.push( iVer1 );
952
+
953
+ }
954
+
955
+ if ( vflags[ iVer2 ] !== tagFlag ) {
956
+
957
+ vflags[ iVer2 ] = tagFlag; vring.push( iVer2 );
958
+
959
+ }
960
+
961
+ }
962
+
963
+ }
964
+
965
+ _updateGeometry( iFaces, iVerts ) {
966
+
967
+ if ( iVerts === undefined && iFaces !== undefined ) iVerts = this.getVerticesFromFaces( iFaces );
968
+
969
+ this._updateFacesAabbAndNormal( iFaces );
970
+ this._updateVerticesNormal( iVerts );
971
+ this._updateOctree( iFaces );
972
+
973
+ }
974
+
975
+ _updateFacesAabbAndNormal( iFaces ) {
976
+
977
+ const faceNormals = this._faceNormals;
978
+ const faceBoxes = this._faceBoxes;
979
+ const faceCenters = this._faceCenters;
980
+ const vAr = this._verticesXYZ;
981
+ const fAr = this._facesABCD;
982
+ const full = iFaces === undefined;
983
+ const nbFaces = full ? this._nbFaces : iFaces.length;
984
+
985
+ for ( let i = 0; i < nbFaces; ++ i ) {
986
+
987
+ const ind = full ? i : iFaces[ i ];
988
+ const idTri = ind * 3;
989
+ const idFace = ind * 4;
990
+ const idBox = ind * 6;
991
+ const ind1 = fAr[ idFace ] * 3;
992
+ const ind2 = fAr[ idFace + 1 ] * 3;
993
+ const ind3 = fAr[ idFace + 2 ] * 3;
994
+
995
+ const v1x = vAr[ ind1 ], v1y = vAr[ ind1 + 1 ], v1z = vAr[ ind1 + 2 ];
996
+ const v2x = vAr[ ind2 ], v2y = vAr[ ind2 + 1 ], v2z = vAr[ ind2 + 2 ];
997
+ const v3x = vAr[ ind3 ], v3y = vAr[ ind3 + 1 ], v3z = vAr[ ind3 + 2 ];
998
+
999
+ const ax = v2x - v1x, ay = v2y - v1y, az = v2z - v1z;
1000
+ const bx = v3x - v1x, by = v3y - v1y, bz = v3z - v1z;
1001
+ faceNormals[ idTri ] = ay * bz - az * by;
1002
+ faceNormals[ idTri + 1 ] = az * bx - ax * bz;
1003
+ faceNormals[ idTri + 2 ] = ax * by - ay * bx;
1004
+
1005
+ const xmin = v1x < v2x ? ( v1x < v3x ? v1x : v3x ) : ( v2x < v3x ? v2x : v3x );
1006
+ const xmax = v1x > v2x ? ( v1x > v3x ? v1x : v3x ) : ( v2x > v3x ? v2x : v3x );
1007
+ const ymin = v1y < v2y ? ( v1y < v3y ? v1y : v3y ) : ( v2y < v3y ? v2y : v3y );
1008
+ const ymax = v1y > v2y ? ( v1y > v3y ? v1y : v3y ) : ( v2y > v3y ? v2y : v3y );
1009
+ const zmin = v1z < v2z ? ( v1z < v3z ? v1z : v3z ) : ( v2z < v3z ? v2z : v3z );
1010
+ const zmax = v1z > v2z ? ( v1z > v3z ? v1z : v3z ) : ( v2z > v3z ? v2z : v3z );
1011
+
1012
+ faceBoxes[ idBox ] = xmin; faceBoxes[ idBox + 1 ] = ymin; faceBoxes[ idBox + 2 ] = zmin;
1013
+ faceBoxes[ idBox + 3 ] = xmax; faceBoxes[ idBox + 4 ] = ymax; faceBoxes[ idBox + 5 ] = zmax;
1014
+ faceCenters[ idTri ] = ( xmin + xmax ) * 0.5;
1015
+ faceCenters[ idTri + 1 ] = ( ymin + ymax ) * 0.5;
1016
+ faceCenters[ idTri + 2 ] = ( zmin + zmax ) * 0.5;
1017
+
1018
+ }
1019
+
1020
+ }
1021
+
1022
+ _updateVerticesNormal( iVerts ) {
1023
+
1024
+ const nAr = this._normalsXYZ;
1025
+ const renderNAr = this._renderNormalsXYZ;
1026
+ const faceNormals = this._faceNormals;
1027
+ const ringFaces = this._vertRingFace;
1028
+ const full = iVerts === undefined;
1029
+ const nbVerts = full ? this._nbVertices : iVerts.length;
1030
+
1031
+ for ( let i = 0; i < nbVerts; ++ i ) {
1032
+
1033
+ const ind = full ? i : iVerts[ i ];
1034
+ const vrf = ringFaces[ ind ];
1035
+ let nx = 0, ny = 0, nz = 0;
1036
+ for ( let j = 0, l = vrf.length; j < l; ++ j ) {
1037
+
1038
+ const id = vrf[ j ] * 3;
1039
+ nx += faceNormals[ id ];
1040
+ ny += faceNormals[ id + 1 ];
1041
+ nz += faceNormals[ id + 2 ];
1042
+
1043
+ }
1044
+
1045
+ const inverseCount = vrf.length > 0 ? 1.0 / vrf.length : 0;
1046
+ const ind3 = ind * 3;
1047
+ nx *= inverseCount;
1048
+ ny *= inverseCount;
1049
+ nz *= inverseCount;
1050
+ nAr[ ind3 ] = nx;
1051
+ nAr[ ind3 + 1 ] = ny;
1052
+ nAr[ ind3 + 2 ] = nz;
1053
+
1054
+ const length = Math.sqrt( nx * nx + ny * ny + nz * nz );
1055
+ const invLength = length > 0 ? 1.0 / length : 0;
1056
+ renderNAr[ ind3 ] = nx * invLength;
1057
+ renderNAr[ ind3 + 1 ] = ny * invLength;
1058
+ renderNAr[ ind3 + 2 ] = nz * invLength;
1059
+
1060
+ }
1061
+
1062
+ }
1063
+
1064
+ _updateOctree( iFaces ) {
1065
+
1066
+ if ( iFaces === undefined ) {
1067
+
1068
+ this._computeOctree();
1069
+
1070
+ } else {
1071
+
1072
+ this._updateOctreeAdd( this._updateOctreeRemove( iFaces ) );
1073
+
1074
+ }
1075
+
1076
+ }
1077
+
1078
+ _computeOctree() {
1079
+
1080
+ const vAr = this._verticesXYZ;
1081
+ let xmin = Infinity, ymin = Infinity, zmin = Infinity;
1082
+ let xmax = - Infinity, ymax = - Infinity, zmax = - Infinity;
1083
+
1084
+ for ( let i = 0, l = this._nbVertices * 3; i < l; i += 3 ) {
1085
+
1086
+ if ( vAr[ i ] < xmin ) xmin = vAr[ i ];
1087
+ if ( vAr[ i ] > xmax ) xmax = vAr[ i ];
1088
+ if ( vAr[ i + 1 ] < ymin ) ymin = vAr[ i + 1 ];
1089
+ if ( vAr[ i + 1 ] > ymax ) ymax = vAr[ i + 1 ];
1090
+ if ( vAr[ i + 2 ] < zmin ) zmin = vAr[ i + 2 ];
1091
+ if ( vAr[ i + 2 ] > zmax ) zmax = vAr[ i + 2 ];
1092
+
1093
+ }
1094
+
1095
+ const dx = xmax - xmin;
1096
+ const dy = ymax - ymin;
1097
+ const dz = zmax - zmin;
1098
+ const thickness = Math.hypot( dx, dy, dz ) * 0.2;
1099
+
1100
+ if ( dx === 0 ) {
1101
+
1102
+ xmin -= thickness;
1103
+ xmax += thickness;
1104
+
1105
+ }
1106
+
1107
+ if ( dy === 0 ) {
1108
+
1109
+ ymin -= thickness;
1110
+ ymax += thickness;
1111
+
1112
+ }
1113
+
1114
+ if ( dz === 0 ) {
1115
+
1116
+ zmin -= thickness;
1117
+ zmax += thickness;
1118
+
1119
+ }
1120
+
1121
+ const octree = new OctreeCell();
1122
+ octree.resetNbFaces( this._nbFaces );
1123
+ octree._setAabbLoose( xmin, ymin, zmin, xmax, ymax, zmax );
1124
+ octree._setAabbSplit(
1125
+ xmin - dx * 0.3, ymin - dy * 0.3, zmin - dz * 0.3,
1126
+ xmax + dx * 0.3, ymax + dy * 0.3, zmax + dz * 0.3
1127
+ );
1128
+ octree.build( this );
1129
+
1130
+ this._octree = octree;
1131
+ for ( let i = 0, l = this._leavesToUpdate.length; i < l; i ++ ) this._leavesToUpdate[ i ]._queuedForUpdate = false;
1132
+ this._leavesToUpdate.length = 0;
1133
+
1134
+ }
1135
+
1136
+ _updateOctreeRemove( iFaces ) {
1137
+
1138
+ const faceBoxes = this._faceBoxes;
1139
+ const faceCenters = this._faceCenters;
1140
+ const faceLeaf = this._faceLeaf;
1141
+ const facePosInLeaf = this._facePosInLeaf;
1142
+ const facesToMove = new Uint32Array( getMemory( iFaces.length * 4 ), 0, iFaces.length );
1143
+ let count = 0;
1144
+
1145
+ for ( let i = 0, l = iFaces.length; i < l; ++ i ) {
1146
+
1147
+ const iFace = iFaces[ i ];
1148
+ const leaf = faceLeaf[ iFace ];
1149
+ const idCenter = iFace * 3;
1150
+
1151
+ if ( leaf === undefined || leaf === null ) {
1152
+
1153
+ facesToMove[ count ++ ] = iFace;
1154
+ continue;
1155
+
1156
+ }
1157
+
1158
+ const split = leaf._aabbSplit;
1159
+ const x = faceCenters[ idCenter ];
1160
+ const y = faceCenters[ idCenter + 1 ];
1161
+ const z = faceCenters[ idCenter + 2 ];
1162
+
1163
+ if ( x <= split[ 0 ] || y <= split[ 1 ] || z <= split[ 2 ] || x > split[ 3 ] || y > split[ 4 ] || z > split[ 5 ] ) {
1164
+
1165
+ facesToMove[ count ++ ] = iFace;
1166
+ const facesInLeaf = leaf._iFaces;
1167
+ const position = facePosInLeaf[ iFace ];
1168
+ const lastFace = facesInLeaf[ facesInLeaf.length - 1 ];
1169
+
1170
+ facesInLeaf[ position ] = lastFace;
1171
+ facePosInLeaf[ lastFace ] = position;
1172
+ facesInLeaf.pop();
1173
+ queueLeaf( this._leavesToUpdate, leaf );
1174
+
1175
+ } else {
1176
+
1177
+ const idBox = iFace * 6;
1178
+ leaf._expandAabbLoose(
1179
+ faceBoxes[ idBox ], faceBoxes[ idBox + 1 ], faceBoxes[ idBox + 2 ],
1180
+ faceBoxes[ idBox + 3 ], faceBoxes[ idBox + 4 ], faceBoxes[ idBox + 5 ]
1181
+ );
1182
+
1183
+ }
1184
+
1185
+ }
1186
+
1187
+ return facesToMove.subarray( 0, count );
1188
+
1189
+ }
1190
+
1191
+ _updateOctreeAdd( iFaces ) {
1192
+
1193
+ const faceBoxes = this._faceBoxes;
1194
+ const faceCenters = this._faceCenters;
1195
+ const faceLeaf = this._faceLeaf;
1196
+ const facePosInLeaf = this._facePosInLeaf;
1197
+
1198
+ for ( let i = 0, l = iFaces.length; i < l; ++ i ) {
1199
+
1200
+ const iFace = iFaces[ i ];
1201
+ const idBox = iFace * 6;
1202
+ const idCenter = iFace * 3;
1203
+ const newLeaf = this._octree.addFace(
1204
+ iFace,
1205
+ faceBoxes[ idBox ], faceBoxes[ idBox + 1 ], faceBoxes[ idBox + 2 ],
1206
+ faceBoxes[ idBox + 3 ], faceBoxes[ idBox + 4 ], faceBoxes[ idBox + 5 ],
1207
+ faceCenters[ idCenter ], faceCenters[ idCenter + 1 ], faceCenters[ idCenter + 2 ]
1208
+ );
1209
+
1210
+ if ( newLeaf === undefined ) {
1211
+
1212
+ this._computeOctree();
1213
+ return;
1214
+
1215
+ }
1216
+
1217
+ faceLeaf[ iFace ] = newLeaf;
1218
+ facePosInLeaf[ iFace ] = newLeaf._iFaces.length - 1;
1219
+ queueLeaf( this._leavesToUpdate, newLeaf );
1220
+
1221
+ }
1222
+
1223
+ }
1224
+
1225
+ // Mesh queries
1226
+
1227
+ intersectRay( vNear, eyeDir ) {
1228
+
1229
+ const nbFaces = this._nbFaces;
1230
+ const collectBuffer = new Uint32Array( getMemory( nbFaces * 4 ), 0, nbFaces );
1231
+ return this._octree.collectIntersectRay( vNear, eyeDir, collectBuffer );
1232
+
1233
+ }
1234
+
1235
+ intersectSphere( center, radiusSq, collectLeaves = false ) {
1236
+
1237
+ const nbFaces = this._nbFaces;
1238
+ const collectBuffer = new Uint32Array( getMemory( nbFaces * 4 ), 0, nbFaces );
1239
+ return this._octree.collectIntersectSphere( center, radiusSq, collectBuffer, collectLeaves ? this._leavesToUpdate : undefined );
1240
+
1241
+ }
1242
+
1243
+ getVerticesFromFaces( iFaces ) {
1244
+
1245
+ const tagFlag = this.nextTagFlag();
1246
+ const nbFaces = iFaces.length;
1247
+ const vtf = this._vertTagFlags;
1248
+ const fAr = this._facesABCD;
1249
+ let acc = 0;
1250
+ const verts = new Uint32Array( getMemory( 3 * nbFaces * 4 ), 0, nbFaces * 3 );
1251
+ for ( let i = 0; i < nbFaces; ++ i ) {
1252
+
1253
+ const ind = iFaces[ i ] * 4;
1254
+ const iv1 = fAr[ ind ], iv2 = fAr[ ind + 1 ], iv3 = fAr[ ind + 2 ];
1255
+ if ( vtf[ iv1 ] !== tagFlag ) {
1256
+
1257
+ vtf[ iv1 ] = tagFlag; verts[ acc ++ ] = iv1;
1258
+
1259
+ }
1260
+
1261
+ if ( vtf[ iv2 ] !== tagFlag ) {
1262
+
1263
+ vtf[ iv2 ] = tagFlag; verts[ acc ++ ] = iv2;
1264
+
1265
+ }
1266
+
1267
+ if ( vtf[ iv3 ] !== tagFlag ) {
1268
+
1269
+ vtf[ iv3 ] = tagFlag; verts[ acc ++ ] = iv3;
1270
+
1271
+ }
1272
+
1273
+ }
1274
+
1275
+ return verts.slice( 0, acc );
1276
+
1277
+ }
1278
+
1279
+ getFacesFromVertices( iVerts ) {
1280
+
1281
+ const tagFlag = this.nextTagFlag();
1282
+ const ftf = this._facesTagFlags;
1283
+ const frings = this._vertRingFace;
1284
+ const nbVerts = iVerts.length;
1285
+ const faces = new Uint32Array( getMemory( 4 * this._nbFaces ), 0, this._nbFaces );
1286
+ let acc = 0;
1287
+ for ( let i = 0; i < nbVerts; ++ i ) {
1288
+
1289
+ const fring = frings[ iVerts[ i ] ];
1290
+ for ( let j = 0, l = fring.length; j < l; ++ j ) {
1291
+
1292
+ const iFace = fring[ j ];
1293
+ if ( ftf[ iFace ] !== tagFlag ) {
1294
+
1295
+ ftf[ iFace ] = tagFlag;
1296
+ faces[ acc ++ ] = iFace;
1297
+
1298
+ }
1299
+
1300
+ }
1301
+
1302
+ }
1303
+
1304
+ return faces.slice( 0, acc );
1305
+
1306
+ }
1307
+
1308
+ expandsFaces( iFaces, nRing ) {
1309
+
1310
+ const tagFlag = this.nextTagFlag();
1311
+ let nbFaces = iFaces.length;
1312
+ const ftf = this._facesTagFlags;
1313
+ const fAr = this._facesABCD;
1314
+ const ringFaces = this._vertRingFace;
1315
+ let acc = nbFaces;
1316
+ const iFacesExpanded = new Uint32Array( getMemory( 4 * this._nbFaces ), 0, this._nbFaces );
1317
+ iFacesExpanded.set( iFaces );
1318
+ for ( let i = 0; i < nbFaces; ++ i ) ftf[ iFacesExpanded[ i ] ] = tagFlag;
1319
+ let iBegin = 0;
1320
+ while ( nRing ) {
1321
+
1322
+ -- nRing;
1323
+ for ( let i = iBegin; i < nbFaces; ++ i ) {
1324
+
1325
+ const ind = iFacesExpanded[ i ] * 4;
1326
+ for ( let j = 0; j < 3; ++ j ) {
1327
+
1328
+ const idv = fAr[ ind + j ];
1329
+ const vrf = ringFaces[ idv ];
1330
+ for ( let k = 0, l = vrf.length; k < l; ++ k ) {
1331
+
1332
+ const id = vrf[ k ];
1333
+ if ( ftf[ id ] === tagFlag ) continue;
1334
+ ftf[ id ] = tagFlag;
1335
+ iFacesExpanded[ acc ++ ] = id;
1336
+
1337
+ }
1338
+
1339
+ }
1340
+
1341
+ }
1342
+
1343
+ iBegin = nbFaces;
1344
+ nbFaces = acc;
1345
+
1346
+ }
1347
+
1348
+ return iFacesExpanded.slice( 0, acc );
1349
+
1350
+ }
1351
+
1352
+ expandsVertices( iVerts, nRing ) {
1353
+
1354
+ const tagFlag = this.nextTagFlag();
1355
+ let nbVerts = iVerts.length;
1356
+ const vrings = this._vertRingVert;
1357
+ const vtf = this._vertTagFlags;
1358
+ let acc = nbVerts;
1359
+ const nbVertices = this._nbVertices;
1360
+ const iVertsExpanded = new Uint32Array( getMemory( 4 * nbVertices ), 0, nbVertices );
1361
+ iVertsExpanded.set( iVerts );
1362
+ for ( let i = 0; i < nbVerts; ++ i ) vtf[ iVertsExpanded[ i ] ] = tagFlag;
1363
+ let iBegin = 0;
1364
+ while ( nRing ) {
1365
+
1366
+ -- nRing;
1367
+ for ( let i = iBegin; i < nbVerts; ++ i ) {
1368
+
1369
+ const ring = vrings[ iVertsExpanded[ i ] ];
1370
+ for ( let j = 0, l = ring.length; j < l; ++ j ) {
1371
+
1372
+ const id = ring[ j ];
1373
+ if ( vtf[ id ] === tagFlag ) continue;
1374
+ vtf[ id ] = tagFlag;
1375
+ iVertsExpanded[ acc ++ ] = id;
1376
+
1377
+ }
1378
+
1379
+ }
1380
+
1381
+ iBegin = nbVerts;
1382
+ nbVerts = acc;
1383
+
1384
+ }
1385
+
1386
+ return iVertsExpanded.slice( 0, acc );
1387
+
1388
+ }
1389
+
1390
+ // Dynamic topology
1391
+
1392
+ updateRenderTriangles( iFaces ) {
1393
+
1394
+ const tAr = this._trianglesABC;
1395
+ const fAr = this._facesABCD;
1396
+ const full = iFaces === undefined;
1397
+ const nbFaces = full ? this._nbFaces : iFaces.length;
1398
+ for ( let i = 0; i < nbFaces; ++ i ) {
1399
+
1400
+ const id = full ? i : iFaces[ i ];
1401
+ const idt = id * 3;
1402
+ const idf = id * 4;
1403
+ tAr[ idt ] = fAr[ idf ];
1404
+ tAr[ idt + 1 ] = fAr[ idf + 1 ];
1405
+ tAr[ idt + 2 ] = fAr[ idf + 2 ];
1406
+
1407
+ }
1408
+
1409
+ }
1410
+
1411
+ updateVerticesOnEdge( iVerts ) {
1412
+
1413
+ const vOnEdge = this._vertOnEdge;
1414
+ const vrings = this._vertRingVert;
1415
+ const frings = this._vertRingFace;
1416
+ const full = iVerts === undefined;
1417
+ const nbVerts = full ? this._nbVertices : iVerts.length;
1418
+ for ( let i = 0; i < nbVerts; ++ i ) {
1419
+
1420
+ const id = full ? i : iVerts[ i ];
1421
+ vOnEdge[ id ] = vrings[ id ].length !== frings[ id ].length ? 1 : 0;
1422
+
1423
+ }
1424
+
1425
+ }
1426
+
1427
+ updateTopology( iFaces, iVerts ) {
1428
+
1429
+ this.updateRenderTriangles( iFaces );
1430
+ this.updateVerticesOnEdge( iVerts );
1431
+
1432
+ }
1433
+
1434
+ _resizeArray( array, requiredLength ) {
1435
+
1436
+ if ( array === null ) return null;
1437
+
1438
+ const resized = new array.constructor( requiredLength * 2 );
1439
+ resized.set( array.subarray( 0, Math.min( array.length, resized.length ) ) );
1440
+ return resized;
1441
+
1442
+ }
1443
+
1444
+ reAllocateArrays( nbAddElements ) {
1445
+
1446
+ let capacity = this._facesABCD.length / 4;
1447
+ let requiredCount = this._nbFaces + nbAddElements;
1448
+
1449
+ if ( capacity < requiredCount || capacity > requiredCount * 4 ) {
1450
+
1451
+ this._facesABCD = this._resizeArray( this._facesABCD, requiredCount * 4 );
1452
+ this._trianglesABC = this._resizeArray( this._trianglesABC, requiredCount * 3 );
1453
+ this._faceBoxes = this._resizeArray( this._faceBoxes, requiredCount * 6 );
1454
+ this._faceNormals = this._resizeArray( this._faceNormals, requiredCount * 3 );
1455
+ this._faceCenters = this._resizeArray( this._faceCenters, requiredCount * 3 );
1456
+ this._facesTagFlags = this._resizeArray( this._facesTagFlags, requiredCount );
1457
+ this._facePosInLeaf = this._resizeArray( this._facePosInLeaf, requiredCount );
1458
+
1459
+ }
1460
+
1461
+ capacity = this._verticesXYZ.length / 3;
1462
+ requiredCount = this._nbVertices + nbAddElements;
1463
+
1464
+ if ( capacity < requiredCount || capacity > requiredCount * 4 ) {
1465
+
1466
+ this._verticesXYZ = this._resizeArray( this._verticesXYZ, requiredCount * 3 );
1467
+ this._normalsXYZ = this._resizeArray( this._normalsXYZ, requiredCount * 3 );
1468
+ this._renderNormalsXYZ = this._resizeArray( this._renderNormalsXYZ, requiredCount * 3 );
1469
+ this._vertOnEdge = this._resizeArray( this._vertOnEdge, requiredCount );
1470
+ this._vertTagFlags = this._resizeArray( this._vertTagFlags, requiredCount );
1471
+ this._vertSculptFlags = this._resizeArray( this._vertSculptFlags, requiredCount );
1472
+
1473
+ }
1474
+
1475
+ }
1476
+
1477
+ balanceOctree() {
1478
+
1479
+ const leaves = this._leavesToUpdate;
1480
+
1481
+ for ( let i = 0, l = leaves.length; i < l; ++ i ) {
1482
+
1483
+ const leaf = leaves[ i ];
1484
+ leaf._queuedForUpdate = false;
1485
+
1486
+ if ( leaf._iFaces.length === 0 ) {
1487
+
1488
+ leaf.pruneIfPossible();
1489
+
1490
+ } else if ( leaf._iFaces.length > OCTREE_MAX_FACES && leaf._depth < OCTREE_MAX_DEPTH ) {
1491
+
1492
+ leaf.build( this );
1493
+
1494
+ }
1495
+
1496
+ }
1497
+
1498
+ leaves.length = 0;
1499
+
1500
+ }
1501
+
1502
+ }
1503
+
1504
+ export { SculptorMesh };