super-three 0.141.0 → 0.147.0

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 (646) hide show
  1. package/README.md +9 -9
  2. package/build/three.cjs +2441 -1569
  3. package/build/three.js +2441 -1569
  4. package/build/three.min.js +1 -1
  5. package/build/three.module.js +2847 -1576
  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 +71 -150
  10. package/examples/js/cameras/CinematicCamera.js +33 -22
  11. package/examples/js/controls/ArcballControls.js +149 -403
  12. package/examples/js/controls/DragControls.js +8 -33
  13. package/examples/js/controls/FirstPersonControls.js +32 -61
  14. package/examples/js/controls/FlyControls.js +29 -63
  15. package/examples/js/controls/OrbitControls.js +125 -103
  16. package/examples/js/controls/PointerLockControls.js +5 -22
  17. package/examples/js/controls/TrackballControls.js +33 -88
  18. package/examples/js/controls/TransformControls.js +101 -182
  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 +6 -20
  28. package/examples/js/effects/AsciiEffect.js +32 -31
  29. package/examples/js/effects/OutlineEffect.js +30 -54
  30. package/examples/js/effects/ParallaxBarrierEffect.js +2 -15
  31. package/examples/js/effects/PeppersGhostEffect.js +14 -41
  32. package/examples/js/effects/StereoEffect.js +2 -6
  33. package/examples/js/environments/RoomEnvironment.js +32 -8
  34. package/examples/js/exporters/ColladaExporter.js +52 -78
  35. package/examples/js/exporters/DRACOExporter.js +22 -34
  36. package/examples/js/exporters/EXRExporter.js +15 -18
  37. package/examples/js/exporters/GLTFExporter.js +168 -345
  38. package/examples/js/exporters/MMDExporter.js +5 -12
  39. package/examples/js/exporters/OBJExporter.js +40 -52
  40. package/examples/js/exporters/PLYExporter.js +50 -57
  41. package/examples/js/exporters/STLExporter.js +5 -14
  42. package/examples/js/exporters/USDZExporter.js +119 -27
  43. package/examples/js/geometries/BoxLineGeometry.js +0 -1
  44. package/examples/js/geometries/ConvexGeometry.js +12 -7
  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 +23 -17
  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 +2 -8
  63. package/examples/js/libs/ktx-parse.umd.js +1 -0
  64. package/examples/js/libs/meshopt_decoder.js +98 -32
  65. package/examples/js/lights/LightProbeGenerator.js +32 -39
  66. package/examples/js/lights/RectAreaLightUniformsLib.js +5 -1
  67. package/examples/js/lines/LineGeometry.js +3 -5
  68. package/examples/js/lines/LineMaterial.js +4 -11
  69. package/examples/js/lines/LineSegments2.js +40 -89
  70. package/examples/js/lines/LineSegmentsGeometry.js +7 -28
  71. package/examples/js/lines/Wireframe.js +2 -7
  72. package/examples/js/lines/WireframeGeometry2.js +3 -1
  73. package/examples/js/loaders/3DMLoader.js +58 -155
  74. package/examples/js/loaders/3MFLoader.js +72 -106
  75. package/examples/js/loaders/AMFLoader.js +0 -25
  76. package/examples/js/loaders/BVHLoader.js +44 -43
  77. package/examples/js/loaders/BasisTextureLoader.js +16 -46
  78. package/examples/js/loaders/ColladaLoader.js +229 -359
  79. package/examples/js/loaders/DDSLoader.js +24 -25
  80. package/examples/js/loaders/DRACOLoader.js +30 -90
  81. package/examples/js/loaders/EXRLoader.js +69 -177
  82. package/examples/js/loaders/FBXLoader.js +294 -441
  83. package/examples/js/loaders/FontLoader.js +9 -31
  84. package/examples/js/loaders/GCodeLoader.js +15 -16
  85. package/examples/js/loaders/GLTFLoader.js +458 -739
  86. package/examples/js/loaders/HDRCubeTextureLoader.js +0 -17
  87. package/examples/js/loaders/KMZLoader.js +3 -7
  88. package/examples/js/loaders/KTXLoader.js +12 -30
  89. package/examples/js/loaders/LDrawLoader.js +309 -355
  90. package/examples/js/loaders/LUT3dlLoader.js +7 -11
  91. package/examples/js/loaders/LUTCubeLoader.js +0 -8
  92. package/examples/js/loaders/LWOLoader.js +59 -124
  93. package/examples/js/loaders/LogLuvLoader.js +27 -77
  94. package/examples/js/loaders/LottieLoader.js +4 -4
  95. package/examples/js/loaders/MD2Loader.js +26 -27
  96. package/examples/js/loaders/MDDLoader.js +6 -10
  97. package/examples/js/loaders/MMDLoader.js +180 -189
  98. package/examples/js/loaders/MTLLoader.js +18 -47
  99. package/examples/js/loaders/NRRDLoader.js +44 -84
  100. package/examples/js/loaders/OBJLoader.js +56 -77
  101. package/examples/js/loaders/PCDLoader.js +92 -42
  102. package/examples/js/loaders/PDBLoader.js +17 -13
  103. package/examples/js/loaders/PLYLoader.js +65 -51
  104. package/examples/js/loaders/PRWMLoader.js +11 -22
  105. package/examples/js/loaders/PVRLoader.js +7 -16
  106. package/examples/js/loaders/RGBELoader.js +36 -61
  107. package/examples/js/loaders/RGBMLoader.js +26 -87
  108. package/examples/js/loaders/STLLoader.js +20 -27
  109. package/examples/js/loaders/SVGLoader.js +365 -236
  110. package/examples/js/loaders/TDSLoader.js +81 -118
  111. package/examples/js/loaders/TGALoader.js +39 -41
  112. package/examples/js/loaders/TIFFLoader.js +30 -0
  113. package/examples/js/loaders/TTFLoader.js +0 -8
  114. package/examples/js/loaders/TiltLoader.js +14 -15
  115. package/examples/js/loaders/VOXLoader.js +8 -16
  116. package/examples/js/loaders/VRMLLoader.js +266 -354
  117. package/examples/js/loaders/VTKLoader.js +102 -119
  118. package/examples/js/loaders/XYZLoader.js +2 -4
  119. package/examples/js/loaders/lwo/IFFParser.js +55 -136
  120. package/examples/js/loaders/lwo/LWO2Parser.js +39 -89
  121. package/examples/js/loaders/lwo/LWO3Parser.js +38 -79
  122. package/examples/js/materials/MeshGouraudMaterial.js +387 -0
  123. package/examples/js/math/Capsule.js +0 -17
  124. package/examples/js/math/ColorConverter.js +3 -53
  125. package/examples/js/math/ConvexHull.js +185 -141
  126. package/examples/js/math/ImprovedNoise.js +1 -1
  127. package/examples/js/math/Lut.js +8 -15
  128. package/examples/js/math/MeshSurfaceSampler.js +6 -28
  129. package/examples/js/math/OBB.js +90 -49
  130. package/examples/js/math/Octree.js +2 -57
  131. package/examples/js/math/SimplexNoise.js +74 -88
  132. package/examples/js/misc/ConvexObjectBreaker.js +37 -48
  133. package/examples/js/misc/GPUComputationRenderer.js +47 -14
  134. package/examples/js/misc/Gyroscope.js +5 -9
  135. package/examples/js/misc/MD2Character.js +14 -23
  136. package/examples/js/misc/MD2CharacterComplex.js +73 -54
  137. package/examples/js/misc/MorphAnimMesh.js +0 -6
  138. package/examples/js/misc/MorphBlendMesh.js +3 -30
  139. package/examples/js/misc/ProgressiveLightMap.js +47 -43
  140. package/examples/js/misc/RollerCoaster.js +17 -24
  141. package/examples/js/misc/TubePainter.js +18 -12
  142. package/examples/js/misc/Volume.js +173 -194
  143. package/examples/js/misc/VolumeSlice.js +91 -99
  144. package/examples/js/modifiers/CurveModifier.js +19 -21
  145. package/examples/js/modifiers/EdgeSplitModifier.js +0 -30
  146. package/examples/js/modifiers/SimplifyModifier.js +57 -60
  147. package/examples/js/modifiers/TessellateModifier.js +2 -9
  148. package/examples/js/objects/GroundProjectedEnv.js +181 -0
  149. package/examples/js/objects/Lensflare.js +47 -38
  150. package/examples/js/objects/LightningStorm.js +10 -13
  151. package/examples/js/objects/MarchingCubes.js +80 -59
  152. package/examples/js/objects/Reflector.js +31 -22
  153. package/examples/js/objects/ReflectorForSSRPass.js +20 -25
  154. package/examples/js/objects/Refractor.js +61 -33
  155. package/examples/js/objects/ShadowMesh.js +6 -3
  156. package/examples/js/objects/Sky.js +2 -7
  157. package/examples/js/objects/Water.js +23 -18
  158. package/examples/js/objects/Water2.js +20 -19
  159. package/examples/js/physics/AmmoPhysics.js +23 -20
  160. package/examples/js/physics/OimoPhysics.js +19 -17
  161. package/examples/js/postprocessing/AdaptiveToneMappingPass.js +13 -20
  162. package/examples/js/postprocessing/AfterimagePass.js +19 -12
  163. package/examples/js/postprocessing/BloomPass.js +38 -17
  164. package/examples/js/postprocessing/BokehPass.js +29 -12
  165. package/examples/js/postprocessing/ClearPass.js +1 -6
  166. package/examples/js/postprocessing/CubeTexturePass.js +12 -9
  167. package/examples/js/postprocessing/DotScreenPass.js +7 -5
  168. package/examples/js/postprocessing/EffectComposer.js +25 -32
  169. package/examples/js/postprocessing/FilmPass.js +7 -5
  170. package/examples/js/postprocessing/GlitchPass.js +10 -11
  171. package/examples/js/postprocessing/HalftonePass.js +9 -9
  172. package/examples/js/postprocessing/LUTPass.js +2 -15
  173. package/examples/js/postprocessing/MaskPass.js +20 -17
  174. package/examples/js/postprocessing/OutlinePass.js +49 -38
  175. package/examples/js/postprocessing/Pass.js +11 -14
  176. package/examples/js/postprocessing/RenderPass.js +3 -7
  177. package/examples/js/postprocessing/RenderPixelatedPass.js +215 -0
  178. package/examples/js/postprocessing/SAOPass.js +40 -32
  179. package/examples/js/postprocessing/SMAAPass.js +34 -17
  180. package/examples/js/postprocessing/SSAARenderPass.js +14 -14
  181. package/examples/js/postprocessing/SSAOPass.js +56 -42
  182. package/examples/js/postprocessing/SSRPass.js +78 -61
  183. package/examples/js/postprocessing/SavePass.js +14 -6
  184. package/examples/js/postprocessing/ShaderPass.js +9 -8
  185. package/examples/js/postprocessing/TAARenderPass.js +11 -9
  186. package/examples/js/postprocessing/TexturePass.js +7 -4
  187. package/examples/js/postprocessing/UnrealBloomPass.js +43 -25
  188. package/examples/js/renderers/CSS2DRenderer.js +4 -23
  189. package/examples/js/renderers/CSS3DRenderer.js +5 -26
  190. package/examples/js/renderers/Projector.js +31 -108
  191. package/examples/js/renderers/SVGRenderer.js +4 -50
  192. package/examples/js/shaders/ACESFilmicToneMappingShader.js +3 -6
  193. package/examples/js/shaders/AfterimageShader.js +3 -6
  194. package/examples/js/shaders/BasicShader.js +3 -6
  195. package/examples/js/shaders/BleachBypassShader.js +3 -6
  196. package/examples/js/shaders/BlendShader.js +3 -6
  197. package/examples/js/shaders/BokehShader.js +3 -6
  198. package/examples/js/shaders/BokehShader2.js +4 -13
  199. package/examples/js/shaders/BrightnessContrastShader.js +3 -6
  200. package/examples/js/shaders/ColorCorrectionShader.js +2 -6
  201. package/examples/js/shaders/ColorifyShader.js +2 -6
  202. package/examples/js/shaders/ConvolutionShader.js +5 -10
  203. package/examples/js/shaders/CopyShader.js +3 -6
  204. package/examples/js/shaders/DOFMipMapShader.js +3 -6
  205. package/examples/js/shaders/DepthLimitedBlurShader.js +2 -9
  206. package/examples/js/shaders/DigitalGlitch.js +3 -6
  207. package/examples/js/shaders/DotScreenShader.js +2 -6
  208. package/examples/js/shaders/FXAAShader.js +1 -3
  209. package/examples/js/shaders/FilmShader.js +3 -6
  210. package/examples/js/shaders/FocusShader.js +3 -6
  211. package/examples/js/shaders/FreiChenShader.js +2 -6
  212. package/examples/js/shaders/GammaCorrectionShader.js +3 -6
  213. package/examples/js/shaders/GodRaysShader.js +11 -24
  214. package/examples/js/shaders/HalftoneShader.js +3 -6
  215. package/examples/js/shaders/HorizontalBlurShader.js +3 -6
  216. package/examples/js/shaders/HorizontalTiltShiftShader.js +3 -6
  217. package/examples/js/shaders/HueSaturationShader.js +3 -6
  218. package/examples/js/shaders/KaleidoShader.js +3 -6
  219. package/examples/js/shaders/LuminosityHighPassShader.js +2 -6
  220. package/examples/js/shaders/LuminosityShader.js +4 -7
  221. package/examples/js/shaders/MMDToonShader.js +2 -4
  222. package/examples/js/shaders/MirrorShader.js +3 -6
  223. package/examples/js/shaders/NormalMapShader.js +2 -6
  224. package/examples/js/shaders/RGBShiftShader.js +3 -6
  225. package/examples/js/shaders/SAOShader.js +2 -6
  226. package/examples/js/shaders/SMAAShader.js +6 -18
  227. package/examples/js/shaders/SSAOShader.js +2 -6
  228. package/examples/js/shaders/SSRShader.js +6 -18
  229. package/examples/js/shaders/SepiaShader.js +3 -6
  230. package/examples/js/shaders/SobelOperatorShader.js +2 -6
  231. package/examples/js/shaders/TechnicolorShader.js +3 -6
  232. package/examples/js/shaders/ToneMapShader.js +4 -7
  233. package/examples/js/shaders/ToonShader.js +8 -24
  234. package/examples/js/shaders/TriangleBlurShader.js +2 -6
  235. package/examples/js/shaders/UnpackDepthRGBAShader.js +3 -6
  236. package/examples/js/shaders/VelocityShader.js +126 -0
  237. package/examples/js/shaders/VerticalBlurShader.js +3 -6
  238. package/examples/js/shaders/VerticalTiltShiftShader.js +3 -6
  239. package/examples/js/shaders/VignetteShader.js +3 -6
  240. package/examples/js/shaders/VolumeShader.js +2 -6
  241. package/examples/js/shaders/WaterRefractionShader.js +2 -6
  242. package/examples/js/textures/FlakesTexture.js +0 -1
  243. package/examples/js/utils/BufferGeometryUtils.js +237 -171
  244. package/examples/js/utils/CameraUtils.js +5 -20
  245. package/examples/js/utils/GPUStatsPanel.js +3 -12
  246. package/examples/js/utils/GeometryCompressionUtils.js +19 -44
  247. package/examples/js/utils/GeometryUtils.js +15 -36
  248. package/examples/js/utils/LDrawUtils.js +8 -11
  249. package/examples/js/utils/PackedPhongMaterial.js +6 -4
  250. package/examples/js/utils/SceneUtils.js +109 -14
  251. package/examples/js/utils/ShadowMapViewer.js +17 -14
  252. package/examples/js/utils/SkeletonUtils.js +13 -27
  253. package/examples/js/utils/UVsDebug.js +20 -12
  254. package/examples/js/utils/WorkerPool.js +1 -11
  255. package/examples/jsm/animation/CCDIKSolver.js +27 -3
  256. package/examples/jsm/animation/MMDPhysics.js +28 -22
  257. package/examples/jsm/capabilities/WebGPU.js +3 -1
  258. package/examples/jsm/controls/ArcballControls.js +17 -2
  259. package/examples/jsm/controls/FirstPersonControls.js +20 -27
  260. package/examples/jsm/controls/FlyControls.js +16 -24
  261. package/examples/jsm/controls/OrbitControls.js +44 -9
  262. package/examples/jsm/controls/PointerLockControls.js +0 -7
  263. package/examples/jsm/controls/TrackballControls.js +14 -5
  264. package/examples/jsm/controls/TransformControls.js +18 -16
  265. package/examples/jsm/csm/CSM.js +1 -0
  266. package/examples/jsm/csm/CSMHelper.js +30 -0
  267. package/examples/jsm/effects/AnaglyphEffect.js +2 -2
  268. package/examples/jsm/effects/OutlineEffect.js +4 -25
  269. package/examples/jsm/effects/ParallaxBarrierEffect.js +2 -2
  270. package/examples/jsm/effects/PeppersGhostEffect.js +2 -2
  271. package/examples/jsm/effects/StereoEffect.js +2 -2
  272. package/examples/jsm/environments/RoomEnvironment.js +23 -0
  273. package/examples/jsm/exporters/ColladaExporter.js +4 -13
  274. package/examples/jsm/exporters/DRACOExporter.js +0 -13
  275. package/examples/jsm/exporters/GLTFExporter.js +29 -110
  276. package/examples/jsm/exporters/KTX2Exporter.js +29 -29
  277. package/examples/jsm/exporters/OBJExporter.js +0 -18
  278. package/examples/jsm/exporters/PLYExporter.js +14 -22
  279. package/examples/jsm/exporters/STLExporter.js +1 -9
  280. package/examples/jsm/exporters/USDZExporter.js +107 -4
  281. package/examples/jsm/geometries/ConvexGeometry.js +1 -1
  282. package/examples/jsm/geometries/ParametricGeometry.js +0 -6
  283. package/examples/jsm/helpers/OctreeHelper.js +22 -8
  284. package/examples/jsm/helpers/VertexNormalsHelper.js +7 -1
  285. package/examples/jsm/helpers/VertexTangentsHelper.js +7 -0
  286. package/examples/jsm/helpers/ViewHelper.js +24 -0
  287. package/examples/jsm/interactive/HTMLMesh.js +14 -15
  288. package/examples/jsm/interactive/InteractiveGroup.js +4 -2
  289. package/examples/jsm/interactive/SelectionHelper.js +5 -3
  290. package/examples/jsm/libs/flow.module.js +610 -160
  291. package/examples/jsm/libs/lottie_canvas.module.js +14844 -0
  292. package/examples/jsm/libs/meshopt_decoder.module.js +97 -32
  293. package/examples/jsm/libs/utif.module.js +1579 -0
  294. package/examples/jsm/libs/zstddec.module.js +1 -0
  295. package/examples/jsm/lines/LineSegments2.js +4 -0
  296. package/examples/jsm/loaders/3DMLoader.js +1 -2
  297. package/examples/jsm/loaders/ColladaLoader.js +29 -0
  298. package/examples/jsm/loaders/DRACOLoader.js +2 -28
  299. package/examples/jsm/loaders/EXRLoader.js +3 -13
  300. package/examples/jsm/loaders/FBXLoader.js +26 -3
  301. package/examples/jsm/loaders/FontLoader.js +3 -16
  302. package/examples/jsm/loaders/GLTFLoader.js +321 -464
  303. package/examples/jsm/loaders/HDRCubeTextureLoader.js +0 -13
  304. package/examples/jsm/loaders/KTX2Loader.js +254 -53
  305. package/examples/jsm/loaders/LDrawLoader.js +149 -87
  306. package/examples/jsm/loaders/LottieLoader.js +4 -2
  307. package/examples/jsm/loaders/MaterialXLoader.js +728 -0
  308. package/examples/jsm/loaders/OBJLoader.js +6 -14
  309. package/examples/jsm/loaders/PCDLoader.js +60 -14
  310. package/examples/jsm/loaders/PLYLoader.js +71 -19
  311. package/examples/jsm/loaders/RGBELoader.js +1 -1
  312. package/examples/jsm/loaders/SVGLoader.js +231 -17
  313. package/examples/jsm/loaders/TIFFLoader.js +36 -0
  314. package/examples/jsm/loaders/USDZLoader.js +633 -0
  315. package/examples/jsm/loaders/VRMLLoader.js +36 -26
  316. package/examples/jsm/loaders/VTKLoader.js +1 -1
  317. package/examples/jsm/loaders/lwo/LWO2Parser.js +6 -8
  318. package/examples/jsm/loaders/lwo/LWO3Parser.js +6 -8
  319. package/examples/jsm/materials/MeshGouraudMaterial.js +423 -0
  320. package/examples/jsm/math/ColorConverter.js +1 -49
  321. package/examples/jsm/math/ConvexHull.js +4 -4
  322. package/examples/jsm/math/Octree.js +1 -1
  323. package/examples/jsm/misc/GPUComputationRenderer.js +43 -0
  324. package/examples/jsm/misc/Volume.js +169 -171
  325. package/examples/jsm/misc/VolumeSlice.js +78 -80
  326. package/examples/jsm/modifiers/SimplifyModifier.js +1 -1
  327. package/examples/jsm/node-editor/NodeEditor.js +91 -12
  328. package/examples/jsm/node-editor/accessors/MatcapUVEditor.js +1 -1
  329. package/examples/jsm/node-editor/accessors/NormalEditor.js +1 -1
  330. package/examples/jsm/node-editor/accessors/PositionEditor.js +1 -1
  331. package/examples/jsm/node-editor/accessors/UVEditor.js +1 -1
  332. package/examples/jsm/node-editor/core/BaseNode.js +10 -3
  333. package/examples/jsm/node-editor/display/BlendEditor.js +1 -1
  334. package/examples/jsm/node-editor/display/NormalMapEditor.js +1 -1
  335. package/examples/jsm/node-editor/inputs/ColorEditor.js +1 -1
  336. package/examples/jsm/node-editor/inputs/FloatEditor.js +1 -1
  337. package/examples/jsm/node-editor/inputs/SliderEditor.js +1 -1
  338. package/examples/jsm/node-editor/inputs/TextureEditor.js +1 -1
  339. package/examples/jsm/node-editor/inputs/Vector2Editor.js +1 -1
  340. package/examples/jsm/node-editor/inputs/Vector3Editor.js +1 -1
  341. package/examples/jsm/node-editor/inputs/Vector4Editor.js +1 -1
  342. package/examples/jsm/node-editor/materials/BasicMaterialEditor.js +7 -10
  343. package/examples/jsm/node-editor/materials/PointsMaterialEditor.js +1 -1
  344. package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +7 -10
  345. package/examples/jsm/node-editor/math/AngleEditor.js +4 -4
  346. package/examples/jsm/node-editor/math/DotEditor.js +1 -1
  347. package/examples/jsm/node-editor/math/InvertEditor.js +3 -3
  348. package/examples/jsm/node-editor/math/LimiterEditor.js +1 -1
  349. package/examples/jsm/node-editor/math/NormalizeEditor.js +1 -1
  350. package/examples/jsm/node-editor/math/OperatorEditor.js +1 -1
  351. package/examples/jsm/node-editor/math/PowerEditor.js +1 -1
  352. package/examples/jsm/node-editor/math/TrigonometryEditor.js +1 -1
  353. package/examples/jsm/node-editor/procedural/CheckerEditor.js +1 -1
  354. package/examples/jsm/node-editor/scene/MeshEditor.js +11 -8
  355. package/examples/jsm/node-editor/utils/JoinEditor.js +1 -1
  356. package/examples/jsm/node-editor/utils/OscillatorEditor.js +1 -1
  357. package/examples/jsm/node-editor/utils/PreviewEditor.js +7 -3
  358. package/examples/jsm/node-editor/utils/SplitEditor.js +1 -1
  359. package/examples/jsm/node-editor/utils/TimerEditor.js +1 -1
  360. package/examples/jsm/nodes/Nodes.js +70 -13
  361. package/examples/jsm/nodes/accessors/BitangentNode.js +62 -0
  362. package/examples/jsm/nodes/accessors/CubeTextureNode.js +9 -5
  363. package/examples/jsm/nodes/accessors/NormalNode.js +8 -8
  364. package/examples/jsm/nodes/accessors/Object3DNode.js +1 -1
  365. package/examples/jsm/nodes/accessors/PositionNode.js +11 -5
  366. package/examples/jsm/nodes/accessors/ReferenceNode.js +1 -1
  367. package/examples/jsm/nodes/accessors/ReflectVectorNode.js +31 -0
  368. package/examples/jsm/nodes/accessors/SkinningNode.js +8 -1
  369. package/examples/jsm/nodes/accessors/TangentNode.js +95 -0
  370. package/examples/jsm/nodes/core/AttributeNode.js +32 -9
  371. package/examples/jsm/nodes/core/CodeNode.js +3 -3
  372. package/examples/jsm/nodes/core/FunctionCallNode.js +20 -5
  373. package/examples/jsm/nodes/core/FunctionNode.js +2 -2
  374. package/examples/jsm/nodes/core/Node.js +15 -13
  375. package/examples/jsm/nodes/core/NodeBuilder.js +67 -18
  376. package/examples/jsm/nodes/core/NodeFrame.js +2 -2
  377. package/examples/jsm/nodes/core/NodeUtils.js +23 -1
  378. package/examples/jsm/nodes/core/NodeVarying.js +17 -0
  379. package/examples/jsm/nodes/core/VaryingNode.js +56 -0
  380. package/examples/jsm/nodes/core/constants.js +13 -13
  381. package/examples/jsm/nodes/display/BlendModeNode.js +85 -0
  382. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +84 -0
  383. package/examples/jsm/nodes/display/NormalMapNode.js +19 -12
  384. package/examples/jsm/nodes/display/PosterizeNode.js +25 -0
  385. package/examples/jsm/nodes/display/ViewportNode.js +106 -0
  386. package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +5 -5
  387. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +3 -3
  388. package/examples/jsm/nodes/functions/light/getDistanceAttenuation.js +2 -2
  389. package/examples/jsm/nodes/geometry/RangeNode.js +109 -0
  390. package/examples/jsm/nodes/gpgpu/ComputeNode.js +3 -1
  391. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +1 -1
  392. package/examples/jsm/nodes/lighting/EnvironmentNode.js +8 -7
  393. package/examples/jsm/nodes/lighting/LightingContextNode.js +4 -4
  394. package/examples/jsm/nodes/loaders/NodeLoader.js +2 -2
  395. package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +33 -0
  396. package/examples/jsm/nodes/materials/Materials.js +21 -31
  397. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +70 -0
  398. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +4 -7
  399. package/examples/jsm/nodes/materials/NodeMaterial.js +11 -3
  400. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +28 -17
  401. package/examples/jsm/nodes/materialx/DISCLAIMER.md +199 -0
  402. package/examples/jsm/nodes/materialx/MaterialXNodes.js +59 -0
  403. package/examples/jsm/nodes/materialx/lib/mx_hsv.js +56 -0
  404. package/examples/jsm/nodes/materialx/lib/mx_noise.js +617 -0
  405. package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +18 -0
  406. package/examples/jsm/nodes/math/MathNode.js +7 -17
  407. package/examples/jsm/nodes/math/OperatorNode.js +16 -3
  408. package/examples/jsm/nodes/parsers/GLSLNodeFunction.js +21 -6
  409. package/examples/jsm/nodes/procedural/CheckerNode.js +2 -2
  410. package/examples/jsm/nodes/shadernode/ShaderNode.js +40 -25
  411. package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +95 -68
  412. package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +49 -6
  413. package/examples/jsm/nodes/utils/ConvertNode.js +18 -12
  414. package/examples/jsm/nodes/utils/EquirectUVNode.js +27 -0
  415. package/examples/jsm/nodes/utils/JoinNode.js +15 -9
  416. package/examples/jsm/nodes/utils/MatcapUVNode.js +2 -4
  417. package/examples/jsm/nodes/utils/MaxMipLevelNode.js +3 -2
  418. package/examples/jsm/nodes/utils/OscNode.js +2 -2
  419. package/examples/jsm/nodes/utils/RemapNode.js +34 -0
  420. package/examples/jsm/nodes/utils/RotateUVNode.js +32 -0
  421. package/examples/jsm/nodes/utils/SplitNode.js +21 -5
  422. package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +8 -10
  423. package/examples/jsm/nodes/utils/TimerNode.js +23 -3
  424. package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +51 -0
  425. package/examples/jsm/objects/GroundProjectedEnv.js +186 -0
  426. package/examples/jsm/objects/Reflector.js +12 -5
  427. package/examples/jsm/objects/ReflectorForSSRPass.js +3 -5
  428. package/examples/jsm/objects/Refractor.js +12 -6
  429. package/examples/jsm/objects/ShadowMesh.js +8 -2
  430. package/examples/jsm/postprocessing/AfterimagePass.js +17 -4
  431. package/examples/jsm/postprocessing/BloomPass.js +22 -3
  432. package/examples/jsm/postprocessing/BokehPass.js +18 -4
  433. package/examples/jsm/postprocessing/CubeTexturePass.js +12 -5
  434. package/examples/jsm/postprocessing/DotScreenPass.js +8 -0
  435. package/examples/jsm/postprocessing/EffectComposer.js +9 -0
  436. package/examples/jsm/postprocessing/FilmPass.js +8 -0
  437. package/examples/jsm/postprocessing/GlitchPass.js +13 -1
  438. package/examples/jsm/postprocessing/HalftonePass.js +8 -0
  439. package/examples/jsm/postprocessing/OutlinePass.js +25 -3
  440. package/examples/jsm/postprocessing/Pass.js +2 -0
  441. package/examples/jsm/postprocessing/RenderPixelatedPass.js +234 -0
  442. package/examples/jsm/postprocessing/SAOPass.js +20 -0
  443. package/examples/jsm/postprocessing/SMAAPass.js +16 -0
  444. package/examples/jsm/postprocessing/SSAARenderPass.js +4 -0
  445. package/examples/jsm/postprocessing/SavePass.js +17 -1
  446. package/examples/jsm/postprocessing/ShaderPass.js +8 -0
  447. package/examples/jsm/postprocessing/TAARenderPass.js +9 -0
  448. package/examples/jsm/postprocessing/TexturePass.js +8 -0
  449. package/examples/jsm/postprocessing/UnrealBloomPass.js +16 -0
  450. package/examples/jsm/renderers/CSS2DRenderer.js +2 -2
  451. package/examples/jsm/renderers/CSS3DRenderer.js +2 -2
  452. package/examples/jsm/renderers/Projector.js +2 -24
  453. package/examples/jsm/renderers/webgl/nodes/SlotNode.js +9 -5
  454. package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +363 -231
  455. package/examples/jsm/renderers/webgl/nodes/WebGLNodes.js +7 -3
  456. package/examples/jsm/renderers/webgpu/WebGPUAnimation.js +58 -0
  457. package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +63 -5
  458. package/examples/jsm/renderers/webgpu/WebGPUBackground.js +68 -3
  459. package/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js +6 -0
  460. package/examples/jsm/renderers/webgpu/WebGPUGeometries.js +6 -0
  461. package/examples/jsm/renderers/webgpu/WebGPUObjects.js +1 -1
  462. package/examples/jsm/renderers/webgpu/WebGPURenderPipeline.js +17 -19
  463. package/examples/jsm/renderers/webgpu/WebGPURenderPipelines.js +16 -14
  464. package/examples/jsm/renderers/webgpu/WebGPURenderStates.js +2 -2
  465. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +113 -93
  466. package/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js +5 -3
  467. package/examples/jsm/renderers/webgpu/WebGPUTextures.js +2 -2
  468. package/examples/jsm/renderers/webgpu/WebGPUUtils.js +81 -0
  469. package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +63 -36
  470. package/examples/jsm/renderers/webgpu/nodes/WebGPUNodes.js +1 -1
  471. package/examples/jsm/shaders/LuminosityShader.js +1 -1
  472. package/examples/jsm/shaders/MMDToonShader.js +2 -4
  473. package/examples/jsm/shaders/ToneMapShader.js +1 -1
  474. package/examples/jsm/shaders/VelocityShader.js +128 -0
  475. package/examples/jsm/utils/BufferGeometryUtils.js +176 -43
  476. package/examples/jsm/utils/GeometryUtils.js +17 -25
  477. package/examples/jsm/utils/PackedPhongMaterial.js +0 -1
  478. package/examples/jsm/utils/SceneUtils.js +117 -12
  479. package/examples/jsm/webxr/OculusHandModel.js +3 -2
  480. package/examples/jsm/webxr/OculusHandPointerModel.js +6 -1
  481. package/examples/jsm/webxr/VRButton.js +1 -7
  482. package/examples/jsm/webxr/XRHandMeshModel.js +8 -3
  483. package/package.json +22 -18
  484. package/src/Three.Legacy.js +262 -36
  485. package/src/Three.js +4 -2
  486. package/src/animation/AnimationAction.js +6 -5
  487. package/src/animation/AnimationClip.js +1 -1
  488. package/src/animation/AnimationMixer.js +1 -1
  489. package/src/animation/AnimationUtils.js +204 -199
  490. package/src/animation/KeyframeTrack.js +1 -1
  491. package/src/animation/PropertyBinding.js +31 -5
  492. package/src/audio/AudioContext.js +5 -5
  493. package/src/cameras/CubeCamera.js +14 -21
  494. package/src/constants.js +2 -4
  495. package/src/core/BufferAttribute.js +81 -111
  496. package/src/core/BufferGeometry.js +3 -41
  497. package/src/core/InstancedBufferAttribute.js +0 -10
  498. package/src/core/InstancedBufferGeometry.js +1 -7
  499. package/src/core/InterleavedBuffer.js +1 -1
  500. package/src/core/InterleavedBufferAttribute.js +57 -8
  501. package/src/core/Object3D.js +22 -5
  502. package/src/core/Uniform.js +0 -7
  503. package/src/core/UniformsGroup.js +92 -0
  504. package/src/extras/DataUtils.js +104 -88
  505. package/src/extras/Earcut.js +67 -67
  506. package/src/extras/core/Path.js +1 -0
  507. package/src/extras/core/ShapePath.js +1 -4
  508. package/src/extras/curves/CatmullRomCurve3.js +4 -2
  509. package/src/geometries/BoxGeometry.js +1 -1
  510. package/src/geometries/CapsuleGeometry.js +1 -1
  511. package/src/geometries/CircleGeometry.js +1 -1
  512. package/src/geometries/ConeGeometry.js +1 -1
  513. package/src/geometries/CylinderGeometry.js +2 -1
  514. package/src/geometries/DodecahedronGeometry.js +1 -1
  515. package/src/geometries/EdgesGeometry.js +5 -4
  516. package/src/geometries/ExtrudeGeometry.js +2 -11
  517. package/src/geometries/IcosahedronGeometry.js +1 -1
  518. package/src/geometries/LatheGeometry.js +2 -2
  519. package/src/geometries/OctahedronGeometry.js +1 -1
  520. package/src/geometries/PlaneGeometry.js +2 -1
  521. package/src/geometries/PolyhedronGeometry.js +2 -2
  522. package/src/geometries/RingGeometry.js +1 -1
  523. package/src/geometries/ShapeGeometry.js +3 -2
  524. package/src/geometries/SphereGeometry.js +2 -1
  525. package/src/geometries/TetrahedronGeometry.js +1 -1
  526. package/src/geometries/TorusGeometry.js +2 -1
  527. package/src/geometries/TorusKnotGeometry.js +2 -1
  528. package/src/geometries/TubeGeometry.js +2 -1
  529. package/src/geometries/WireframeGeometry.js +1 -0
  530. package/src/helpers/ArrowHelper.js +9 -0
  531. package/src/helpers/Box3Helper.js +7 -0
  532. package/src/helpers/BoxHelper.js +7 -1
  533. package/src/helpers/CameraHelper.js +97 -38
  534. package/src/helpers/DirectionalLightHelper.js +6 -1
  535. package/src/helpers/GridHelper.js +7 -0
  536. package/src/helpers/HemisphereLightHelper.js +5 -1
  537. package/src/helpers/PlaneHelper.js +15 -9
  538. package/src/helpers/PointLightHelper.js +2 -1
  539. package/src/helpers/PolarGridHelper.js +25 -14
  540. package/src/helpers/SkeletonHelper.js +7 -0
  541. package/src/helpers/SpotLightHelper.js +5 -2
  542. package/src/lights/LightShadow.js +1 -2
  543. package/src/lights/PointLight.js +2 -2
  544. package/src/lights/SpotLight.js +4 -2
  545. package/src/loaders/FileLoader.js +16 -2
  546. package/src/loaders/LoadingManager.js +1 -1
  547. package/src/loaders/MaterialLoader.js +49 -7
  548. package/src/loaders/ObjectLoader.js +9 -42
  549. package/src/materials/Material.js +2 -34
  550. package/src/materials/Materials.js +0 -27
  551. package/src/materials/MeshLambertMaterial.js +28 -1
  552. package/src/materials/MeshPhysicalMaterial.js +1 -1
  553. package/src/materials/ShaderMaterial.js +3 -7
  554. package/src/math/Color.js +8 -18
  555. package/src/math/MathUtils.js +1 -7
  556. package/src/math/Matrix3.js +54 -25
  557. package/src/math/Matrix4.js +3 -27
  558. package/src/math/Quaternion.js +1 -21
  559. package/src/math/Ray.js +2 -5
  560. package/src/math/Sphere.js +36 -21
  561. package/src/math/Vector2.js +4 -24
  562. package/src/math/Vector3.js +7 -46
  563. package/src/math/Vector4.js +4 -24
  564. package/src/objects/InstancedMesh.js +7 -0
  565. package/src/objects/LOD.js +25 -6
  566. package/src/renderers/WebGL3DRenderTarget.js +1 -1
  567. package/src/renderers/WebGLArrayRenderTarget.js +1 -1
  568. package/src/renderers/WebGLCubeRenderTarget.js +1 -1
  569. package/src/renderers/WebGLMultipleRenderTargets.js +1 -1
  570. package/src/renderers/WebGLRenderTarget.js +1 -1
  571. package/src/renderers/WebGLRenderer.js +119 -69
  572. package/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +12 -12
  573. package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +3 -5
  574. package/src/renderers/shaders/ShaderChunk/common.glsl.js +6 -5
  575. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +24 -24
  576. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -4
  577. package/src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl.js +1 -1
  578. package/src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl.js +1 -1
  579. package/src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js +2 -1
  580. package/src/renderers/shaders/ShaderChunk/iridescence_fragment.glsl.js +113 -99
  581. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +34 -13
  582. package/src/renderers/shaders/ShaderChunk/lights_lambert_fragment.glsl.js +5 -0
  583. package/src/renderers/shaders/ShaderChunk/lights_lambert_pars_fragment.glsl.js +28 -0
  584. package/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js +0 -2
  585. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +3 -1
  586. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +13 -1
  587. package/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js +0 -2
  588. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -4
  589. package/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js +2 -4
  590. package/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js +1 -1
  591. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +8 -0
  592. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +18 -7
  593. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +8 -3
  594. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +9 -6
  595. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
  596. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +14 -10
  597. package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +2 -2
  598. package/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js +1 -1
  599. package/src/renderers/shaders/ShaderChunk.js +7 -2
  600. package/src/renderers/shaders/ShaderLib/background.glsl.js +7 -2
  601. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +62 -0
  602. package/src/renderers/shaders/ShaderLib/cube.glsl.js +4 -6
  603. package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +0 -1
  604. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +22 -50
  605. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
  606. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +0 -3
  607. package/src/renderers/shaders/ShaderLib.js +50 -36
  608. package/src/renderers/shaders/UniformsLib.js +13 -12
  609. package/src/renderers/shaders/UniformsUtils.js +29 -0
  610. package/src/renderers/webgl/WebGLAttributes.js +2 -0
  611. package/src/renderers/webgl/WebGLBackground.js +17 -9
  612. package/src/renderers/webgl/WebGLLights.js +37 -17
  613. package/src/renderers/webgl/WebGLMaterials.js +2 -1
  614. package/src/renderers/webgl/WebGLMorphtargets.js +0 -20
  615. package/src/renderers/webgl/WebGLProgram.js +6 -11
  616. package/src/renderers/webgl/WebGLPrograms.js +30 -26
  617. package/src/renderers/webgl/WebGLRenderLists.js +5 -4
  618. package/src/renderers/webgl/WebGLRenderStates.js +5 -4
  619. package/src/renderers/webgl/WebGLShaderCache.js +9 -6
  620. package/src/renderers/webgl/WebGLShadowMap.js +13 -16
  621. package/src/renderers/webgl/WebGLState.js +125 -41
  622. package/src/renderers/webgl/WebGLTextures.js +94 -39
  623. package/src/renderers/webgl/WebGLUniforms.js +156 -28
  624. package/src/renderers/webgl/WebGLUniformsGroups.js +372 -0
  625. package/src/renderers/webgl/WebGLUtils.js +3 -1
  626. package/src/renderers/webvr/WebVRManager.js +42 -9
  627. package/src/renderers/webvr/WebVRUtils.js +1 -1
  628. package/src/renderers/webxr/WebXRController.js +91 -50
  629. package/src/renderers/webxr/WebXRManager.js +127 -34
  630. package/src/scenes/Scene.js +24 -3
  631. package/src/textures/CompressedArrayTexture.js +18 -0
  632. package/src/textures/Source.js +1 -1
  633. package/src/textures/Texture.js +2 -1
  634. package/src/utils.js +1 -1
  635. package/examples/js/controls/experimental/CameraControls.js +0 -1048
  636. package/examples/js/libs/lottie_canvas.js +0 -12751
  637. package/examples/js/loaders/KTX2Loader.js +0 -558
  638. package/examples/js/shaders/PixelShader.js +0 -51
  639. package/examples/jsm/controls/experimental/CameraControls.js +0 -1248
  640. package/examples/jsm/nodes/accessors/ReflectNode.js +0 -70
  641. package/examples/jsm/nodes/core/NodeVary.js +0 -14
  642. package/examples/jsm/nodes/core/VaryNode.js +0 -54
  643. package/examples/jsm/package.json +0 -3
  644. package/examples/jsm/renderers/webgl/nodes/WebGLPhysicalContextNode.js +0 -45
  645. package/examples/jsm/shaders/PixelShader.js +0 -44
  646. package/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl.js +0 -122
