super-three 0.144.0 → 0.147.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 (450) hide show
  1. package/README.md +1 -1
  2. package/build/three.cjs +737 -388
  3. package/build/three.js +737 -388
  4. package/build/three.min.js +1 -1
  5. package/build/three.module.js +911 -409
  6. package/examples/js/animation/AnimationClipCreator.js +0 -8
  7. package/examples/js/animation/CCDIKSolver.js +50 -67
  8. package/examples/js/animation/MMDAnimationHelper.js +66 -137
  9. package/examples/js/animation/MMDPhysics.js +70 -134
  10. package/examples/js/cameras/CinematicCamera.js +33 -22
  11. package/examples/js/controls/ArcballControls.js +138 -405
  12. package/examples/js/controls/DragControls.js +8 -33
  13. package/examples/js/controls/FirstPersonControls.js +32 -54
  14. package/examples/js/controls/FlyControls.js +29 -55
  15. package/examples/js/controls/OrbitControls.js +125 -99
  16. package/examples/js/controls/PointerLockControls.js +5 -14
  17. package/examples/js/controls/TrackballControls.js +33 -86
  18. package/examples/js/controls/TransformControls.js +85 -170
  19. package/examples/js/csm/CSM.js +4 -39
  20. package/examples/js/csm/CSMFrustum.js +3 -9
  21. package/examples/js/csm/CSMHelper.js +24 -4
  22. package/examples/js/csm/CSMShader.js +2 -6
  23. package/examples/js/curves/CurveExtras.js +27 -27
  24. package/examples/js/curves/NURBSCurve.js +4 -16
  25. package/examples/js/curves/NURBSSurface.js +3 -9
  26. package/examples/js/curves/NURBSUtils.js +8 -45
  27. package/examples/js/effects/AnaglyphEffect.js +4 -18
  28. package/examples/js/effects/AsciiEffect.js +32 -31
  29. package/examples/js/effects/OutlineEffect.js +26 -30
  30. package/examples/js/effects/ParallaxBarrierEffect.js +0 -13
  31. package/examples/js/effects/PeppersGhostEffect.js +12 -39
  32. package/examples/js/effects/StereoEffect.js +0 -4
  33. package/examples/js/environments/RoomEnvironment.js +12 -10
  34. package/examples/js/exporters/ColladaExporter.js +48 -65
  35. package/examples/js/exporters/DRACOExporter.js +22 -22
  36. package/examples/js/exporters/EXRExporter.js +15 -18
  37. package/examples/js/exporters/GLTFExporter.js +141 -317
  38. package/examples/js/exporters/MMDExporter.js +5 -12
  39. package/examples/js/exporters/OBJExporter.js +42 -33
  40. package/examples/js/exporters/PLYExporter.js +38 -33
  41. package/examples/js/exporters/STLExporter.js +5 -7
  42. package/examples/js/exporters/USDZExporter.js +113 -27
  43. package/examples/js/geometries/BoxLineGeometry.js +0 -1
  44. package/examples/js/geometries/ConvexGeometry.js +11 -6
  45. package/examples/js/geometries/DecalGeometry.js +53 -20
  46. package/examples/js/geometries/LightningStrike.js +54 -67
  47. package/examples/js/geometries/ParametricGeometries.js +8 -7
  48. package/examples/js/geometries/ParametricGeometry.js +25 -12
  49. package/examples/js/geometries/RoundedBoxGeometry.js +21 -19
  50. package/examples/js/geometries/TeapotGeometry.js +54 -50
  51. package/examples/js/geometries/TextGeometry.js +6 -4
  52. package/examples/js/helpers/LightProbeHelper.js +1 -2
  53. package/examples/js/helpers/OctreeHelper.js +22 -20
  54. package/examples/js/helpers/PositionalAudioHelper.js +8 -6
  55. package/examples/js/helpers/RectAreaLightHelper.js +6 -7
  56. package/examples/js/helpers/VertexNormalsHelper.js +15 -13
  57. package/examples/js/helpers/VertexTangentsHelper.js +15 -9
  58. package/examples/js/helpers/ViewHelper.js +31 -16
  59. package/examples/js/interactive/HTMLMesh.js +25 -39
  60. package/examples/js/interactive/InteractiveGroup.js +9 -14
  61. package/examples/js/interactive/SelectionBox.js +3 -70
  62. package/examples/js/interactive/SelectionHelper.js +0 -8
  63. package/examples/js/lights/LightProbeGenerator.js +32 -39
  64. package/examples/js/lights/RectAreaLightUniformsLib.js +5 -1
  65. package/examples/js/lines/LineGeometry.js +3 -5
  66. package/examples/js/lines/LineMaterial.js +4 -11
  67. package/examples/js/lines/LineSegments2.js +40 -89
  68. package/examples/js/lines/LineSegmentsGeometry.js +7 -28
  69. package/examples/js/lines/Wireframe.js +2 -7
  70. package/examples/js/lines/WireframeGeometry2.js +3 -1
  71. package/examples/js/loaders/3DMLoader.js +58 -155
  72. package/examples/js/loaders/3MFLoader.js +72 -106
  73. package/examples/js/loaders/AMFLoader.js +0 -25
  74. package/examples/js/loaders/BVHLoader.js +44 -43
  75. package/examples/js/loaders/BasisTextureLoader.js +16 -46
  76. package/examples/js/loaders/ColladaLoader.js +228 -359
  77. package/examples/js/loaders/DDSLoader.js +24 -25
  78. package/examples/js/loaders/DRACOLoader.js +29 -66
  79. package/examples/js/loaders/EXRLoader.js +67 -164
  80. package/examples/js/loaders/FBXLoader.js +287 -441
  81. package/examples/js/loaders/FontLoader.js +6 -15
  82. package/examples/js/loaders/GCodeLoader.js +15 -16
  83. package/examples/js/loaders/GLTFLoader.js +409 -706
  84. package/examples/js/loaders/HDRCubeTextureLoader.js +0 -6
  85. package/examples/js/loaders/KMZLoader.js +3 -7
  86. package/examples/js/loaders/KTXLoader.js +12 -30
  87. package/examples/js/loaders/LDrawLoader.js +178 -289
  88. package/examples/js/loaders/LUT3dlLoader.js +7 -11
  89. package/examples/js/loaders/LUTCubeLoader.js +0 -8
  90. package/examples/js/loaders/LWOLoader.js +59 -124
  91. package/examples/js/loaders/LogLuvLoader.js +27 -77
  92. package/examples/js/loaders/LottieLoader.js +4 -4
  93. package/examples/js/loaders/MD2Loader.js +26 -27
  94. package/examples/js/loaders/MDDLoader.js +6 -10
  95. package/examples/js/loaders/MMDLoader.js +180 -189
  96. package/examples/js/loaders/MTLLoader.js +18 -47
  97. package/examples/js/loaders/NRRDLoader.js +44 -84
  98. package/examples/js/loaders/OBJLoader.js +50 -65
  99. package/examples/js/loaders/PCDLoader.js +34 -29
  100. package/examples/js/loaders/PDBLoader.js +17 -13
  101. package/examples/js/loaders/PLYLoader.js +62 -48
  102. package/examples/js/loaders/PRWMLoader.js +11 -22
  103. package/examples/js/loaders/PVRLoader.js +7 -16
  104. package/examples/js/loaders/RGBELoader.js +36 -61
  105. package/examples/js/loaders/RGBMLoader.js +26 -87
  106. package/examples/js/loaders/STLLoader.js +20 -27
  107. package/examples/js/loaders/SVGLoader.js +361 -233
  108. package/examples/js/loaders/TDSLoader.js +81 -118
  109. package/examples/js/loaders/TGALoader.js +39 -41
  110. package/examples/js/loaders/TIFFLoader.js +0 -1
  111. package/examples/js/loaders/TTFLoader.js +0 -8
  112. package/examples/js/loaders/TiltLoader.js +14 -15
  113. package/examples/js/loaders/VOXLoader.js +8 -16
  114. package/examples/js/loaders/VRMLLoader.js +243 -340
  115. package/examples/js/loaders/VTKLoader.js +101 -118
  116. package/examples/js/loaders/XYZLoader.js +2 -4
  117. package/examples/js/loaders/lwo/IFFParser.js +55 -136
  118. package/examples/js/loaders/lwo/LWO2Parser.js +32 -83
  119. package/examples/js/loaders/lwo/LWO3Parser.js +31 -73
  120. package/examples/js/materials/MeshGouraudMaterial.js +15 -13
  121. package/examples/js/math/Capsule.js +0 -17
  122. package/examples/js/math/ColorConverter.js +3 -3
  123. package/examples/js/math/ConvexHull.js +185 -141
  124. package/examples/js/math/ImprovedNoise.js +1 -1
  125. package/examples/js/math/Lut.js +8 -15
  126. package/examples/js/math/MeshSurfaceSampler.js +6 -28
  127. package/examples/js/math/OBB.js +90 -49
  128. package/examples/js/math/Octree.js +2 -57
  129. package/examples/js/math/SimplexNoise.js +74 -88
  130. package/examples/js/misc/ConvexObjectBreaker.js +37 -48
  131. package/examples/js/misc/GPUComputationRenderer.js +26 -16
  132. package/examples/js/misc/Gyroscope.js +5 -9
  133. package/examples/js/misc/MD2Character.js +14 -23
  134. package/examples/js/misc/MD2CharacterComplex.js +73 -54
  135. package/examples/js/misc/MorphAnimMesh.js +0 -6
  136. package/examples/js/misc/MorphBlendMesh.js +3 -30
  137. package/examples/js/misc/ProgressiveLightMap.js +47 -43
  138. package/examples/js/misc/RollerCoaster.js +17 -24
  139. package/examples/js/misc/TubePainter.js +18 -12
  140. package/examples/js/misc/Volume.js +16 -45
  141. package/examples/js/misc/VolumeSlice.js +14 -24
  142. package/examples/js/modifiers/CurveModifier.js +19 -21
  143. package/examples/js/modifiers/EdgeSplitModifier.js +0 -30
  144. package/examples/js/modifiers/SimplifyModifier.js +56 -59
  145. package/examples/js/modifiers/TessellateModifier.js +2 -9
  146. package/examples/js/objects/GroundProjectedEnv.js +2 -14
  147. package/examples/js/objects/Lensflare.js +47 -38
  148. package/examples/js/objects/LightningStorm.js +10 -13
  149. package/examples/js/objects/MarchingCubes.js +80 -59
  150. package/examples/js/objects/Reflector.js +22 -20
  151. package/examples/js/objects/ReflectorForSSRPass.js +19 -23
  152. package/examples/js/objects/Refractor.js +52 -30
  153. package/examples/js/objects/ShadowMesh.js +1 -2
  154. package/examples/js/objects/Sky.js +2 -7
  155. package/examples/js/objects/Water.js +23 -18
  156. package/examples/js/objects/Water2.js +20 -19
  157. package/examples/js/physics/AmmoPhysics.js +23 -20
  158. package/examples/js/physics/OimoPhysics.js +19 -17
  159. package/examples/js/postprocessing/AdaptiveToneMappingPass.js +13 -20
  160. package/examples/js/postprocessing/AfterimagePass.js +19 -12
  161. package/examples/js/postprocessing/BloomPass.js +38 -17
  162. package/examples/js/postprocessing/BokehPass.js +29 -12
  163. package/examples/js/postprocessing/ClearPass.js +1 -6
  164. package/examples/js/postprocessing/CubeTexturePass.js +12 -9
  165. package/examples/js/postprocessing/DotScreenPass.js +7 -5
  166. package/examples/js/postprocessing/EffectComposer.js +25 -32
  167. package/examples/js/postprocessing/FilmPass.js +7 -5
  168. package/examples/js/postprocessing/GlitchPass.js +10 -11
  169. package/examples/js/postprocessing/HalftonePass.js +9 -9
  170. package/examples/js/postprocessing/LUTPass.js +2 -15
  171. package/examples/js/postprocessing/MaskPass.js +20 -17
  172. package/examples/js/postprocessing/OutlinePass.js +45 -36
  173. package/examples/js/postprocessing/Pass.js +11 -14
  174. package/examples/js/postprocessing/RenderPass.js +3 -7
  175. package/examples/js/postprocessing/RenderPixelatedPass.js +215 -0
  176. package/examples/js/postprocessing/SAOPass.js +40 -32
  177. package/examples/js/postprocessing/SMAAPass.js +34 -17
  178. package/examples/js/postprocessing/SSAARenderPass.js +14 -14
  179. package/examples/js/postprocessing/SSAOPass.js +56 -42
  180. package/examples/js/postprocessing/SSRPass.js +78 -61
  181. package/examples/js/postprocessing/SavePass.js +14 -6
  182. package/examples/js/postprocessing/ShaderPass.js +9 -8
  183. package/examples/js/postprocessing/TAARenderPass.js +11 -9
  184. package/examples/js/postprocessing/TexturePass.js +7 -4
  185. package/examples/js/postprocessing/UnrealBloomPass.js +43 -25
  186. package/examples/js/renderers/CSS2DRenderer.js +2 -21
  187. package/examples/js/renderers/CSS3DRenderer.js +3 -24
  188. package/examples/js/renderers/Projector.js +29 -85
  189. package/examples/js/renderers/SVGRenderer.js +4 -50
  190. package/examples/js/shaders/ACESFilmicToneMappingShader.js +3 -6
  191. package/examples/js/shaders/AfterimageShader.js +3 -6
  192. package/examples/js/shaders/BasicShader.js +3 -6
  193. package/examples/js/shaders/BleachBypassShader.js +3 -6
  194. package/examples/js/shaders/BlendShader.js +3 -6
  195. package/examples/js/shaders/BokehShader.js +3 -6
  196. package/examples/js/shaders/BokehShader2.js +4 -13
  197. package/examples/js/shaders/BrightnessContrastShader.js +3 -6
  198. package/examples/js/shaders/ColorCorrectionShader.js +2 -6
  199. package/examples/js/shaders/ColorifyShader.js +2 -6
  200. package/examples/js/shaders/ConvolutionShader.js +5 -10
  201. package/examples/js/shaders/CopyShader.js +3 -6
  202. package/examples/js/shaders/DOFMipMapShader.js +3 -6
  203. package/examples/js/shaders/DepthLimitedBlurShader.js +2 -9
  204. package/examples/js/shaders/DigitalGlitch.js +3 -6
  205. package/examples/js/shaders/DotScreenShader.js +2 -6
  206. package/examples/js/shaders/FXAAShader.js +1 -3
  207. package/examples/js/shaders/FilmShader.js +3 -6
  208. package/examples/js/shaders/FocusShader.js +3 -6
  209. package/examples/js/shaders/FreiChenShader.js +2 -6
  210. package/examples/js/shaders/GammaCorrectionShader.js +3 -6
  211. package/examples/js/shaders/GodRaysShader.js +11 -24
  212. package/examples/js/shaders/HalftoneShader.js +3 -6
  213. package/examples/js/shaders/HorizontalBlurShader.js +3 -6
  214. package/examples/js/shaders/HorizontalTiltShiftShader.js +3 -6
  215. package/examples/js/shaders/HueSaturationShader.js +3 -6
  216. package/examples/js/shaders/KaleidoShader.js +3 -6
  217. package/examples/js/shaders/LuminosityHighPassShader.js +2 -6
  218. package/examples/js/shaders/LuminosityShader.js +3 -6
  219. package/examples/js/shaders/MMDToonShader.js +2 -8
  220. package/examples/js/shaders/MirrorShader.js +3 -6
  221. package/examples/js/shaders/NormalMapShader.js +2 -6
  222. package/examples/js/shaders/RGBShiftShader.js +3 -6
  223. package/examples/js/shaders/SAOShader.js +2 -6
  224. package/examples/js/shaders/SMAAShader.js +6 -18
  225. package/examples/js/shaders/SSAOShader.js +2 -6
  226. package/examples/js/shaders/SSRShader.js +6 -18
  227. package/examples/js/shaders/SepiaShader.js +3 -6
  228. package/examples/js/shaders/SobelOperatorShader.js +2 -6
  229. package/examples/js/shaders/TechnicolorShader.js +3 -6
  230. package/examples/js/shaders/ToneMapShader.js +3 -6
  231. package/examples/js/shaders/ToonShader.js +8 -24
  232. package/examples/js/shaders/TriangleBlurShader.js +2 -6
  233. package/examples/js/shaders/UnpackDepthRGBAShader.js +3 -6
  234. package/examples/js/shaders/VelocityShader.js +126 -0
  235. package/examples/js/shaders/VerticalBlurShader.js +3 -6
  236. package/examples/js/shaders/VerticalTiltShiftShader.js +3 -6
  237. package/examples/js/shaders/VignetteShader.js +3 -6
  238. package/examples/js/shaders/VolumeShader.js +2 -6
  239. package/examples/js/shaders/WaterRefractionShader.js +2 -6
  240. package/examples/js/textures/FlakesTexture.js +0 -1
  241. package/examples/js/utils/BufferGeometryUtils.js +236 -170
  242. package/examples/js/utils/CameraUtils.js +5 -20
  243. package/examples/js/utils/GPUStatsPanel.js +3 -12
  244. package/examples/js/utils/GeometryCompressionUtils.js +19 -44
  245. package/examples/js/utils/GeometryUtils.js +13 -18
  246. package/examples/js/utils/LDrawUtils.js +8 -11
  247. package/examples/js/utils/PackedPhongMaterial.js +6 -4
  248. package/examples/js/utils/SceneUtils.js +117 -6
  249. package/examples/js/utils/ShadowMapViewer.js +17 -14
  250. package/examples/js/utils/SkeletonUtils.js +13 -27
  251. package/examples/js/utils/UVsDebug.js +20 -12
  252. package/examples/js/utils/WorkerPool.js +1 -11
  253. package/examples/jsm/animation/CCDIKSolver.js +27 -3
  254. package/examples/jsm/animation/MMDPhysics.js +25 -0
  255. package/examples/jsm/capabilities/WebGPU.js +3 -1
  256. package/examples/jsm/controls/FirstPersonControls.js +20 -20
  257. package/examples/jsm/controls/FlyControls.js +16 -17
  258. package/examples/jsm/controls/OrbitControls.js +44 -4
  259. package/examples/jsm/controls/TrackballControls.js +14 -2
  260. package/examples/jsm/controls/TransformControls.js +1 -1
  261. package/examples/jsm/csm/CSM.js +1 -0
  262. package/examples/jsm/csm/CSMHelper.js +30 -0
  263. package/examples/jsm/exporters/GLTFExporter.js +0 -79
  264. package/examples/jsm/exporters/USDZExporter.js +93 -1
  265. package/examples/jsm/helpers/OctreeHelper.js +22 -8
  266. package/examples/jsm/helpers/VertexNormalsHelper.js +7 -1
  267. package/examples/jsm/helpers/VertexTangentsHelper.js +7 -0
  268. package/examples/jsm/helpers/ViewHelper.js +24 -0
  269. package/examples/jsm/interactive/HTMLMesh.js +5 -6
  270. package/examples/jsm/interactive/InteractiveGroup.js +4 -2
  271. package/examples/jsm/libs/flow.module.js +610 -160
  272. package/examples/jsm/libs/lottie_canvas.module.js +14844 -0
  273. package/examples/jsm/lines/LineSegments2.js +4 -0
  274. package/examples/jsm/loaders/3DMLoader.js +1 -2
  275. package/examples/jsm/loaders/ColladaLoader.js +28 -0
  276. package/examples/jsm/loaders/FBXLoader.js +18 -2
  277. package/examples/jsm/loaders/GLTFLoader.js +269 -428
  278. package/examples/jsm/loaders/KTX2Loader.js +68 -29
  279. package/examples/jsm/loaders/LDrawLoader.js +14 -13
  280. package/examples/jsm/loaders/LottieLoader.js +4 -2
  281. package/examples/jsm/loaders/MaterialXLoader.js +728 -0
  282. package/examples/jsm/loaders/PCDLoader.js +1 -1
  283. package/examples/jsm/loaders/PLYLoader.js +68 -16
  284. package/examples/jsm/loaders/SVGLoader.js +227 -14
  285. package/examples/jsm/loaders/USDZLoader.js +351 -111
  286. package/examples/jsm/loaders/VRMLLoader.js +13 -1
  287. package/examples/jsm/math/ConvexHull.js +4 -4
  288. package/examples/jsm/math/Octree.js +1 -1
  289. package/examples/jsm/node-editor/NodeEditor.js +91 -12
  290. package/examples/jsm/node-editor/core/BaseNode.js +10 -3
  291. package/examples/jsm/node-editor/materials/BasicMaterialEditor.js +6 -9
  292. package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +6 -9
  293. package/examples/jsm/node-editor/math/AngleEditor.js +3 -3
  294. package/examples/jsm/node-editor/math/InvertEditor.js +2 -2
  295. package/examples/jsm/node-editor/scene/MeshEditor.js +11 -8
  296. package/examples/jsm/node-editor/utils/PreviewEditor.js +4 -0
  297. package/examples/jsm/nodes/Nodes.js +30 -3
  298. package/examples/jsm/nodes/accessors/BitangentNode.js +62 -0
  299. package/examples/jsm/nodes/accessors/NormalNode.js +6 -6
  300. package/examples/jsm/nodes/accessors/Object3DNode.js +1 -1
  301. package/examples/jsm/nodes/accessors/PositionNode.js +6 -0
  302. package/examples/jsm/nodes/accessors/ReferenceNode.js +1 -1
  303. package/examples/jsm/nodes/accessors/SkinningNode.js +8 -1
  304. package/examples/jsm/nodes/accessors/TangentNode.js +95 -0
  305. package/examples/jsm/nodes/core/AttributeNode.js +31 -8
  306. package/examples/jsm/nodes/core/Node.js +1 -1
  307. package/examples/jsm/nodes/core/NodeBuilder.js +55 -6
  308. package/examples/jsm/nodes/core/NodeFrame.js +2 -2
  309. package/examples/jsm/nodes/core/NodeVarying.js +7 -4
  310. package/examples/jsm/nodes/core/VaryingNode.js +6 -4
  311. package/examples/jsm/nodes/core/constants.js +13 -13
  312. package/examples/jsm/nodes/display/BlendModeNode.js +85 -0
  313. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +2 -12
  314. package/examples/jsm/nodes/display/NormalMapNode.js +19 -12
  315. package/examples/jsm/nodes/display/PosterizeNode.js +25 -0
  316. package/examples/jsm/nodes/display/ViewportNode.js +106 -0
  317. package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +5 -5
  318. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +3 -3
  319. package/examples/jsm/nodes/functions/light/getDistanceAttenuation.js +2 -2
  320. package/examples/jsm/nodes/gpgpu/ComputeNode.js +1 -1
  321. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +1 -1
  322. package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +3 -1
  323. package/examples/jsm/nodes/materials/Materials.js +9 -7
  324. package/examples/jsm/nodes/materials/NodeMaterial.js +9 -1
  325. package/examples/jsm/nodes/materialx/{Disclaimer.md → DISCLAIMER.md} +1 -1
  326. package/examples/jsm/nodes/materialx/MaterialXNodes.js +59 -0
  327. package/examples/jsm/nodes/materialx/{functions/lib → lib}/mx_hsv.js +1 -1
  328. package/examples/jsm/nodes/materialx/{functions/lib → lib}/mx_noise.js +13 -3
  329. package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +18 -0
  330. package/examples/jsm/nodes/math/MathNode.js +5 -5
  331. package/examples/jsm/nodes/math/OperatorNode.js +16 -3
  332. package/examples/jsm/nodes/shadernode/ShaderNode.js +35 -20
  333. package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +87 -63
  334. package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +29 -0
  335. package/examples/jsm/nodes/utils/ConvertNode.js +15 -14
  336. package/examples/jsm/nodes/utils/EquirectUVNode.js +27 -0
  337. package/examples/jsm/nodes/utils/JoinNode.js +8 -2
  338. package/examples/jsm/nodes/utils/MatcapUVNode.js +2 -4
  339. package/examples/jsm/nodes/utils/MaxMipLevelNode.js +1 -1
  340. package/examples/jsm/nodes/utils/OscNode.js +2 -2
  341. package/examples/jsm/nodes/utils/RemapNode.js +34 -0
  342. package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +8 -10
  343. package/examples/jsm/nodes/utils/TimerNode.js +21 -1
  344. package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +51 -0
  345. package/examples/jsm/postprocessing/AfterimagePass.js +17 -4
  346. package/examples/jsm/postprocessing/BloomPass.js +22 -3
  347. package/examples/jsm/postprocessing/BokehPass.js +18 -4
  348. package/examples/jsm/postprocessing/CubeTexturePass.js +12 -5
  349. package/examples/jsm/postprocessing/DotScreenPass.js +8 -0
  350. package/examples/jsm/postprocessing/EffectComposer.js +9 -0
  351. package/examples/jsm/postprocessing/FilmPass.js +8 -0
  352. package/examples/jsm/postprocessing/GlitchPass.js +13 -1
  353. package/examples/jsm/postprocessing/HalftonePass.js +8 -0
  354. package/examples/jsm/postprocessing/OutlinePass.js +21 -1
  355. package/examples/jsm/postprocessing/Pass.js +2 -0
  356. package/examples/jsm/postprocessing/RenderPixelatedPass.js +234 -0
  357. package/examples/jsm/postprocessing/SAOPass.js +20 -0
  358. package/examples/jsm/postprocessing/SMAAPass.js +16 -0
  359. package/examples/jsm/postprocessing/SSAARenderPass.js +4 -0
  360. package/examples/jsm/postprocessing/SavePass.js +17 -1
  361. package/examples/jsm/postprocessing/ShaderPass.js +8 -0
  362. package/examples/jsm/postprocessing/TAARenderPass.js +9 -0
  363. package/examples/jsm/postprocessing/TexturePass.js +8 -0
  364. package/examples/jsm/postprocessing/UnrealBloomPass.js +16 -0
  365. package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +56 -35
  366. package/examples/jsm/renderers/webgpu/WebGPUAnimation.js +58 -0
  367. package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +63 -5
  368. package/examples/jsm/renderers/webgpu/WebGPUBackground.js +36 -7
  369. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +47 -12
  370. package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +41 -9
  371. package/examples/jsm/shaders/MMDToonShader.js +0 -2
  372. package/examples/jsm/shaders/VelocityShader.js +128 -0
  373. package/examples/jsm/utils/BufferGeometryUtils.js +174 -42
  374. package/examples/jsm/utils/SceneUtils.js +129 -4
  375. package/examples/jsm/webxr/OculusHandModel.js +3 -2
  376. package/examples/jsm/webxr/XRHandMeshModel.js +8 -3
  377. package/package.json +13 -13
  378. package/src/Three.js +1 -0
  379. package/src/animation/PropertyBinding.js +7 -0
  380. package/src/audio/AudioContext.js +5 -5
  381. package/src/cameras/CubeCamera.js +14 -14
  382. package/src/constants.js +1 -1
  383. package/src/core/InstancedBufferGeometry.js +1 -7
  384. package/src/core/InterleavedBufferAttribute.js +4 -4
  385. package/src/extras/Earcut.js +67 -67
  386. package/src/geometries/PolyhedronGeometry.js +1 -1
  387. package/src/geometries/ShapeGeometry.js +1 -1
  388. package/src/helpers/ArrowHelper.js +9 -0
  389. package/src/helpers/Box3Helper.js +7 -0
  390. package/src/helpers/BoxHelper.js +7 -1
  391. package/src/helpers/DirectionalLightHelper.js +5 -1
  392. package/src/helpers/GridHelper.js +7 -0
  393. package/src/helpers/HemisphereLightHelper.js +4 -1
  394. package/src/helpers/PlaneHelper.js +9 -0
  395. package/src/helpers/PointLightHelper.js +2 -1
  396. package/src/helpers/PolarGridHelper.js +7 -0
  397. package/src/helpers/SkeletonHelper.js +7 -0
  398. package/src/helpers/SpotLightHelper.js +4 -2
  399. package/src/lights/LightShadow.js +1 -2
  400. package/src/lights/PointLight.js +2 -2
  401. package/src/lights/SpotLight.js +2 -2
  402. package/src/loaders/FileLoader.js +4 -1
  403. package/src/loaders/ObjectLoader.js +5 -1
  404. package/src/materials/Material.js +1 -1
  405. package/src/materials/MeshPhysicalMaterial.js +1 -1
  406. package/src/math/Color.js +5 -5
  407. package/src/math/Matrix3.js +53 -18
  408. package/src/math/Ray.js +2 -5
  409. package/src/math/Sphere.js +36 -21
  410. package/src/objects/InstancedMesh.js +7 -0
  411. package/src/objects/LOD.js +25 -6
  412. package/src/renderers/WebGL3DRenderTarget.js +1 -1
  413. package/src/renderers/WebGLArrayRenderTarget.js +1 -1
  414. package/src/renderers/WebGLCubeRenderTarget.js +1 -1
  415. package/src/renderers/WebGLMultipleRenderTargets.js +1 -1
  416. package/src/renderers/WebGLRenderTarget.js +1 -1
  417. package/src/renderers/WebGLRenderer.js +36 -62
  418. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -4
  419. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +0 -1
  420. package/src/renderers/shaders/ShaderChunk/lights_lambert_pars_fragment.glsl.js +0 -2
  421. package/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js +0 -2
  422. package/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js +0 -2
  423. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -4
  424. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +8 -0
  425. package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +2 -2
  426. package/src/renderers/shaders/ShaderChunk.js +3 -0
  427. package/src/renderers/shaders/ShaderLib/background.glsl.js +7 -2
  428. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +62 -0
  429. package/src/renderers/shaders/ShaderLib/cube.glsl.js +4 -6
  430. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +0 -3
  431. package/src/renderers/shaders/ShaderLib.js +20 -6
  432. package/src/renderers/shaders/UniformsLib.js +1 -1
  433. package/src/renderers/shaders/UniformsUtils.js +15 -0
  434. package/src/renderers/webgl/WebGLAttributes.js +2 -0
  435. package/src/renderers/webgl/WebGLBackground.js +15 -7
  436. package/src/renderers/webgl/WebGLLights.js +0 -4
  437. package/src/renderers/webgl/WebGLMaterials.js +2 -1
  438. package/src/renderers/webgl/WebGLShadowMap.js +3 -1
  439. package/src/renderers/webgl/WebGLState.js +78 -41
  440. package/src/renderers/webgl/WebGLTextures.js +94 -39
  441. package/src/renderers/webgl/WebGLUniforms.js +152 -24
  442. package/src/renderers/webgl/WebGLUtils.js +1 -1
  443. package/src/renderers/webxr/WebXRController.js +46 -13
  444. package/src/renderers/webxr/WebXRManager.js +71 -3
  445. package/src/scenes/Scene.js +8 -0
  446. package/src/textures/CompressedArrayTexture.js +18 -0
  447. package/src/textures/Texture.js +2 -1
  448. package/examples/js/libs/lottie_canvas.js +0 -12751
  449. package/examples/js/shaders/PixelShader.js +0 -51
  450. package/examples/jsm/shaders/PixelShader.js +0 -44
