@unikia/upe-renderer 0.186.110 → 0.187.11

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 (506) hide show
  1. package/README.md +5 -7
  2. package/UPSTREAM.md +4 -4
  3. package/build/three.core.js +853 -277
  4. package/build/three.module.js +1098 -1280
  5. package/build/three.tsl.js +41938 -686
  6. package/build/three.webgpu.js +10604 -49055
  7. package/build/three.webgpu.nodes.js +9249 -5788
  8. package/examples/jsm/Addons.js +2 -0
  9. package/examples/jsm/animation/CCDIKSolver.js +17 -5
  10. package/examples/jsm/controls/FirstPersonControls.js +1 -1
  11. package/examples/jsm/controls/OrbitControls.js +27 -14
  12. package/examples/jsm/csm/CSMShader.js +74 -3
  13. package/examples/jsm/curves/CurveExtras.js +4 -4
  14. package/examples/jsm/curves/NURBSCurve.js +14 -0
  15. package/examples/jsm/exporters/EXRExporter.js +673 -16
  16. package/examples/jsm/exporters/GLTFExporter.js +4 -4
  17. package/examples/jsm/exporters/KTX2Exporter.js +1 -1
  18. package/examples/jsm/exporters/OBJExporter.js +48 -5
  19. package/examples/jsm/exporters/PLYExporter.js +22 -11
  20. package/examples/jsm/generators/CityGenerator.js +3 -2
  21. package/examples/jsm/generators/city/SkyscraperGenerator.js +63 -21
  22. package/examples/jsm/gpgpu/BitonicSort.js +30 -23
  23. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -1
  24. package/examples/jsm/inspector/Extension.js +1 -1
  25. package/examples/jsm/inspector/Inspector.js +6 -46
  26. package/examples/jsm/inspector/RendererInspector.js +43 -8
  27. package/examples/jsm/inspector/Storage.js +49 -0
  28. package/examples/jsm/inspector/extensions/color-grading/ColorGrading.js +32 -27
  29. package/examples/jsm/inspector/tabs/Parameters.js +5 -1
  30. package/examples/jsm/inspector/tabs/Performance.js +22 -7
  31. package/examples/jsm/inspector/tabs/Settings.js +1 -1
  32. package/examples/jsm/inspector/tabs/Timeline.js +83 -7
  33. package/examples/jsm/inspector/tabs/Viewer.js +25 -10
  34. package/examples/jsm/inspector/ui/Profiler.js +1 -1
  35. package/examples/jsm/inspector/ui/Style.js +21 -53
  36. package/examples/jsm/inspector/ui/Values.js +28 -3
  37. package/examples/jsm/libs/fflate.module.js +83 -56
  38. package/examples/jsm/libs/mikktspace.README.md +27 -0
  39. package/examples/jsm/libs/mikktspace.module.js +721 -109
  40. package/examples/jsm/lighting/ClusteredLighting.js +100 -2
  41. package/examples/jsm/lighting/LightMapper.js +295 -0
  42. package/examples/jsm/lighting/LightProbeGrid.js +242 -139
  43. package/examples/jsm/lighting/LightProbeGridWebGL.js +30 -14
  44. package/examples/jsm/lighting/vxgi/VXGIConeTracer.js +54 -5
  45. package/examples/jsm/lighting/vxgi/VXGIIrradiance.js +43 -0
  46. package/examples/jsm/lighting/vxgi/VXGINode.js +13 -56
  47. package/examples/jsm/lighting/vxgi/VXGISceneCollector.js +316 -1
  48. package/examples/jsm/lighting/vxgi/VXGIVolume.js +69 -59
  49. package/examples/jsm/lights/SunLight.js +9 -4
  50. package/examples/jsm/lights/SunLightNode.js +3 -3
  51. package/examples/jsm/lines/LineMaterial.js +26 -10
  52. package/examples/jsm/loaders/3DMLoader.js +10 -1
  53. package/examples/jsm/loaders/3MFLoader.js +5 -1
  54. package/examples/jsm/loaders/AMFLoader.js +2 -0
  55. package/examples/jsm/loaders/BVHLoader.js +2 -0
  56. package/examples/jsm/loaders/ColladaLoader.js +8 -0
  57. package/examples/jsm/loaders/DDSLoader.js +1 -1
  58. package/examples/jsm/loaders/DRACOLoader.js +5 -1
  59. package/examples/jsm/loaders/EXRLoader.js +120 -104
  60. package/examples/jsm/loaders/FBXLoader.js +4 -0
  61. package/examples/jsm/loaders/FontLoader.js +2 -0
  62. package/examples/jsm/loaders/GCodeLoader.js +5 -9
  63. package/examples/jsm/loaders/GLTFLoader.js +112 -31
  64. package/examples/jsm/loaders/GaussianSplatPLYLoader.js +2 -0
  65. package/examples/jsm/loaders/HDRCubeTextureLoader.js +3 -0
  66. package/examples/jsm/loaders/IESLoader.js +46 -12
  67. package/examples/jsm/loaders/JXLLoader.js +159 -0
  68. package/examples/jsm/loaders/KMZLoader.js +6 -0
  69. package/examples/jsm/loaders/KSPLATLoader.js +2 -0
  70. package/examples/jsm/loaders/KTX2Loader.js +49 -4
  71. package/examples/jsm/loaders/KTXLoader.js +5 -3
  72. package/examples/jsm/loaders/LDrawLoader.js +15 -22
  73. package/examples/jsm/loaders/LUT3dlLoader.js +5 -1
  74. package/examples/jsm/loaders/LUTCubeLoader.js +6 -2
  75. package/examples/jsm/loaders/LUTImageLoader.js +2 -0
  76. package/examples/jsm/loaders/LWOLoader.js +6 -0
  77. package/examples/jsm/loaders/MD2Loader.js +2 -0
  78. package/examples/jsm/loaders/MDDLoader.js +4 -0
  79. package/examples/jsm/loaders/MTLLoader.js +8 -0
  80. package/examples/jsm/loaders/MaterialXLoader.js +57 -5
  81. package/examples/jsm/loaders/NRRDLoader.js +4 -2
  82. package/examples/jsm/loaders/OBJLoader.js +10 -4
  83. package/examples/jsm/loaders/PCDLoader.js +6 -2
  84. package/examples/jsm/loaders/PDBLoader.js +5 -3
  85. package/examples/jsm/loaders/PLYLoader.js +39 -15
  86. package/examples/jsm/loaders/PVRLoader.js +2 -2
  87. package/examples/jsm/loaders/SPLATLoader.js +2 -0
  88. package/examples/jsm/loaders/SPZLoader.js +2 -0
  89. package/examples/jsm/loaders/STLLoader.js +3 -1
  90. package/examples/jsm/loaders/SVGLoader.js +27 -49
  91. package/examples/jsm/loaders/TDSLoader.js +4 -0
  92. package/examples/jsm/loaders/TGALoader.js +6 -5
  93. package/examples/jsm/loaders/TTFLoader.js +2 -0
  94. package/examples/jsm/loaders/USDLoader.js +14 -0
  95. package/examples/jsm/loaders/UltraHDRLoader.js +2 -0
  96. package/examples/jsm/loaders/VOXLoader.js +3 -0
  97. package/examples/jsm/loaders/VRMLLoader.js +4 -0
  98. package/examples/jsm/loaders/VTKLoader.js +2 -0
  99. package/examples/jsm/loaders/XYZLoader.js +2 -0
  100. package/examples/jsm/loaders/collada/ColladaComposer.js +15 -8
  101. package/examples/jsm/loaders/materialx/MaterialXDocument.js +610 -138
  102. package/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js +12 -95
  103. package/examples/jsm/loaders/materialx/MaterialXLog.js +4 -0
  104. package/examples/jsm/loaders/materialx/MaterialXNodeDefs.js +99 -0
  105. package/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js +760 -1
  106. package/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js +222 -372
  107. package/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js +163 -259
  108. package/examples/jsm/loaders/materialx/MaterialXUtils.js +25 -0
  109. package/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js +161 -159
  110. package/examples/jsm/loaders/usd/USDAParser.js +56 -47
  111. package/examples/jsm/loaders/usd/USDComposer.js +25 -30
  112. package/examples/jsm/math/ColorConverter.js +7 -3
  113. package/examples/jsm/math/Lut.js +2 -2
  114. package/examples/jsm/math/OBB.js +3 -3
  115. package/examples/jsm/math/Octree.js +20 -17
  116. package/examples/jsm/objects/GaussianSplat.js +5 -4
  117. package/examples/jsm/objects/Reflector.js +5 -0
  118. package/examples/jsm/objects/SkyMesh.js +14 -7
  119. package/examples/jsm/objects/Water2Mesh.js +2 -2
  120. package/examples/jsm/physics/RapierPhysics.js +2 -2
  121. package/examples/jsm/pipelines/MeshletDrawingPipeline.js +5571 -0
  122. package/examples/jsm/pipelines/VisibilityBufferDrawingPipeline.js +954 -0
  123. package/examples/jsm/postprocessing/BokehPass.js +1 -1
  124. package/examples/jsm/postprocessing/GTAOPass.js +26 -18
  125. package/examples/jsm/renderers/SVGRenderer.js +3 -2
  126. package/examples/jsm/shaders/GTAOShader.js +7 -4
  127. package/examples/jsm/shaders/PoissonDenoiseShader.js +1 -10
  128. package/examples/jsm/tsl/WebGLNodesHandler.js +21 -9
  129. package/examples/jsm/tsl/display/AfterImageNode.js +3 -3
  130. package/examples/jsm/tsl/display/BilateralBlurNode.js +3 -3
  131. package/examples/jsm/tsl/display/BloomNode.js +3 -3
  132. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +8 -19
  133. package/examples/jsm/tsl/display/DenoiseNode.js +5 -5
  134. package/examples/jsm/tsl/display/DepthOfFieldNode.js +3 -3
  135. package/examples/jsm/tsl/display/DotScreenNode.js +3 -3
  136. package/examples/jsm/tsl/display/FSR1Node.js +3 -3
  137. package/examples/jsm/tsl/display/FXAANode.js +3 -10
  138. package/examples/jsm/tsl/display/FilmNode.js +3 -3
  139. package/examples/jsm/tsl/display/GTAONode.js +33 -25
  140. package/examples/jsm/tsl/display/GaussianBlurNode.js +3 -3
  141. package/examples/jsm/tsl/display/GodraysNode.js +5 -19
  142. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +8 -4
  143. package/examples/jsm/tsl/display/LensflareNode.js +3 -3
  144. package/examples/jsm/tsl/display/Lut3DNode.js +3 -3
  145. package/examples/jsm/tsl/display/OITPassNode.js +0 -11
  146. package/examples/jsm/tsl/display/OutlineNode.js +107 -5
  147. package/examples/jsm/tsl/display/PixelationPassNode.js +85 -193
  148. package/examples/jsm/tsl/display/RGBShiftNode.js +3 -3
  149. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +23 -126
  150. package/examples/jsm/tsl/display/SMAANode.js +3 -3
  151. package/examples/jsm/tsl/display/SSAONode.js +6 -20
  152. package/examples/jsm/tsl/display/SSGINode.js +36 -29
  153. package/examples/jsm/tsl/display/SSRNode.js +135 -63
  154. package/examples/jsm/tsl/display/SSSNode.js +6 -20
  155. package/examples/jsm/tsl/display/SharpenNode.js +3 -3
  156. package/examples/jsm/tsl/display/SobelOperatorNode.js +3 -3
  157. package/examples/jsm/tsl/display/TAAUNode.js +10 -42
  158. package/examples/jsm/tsl/display/TRAANode.js +11 -43
  159. package/examples/jsm/tsl/display/TemporalReprojectNode.js +42 -47
  160. package/examples/jsm/tsl/display/TransitionNode.js +3 -3
  161. package/examples/jsm/tsl/display/lensDirt.js +30 -0
  162. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +482 -121
  163. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +41 -140
  164. package/examples/jsm/tsl/lighting/LightProbeGridNode.js +72 -25
  165. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +6 -0
  166. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +6 -0
  167. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +6 -0
  168. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +6 -0
  169. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +6 -0
  170. package/examples/jsm/tsl/shadows/TileShadowNode.js +102 -14
  171. package/examples/jsm/tsl/utils/Raymarching.js +1 -1
  172. package/examples/jsm/tsl/utils/SoftParticles.js +5 -12
  173. package/examples/jsm/tsl/utils/SpecularHelpers.js +47 -70
  174. package/examples/jsm/tsl/utils/TAAUtils.js +6 -17
  175. package/examples/jsm/utils/BufferGeometryUtils.js +110 -88
  176. package/examples/jsm/utils/MeshletGeometryUtils.js +417 -0
  177. package/examples/jsm/utils/SceneOptimizer.js +2 -1
  178. package/examples/jsm/utils/SceneUtils.js +1 -1
  179. package/examples/jsm/utils/unwrapUVs.js +865 -0
  180. package/examples/jsm/webxr/XREstimatedLight.js +11 -4
  181. package/package.json +3 -3
  182. package/src/Three.TSL.js +2 -683
  183. package/src/Three.WebGPU.Nodes.js +2 -1
  184. package/src/Three.WebGPU.js +2 -1
  185. package/src/animation/AnimationAction.js +1 -1
  186. package/src/animation/AnimationUtils.js +1 -3
  187. package/src/animation/KeyframeTrack.js +19 -0
  188. package/src/cameras/ArrayCamera.js +12 -0
  189. package/src/cameras/CubeCamera.js +3 -3
  190. package/src/constants.js +1 -9
  191. package/src/core/BufferAttribute.js +57 -21
  192. package/src/core/BufferGeometry.js +5 -13
  193. package/src/core/Clock.js +1 -1
  194. package/src/core/InterleavedBuffer.js +28 -18
  195. package/src/core/InterleavedBufferAttribute.js +54 -20
  196. package/src/core/Object3D.js +19 -9
  197. package/src/core/Raycaster.js +2 -0
  198. package/src/core/RenderTarget.js +11 -5
  199. package/src/core/UniformsGroup.js +7 -3
  200. package/src/extras/PMREMGenerator.js +392 -685
  201. package/src/extras/core/Curve.js +4 -0
  202. package/src/extras/core/CurvePath.js +13 -0
  203. package/src/extras/core/ShapePath.js +1 -1
  204. package/src/geometries/EdgesGeometry.js +12 -10
  205. package/src/geometries/LatheGeometry.js +2 -0
  206. package/src/helpers/PolarGridHelper.js +1 -1
  207. package/src/lights/Light.js +11 -0
  208. package/src/lights/LightProbe.js +2 -0
  209. package/src/lights/LightShadow.js +2 -0
  210. package/src/loaders/AnimationLoader.js +2 -0
  211. package/src/loaders/AudioLoader.js +2 -0
  212. package/src/loaders/BufferGeometryLoader.js +2 -0
  213. package/src/loaders/CompressedTextureLoader.js +2 -0
  214. package/src/loaders/CubeTextureLoader.js +2 -0
  215. package/src/loaders/DataTextureLoader.js +2 -0
  216. package/src/loaders/FileLoader.js +2 -0
  217. package/src/loaders/ImageBitmapLoader.js +3 -1
  218. package/src/loaders/ImageLoader.js +1 -0
  219. package/src/loaders/Loader.js +47 -0
  220. package/src/loaders/MaterialLoader.js +2 -0
  221. package/src/loaders/ObjectLoader.js +27 -8
  222. package/src/loaders/TextureLoader.js +5 -3
  223. package/src/loaders/nodes/NodeLoader.js +2 -0
  224. package/src/materials/Material.js +21 -2
  225. package/src/materials/MeshDepthMaterial.js +1 -1
  226. package/src/materials/MeshDistanceMaterial.js +1 -1
  227. package/src/materials/MeshLambertMaterial.js +1 -1
  228. package/src/materials/MeshMatcapMaterial.js +1 -1
  229. package/src/materials/MeshNormalMaterial.js +1 -1
  230. package/src/materials/MeshPhongMaterial.js +1 -1
  231. package/src/materials/MeshPhysicalMaterial.js +90 -11
  232. package/src/materials/MeshStandardMaterial.js +1 -1
  233. package/src/materials/MeshToonMaterial.js +1 -1
  234. package/src/materials/nodes/Line2NodeMaterial.js +32 -10
  235. package/src/materials/nodes/MeshLambertNodeMaterial.js +13 -0
  236. package/src/materials/nodes/MeshPhongNodeMaterial.js +13 -0
  237. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +40 -5
  238. package/src/materials/nodes/MeshToonNodeMaterial.js +13 -0
  239. package/src/materials/nodes/NodeMaterial.js +36 -16
  240. package/src/materials/nodes/NodeMaterialInstance.js +193 -0
  241. package/src/materials/nodes/NodeMaterials.js +1 -0
  242. package/src/materials/nodes/PointsNodeMaterial.js +1 -1
  243. package/src/materials/nodes/SpriteNodeMaterial.js +3 -3
  244. package/src/materials/nodes/manager/NodeMaterialObserver.js +191 -22
  245. package/src/math/Box3.js +2 -2
  246. package/src/math/Color.js +8 -8
  247. package/src/math/ColorManagement.js +2 -21
  248. package/src/math/FrustumArray.js +12 -0
  249. package/src/math/Interpolant.js +1 -1
  250. package/src/math/Line3.js +2 -4
  251. package/src/math/MathUtils.js +33 -46
  252. package/src/math/Matrix2.js +1 -1
  253. package/src/math/Matrix3.js +1 -1
  254. package/src/math/Matrix4.js +1 -1
  255. package/src/math/Triangle.js +2 -1
  256. package/src/math/Vector2.js +1 -1
  257. package/src/math/Vector3.js +1 -1
  258. package/src/math/Vector4.js +1 -1
  259. package/src/nodes/Nodes.js +1 -0
  260. package/src/nodes/TSL.js +2 -0
  261. package/src/nodes/accessors/Arrays.js +1 -1
  262. package/src/nodes/accessors/Batch.js +29 -23
  263. package/src/nodes/accessors/BufferAttributeNode.js +21 -1
  264. package/src/nodes/accessors/BuiltinNode.js +6 -0
  265. package/src/nodes/accessors/Camera.js +100 -93
  266. package/src/nodes/accessors/ClippingNode.js +17 -6
  267. package/src/nodes/accessors/CubeTextureNode.js +12 -24
  268. package/src/nodes/accessors/Instance.js +198 -160
  269. package/src/nodes/accessors/Lights.js +19 -6
  270. package/src/nodes/accessors/MaterialNode.js +33 -4
  271. package/src/nodes/accessors/Morph.js +81 -22
  272. package/src/nodes/accessors/Normal.js +0 -42
  273. package/src/nodes/accessors/Object3DNode.js +6 -0
  274. package/src/nodes/accessors/PointUVNode.js +6 -0
  275. package/src/nodes/accessors/ReferenceAttributeNode.js +279 -0
  276. package/src/nodes/accessors/ReferenceBaseNode.js +6 -0
  277. package/src/nodes/accessors/ReferenceNode.js +6 -0
  278. package/src/nodes/accessors/Skinning.js +57 -52
  279. package/src/nodes/accessors/StorageBufferNode.js +3 -12
  280. package/src/nodes/accessors/TextureBicubic.js +30 -27
  281. package/src/nodes/accessors/TextureNode.js +164 -78
  282. package/src/nodes/accessors/TextureSizeNode.js +6 -0
  283. package/src/nodes/accessors/UniformArrayNode.js +8 -15
  284. package/src/nodes/accessors/VelocityNode.js +13 -8
  285. package/src/nodes/code/CodeNode.js +6 -0
  286. package/src/nodes/code/ExpressionNode.js +6 -0
  287. package/src/nodes/code/FunctionCallNode.js +3 -3
  288. package/src/nodes/code/FunctionNode.js +15 -13
  289. package/src/nodes/core/ArrayNode.js +3 -3
  290. package/src/nodes/core/AssignNode.js +10 -9
  291. package/src/nodes/core/AttributeNode.js +39 -0
  292. package/src/nodes/core/BypassNode.js +6 -0
  293. package/src/nodes/core/ConstNode.js +31 -1
  294. package/src/nodes/core/ContextNode.js +11 -6
  295. package/src/nodes/core/IndexNode.js +6 -0
  296. package/src/nodes/core/InputNode.js +6 -0
  297. package/src/nodes/core/InspectorNode.js +17 -31
  298. package/src/nodes/core/IsolateNode.js +8 -0
  299. package/src/nodes/core/Node.js +367 -67
  300. package/src/nodes/core/NodeBuilder.js +664 -222
  301. package/src/nodes/core/NodeUtils.js +25 -0
  302. package/src/nodes/core/NodeVar.js +10 -1
  303. package/src/nodes/core/OutputStructNode.js +6 -0
  304. package/src/nodes/core/OverrideContextNode.js +38 -37
  305. package/src/nodes/core/PropertyNode.js +14 -0
  306. package/src/nodes/core/StackNode.js +33 -21
  307. package/src/nodes/core/StructNode.js +6 -0
  308. package/src/nodes/core/StructTypeNode.js +6 -0
  309. package/src/nodes/core/SubBuildNode.js +8 -0
  310. package/src/nodes/core/TempNode.js +10 -35
  311. package/src/nodes/core/UniformGroupNode.js +6 -0
  312. package/src/nodes/core/VarNode.js +43 -135
  313. package/src/nodes/core/VaryingNode.js +33 -2
  314. package/src/nodes/display/BlendModes.js +5 -40
  315. package/src/nodes/display/BumpMapNode.js +17 -7
  316. package/src/nodes/display/ColorAdjustment.js +22 -10
  317. package/src/nodes/display/ColorSpaceFunctions.js +2 -14
  318. package/src/nodes/display/ColorSpaceNode.js +3 -3
  319. package/src/nodes/display/FrontFacingNode.js +6 -0
  320. package/src/nodes/display/NormalMapNode.js +3 -3
  321. package/src/nodes/display/PassNode.js +75 -16
  322. package/src/nodes/display/RenderOutputNode.js +22 -5
  323. package/src/nodes/display/ScreenNode.js +6 -0
  324. package/src/nodes/display/ToneMappingFunctions.js +9 -51
  325. package/src/nodes/display/ToneMappingNode.js +3 -3
  326. package/src/nodes/display/ToonOutlinePassNode.js +66 -2
  327. package/src/nodes/display/ViewportDepthNode.js +34 -4
  328. package/src/nodes/functions/BSDF/BRDF_EON.js +65 -0
  329. package/src/nodes/functions/BSDF/BRDF_GGX.js +5 -3
  330. package/src/nodes/functions/BSDF/BRDF_Sheen.js +2 -16
  331. package/src/nodes/functions/BSDF/D_GGX.js +1 -8
  332. package/src/nodes/functions/BSDF/D_GGX_Anisotropic.js +7 -10
  333. package/src/nodes/functions/BSDF/LTC.js +20 -47
  334. package/src/nodes/functions/BSDF/Schlick_to_F0.js +1 -9
  335. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -9
  336. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +10 -13
  337. package/src/nodes/functions/PhysicalLightingModel.js +84 -51
  338. package/src/nodes/functions/VolumetricLightingModel.js +1 -1
  339. package/src/nodes/functions/material/getAlphaHashThreshold.js +3 -9
  340. package/src/nodes/functions/material/getParallaxCorrectNormal.js +10 -11
  341. package/src/nodes/functions/material/getRoughness.js +3 -1
  342. package/src/nodes/geometry/RangeNode.js +52 -69
  343. package/src/nodes/gpgpu/AtomicFunctionNode.js +11 -6
  344. package/src/nodes/gpgpu/BarrierNode.js +6 -0
  345. package/src/nodes/gpgpu/ComputeBuiltinNode.js +6 -0
  346. package/src/nodes/gpgpu/ComputeNode.js +6 -0
  347. package/src/nodes/gpgpu/SubgroupFunctionNode.js +38 -29
  348. package/src/nodes/gpgpu/WorkgroupInfoNode.js +6 -0
  349. package/src/nodes/lighting/AnalyticLightNode.js +7 -14
  350. package/src/nodes/lighting/BasicEnvironmentNode.js +5 -1
  351. package/src/nodes/lighting/EnvironmentNode.js +58 -8
  352. package/src/nodes/lighting/IESSpotLightNode.js +19 -4
  353. package/src/nodes/lighting/LightProbeNode.js +2 -1
  354. package/src/nodes/lighting/LightUtils.js +2 -2
  355. package/src/nodes/lighting/LightingNode.js +6 -0
  356. package/src/nodes/lighting/LightsNode.js +26 -32
  357. package/src/nodes/lighting/PointShadowNode.js +92 -48
  358. package/src/nodes/lighting/ProjectorLightNode.js +1 -1
  359. package/src/nodes/lighting/RectAreaLightNode.js +13 -14
  360. package/src/nodes/lighting/ShadowBaseNode.js +9 -17
  361. package/src/nodes/lighting/ShadowFilterNode.js +26 -3
  362. package/src/nodes/lighting/ShadowNode.js +13 -11
  363. package/src/nodes/materialx/MaterialXColor.js +2 -14
  364. package/src/nodes/materialx/MaterialXColorTransform.js +1 -7
  365. package/src/nodes/materialx/MaterialXNodes.js +8 -11
  366. package/src/nodes/materialx/MaterialXNoise.js +195 -454
  367. package/src/nodes/math/BitcastNode.js +5 -5
  368. package/src/nodes/math/BitcountNode.js +18 -46
  369. package/src/nodes/math/ConditionalNode.js +92 -22
  370. package/src/nodes/math/Hash.js +1 -1
  371. package/src/nodes/math/MathNode.js +86 -64
  372. package/src/nodes/math/MathUtils.js +2 -2
  373. package/src/nodes/math/OperatorNode.js +42 -59
  374. package/src/nodes/math/PackFloatNode.js +9 -9
  375. package/src/nodes/math/Packed4x8IntegerNode.js +20 -52
  376. package/src/nodes/math/TriNoise3D.js +3 -23
  377. package/src/nodes/math/UnpackFloatNode.js +9 -9
  378. package/src/nodes/pmrem/PMREMNode.js +38 -75
  379. package/src/nodes/pmrem/PMREMUtils.js +108 -272
  380. package/src/nodes/procedural/Checker.js +1 -1
  381. package/src/nodes/tsl/TSLCore.js +199 -74
  382. package/src/nodes/utils/ArrayElementNode.js +19 -1
  383. package/src/nodes/utils/CubeMapNode.js +3 -3
  384. package/src/nodes/utils/DebugNode.js +2 -2
  385. package/src/nodes/utils/EventNode.js +6 -0
  386. package/src/nodes/utils/FlipNode.js +3 -3
  387. package/src/nodes/utils/FunctionOverloadingNode.js +7 -1
  388. package/src/nodes/utils/JoinNode.js +3 -3
  389. package/src/nodes/utils/LoopNode.js +14 -9
  390. package/src/nodes/utils/MemberNode.js +18 -0
  391. package/src/nodes/utils/PostProcessingUtils.js +20 -25
  392. package/src/nodes/utils/RTTNode.js +2 -0
  393. package/src/nodes/utils/ReflectorNode.js +24 -0
  394. package/src/nodes/utils/RotateNode.js +3 -3
  395. package/src/nodes/utils/SampleNode.js +6 -0
  396. package/src/nodes/utils/SetNode.js +3 -3
  397. package/src/nodes/utils/SplitNode.js +6 -0
  398. package/src/nodes/utils/UVUtils.js +2 -2
  399. package/src/objects/BatchedMesh.js +146 -15
  400. package/src/objects/InstancedMesh.js +12 -4
  401. package/src/objects/Line.js +20 -0
  402. package/src/objects/Mesh.js +8 -0
  403. package/src/objects/Points.js +20 -0
  404. package/src/objects/Skeleton.js +26 -0
  405. package/src/objects/SkinnedMesh.js +3 -3
  406. package/src/objects/Sprite.js +10 -0
  407. package/src/renderers/WebGLRenderer.js +104 -70
  408. package/src/renderers/common/Animation.js +5 -1
  409. package/src/renderers/common/Attributes.js +67 -57
  410. package/src/renderers/common/Backend.js +78 -3
  411. package/src/renderers/common/BindGroup.js +11 -0
  412. package/src/renderers/common/Binding.js +0 -11
  413. package/src/renderers/common/Bindings.js +116 -10
  414. package/src/renderers/common/Buffer.js +1 -1
  415. package/src/renderers/common/ClippingContext.js +12 -1
  416. package/src/renderers/common/ComputePipeline.js +17 -1
  417. package/src/renderers/common/DirectRenderPipeline.js +7 -3
  418. package/src/renderers/common/Geometries.js +170 -132
  419. package/src/renderers/common/Info.js +1 -1
  420. package/src/renderers/common/InspectorBase.js +5 -5
  421. package/src/renderers/common/Lighting.js +59 -0
  422. package/src/renderers/common/Pipelines.js +26 -12
  423. package/src/renderers/common/ProgrammableStage.js +1 -17
  424. package/src/renderers/common/RenderContext.js +21 -0
  425. package/src/renderers/common/RenderContexts.js +13 -4
  426. package/src/renderers/common/RenderObject.js +111 -35
  427. package/src/renderers/common/RenderObjects.js +37 -19
  428. package/src/renderers/common/Renderer.js +537 -295
  429. package/src/renderers/common/RendererUtils.js +15 -0
  430. package/src/renderers/common/StandardDrawingPipeline.js +343 -0
  431. package/src/renderers/common/Storage3DTexture.js +11 -0
  432. package/src/renderers/common/StorageArrayTexture.js +10 -0
  433. package/src/renderers/common/StorageTexture.js +0 -9
  434. package/src/renderers/common/Textures.js +144 -37
  435. package/src/renderers/common/UniformsGroup.js +19 -0
  436. package/src/renderers/common/XRManager.js +10 -91
  437. package/src/renderers/common/extras/PMREMGenerator.js +298 -576
  438. package/src/renderers/common/nodes/NodeBuilderState.js +7 -5
  439. package/src/renderers/common/nodes/NodeLibrary.js +11 -35
  440. package/src/renderers/common/nodes/NodeManager.js +80 -31
  441. package/src/renderers/common/nodes/NodeSampledTexture.js +14 -0
  442. package/src/renderers/common/nodes/NodeSampler.js +14 -0
  443. package/src/renderers/common/nodes/NodeStorageBuffer.js +1 -1
  444. package/src/renderers/common/nodes/NodeUniformBuffer.js +1 -14
  445. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +13 -4
  446. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +8 -8
  447. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +23 -11
  448. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +21 -2
  449. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -1
  450. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +18 -2
  451. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +104 -7
  452. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +11 -2
  453. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +36 -20
  454. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +5 -0
  455. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +6 -0
  456. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +5 -0
  457. package/src/renderers/shaders/ShaderChunk.js +0 -2
  458. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +4 -18
  459. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
  460. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  461. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +8 -1
  462. package/src/renderers/shaders/ShaderLib.js +3 -0
  463. package/src/renderers/shaders/UniformsLib.js +4 -5
  464. package/src/renderers/webgl/WebGLBackground.js +3 -3
  465. package/src/renderers/webgl/WebGLBindingStates.js +4 -2
  466. package/src/renderers/webgl/WebGLCapabilities.js +7 -1
  467. package/src/renderers/webgl/WebGLEnvironments.js +2 -2
  468. package/src/renderers/webgl/WebGLGeometries.js +42 -14
  469. package/src/renderers/webgl/WebGLMaterials.js +15 -2
  470. package/src/renderers/webgl/WebGLOutput.js +37 -1
  471. package/src/renderers/webgl/WebGLProgram.js +13 -54
  472. package/src/renderers/webgl/WebGLPrograms.js +22 -8
  473. package/src/renderers/webgl/WebGLRenderStates.js +11 -8
  474. package/src/renderers/webgl/WebGLShadowMap.js +6 -4
  475. package/src/renderers/webgl/WebGLState.js +10 -6
  476. package/src/renderers/webgl/WebGLTextures.js +129 -77
  477. package/src/renderers/webgl/WebGLUniforms.js +44 -6
  478. package/src/renderers/webgl/WebGLUniformsGroups.js +75 -69
  479. package/src/renderers/webgl-fallback/WebGLBackend.js +206 -278
  480. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +154 -20
  481. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +45 -42
  482. package/src/renderers/webgl-fallback/utils/WebGLState.js +29 -4
  483. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +129 -49
  484. package/src/renderers/webgl-fallback/utils/WebGLVertexArrayUtils.js +346 -0
  485. package/src/renderers/webgpu/WebGPUBackend.js +140 -82
  486. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  487. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +10 -10
  488. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +10 -10
  489. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +135 -60
  490. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +128 -55
  491. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +1 -1
  492. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +15 -12
  493. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +55 -19
  494. package/src/renderers/webgpu/utils/WebGPUUtils.js +20 -3
  495. package/src/renderers/webxr/WebXRController.js +3 -3
  496. package/src/renderers/webxr/WebXRManager.js +5 -90
  497. package/src/scenes/Scene.js +4 -4
  498. package/src/textures/CompressedTexture.js +2 -2
  499. package/src/textures/DepthTexture.js +2 -2
  500. package/src/textures/FramebufferTexture.js +11 -0
  501. package/src/textures/Texture.js +29 -1
  502. package/src/textures/TextureSource.js +1 -1
  503. package/src/upe.js +1 -1
  504. package/src/utils.js +4 -4
  505. package/examples/jsm/libs/surfaceNet.js +0 -201
  506. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -186