@@ -18,7 +18,6 @@
18
18
  let fbxTree;
19
19
  let connections;
20
20
  let sceneGraph;
21
-
22
21
  class FBXLoader extends THREE.Loader {
23
22
 
24
23
  constructor( manager ) {
@@ -26,7 +25,6 @@
26
25
  super( manager );
27
26
 
28
27
  }
29
-
30
28
  load( url, onLoad, onProgress, onError ) {
31
29
 
32
30
  const scope = this;
@@ -61,7 +59,6 @@
61
59
  }, onProgress, onError );
62
60
 
63
61
  }
64
-
65
62
  parse( FBXBuffer, path ) {
66
63
 
67
64
  if ( isFbxFormatBinary( FBXBuffer ) ) {
@@ -71,7 +68,6 @@
71
68
  } else {
72
69
 
73
70
  const FBXText = convertArrayBufferToString( FBXBuffer );
74
-
75
71
  if ( ! isFbxFormatASCII( FBXText ) ) {
76
72
 
77
73
  throw new Error( 'THREE.FBXLoader: Unknown format.' );
@@ -86,17 +82,18 @@
86
82
 
87
83
  fbxTree = new TextParser().parse( FBXText );
88
84
 
89
- } // console.log( fbxTree );
85
+ }
90
86
 
87
+ // console.log( fbxTree );
91
88
 
92
89
  const textureLoader = new THREE.TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
93
90
  return new FBXTreeParser( textureLoader, this.manager ).parse( fbxTree );
94
91
 
95
92
  }