@@ -14,11 +14,6 @@
14
14
 
15
15
  return new GLTFMaterialsUnlitExtension( writer );
16
16
 
17
- } );
18
- this.register( function ( writer ) {
19
-
20
- return new GLTFMaterialsPBRSpecularGlossiness( writer );
21
-
22
17
  } );
23
18
  this.register( function ( writer ) {
24
19
 
@@ -42,7 +37,6 @@
42
37
  } );
43
38
 
44
39
  }
45
-
46
40
  register( callback ) {
47
41
 
48
42
  if ( this.pluginCallbacks.indexOf( callback ) === - 1 ) {
@@ -54,7 +48,6 @@
54
48
  return this;
55
49
 
56
50
  }
57
-
58
51
  unregister( callback ) {
59
52
 
60
53
  if ( this.pluginCallbacks.indexOf( callback ) !== - 1 ) {
@@ -66,6 +59,7 @@
66
59
  return this;
67
60
 
68
61
  }
62
+
69
63
  /**
70
64
  * Parse scenes and generate GLTF output
71
65
  * @param {Scene or [THREE.Scenes]} input THREE.Scene or Array of THREE.Scenes
@@ -73,13 +67,10 @@
73
67
  * @param {Function} onError Callback on errors
74
68
  * @param {Object} options options
75
69
  */
76
-
77
-
78
70
  parse( input, onDone, onError, options ) {
79
71
 
80
72
  const writer = new GLTFWriter();
81
73
  const plugins = [];
82
-
83
74
  for ( let i = 0, il = this.pluginCallbacks.length; i < il; i ++ ) {
84
75
 
85
76
  plugins.push( this.pluginCallbacks[ i ]( writer ) );
@@ -90,7 +81,6 @@
90
81
  writer.write( input, onDone, options ).catch( onError );
91
82
 
92
83
  }
93
-
94
84
  parseAsync( input, options ) {
95
85
 
96
86
  const scope = this;
@@ -102,11 +92,12 @@
102
92
 
103
93
  }
104
94
 
105
- } //------------------------------------------------------------------------------
95
+ }
96
+
97
+ //------------------------------------------------------------------------------
106
98
  // Constants
107
99
  //------------------------------------------------------------------------------
108
100
 
109
-
110
101
  const WEBGL_CONSTANTS = {
111
102
  POINTS: 0x0000,
112
103
  LINES: 0x0001,
@@ -146,7 +137,9 @@
146
137
  position: 'translation',
147
138
  quaternion: 'rotation',
148
139
  morphTargetInfluences: 'weights'
149
- }; // GLB constants
140
+ };
141
+
142
+ // GLB constants
150
143
  // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#glb-file-format-specification