@@ -0,0 +1,865 @@
1
+ import { Box2, BufferGeometry, Float32BufferAttribute, Vector2, Vector3 } from 'three';
2
+ import { remapAttribute } from './BufferGeometryUtils.js';
3
+ import { potpack } from '../libs/potpack.module.js';
4
+
5
+ /**
6
+ * Generates a unique UV atlas for the meshes in a hierarchy, measured in world space.
7
+ * Each mesh receives a new geometry. Skinned and morphed meshes are unwrapped in
8
+ * their current pose. InstancedMesh and BatchedMesh are skipped with a warning.
9
+ * Excluded faces collapse onto the UV of a neighboring chart vertex, or (0, 0) if
10
+ * isolated, and get a faceCharts entry of -1.
11
+ *
12
+ * @three_import import { unwrapUVs } from 'three/addons/utils/unwrapUVs.js';
13
+ *
14
+ * @param {Object3D} root - A mesh or hierarchy to unwrap.
15
+ * @param {Object} [options] - Atlas and chart options.
16
+ * @param {string} [options.attribute='uv1'] - Output attribute: uv, uv1, uv2, uv3.
17
+ * @param {string} [options.mode='lightmap'] - 'lightmap' or 'normal'. Normal tries LSCM.
18
+ * @param {number} [options.resolution=1024] - Square atlas size in pixels, integer >= 4.
19
+ * @param {number} [options.padding=4] - Nonnegative gutter in pixels; 2 * padding + 1 must be less than resolution.
20
+ * @param {number} [options.texelsPerUnit=0] - Common world density; zero fits the atlas. Must be nonnegative.
21
+ * @param {boolean} [options.respectUVSeams] - Cut discontinuities in existing uv (normal default).
22
+ * @param {boolean} [options.useInputUVs=false] - Preserve valid authored UV charts before trying LSCM.
23
+ * @return {?Object} Atlas size, density, chart bounds, mesh vertex/face mappings and warning
24
+ * counts (excluded faces, tiny faces under 0.01 atlas pixels squared and single-triangle
25
+ * charts, which signal fragmentation), or null if the charts do not fit. Meshes are left
26
+ * unchanged in that case. Charts that fail Float32 validation are split and repacked;
27
+ * single faces that still fail are excluded.
28
+ */
29
+ function unwrapUVs( root, options = {} ) {
30
+
31
+ const settings = {
32
+ attribute: 'uv1', mode: 'lightmap', resolution: 1024, padding: 4,
33
+ texelsPerUnit: 0,
34
+ useInputUVs: false,
35
+ ...options, maxAreaRatio: 2
36
+ };
37
+ settings.maxStretch = settings.mode === 'normal' ? 2 : 1.5;
38
+ settings.respectUVSeams ??= settings.mode === 'normal';
39
+ root.updateWorldMatrix( true, true );
40
+
41
+ const records = [];
42
+ root.traverse( mesh => {
43
+
44
+ if ( ! mesh.isMesh ) return;
45
+ if ( mesh.isInstancedMesh || mesh.isBatchedMesh ) {
46
+
47
+ console.warn( 'THREE.unwrapUVs(): InstancedMesh and BatchedMesh are not supported. Skipping mesh.', mesh );
48
+ return;
49
+
50
+ }
51
+
52
+ records.push( readMesh( mesh, settings ) );
53
+
54
+ } );
55
+
56
+ const charts = [];
57
+ for ( const record of records ) {
58
+
59
+ for ( const faces of growCharts( record, settings ) ) {
60
+
61
+ parameterize( record, faces, settings, charts );
62
+
63
+ }
64
+
65
+ }
66
+
67
+ let density;
68
+ for ( ; ; ) {
69
+
70
+ density = packCharts( charts, settings );
71
+ if ( density === null ) return null;
72
+
73
+ const failed = [];
74
+ for ( let i = charts.length - 1; i >= 0; i -- ) {
75
+
76
+ if ( validateFloat32Chart( charts[ i ], settings, density ) === null ) failed.push( ...charts.splice( i, 1 ) );
77
+
78
+ }
79
+
80
+ if ( failed.length === 0 ) break;
81
+
82
+ // Float32 rounding broke these charts at this density; split them and repack.
83
+ for ( const chart of failed ) splitFaces( chart.record, chart.faces, settings, charts );
84
+
85
+ }
86
+
87
+ for ( let i = charts.length - 1; i >= 0; i -- ) {
88
+
89
+ if ( charts[ i ].dropped.size === charts[ i ].faces.length ) charts.splice( i, 1 );
90
+
91
+ }
92
+
93
+ for ( let i = 0; i < charts.length; i ++ ) {
94
+
95
+ charts[ i ].faces.forEach( ( face, t ) => {
96
+
97
+ if ( ! charts[ i ].dropped.has( t ) ) charts[ i ].record.faceCharts[ face ] = i;
98
+
99
+ } );
100
+
101
+ }
102
+
103
+ for ( const record of records ) record.mesh.geometry = rebuildGeometry( record, charts, settings );
104
+
105
+ let tinyFaces = 0;
106
+ for ( const chart of charts ) {
107
+
108
+ for ( const [ t, triangle ] of chart.triangles.entries() ) {
109
+
110
+ if ( ! chart.dropped.has( t ) && Math.abs( cross2( ...triangle.map( i => chart.outputUV[ i ] ) ) ) * settings.resolution ** 2 / 2 < 0.01 ) tinyFaces ++;
111
+
112
+ }
113
+
114
+ }
115
+
116
+ const excludedFaces = records.reduce( ( sum, record ) => sum + record.faceCharts.filter( chart => chart === - 1 ).length, 0 );
117
+ const singleTriangleCharts = charts.filter( chart => chart.faces.length === 1 ).length;
118
+
119
+ return {
120
+ attribute: settings.attribute, resolution: settings.resolution, padding: settings.padding,
121
+ texelsPerUnit: density,
122
+ charts: charts.map( chart => ( { x: chart.box.x, y: chart.box.y, width: chart.box.w, height: chart.box.h } ) ),
123
+ meshes: records.map( record => ( { mesh: record.mesh, sourceVertices: record.sourceVertices, faceCharts: record.faceCharts } ) ),
124
+ warnings: { excludedFaces, tinyFaces, singleTriangleCharts }
125
+ };
126
+
127
+ }
128
+
129
+ function readMesh( mesh, settings ) {
130
+
131
+ mesh.updateMatrixWorld( true ); // Also refresh SkinnedMesh.bindMatrixInverse.
132
+ if ( mesh.isSkinnedMesh ) {
133
+
134
+ for ( const bone of mesh.skeleton.bones ) bone.updateWorldMatrix( true, false );
135
+
136
+ }
137
+
138
+ const geometry = mesh.geometry, position = geometry.getAttribute( 'position' );
139
+ const index = geometry.index;
140
+ const count = index ? index.count : position.count;
141
+ const points = [], welds = [], unique = new Map();
142
+ for ( let i = 0; i < position.count; i ++ ) {
143
+
144
+ // Exact positional welding only, for topology; output attributes keep original identity.
145
+ const key = `${ position.getX( i ) },${ position.getY( i ) },${ position.getZ( i ) }`;
146
+ if ( ! unique.has( key ) ) unique.set( key, unique.size );
147
+ welds.push( unique.get( key ) );
148
+ points.push( mesh.getVertexPosition( i, new Vector3() ).applyMatrix4( mesh.matrixWorld ) );
149
+
150
+ }
151
+
152
+ const materials = new Int32Array( count / 3 );
153
+ for ( const group of geometry.groups ) {
154
+
155
+ materials.fill( group.materialIndex, group.start / 3, ( group.start + group.count ) / 3 );
156
+
157
+ }
158
+
159
+ const faces = [], edges = new Map();
160
+ for ( let offset = 0; offset < count; offset += 3 ) {
161
+
162
+ const vertices = [ 0, 1, 2 ].map( j => index ? index.getX( offset + j ) : offset + j );
163
+ const normal = new Vector3().subVectors( points[ vertices[ 1 ] ], points[ vertices[ 0 ] ] );
164
+ normal.cross( new Vector3().subVectors( points[ vertices[ 2 ] ], points[ vertices[ 0 ] ] ) );
165
+ const area = normal.length() * 0.5;
166
+ const longest = Math.max( ...[ 0, 1, 2 ].map( j => points[ vertices[ j ] ].distanceToSquared( points[ vertices[ ( j + 1 ) % 3 ] ] ) ) );
167
+ // slivers beyond Float32 precision are excluded from the atlas
168
+ const ignored = ! ( area > longest * 1e-6 );
169
+ const face = { vertices, welds: vertices.map( v => welds[ v ] ), normal: normal.normalize(), area, ignored, neighbors: [] };
170
+ const f = faces.length;
171
+ faces.push( face );
172
+ if ( face.ignored ) continue;
173
+
174
+ for ( let j = 0; j < 3; j ++ ) {
175
+
176
+ const a = face.welds[ j ], b = face.welds[ ( j + 1 ) % 3 ];
177
+ const key = a < b ? `${ a },${ b }` : `${ b },${ a }`;
178
+ if ( ! edges.has( key ) ) edges.set( key, [] );
179
+ edges.get( key ).push( { f, j, a, b } );
180
+
181
+ }
182
+
183
+ }
184
+
185
+ const uv = geometry.getAttribute( 'uv' );
186
+ for ( const edge of edges.values() ) {
187
+
188
+ // Pair opposite half-edges by closest normal, so duplicated double-sided shells
189
+ // (four faces per edge) join each side separately instead of becoming all seams.
190
+ const pairs = [], used = new Set();
191
+ for ( const x of edge ) {
192
+
193
+ let best = null, bestDot = - Infinity;
194
+ for ( const y of edge ) {
195
+
196
+ if ( used.has( x ) || used.has( y ) || y.a !== x.b || y.b !== x.a || materials[ x.f ] !== materials[ y.f ] ) continue;
197
+ const dot = faces[ x.f ].normal.dot( faces[ y.f ].normal );
198
+ if ( dot > bestDot ) {
199
+
200
+ best = y; bestDot = dot;
201
+
202
+ }
203
+
204
+ }
205
+
206
+ if ( best ) {
207
+
208
+ pairs.push( [ x, best ] );
209
+ used.add( x ).add( best );
210
+
211
+ }
212
+
213
+ }
214
+
215
+ for ( const [ a, b ] of pairs ) {
216
+
217
+ if ( ( settings.respectUVSeams || settings.useInputUVs ) && uv ) {
218
+
219
+ const av = faces[ a.f ].vertices, bv = faces[ b.f ].vertices;
220
+ if ( ! equalUV( uv, av[ a.j ], bv[ ( b.j + 1 ) % 3 ] ) || ! equalUV( uv, av[ ( a.j + 1 ) % 3 ], bv[ b.j ] ) ) continue;
221
+
222
+ }
223
+
224
+ faces[ a.f ].neighbors.push( b.f );
225
+ faces[ b.f ].neighbors.push( a.f );
226
+
227
+ }
228
+
229
+ }
230
+
231
+ // UV discontinuities can be cuts inside a connected chart (e.g. a slit
232
+ // cylinder). Keep the two coincident seam endpoints distinct in the solver.
233
+ const vertexKeys = welds.map( ( weld, i ) => uv && ( settings.respectUVSeams || settings.useInputUVs ) ? `${ weld },${ uv.getX( i ) },${ uv.getY( i ) }` : weld );
234
+ return { mesh, original: geometry, points, faces, vertexKeys, faceCharts: new Int32Array( faces.length ).fill( - 1 ) };
235
+
236
+ }
237
+
238
+ function equalUV( uv, a, b ) {
239
+
240
+ return uv.getX( a ) === uv.getX( b ) && uv.getY( a ) === uv.getY( b );
241
+
242
+ }
243
+
244
+ function growCharts( record, settings ) {
245
+
246
+ const assigned = new Uint8Array( record.faces.length ), charts = [];
247
+ // Lightmap charts use planar projection; keep the costlier LSCM charts smaller.
248
+ const limit = settings.mode === 'lightmap' ? 8192 : 2048;
249
+ // Wider normal cones in normal mode give LSCM useful curved patches to solve.
250
+ const cosine = settings.useInputUVs && record.original.attributes.uv ? - 1 : settings.mode === 'normal' ? 0.35 : 1 / settings.maxStretch;
251
+ for ( let seed = 0; seed < assigned.length; seed ++ ) {
252
+
253
+ if ( assigned[ seed ] || record.faces[ seed ].ignored ) continue;
254
+ const faces = [ seed ], normal = record.faces[ seed ].normal;
255
+ assigned[ seed ] = 1;
256
+ for ( let i = 0; i < faces.length && faces.length < limit; i ++ ) {
257
+
258
+ for ( const neighbor of record.faces[ faces[ i ] ].neighbors ) {
259
+
260
+ if ( assigned[ neighbor ] || record.faces[ neighbor ].normal.dot( normal ) < cosine ) continue;
261
+ assigned[ neighbor ] = 1;
262
+ faces.push( neighbor );
263
+ if ( faces.length === limit ) break;
264
+
265
+ }
266
+
267
+ }
268
+
269
+ charts.push( faces );
270
+
271
+ }
272
+
273
+ return charts;
274
+
275
+ }
276
+
277
+ function parameterize( record, faces, settings, charts ) {
278
+
279
+ const normal = new Vector3();
280
+ for ( const f of faces ) normal.addScaledVector( record.faces[ f ].normal, record.faces[ f ].area );
281
+ normal.normalize();
282
+ const axis = Math.abs( normal.x ) < 0.8 ? new Vector3( 1, 0, 0 ) : new Vector3( 0, 1, 0 );
283
+ const u = axis.cross( normal ).normalize(), v = new Vector3().crossVectors( normal, u );
284
+ const vertexMap = new Map(), positions = [], uv = [], triangles = [];
285
+ const useInput = settings.useInputUVs && record.original.attributes.uv;
286
+ const origin = record.points[ record.faces[ faces[ 0 ] ].vertices[ 0 ] ];
287
+ let worldArea = 0;
288
+ for ( const f of faces ) {
289
+
290
+ const face = record.faces[ f ];
291
+ worldArea += face.area;
292
+ triangles.push( face.vertices.map( vertex => {
293
+
294
+ const key = record.vertexKeys[ vertex ];
295
+ if ( ! vertexMap.has( key ) ) {
296
+
297
+ vertexMap.set( key, positions.length );
298
+ const p = record.points[ vertex ].clone().sub( origin );
299
+ positions.push( p );
300
+ uv.push( useInput ? [ useInput.getX( vertex ), useInput.getY( vertex ) ] : [ p.dot( u ), p.dot( v ) ] );
301
+
302
+ }
303
+
304
+ return vertexMap.get( key );
305
+
306
+ } ) );
307
+
308
+ }
309
+
310
+ if ( useInput && triangles.reduce( ( sum, tri ) => sum + cross2( ...tri.map( i => uv[ i ] ) ), 0 ) < 0 ) {
311
+
312
+ for ( const p of uv ) p[ 1 ] = - p[ 1 ];
313
+
314
+ }
315
+
316
+ let candidate = uv;
317
+ const initialQuality = checkChart( positions, triangles, uv, worldArea, settings );
318
+ let quality = initialQuality;
319
+ if ( settings.mode === 'normal' && faces.length > 1 && ! ( initialQuality && ( useInput || initialQuality.maxStretch < 1.000001 ) ) ) {
320
+
321
+ const conformal = solveLSCM( positions, triangles, uv );
322
+ const conformalQuality = conformal && checkChart( positions, triangles, conformal, worldArea, settings );
323
+ if ( conformalQuality ) {
324
+
325
+ candidate = conformal;
326
+ quality = conformalQuality;
327
+
328
+ }
329
+
330
+ }
331
+
332
+ if ( ! quality ) {
333
+
334
+ if ( useInput && ( settings.mode === 'lightmap' || faces.length === 1 ) ) {
335
+
336
+ // Reproject a rejected lightmap island before splitting its authored UVs
337
+ // into one chart per triangle. Normal mode already tries LSCM above.
338
+ parameterize( record, faces, { ...settings, useInputUVs: false }, charts );
339
+ return;
340
+
341
+ }
342
+
343
+ if ( faces.length === 1 ) {
344
+
345
+ record.faces[ faces[ 0 ] ].ignored = true;
346
+ return;
347
+
348
+ }
349
+
350
+ splitFaces( record, faces, settings, charts );
351
+ return;
352
+
353
+ }
354
+
355
+ const scale = Math.sqrt( worldArea / quality.area );
356
+ for ( const p of candidate ) {
357
+
358
+ p[ 0 ] *= scale; p[ 1 ] *= scale;
359
+
360
+ }
361
+
362
+ // Principal-axis alignment reduces rectangle waste without reflection.
363
+ alignChart( candidate );
364
+ const bounds = getBounds( candidate );
365
+ for ( const p of candidate ) {
366
+
367
+ p[ 0 ] -= bounds.min.x; p[ 1 ] -= bounds.min.y;
368
+
369
+ }
370
+
371
+ charts.push( {
372
+ record, faces, vertexMap, uv: candidate, worldArea,
373
+ width: bounds.max.x - bounds.min.x, height: bounds.max.y - bounds.min.y,
374
+ positions, triangles
375
+ } );
376
+
377
+ }
378
+
379
+ function splitFaces( record, faces, settings, charts ) {
380
+
381
+ const half = Math.floor( faces.length / 2 );
382
+ for ( const subset of [ faces.slice( 0, half ), faces.slice( half ) ] ) {
383
+
384
+ for ( const component of connectedComponents( record, subset ) ) parameterize( record, component, settings, charts );
385
+
386
+ }
387
+
388
+ }
389
+
390
+ function connectedComponents( record, faces ) {
391
+
392
+ const remaining = new Set( faces ), components = [];
393
+ for ( const seed of faces ) {
394
+
395
+ if ( ! remaining.delete( seed ) ) continue;
396
+ const component = [ seed ];
397
+ for ( let i = 0; i < component.length; i ++ ) {
398
+
399
+ for ( const neighbor of record.faces[ component[ i ] ].neighbors ) {
400
+
401
+ if ( remaining.delete( neighbor ) ) component.push( neighbor );
402
+
403
+ }
404
+
405
+ }
406
+
407
+ components.push( component );
408
+
409
+ }
410
+
411
+ return components;
412
+
413
+ }
414
+
415
+ function checkChart( positions, triangles, uv, worldArea, settings ) {
416
+
417
+ if ( uv.some( p => ! Number.isFinite( p[ 0 ] + p[ 1 ] ) ) ) return null;
418
+ let area = 0, maxStretch = 1, minRatio = Infinity, maxRatio = 0;
419
+ for ( const tri of triangles ) {
420
+
421
+ const { length, x, y, cross } = triangleFrame( positions, tri );
422
+ const [ p, q, r ] = tri.map( i => uv[ i ] );
423
+ const determinant = cross2( p, q, r );
424
+ if ( ! ( determinant > 0 ) ) return null;
425
+ area += determinant * 0.5;
426
+ const ux = ( q[ 0 ] - p[ 0 ] ) / length, vx = ( q[ 1 ] - p[ 1 ] ) / length;
427
+ const uy = ( r[ 0 ] - p[ 0 ] - ux * x ) / y, vy = ( r[ 1 ] - p[ 1 ] - vx * x ) / y;
428
+ const aa = ux * ux + vx * vx, bb = uy * uy + vy * vy, cc = ux * uy + vx * vy;
429
+ const trace = aa + bb, difference = aa - bb, delta = Math.sqrt( difference * difference + 4 * cc * cc );
430
+ // Use determinant for the small eigenvalue to avoid subtractive cancellation.
431
+ const largest = ( trace + delta ) * 0.5;
432
+ const jacobianDet = determinant / cross;
433
+ const stretch = largest / jacobianDet;
434
+ if ( ! Number.isFinite( stretch ) || stretch > settings.maxStretch * ( 1 + 1e-8 ) ) return null;
435
+ maxStretch = Math.max( maxStretch, stretch );
436
+ minRatio = Math.min( minRatio, jacobianDet );
437
+ maxRatio = Math.max( maxRatio, jacobianDet );
438
+
439
+ }
440
+
441
+ const mean = area / worldArea;
442
+ if ( minRatio / mean < 1 / settings.maxAreaRatio - 1e-8 || maxRatio / mean > settings.maxAreaRatio + 1e-8 ) return null;
443
+ if ( hasOverlap( uv, triangles ) ) return null;
444
+ return { area, maxStretch };
445
+
446
+ }
447
+
448
+ function cross2( a, b, c ) {
449
+
450
+ return ( b[ 0 ] - a[ 0 ] ) * ( c[ 1 ] - a[ 1 ] ) - ( b[ 1 ] - a[ 1 ] ) * ( c[ 0 ] - a[ 0 ] );
451
+
452
+ }
453
+
454
+ function getBounds( points ) {
455
+
456
+ const bounds = new Box2(), point = new Vector2();
457
+ for ( const p of points ) bounds.expandByPoint( point.set( p[ 0 ], p[ 1 ] ) );
458
+ return bounds;
459
+
460
+ }
461
+
462
+ function hasOverlap( uv, triangles ) {
463
+
464
+ const bounds = getBounds( uv );
465
+ const extent = Math.max( bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y );
466
+ const cellSize = extent / Math.max( 1, Math.sqrt( triangles.length ) );
467
+ const epsilon = extent * 1e-10, cells = new Map();
468
+ for ( let i = 0; i < triangles.length; i ++ ) {
469
+
470
+ const points = triangles[ i ].map( v => uv[ v ] ), box = getBounds( points ), seen = new Set();
471
+ for ( let x = Math.floor( ( box.min.x - bounds.min.x ) / cellSize ); x <= Math.floor( ( box.max.x - bounds.min.x ) / cellSize ); x ++ ) {
472
+
473
+ for ( let y = Math.floor( ( box.min.y - bounds.min.y ) / cellSize ); y <= Math.floor( ( box.max.y - bounds.min.y ) / cellSize ); y ++ ) {
474
+
475
+ const key = `${ x },${ y }`;
476
+ if ( ! cells.has( key ) ) cells.set( key, [] );
477
+ const cell = cells.get( key );
478
+ for ( const other of cell ) {
479
+
480
+ if ( seen.has( other ) ) continue;
481
+ seen.add( other );
482
+ if ( overlapSAT( points, triangles[ other ].map( v => uv[ v ] ), epsilon ) ) return true;
483
+
484
+ }
485
+
486
+ cell.push( i );
487
+
488
+ }
489
+
490
+ }
491
+
492
+ }
493
+
494
+ return false;
495
+
496
+ }
497
+
498
+ // Strict interior intersection: shared edges and vertices are allowed.
499
+ function overlapSAT( a, b, epsilon ) {
500
+
501
+ for ( const tri of [ a, b ] ) {
502
+
503
+ for ( let j = 0; j < 3; j ++ ) {
504
+
505
+ const p = tri[ j ], q = tri[ ( j + 1 ) % 3 ];
506
+ const nx = p[ 1 ] - q[ 1 ], ny = q[ 0 ] - p[ 0 ];
507
+ let minA = Infinity, maxA = - Infinity, minB = Infinity, maxB = - Infinity;
508
+ for ( let k = 0; k < 3; k ++ ) {
509
+
510
+ const da = a[ k ][ 0 ] * nx + a[ k ][ 1 ] * ny, db = b[ k ][ 0 ] * nx + b[ k ][ 1 ] * ny;
511
+ minA = Math.min( minA, da ); maxA = Math.max( maxA, da );
512
+ minB = Math.min( minB, db ); maxB = Math.max( maxB, db );
513
+
514
+ }
515
+
516
+ if ( Math.min( maxA, maxB ) - Math.max( minA, minB ) <= epsilon * Math.sqrt( nx * nx + ny * ny ) ) return false;
517
+
518
+ }
519
+
520
+ }
521
+
522
+ return true;
523
+
524
+ }
525
+
526
+ function alignChart( uv ) {
527
+
528
+ let x = 0, y = 0, xx = 0, yy = 0, xy = 0;
529
+ for ( const p of uv ) {
530
+
531
+ x += p[ 0 ]; y += p[ 1 ];
532
+
533
+ }
534
+
535
+ x /= uv.length; y /= uv.length;
536
+ for ( const p of uv ) {
537
+
538
+ xx += ( p[ 0 ] - x ) ** 2; yy += ( p[ 1 ] - y ) ** 2; xy += ( p[ 0 ] - x ) * ( p[ 1 ] - y );
539
+
540
+ }
541
+
542
+ const angle = 0.5 * Math.atan2( 2 * xy, xx - yy ), cosine = Math.cos( angle ), sine = Math.sin( angle );
543
+ const rotated = uv.map( p => [ cosine * p[ 0 ] + sine * p[ 1 ], - sine * p[ 0 ] + cosine * p[ 1 ] ] );
544
+ const a = getBounds( uv ), b = getBounds( rotated );
545
+ if ( ( b.max.x - b.min.x ) * ( b.max.y - b.min.y ) < ( a.max.x - a.min.x ) * ( a.max.y - a.min.y ) ) {
546
+
547
+ for ( let i = 0; i < uv.length; i ++ ) uv[ i ] = rotated[ i ];
548
+
549
+ }
550
+
551
+ }
552
+
553
+ function packCharts( charts, settings ) {
554
+
555
+ if ( charts.length === 0 ) return 0;
556
+ // Half a pixel beyond the requested gutter protects the texel-center boundary.
557
+ const border = settings.padding + 0.5;
558
+ function pack( density ) {
559
+
560
+ const boxes = charts.map( chart => ( {
561
+ chart, w: Math.max( 1, Math.ceil( chart.width * density + border * 2 ) ),
562
+ h: Math.max( 1, Math.ceil( chart.height * density + border * 2 ) )
563
+ } ) );
564
+ const result = potpack( boxes );
565
+ if ( result.w > settings.resolution || result.h > settings.resolution ) return packShelves( boxes, settings.resolution );
566
+ return boxes;
567
+
568
+ }
569
+
570
+ let density = settings.texelsPerUnit, boxes = density > 0 ? pack( density ) : null;
571
+ if ( density > 0 && ! boxes ) console.warn( 'THREE.unwrapUVs(): Charts do not fit at the requested texelsPerUnit. Fitting the atlas instead.' );
572
+
573
+ if ( ! boxes ) {
574
+
575
+ const area = charts.reduce( ( sum, chart ) => sum + chart.width * chart.height, 0 );
576
+ let low = 0, high = settings.resolution / Math.sqrt( area );
577
+ for ( let iteration = 0; iteration < 24; iteration ++ ) {
578
+
579
+ const middle = ( low + high ) * 0.5, trial = pack( middle );
580
+ if ( trial ) {
581
+
582
+ low = middle; boxes = trial;
583
+
584
+ } else {
585
+
586
+ high = middle;
587
+
588
+ }
589
+
590
+ }
591
+
592
+ density = low;
593
+ if ( ! boxes ) {
594
+
595
+ console.error( 'THREE.unwrapUVs(): Charts do not fit the atlas. Increase the resolution, reduce the padding or partition the hierarchy.' );
596
+ return null;
597
+
598
+ }
599
+
600
+ }
601
+
602
+ for ( const box of boxes ) box.chart.box = { x: box.x, y: box.y, w: box.w, h: box.h };
603
+ return density;
604
+
605
+ }
606
+
607
+ // A fixed-width fallback avoids potpack's unconstrained container-width heuristic.
608
+ function packShelves( boxes, resolution ) {
609
+
610
+ const shelves = [];
611
+ let height = 0;
612
+ for ( const box of boxes ) {
613
+
614
+ if ( box.w > resolution || box.h > resolution ) return null;
615
+ let best = null;
616
+ for ( const shelf of shelves ) {
617
+
618
+ if ( shelf.h >= box.h && shelf.x + box.w <= resolution && ( best === null || shelf.x > best.x ) ) best = shelf;
619
+
620
+ }
621
+
622
+ if ( best === null ) {
623
+
624
+ if ( height + box.h > resolution ) return null;
625
+ best = { x: 0, y: height, h: box.h };
626
+ shelves.push( best );
627
+ height += box.h;
628
+
629
+ }
630
+
631
+ box.x = best.x;
632
+ box.y = best.y;
633
+ best.x += box.w;
634
+
635
+ }
636
+
637
+ return boxes;
638
+
639
+ }
640
+
641
+ function validateFloat32Chart( chart, settings, density ) {
642
+
643
+ const border = settings.padding + 0.5;
644
+ chart.outputUV = chart.uv.map( p => [
645
+ Math.fround( ( chart.box.x + border + p[ 0 ] * density ) / settings.resolution ),
646
+ Math.fround( ( chart.box.y + border + p[ 1 ] * density ) / settings.resolution )
647
+ ] );
648
+ // Validate the coordinates the GPU actually receives, not just the solver's
649
+ // doubles. Slivers can collapse or reverse after atlas translation/rounding.
650
+ const limits = { ...settings, maxStretch: settings.maxStretch * ( 1 + 5e-4 ), maxAreaRatio: settings.maxAreaRatio * ( 1 + 5e-4 ) };
651
+ // Drops are recomputed on every pass, so a repack at another density can restore them.
652
+ chart.dropped = new Set();
653
+ if ( checkChart( chart.positions, chart.triangles, chart.outputUV, chart.worldArea, limits ) ) return true;
654
+
655
+ // Drop failing single faces and subtexel faces; anything else needs a split.
656
+ const triangles = [];
657
+ let worldArea = chart.worldArea;
658
+ for ( let i = 0; i < chart.triangles.length; i ++ ) {
659
+
660
+ const triangle = chart.triangles[ i ], face = chart.record.faces[ chart.faces[ i ] ];
661
+ if ( chart.triangles.length === 1 || face.area * density * density < 1 && ! checkChart( chart.positions, [ triangle ], chart.outputUV, face.area, limits ) ) {
662
+
663
+ chart.dropped.add( i );
664
+ worldArea -= face.area;
665
+
666
+ } else {
667
+
668
+ triangles.push( triangle );
669
+
670
+ }
671
+
672
+ }
673
+
674
+ return triangles.length === 0 || checkChart( chart.positions, triangles, chart.outputUV, worldArea, limits ) ? true : null;
675
+
676
+ }
677
+
678
+ function rebuildGeometry( record, charts, settings ) {
679
+
680
+ const original = record.original, lookup = new Map(), source = [], values = [], indices = [];
681
+ const chartUV = ( chart, vertex ) => chart.outputUV[ chart.vertexMap.get( record.vertexKeys[ vertex ] ) ];
682
+
683
+ // Excluded faces collapse onto a welded neighbor's UV so they sample adjacent lighting
684
+ // rather than the gutter of whichever chart sits at (0, 0). Isolated ones keep (0, 0).
685
+ const weldUVs = new Map();
686
+ for ( let f = 0; f < record.faces.length; f ++ ) {
687
+
688
+ const chart = charts[ record.faceCharts[ f ] ], face = record.faces[ f ];
689
+ if ( chart ) for ( let j = 0; j < 3; j ++ ) weldUVs.set( face.welds[ j ], chartUV( chart, face.vertices[ j ] ) );
690
+
691
+ }
692
+
693
+ for ( let f = 0; f < record.faces.length; f ++ ) {
694
+
695
+ const chartIndex = record.faceCharts[ f ], chart = charts[ chartIndex ], face = record.faces[ f ];
696
+ const fallback = chart ? null : face.welds.map( weld => weldUVs.get( weld ) ).find( Boolean ) ?? [ 0, 0 ];
697
+ for ( let j = 0; j < 3; j ++ ) {
698
+
699
+ const vertex = face.vertices[ j ], key = chart ? `${ vertex },${ chartIndex }` : `${ vertex },${ fallback }`;
700
+ if ( ! lookup.has( key ) ) {
701
+
702
+ lookup.set( key, source.length );
703
+ source.push( vertex );
704
+ const p = chart ? chartUV( chart, vertex ) : fallback;
705
+ values.push( p[ 0 ], p[ 1 ] );
706
+
707
+ }
708
+
709
+ indices.push( lookup.get( key ) );
710
+
711
+ }
712
+
713
+ }
714
+
715
+ const geometry = new BufferGeometry(), buffers = new Map();
716
+ geometry.name = original.name;
717
+ geometry.morphTargetsRelative = original.morphTargetsRelative;
718
+ geometry.userData = original.userData;
719
+ geometry.setDrawRange( original.drawRange.start, original.drawRange.count );
720
+ for ( const group of original.groups ) geometry.addGroup( group.start, group.count, group.materialIndex );
721
+
722
+ for ( const name of Object.keys( original.attributes ) ) geometry.setAttribute( name, remapAttribute( original.attributes[ name ], source, buffers ) );
723
+ for ( const name of Object.keys( original.morphAttributes ) ) {
724
+
725
+ geometry.morphAttributes[ name ] = original.morphAttributes[ name ].map( attribute => remapAttribute( attribute, source, buffers ) );
726
+
727
+ }
728
+
729
+ geometry.setIndex( indices );
730
+ geometry.setAttribute( settings.attribute, new Float32BufferAttribute( values, 2 ) );
731
+ if ( settings.attribute === 'uv' ) geometry.deleteAttribute( 'tangent' );
732
+ record.sourceVertices = Uint32Array.from( source );
733
+ return geometry;
734
+
735
+ }
736
+
737
+ function triangleFrame( positions, triangle ) {
738
+
739
+ const [ a, b, c ] = triangle.map( i => positions[ i ] );
740
+ const ab = new Vector3().subVectors( b, a ), ac = new Vector3().subVectors( c, a );
741
+ const length = ab.length(), cross = new Vector3().crossVectors( ab, ac ).length();
742
+ return { length, x: ac.dot( ab ) / length, y: cross / length, cross };
743
+
744
+ }
745
+
746
+ // Least squares conformal maps, solved with Jacobi-preconditioned conjugate gradients.
747
+ // Two pinned vertices remove the similarity null modes. Returns null on failure.
748
+ function solveLSCM( positions, triangles, initial ) {
749
+
750
+ let pinA = 0, pinB = 0, distance = 0;
751
+ for ( let i = 1; i < initial.length; i ++ ) {
752
+
753
+ if ( initial[ i ][ 0 ] < initial[ pinA ][ 0 ] ) pinA = i;
754
+
755
+ }
756
+
757
+ for ( let i = 0; i < initial.length; i ++ ) {
758
+
759
+ const d = ( initial[ i ][ 0 ] - initial[ pinA ][ 0 ] ) ** 2 + ( initial[ i ][ 1 ] - initial[ pinA ][ 1 ] ) ** 2;
760
+ if ( d > distance ) {
761
+
762
+ distance = d; pinB = i;
763
+
764
+ }
765
+
766
+ }
767
+
768
+ if ( distance === 0 ) return null;
769
+ const n = positions.length * 2, fixed = new Uint8Array( n );
770
+ for ( const pin of [ pinA, pinB ] ) {
771
+
772
+ fixed[ pin * 2 ] = 1; fixed[ pin * 2 + 1 ] = 1;
773
+
774
+ }
775
+
776
+ const rows = [];
777
+ for ( const tri of triangles ) {
778
+
779
+ const { length, x, y } = triangleFrame( positions, tri );
780
+ if ( ! ( y > 0 && length > 0 ) ) return null;
781
+ const weight = Math.sqrt( length * y * 0.5 );
782
+ const gx = [ - 1 / length, 1 / length, 0 ], gy = [ ( x - length ) / ( length * y ), - x / ( length * y ), 1 / y ];
783
+ const indices = tri.flatMap( i => [ i * 2, i * 2 + 1 ] );
784
+ rows.push( { indices, values: gx.flatMap( ( value, i ) => [ value * weight, - gy[ i ] * weight ] ) } );
785
+ rows.push( { indices, values: gy.flatMap( ( value, i ) => [ value * weight, gx[ i ] * weight ] ) } );
786
+
787
+ }
788
+
789
+ const diagonal = new Float64Array( n ), rhs = new Float64Array( n );
790
+ for ( const row of rows ) {
791
+
792
+ let offset = 0;
793
+ for ( let j = 0; j < 6; j ++ ) {
794
+
795
+ const i = row.indices[ j ];
796
+ if ( fixed[ i ] ) offset += row.values[ j ] * initial[ i >> 1 ][ i % 2 ];
797
+
798
+ }
799
+
800
+ for ( let j = 0; j < 6; j ++ ) {
801
+
802
+ const i = row.indices[ j ];
803
+ if ( ! fixed[ i ] ) {
804
+
805
+ diagonal[ i ] += row.values[ j ] ** 2; rhs[ i ] -= row.values[ j ] * offset;
806
+
807
+ }
808
+
809
+ }
810
+
811
+ }
812
+
813
+ function multiply( input, output ) {
814
+
815
+ output.fill( 0 );
816
+ for ( const row of rows ) {
817
+
818
+ let sum = 0;
819
+ for ( let j = 0; j < 6; j ++ ) if ( ! fixed[ row.indices[ j ] ] ) sum += row.values[ j ] * input[ row.indices[ j ] ];
820
+ for ( let j = 0; j < 6; j ++ ) if ( ! fixed[ row.indices[ j ] ] ) output[ row.indices[ j ] ] += row.values[ j ] * sum;
821
+
822
+ }
823
+
824
+ }
825
+
826
+ const solution = new Float64Array( n ), residual = new Float64Array( n ), direction = new Float64Array( n ), product = new Float64Array( n );
827
+ for ( let i = 0; i < n; i ++ ) if ( ! fixed[ i ] ) solution[ i ] = initial[ i >> 1 ][ i % 2 ];
828
+ multiply( solution, product );
829
+ let rz = 0;
830
+ for ( let i = 0; i < n; i ++ ) {
831
+
832
+ residual[ i ] = rhs[ i ] - product[ i ];
833
+ direction[ i ] = diagonal[ i ] > 0 ? residual[ i ] / diagonal[ i ] : 0;
834
+ rz += residual[ i ] * direction[ i ];
835
+
836
+ }
837
+
838
+ const tolerance = rz * 1e-12;
839
+ for ( let iteration = 0; iteration < Math.min( n, 300 ) && rz > tolerance && rz > 1e-24; iteration ++ ) {
840
+
841
+ multiply( direction, product );
842
+ let denominator = 0;
843
+ for ( let i = 0; i < n; i ++ ) denominator += direction[ i ] * product[ i ];
844
+ if ( ! ( denominator > 0 ) ) return null;
845
+ const alpha = rz / denominator;
846
+ let next = 0;
847
+ for ( let i = 0; i < n; i ++ ) {
848
+
849
+ solution[ i ] += alpha * direction[ i ];
850
+ residual[ i ] -= alpha * product[ i ];
851
+ if ( diagonal[ i ] > 0 ) next += residual[ i ] ** 2 / diagonal[ i ];
852
+
853
+ }
854
+
855
+ const beta = next / rz;
856
+ for ( let i = 0; i < n; i ++ ) direction[ i ] = ( diagonal[ i ] > 0 ? residual[ i ] / diagonal[ i ] : 0 ) + beta * direction[ i ];
857
+ rz = next;
858
+
859
+ }
860
+
861
+ return initial.map( ( p, i ) => fixed[ i * 2 ] ? p.slice() : [ solution[ i * 2 ], solution[ i * 2 + 1 ] ] );
862
+
863
+ }
864
+
865
+ export { unwrapUVs };