96
93
 
97
- } // Parse the FBXTree object returned by the BinaryParser or TextParser and return a THREE.Group
98
-
94
+ }
99
95
 
96
+ // Parse the FBXTree object returned by the BinaryParser or TextParser and return a THREE.Group
100
97
  class FBXTreeParser {
101
98
 
102
99
  constructor( textureLoader, manager ) {
@@ -105,7 +102,6 @@
105
102
  this.manager = manager;
106
103
 
107
104
  }
108
-
109
105
  parse() {
110
106
 
111
107
  connections = this.parseConnections();
@@ -117,14 +113,13 @@
117
113
  this.parseScene( deformers, geometryMap, materials );
118
114
  return sceneGraph;
119
115
 
120
- } // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry )
121
- // and details the connection type
122
-
116
+ }
123
117
 
118
+ // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry )
119
+ // and details the connection type
124
120
  parseConnections() {
125
121
 
126
122
  const connectionMap = new Map();
127
-
128
123
  if ( 'Connections' in fbxTree ) {
129
124
 
130
125
  const rawConnections = fbxTree.Connections.connections;
@@ -133,7 +128,6 @@
133
128
  const fromID = rawConnection[ 0 ];
134
129
  const toID = rawConnection[ 1 ];
135
130
  const relationship = rawConnection[ 2 ];
136
-
137
131
  if ( ! connectionMap.has( fromID ) ) {
138
132
 
139
133
  connectionMap.set( fromID, {
@@ -148,7 +142,6 @@
148
142
  relationship: relationship
149
143
  };
150
144
  connectionMap.get( fromID ).parents.push( parentRelationship );
151
-
152
145
  if ( ! connectionMap.has( toID ) ) {
153
146
 
154
147
  connectionMap.set( toID, {
@@ -170,31 +163,29 @@
170
163
 
171
164
  return connectionMap;
172
165
 
173
- } // Parse FBXTree.Objects.Video for embedded image data
166
+ }
167
+
168
+ // Parse FBXTree.Objects.Video for embedded image data
174
169
  // These images are connected to textures in FBXTree.Objects.Textures
175
170
  // via FBXTree.Connections.
176
-
177
-
178
171
  parseImages() {
179
172
 
180
173
  const images = {};
181
174
  const blobs = {};
182
-
183
175
  if ( 'Video' in fbxTree.Objects ) {
184
176
 
185
177
  const videoNodes = fbxTree.Objects.Video;
186
-
187
178
  for ( const nodeID in videoNodes ) {
188
179
 
189
180
  const videoNode = videoNodes[ nodeID ];
190
181
  const id = parseInt( nodeID );
191
- images[ id ] = videoNode.RelativeFilename || videoNode.Filename; // raw image data is in videoNode.Content
182
+ images[ id ] = videoNode.RelativeFilename || videoNode.Filename;
192
183
 
184
+ // raw image data is in videoNode.Content
193
185
  if ( 'Content' in videoNode ) {
194
186
 
195
187
  const arrayBufferContent = videoNode.Content instanceof ArrayBuffer && videoNode.Content.byteLength > 0;
196
188
  const base64Content = typeof videoNode.Content === 'string' && videoNode.Content !== '';
197
-
198
189
  if ( arrayBufferContent || base64Content ) {
199
190
 
200
191
  const image = this.parseImage( videoNodes[ nodeID ] );
@@ -217,35 +208,30 @@
217
208
 
218
209
  return images;
219
210
 
220
- } // Parse embedded image data in FBXTree.Video.Content
221
-
211
+ }
222
212
 
213
+ // Parse embedded image data in FBXTree.Video.Content
223
214
  parseImage( videoNode ) {
224
215
 
225
216
  const content = videoNode.Content;
226
217
  const fileName = videoNode.RelativeFilename || videoNode.Filename;
227
218
  const extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase();
228
219
  let type;
229
-
230
220
  switch ( extension ) {
231
221
 
232
222
  case 'bmp':
233
223
  type = 'image/bmp';
234
224
  break;
235
-
236
225
  case 'jpg':
237
226
  case 'jpeg':
238
227
  type = 'image/jpeg';
239
228
  break;
240
-
241
229
  case 'png':
242
230
  type = 'image/png';
243
231
  break;
244
-
245
232
  case 'tif':
246
233
  type = 'image/tiff';
247
234
  break;
248
-
249
235
  case 'tga':
250
236
  if ( this.manager.getHandler( '.tga' ) === null ) {
251
237
 
@@ -255,7 +241,6 @@
255
241
 
256
242
  type = 'image/tga';
257
243
  break;
258
-
259
244
  default:
260
245
  console.warn( 'FBXLoader: Image type "' + extension + '" is not supported.' );
261
246
  return;
@@ -265,11 +250,13 @@
265
250
  if ( typeof content === 'string' ) {
266
251
 
267
252
  // ASCII format
253
+
268
254
  return 'data:' + type + ';base64,' + content;
269
255
 
270
256
  } else {
271
257
 
272
258
  // Binary Format
259
+
273
260
  const array = new Uint8Array( content );
274
261
  return window.URL.createObjectURL( new Blob( [ array ], {
275
262
  type: type
@@ -277,19 +264,17 @@
277
264
 
278
265
  }
279
266
 
280
- } // Parse nodes in FBXTree.Objects.Texture
267
+ }
268
+
269
+ // Parse nodes in FBXTree.Objects.Texture
281
270
  // These contain details such as UV scaling, cropping, rotation etc and are connected
282
271
  // to images in FBXTree.Objects.Video
283
-
284
-
285
272
  parseTextures( images ) {
286
273
 
287
274
  const textureMap = new Map();
288
-
289
275
  if ( 'Texture' in fbxTree.Objects ) {
290
276
 
291
277
  const textureNodes = fbxTree.Objects.Texture;
292
-
293
278
  for ( const nodeID in textureNodes ) {
294
279
 
295
280
  const texture = this.parseTexture( textureNodes[ nodeID ], images );
@@ -301,9 +286,9 @@
301
286
 
302
287
  return textureMap;
303
288
 
304
- } // Parse individual node in FBXTree.Objects.Texture
305
-
289
+ }
306
290
 
291
+ // Parse individual node in FBXTree.Objects.Texture
307
292
  parseTexture( textureNode, images ) {
308
293
 
309
294
  const texture = this.loadTexture( textureNode, images );
@@ -312,12 +297,13 @@
312
297
  const wrapModeU = textureNode.WrapModeU;
313
298
  const wrapModeV = textureNode.WrapModeV;
314
299
  const valueU = wrapModeU !== undefined ? wrapModeU.value : 0;
315
- const valueV = wrapModeV !== undefined ? wrapModeV.value : 0; // http://download.autodesk.com/us/fbx/SDKdocs/FBX_SDK_Help/files/fbxsdkref/class_k_fbx_texture.html#889640e63e2e681259ea81061b85143a
300
+ const valueV = wrapModeV !== undefined ? wrapModeV.value : 0;
301
+
302
+ // http://download.autodesk.com/us/fbx/SDKdocs/FBX_SDK_Help/files/fbxsdkref/class_k_fbx_texture.html#889640e63e2e681259ea81061b85143a
316
303
  // 0: repeat(default), 1: clamp
317
304
 
318
305
  texture.wrapS = valueU === 0 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
319
306
  texture.wrapT = valueV === 0 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
320
-
321
307
  if ( 'Scaling' in textureNode ) {
322
308
 
323
309
  const values = textureNode.Scaling.value;
@@ -336,19 +322,17 @@
336
322
 
337
323
  return texture;
338
324
 
339
- } // load a texture specified as a blob or data URI, or via an external URL using THREE.TextureLoader
340
-
325
+ }
341
326
 
327
+ // load a texture specified as a blob or data URI, or via an external URL using THREE.TextureLoader
342
328
  loadTexture( textureNode, images ) {
343
329
 
344
330
  let fileName;
345
331
  const currentPath = this.textureLoader.path;
346
332
  const children = connections.get( textureNode.id ).children;
347
-
348
333
  if ( children !== undefined && children.length > 0 && images[ children[ 0 ].ID ] !== undefined ) {
349
334
 
350
335
  fileName = images[ children[ 0 ].ID ];
351
-
352
336
  if ( fileName.indexOf( 'blob:' ) === 0 || fileName.indexOf( 'data:' ) === 0 ) {
353
337
 
354
338
  this.textureLoader.setPath( undefined );
@@ -359,11 +343,9 @@
359
343
 
360
344
  let texture;
361
345
  const extension = textureNode.FileName.slice( - 3 ).toLowerCase();
362
-
363
346
  if ( extension === 'tga' ) {
364
347
 
365
348
  const loader = this.manager.getHandler( '.tga' );
366
-
367
349
  if ( loader === null ) {
368
350
 
369
351
  console.warn( 'FBXLoader: TGA loader not found, creating placeholder texture for', textureNode.RelativeFilename );
@@ -390,17 +372,15 @@
390
372
  this.textureLoader.setPath( currentPath );
391
373
  return texture;
392
374
 
393
- } // Parse nodes in FBXTree.Objects.Material
394
-
375
+ }
395
376
 
377
+ // Parse nodes in FBXTree.Objects.Material
396
378
  parseMaterials( textureMap ) {
397
379
 
398
380
  const materialMap = new Map();
399
-
400
381
  if ( 'Material' in fbxTree.Objects ) {
401
382
 
402
383
  const materialNodes = fbxTree.Objects.Material;
403
-
404
384
  for ( const nodeID in materialNodes ) {
405
385
 
406
386
  const material = this.parseMaterial( materialNodes[ nodeID ], textureMap );
@@ -412,38 +392,36 @@
412
392
 
413
393
  return materialMap;
414
394
 
415
- } // Parse single node in FBXTree.Objects.Material
395
+ }
396
+
397
+ // Parse single node in FBXTree.Objects.Material
416
398
  // Materials are connected to texture maps in FBXTree.Objects.Textures
417
399
  // FBX format currently only supports Lambert and Phong shading models
418
-
419
-
420
400
  parseMaterial( materialNode, textureMap ) {
421
401
 
422
402
  const ID = materialNode.id;
423
403
  const name = materialNode.attrName;
424
- let type = materialNode.ShadingModel; // Case where FBX wraps shading model in property object.
404
+ let type = materialNode.ShadingModel;
425
405
 
406
+ // Case where FBX wraps shading model in property object.
426
407
  if ( typeof type === 'object' ) {
427
408
 
428
409
  type = type.value;
429
410
 
430
- } // Ignore unused materials which don't have any connections.
431
-
411
+ }
432
412
 
413
+ // Ignore unused materials which don't have any connections.
433
414
  if ( ! connections.has( ID ) ) return null;
434
415
  const parameters = this.parseParameters( materialNode, textureMap, ID );
435
416
  let material;
436
-
437
417
  switch ( type.toLowerCase() ) {
438
418
 
439
419
  case 'phong':
440
420
  material = new THREE.MeshPhongMaterial();
441
421
  break;
442
-
443
422
  case 'lambert':
444
423
  material = new THREE.MeshLambertMaterial();
445
424
  break;
446
-
447
425
  default:
448
426
  console.warn( 'THREE.FBXLoader: unknown material type "%s". Defaulting to THREE.MeshPhongMaterial.', type );
449
427
  material = new THREE.MeshPhongMaterial();
@@ -455,14 +433,13 @@
455
433
  material.name = name;
456
434
  return material;
457
435
 
458
- } // Parse FBX material and return parameters suitable for a three.js material
459
- // Also parse the texture map and return any textures associated with the material
460
-
436
+ }
461
437
 
438
+ // Parse FBX material and return parameters suitable for a three.js material
439
+ // Also parse the texture map and return any textures associated with the material
462
440
  parseParameters( materialNode, textureMap, ID ) {
463
441
 
464
442
  const parameters = {};
465
-
466
443
  if ( materialNode.BumpFactor ) {
467
444
 
468
445
  parameters.bumpScale = materialNode.BumpFactor.value;
@@ -542,21 +519,17 @@
542
519
  connections.get( ID ).children.forEach( function ( child ) {
543
520
 
544
521
  const type = child.relationship;
545
-
546
522
  switch ( type ) {
547
523
 
548
524
  case 'Bump':
549
525
  parameters.bumpMap = scope.getTexture( textureMap, child.ID );
550
526
  break;
551
-
552
527
  case 'Maya|TEX_ao_map':
553
528
  parameters.aoMap = scope.getTexture( textureMap, child.ID );
554
529
  break;
555
-
556
530
  case 'DiffuseColor':
557
531
  case 'Maya|TEX_color_map':
558
532
  parameters.map = scope.getTexture( textureMap, child.ID );
559
-
560
533
  if ( parameters.map !== undefined ) {
561
534
 
562
535
  parameters.map.encoding = THREE.sRGBEncoding;
@@ -564,14 +537,11 @@
564
537
  }
565
538
 
566
539
  break;
567
-
568
540
  case 'DisplacementColor':
569
541
  parameters.displacementMap = scope.getTexture( textureMap, child.ID );
570
542
  break;
571
-
572
543
  case 'EmissiveColor':
573
544
  parameters.emissiveMap = scope.getTexture( textureMap, child.ID );
574
-
575
545
  if ( parameters.emissiveMap !== undefined ) {
576
546
 
577
547
  parameters.emissiveMap.encoding = THREE.sRGBEncoding;
@@ -579,15 +549,12 @@
579
549
  }
580
550
 
581
551
  break;
582
-
583
552
  case 'NormalMap':
584
553
  case 'Maya|TEX_normal_map':
585
554
  parameters.normalMap = scope.getTexture( textureMap, child.ID );
586
555
  break;
587
-
588
556
  case 'ReflectionColor':
589
557
  parameters.envMap = scope.getTexture( textureMap, child.ID );
590
-
591
558
  if ( parameters.envMap !== undefined ) {
592
559
 
593
560
  parameters.envMap.mapping = THREE.EquirectangularReflectionMapping;
@@ -596,10 +563,8 @@
596
563
  }
597
564
 
598
565
  break;
599
-
600
566
  case 'SpecularColor':
601
567
  parameters.specularMap = scope.getTexture( textureMap, child.ID );
602
-
603
568
  if ( parameters.specularMap !== undefined ) {
604
569
 
605
570
  parameters.specularMap.encoding = THREE.sRGBEncoding;
@@ -607,20 +572,15 @@
607
572
  }
608
573
 
609
574
  break;
610
-
611
575
  case 'TransparentColor':
612
576
  case 'TransparencyFactor':
613
577
  parameters.alphaMap = scope.getTexture( textureMap, child.ID );
614
578
  parameters.transparent = true;
615
579
  break;
616
-
617
580
  case 'AmbientColor':
618
581
  case 'ShininessExponent': // AKA glossiness map
619
-
620
582
  case 'SpecularFactor': // AKA specularLevel
621
-
622
583
  case 'VectorDisplacementColor': // NOTE: Seems to be a copy of DisplacementColor
623
-
624
584
  default:
625
585
  console.warn( 'THREE.FBXLoader: %s map is not supported in three.js, skipping texture.', type );
626
586
  break;
@@ -630,9 +590,9 @@
630
590
  } );
631
591
  return parameters;
632
592
 
633
- } // get a texture from the textureMap for use by a material.
634
-
593
+ }
635
594
 
595
+ // get a texture from the textureMap for use by a material.
636
596
  getTexture( textureMap, id ) {
637
597
 
638
598
  // if the texture is a layered texture, just use the first layer and issue a warning
@@ -645,25 +605,22 @@
645
605
 
646
606
  return textureMap.get( id );
647
607
 
648
- } // Parse nodes in FBXTree.Objects.Deformer
608
+ }
609
+
610
+ // Parse nodes in FBXTree.Objects.Deformer
649
611
  // Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here
650
612
  // Generates map of THREE.Skeleton-like objects for use later when generating and binding skeletons.
651
-
652
-
653
613
  parseDeformers() {
654
614
 
655
615
  const skeletons = {};
656
616
  const morphTargets = {};
657
-
658
617
  if ( 'Deformer' in fbxTree.Objects ) {
659
618
 
660
619
  const DeformerNodes = fbxTree.Objects.Deformer;
661
-
662
620
  for ( const nodeID in DeformerNodes ) {
663
621
 
664
622
  const deformerNode = DeformerNodes[ nodeID ];
665
623
  const relationships = connections.get( parseInt( nodeID ) );
666
-
667
624
  if ( deformerNode.attrType === 'Skin' ) {
668
625
 
669
626
  const skeleton = this.parseSkeleton( relationships, DeformerNodes );
@@ -693,11 +650,11 @@
693
650
  morphTargets: morphTargets
694
651
  };
695
652
 
696
- } // Parse single nodes in FBXTree.Objects.Deformer
653
+ }
654
+
655
+ // Parse single nodes in FBXTree.Objects.Deformer
697
656
  // The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster'
698
657
  // Each skin node represents a skeleton and each cluster node represents a bone
699
-
700
-
701
658
  parseSkeleton( relationships, deformerNodes ) {
702
659
 
703
660
  const rawBones = [];
@@ -709,9 +666,9 @@
709
666
  ID: child.ID,
710
667
  indices: [],
711
668
  weights: [],
712
- transformLink: new THREE.Matrix4().fromArray( boneNode.TransformLink.a ) // transform: new THREE.Matrix4().fromArray( boneNode.Transform.a ),
669
+ transformLink: new THREE.Matrix4().fromArray( boneNode.TransformLink.a )
670
+ // transform: new THREE.Matrix4().fromArray( boneNode.Transform.a ),
713
671
  // linkMode: boneNode.Mode,
714
-
715
672
  };
716
673
 
717
674
  if ( 'Indexes' in boneNode ) {
@@ -729,13 +686,12 @@
729
686
  bones: []
730
687
  };
731
688
 
732
- } // The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel"
733
-
689
+ }
734
690
 
691
+ // The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel"
735
692
  parseMorphTargets( relationships, deformerNodes ) {
736
693
 
737
694
  const rawMorphTargets = [];
738
-
739
695
  for ( let i = 0; i < relationships.children.length; i ++ ) {
740
696
 
741
697
  const child = relationships.children[ i ];
@@ -758,9 +714,9 @@
758
714
 
759
715
  return rawMorphTargets;
760
716
 
761
- } // create the main THREE.Group() to be returned by the loader
762
-
717
+ }
763
718
 
719
+ // create the main THREE.Group() to be returned by the loader
764
720
  parseScene( deformers, geometryMap, materialMap ) {
765
721
 
766
722
  sceneGraph = new THREE.Group();
@@ -778,7 +734,6 @@
778
734
  if ( parent !== undefined ) parent.add( model );
779
735
 
780
736
  } );
781
-
782
737
  if ( model.parent === null ) {
783
738
 
784
739
  sceneGraph.add( model );
@@ -806,8 +761,9 @@
806
761
  }
807
762
 
808
763
  } );
809
- const animations = new AnimationParser().parse(); // if all the models where already combined in a single group, just return that
764
+ const animations = new AnimationParser().parse();
810
765
 
766
+ // if all the models where already combined in a single group, just return that
811
767
  if ( sceneGraph.children.length === 1 && sceneGraph.children[ 0 ].isGroup ) {
812
768
 
813
769
  sceneGraph.children[ 0 ].animations = animations;
@@ -817,21 +773,19 @@
817
773
 
818
774
  sceneGraph.animations = animations;
819
775
 
820
- } // parse nodes in FBXTree.Objects.Model
821
-
776
+ }
822
777
 
778
+ // parse nodes in FBXTree.Objects.Model
823
779
  parseModels( skeletons, geometryMap, materialMap ) {
824
780
 
825
781
  const modelMap = new Map();
826
782
  const modelNodes = fbxTree.Objects.Model;
827
-
828
783
  for ( const nodeID in modelNodes ) {
829
784
 
830
785
  const id = parseInt( nodeID );
831
786
  const node = modelNodes[ nodeID ];
832
787
  const relationships = connections.get( id );
833
788
  let model = this.buildSkeleton( relationships, skeletons, id, node.attrName );
834
-
835
789
  if ( ! model ) {
836
790
 
837
791
  switch ( node.attrType ) {
@@ -839,24 +793,19 @@
839
793
  case 'Camera':
840
794
  model = this.createCamera( relationships );
841
795
  break;
842
-
843
796
  case 'Light':
844
797
  model = this.createLight( relationships );
845
798
  break;
846
-
847
799
  case 'Mesh':
848
800
  model = this.createMesh( relationships, geometryMap, materialMap );
849
801
  break;
850
-
851
802
  case 'NurbsCurve':
852
803
  model = this.createCurve( relationships, geometryMap );
853
804
  break;
854
-
855
805
  case 'LimbNode':
856
806
  case 'Root':
857
807
  model = new THREE.Bone();
858
808
  break;
859
-
860
809
  case 'Null':
861
810
  default:
862
811
  model = new THREE.Group();
@@ -877,7 +826,6 @@
877
826
  return modelMap;
878
827
 
879
828
  }
880
-
881
829
  buildSkeleton( relationships, skeletons, id, name ) {
882
830
 
883
831
  let bone = null;
@@ -892,13 +840,16 @@
892
840
 
893
841
  const subBone = bone;
894
842
  bone = new THREE.Bone();
895
- bone.matrixWorld.copy( rawBone.transformLink ); // set name and id here - otherwise in cases where "subBone" is created it will not have a name / id
843
+ bone.matrixWorld.copy( rawBone.transformLink );
844
+
845
+ // set name and id here - otherwise in cases where "subBone" is created it will not have a name / id
896
846
 
897
847
  bone.name = name ? THREE.PropertyBinding.sanitizeNodeName( name ) : '';
898
848
  bone.ID = id;
899
- skeleton.bones[ i ] = bone; // In cases where a bone is shared between multiple meshes
900
- // duplicate the bone here and and it as a child of the first bone
849
+ skeleton.bones[ i ] = bone;
901
850
 
851
+ // In cases where a bone is shared between multiple meshes
852
+ // duplicate the bone here and and it as a child of the first bone
902
853
  if ( subBone !== null ) {
903
854
 
904
855
  bone.add( subBone );
@@ -914,9 +865,9 @@
914
865
  } );
915
866
  return bone;
916
867
 
917
- } // create a THREE.PerspectiveCamera or THREE.OrthographicCamera
918
-
868
+ }
919
869
 
870
+ // create a THREE.PerspectiveCamera or THREE.OrthographicCamera
920
871
  createCamera( relationships ) {
921
872
 
922
873
  let model;
@@ -924,7 +875,6 @@
924
875
  relationships.children.forEach( function ( child ) {
925
876
 
926
877
  const attr = fbxTree.Objects.NodeAttribute[ child.ID ];
927
-
928
878
  if ( attr !== undefined ) {
929
879
 
930
880
  cameraAttribute = attr;
@@ -932,7 +882,6 @@
932
882
  }
933
883
 
934
884
  } );
935
-
936
885
  if ( cameraAttribute === undefined ) {
937
886
 
938
887
  model = new THREE.Object3D();
@@ -940,7 +889,6 @@
940
889
  } else {
941
890
 
942
891
  let type = 0;
943
-
944
892
  if ( cameraAttribute.CameraProjectionType !== undefined && cameraAttribute.CameraProjectionType.value === 1 ) {
945
893
 
946
894
  type = 1;
@@ -948,7 +896,6 @@
948
896
  }
949
897
 
950
898
  let nearClippingPlane = 1;
951
-
952
899
  if ( cameraAttribute.NearPlane !== undefined ) {
953
900
 
954
901
  nearClippingPlane = cameraAttribute.NearPlane.value / 1000;
@@ -956,7 +903,6 @@
956
903
  }
957
904
 
958
905
  let farClippingPlane = 1000;
959
-
960
906
  if ( cameraAttribute.FarPlane !== undefined ) {
961
907
 
962
908
  farClippingPlane = cameraAttribute.FarPlane.value / 1000;
@@ -965,7 +911,6 @@
965
911
 
966
912
  let width = window.innerWidth;
967
913
  let height = window.innerHeight;
968
-
969
914
  if ( cameraAttribute.AspectWidth !== undefined && cameraAttribute.AspectHeight !== undefined ) {
970
915
 
971
916
  width = cameraAttribute.AspectWidth.value;
@@ -975,7 +920,6 @@
975
920
 
976
921
  const aspect = width / height;
977
922
  let fov = 45;
978
-
979
923
  if ( cameraAttribute.FieldOfView !== undefined ) {
980
924
 
981
925
  fov = cameraAttribute.FieldOfView.value;
@@ -983,7 +927,6 @@
983
927
  }
984
928
 
985
929
  const focalLength = cameraAttribute.FocalLength ? cameraAttribute.FocalLength.value : null;
986
-
987
930
  switch ( type ) {
988
931
 
989
932
  case 0:
@@ -991,12 +934,10 @@
991
934
  model = new THREE.PerspectiveCamera( fov, aspect, nearClippingPlane, farClippingPlane );
992
935
  if ( focalLength !== null ) model.setFocalLength( focalLength );
993
936
  break;
994
-
995
937
  case 1:
996
938
  // Orthographic
997
939
  model = new THREE.OrthographicCamera( - width / 2, width / 2, height / 2, - height / 2, nearClippingPlane, farClippingPlane );
998
940
  break;
999
-
1000
941
  default:
1001
942
  console.warn( 'THREE.FBXLoader: Unknown camera type ' + type + '.' );
1002
943
  model = new THREE.Object3D();
@@ -1008,9 +949,9 @@
1008
949
 
1009
950
  return model;
1010
951
 
1011
- } // Create a THREE.DirectionalLight, THREE.PointLight or THREE.SpotLight
1012
-
952
+ }
1013
953
 
954
+ // Create a THREE.DirectionalLight, THREE.PointLight or THREE.SpotLight
1014
955
  createLight( relationships ) {
1015
956
 
1016
957
  let model;
@@ -1018,7 +959,6 @@
1018
959
  relationships.children.forEach( function ( child ) {
1019
960
 
1020
961
  const attr = fbxTree.Objects.NodeAttribute[ child.ID ];
1021
-
1022
962
  if ( attr !== undefined ) {
1023
963
 
1024
964
  lightAttribute = attr;
@@ -1026,15 +966,15 @@
1026
966
  }
1027
967
 
1028
968
  } );
1029
-
1030
969
  if ( lightAttribute === undefined ) {
1031
970
 
1032
971
  model = new THREE.Object3D();
1033
972
 
1034
973
  } else {
1035
974
 
1036
- let type; // LightType can be undefined for Point lights
975
+ let type;
1037
976
 
977
+ // LightType can be undefined for Point lights
1038
978
  if ( lightAttribute.LightType === undefined ) {
1039
979
 
1040
980
  type = 0;
@@ -1046,15 +986,15 @@
1046
986
  }
1047
987
 
1048
988
  let color = 0xffffff;
1049
-
1050
989
  if ( lightAttribute.Color !== undefined ) {
1051
990
 
1052
991
  color = new THREE.Color().fromArray( lightAttribute.Color.value );
1053
992
 
1054
993
  }
1055
994
 
1056
- let intensity = lightAttribute.Intensity === undefined ? 1 : lightAttribute.Intensity.value / 100; // light disabled
995
+ let intensity = lightAttribute.Intensity === undefined ? 1 : lightAttribute.Intensity.value / 100;
1057
996
 
997
+ // light disabled
1058
998
  if ( lightAttribute.CastLightOnObject !== undefined && lightAttribute.CastLightOnObject.value === 0 ) {
1059
999
 
1060
1000
  intensity = 0;
@@ -1062,7 +1002,6 @@
1062
1002
  }
1063
1003
 
1064
1004
  let distance = 0;
1065
-
1066
1005
  if ( lightAttribute.FarAttenuationEnd !== undefined ) {
1067
1006
 
1068
1007
  if ( lightAttribute.EnableFarAttenuation !== undefined && lightAttribute.EnableFarAttenuation.value === 0 ) {
@@ -1075,27 +1014,23 @@
1075
1014
 
1076
1015
  }
1077
1016
 
1078
- } // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd?
1079
-
1017
+ }
1080
1018
 
1019
+ // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd?
1081
1020
  const decay = 1;
1082
-
1083
1021
  switch ( type ) {
1084
1022
 
1085
1023
  case 0:
1086
1024
  // Point
1087
1025
  model = new THREE.PointLight( color, intensity, distance, decay );
1088
1026
  break;
1089
-
1090
1027
  case 1:
1091
1028
  // Directional
1092
1029
  model = new THREE.DirectionalLight( color, intensity );
1093
1030
  break;
1094
-
1095
1031
  case 2:
1096
1032
  // Spot
1097
1033
  let angle = Math.PI / 3;
1098
-
1099
1034
  if ( lightAttribute.InnerAngle !== undefined ) {
1100
1035
 
1101
1036
  angle = THREE.MathUtils.degToRad( lightAttribute.InnerAngle.value );
@@ -1103,7 +1038,6 @@
1103
1038
  }
1104
1039
 
1105
1040
  let penumbra = 0;
1106
-
1107
1041
  if ( lightAttribute.OuterAngle !== undefined ) {
1108
1042
 
1109
1043
  // TODO: this is not correct - FBX calculates outer and inner angle in degrees
@@ -1116,7 +1050,6 @@
1116
1050
 
1117
1051
  model = new THREE.SpotLight( color, intensity, distance, angle, penumbra, decay );
1118
1052
  break;
1119
-
1120
1053
  default:
1121
1054
  console.warn( 'THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a THREE.PointLight.' );
1122
1055
  model = new THREE.PointLight( color, intensity );
@@ -1135,14 +1068,14 @@
1135
1068
  return model;
1136
1069
 
1137
1070
  }
1138
-
1139
1071
  createMesh( relationships, geometryMap, materialMap ) {
1140
1072
 
1141
1073
  let model;
1142
1074
  let geometry = null;
1143
1075
  let material = null;
1144
- const materials = []; // get geometry and materials(s) from connections
1076
+ const materials = [];
1145
1077
 
1078
+ // get geometry and materials(s) from connections
1146
1079
  relationships.children.forEach( function ( child ) {
1147
1080
 
1148
1081
  if ( geometryMap.has( child.ID ) ) {
@@ -1158,7 +1091,6 @@
1158
1091
  }
1159
1092
 
1160
1093
  } );
1161
-
1162
1094
  if ( materials.length > 1 ) {
1163
1095
 
1164
1096
  material = materials;
@@ -1200,7 +1132,6 @@
1200
1132
  return model;
1201
1133
 
1202
1134
  }
1203
-
1204
1135
  createCurve( relationships, geometryMap ) {
1205
1136
 
1206
1137
  const geometry = relationships.children.reduce( function ( geo, child ) {
@@ -1208,17 +1139,18 @@
1208
1139
  if ( geometryMap.has( child.ID ) ) geo = geometryMap.get( child.ID );
1209
1140
  return geo;
1210
1141
 
1211
- }, null ); // FBX does not list materials for Nurbs lines, so we'll just put our own in here.
1142
+ }, null );
1212
1143
 
1144
+ // FBX does not list materials for Nurbs lines, so we'll just put our own in here.
1213
1145
  const material = new THREE.LineBasicMaterial( {
1214
1146
  color: 0x3300ff,
1215
1147
  linewidth: 1
1216
1148
  } );
1217
1149
  return new THREE.Line( geometry, material );
1218
1150
 
1219
- } // parse the model node for transform data
1220
-
1151
+ }
1221
1152
 
1153
+ // parse the model node for transform data
1222
1154
  getTransformData( model, modelNode ) {
1223
1155
 
1224
1156
  const transformData = {};
@@ -1236,7 +1168,6 @@
1236
1168
  model.userData.transformData = transformData;
1237
1169
 
1238
1170
  }
1239
-
1240
1171
  setLookAtProperties( model, modelNode ) {
1241
1172
 
1242
1173
  if ( 'LookAtProperty' in modelNode ) {
@@ -1247,11 +1178,11 @@
1247
1178
  if ( child.relationship === 'LookAtProperty' ) {
1248
1179
 
1249
1180
  const lookAtTarget = fbxTree.Objects.Model[ child.ID ];
1250
-
1251
1181
  if ( 'Lcl_Translation' in lookAtTarget ) {
1252
1182
 
1253
- const pos = lookAtTarget.Lcl_Translation.value; // THREE.DirectionalLight, THREE.SpotLight
1183
+ const pos = lookAtTarget.Lcl_Translation.value;
1254
1184
 
1185
+ // THREE.DirectionalLight, THREE.SpotLight
1255
1186
  if ( model.target !== undefined ) {
1256
1187
 
1257
1188
  model.target.position.fromArray( pos );
@@ -1260,6 +1191,7 @@
1260
1191
  } else {
1261
1192
 
1262
1193
  // Cameras and other Object3Ds
1194
+
1263
1195
  model.lookAt( new THREE.Vector3().fromArray( pos ) );
1264
1196
 
1265
1197
  }
@@ -1273,11 +1205,9 @@
1273
1205
  }
1274
1206
 
1275
1207
  }
1276
-
1277
1208
  bindSkeleton( skeletons, geometryMap, modelMap ) {
1278
1209
 
1279
1210
  const bindMatrices = this.parsePoseNodes();
1280
-
1281
1211
  for ( const ID in skeletons ) {
1282
1212
 
1283
1213
  const skeleton = skeletons[ ID ];
@@ -1306,21 +1236,17 @@
1306
1236
  }
1307
1237
 
1308
1238
  }
1309
-
1310
1239
  parsePoseNodes() {
1311
1240
 
1312
1241
  const bindMatrices = {};
1313
-
1314
1242
  if ( 'Pose' in fbxTree.Objects ) {
1315
1243
 
1316
1244
  const BindPoseNode = fbxTree.Objects.Pose;
1317
-
1318
1245
  for ( const nodeID in BindPoseNode ) {
1319
1246
 
1320
1247
  if ( BindPoseNode[ nodeID ].attrType === 'BindPose' && BindPoseNode[ nodeID ].NbPoseNodes > 0 ) {
1321
1248
 
1322
1249
  const poseNodes = BindPoseNode[ nodeID ].PoseNode;
1323
-
1324
1250
  if ( Array.isArray( poseNodes ) ) {
1325
1251
 
1326
1252
  poseNodes.forEach( function ( poseNode ) {
@@ -1343,9 +1269,9 @@
1343
1269
 
1344
1270
  return bindMatrices;
1345
1271
 
1346
- } // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light
1347
-
1272
+ }
1348
1273
 
1274
+ // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light
1349
1275
  createAmbientLight() {
1350
1276
 
1351
1277
  if ( 'GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings ) {
@@ -1354,7 +1280,6 @@
1354
1280
  const r = ambientColor[ 0 ];
1355
1281
  const g = ambientColor[ 1 ];
1356
1282
  const b = ambientColor[ 2 ];
1357
-
1358
1283
  if ( r !== 0 || g !== 0 || b !== 0 ) {
1359
1284
 
1360
1285
  const color = new THREE.Color( r, g, b );
@@ -1366,20 +1291,24 @@
1366
1291
 
1367
1292
  }
1368
1293
 
1369
- } // parse Geometry data from FBXTree and return map of BufferGeometries
1370
-
1294
+ }
1371
1295
 
1296
+ // parse Geometry data from FBXTree and return map of BufferGeometries
1372
1297
  class GeometryParser {
1373
1298
 
1299
+ constructor() {
1300
+
1301
+ this.negativeMaterialIndices = false;
1302
+
1303
+ }
1304
+
1374
1305
  // Parse nodes in FBXTree.Objects.Geometry
1375
1306
  parse( deformers ) {
1376
1307
 
1377
1308
  const geometryMap = new Map();
1378
-
1379
1309
  if ( 'Geometry' in fbxTree.Objects ) {
1380
1310
 
1381
1311
  const geoNodes = fbxTree.Objects.Geometry;
1382
-
1383
1312
  for ( const nodeID in geoNodes ) {
1384
1313
 
1385
1314
  const relationships = connections.get( parseInt( nodeID ) );
@@ -1390,11 +1319,19 @@
1390
1319
 
1391
1320
  }
1392
1321
 
1393
- return geometryMap;
1322
+ // report warnings
1323
+
1324
+ if ( this.negativeMaterialIndices === true ) {
1325
+
1326
+ console.warn( 'THREE.FBXLoader: The FBX file contains invalid (negative) material indices. The asset might not render as expected.' );
1327
+
1328
+ }
1394
1329
 
1395
- } // Parse single node in FBXTree.Objects.Geometry
1330
+ return geometryMap;
1396
1331
 
1332
+ }
1397
1333
 
1334
+ // Parse single node in FBXTree.Objects.Geometry
1398
1335
  parseGeometry( relationships, geoNode, deformers ) {
1399
1336
 
1400
1337
  switch ( geoNode.attrType ) {
@@ -1402,16 +1339,15 @@
1402
1339
  case 'Mesh':
1403
1340
  return this.parseMeshGeometry( relationships, geoNode, deformers );
1404
1341
  break;
1405
-
1406
1342
  case 'NurbsCurve':
1407
1343
  return this.parseNurbsGeometry( geoNode );
1408
1344
  break;
1409
1345
 
1410
1346
  }
1411
1347
 
1412
- } // Parse single node mesh geometry in FBXTree.Objects.Geometry
1413
-
1348
+ }
1414
1349
 
1350
+ // Parse single node mesh geometry in FBXTree.Objects.Geometry
1415
1351
  parseMeshGeometry( relationships, geoNode, deformers ) {
1416
1352
 
1417
1353
  const skeletons = deformers.skeletons;
@@ -1420,8 +1356,9 @@
1420
1356
 
1421
1357
  return fbxTree.Objects.Model[ parent.ID ];
1422
1358
 
1423
- } ); // don't create geometry if it is not associated with any models
1359
+ } );
1424
1360
 
1361
+ // don't create geometry if it is not associated with any models
1425
1362
  if ( modelNodes.length === 0 ) return;
1426
1363
  const skeleton = relationships.children.reduce( function ( skeleton, child ) {
1427
1364
 
@@ -1437,9 +1374,10 @@
1437
1374
 
1438
1375
  }
1439
1376
 
1440
- } ); // Assume one model and get the preRotation from that
1441
- // if there is more than one model associated with the geometry this may cause problems
1377
+ } );
1442
1378
 
1379
+ // Assume one model and get the preRotation from that
1380
+ // if there is more than one model associated with the geometry this may cause problems
1443
1381
  const modelNode = modelNodes[ 0 ];
1444
1382
  const transformData = {};
1445
1383
  if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value );
@@ -1450,9 +1388,9 @@
1450
1388
  const transform = generateTransform( transformData );
1451
1389
  return this.genGeometry( geoNode, skeleton, morphTargets, transform );
1452
1390
 
1453
- } // Generate a THREE.BufferGeometry from a node in FBXTree.Objects.Geometry
1454
-
1391
+ }
1455
1392
 
1393
+ // Generate a THREE.BufferGeometry from a node in FBXTree.Objects.Geometry
1456
1394
  genGeometry( geoNode, skeleton, morphTargets, preTransform ) {
1457
1395
 
1458
1396
  const geo = new THREE.BufferGeometry();
@@ -1462,7 +1400,6 @@
1462
1400
  const positionAttribute = new THREE.Float32BufferAttribute( buffers.vertex, 3 );
1463
1401
  positionAttribute.applyMatrix4( preTransform );
1464
1402
  geo.setAttribute( 'position', positionAttribute );
1465
-
1466
1403
  if ( buffers.colors.length > 0 ) {
1467
1404
 
1468
1405
  geo.setAttribute( 'color', new THREE.Float32BufferAttribute( buffers.colors, 3 ) );
@@ -1472,8 +1409,9 @@
1472
1409
  if ( skeleton ) {
1473
1410
 
1474
1411
  geo.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( buffers.weightsIndices, 4 ) );
1475
- geo.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( buffers.vertexWeights, 4 ) ); // used later to bind the skeleton to the model
1412
+ geo.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( buffers.vertexWeights, 4 ) );
1476
1413
 
1414
+ // used later to bind the skeleton to the model
1477
1415
  geo.FBX_Deformer = skeleton;
1478
1416
 
1479
1417
  }
@@ -1490,8 +1428,9 @@
1490
1428
  buffers.uvs.forEach( function ( uvBuffer, i ) {
1491
1429
 
1492
1430
  // subsequent uv buffers are called 'uv1', 'uv2', ...
1493
- let name = 'uv' + ( i + 1 ).toString(); // the first uv buffer is just called 'uv'
1431
+ let name = 'uv' + ( i + 1 ).toString();
1494
1432
 
1433
+ // the first uv buffer is just called 'uv'
1495
1434
  if ( i === 0 ) {
1496
1435
 
1497
1436
  name = 'uv';
@@ -1501,7 +1440,6 @@
1501
1440
  geo.setAttribute( name, new THREE.Float32BufferAttribute( buffers.uvs[ i ], 2 ) );
1502
1441
 
1503
1442
  } );
1504
-
1505
1443
  if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) {
1506
1444
 
1507
1445
  // Convert the material indices of each vertex into rendering groups on the geometry.
@@ -1517,23 +1455,23 @@
1517
1455
 
1518
1456
  }
1519
1457
 
1520
- } ); // the loop above doesn't add the last group, do that here.
1458
+ } );
1521
1459
 
1460
+ // the loop above doesn't add the last group, do that here.
1522
1461
  if ( geo.groups.length > 0 ) {
1523
1462
 
1524
1463
  const lastGroup = geo.groups[ geo.groups.length - 1 ];
1525
1464
  const lastIndex = lastGroup.start + lastGroup.count;
1526
-
1527
1465
  if ( lastIndex !== buffers.materialIndex.length ) {
1528
1466
 
1529
1467
  geo.addGroup( lastIndex, buffers.materialIndex.length - lastIndex, prevMaterialIndex );
1530
1468
 
1531
1469
  }
1532
1470
 
1533
- } // case where there are multiple materials but the whole geometry is only
1534
- // using one of them
1535
-
1471
+ }
1536
1472
 
1473
+ // case where there are multiple materials but the whole geometry is only
1474
+ // using one of them
1537
1475
  if ( geo.groups.length === 0 ) {
1538
1476
 
1539
1477
  geo.addGroup( 0, buffers.materialIndex.length, buffers.materialIndex[ 0 ] );
@@ -1546,13 +1484,11 @@
1546
1484
  return geo;
1547
1485
 
1548
1486
  }
1549
-
1550
1487
  parseGeoNode( geoNode, skeleton ) {
1551
1488
 
1552
1489
  const geoInfo = {};
1553
1490
  geoInfo.vertexPositions = geoNode.Vertices !== undefined ? geoNode.Vertices.a : [];
1554
1491
  geoInfo.vertexIndices = geoNode.PolygonVertexIndex !== undefined ? geoNode.PolygonVertexIndex.a : [];
1555
-
1556
1492
  if ( geoNode.LayerElementColor ) {
1557
1493
 
1558
1494
  geoInfo.color = this.parseVertexColors( geoNode.LayerElementColor[ 0 ] );
@@ -1575,7 +1511,6 @@
1575
1511
 
1576
1512
  geoInfo.uv = [];
1577
1513
  let i = 0;
1578
-
1579
1514
  while ( geoNode.LayerElementUV[ i ] ) {
1580
1515
 
1581
1516
  if ( geoNode.LayerElementUV[ i ].UV ) {
@@ -1591,7 +1526,6 @@
1591
1526
  }
1592
1527
 
1593
1528
  geoInfo.weightTable = {};
1594
-
1595
1529
  if ( skeleton !== null ) {
1596
1530
 
1597
1531
  geoInfo.skeleton = skeleton;
@@ -1615,7 +1549,6 @@
1615
1549
  return geoInfo;
1616
1550
 
1617
1551
  }
1618
-
1619
1552
  genBuffers( geoInfo ) {
1620
1553
 
1621
1554
  const buffers = {
@@ -1629,8 +1562,9 @@
1629
1562
  };
1630
1563
  let polygonIndex = 0;
1631
1564
  let faceLength = 0;
1632
- let displayedWeightsWarning = false; // these will hold data for a single face
1565
+ let displayedWeightsWarning = false;
1633
1566
 
1567
+ // these will hold data for a single face
1634
1568
  let facePositionIndexes = [];
1635
1569
  let faceNormals = [];
1636
1570
  let faceColors = [];
@@ -1641,18 +1575,18 @@
1641
1575
  geoInfo.vertexIndices.forEach( function ( vertexIndex, polygonVertexIndex ) {
1642
1576
 
1643
1577
  let materialIndex;
1644
- let endOfFace = false; // Face index and vertex index arrays are combined in a single array
1578
+ let endOfFace = false;
1579
+
1580
+ // Face index and vertex index arrays are combined in a single array
1645
1581
  // A cube with quad faces looks like this:
1646
1582
  // PolygonVertexIndex: *24 {
1647
1583
  // a: 0, 1, 3, -3, 2, 3, 5, -5, 4, 5, 7, -7, 6, 7, 1, -1, 1, 7, 5, -4, 6, 0, 2, -5
1648
1584
  // }
1649
1585
  // Negative numbers mark the end of a face - first face here is 0, 1, 3, -3
1650
1586
  // to find index of last vertex bit shift the index: ^ - 1
1651
-
1652
1587
  if ( vertexIndex < 0 ) {
1653
1588
 
1654
1589
  vertexIndex = vertexIndex ^ - 1; // equivalent to ( x * -1 ) - 1
1655
-
1656
1590
  endOfFace = true;
1657
1591
 
1658
1592
  }
@@ -1660,7 +1594,6 @@
1660
1594
  let weightIndices = [];
1661
1595
  let weights = [];
1662
1596
  facePositionIndexes.push( vertexIndex * 3, vertexIndex * 3 + 1, vertexIndex * 3 + 2 );
1663
-
1664
1597
  if ( geoInfo.color ) {
1665
1598
 
1666
1599
  const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.color );
@@ -1714,9 +1647,9 @@
1714
1647
  weightIndices = wIndex;
1715
1648
  weights = Weight;
1716
1649
 
1717
- } // if the weight array is shorter than 4 pad with 0s
1718
-
1650
+ }
1719
1651
 
1652
+ // if the weight array is shorter than 4 pad with 0s
1720
1653
  while ( weights.length < 4 ) {
1721
1654
 
1722
1655
  weights.push( 0 );
@@ -1743,6 +1676,12 @@
1743
1676
  if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) {
1744
1677
 
1745
1678
  materialIndex = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material )[ 0 ];
1679
+ if ( materialIndex < 0 ) {
1680
+
1681
+ scope.negativeMaterialIndices = true;
1682
+ materialIndex = 0; // fallback
1683
+
1684
+ }
1746
1685
 
1747
1686
  }
1748
1687
 
@@ -1751,7 +1690,6 @@
1751
1690
  geoInfo.uv.forEach( function ( uv, i ) {
1752
1691
 
1753
1692
  const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, uv );
1754
-
1755
1693
  if ( faceUVs[ i ] === undefined ) {
1756
1694
 
1757
1695
  faceUVs[ i ] = [];
@@ -1766,13 +1704,14 @@
1766
1704
  }
1767
1705
 
1768
1706
  faceLength ++;
1769
-
1770
1707
  if ( endOfFace ) {
1771
1708
 
1709
+ if ( faceLength > 4 ) console.warn( 'THREE.FBXLoader: Polygons with more than four sides are not supported. Make sure to triangulate the geometry during export.' );
1772
1710
  scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength );
1773
1711
  polygonIndex ++;
1774
- faceLength = 0; // reset arrays for the next face
1712
+ faceLength = 0;
1775
1713
 
1714
+ // reset arrays for the next face
1776
1715
  facePositionIndexes = [];
1777
1716
  faceNormals = [];
1778
1717
  faceColors = [];
@@ -1785,9 +1724,9 @@
1785
1724
  } );
1786
1725
  return buffers;
1787
1726
 
1788
- } // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
1789
-
1727
+ }
1790
1728
 
1729
+ // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
1791
1730
  genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) {
1792
1731
 
1793
1732
  for ( let i = 2; i < faceLength; i ++ ) {
@@ -1801,7 +1740,6 @@
1801
1740
  buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 ] ] );
1802
1741
  buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 1 ] ] );
1803
1742
  buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 2 ] ] );