151
144
 
152
145
  const GLB_HEADER_BYTES = 12;
@@ -154,7 +147,9 @@
154
147
  const GLB_VERSION = 2;
155
148
  const GLB_CHUNK_PREFIX_BYTES = 8;
156
149
  const GLB_CHUNK_TYPE_JSON = 0x4E4F534A;
157
- const GLB_CHUNK_TYPE_BIN = 0x004E4942; //------------------------------------------------------------------------------
150
+ const GLB_CHUNK_TYPE_BIN = 0x004E4942;
151
+
152
+ //------------------------------------------------------------------------------
158
153
  // Utility functions
159
154
  //------------------------------------------------------------------------------
160
155
 
@@ -164,7 +159,6 @@
164
159
  * @param {Array} array2 Array 2 to compare
165
160
  * @return {Boolean} Returns true if both arrays are equal
166
161
  */
167
-
168
162
  function equalArray( array1, array2 ) {
169
163
 
170
164
  return array1.length === array2.length && array1.every( function ( element, index ) {
@@ -174,31 +168,30 @@
174
168
  } );
175
169
 
176
170
  }
171
+
177
172
  /**
178
173
  * Converts a string to an ArrayBuffer.
179
174
  * @param {string} text
180
175
  * @return {ArrayBuffer}
181
176
  */
182
-
183
-
184
177
  function stringToArrayBuffer( text ) {
185
178
 
186
179
  return new TextEncoder().encode( text ).buffer;
187
180
 
188
181
  }
182
+
189
183
  /**
190
184
  * Is identity matrix
191
185
  *
192
186
  * @param {Matrix4} matrix
193
187
  * @returns {Boolean} Returns true, if parameter is identity matrix
194
188
  */
195
-
196
-
197
189
  function isIdentityMatrix( matrix ) {
198
190
 
199
191
  return equalArray( matrix.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] );
200
192
 
201
193
  }
194
+
202
195
  /**
203
196
  * Get the min and max vectors from the given attribute
204
197
  * @param {BufferAttribute} attribute Attribute to find the min/max in range from start to start + count
@@ -206,24 +199,21 @@
206
199
  * @param {Integer} count
207
200
  * @return {Object} Object containing the `min` and `max` values (As an array of attribute.itemSize components)
208
201
  */