1804
-
1805
1743
  if ( geoInfo.skeleton ) {
1806
1744
 
1807
1745
  buffers.vertexWeights.push( faceWeights[ 0 ] );
@@ -1886,12 +1824,12 @@
1886
1824
  }
1887
1825
 
1888
1826
  }
1889
-
1890
1827
  addMorphTargets( parentGeo, parentGeoNode, morphTargets, preTransform ) {
1891
1828
 
1892
1829
  if ( morphTargets.length === 0 ) return;
1893
1830
  parentGeo.morphTargetsRelative = true;
1894
- parentGeo.morphAttributes.position = []; // parentGeo.morphAttributes.normal = []; // not implemented
1831
+ parentGeo.morphAttributes.position = [];
1832
+ // parentGeo.morphAttributes.normal = []; // not implemented
1895
1833
 
1896
1834
  const scope = this;
1897
1835
  morphTargets.forEach( function ( morphTarget ) {
@@ -1899,7 +1837,6 @@
1899
1837
  morphTarget.rawTargets.forEach( function ( rawTarget ) {
1900
1838
 
1901
1839
  const morphGeoNode = fbxTree.Objects.Geometry[ rawTarget.geoID ];
1902
-
1903
1840
  if ( morphGeoNode !== undefined ) {
1904
1841
 
1905
1842
  scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name );
@@ -1910,12 +1847,12 @@
1910
1847
 
1911
1848
  } );
1912
1849
 
1913
- } // a morph geometry node is similar to a standard node, and the node is also contained
1850
+ }
1851
+
1852
+ // a morph geometry node is similar to a standard node, and the node is also contained
1914
1853
  // in FBXTree.Objects.Geometry, however it can only have attributes for position, normal
1915
1854
  // and a special attribute Index defining which vertices of the original geometry are affected
1916
1855
  // Normal and position attributes only have data for the vertices that are affected by the morph
1917
-
1918
-
1919
1856
  genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, name ) {
1920
1857
 
1921
1858
  const vertexIndices = parentGeoNode.PolygonVertexIndex !== undefined ? parentGeoNode.PolygonVertexIndex.a : [];
@@ -1923,7 +1860,6 @@
1923
1860
  const indices = morphGeoNode.Indexes !== undefined ? morphGeoNode.Indexes.a : [];
1924
1861
  const length = parentGeo.attributes.position.count * 3;
1925
1862
  const morphPositions = new Float32Array( length );
1926
-
1927
1863
  for ( let i = 0; i < indices.length; i ++ ) {
1928
1864
 
1929
1865
  const morphIndex = indices[ i ] * 3;
@@ -1931,9 +1867,9 @@
1931
1867
  morphPositions[ morphIndex + 1 ] = morphPositionsSparse[ i * 3 + 1 ];
1932
1868
  morphPositions[ morphIndex + 2 ] = morphPositionsSparse[ i * 3 + 2 ];
1933
1869
 
1934
- } // TODO: add morph normal support
1935
-
1870
+ }
1936
1871
 
1872
+ // TODO: add morph normal support
1937
1873
  const morphGeoInfo = {
1938
1874
  vertexIndices: vertexIndices,
1939
1875
  vertexPositions: morphPositions
@@ -1944,16 +1880,15 @@
1944
1880
  positionAttribute.applyMatrix4( preTransform );
1945
1881
  parentGeo.morphAttributes.position.push( positionAttribute );
1946
1882
 
1947
- } // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists
1948
-
1883
+ }
1949
1884
 
1885
+ // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists
1950
1886
  parseNormals( NormalNode ) {
1951
1887
 
1952
1888
  const mappingType = NormalNode.MappingInformationType;
1953
1889
  const referenceType = NormalNode.ReferenceInformationType;
1954
1890
  const buffer = NormalNode.Normals.a;
1955
1891
  let indexBuffer = [];
1956
-
1957
1892
  if ( referenceType === 'IndexToDirect' ) {
1958
1893
 
1959
1894
  if ( 'NormalIndex' in NormalNode ) {
@@ -1976,16 +1911,15 @@
1976
1911
  referenceType: referenceType
1977
1912
  };
1978
1913
 
1979
- } // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists
1980
-
1914
+ }
1981
1915
 
1916
+ // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists
1982
1917
  parseUVs( UVNode ) {
1983
1918
 
1984
1919
  const mappingType = UVNode.MappingInformationType;
1985
1920
  const referenceType = UVNode.ReferenceInformationType;
1986
1921
  const buffer = UVNode.UV.a;
1987
1922
  let indexBuffer = [];
1988
-
1989
1923
  if ( referenceType === 'IndexToDirect' ) {
1990
1924
 
1991
1925
  indexBuffer = UVNode.UVIndex.a;
@@ -2000,16 +1934,15 @@
2000
1934
  referenceType: referenceType
2001
1935
  };
2002
1936
 
2003
- } // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists
2004
-
1937
+ }
2005
1938
 