209
-
210
-
211
202
  function getMinMax( attribute, start, count ) {
212
203
 
213
204
  const output = {
214
205
  min: new Array( attribute.itemSize ).fill( Number.POSITIVE_INFINITY ),
215
206
  max: new Array( attribute.itemSize ).fill( Number.NEGATIVE_INFINITY )
216
207
  };
217
-
218
208
  for ( let i = start; i < start + count; i ++ ) {
219
209
 
220
210
  for ( let a = 0; a < attribute.itemSize; a ++ ) {
221
211
 
222
212
  let value;
223
-
224
213
  if ( attribute.itemSize > 4 ) {
225
214
 
226
215
  // no support for interleaved data for itemSize > 4
216
+
227
217
  value = attribute.array[ i * attribute.itemSize + a ];
228
218
 
229
219
  } else {
@@ -242,6 +232,7 @@
242
232
  return output;
243
233
 
244
234
  }
235
+
245
236
  /**
246
237
  * Get the required size + padding for a buffer, rounded to the next 4-byte boundary.
247
238
  * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
@@ -250,13 +241,12 @@
250
241
  * @returns {Integer} new buffer size with required padding.
251
242
  *
252
243
  */
253
-
254
-
255
244
  function getPaddedBufferSize( bufferSize ) {
256
245
 
257
246
  return Math.ceil( bufferSize / 4 ) * 4;
258
247
 
259
248
  }
249
+
260
250
  /**
261
251
  * Returns a buffer aligned to 4-byte boundary.
262
252
  *
@@ -264,17 +254,13 @@
264
254
  * @param {Integer} paddingByte (Optional)
265
255
  * @returns {ArrayBuffer} The same buffer if it's already aligned to 4-byte boundary or a new buffer
266
256
  */
267
-
268
-
269
257
  function getPaddedArrayBuffer( arrayBuffer, paddingByte = 0 ) {
270
258
 
271
259
  const paddedLength = getPaddedBufferSize( arrayBuffer.byteLength );
272
-
273
260
  if ( paddedLength !== arrayBuffer.byteLength ) {
274
261
 
275
262
  const array = new Uint8Array( paddedLength );
276
263
  array.set( new Uint8Array( arrayBuffer ) );
277
-
278
264
  if ( paddingByte !== 0 ) {
279
265
 
280
266
  for ( let i = arrayBuffer.byteLength; i < paddedLength; i ++ ) {
@@ -313,9 +299,10 @@
313
299
 
314
300
  }
315
301
 
316
- let quality; // Blink's implementation of convertToBlob seems to default to a quality level of 100%
317
- // Use the Blink default quality levels of toBlob instead so that file sizes are comparable.
302
+ let quality;
318
303
 
304
+ // Blink's implementation of convertToBlob seems to default to a quality level of 100%
305
+ // Use the Blink default quality levels of toBlob instead so that file sizes are comparable.
319
306
  if ( mimeType === 'image/jpeg' ) {
320
307
 
321
308
  quality = 0.92;
@@ -332,11 +319,10 @@
332
319
  } );
333
320
 
334
321
  }
322
+
335
323
  /**
336
324
  * Writer
337
325
  */
338
-
339
-
340
326
  class GLTFWriter {
341
327
 
342
328
  constructor() {
@@ -368,20 +354,18 @@
368
354
  };
369
355
 
370
356
  }
371
-
372
357
  setPlugins( plugins ) {
373
358
 
374
359
  this.plugins = plugins;
375
360
 
376
361
  }
362
+
377
363
  /**
378
364
  * Parse scenes and generate GLTF output
379
365
  * @param {Scene or [THREE.Scenes]} input THREE.Scene or Array of THREE.Scenes
380
366
  * @param {Function} onDone Callback on completed
381
367
  * @param {Object} options options
382
368
  */
383
-
384
-
385
369
  async write( input, onDone, options ) {
386
370
 
387
371
  this.options = Object.assign( {}, {
@@ -389,12 +373,10 @@
389
373
  binary: false,
390
374
  trs: false,
391
375
  onlyVisible: true,
392
- truncateDrawRange: true,
393
376
  maxTextureSize: Infinity,
394
377
  animations: [],
395
378
  includeCustomExtensions: false
396
379
  }, options );
397
-
398
380
  if ( this.options.animations.length > 0 ) {
399
381
 
400
382
  // Only TRS properties, and not matrices, may be targeted by animation.
@@ -408,36 +390,40 @@
408
390
  const buffers = writer.buffers;
409
391
  const json = writer.json;
410
392
  options = writer.options;
411
- const extensionsUsed = writer.extensionsUsed; // Merge buffers.
393
+ const extensionsUsed = writer.extensionsUsed;
412
394
 
395
+ // Merge buffers.
413
396
  const blob = new Blob( buffers, {
414
397
  type: 'application/octet-stream'
415
- } ); // Declare extensions.
398
+ } );
416
399
 
400
+ // Declare extensions.
417
401
  const extensionsUsedList = Object.keys( extensionsUsed );
418
- if ( extensionsUsedList.length > 0 ) json.extensionsUsed = extensionsUsedList; // Update bytelength of the single buffer.
402
+ if ( extensionsUsedList.length > 0 ) json.extensionsUsed = extensionsUsedList;
419
403
 
404
+ // Update bytelength of the single buffer.
420
405
  if ( json.buffers && json.buffers.length > 0 ) json.buffers[ 0 ].byteLength = blob.size;
421
-
422
406
  if ( options.binary === true ) {
423
407
 
424
408
  // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#glb-file-format-specification
409
+
425
410
  const reader = new FileReader();
426
411
  reader.readAsArrayBuffer( blob );
427
-
428
412
  reader.onloadend = function () {
429
413
 
430
414
  // Binary chunk.
431
415
  const binaryChunk = getPaddedArrayBuffer( reader.result );
432
416
  const binaryChunkPrefix = new DataView( new ArrayBuffer( GLB_CHUNK_PREFIX_BYTES ) );
433
417
  binaryChunkPrefix.setUint32( 0, binaryChunk.byteLength, true );
434
- binaryChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_BIN, true ); // JSON chunk.
418
+ binaryChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_BIN, true );
435
419
 
420
+ // JSON chunk.
436
421
  const jsonChunk = getPaddedArrayBuffer( stringToArrayBuffer( JSON.stringify( json ) ), 0x20 );
437
422
  const jsonChunkPrefix = new DataView( new ArrayBuffer( GLB_CHUNK_PREFIX_BYTES ) );
438
423
  jsonChunkPrefix.setUint32( 0, jsonChunk.byteLength, true );
439
- jsonChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_JSON, true ); // GLB header.
424
+ jsonChunkPrefix.setUint32( 4, GLB_CHUNK_TYPE_JSON, true );
440
425
 
426
+ // GLB header.
441
427
  const header = new ArrayBuffer( GLB_HEADER_BYTES );
442
428
  const headerView = new DataView( header );
443
429
  headerView.setUint32( 0, GLB_HEADER_MAGIC, true );
@@ -449,7 +435,6 @@
449
435
  } );
450
436
  const glbReader = new FileReader();
451
437
  glbReader.readAsArrayBuffer( glbBlob );
452
-
453
438
  glbReader.onloadend = function () {
454
439
 
455
440
  onDone( glbReader.result );
@@ -464,7 +449,6 @@
464
449
 
465
450
  const reader = new FileReader();
466
451
  reader.readAsDataURL( blob );
467
-
468
452
  reader.onloadend = function () {
469
453
 
470
454
  const base64data = reader.result;
@@ -482,28 +466,24 @@
482
466
  }
483
467
 
484
468
  }
469
+
485
470
  /**
486
471
  * Serializes a userData.
487
472
  *
488
473
  * @param {THREE.Object3D|THREE.Material} object
489
474
  * @param {Object} objectDef
490
475
  */
491
-
492
-
493
476
  serializeUserData( object, objectDef ) {
494
477
 
495
478
  if ( Object.keys( object.userData ).length === 0 ) return;
496
479
  const options = this.options;
497
480
  const extensionsUsed = this.extensionsUsed;
498
-
499
481
  try {
500
482
 
501
483
  const json = JSON.parse( JSON.stringify( object.userData ) );
502
-
503
484
  if ( options.includeCustomExtensions && json.gltfExtensions ) {
504
485
 
505
486
  if ( objectDef.extensions === undefined ) objectDef.extensions = {};
506
-
507
487
  for ( const extensionName in json.gltfExtensions ) {
508
488
 
509
489
  objectDef.extensions[ extensionName ] = json.gltfExtensions[ extensionName ];
@@ -524,13 +504,12 @@
524
504
  }
525
505
 
526
506
  }
507
+
527
508
  /**
528
509
  * Returns ids for buffer attributes.
529
510
  * @param {Object} object
530
511
  * @return {Integer}
531
512
  */
532
-
533
-
534
513
  getUID( attribute, isRelativeCopy = false ) {
535
514
 
536
515
  if ( this.uids.has( attribute ) === false ) {
@@ -546,20 +525,18 @@
546
525
  return uids.get( isRelativeCopy );
547
526
 
548
527
  }
528
+
549
529
  /**
550
530
  * Checks if normal attribute values are normalized.
551
531
  *
552
532
  * @param {BufferAttribute} normal
553
533
  * @returns {Boolean}
554
534
  */
555
-
556
-
557
535
  isNormalizedNormalAttribute( normal ) {
558
536
 
559
537
  const cache = this.cache;
560
538
  if ( cache.attributesNormalized.has( normal ) ) return false;
561
539
  const v = new THREE.Vector3();
562
-
563
540
  for ( let i = 0, il = normal.count; i < il; i ++ ) {
564
541
 
565
542
  // 0.0005 is from glTF-validator
@@ -570,6 +547,7 @@
570
547
  return true;
571
548
 
572
549
  }
550
+
573
551
  /**
574
552
  * Creates normalized normal buffer attribute.
575
553
  *
@@ -577,19 +555,15 @@
577
555
  * @returns {BufferAttribute}
578
556
  *
579
557
  */
580
-
581
-
582
558
  createNormalizedNormalAttribute( normal ) {
583
559
 
584
560
  const cache = this.cache;
585
561
  if ( cache.attributesNormalized.has( normal ) ) return cache.attributesNormalized.get( normal );
586
562
  const attribute = normal.clone();
587
563
  const v = new THREE.Vector3();
588
-
589
564
  for ( let i = 0, il = attribute.count; i < il; i ++ ) {
590
565
 
591
566
  v.fromBufferAttribute( attribute, i );
592
-
593
567
  if ( v.x === 0 && v.y === 0 && v.z === 0 ) {
594
568
 
595
569
  // if values can't be normalized set (1, 0, 0)
@@ -609,6 +583,7 @@
609
583
  return attribute;
610
584
 
611
585
  }
586
+
612
587
  /**
613
588
  * Applies a texture transform, if present, to the map definition. Requires
614
589
  * the KHR_texture_transform extension.
@@ -616,13 +591,10 @@
616
591
  * @param {Object} mapDef
617
592
  * @param {THREE.Texture} texture
618
593
  */
619
-
620
-
621
594
  applyTextureTransform( mapDef, texture ) {
622
595
 
623
596
  let didTransform = false;
624
597
  const transformDef = {};
625
-
626
598
  if ( texture.offset.x !== 0 || texture.offset.y !== 0 ) {
627
599
 
628
600
  transformDef.offset = texture.offset.toArray();
@@ -653,11 +625,9 @@
653
625
  }
654
626
 
655
627
  }
656
-
657
628
  buildMetalRoughTexture( metalnessMap, roughnessMap ) {
658
629
 
659
630
  if ( metalnessMap === roughnessMap ) return metalnessMap;
660
-
661
631
  function getEncodingConversion( map ) {
662
632
 
663
633
  if ( map.encoding === THREE.sRGBEncoding ) {
@@ -690,13 +660,11 @@
690
660
  context.fillStyle = '#00ffff';
691
661
  context.fillRect( 0, 0, width, height );
692
662
  const composite = context.getImageData( 0, 0, width, height );
693
-
694
663
  if ( metalness ) {
695
664
 
696
665
  context.drawImage( metalness, 0, 0, width, height );
697
666
  const convert = getEncodingConversion( metalnessMap );
698
667
  const data = context.getImageData( 0, 0, width, height ).data;
699
-
700
668
  for ( let i = 2; i < data.length; i += 4 ) {
701
669
 
702
670
  composite.data[ i ] = convert( data[ i ] / 256 ) * 256;
@@ -710,7 +678,6 @@
710
678
  context.drawImage( roughness, 0, 0, width, height );
711
679
  const convert = getEncodingConversion( roughnessMap );
712
680
  const data = context.getImageData( 0, 0, width, height ).data;
713
-
714
681
  for ( let i = 1; i < data.length; i += 4 ) {
715
682
 
716
683
  composite.data[ i ] = convert( data[ i ] / 256 ) * 256;
@@ -719,7 +686,9 @@
719
686
 
720
687
  }
721
688
 
722
- context.putImageData( composite, 0, 0 ); //
689
+ context.putImageData( composite, 0, 0 );
690
+
691
+ //
723
692
 
724
693
  const reference = metalnessMap || roughnessMap;
725
694
  const texture = reference.clone();
@@ -728,25 +697,26 @@
728
697
  return texture;
729
698
 
730
699
  }
700
+
731
701
  /**
732
702
  * Process a buffer to append to the default one.
733
703
  * @param {ArrayBuffer} buffer
734
704
  * @return {Integer}
735
705
  */
736
-
737
-
738
706
  processBuffer( buffer ) {
739
707
 
740
708
  const json = this.json;
741
709
  const buffers = this.buffers;
742
710
  if ( ! json.buffers ) json.buffers = [ {
743
711
  byteLength: 0
744
- } ]; // All buffers are merged before export.
712
+ } ];
745
713
 
714
+ // All buffers are merged before export.
746
715
  buffers.push( buffer );
747
716
  return 0;
748
717
 
749
718
  }
719
+
750
720
  /**
751
721
  * Process and generate a BufferView
752
722
  * @param {BufferAttribute} attribute
@@ -756,15 +726,14 @@
756
726
  * @param {number} target (Optional) Target usage of the BufferView
757
727
  * @return {Object}
758
728
  */
759
-
760
-
761
729
  processBufferView( attribute, componentType, start, count, target ) {
762
730
 
763
731
  const json = this.json;
764
- if ( ! json.bufferViews ) json.bufferViews = []; // Create a new dataview and dump the attribute's array into it
732
+ if ( ! json.bufferViews ) json.bufferViews = [];
765
733
 
766
- let componentSize;
734
+ // Create a new dataview and dump the attribute's array into it
767
735
 
736
+ let componentSize;
768
737
  if ( componentType === WEBGL_CONSTANTS.UNSIGNED_BYTE ) {
769
738
 
770
739
  componentSize = 1;
@@ -782,16 +751,15 @@
782
751
  const byteLength = getPaddedBufferSize( count * attribute.itemSize * componentSize );
783
752
  const dataView = new DataView( new ArrayBuffer( byteLength ) );
784
753
  let offset = 0;
785
-
786
754
  for ( let i = start; i < start + count; i ++ ) {
787
755
 
788
756
  for ( let a = 0; a < attribute.itemSize; a ++ ) {
789
757
 
790
758
  let value;
791
-
792
759
  if ( attribute.itemSize > 4 ) {
793
760
 
794
761
  // no support for interleaved data for itemSize > 4
762
+
795
763
  value = attribute.array[ i * attribute.itemSize + a ];
796
764
 
797
765
  } else {
@@ -830,7 +798,6 @@
830
798
  byteLength: byteLength
831
799
  };
832
800
  if ( target !== undefined ) bufferViewDef.target = target;
833
-
834
801
  if ( target === WEBGL_CONSTANTS.ARRAY_BUFFER ) {
835
802
 
836
803
  // Only define byteStride for vertex attributes.
@@ -839,8 +806,9 @@
839
806
  }
840
807
 
841
808
  this.byteOffset += byteLength;
842
- json.bufferViews.push( bufferViewDef ); // @TODO Merge bufferViews where possible.
809
+ json.bufferViews.push( bufferViewDef );
843
810
 
811
+ // @TODO Merge bufferViews where possible.
844
812
  const output = {
845
813
  id: json.bufferViews.length - 1,
846
814
  byteLength: 0
@@ -848,13 +816,12 @@
848
816
  return output;
849
817
 
850
818
  }
819
+
851
820
  /**
852
821
  * Process and generate a BufferView from an image Blob.
853
822
  * @param {Blob} blob
854
823
  * @return {Promise<Integer>}
855
824
  */
856
-
857
-
858
825
  processBufferViewImage( blob ) {
859
826
 
860
827
  const writer = this;
@@ -864,7 +831,6 @@
864
831
 
865
832
  const reader = new FileReader();
866
833
  reader.readAsArrayBuffer( blob );
867
-
868
834
  reader.onloadend = function () {
869
835
 
870
836
  const buffer = getPaddedArrayBuffer( reader.result );
@@ -881,6 +847,7 @@
881
847
  } );
882
848
 
883
849
  }
850
+
884
851
  /**
885
852
  * Process attribute to generate an accessor
886
853
  * @param {BufferAttribute} attribute Attribute to process
@@ -889,11 +856,8 @@
889
856
  * @param {Integer} count (Optional)
890
857
  * @return {Integer|null} Index of the processed accessor on the "accessors" array
891
858
  */
892
-
893
-
894
859
  processAccessor( attribute, geometry, start, count ) {
895
860
 
896
- const options = this.options;
897
861
  const json = this.json;
898
862
  const types = {
899
863
  1: 'SCALAR',
@@ -902,8 +866,9 @@
902
866
  4: 'VEC4',
903
867
  16: 'MAT4'
904
868
  };
905
- let componentType; // Detect the component type of the attribute array (float, uint or ushort)
869
+ let componentType;
906
870
 
871
+ // Detect the component type of the attribute array (float, uint or ushort)
907
872
  if ( attribute.array.constructor === Float32Array ) {
908
873
 
909
874
  componentType = WEBGL_CONSTANTS.FLOAT;
@@ -927,24 +892,15 @@
927
892
  }
928
893
 
929
894
  if ( start === undefined ) start = 0;
930
- if ( count === undefined ) count = attribute.count; // @TODO Indexed buffer geometry with drawRange not supported yet
931
-
932
- if ( options.truncateDrawRange && geometry !== undefined && geometry.index === null ) {
933
-
934
- const end = start + count;
935
- const end2 = geometry.drawRange.count === Infinity ? attribute.count : geometry.drawRange.start + geometry.drawRange.count;
936
- start = Math.max( start, geometry.drawRange.start );
937
- count = Math.min( end, end2 ) - start;
938
- if ( count < 0 ) count = 0;
939
-
940
- } // Skip creating an accessor if the attribute doesn't have data to export
941
-
895
+ if ( count === undefined ) count = attribute.count;
942
896
 
897
+ // Skip creating an accessor if the attribute doesn't have data to export
943
898
  if ( count === 0 ) return null;
944
899
  const minMax = getMinMax( attribute, start, count );
945
- let bufferViewTarget; // If geometry isn't provided, don't infer the target usage of the bufferView. For
946
- // animation samplers, target must not be set.
900
+ let bufferViewTarget;
947
901
 
902
+ // If geometry isn't provided, don't infer the target usage of the bufferView. For
903
+ // animation samplers, target must not be set.
948
904
  if ( geometry !== undefined ) {
949
905
 
950
906
  bufferViewTarget = attribute === geometry.index ? WEBGL_CONSTANTS.ELEMENT_ARRAY_BUFFER : WEBGL_CONSTANTS.ARRAY_BUFFER;
@@ -966,6 +922,7 @@
966
922
  return json.accessors.push( accessorDef ) - 1;
967
923
 
968
924
  }
925
+
969
926
  /**
970
927
  * Process image
971
928
  * @param {Image} image to process
@@ -974,8 +931,6 @@
974
931
  * @param {String} mimeType export format
975
932
  * @return {Integer} Index of the processed texture in the "images" array
976
933
  */
977
-
978
-
979
934
  processImage( image, format, flipY, mimeType = 'image/png' ) {
980
935
 
981
936
  const writer = this;
@@ -995,7 +950,6 @@
995
950
  canvas.width = Math.min( image.width, options.maxTextureSize );
996
951
  canvas.height = Math.min( image.height, options.maxTextureSize );
997
952
  const ctx = canvas.getContext( '2d' );
998
-
999
953
  if ( flipY === true ) {
1000
954
 
1001
955
  ctx.translate( 0, canvas.height );
@@ -1006,6 +960,7 @@
1006
960
  if ( image.data !== undefined ) {
1007
961
 
1008
962
  // THREE.DataTexture
963
+
1009
964
  if ( format !== THREE.RGBAFormat ) {
1010
965
 
1011
966
  console.error( 'GLTFExporter: Only THREE.RGBAFormat is supported.' );
@@ -1019,7 +974,6 @@
1019
974
  }
1020
975
 
1021
976
  const data = new Uint8ClampedArray( image.height * image.width * 4 );
1022
-
1023
977
  for ( let i = 0; i < data.length; i += 4 ) {
1024
978
 
1025
979
  data[ i + 0 ] = image.data[ i + 0 ];
@@ -1068,13 +1022,12 @@
1068
1022
  return index;
1069
1023
 
1070
1024
  }
1025
+
1071
1026
  /**
1072
1027
  * Process sampler
1073
1028
  * @param {Texture} map Texture to process
1074
1029
  * @return {Integer} Index of the processed texture in the "samplers" array
1075
1030
  */
1076
-
1077
-
1078
1031
  processSampler( map ) {
1079
1032
 
1080
1033
  const json = this.json;
@@ -1088,13 +1041,12 @@
1088
1041
  return json.samplers.push( samplerDef ) - 1;
1089
1042
 
1090
1043
  }
1044
+
1091
1045
  /**
1092
1046
  * Process texture
1093
1047
  * @param {Texture} map Map to process
1094
1048
  * @return {Integer} Index of the processed texture in the "textures" array
1095
1049
  */
1096
-
1097
-
1098
1050
  processTexture( map ) {
1099
1051
 
1100
1052
  const cache = this.cache;
@@ -1108,31 +1060,27 @@
1108
1060
  source: this.processImage( map.image, map.format, map.flipY, mimeType )
1109
1061
  };
1110
1062
  if ( map.name ) textureDef.name = map.name;
1111
-
1112
1063
  this._invokeAll( function ( ext ) {
1113
1064
 
1114
1065
  ext.writeTexture && ext.writeTexture( map, textureDef );
1115
1066
 
1116
1067
  } );
1117
-
1118
1068
  const index = json.textures.push( textureDef ) - 1;
1119
1069
  cache.textures.set( map, index );
1120
1070
  return index;
1121
1071
 
1122
1072
  }
1073
+
1123
1074
  /**
1124
1075
  * Process material
1125
1076
  * @param {THREE.Material} material Material to process
1126
1077
  * @return {Integer|null} Index of the processed material in the "materials" array
1127
1078
  */
1128
-
1129
-
1130
1079
  processMaterial( material ) {
1131
1080
 
1132
1081
  const cache = this.cache;
1133
1082
  const json = this.json;
1134
1083
  if ( cache.materials.has( material ) ) return cache.materials.get( material );
1135
-
1136
1084
  if ( material.isShaderMaterial ) {
1137
1085
 
1138
1086
  console.warn( 'GLTFExporter: THREE.ShaderMaterial not supported.' );
@@ -1140,21 +1088,20 @@
1140
1088
 
1141
1089
  }
1142
1090
 
1143
- if ( ! json.materials ) json.materials = []; // @QUESTION Should we avoid including any attribute that has the default value?
1091
+ if ( ! json.materials ) json.materials = [];
1144
1092
 
1093
+ // @QUESTION Should we avoid including any attribute that has the default value?
1145
1094
  const materialDef = {
1146
1095
  pbrMetallicRoughness: {}
1147
1096
  };
1148
-
1149
1097
  if ( material.isMeshStandardMaterial !== true && material.isMeshBasicMaterial !== true ) {
1150
1098
 
1151
1099
  console.warn( 'GLTFExporter: Use MeshStandardMaterial or MeshBasicMaterial for best results.' );
1152
1100
 
1153
- } // pbrMetallicRoughness.baseColorFactor
1154
-
1101
+ }
1155
1102
 
1103
+ // pbrMetallicRoughness.baseColorFactor
1156
1104
  const color = material.color.toArray().concat( [ material.opacity ] );
1157
-
1158
1105
  if ( ! equalArray( color, [ 1, 1, 1, 1 ] ) ) {
1159
1106
 
1160
1107
  materialDef.pbrMetallicRoughness.baseColorFactor = color;
@@ -1171,9 +1118,9 @@
1171
1118
  materialDef.pbrMetallicRoughness.metallicFactor = 0.5;
1172
1119
  materialDef.pbrMetallicRoughness.roughnessFactor = 0.5;
1173
1120
 
1174
- } // pbrMetallicRoughness.metallicRoughnessTexture
1175
-
1121
+ }
1176
1122
 
1123
+ // pbrMetallicRoughness.metallicRoughnessTexture
1177
1124
  if ( material.metalnessMap || material.roughnessMap ) {
1178
1125
 
1179
1126
  const metalRoughTexture = this.buildMetalRoughTexture( material.metalnessMap, material.roughnessMap );
@@ -1183,9 +1130,9 @@
1183
1130
  this.applyTextureTransform( metalRoughMapDef, metalRoughTexture );
1184
1131
  materialDef.pbrMetallicRoughness.metallicRoughnessTexture = metalRoughMapDef;
1185
1132
 
1186
- } // pbrMetallicRoughness.baseColorTexture or pbrSpecularGlossiness diffuseTexture
1187
-
1133
+ }
1188
1134
 
1135
+ // pbrMetallicRoughness.baseColorTexture or pbrSpecularGlossiness diffuseTexture
1189
1136
  if ( material.map ) {
1190
1137
 
1191
1138
  const baseColorMapDef = {
@@ -1201,7 +1148,6 @@
1201
1148
  // note: emissive components are limited to stay within the 0 - 1 range to accommodate glTF spec. see #21849 and #22000.
1202
1149
  const emissive = material.emissive.clone().multiplyScalar( material.emissiveIntensity );
1203
1150
  const maxEmissiveComponent = Math.max( emissive.r, emissive.g, emissive.b );
1204
-
1205
1151
  if ( maxEmissiveComponent > 1 ) {
1206
1152
 
1207
1153
  emissive.multiplyScalar( 1 / maxEmissiveComponent );
@@ -1213,9 +1159,9 @@
1213
1159
 
1214
1160
  materialDef.emissiveFactor = emissive.toArray();
1215
1161
 
1216
- } // emissiveTexture
1217
-
1162
+ }
1218
1163
 
1164
+ // emissiveTexture
1219
1165
  if ( material.emissiveMap ) {
1220
1166
 
1221
1167
  const emissiveMapDef = {
@@ -1226,15 +1172,14 @@
1226
1172
 
1227
1173
  }
1228
1174
 
1229
- } // normalTexture
1230
-
1175
+ }
1231
1176
 
1177
+ // normalTexture
1232
1178
  if ( material.normalMap ) {
1233
1179
 
1234
1180
  const normalMapDef = {
1235
1181
  index: this.processTexture( material.normalMap )
1236
1182
  };
1237
-
1238
1183
  if ( material.normalScale && material.normalScale.x !== 1 ) {
1239
1184
 
1240
1185
  // glTF normal scale is univariate. Ignore `y`, which may be flipped.
@@ -1246,16 +1191,15 @@
1246
1191
  this.applyTextureTransform( normalMapDef, material.normalMap );
1247
1192
  materialDef.normalTexture = normalMapDef;
1248
1193
 
1249
- } // occlusionTexture
1250
-
1194
+ }
1251
1195
 
1196
+ // occlusionTexture
1252
1197
  if ( material.aoMap ) {
1253
1198
 
1254
1199
  const occlusionMapDef = {
1255
1200
  index: this.processTexture( material.aoMap ),
1256
1201
  texCoord: 1
1257
1202
  };
1258
-
1259
1203
  if ( material.aoMapIntensity !== 1.0 ) {
1260
1204
 
1261
1205
  occlusionMapDef.strength = material.aoMapIntensity;
@@ -1265,9 +1209,9 @@
1265
1209
  this.applyTextureTransform( occlusionMapDef, material.aoMap );
1266
1210
  materialDef.occlusionTexture = occlusionMapDef;
1267
1211
 
1268
- } // alphaMode
1269
-
1212
+ }
1270
1213
 
1214
+ // alphaMode
1271
1215
  if ( material.transparent ) {
1272
1216
 
1273
1217
  materialDef.alphaMode = 'BLEND';
@@ -1281,37 +1225,33 @@
1281
1225
 
1282
1226
  }
1283
1227
 
1284
- } // doubleSided
1285
-
1228
+ }
1286
1229
 
1230
+ // doubleSided
1287
1231
  if ( material.side === THREE.DoubleSide ) materialDef.doubleSided = true;
1288
1232
  if ( material.name !== '' ) materialDef.name = material.name;
1289
1233
  this.serializeUserData( material, materialDef );
1290
-
1291
1234
  this._invokeAll( function ( ext ) {
1292
1235
 
1293
1236
  ext.writeMaterial && ext.writeMaterial( material, materialDef );
1294
1237
 
1295
1238
  } );
1296
-
1297
1239
  const index = json.materials.push( materialDef ) - 1;
1298
1240
  cache.materials.set( material, index );
1299
1241
  return index;
1300
1242
 
1301
1243
  }
1244
+
1302
1245
  /**
1303
1246
  * Process mesh
1304
1247
  * @param {THREE.Mesh} mesh Mesh to process
1305
1248
  * @return {Integer|null} Index of the processed mesh in the "meshes" array
1306
1249
  */
1307
-
1308
-
1309
1250
  processMesh( mesh ) {
1310
1251
 
1311
1252
  const cache = this.cache;
1312
1253
  const json = this.json;
1313
1254
  const meshCacheKeyParts = [ mesh.geometry.uuid ];
1314
-
1315
1255
  if ( Array.isArray( mesh.material ) ) {
1316
1256
 
1317
1257
  for ( let i = 0, l = mesh.material.length; i < l; i ++ ) {
@@ -1329,8 +1269,9 @@
1329
1269
  const meshCacheKey = meshCacheKeyParts.join( ':' );
1330
1270
  if ( cache.meshes.has( meshCacheKey ) ) return cache.meshes.get( meshCacheKey );
1331
1271
  const geometry = mesh.geometry;
1332
- let mode; // Use the correct mode
1272
+ let mode;
1333
1273
 
1274
+ // Use the correct mode
1334
1275
  if ( mesh.isLineSegments ) {
1335
1276
 
1336
1277
  mode = WEBGL_CONSTANTS.LINES;
@@ -1356,8 +1297,9 @@
1356
1297
  const meshDef = {};
1357
1298
  const attributes = {};
1358
1299
  const primitives = [];
1359
- const targets = []; // Conversion between attributes names in threejs and gltf spec
1300
+ const targets = [];
1360
1301
 
1302
+ // Conversion between attributes names in threejs and gltf spec
1361
1303
  const nameConversion = {
1362
1304
  uv: 'TEXCOORD_0',
1363
1305
  uv2: 'TEXCOORD_1',
@@ -1366,40 +1308,37 @@
1366
1308
  skinIndex: 'JOINTS_0'
1367
1309
  };
1368
1310
  const originalNormal = geometry.getAttribute( 'normal' );
1369
-
1370
1311
  if ( originalNormal !== undefined && ! this.isNormalizedNormalAttribute( originalNormal ) ) {
1371
1312
 
1372
1313
  console.warn( 'THREE.GLTFExporter: Creating normalized normal attribute from the non-normalized one.' );
1373
1314
  geometry.setAttribute( 'normal', this.createNormalizedNormalAttribute( originalNormal ) );
1374
1315
 
1375
- } // @QUESTION Detect if .vertexColors = true?
1376
- // For every attribute create an accessor
1377
-
1316
+ }
1378
1317
 
1318
+ // @QUESTION Detect if .vertexColors = true?
1319
+ // For every attribute create an accessor
1379
1320
  let modifiedAttribute = null;
1380
-
1381
1321
  for ( let attributeName in geometry.attributes ) {
1382
1322
 
1383
1323
  // Ignore morph target attributes, which are exported later.
1384
1324
  if ( attributeName.slice( 0, 5 ) === 'morph' ) continue;
1385
1325
  const attribute = geometry.attributes[ attributeName ];
1386
- attributeName = nameConversion[ attributeName ] || attributeName.toUpperCase(); // Prefix all geometry attributes except the ones specifically
1387
- // listed in the spec; non-spec attributes are considered custom.
1326
+ attributeName = nameConversion[ attributeName ] || attributeName.toUpperCase();
1388
1327
 
1328
+ // Prefix all geometry attributes except the ones specifically
1329
+ // listed in the spec; non-spec attributes are considered custom.
1389
1330
  const validVertexAttributes = /^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/;
1390
1331
  if ( ! validVertexAttributes.test( attributeName ) ) attributeName = '_' + attributeName;
1391
-
1392
1332
  if ( cache.attributes.has( this.getUID( attribute ) ) ) {
1393
1333
 
1394
1334
  attributes[ attributeName ] = cache.attributes.get( this.getUID( attribute ) );
1395
1335
  continue;
1396
1336
 
1397
- } // JOINTS_0 must be UNSIGNED_BYTE or UNSIGNED_SHORT.
1398
-
1337
+ }
1399
1338
 
1339
+ // JOINTS_0 must be UNSIGNED_BYTE or UNSIGNED_SHORT.
1400
1340
  modifiedAttribute = null;
1401
1341
  const array = attribute.array;
1402
-
1403
1342
  if ( attributeName === 'JOINTS_0' && ! ( array instanceof Uint16Array ) && ! ( array instanceof Uint8Array ) ) {
1404
1343
 
1405
1344
  console.warn( 'GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.' );
@@ -1408,7 +1347,6 @@
1408
1347
  }
1409
1348
 
1410
1349
  const accessor = this.processAccessor( modifiedAttribute || attribute, geometry );
1411
-
1412
1350
  if ( accessor !== null ) {
1413
1351
 
1414
1352
  attributes[ attributeName ] = accessor;
@@ -1418,16 +1356,17 @@
1418
1356
 
1419
1357
  }
1420
1358
 
1421
- if ( originalNormal !== undefined ) geometry.setAttribute( 'normal', originalNormal ); // Skip if no exportable attributes found
1359
+ if ( originalNormal !== undefined ) geometry.setAttribute( 'normal', originalNormal );
1422
1360
 
1423
- if ( Object.keys( attributes ).length === 0 ) return null; // Morph targets
1361
+ // Skip if no exportable attributes found
1362
+ if ( Object.keys( attributes ).length === 0 ) return null;
1424
1363
 
1364
+ // Morph targets
1425
1365
  if ( mesh.morphTargetInfluences !== undefined && mesh.morphTargetInfluences.length > 0 ) {
1426
1366
 
1427
1367
  const weights = [];
1428
1368
  const targetNames = [];
1429
1369
  const reverseDictionary = {};
1430
-
1431
1370
  if ( mesh.morphTargetDictionary !== undefined ) {
1432
1371
 
1433
1372
  for ( const key in mesh.morphTargetDictionary ) {
@@ -1442,11 +1381,11 @@
1442
1381
 
1443
1382
  const target = {};
1444
1383
  let warned = false;
1445
-
1446
1384
  for ( const attributeName in geometry.morphAttributes ) {
1447
1385
 
1448
1386
  // glTF 2.0 morph supports only POSITION/NORMAL/TANGENT.
1449
1387
  // Three.js doesn't support TANGENT yet.
1388
+
1450
1389
  if ( attributeName !== 'position' && attributeName !== 'normal' ) {
1451
1390
 
1452
1391
  if ( ! warned ) {
@@ -1461,23 +1400,23 @@
1461
1400
  }
1462
1401
 
1463
1402
  const attribute = geometry.morphAttributes[ attributeName ][ i ];
1464
- const gltfAttributeName = attributeName.toUpperCase(); // Three.js morph attribute has absolute values while the one of glTF has relative values.
1403
+ const gltfAttributeName = attributeName.toUpperCase();
1404
+
1405
+ // Three.js morph attribute has absolute values while the one of glTF has relative values.
1465
1406
  //
1466
1407
  // glTF 2.0 Specification:
1467
1408
  // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#morph-targets
1468
1409
 
1469
1410
  const baseAttribute = geometry.attributes[ attributeName ];
1470
-
1471
1411
  if ( cache.attributes.has( this.getUID( attribute, true ) ) ) {
1472
1412
 
1473
1413
  target[ gltfAttributeName ] = cache.attributes.get( this.getUID( attribute, true ) );
1474
1414
  continue;
1475
1415
 
1476
- } // Clones attribute not to override
1477
-
1416
+ }
1478
1417
 
1418
+ // Clones attribute not to override
1479
1419
  const relativeAttribute = attribute.clone();
1480
-
1481
1420
  if ( ! geometry.morphTargetsRelative ) {
1482
1421
 
1483
1422
  for ( let j = 0, jl = attribute.count; j < jl; j ++ ) {
@@ -1500,7 +1439,6 @@
1500
1439
  }
1501
1440
 
1502
1441
  meshDef.weights = weights;
1503
-
1504
1442
  if ( targetNames.length > 0 ) {
1505
1443
 
1506
1444
  meshDef.extras = {};
@@ -1518,7 +1456,6 @@
1518
1456
  start: undefined,
1519
1457
  count: undefined
1520
1458
  } ];
1521
-
1522
1459
  for ( let i = 0, il = groups.length; i < il; i ++ ) {
1523
1460
 
1524
1461
  const primitive = {
@@ -1527,11 +1464,9 @@
1527
1464
  };
1528
1465
  this.serializeUserData( geometry, primitive );
1529
1466
  if ( targets.length > 0 ) primitive.targets = targets;
1530
-
1531
1467
  if ( geometry.index !== null ) {
1532
1468
 
1533
1469
  let cacheKey = this.getUID( geometry.index );
1534
-
1535
1470
  if ( groups[ i ].start !== undefined || groups[ i ].count !== undefined ) {
1536
1471
 
1537
1472
  cacheKey += ':' + groups[ i ].start + ':' + groups[ i ].count;
@@ -1561,25 +1496,22 @@
1561
1496
 
1562
1497
  meshDef.primitives = primitives;
1563
1498
  if ( ! json.meshes ) json.meshes = [];
1564
-
1565
1499
  this._invokeAll( function ( ext ) {
1566
1500
 
1567
1501
  ext.writeMesh && ext.writeMesh( mesh, meshDef );
1568
1502
 
1569
1503
  } );
1570
-
1571
1504
  const index = json.meshes.push( meshDef ) - 1;
1572
1505
  cache.meshes.set( meshCacheKey, index );
1573
1506
  return index;
1574
1507
 
1575
1508
  }
1509
+
1576
1510
  /**
1577
1511
  * Process camera
1578
1512
  * @param {THREE.Camera} camera Camera to process
1579
1513
  * @return {Integer} Index of the processed mesh in the "camera" array
1580
1514
  */
1581
-
1582
-
1583
1515
  processCamera( camera ) {
1584
1516
 
1585
1517
  const json = this.json;
@@ -1588,7 +1520,6 @@
1588
1520
  const cameraDef = {
1589
1521
  type: isOrtho ? 'orthographic' : 'perspective'
1590
1522
  };
1591
-
1592
1523
  if ( isOrtho ) {
1593
1524
 
1594
1525
  cameraDef.orthographic = {
@@ -1607,13 +1538,14 @@
1607
1538
  znear: camera.near < 0 ? 0 : camera.near
1608
1539
  };
1609
1540
 
1610
- } // Question: Is saving "type" as name intentional?
1611
-
1541
+ }
1612
1542
 
1543
+ // Question: Is saving "type" as name intentional?
1613
1544
  if ( camera.name !== '' ) cameraDef.name = camera.type;
1614
1545
  return json.cameras.push( cameraDef ) - 1;
1615
1546
 
1616
1547
  }
1548
+
1617
1549
  /**
1618
1550
  * Creates glTF animation entry from AnimationClip object.
1619
1551
  *
@@ -1624,8 +1556,6 @@
1624
1556
  * @param {THREE.Object3D} root
1625
1557
  * @return {number|null}
1626
1558
  */
1627
-
1628
-
1629
1559
  processAnimation( clip, root ) {
1630
1560
 
1631
1561
  const json = this.json;
@@ -1635,14 +1565,12 @@
1635
1565
  const tracks = clip.tracks;
1636
1566
  const channels = [];
1637
1567
  const samplers = [];
1638
-
1639
1568
  for ( let i = 0; i < tracks.length; ++ i ) {
1640
1569
 
1641
1570
  const track = tracks[ i ];
1642
1571
  const trackBinding = THREE.PropertyBinding.parseTrackName( track.name );
1643
1572
  let trackNode = THREE.PropertyBinding.findNode( root, trackBinding.nodeName );
1644
1573
  const trackProperty = PATH_PROPERTIES[ trackBinding.propertyName ];
1645
-
1646
1574
  if ( trackBinding.objectName === 'bones' ) {
1647
1575
 
1648
1576
  if ( trackNode.isSkinnedMesh === true ) {
@@ -1666,24 +1594,26 @@
1666
1594
 
1667
1595
  const inputItemSize = 1;
1668
1596
  let outputItemSize = track.values.length / track.times.length;
1669
-
1670
1597
  if ( trackProperty === PATH_PROPERTIES.morphTargetInfluences ) {
1671
1598
 
1672
1599
  outputItemSize /= trackNode.morphTargetInfluences.length;
1673
1600
 
1674
1601
  }
1675
1602
 
1676
- let interpolation; // @TODO export CubicInterpolant(InterpolateSmooth) as CUBICSPLINE
1603
+ let interpolation;
1604
+
1605
+ // @TODO export CubicInterpolant(InterpolateSmooth) as CUBICSPLINE
1606
+
1677
1607
  // Detecting glTF cubic spline interpolant by checking factory method's special property
1678
1608
  // GLTFCubicSplineInterpolant is a custom interpolant and track doesn't return
1679
1609
  // valid value from .getInterpolation().
1680
-
1681
1610
  if ( track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true ) {
1682
1611
 
1683
- interpolation = 'CUBICSPLINE'; // itemSize of CUBICSPLINE keyframe is 9
1612
+ interpolation = 'CUBICSPLINE';
1613
+
1614
+ // itemSize of CUBICSPLINE keyframe is 9
1684
1615
  // (VEC3 * 3: inTangent, splineVertex, and outTangent)
1685
1616
  // but needs to be stored as VEC3 so dividing by 3 here.
1686
-
1687
1617
  outputItemSize /= 3;
1688
1618
 
1689
1619
  } else if ( track.getInterpolation() === THREE.InterpolateDiscrete ) {
@@ -1719,12 +1649,11 @@
1719
1649
  return json.animations.length - 1;
1720
1650
 
1721
1651
  }
1652
+
1722
1653
  /**
1723
1654
  * @param {THREE.Object3D} object
1724
1655
  * @return {number|null}
1725
1656
  */
1726
-
1727
-
1728
1657
  processSkin( object ) {
1729
1658
 
1730
1659
  const json = this.json;
@@ -1737,7 +1666,6 @@
1737
1666
  const joints = [];
1738
1667
  const inverseBindMatrices = new Float32Array( skeleton.bones.length * 16 );
1739
1668
  const temporaryBoneInverse = new THREE.Matrix4();
1740
-
1741
1669
  for ( let i = 0; i < skeleton.bones.length; ++ i ) {
1742
1670
 
1743
1671
  joints.push( nodeMap.get( skeleton.bones[ i ] ) );
@@ -1756,13 +1684,12 @@
1756
1684
  return skinIndex;
1757
1685
 
1758
1686
  }
1687
+
1759
1688
  /**
1760
1689
  * Process Object3D node
1761
1690
  * @param {THREE.Object3D} node Object3D to processNode
1762
1691
  * @return {Integer} Index of the node in the nodes list
1763
1692
  */
1764
-
1765
-
1766
1693
  processNode( object ) {
1767
1694
 
1768
1695
  const json = this.json;
@@ -1770,13 +1697,11 @@
1770
1697
  const nodeMap = this.nodeMap;
1771
1698
  if ( ! json.nodes ) json.nodes = [];
1772
1699
  const nodeDef = {};
1773
-
1774
1700
  if ( options.trs ) {
1775
1701
 
1776
1702
  const rotation = object.quaternion.toArray();
1777
1703
  const position = object.position.toArray();
1778
1704
  const scale = object.scale.toArray();
1779
-
1780
1705
  if ( ! equalArray( rotation, [ 0, 0, 0, 1 ] ) ) {
1781
1706
 
1782
1707
  nodeDef.rotation = rotation;
@@ -1809,12 +1734,11 @@
1809
1734
 
1810
1735
  }
1811
1736
 
1812
- } // We don't export empty strings name because it represents no-name in Three.js.
1813
-
1737
+ }
1814
1738
 
1739
+ // We don't export empty strings name because it represents no-name in Three.js.
1815
1740
  if ( object.name !== '' ) nodeDef.name = String( object.name );
1816
1741
  this.serializeUserData( object, nodeDef );
1817
-
1818
1742
  if ( object.isMesh || object.isLine || object.isPoints ) {
1819
1743
 
1820
1744
  const meshIndex = this.processMesh( object );
@@ -1827,15 +1751,12 @@
1827
1751
  }
1828
1752
 
1829
1753
  if ( object.isSkinnedMesh ) this.skins.push( object );
1830
-
1831
1754
  if ( object.children.length > 0 ) {
1832
1755
 
1833
1756
  const children = [];
1834
-
1835
1757
  for ( let i = 0, l = object.children.length; i < l; i ++ ) {
1836
1758
 
1837
1759
  const child = object.children[ i ];
1838
-
1839
1760
  if ( child.visible || options.onlyVisible === false ) {
1840
1761
 
1841
1762
  const nodeIndex = this.processNode( child );
@@ -1854,23 +1775,20 @@
1854
1775
  ext.writeNode && ext.writeNode( object, nodeDef );
1855
1776
 
1856
1777
  } );
1857
-
1858
1778
  const nodeIndex = json.nodes.push( nodeDef ) - 1;
1859
1779
  nodeMap.set( object, nodeIndex );
1860
1780
  return nodeIndex;
1861
1781
 
1862
1782
  }
1783
+
1863
1784
  /**
1864
1785
  * Process THREE.Scene
1865
1786
  * @param {Scene} node THREE.Scene to process
1866
1787
  */
1867
-
1868
-
1869
1788
  processScene( scene ) {
1870
1789
 
1871
1790
  const json = this.json;
1872
1791
  const options = this.options;
1873
-
1874
1792
  if ( ! json.scenes ) {
1875
1793
 
1876
1794
  json.scenes = [];
@@ -1882,11 +1800,9 @@
1882
1800
  if ( scene.name !== '' ) sceneDef.name = scene.name;
1883
1801
  json.scenes.push( sceneDef );
1884
1802
  const nodes = [];
1885
-
1886
1803
  for ( let i = 0, l = scene.children.length; i < l; i ++ ) {
1887
1804
 
1888
1805
  const child = scene.children[ i ];
1889
-
1890
1806
  if ( child.visible || options.onlyVisible === false ) {
1891
1807
 
1892
1808
  const nodeIndex = this.processNode( child );
@@ -1900,17 +1816,15 @@
1900
1816
  this.serializeUserData( scene, sceneDef );
1901
1817
 
1902
1818
  }
1819
+
1903
1820
  /**
1904
1821
  * Creates a THREE.Scene to hold a list of objects and parse it
1905
1822
  * @param {Array} objects List of objects to process
1906
1823
  */
1907
-
1908
-
1909
1824
  processObjects( objects ) {
1910
1825
 
1911
1826
  const scene = new THREE.Scene();
1912
1827
  scene.name = 'AuxScene';
1913
-
1914
1828
  for ( let i = 0; i < objects.length; i ++ ) {
1915
1829
 
1916
1830
  // We push directly to children instead of calling `add` to prevent
@@ -1922,24 +1836,20 @@
1922
1836
  this.processScene( scene );
1923
1837
 
1924
1838
  }
1839
+
1925
1840
  /**
1926
1841
  * @param {THREE.Object3D|Array<THREE.Object3D>} input
1927
1842
  */
1928
-
1929
-
1930
1843
  processInput( input ) {
1931
1844
 
1932
1845
  const options = this.options;
1933
1846
  input = input instanceof Array ? input : [ input ];
1934
-
1935
1847
  this._invokeAll( function ( ext ) {
1936
1848
 
1937
1849
  ext.beforeParse && ext.beforeParse( input );
1938
1850
 
1939
1851
  } );
1940
-
1941
1852
  const objectsWithoutScene = [];
1942
-
1943
1853
  for ( let i = 0; i < input.length; i ++ ) {
1944
1854
 
1945
1855
  if ( input[ i ] instanceof THREE.Scene ) {
@@ -1955,7 +1865,6 @@
1955
1865
  }
1956
1866
 
1957
1867
  if ( objectsWithoutScene.length > 0 ) this.processObjects( objectsWithoutScene );
1958
-
1959
1868
  for ( let i = 0; i < this.skins.length; ++ i ) {
1960
1869
 
1961
1870
  this.processSkin( this.skins[ i ] );
@@ -1975,7 +1884,6 @@
1975
1884
  } );
1976
1885
 
1977
1886
  }
1978
-
1979
1887
  _invokeAll( func ) {
1980
1888
 
1981
1889
  for ( let i = 0, il = this.plugins.length; i < il; i ++ ) {
@@ -1987,13 +1895,12 @@
1987
1895
  }
1988
1896
 
1989
1897
  }
1898
+
1990
1899
  /**
1991
1900
  * Punctual Lights Extension
1992
1901
  *
1993
1902
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
1994
1903
  */
1995
-
1996
-
1997
1904
  class GLTFLightExtension {
1998
1905
 
1999
1906
  constructor( writer ) {
@@ -2002,11 +1909,9 @@
2002
1909
  this.name = 'KHR_lights_punctual';
2003
1910
 
2004
1911
  }
2005
-
2006
1912
  writeNode( light, nodeDef ) {
2007
1913
 
2008
1914
  if ( ! light.isLight ) return;
2009
-
2010
1915
  if ( ! light.isDirectionalLight && ! light.isPointLight && ! light.isSpotLight ) {
2011
1916
 
2012
1917
  console.warn( 'THREE.GLTFExporter: Only directional, point, and spot lights are supported.', light );
@@ -2021,7 +1926,6 @@
2021
1926
  if ( light.name ) lightDef.name = light.name;
2022
1927
  lightDef.color = light.color.toArray();
2023
1928
  lightDef.intensity = light.intensity;
2024
-
2025
1929
  if ( light.isDirectionalLight ) {
2026
1930
 
2027
1931
  lightDef.type = 'directional';
@@ -2073,13 +1977,12 @@
2073
1977
  }
2074
1978
 
2075
1979
  }
1980
+
2076
1981
  /**
2077
1982
  * Unlit Materials Extension
2078
1983
  *
2079
1984
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit
2080
1985
  */
2081
-
2082
-
2083
1986
  class GLTFMaterialsUnlitExtension {
2084
1987
 
2085
1988
  constructor( writer ) {
@@ -2088,7 +1991,6 @@
2088
1991
  this.name = 'KHR_materials_unlit';
2089
1992
 
2090
1993
  }
2091
-
2092
1994
  writeMaterial( material, materialDef ) {
2093
1995
 
2094
1996
  if ( ! material.isMeshBasicMaterial ) return;
@@ -2103,70 +2005,12 @@
2103
2005
  }
2104
2006
 
2105
2007
  }
2106
- /**
2107
- * Specular-Glossiness Extension
2108
- *
2109
- * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
2110
- */
2111
-
2112
-
2113
- class GLTFMaterialsPBRSpecularGlossiness {
2114
-
2115
- constructor( writer ) {
2116
-
2117
- this.writer = writer;
2118
- this.name = 'KHR_materials_pbrSpecularGlossiness';
2119
-
2120
- }
2121
-
2122
- writeMaterial( material, materialDef ) {
2123
-
2124
- if ( ! material.isGLTFSpecularGlossinessMaterial ) return;
2125
- const writer = this.writer;
2126
- const extensionsUsed = writer.extensionsUsed;
2127
- const extensionDef = {};
2128
-
2129
- if ( materialDef.pbrMetallicRoughness.baseColorFactor ) {
2130
-
2131
- extensionDef.diffuseFactor = materialDef.pbrMetallicRoughness.baseColorFactor;
2132
-
2133
- }
2134
2008
 
2135
- const specularFactor = [ 1, 1, 1 ];
2136
- material.specular.toArray( specularFactor, 0 );
2137
- extensionDef.specularFactor = specularFactor;
2138
- extensionDef.glossinessFactor = material.glossiness;
2139
-
2140
- if ( materialDef.pbrMetallicRoughness.baseColorTexture ) {
2141
-
2142
- extensionDef.diffuseTexture = materialDef.pbrMetallicRoughness.baseColorTexture;
2143
-
2144
- }
2145
-
2146
- if ( material.specularMap ) {
2147
-
2148
- const specularMapDef = {
2149
- index: writer.processTexture( material.specularMap )
2150
- };
2151
- writer.applyTextureTransform( specularMapDef, material.specularMap );
2152
- extensionDef.specularGlossinessTexture = specularMapDef;
2153
-
2154
- }
2155
-
2156
- materialDef.extensions = materialDef.extensions || {};
2157
- materialDef.extensions[ this.name ] = extensionDef;
2158
- extensionsUsed[ this.name ] = true;
2159
-
2160
- }
2161
-
2162
- }
2163
2009
  /**
2164
2010
  * Clearcoat Materials Extension
2165
2011
  *
2166
2012
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
2167
2013
  */
2168
-
2169
-
2170
2014
  class GLTFMaterialsClearcoatExtension {
2171
2015
 
2172
2016
  constructor( writer ) {
@@ -2175,7 +2019,6 @@
2175
2019
  this.name = 'KHR_materials_clearcoat';
2176
2020
 
2177
2021
  }
2178
-
2179
2022
  writeMaterial( material, materialDef ) {
2180
2023
 
2181
2024
  if ( ! material.isMeshPhysicalMaterial ) return;
@@ -2183,7 +2026,6 @@
2183
2026
  const extensionsUsed = writer.extensionsUsed;
2184
2027
  const extensionDef = {};
2185
2028
  extensionDef.clearcoatFactor = material.clearcoat;
2186
-
2187
2029
  if ( material.clearcoatMap ) {
2188
2030
 
2189
2031
  const clearcoatMapDef = {
@@ -2195,7 +2037,6 @@
2195
2037
  }
2196
2038
 
2197
2039
  extensionDef.clearcoatRoughnessFactor = material.clearcoatRoughness;
2198
-
2199
2040
  if ( material.clearcoatRoughnessMap ) {
2200
2041
 
2201
2042
  const clearcoatRoughnessMapDef = {
@@ -2223,13 +2064,12 @@
2223
2064
  }
2224
2065
 
2225
2066
  }
2067
+
2226
2068
  /**
2227
2069
  * Iridescence Materials Extension
2228
2070
  *
2229
2071
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence
2230
2072
  */
2231
-
2232
-
2233
2073
  class GLTFMaterialsIridescenceExtension {
2234
2074
 
2235
2075
  constructor( writer ) {
@@ -2238,7 +2078,6 @@
2238
2078
  this.name = 'KHR_materials_iridescence';
2239
2079
 
2240
2080
  }
2241
-
2242
2081
  writeMaterial( material, materialDef ) {
2243
2082
 
2244
2083
  if ( ! material.isMeshPhysicalMaterial ) return;
@@ -2246,7 +2085,6 @@
2246
2085
  const extensionsUsed = writer.extensionsUsed;
2247
2086
  const extensionDef = {};
2248
2087
  extensionDef.iridescenceFactor = material.iridescence;
2249
-
2250
2088
  if ( material.iridescenceMap ) {
2251
2089
 
2252
2090
  const iridescenceMapDef = {
@@ -2260,7 +2098,6 @@
2260
2098
  extensionDef.iridescenceIor = material.iridescenceIOR;
2261
2099
  extensionDef.iridescenceThicknessMinimum = material.iridescenceThicknessRange[ 0 ];
2262
2100
  extensionDef.iridescenceThicknessMaximum = material.iridescenceThicknessRange[ 1 ];
2263
-
2264
2101
  if ( material.iridescenceThicknessMap ) {
2265
2102
 
2266
2103
  const iridescenceThicknessMapDef = {
@@ -2278,13 +2115,12 @@
2278
2115
  }
2279
2116
 
2280
2117
  }
2118
+
2281
2119
  /**
2282
2120
  * Transmission Materials Extension
2283
2121
  *
2284
2122
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
2285
2123
  */
2286
-
2287
-
2288
2124
  class GLTFMaterialsTransmissionExtension {
2289
2125
 
2290
2126
  constructor( writer ) {
@@ -2293,7 +2129,6 @@
2293
2129
  this.name = 'KHR_materials_transmission';
2294
2130
 
2295
2131
  }
2296
-
2297
2132
  writeMaterial( material, materialDef ) {
2298
2133
 
2299
2134
  if ( ! material.isMeshPhysicalMaterial || material.transmission === 0 ) return;
@@ -2301,7 +2136,6 @@
2301
2136
  const extensionsUsed = writer.extensionsUsed;
2302
2137
  const extensionDef = {};
2303
2138
  extensionDef.transmissionFactor = material.transmission;
2304
-
2305
2139
  if ( material.transmissionMap ) {
2306
2140
 
2307
2141
  const transmissionMapDef = {
@@ -2319,13 +2153,12 @@
2319
2153
  }
2320
2154
 
2321
2155
  }
2156
+
2322
2157
  /**
2323
2158
  * Materials Volume Extension
2324
2159
  *
2325
2160
  * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume
2326
2161
  */
2327
-
2328
-
2329
2162
  class GLTFMaterialsVolumeExtension {
2330
2163
 
2331
2164
  constructor( writer ) {
@@ -2334,7 +2167,6 @@
2334
2167
  this.name = 'KHR_materials_volume';
2335
2168
 
2336
2169
  }
2337
-
2338
2170
  writeMaterial( material, materialDef ) {
2339
2171
 
2340
2172
  if ( ! material.isMeshPhysicalMaterial || material.transmission === 0 ) return;
@@ -2342,7 +2174,6 @@
2342
2174
  const extensionsUsed = writer.extensionsUsed;
2343
2175
  const extensionDef = {};
2344
2176
  extensionDef.thicknessFactor = material.thickness;
2345
-
2346
2177
  if ( material.thicknessMap ) {
2347
2178
 
2348
2179
  const thicknessMapDef = {
@@ -2362,26 +2193,22 @@
2362
2193
  }
2363
2194
 
2364
2195
  }
2196
+
2365
2197
  /**
2366
2198
  * Static utility functions
2367
2199
  */
2368
-
2369
-
2370
2200
  GLTFExporter.Utils = {
2371
2201
  insertKeyframe: function ( track, time ) {
2372
2202
 
2373
2203
  const tolerance = 0.001; // 1ms
2374
-
2375
2204
  const valueSize = track.getValueSize();
2376
2205
  const times = new track.TimeBufferType( track.times.length + 1 );
2377
2206
  const values = new track.ValueBufferType( track.values.length + valueSize );
2378
2207
  const interpolant = track.createInterpolant( new track.ValueBufferType( valueSize ) );
2379
2208
  let index;
2380
-
2381
2209
  if ( track.times.length === 0 ) {
2382
2210
 
2383
2211
  times[ 0 ] = time;
2384
-
2385
2212
  for ( let i = 0; i < valueSize; i ++ ) {
2386
2213
 
2387
2214
  values[ i ] = 0;
@@ -2418,7 +2245,6 @@
2418
2245
  for ( let i = 0; i < track.times.length; i ++ ) {
2419
2246
 
2420
2247
  if ( Math.abs( track.times[ i ] - time ) < tolerance ) return i;
2421
-
2422
2248
  if ( track.times[ i ] < time && track.times[ i + 1 ] > time ) {
2423
2249
 
2424
2250
  times.set( track.times.slice( 0, i + 1 ), 0 );
@@ -2446,13 +2272,11 @@
2446
2272
  const tracks = [];
2447
2273
  const mergedTracks = {};
2448
2274
  const sourceTracks = clip.tracks;
2449
-
2450
2275
  for ( let i = 0; i < sourceTracks.length; ++ i ) {
2451
2276
 
2452
2277
  let sourceTrack = sourceTracks[ i ];
2453
2278
  const sourceTrackBinding = THREE.PropertyBinding.parseTrackName( sourceTrack.name );
2454
2279
  const sourceTrackNode = THREE.PropertyBinding.findNode( root, sourceTrackBinding.nodeName );
2455
-
2456
2280
  if ( sourceTrackBinding.propertyName !== 'morphTargetInfluences' || sourceTrackBinding.propertyIndex === undefined ) {
2457
2281
 
2458
2282
  // Tracks that don't affect morph targets, or that affect all morph targets together, can be left as-is.
@@ -2479,29 +2303,28 @@
2479
2303
 
2480
2304
  const targetCount = sourceTrackNode.morphTargetInfluences.length;
2481
2305
  const targetIndex = sourceTrackNode.morphTargetDictionary[ sourceTrackBinding.propertyIndex ];
2482
-
2483
2306
  if ( targetIndex === undefined ) {
2484
2307
 
2485
2308
  throw new Error( 'THREE.GLTFExporter: Morph target name not found: ' + sourceTrackBinding.propertyIndex );
2486
2309
 
2487
2310
  }
2488
2311
 
2489
- let mergedTrack; // If this is the first time we've seen this object, create a new
2490
- // track to store merged keyframe data for each morph target.
2312
+ let mergedTrack;
2491
2313
 
2314
+ // If this is the first time we've seen this object, create a new
2315
+ // track to store merged keyframe data for each morph target.
2492
2316
  if ( mergedTracks[ sourceTrackNode.uuid ] === undefined ) {
2493
2317
 
2494
2318
  mergedTrack = sourceTrack.clone();
2495
2319
  const values = new mergedTrack.ValueBufferType( targetCount * mergedTrack.times.length );
2496
-
2497
2320
  for ( let j = 0; j < mergedTrack.times.length; j ++ ) {
2498
2321
 
2499
2322
  values[ j * targetCount + targetIndex ] = mergedTrack.values[ j ];
2500
2323
 
2501
- } // We need to take into consideration the intended target node
2502
- // of our original un-merged morphTarget animation.
2503
-
2324
+ }
2504
2325
 
2326
+ // We need to take into consideration the intended target node
2327
+ // of our original un-merged morphTarget animation.
2505
2328
  mergedTrack.name = ( sourceTrackBinding.nodeName || '' ) + '.morphTargetInfluences';
2506
2329
  mergedTrack.values = values;
2507
2330
  mergedTracks[ sourceTrackNode.uuid ] = mergedTrack;
@@ -2511,18 +2334,19 @@
2511
2334
  }
2512
2335
 
2513
2336
  const sourceInterpolant = sourceTrack.createInterpolant( new sourceTrack.ValueBufferType( 1 ) );
2514
- mergedTrack = mergedTracks[ sourceTrackNode.uuid ]; // For every existing keyframe of the merged track, write a (possibly
2515
- // interpolated) value from the source track.
2337
+ mergedTrack = mergedTracks[ sourceTrackNode.uuid ];
2516
2338
 
2339
+ // For every existing keyframe of the merged track, write a (possibly
2340
+ // interpolated) value from the source track.
2517
2341
  for ( let j = 0; j < mergedTrack.times.length; j ++ ) {
2518
2342
 
2519
2343
  mergedTrack.values[ j * targetCount + targetIndex ] = sourceInterpolant.evaluate( mergedTrack.times[ j ] );
2520
2344
 
2521
- } // For every existing keyframe of the source track, write a (possibly
2345
+ }
2346
+
2347
+ // For every existing keyframe of the source track, write a (possibly
2522
2348
  // new) keyframe to the merged track. Values from the previous loop may
2523
2349
  // be written again, but keyframes are de-duplicated.
2524
-
2525
-
2526
2350
  for ( let j = 0; j < sourceTrack.times.length; j ++ ) {
2527
2351
 
2528
2352
  const keyframeIndex = this.insertKeyframe( mergedTrack, sourceTrack.times[ j ] );