1939
+ // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists
2006
1940
  parseVertexColors( ColorNode ) {
2007
1941
 
2008
1942
  const mappingType = ColorNode.MappingInformationType;
2009
1943
  const referenceType = ColorNode.ReferenceInformationType;
2010
1944
  const buffer = ColorNode.Colors.a;
2011
1945
  let indexBuffer = [];
2012
-
2013
1946
  if ( referenceType === 'IndexToDirect' ) {
2014
1947
 
2015
1948
  indexBuffer = ColorNode.ColorIndex.a;
@@ -2024,14 +1957,13 @@
2024
1957
  referenceType: referenceType
2025
1958
  };
2026
1959
 
2027
- } // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists
2028
-
1960
+ }
2029
1961
 
1962
+ // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists
2030
1963
  parseMaterialIndices( MaterialNode ) {
2031
1964
 
2032
1965
  const mappingType = MaterialNode.MappingInformationType;
2033
1966
  const referenceType = MaterialNode.ReferenceInformationType;
2034
-
2035
1967
  if ( mappingType === 'NoMappingInformation' ) {
2036
1968
 
2037
1969
  return {
@@ -2044,12 +1976,12 @@
2044
1976
 
2045
1977
  }
2046
1978
 
2047
- const materialIndexBuffer = MaterialNode.Materials.a; // Since materials are stored as indices, there's a bit of a mismatch between FBX and what
1979
+ const materialIndexBuffer = MaterialNode.Materials.a;
1980
+
1981
+ // Since materials are stored as indices, there's a bit of a mismatch between FBX and what
2048
1982
  // we expect.So we create an intermediate buffer that points to the index in the buffer,
2049
1983
  // for conforming with the other functions we've written for other data.
2050
-
2051
1984
  const materialIndices = [];
2052
-
2053
1985
  for ( let i = 0; i < materialIndexBuffer.length; ++ i ) {
2054
1986
 
2055
1987
  materialIndices.push( i );
@@ -2064,9 +1996,9 @@
2064
1996
  referenceType: referenceType
2065
1997
  };
2066
1998
 
2067
- } // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry
2068
-
1999
+ }
2069
2000
 
2001
+ // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry
2070
2002
  parseNurbsGeometry( geoNode ) {
2071
2003
 
2072
2004
  if ( THREE.NURBSCurve === undefined ) {
@@ -2077,7 +2009,6 @@
2077
2009
  }
2078
2010
 
2079
2011
  const order = parseInt( geoNode.Order );
2080
-
2081
2012
  if ( isNaN( order ) ) {
2082
2013
 
2083
2014
  console.error( 'THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geoNode.Order, geoNode.id );
@@ -2089,7 +2020,6 @@
2089
2020
  const knots = geoNode.KnotVector.a;
2090
2021
  const controlPoints = [];
2091
2022
  const pointsValues = geoNode.Points.a;
2092
-
2093
2023
  for ( let i = 0, l = pointsValues.length; i < l; i += 4 ) {
2094
2024
 
2095
2025
  controlPoints.push( new THREE.Vector4().fromArray( pointsValues, i ) );
@@ -2097,7 +2027,6 @@
2097
2027
  }
2098
2028
 
2099
2029
  let startKnot, endKnot;
2100
-
2101
2030
  if ( geoNode.Form === 'Closed' ) {
2102
2031
 
2103
2032
  controlPoints.push( controlPoints[ 0 ] );
@@ -2106,7 +2035,6 @@
2106
2035
 
2107
2036
  startKnot = degree;
2108
2037
  endKnot = knots.length - 1 - startKnot;
2109
-
2110
2038
  for ( let i = 0; i < degree; ++ i ) {
2111
2039
 
2112
2040
  controlPoints.push( controlPoints[ i ] );
@@ -2121,9 +2049,9 @@
2121
2049
 
2122
2050
  }
2123
2051
 
2124
- } // parse animation data from FBXTree
2125
-
2052
+ }
2126
2053
 
2054
+ // parse animation data from FBXTree
2127
2055
  class AnimationParser {
2128
2056
 
2129
2057
  // take raw animation clips and turn them into three.js animation clips
@@ -2131,7 +2059,6 @@
2131
2059
 
2132
2060
  const animationClips = [];
2133
2061
  const rawClips = this.parseClips();
2134
-
2135
2062
  if ( rawClips !== undefined ) {
2136
2063
 
2137
2064
  for ( const key in rawClips ) {
@@ -2147,7 +2074,6 @@
2147
2074
  return animationClips;
2148
2075
 
2149
2076
  }
2150
-
2151
2077
  parseClips() {
2152
2078
 
2153
2079
  // since the actual transformation data is stored in FBXTree.Objects.AnimationCurve,
@@ -2159,20 +2085,18 @@
2159
2085
  const rawClips = this.parseAnimStacks( layersMap );
2160
2086
  return rawClips;
2161
2087
 
2162
- } // parse nodes in FBXTree.Objects.AnimationCurveNode
2088
+ }
2089
+
2090
+ // parse nodes in FBXTree.Objects.AnimationCurveNode
2163
2091
  // each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation )
2164
2092
  // and is referenced by an AnimationLayer
2165
-
2166
-
2167
2093
  parseAnimationCurveNodes() {
2168
2094
 
2169
2095
  const rawCurveNodes = fbxTree.Objects.AnimationCurveNode;
2170
2096
  const curveNodesMap = new Map();
2171
-
2172
2097
  for ( const nodeID in rawCurveNodes ) {
2173
2098
 
2174
2099
  const rawCurveNode = rawCurveNodes[ nodeID ];
2175
-
2176
2100
  if ( rawCurveNode.attrName.match( /S|R|T|DeformPercent/ ) !== null ) {
2177
2101
 
2178
2102
  const curveNode = {
@@ -2188,14 +2112,16 @@
2188
2112
 
2189
2113
  return curveNodesMap;
2190
2114
 
2191
- } // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to
2115
+ }
2116
+
2117
+ // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to
2192
2118
  // previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated
2193
2119
  // axis ( e.g. times and values of x rotation)
2194
-
2195
-
2196
2120
  parseAnimationCurves( curveNodesMap ) {
2197
2121
 
2198
- const rawCurves = fbxTree.Objects.AnimationCurve; // TODO: Many values are identical up to roundoff error, but won't be optimised
2122
+ const rawCurves = fbxTree.Objects.AnimationCurve;
2123
+
2124
+ // TODO: Many values are identical up to roundoff error, but won't be optimised
2199
2125
  // e.g. position times: [0, 0.4, 0. 8]
2200
2126
  // position values: [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.235384487103147e-7, 93.67520904541016, -0.9982695579528809]
2201
2127
  // clearly, this should be optimised to
@@ -2210,12 +2136,10 @@
2210
2136
  values: rawCurves[ nodeID ].KeyValueFloat.a
2211
2137
  };
2212
2138
  const relationships = connections.get( animationCurve.id );
2213
-
2214
2139
  if ( relationships !== undefined ) {
2215
2140
 
2216
2141
  const animationCurveID = relationships.parents[ 0 ].ID;
2217
2142
  const animationCurveRelationship = relationships.parents[ 0 ].relationship;
2218
-
2219
2143
  if ( animationCurveRelationship.match( /X/ ) ) {
2220
2144
 
2221
2145
  curveNodesMap.get( animationCurveID ).curves[ 'x' ] = animationCurve;
@@ -2238,21 +2162,19 @@
2238
2162
 
2239
2163
  }
2240
2164
 
2241
- } // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references
2165
+ }
2166
+
2167
+ // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references
2242
2168
  // to various AnimationCurveNodes and is referenced by an AnimationStack node
2243
2169
  // note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack
2244
-
2245
-
2246
2170
  parseAnimationLayers( curveNodesMap ) {
2247
2171
 
2248
2172
  const rawLayers = fbxTree.Objects.AnimationLayer;
2249
2173
  const layersMap = new Map();
2250
-
2251
2174
  for ( const nodeID in rawLayers ) {
2252
2175
 
2253
2176
  const layerCurveNodes = [];
2254
2177
  const connection = connections.get( parseInt( nodeID ) );
2255
-
2256
2178
  if ( connection !== undefined ) {
2257
2179
 
2258
2180
  // all the animationCurveNodes used in the layer
@@ -2261,8 +2183,9 @@
2261
2183
 
2262
2184
  if ( curveNodesMap.has( child.ID ) ) {
2263
2185
 
2264
- const curveNode = curveNodesMap.get( child.ID ); // check that the curves are defined for at least one axis, otherwise ignore the curveNode
2186
+ const curveNode = curveNodesMap.get( child.ID );
2265
2187
 
2188
+ // check that the curves are defined for at least one axis, otherwise ignore the curveNode
2266
2189
  if ( curveNode.curves.x !== undefined || curveNode.curves.y !== undefined || curveNode.curves.z !== undefined ) {
2267
2190
 
2268
2191
  if ( layerCurveNodes[ i ] === undefined ) {
@@ -2272,11 +2195,9 @@
2272
2195
  return parent.relationship !== undefined;
2273
2196
 
2274
2197
  } )[ 0 ].ID;
2275
-
2276
2198
  if ( modelID !== undefined ) {
2277
2199
 
2278
2200
  const rawModel = fbxTree.Objects.Model[ modelID.toString() ];
2279
-
2280
2201
  if ( rawModel === undefined ) {
2281
2202
 
2282
2203
  console.warn( 'THREE.FBXLoader: Encountered a unused curve.', child );
@@ -2301,9 +2222,10 @@
2301
2222
  }
2302
2223
 
2303
2224
  } );
2304
- if ( ! node.transform ) node.transform = new THREE.Matrix4(); // if the animated model is pre rotated, we'll have to apply the pre rotations to every
2305
- // animation value as well
2225
+ if ( ! node.transform ) node.transform = new THREE.Matrix4();
2306
2226
 
2227
+ // if the animated model is pre rotated, we'll have to apply the pre rotations to every
2228
+ // animation value as well
2307
2229
  if ( 'PreRotation' in rawModel ) node.preRotation = rawModel.PreRotation.value;
2308
2230
  if ( 'PostRotation' in rawModel ) node.postRotation = rawModel.PostRotation.value;
2309
2231
  layerCurveNodes[ i ] = node;
@@ -2324,8 +2246,9 @@
2324
2246
 
2325
2247
  } )[ 0 ].ID;
2326
2248
  const morpherID = connections.get( deformerID ).parents[ 0 ].ID;
2327
- const geoID = connections.get( morpherID ).parents[ 0 ].ID; // assuming geometry is not used in more than one model
2249
+ const geoID = connections.get( morpherID ).parents[ 0 ].ID;
2328
2250
 
2251
+ // assuming geometry is not used in more than one model
2329
2252
  const modelID = connections.get( geoID ).parents[ 0 ].ID;
2330
2253
  const rawModel = fbxTree.Objects.Model[ modelID ];
2331
2254
  const node = {
@@ -2351,20 +2274,19 @@
2351
2274
 
2352
2275
  return layersMap;
2353
2276
 
2354
- } // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation
2355
- // hierarchy. Each Stack node will be used to create a THREE.AnimationClip
2356
-
2277
+ }
2357
2278
 
2279
+ // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation
2280
+ // hierarchy. Each Stack node will be used to create a THREE.AnimationClip
2358
2281
  parseAnimStacks( layersMap ) {
2359
2282
 
2360
- const rawStacks = fbxTree.Objects.AnimationStack; // connect the stacks (clips) up to the layers
2283
+ const rawStacks = fbxTree.Objects.AnimationStack;
2361
2284
 
2285
+ // connect the stacks (clips) up to the layers
2362
2286
  const rawClips = {};
2363
-
2364
2287
  for ( const nodeID in rawStacks ) {
2365
2288
 
2366
2289
  const children = connections.get( parseInt( nodeID ) ).children;
2367
-
2368
2290
  if ( children.length > 1 ) {
2369
2291
 
2370
2292
  // it seems like stacks will always be associated with a single layer. But just in case there are files
@@ -2384,7 +2306,6 @@
2384
2306
  return rawClips;
2385
2307
 
2386
2308
  }
2387
-
2388
2309
  addClip( rawClip ) {
2389
2310
 
2390
2311
  let tracks = [];
@@ -2397,7 +2318,6 @@
2397
2318
  return new THREE.AnimationClip( rawClip.name, - 1, tracks );
2398
2319
 
2399
2320
  }
2400
-
2401
2321
  generateTracks( rawTracks ) {
2402
2322
 
2403
2323
  const tracks = [];
@@ -2408,7 +2328,6 @@
2408
2328
  initialPosition = initialPosition.toArray();
2409
2329
  initialRotation = new THREE.Euler().setFromQuaternion( initialRotation, rawTracks.eulerOrder ).toArray();
2410
2330
  initialScale = initialScale.toArray();
2411
-
2412
2331
  if ( rawTracks.T !== undefined && Object.keys( rawTracks.T.curves ).length > 0 ) {
2413
2332
 
2414
2333
  const positionTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.T.curves, initialPosition, 'position' );
@@ -2440,7 +2359,6 @@
2440
2359
  return tracks;
2441
2360
 
2442
2361
  }
2443
-
2444
2362
  generateVectorTrack( modelName, curves, initialValue, type ) {
2445
2363
 
2446
2364
  const times = this.getTimesForAllAxes( curves );
@@ -2448,7 +2366,6 @@
2448
2366
  return new THREE.VectorKeyframeTrack( modelName + '.' + type, times, values );
2449
2367
 
2450
2368
  }
2451
-
2452
2369
  generateRotationTrack( modelName, curves, initialValue, preRotation, postRotation, eulerOrder ) {
2453
2370
 
2454
2371
  if ( curves.x !== undefined ) {
@@ -2474,7 +2391,6 @@
2474
2391
 
2475
2392
  const times = this.getTimesForAllAxes( curves );
2476
2393
  const values = this.getKeyframeTrackValues( times, curves, initialValue );
2477
-
2478
2394
  if ( preRotation !== undefined ) {
2479
2395
 
2480
2396
  preRotation = preRotation.map( THREE.MathUtils.degToRad );
@@ -2496,7 +2412,6 @@
2496
2412
  const quaternion = new THREE.Quaternion();
2497
2413
  const euler = new THREE.Euler();
2498
2414
  const quaternionValues = [];
2499
-
2500
2415
  for ( let i = 0; i < values.length; i += 3 ) {
2501
2416
 
2502
2417
  euler.set( values[ i ], values[ i + 1 ], values[ i + 2 ], eulerOrder );
@@ -2510,7 +2425,6 @@
2510
2425
  return new THREE.QuaternionKeyframeTrack( modelName + '.quaternion', times, quaternionValues );
2511
2426
 
2512
2427
  }
2513
-
2514
2428
  generateMorphTrack( rawTracks ) {
2515
2429
 
2516
2430
  const curves = rawTracks.DeformPercent.curves.morph;
@@ -2522,33 +2436,34 @@
2522
2436
  const morphNum = sceneGraph.getObjectByName( rawTracks.modelName ).morphTargetDictionary[ rawTracks.morphName ];
2523
2437
  return new THREE.NumberKeyframeTrack( rawTracks.modelName + '.morphTargetInfluences[' + morphNum + ']', curves.times, values );
2524
2438
 
2525
- } // For all animated objects, times are defined separately for each axis
2526
- // Here we'll combine the times into one sorted array without duplicates
2527
-
2439
+ }
2528
2440
 
2441
+ // For all animated objects, times are defined separately for each axis
2442
+ // Here we'll combine the times into one sorted array without duplicates
2529
2443
  getTimesForAllAxes( curves ) {
2530
2444
 
2531
- let times = []; // first join together the times for each axis, if defined
2445
+ let times = [];
2532
2446
 
2447
+ // first join together the times for each axis, if defined
2533
2448
  if ( curves.x !== undefined ) times = times.concat( curves.x.times );
2534
2449
  if ( curves.y !== undefined ) times = times.concat( curves.y.times );
2535
- if ( curves.z !== undefined ) times = times.concat( curves.z.times ); // then sort them
2450
+ if ( curves.z !== undefined ) times = times.concat( curves.z.times );
2536
2451
 
2452
+ // then sort them
2537
2453
  times = times.sort( function ( a, b ) {
2538
2454
 
2539
2455
  return a - b;
2540
2456
 
2541
- } ); // and remove duplicates
2457
+ } );
2542
2458
 
2459
+ // and remove duplicates
2543
2460
  if ( times.length > 1 ) {
2544
2461
 
2545
2462
  let targetIndex = 1;
2546
2463
  let lastValue = times[ 0 ];
2547
-
2548
2464
  for ( let i = 1; i < times.length; i ++ ) {
2549
2465
 
2550
2466
  const currentValue = times[ i ];
2551
-
2552
2467
  if ( currentValue !== lastValue ) {
2553
2468
 
2554
2469
  times[ targetIndex ] = currentValue;
@@ -2566,7 +2481,6 @@
2566
2481
  return times;
2567
2482
 
2568
2483
  }
2569
-
2570
2484
  getKeyframeTrackValues( times, curves, initialValue ) {
2571
2485
 
2572
2486
  const prevValue = initialValue;
@@ -2578,8 +2492,9 @@
2578
2492
 
2579
2493
  if ( curves.x ) xIndex = curves.x.times.indexOf( time );
2580
2494
  if ( curves.y ) yIndex = curves.y.times.indexOf( time );
2581
- if ( curves.z ) zIndex = curves.z.times.indexOf( time ); // if there is an x value defined for this frame, use that
2495
+ if ( curves.z ) zIndex = curves.z.times.indexOf( time );
2582
2496
 
2497
+ // if there is an x value defined for this frame, use that
2583
2498
  if ( xIndex !== - 1 ) {
2584
2499
 
2585
2500
  const xValue = curves.x.values[ xIndex ];
@@ -2620,11 +2535,11 @@
2620
2535
  } );
2621
2536
  return values;
2622
2537
 
2623
- } // Rotations are defined as THREE.Euler angles which can have values of any size
2538
+ }
2539
+
2540
+ // Rotations are defined as THREE.Euler angles which can have values of any size
2624
2541
  // These will be converted to quaternions which don't support values greater than
2625
2542
  // PI, so we'll interpolate large rotations
2626
-
2627
-
2628
2543
  interpolateRotations( curve ) {
2629
2544
 
2630
2545
  for ( let i = 1; i < curve.values.length; i ++ ) {
@@ -2632,7 +2547,6 @@
2632
2547
  const initialValue = curve.values[ i - 1 ];
2633
2548
  const valuesSpan = curve.values[ i ] - initialValue;
2634
2549
  const absoluteSpan = Math.abs( valuesSpan );
2635
-
2636
2550
  if ( absoluteSpan >= 180 ) {
2637
2551
 
2638
2552
  const numSubIntervals = absoluteSpan / 180;
@@ -2644,7 +2558,6 @@
2644
2558
  let nextTime = initialTime + interval;
2645
2559
  const interpolatedTimes = [];
2646
2560
  const interpolatedValues = [];
2647
-
2648
2561
  while ( nextTime < curve.times[ i ] ) {
2649
2562
 
2650
2563
  interpolatedTimes.push( nextTime );
@@ -2663,9 +2576,9 @@
2663
2576
 
2664
2577
  }
2665
2578
 
2666
- } // parse an FBX file in ASCII format
2667
-
2579
+ }
2668
2580
 
2581
+ // parse an FBX file in ASCII format
2669
2582
  class TextParser {
2670
2583
 
2671
2584
  getPrevNode() {
@@ -2673,40 +2586,34 @@
2673
2586
  return this.nodeStack[ this.currentIndent - 2 ];
2674
2587
 
2675
2588
  }
2676
-
2677
2589
  getCurrentNode() {
2678
2590
 
2679
2591
  return this.nodeStack[ this.currentIndent - 1 ];
2680
2592
 
2681
2593
  }
2682
-
2683
2594
  getCurrentProp() {
2684
2595
 
2685
2596
  return this.currentProp;
2686
2597
 
2687
2598
  }
2688
-
2689
2599
  pushStack( node ) {
2690
2600
 
2691
2601
  this.nodeStack.push( node );
2692
2602
  this.currentIndent += 1;
2693
2603
 
2694
2604
  }
2695
-
2696
2605
  popStack() {
2697
2606
 
2698
2607
  this.nodeStack.pop();
2699
2608
  this.currentIndent -= 1;
2700
2609
 
2701
2610
  }
2702
-
2703
2611
  setCurrentProp( val, name ) {
2704
2612
 
2705
2613
  this.currentProp = val;
2706
2614
  this.currentPropName = name;
2707
2615
 
2708
2616
  }
2709
-
2710
2617
  parse( text ) {
2711
2618
 
2712
2619
  this.currentIndent = 0;
@@ -2724,7 +2631,6 @@
2724
2631
  const matchBeginning = line.match( '^\\t{' + scope.currentIndent + '}(\\w+):(.*){', '' );
2725
2632
  const matchProperty = line.match( '^\\t{' + scope.currentIndent + '}(\\w+):[\\s\\t\\r\\n](.*)' );
2726
2633
  const matchEnd = line.match( '^\\t{' + ( scope.currentIndent - 1 ) + '}}' );
2727
-
2728
2634
  if ( matchBeginning ) {
2729
2635
 
2730
2636
  scope.parseNodeBegin( line, matchBeginning );
@@ -2749,7 +2655,6 @@
2749
2655
  return this.allNodes;
2750
2656
 
2751
2657
  }
2752
-
2753
2658
  parseNodeBegin( line, property ) {
2754
2659
 
2755
2660
  const nodeName = property[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' );
@@ -2762,8 +2667,9 @@
2762
2667
  name: nodeName
2763
2668
  };
2764
2669
  const attrs = this.parseNodeAttr( nodeAttrs );
2765
- const currentNode = this.getCurrentNode(); // a top node
2670
+ const currentNode = this.getCurrentNode();
2766
2671
 
2672
+ // a top node
2767
2673
  if ( this.currentIndent === 0 ) {
2768
2674
 
2769
2675
  this.allNodes.add( nodeName, node );
@@ -2771,6 +2677,7 @@
2771
2677
  } else {
2772
2678
 
2773
2679
  // a subnode
2680
+
2774
2681
  // if the subnode already exists, append it
2775
2682
  if ( nodeName in currentNode ) {
2776
2683
 
@@ -2807,15 +2714,12 @@
2807
2714
  this.pushStack( node );
2808
2715
 
2809
2716
  }
2810
-
2811
2717
  parseNodeAttr( attrs ) {
2812
2718
 
2813
2719
  let id = attrs[ 0 ];
2814
-
2815
2720
  if ( attrs[ 0 ] !== '' ) {
2816
2721
 
2817
2722
  id = parseInt( attrs[ 0 ] );
2818
-
2819
2723
  if ( isNaN( id ) ) {
2820
2724
 
2821
2725
  id = attrs[ 0 ];
@@ -2826,7 +2730,6 @@
2826
2730
 
2827
2731
  let name = '',
2828
2732
  type = '';
2829
-
2830
2733
  if ( attrs.length > 1 ) {
2831
2734
 
2832
2735
  name = attrs[ 1 ].replace( /^(\w+)::/, '' );
@@ -2841,14 +2744,14 @@
2841
2744
  };
2842
2745
 
2843
2746
  }
2844
-
2845
2747
  parseNodeProperty( line, property, contentLine ) {
2846
2748
 
2847
2749
  let propName = property[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
2848
- let propValue = property[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim(); // for special case: base64 image data follows "Content: ," line
2750
+ let propValue = property[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
2751
+
2752
+ // for special case: base64 image data follows "Content: ," line
2849
2753
  // Content: ,
2850
2754
  // "/9j/4RDaRXhpZgAATU0A..."
2851
-
2852
2755
  if ( propName === 'Content' && propValue === ',' ) {
2853
2756
 
2854
2757
  propValue = contentLine.replace( /"/g, '' ).replace( /,$/, '' ).trim();
@@ -2857,15 +2760,14 @@
2857
2760
 
2858
2761
  const currentNode = this.getCurrentNode();
2859
2762
  const parentName = currentNode.name;
2860
-
2861
2763
  if ( parentName === 'Properties70' ) {
2862
2764
 
2863
2765
  this.parseNodeSpecialProperty( line, propName, propValue );
2864
2766
  return;
2865
2767
 
2866
- } // Connections
2867
-
2768
+ }
2868
2769
 
2770
+ // Connections
2869
2771
  if ( propName === 'C' ) {
2870
2772
 
2871
2773
  const connProps = propValue.split( ',' ).slice( 1 );
@@ -2880,18 +2782,18 @@
2880
2782
  propName = 'connections';
2881
2783
  propValue = [ from, to ];
2882
2784
  append( propValue, rest );
2883
-
2884
2785
  if ( currentNode[ propName ] === undefined ) {
2885
2786
 
2886
2787
  currentNode[ propName ] = [];
2887
2788
 
2888
2789
  }
2889
2790
 
2890
- } // Node
2891
-
2791
+ }
2892
2792
 
2893
- if ( propName === 'Node' ) currentNode.id = propValue; // connections
2793
+ // Node
2794
+ if ( propName === 'Node' ) currentNode.id = propValue;
2894
2795
 
2796
+ // connections
2895
2797
  if ( propName in currentNode && Array.isArray( currentNode[ propName ] ) ) {
2896
2798
 
2897
2799
  currentNode[ propName ].push( propValue );
@@ -2902,8 +2804,9 @@
2902
2804
 
2903
2805
  }
2904
2806
 
2905
- this.setCurrentProp( currentNode, propName ); // convert string to array, unless it ends in ',' in which case more will be added to it
2807
+ this.setCurrentProp( currentNode, propName );
2906
2808
 
2809
+ // convert string to array, unless it ends in ',' in which case more will be added to it
2907
2810
  if ( propName === 'a' && propValue.slice( - 1 ) !== ',' ) {
2908
2811
 
2909
2812
  currentNode.a = parseNumberArray( propValue );
@@ -2911,22 +2814,22 @@
2911
2814
  }
2912
2815
 
2913
2816
  }
2914
-
2915
2817
  parseNodePropertyContinued( line ) {
2916
2818
 
2917
2819
  const currentNode = this.getCurrentNode();
2918
- currentNode.a += line; // if the line doesn't end in ',' we have reached the end of the property value
2919
- // so convert the string to an array
2820
+ currentNode.a += line;
2920
2821
 
2822
+ // if the line doesn't end in ',' we have reached the end of the property value
2823
+ // so convert the string to an array
2921
2824
  if ( line.slice( - 1 ) !== ',' ) {
2922
2825
 
2923
2826
  currentNode.a = parseNumberArray( currentNode.a );
2924
2827
 
2925
2828
  }
2926
2829
 
2927
- } // parse "Property70"
2928
-
2830
+ }
2929
2831
 
2832
+ // parse "Property70"
2930
2833
  parseNodeSpecialProperty( line, propName, propValue ) {
2931
2834
 
2932
2835
  // split this
@@ -2942,8 +2845,9 @@
2942
2845
  const innerPropType1 = props[ 1 ];
2943
2846
  const innerPropType2 = props[ 2 ];
2944
2847
  const innerPropFlag = props[ 3 ];
2945
- let innerPropValue = props[ 4 ]; // cast values where needed, otherwise leave as strings
2848
+ let innerPropValue = props[ 4 ];
2946
2849
 
2850
+ // cast values where needed, otherwise leave as strings
2947
2851
  switch ( innerPropType1 ) {
2948
2852
 
2949
2853
  case 'int':
@@ -2955,7 +2859,6 @@
2955
2859
  case 'FieldOfView':
2956
2860
  innerPropValue = parseFloat( innerPropValue );
2957
2861
  break;
2958
-
2959
2862
  case 'Color':
2960
2863
  case 'ColorRGB':
2961
2864
  case 'Vector3D':
@@ -2965,9 +2868,9 @@
2965
2868
  innerPropValue = parseNumberArray( innerPropValue );
2966
2869
  break;
2967
2870
 
2968
- } // CAUTION: these props must append to parent's parent
2969
-
2871
+ }
2970
2872
 
2873
+ // CAUTION: these props must append to parent's parent
2971
2874
  this.getPrevNode()[ innerPropName ] = {
2972
2875
  'type': innerPropType1,
2973
2876
  'type2': innerPropType2,
@@ -2978,9 +2881,9 @@
2978
2881
 
2979
2882
  }
2980
2883
 
2981
- } // Parse an FBX file in Binary format
2982
-
2884
+ }
2983
2885
 
2886
+ // Parse an FBX file in Binary format
2984
2887
  class BinaryParser {
2985
2888
 
2986
2889
  parse( buffer ) {
@@ -2989,7 +2892,6 @@
2989
2892
  reader.skip( 23 ); // skip magic 23 bytes
2990
2893
 
2991
2894
  const version = reader.getUint32();
2992
-
2993
2895
  if ( version < 6400 ) {
2994
2896
 
2995
2897
  throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + version );
@@ -2997,7 +2899,6 @@
2997
2899
  }
2998
2900
 
2999
2901
  const allNodes = new FBXTree();
3000
-
3001
2902
  while ( ! this.endOfContent( reader ) ) {
3002
2903
 
3003
2904
  const node = this.parseNode( reader, version );
@@ -3007,9 +2908,9 @@
3007
2908
 
3008
2909
  return allNodes;
3009
2910
 
3010
- } // Check if reader has reached the end of content.
3011
-
2911
+ }
3012
2912
 
2913
+ // Check if reader has reached the end of content.
3013
2914
  endOfContent( reader ) {
3014
2915
 
3015
2916
  // footer size: 160bytes + 16-byte alignment padding
@@ -3030,37 +2931,38 @@
3030
2931
 
3031
2932
  }
3032
2933
 
3033
- } // recursively parse nodes until the end of the file is reached
3034
-
2934
+ }
3035
2935
 
2936
+ // recursively parse nodes until the end of the file is reached
3036
2937
  parseNode( reader, version ) {
3037
2938
 
3038
- const node = {}; // The first three data sizes depends on version.
2939
+ const node = {};
3039
2940
 
2941
+ // The first three data sizes depends on version.
3040
2942
  const endOffset = version >= 7500 ? reader.getUint64() : reader.getUint32();
3041
2943
  const numProperties = version >= 7500 ? reader.getUint64() : reader.getUint32();
3042
2944
  version >= 7500 ? reader.getUint64() : reader.getUint32(); // the returned propertyListLen is not used
3043
2945
 
3044
2946
  const nameLen = reader.getUint8();
3045
- const name = reader.getString( nameLen ); // Regards this node as NULL-record if endOffset is zero
2947
+ const name = reader.getString( nameLen );
3046
2948
 
2949
+ // Regards this node as NULL-record if endOffset is zero
3047
2950
  if ( endOffset === 0 ) return null;
3048
2951
  const propertyList = [];
3049
-
3050
2952
  for ( let i = 0; i < numProperties; i ++ ) {
3051
2953
 
3052
2954
  propertyList.push( this.parseProperty( reader ) );
3053
2955
 
3054
- } // Regards the first three elements in propertyList as id, attrName, and attrType
3055
-
2956
+ }
3056
2957
 
2958
+ // Regards the first three elements in propertyList as id, attrName, and attrType
3057
2959
  const id = propertyList.length > 0 ? propertyList[ 0 ] : '';
3058
2960
  const attrName = propertyList.length > 1 ? propertyList[ 1 ] : '';
3059
- const attrType = propertyList.length > 2 ? propertyList[ 2 ] : ''; // check if this node represents just a single property
3060
- // like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]}
2961
+ const attrType = propertyList.length > 2 ? propertyList[ 2 ] : '';
3061
2962
 
2963
+ // check if this node represents just a single property
2964
+ // like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]}
3062
2965
  node.singleProperty = numProperties === 1 && reader.getOffset() === endOffset ? true : false;
3063
-
3064
2966
  while ( endOffset > reader.getOffset() ) {
3065
2967
 
3066
2968
  const subNode = this.parseNode( reader, version );
@@ -3077,14 +2979,12 @@
3077
2979
  return node;
3078
2980
 
3079
2981
  }
3080
-
3081
2982
  parseSubNode( name, node, subNode ) {
3082
2983
 
3083
2984
  // special case: child node is single property
3084
2985
  if ( subNode.singleProperty === true ) {
3085
2986
 
3086
2987
  const value = subNode.propertyList[ 0 ];
3087
-
3088
2988
  if ( Array.isArray( value ) ) {
3089
2989
 
3090
2990
  node[ subNode.name ] = subNode;
@@ -3105,7 +3005,6 @@
3105
3005
  if ( i !== 0 ) array.push( property );
3106
3006
 
3107
3007
  } );
3108
-
3109
3008
  if ( node.connections === undefined ) {
3110
3009
 
3111
3010
  node.connections = [];
@@ -3132,7 +3031,6 @@
3132
3031
  let innerPropValue;
3133
3032
  if ( innerPropName.indexOf( 'Lcl ' ) === 0 ) innerPropName = innerPropName.replace( 'Lcl ', 'Lcl_' );
3134
3033
  if ( innerPropType1.indexOf( 'Lcl ' ) === 0 ) innerPropType1 = innerPropType1.replace( 'Lcl ', 'Lcl_' );
3135
-
3136
3034
  if ( innerPropType1 === 'Color' || innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) {
3137
3035
 
3138
3036
  innerPropValue = [ subNode.propertyList[ 4 ], subNode.propertyList[ 5 ], subNode.propertyList[ 6 ] ];
@@ -3141,9 +3039,9 @@
3141
3039
 
3142
3040
  innerPropValue = subNode.propertyList[ 4 ];
3143
3041
 
3144
- } // this will be copied to parent, see above
3145
-
3042
+ }
3146
3043
 
3044
+ // this will be copied to parent, see above
3147
3045
  node[ innerPropName ] = {
3148
3046
  'type': innerPropType1,
3149
3047
  'type2': innerPropType2,
@@ -3185,40 +3083,30 @@
3185
3083
  }
3186
3084
 
3187
3085
  }
3188
-
3189
3086
  parseProperty( reader ) {
3190
3087
 
3191
3088
  const type = reader.getString( 1 );
3192
3089
  let length;
3193
-
3194
3090
  switch ( type ) {
3195
3091
 
3196
3092
  case 'C':
3197
3093
  return reader.getBoolean();
3198
-
3199
3094
  case 'D':
3200
3095
  return reader.getFloat64();
3201
-
3202
3096
  case 'F':
3203
3097
  return reader.getFloat32();
3204
-
3205
3098
  case 'I':
3206
3099
  return reader.getInt32();
3207
-
3208
3100
  case 'L':
3209
3101
  return reader.getInt64();
3210
-
3211
3102
  case 'R':
3212
3103
  length = reader.getUint32();
3213
3104
  return reader.getArrayBuffer( length );
3214
-
3215
3105
  case 'S':
3216
3106
  length = reader.getUint32();
3217
3107
  return reader.getString( length );
3218
-
3219
3108
  case 'Y':
3220
3109
  return reader.getInt16();
3221
-
3222
3110
  case 'b':
3223
3111
  case 'c':
3224
3112
  case 'd':
@@ -3227,9 +3115,7 @@
3227
3115
  case 'l':
3228
3116
  const arrayLength = reader.getUint32();
3229
3117
  const encoding = reader.getUint32(); // 0: non-compressed, 1: compressed
3230
-
3231
3118
  const compressedLength = reader.getUint32();
3232
-
3233
3119
  if ( encoding === 0 ) {
3234
3120
 
3235
3121
  switch ( type ) {
@@ -3237,16 +3123,12 @@
3237
3123
  case 'b':
3238
3124
  case 'c':
3239
3125
  return reader.getBooleanArray( arrayLength );
3240
-
3241
3126
  case 'd':
3242
3127
  return reader.getFloat64Array( arrayLength );
3243
-
3244
3128
  case 'f':
3245
3129
  return reader.getFloat32Array( arrayLength );
3246
-
3247
3130
  case 'i':
3248
3131
  return reader.getInt32Array( arrayLength );
3249
-
3250
3132
  case 'l':
3251
3133
  return reader.getInt64Array( arrayLength );
3252
3134
 
@@ -3261,24 +3143,18 @@
3261
3143
  }
3262
3144
 
3263
3145
  const data = fflate.unzlibSync( new Uint8Array( reader.getArrayBuffer( compressedLength ) ) ); // eslint-disable-line no-undef
3264
-
3265
3146
  const reader2 = new BinaryReader( data.buffer );
3266
-
3267
3147
  switch ( type ) {
3268
3148
 
3269
3149
  case 'b':
3270
3150
  case 'c':
3271
3151
  return reader2.getBooleanArray( arrayLength );
3272
-
3273
3152
  case 'd':
3274
3153
  return reader2.getFloat64Array( arrayLength );
3275
-
3276
3154
  case 'f':
3277
3155
  return reader2.getFloat32Array( arrayLength );
3278
-
3279
3156
  case 'i':
3280
3157
  return reader2.getInt32Array( arrayLength );
3281
-
3282
3158
  case 'l':
3283
3159
  return reader2.getInt64Array( arrayLength );
3284
3160
 
@@ -3295,7 +3171,6 @@
3295
3171
  }
3296
3172
 
3297
3173
  }
3298
-
3299
3174
  class BinaryReader {
3300
3175
 
3301
3176
  constructor( buffer, littleEndian ) {
@@ -3305,38 +3180,33 @@
3305
3180
  this.littleEndian = littleEndian !== undefined ? littleEndian : true;
3306
3181
 
3307
3182
  }
3308
-
3309
3183
  getOffset() {
3310
3184
 
3311
3185
  return this.offset;
3312
3186
 
3313
3187
  }
3314
-
3315
3188
  size() {
3316
3189
 
3317
3190
  return this.dv.buffer.byteLength;
3318
3191
 
3319
3192
  }
3320
-
3321
3193
  skip( length ) {
3322
3194
 
3323
3195
  this.offset += length;
3324
3196
 
3325
- } // seems like true/false representation depends on exporter.
3197
+ }
3198
+
3199
+ // seems like true/false representation depends on exporter.
3326
3200
  // true: 1 or 'Y'(=0x59), false: 0 or 'T'(=0x54)
3327
3201
  // then sees LSB.
3328
-
3329
-
3330
3202
  getBoolean() {
3331
3203
 
3332
3204
  return ( this.getUint8() & 1 ) === 1;
3333
3205
 
3334
3206
  }
3335
-
3336
3207
  getBooleanArray( size ) {
3337
3208
 
3338
3209
  const a = [];
3339
-
3340
3210
  for ( let i = 0; i < size; i ++ ) {
3341
3211
 
3342
3212
  a.push( this.getBoolean() );
@@ -3346,7 +3216,6 @@
3346
3216
  return a;
3347
3217
 
3348
3218
  }
3349
-
3350
3219
  getUint8() {
3351
3220
 
3352
3221
  const value = this.dv.getUint8( this.offset );
@@ -3354,7 +3223,6 @@
3354
3223
  return value;
3355
3224
 
3356
3225
  }
3357
-
3358
3226
  getInt16() {
3359
3227
 
3360
3228
  const value = this.dv.getInt16( this.offset, this.littleEndian );
@@ -3362,7 +3230,6 @@
3362
3230
  return value;
3363
3231
 
3364
3232
  }
3365
-
3366
3233
  getInt32() {
3367
3234
 
3368
3235
  const value = this.dv.getInt32( this.offset, this.littleEndian );
@@ -3370,11 +3237,9 @@
3370
3237
  return value;
3371
3238
 
3372
3239
  }
3373
-
3374
3240
  getInt32Array( size ) {
3375
3241
 
3376
3242
  const a = [];
3377
-
3378
3243
  for ( let i = 0; i < size; i ++ ) {
3379
3244
 
3380
3245
  a.push( this.getInt32() );
@@ -3384,24 +3249,22 @@
3384
3249
  return a;
3385
3250
 
3386
3251
  }
3387
-
3388
3252
  getUint32() {
3389
3253
 
3390
3254
  const value = this.dv.getUint32( this.offset, this.littleEndian );
3391
3255
  this.offset += 4;
3392
3256
  return value;
3393
3257
 
3394
- } // JavaScript doesn't support 64-bit integer so calculate this here
3258
+ }
3259
+
3260
+ // JavaScript doesn't support 64-bit integer so calculate this here
3395
3261
  // 1 << 32 will return 1 so using multiply operation instead here.
3396
3262
  // There's a possibility that this method returns wrong value if the value
3397
3263
  // is out of the range between Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER.
3398
3264
  // TODO: safely handle 64-bit integer
3399
-
3400
-
3401
3265
  getInt64() {
3402
3266
 
3403
3267
  let low, high;
3404
-
3405
3268
  if ( this.littleEndian ) {
3406
3269
 
3407
3270
  low = this.getUint32();
@@ -3412,9 +3275,9 @@
3412
3275
  high = this.getUint32();
3413
3276
  low = this.getUint32();
3414
3277
 
3415
- } // calculate negative value
3416
-
3278
+ }
3417
3279
 
3280
+ // calculate negative value
3418
3281
  if ( high & 0x80000000 ) {
3419
3282
 
3420
3283
  high = ~ high & 0xFFFFFFFF;
@@ -3428,11 +3291,9 @@
3428
3291
  return high * 0x100000000 + low;
3429
3292
 
3430
3293
  }
3431
-
3432
3294
  getInt64Array( size ) {
3433
3295
 
3434
3296
  const a = [];
3435
-
3436
3297
  for ( let i = 0; i < size; i ++ ) {
3437
3298
 
3438
3299
  a.push( this.getInt64() );
@@ -3441,13 +3302,12 @@
3441
3302
 
3442
3303
  return a;
3443
3304
 
3444
- } // Note: see getInt64() comment
3445
-
3305
+ }
3446
3306
 
3307
+ // Note: see getInt64() comment
3447
3308
  getUint64() {
3448
3309
 
3449
3310
  let low, high;
3450
-
3451
3311
  if ( this.littleEndian ) {
3452
3312
 
3453
3313
  low = this.getUint32();
@@ -3463,7 +3323,6 @@
3463
3323
  return high * 0x100000000 + low;
3464
3324
 
3465
3325
  }
3466
-
3467
3326
  getFloat32() {
3468
3327
 
3469
3328
  const value = this.dv.getFloat32( this.offset, this.littleEndian );
@@ -3471,11 +3330,9 @@
3471
3330
  return value;
3472
3331
 
3473
3332
  }
3474
-
3475
3333
  getFloat32Array( size ) {
3476
3334
 
3477
3335
  const a = [];
3478
-
3479
3336
  for ( let i = 0; i < size; i ++ ) {
3480
3337
 
3481
3338
  a.push( this.getFloat32() );
@@ -3485,7 +3342,6 @@
3485
3342
  return a;
3486
3343
 
3487
3344
  }
3488
-
3489
3345
  getFloat64() {
3490
3346
 
3491
3347
  const value = this.dv.getFloat64( this.offset, this.littleEndian );
@@ -3493,11 +3349,9 @@
3493
3349
  return value;
3494
3350
 
3495
3351
  }
3496
-
3497
3352
  getFloat64Array( size ) {
3498
3353
 
3499
3354
  const a = [];
3500
-
3501
3355
  for ( let i = 0; i < size; i ++ ) {
3502
3356
 
3503
3357
  a.push( this.getFloat64() );
@@ -3507,7 +3361,6 @@
3507
3361
  return a;
3508
3362
 
3509
3363
  }
3510
-
3511
3364
  getArrayBuffer( size ) {
3512
3365
 
3513
3366
  const value = this.dv.buffer.slice( this.offset, this.offset + size );
@@ -3515,12 +3368,10 @@
3515
3368
  return value;
3516
3369
 
3517
3370
  }
3518
-
3519
3371
  getString( size ) {
3520
3372
 
3521
3373
  // note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead
3522
3374
  let a = [];
3523
-
3524
3375
  for ( let i = 0; i < size; i ++ ) {
3525
3376
 
3526
3377
  a[ i ] = this.getUint8();
@@ -3533,10 +3384,10 @@
3533
3384
 
3534
3385
  }
3535
3386
 
3536
- } // FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format)
3537
- // and BinaryParser( FBX Binary format)
3538
-
3387
+ }
3539
3388
 
3389
+ // FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format)
3390
+ // and BinaryParser( FBX Binary format)
3540
3391
  class FBXTree {
3541
3392
 
3542
3393
  add( key, val ) {
@@ -3545,8 +3396,9 @@
3545
3396
 
3546
3397
  }
3547
3398
 
3548
- } // ************** UTILITY FUNCTIONS **************
3399
+ }
3549
3400
 
3401
+ // ************** UTILITY FUNCTIONS **************
3550
3402
 
3551
3403
  function isFbxFormatBinary( buffer ) {
3552
3404
 
@@ -3559,7 +3411,6 @@
3559
3411
 
3560
3412
  const CORRECT = [ 'K', 'a', 'y', 'd', 'a', 'r', 'a', '\\', 'F', 'B', 'X', '\\', 'B', 'i', 'n', 'a', 'r', 'y', '\\', '\\' ];
3561
3413
  let cursor = 0;
3562
-
3563
3414
  function read( offset ) {
3564
3415
 
3565
3416
  const result = text[ offset - 1 ];
@@ -3572,7 +3423,6 @@
3572
3423
  for ( let i = 0; i < CORRECT.length; ++ i ) {
3573
3424
 
3574
3425
  const num = read( 1 );
3575
-
3576
3426
  if ( num === CORRECT[ i ] ) {
3577
3427
 
3578
3428
  return false;
@@ -3589,7 +3439,6 @@
3589
3439
 
3590
3440
  const versionRegExp = /FBXVersion: (\d+)/;
3591
3441
  const match = text.match( versionRegExp );
3592
-
3593
3442
  if ( match ) {
3594
3443
 
3595
3444
  const version = parseInt( match[ 1 ] );
@@ -3599,39 +3448,35 @@
3599
3448
 
3600
3449
  throw new Error( 'THREE.FBXLoader: Cannot find the version number for the file given.' );
3601
3450
 
3602
- } // Converts FBX ticks into real time seconds.
3603
-
3451
+ }
3604
3452
 
3453
+ // Converts FBX ticks into real time seconds.
3605
3454
  function convertFBXTimeToSeconds( time ) {
3606
3455
 
3607
3456
  return time / 46186158000;
3608
3457
 
3609
3458
  }
3610
3459
 
3611
- const dataArray = []; // extracts the data from the correct position in the FBX array based on indexing type
3460
+ const dataArray = [];
3612
3461
 
3462
+ // extracts the data from the correct position in the FBX array based on indexing type
3613
3463
  function getData( polygonVertexIndex, polygonIndex, vertexIndex, infoObject ) {
3614
3464
 
3615
3465
  let index;
3616
-
3617
3466
  switch ( infoObject.mappingType ) {
3618
3467
 
3619
3468
  case 'ByPolygonVertex':
3620
3469
  index = polygonVertexIndex;
3621
3470
  break;
3622
-
3623
3471
  case 'ByPolygon':
3624
3472
  index = polygonIndex;
3625
3473
  break;
3626
-
3627
3474
  case 'ByVertice':
3628
3475
  index = vertexIndex;
3629
3476
  break;
3630
-
3631
3477
  case 'AllSame':
3632
3478
  index = infoObject.indices[ 0 ];
3633
3479
  break;
3634
-
3635
3480
  default:
3636
3481
  console.warn( 'THREE.FBXLoader: unknown attribute mapping type ' + infoObject.mappingType );
3637
3482
 
@@ -3645,10 +3490,11 @@
3645
3490
  }
3646
3491
 
3647
3492
  const tempEuler = new THREE.Euler();
3648
- const tempVec = new THREE.Vector3(); // generate transformation from FBX transform data
3493
+ const tempVec = new THREE.Vector3();
3494
+
3495
+ // generate transformation from FBX transform data
3649
3496
  // ref: https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm
3650
3497
  // ref: http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/index.html?url=cpp_ref/_transformations_2main_8cxx-example.html,topicNumber=cpp_ref__transformations_2main_8cxx_example_htmlfc10a1e1-b18d-4e72-9dc0-70d0f1959f5e
3651
-
3652
3498
  function generateTransform( transformData ) {
3653
3499
 
3654
3500
  const lTranslationM = new THREE.Matrix4();
@@ -3665,11 +3511,10 @@
3665
3511
  const lGlobalT = new THREE.Matrix4();
3666
3512
  const inheritType = transformData.inheritType ? transformData.inheritType : 0;
3667
3513
  if ( transformData.translation ) lTranslationM.setPosition( tempVec.fromArray( transformData.translation ) );
3668
-
3669
3514
  if ( transformData.preRotation ) {
3670
3515
 
3671
3516
  const array = transformData.preRotation.map( THREE.MathUtils.degToRad );
3672
- array.push( transformData.eulerOrder );
3517
+ array.push( transformData.eulerOrder || THREE.Euler.DefaultOrder );
3673
3518
  lPreRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) );
3674
3519
 
3675
3520
  }
@@ -3677,7 +3522,7 @@
3677
3522
  if ( transformData.rotation ) {
3678
3523
 
3679
3524
  const array = transformData.rotation.map( THREE.MathUtils.degToRad );
3680
- array.push( transformData.eulerOrder );
3525
+ array.push( transformData.eulerOrder || THREE.Euler.DefaultOrder );
3681
3526
  lRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) );
3682
3527
 
3683
3528
  }
@@ -3685,19 +3530,21 @@
3685
3530
  if ( transformData.postRotation ) {
3686
3531
 
3687
3532
  const array = transformData.postRotation.map( THREE.MathUtils.degToRad );
3688
- array.push( transformData.eulerOrder );
3533
+ array.push( transformData.eulerOrder || THREE.Euler.DefaultOrder );
3689
3534
  lPostRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) );
3690
3535
  lPostRotationM.invert();
3691
3536
 
3692
3537
  }
3693
3538
 
3694
- if ( transformData.scale ) lScalingM.scale( tempVec.fromArray( transformData.scale ) ); // Pivots and offsets
3539
+ if ( transformData.scale ) lScalingM.scale( tempVec.fromArray( transformData.scale ) );
3695
3540
 
3541
+ // Pivots and offsets
3696
3542
  if ( transformData.scalingOffset ) lScalingOffsetM.setPosition( tempVec.fromArray( transformData.scalingOffset ) );
3697
3543
  if ( transformData.scalingPivot ) lScalingPivotM.setPosition( tempVec.fromArray( transformData.scalingPivot ) );
3698
3544
  if ( transformData.rotationOffset ) lRotationOffsetM.setPosition( tempVec.fromArray( transformData.rotationOffset ) );
3699
- if ( transformData.rotationPivot ) lRotationPivotM.setPosition( tempVec.fromArray( transformData.rotationPivot ) ); // parent transform
3545
+ if ( transformData.rotationPivot ) lRotationPivotM.setPosition( tempVec.fromArray( transformData.rotationPivot ) );
3700
3546
 
3547
+ // parent transform
3701
3548
  if ( transformData.parentMatrixWorld ) {
3702
3549
 
3703
3550
  lParentLX.copy( transformData.parentMatrix );
@@ -3705,18 +3552,18 @@
3705
3552
 
3706
3553
  }
3707
3554
 
3708
- const lLRM = lPreRotationM.clone().multiply( lRotationM ).multiply( lPostRotationM ); // Global Rotation
3709
-
3555
+ const lLRM = lPreRotationM.clone().multiply( lRotationM ).multiply( lPostRotationM );
3556
+ // Global Rotation
3710
3557
  const lParentGRM = new THREE.Matrix4();
3711
- lParentGRM.extractRotation( lParentGX ); // Global Shear*Scaling
3558
+ lParentGRM.extractRotation( lParentGX );
3712
3559
 
3560
+ // Global Shear*Scaling
3713
3561
  const lParentTM = new THREE.Matrix4();
3714
3562
  lParentTM.copyPosition( lParentGX );
3715
3563
  const lParentGRSM = lParentTM.clone().invert().multiply( lParentGX );
3716
3564
  const lParentGSM = lParentGRM.clone().invert().multiply( lParentGRSM );
3717
3565
  const lLSM = lScalingM;
3718
3566
  const lGlobalRS = new THREE.Matrix4();
3719
-
3720
3567
  if ( inheritType === 0 ) {
3721
3568
 
3722
3569
  lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM ).multiply( lLSM );
@@ -3735,29 +3582,35 @@
3735
3582
  }
3736
3583
 
3737
3584
  const lRotationPivotM_inv = lRotationPivotM.clone().invert();
3738
- const lScalingPivotM_inv = lScalingPivotM.clone().invert(); // Calculate the local transform matrix
3739
-
3585
+ const lScalingPivotM_inv = lScalingPivotM.clone().invert();
3586
+ // Calculate the local transform matrix
3740
3587
  let lTransform = lTranslationM.clone().multiply( lRotationOffsetM ).multiply( lRotationPivotM ).multiply( lPreRotationM ).multiply( lRotationM ).multiply( lPostRotationM ).multiply( lRotationPivotM_inv ).multiply( lScalingOffsetM ).multiply( lScalingPivotM ).multiply( lScalingM ).multiply( lScalingPivotM_inv );
3741
3588
  const lLocalTWithAllPivotAndOffsetInfo = new THREE.Matrix4().copyPosition( lTransform );
3742
3589
  const lGlobalTranslation = lParentGX.clone().multiply( lLocalTWithAllPivotAndOffsetInfo );
3743
3590
  lGlobalT.copyPosition( lGlobalTranslation );
3744
- lTransform = lGlobalT.clone().multiply( lGlobalRS ); // from global to local
3591
+ lTransform = lGlobalT.clone().multiply( lGlobalRS );
3745
3592
 
3593
+ // from global to local
3746
3594
  lTransform.premultiply( lParentGX.invert() );
3747
3595
  return lTransform;
3748
3596
 
3749
- } // Returns the three.js intrinsic THREE.Euler order corresponding to FBX extrinsic THREE.Euler order
3750
- // ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html
3751
-
3597
+ }
3752
3598
 
3599
+ // Returns the three.js intrinsic THREE.Euler order corresponding to FBX extrinsic THREE.Euler order
3600
+ // ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html
3753
3601
  function getEulerOrder( order ) {
3754
3602
 
3755
3603
  order = order || 0;
3756
- const enums = [ 'ZYX', // -> XYZ extrinsic
3757
- 'YZX', // -> XZY extrinsic
3758
- 'XZY', // -> YZX extrinsic
3759
- 'ZXY', // -> YXZ extrinsic
3760
- 'YXZ', // -> ZXY extrinsic
3604
+ const enums = [ 'ZYX',
3605
+ // -> XYZ extrinsic
3606
+ 'YZX',
3607
+ // -> XZY extrinsic
3608
+ 'XZY',
3609
+ // -> YZX extrinsic
3610
+ 'ZXY',
3611
+ // -> YXZ extrinsic
3612
+ 'YXZ',
3613
+ // -> ZXY extrinsic
3761
3614
  'XYZ' // -> ZYX extrinsic
3762
3615
  //'SphericXYZ', // not possible to support
3763
3616
  ];
@@ -3771,10 +3624,10 @@
3771
3624
 
3772
3625
  return enums[ order ];
3773
3626
 
3774
- } // Parses comma separated list of numbers and returns them an array.
3775
- // Used internally by the TextParser
3776
-
3627
+ }
3777
3628
 
3629
+ // Parses comma separated list of numbers and returns them an array.
3630
+ // Used internally by the TextParser
3778
3631
  function parseNumberArray( value ) {
3779
3632
 
3780
3633
  const array = value.split( ',' ).map( function ( val ) {
@@ -3814,9 +3667,9 @@
3814
3667
 
3815
3668
  return a;
3816
3669
 
3817
- } // inject array a2 into array a1 at index
3818
-
3670
+ }
3819
3671
 
3672
+ // inject array a2 into array a1 at index
3820
3673
  function inject( a1, index, a2 ) {
3821
3674
 
3822
3675
  return a1.slice( 0, index ).concat( a2 ).concat( a1.slice( index ) );