super-three 0.157.1 → 0.160.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 (303) hide show
  1. package/README.md +6 -4
  2. package/build/three.cjs +3100 -1537
  3. package/build/three.js +3100 -1537
  4. package/build/three.min.js +1 -1
  5. package/build/three.module.js +3093 -1538
  6. package/build/three.module.min.js +1 -1
  7. package/examples/jsm/Addons.js +291 -0
  8. package/examples/jsm/controls/FlyControls.js +26 -0
  9. package/examples/jsm/controls/OrbitControls.js +62 -41
  10. package/examples/jsm/controls/TransformControls.js +27 -11
  11. package/examples/jsm/csm/CSMShader.js +53 -48
  12. package/examples/jsm/exporters/GLTFExporter.js +151 -3
  13. package/examples/jsm/exporters/USDZExporter.js +27 -19
  14. package/examples/jsm/geometries/InstancedPointsGeometry.js +174 -0
  15. package/examples/jsm/geometries/SDFGeometryGenerator.js +144 -0
  16. package/examples/jsm/helpers/TextureHelper.js +237 -0
  17. package/examples/jsm/interactive/HTMLMesh.js +9 -2
  18. package/examples/jsm/libs/lottie_canvas.module.js +6 -1
  19. package/examples/jsm/libs/opentype.module.js +13 -75
  20. package/examples/jsm/libs/surfaceNet.js +201 -0
  21. package/examples/jsm/lines/LineMaterial.js +16 -33
  22. package/examples/jsm/loaders/ColladaLoader.js +0 -6
  23. package/examples/jsm/loaders/DRACOLoader.js +4 -3
  24. package/examples/jsm/loaders/FBXLoader.js +294 -124
  25. package/examples/jsm/loaders/GLTFLoader.js +83 -6
  26. package/examples/jsm/loaders/LUTImageLoader.js +162 -0
  27. package/examples/jsm/loaders/MaterialXLoader.js +73 -54
  28. package/examples/jsm/loaders/NRRDLoader.js +0 -13
  29. package/examples/jsm/loaders/SVGLoader.js +4 -4
  30. package/examples/jsm/loaders/USDZLoader.js +3 -17
  31. package/examples/jsm/loaders/lwo/IFFParser.js +89 -93
  32. package/examples/jsm/materials/MeshGouraudMaterial.js +2 -0
  33. package/examples/jsm/math/Capsule.js +0 -55
  34. package/examples/jsm/math/Octree.js +85 -7
  35. package/examples/jsm/misc/Timer.js +119 -0
  36. package/examples/jsm/misc/TubePainter.js +3 -6
  37. package/examples/jsm/modifiers/CurveModifier.js +20 -2
  38. package/examples/jsm/modifiers/SimplifyModifier.js +103 -11
  39. package/examples/jsm/modifiers/TessellateModifier.js +3 -3
  40. package/examples/jsm/nodes/Nodes.js +16 -12
  41. package/examples/jsm/nodes/accessors/CameraNode.js +18 -2
  42. package/examples/jsm/nodes/accessors/CubeTextureNode.js +5 -73
  43. package/examples/jsm/nodes/accessors/InstanceNode.js +3 -3
  44. package/examples/jsm/nodes/accessors/InstancedPointsMaterialNode.js +21 -0
  45. package/examples/jsm/nodes/accessors/MaterialNode.js +68 -31
  46. package/examples/jsm/nodes/accessors/MaterialReferenceNode.js +11 -2
  47. package/examples/jsm/nodes/accessors/ModelNode.js +1 -2
  48. package/examples/jsm/nodes/accessors/ModelViewProjectionNode.js +12 -3
  49. package/examples/jsm/nodes/accessors/MorphNode.js +191 -16
  50. package/examples/jsm/nodes/accessors/NormalNode.js +1 -1
  51. package/examples/jsm/nodes/accessors/PositionNode.js +1 -1
  52. package/examples/jsm/nodes/accessors/ReferenceNode.js +25 -1
  53. package/examples/jsm/nodes/accessors/SkinningNode.js +13 -3
  54. package/examples/jsm/nodes/accessors/TextureNode.js +123 -37
  55. package/examples/jsm/nodes/code/CodeNode.js +3 -3
  56. package/examples/jsm/nodes/code/FunctionNode.js +1 -1
  57. package/examples/jsm/nodes/core/AssignNode.js +72 -0
  58. package/examples/jsm/nodes/core/AttributeNode.js +7 -1
  59. package/examples/jsm/nodes/core/CacheNode.js +4 -1
  60. package/examples/jsm/nodes/core/ConstNode.js +1 -1
  61. package/examples/jsm/nodes/core/LightingModel.js +3 -1
  62. package/examples/jsm/nodes/core/Node.js +13 -15
  63. package/examples/jsm/nodes/core/NodeBuilder.js +209 -42
  64. package/examples/jsm/nodes/core/NodeFrame.js +10 -8
  65. package/examples/jsm/nodes/core/NodeUniform.js +12 -0
  66. package/examples/jsm/nodes/core/NodeUtils.js +7 -9
  67. package/examples/jsm/nodes/core/OutputStructNode.js +4 -4
  68. package/examples/jsm/nodes/core/ParameterNode.js +33 -0
  69. package/examples/jsm/nodes/core/PropertyNode.js +15 -6
  70. package/examples/jsm/nodes/core/StackNode.js +7 -17
  71. package/examples/jsm/nodes/core/StructTypeNode.js +4 -4
  72. package/examples/jsm/nodes/core/TempNode.js +1 -1
  73. package/examples/jsm/nodes/core/UniformGroup.js +13 -0
  74. package/examples/jsm/nodes/core/UniformGroupNode.js +36 -0
  75. package/examples/jsm/nodes/core/UniformNode.js +17 -0
  76. package/examples/jsm/nodes/core/VarNode.js +7 -34
  77. package/examples/jsm/nodes/core/VaryingNode.js +3 -7
  78. package/examples/jsm/nodes/display/BumpMapNode.js +35 -13
  79. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +6 -10
  80. package/examples/jsm/nodes/display/GaussianBlurNode.js +170 -0
  81. package/examples/jsm/nodes/display/NormalMapNode.js +3 -1
  82. package/examples/jsm/nodes/display/PassNode.js +182 -0
  83. package/examples/jsm/nodes/display/ViewportDepthNode.js +31 -3
  84. package/examples/jsm/nodes/display/ViewportDepthTextureNode.js +2 -2
  85. package/examples/jsm/nodes/display/ViewportNode.js +17 -10
  86. package/examples/jsm/nodes/functions/BSDF/BRDF_Sheen.js +20 -6
  87. package/examples/jsm/nodes/functions/BSDF/DFGApprox.js +8 -7
  88. package/examples/jsm/nodes/functions/BSDF/D_GGX.js +8 -3
  89. package/examples/jsm/nodes/functions/BSDF/Schlick_to_F0.js +8 -0
  90. package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +8 -0
  91. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +93 -43
  92. package/examples/jsm/nodes/gpgpu/ComputeNode.js +2 -2
  93. package/examples/jsm/nodes/lighting/AmbientLightNode.js +1 -1
  94. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +55 -6
  95. package/examples/jsm/nodes/lighting/DirectionalLightNode.js +1 -1
  96. package/examples/jsm/nodes/lighting/EnvironmentNode.js +8 -18
  97. package/examples/jsm/nodes/lighting/LightingContextNode.js +21 -57
  98. package/examples/jsm/nodes/lighting/LightsNode.js +80 -20
  99. package/examples/jsm/nodes/lighting/PointLightNode.js +1 -1
  100. package/examples/jsm/nodes/lighting/SpotLightNode.js +1 -1
  101. package/examples/jsm/nodes/materials/InstancedPointsNodeMaterial.js +162 -0
  102. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +76 -77
  103. package/examples/jsm/nodes/materials/LineDashedNodeMaterial.js +5 -5
  104. package/examples/jsm/nodes/materials/Materials.js +1 -0
  105. package/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js +1 -0
  106. package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +3 -3
  107. package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +3 -3
  108. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +47 -20
  109. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +6 -6
  110. package/examples/jsm/nodes/materials/NodeMaterial.js +82 -60
  111. package/examples/jsm/nodes/materials/PointsNodeMaterial.js +0 -10
  112. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +0 -7
  113. package/examples/jsm/nodes/materialx/MaterialXNodes.js +10 -10
  114. package/examples/jsm/nodes/materialx/lib/mx_hsv.js +128 -54
  115. package/examples/jsm/nodes/materialx/lib/mx_noise.js +1430 -618
  116. package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +24 -14
  117. package/examples/jsm/nodes/math/MathNode.js +2 -0
  118. package/examples/jsm/nodes/math/OperatorNode.js +24 -27
  119. package/examples/jsm/nodes/shadernode/ShaderNode.js +158 -10
  120. package/examples/jsm/nodes/utils/ArrayElementNode.js +2 -0
  121. package/examples/jsm/nodes/utils/DiscardNode.js +3 -2
  122. package/examples/jsm/nodes/utils/FunctionOverloadingNode.js +95 -0
  123. package/examples/jsm/nodes/utils/JoinNode.js +11 -1
  124. package/examples/jsm/nodes/utils/LoopNode.js +36 -24
  125. package/examples/jsm/nodes/utils/RemapNode.js +2 -2
  126. package/examples/jsm/nodes/utils/SplitNode.js +10 -2
  127. package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +3 -3
  128. package/examples/jsm/objects/InstancedPoints.js +21 -0
  129. package/examples/jsm/objects/Lensflare.js +20 -0
  130. package/examples/jsm/objects/QuadMesh.js +60 -0
  131. package/examples/jsm/objects/ReflectorForSSRPass.js +3 -0
  132. package/examples/jsm/objects/Refractor.js +3 -0
  133. package/examples/jsm/objects/Sky.js +5 -3
  134. package/examples/jsm/objects/Water.js +5 -2
  135. package/examples/jsm/objects/Water2.js +3 -0
  136. package/examples/jsm/physics/AmmoPhysics.js +21 -0
  137. package/examples/jsm/physics/RapierPhysics.js +21 -0
  138. package/examples/jsm/postprocessing/BokehPass.js +3 -2
  139. package/examples/jsm/postprocessing/GTAOPass.js +572 -0
  140. package/examples/jsm/postprocessing/LUTPass.js +2 -1
  141. package/examples/jsm/postprocessing/OutputPass.js +3 -0
  142. package/examples/jsm/postprocessing/Pass.js +14 -3
  143. package/examples/jsm/postprocessing/SAOPass.js +0 -1
  144. package/examples/jsm/postprocessing/SMAAPass.js +0 -2
  145. package/examples/jsm/postprocessing/TAARenderPass.js +1 -2
  146. package/examples/jsm/renderers/CSS3DRenderer.js +3 -9
  147. package/examples/jsm/renderers/SVGRenderer.js +9 -6
  148. package/examples/jsm/renderers/common/Animation.js +10 -21
  149. package/examples/jsm/renderers/common/Backend.js +19 -3
  150. package/examples/jsm/renderers/common/Background.js +20 -22
  151. package/examples/jsm/renderers/common/Bindings.js +31 -22
  152. package/examples/jsm/renderers/common/ChainMap.js +3 -3
  153. package/examples/jsm/renderers/common/Color4.js +37 -0
  154. package/examples/jsm/renderers/common/Geometries.js +4 -4
  155. package/examples/jsm/renderers/common/Info.js +12 -2
  156. package/examples/jsm/renderers/common/Pipelines.js +3 -51
  157. package/examples/jsm/renderers/common/PostProcessing.js +25 -0
  158. package/examples/jsm/renderers/common/RenderContext.js +1 -1
  159. package/examples/jsm/renderers/common/RenderContexts.js +1 -1
  160. package/examples/jsm/renderers/common/RenderObject.js +21 -2
  161. package/examples/jsm/renderers/common/RenderObjects.js +5 -3
  162. package/examples/jsm/renderers/common/Renderer.js +137 -37
  163. package/examples/jsm/renderers/common/StorageTexture.js +1 -0
  164. package/examples/jsm/renderers/common/Textures.js +8 -37
  165. package/examples/jsm/renderers/common/nodes/NodeBuilderState.js +10 -2
  166. package/examples/jsm/renderers/common/nodes/NodeUniformsGroup.js +44 -0
  167. package/examples/jsm/renderers/common/nodes/Nodes.js +121 -19
  168. package/examples/jsm/renderers/webgl/WebGLBackend.js +366 -67
  169. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +183 -38
  170. package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +92 -5
  171. package/examples/jsm/renderers/webgl/utils/WebGLCapabilities.js +36 -0
  172. package/examples/jsm/renderers/webgl/utils/WebGLExtensions.js +11 -1
  173. package/examples/jsm/renderers/webgl/utils/WebGLState.js +14 -2
  174. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +71 -2
  175. package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +42 -0
  176. package/examples/jsm/renderers/webgl-legacy/nodes/SlotNode.js +1 -1
  177. package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js +33 -3
  178. package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js +4 -14
  179. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +188 -137
  180. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +1 -1
  181. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +241 -90
  182. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +15 -10
  183. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +11 -3
  184. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +2 -3
  185. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +88 -6
  186. package/examples/jsm/shaders/ACESFilmicToneMappingShader.js +2 -0
  187. package/examples/jsm/shaders/AfterimageShader.js +2 -0
  188. package/examples/jsm/shaders/BasicShader.js +2 -0
  189. package/examples/jsm/shaders/BlendShader.js +2 -0
  190. package/examples/jsm/shaders/BokehShader.js +2 -0
  191. package/examples/jsm/shaders/BokehShader2.js +4 -0
  192. package/examples/jsm/shaders/BrightnessContrastShader.js +2 -0
  193. package/examples/jsm/shaders/ColorCorrectionShader.js +2 -0
  194. package/examples/jsm/shaders/DOFMipMapShader.js +2 -0
  195. package/examples/jsm/shaders/DepthLimitedBlurShader.js +5 -0
  196. package/examples/jsm/shaders/FXAAShader.js +135 -133
  197. package/examples/jsm/shaders/FilmShader.js +1 -1
  198. package/examples/jsm/shaders/FocusShader.js +2 -0
  199. package/examples/jsm/shaders/FreiChenShader.js +2 -0
  200. package/examples/jsm/shaders/GTAOShader.js +424 -0
  201. package/examples/jsm/shaders/GodRaysShader.js +8 -0
  202. package/examples/jsm/shaders/HalftoneShader.js +2 -0
  203. package/examples/jsm/shaders/HorizontalTiltShiftShader.js +2 -0
  204. package/examples/jsm/shaders/HueSaturationShader.js +2 -0
  205. package/examples/jsm/shaders/KaleidoShader.js +2 -0
  206. package/examples/jsm/shaders/LuminosityHighPassShader.js +2 -0
  207. package/examples/jsm/shaders/LuminosityShader.js +2 -0
  208. package/examples/jsm/shaders/MMDToonShader.js +2 -0
  209. package/examples/jsm/shaders/MirrorShader.js +2 -0
  210. package/examples/jsm/shaders/NormalMapShader.js +2 -0
  211. package/examples/jsm/shaders/OutputShader.js +8 -5
  212. package/examples/jsm/shaders/PoissonDenoiseShader.js +226 -0
  213. package/examples/jsm/shaders/SAOShader.js +7 -3
  214. package/examples/jsm/shaders/SMAAShader.js +6 -0
  215. package/examples/jsm/shaders/SSAOShader.js +8 -3
  216. package/examples/jsm/shaders/SSRShader.js +6 -0
  217. package/examples/jsm/shaders/SobelOperatorShader.js +2 -0
  218. package/examples/jsm/shaders/SubsurfaceScatteringShader.js +2 -0
  219. package/examples/jsm/shaders/TechnicolorShader.js +2 -0
  220. package/examples/jsm/shaders/TriangleBlurShader.js +2 -0
  221. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -0
  222. package/examples/jsm/shaders/VelocityShader.js +2 -0
  223. package/examples/jsm/shaders/VerticalTiltShiftShader.js +2 -0
  224. package/examples/jsm/shaders/WaterRefractionShader.js +2 -0
  225. package/examples/jsm/transpiler/AST.js +270 -0
  226. package/examples/jsm/transpiler/GLSLDecoder.js +941 -0
  227. package/examples/jsm/transpiler/ShaderToyDecoder.js +49 -0
  228. package/examples/jsm/transpiler/TSLEncoder.js +715 -0
  229. package/examples/jsm/transpiler/Transpiler.js +18 -0
  230. package/examples/jsm/utils/SortUtils.js +158 -0
  231. package/examples/jsm/utils/TextureUtils.js +33 -21
  232. package/examples/jsm/webxr/ARButton.js +14 -0
  233. package/examples/jsm/webxr/VRButton.js +24 -9
  234. package/examples/jsm/webxr/XRButton.js +27 -11
  235. package/examples/jsm/webxr/XREstimatedLight.js +1 -1
  236. package/package.json +8 -6
  237. package/src/Three.js +1 -0
  238. package/src/constants.js +8 -1
  239. package/src/core/BufferAttribute.js +21 -2
  240. package/src/core/InterleavedBuffer.js +21 -1
  241. package/src/core/Object3D.js +60 -12
  242. package/src/core/UniformsGroup.js +7 -1
  243. package/src/extras/PMREMGenerator.js +7 -1
  244. package/src/extras/curves/LineCurve3.js +4 -0
  245. package/src/loaders/AudioLoader.js +1 -1
  246. package/src/loaders/BufferGeometryLoader.js +0 -7
  247. package/src/loaders/ImageBitmapLoader.js +25 -1
  248. package/src/loaders/MaterialLoader.js +10 -2
  249. package/src/loaders/ObjectLoader.js +49 -0
  250. package/src/materials/Material.js +27 -13
  251. package/src/materials/ShaderMaterial.js +2 -1
  252. package/src/math/Box3.js +35 -18
  253. package/src/math/ColorManagement.js +0 -16
  254. package/src/math/Quaternion.js +5 -4
  255. package/src/math/Sphere.js +2 -0
  256. package/src/math/Triangle.js +17 -5
  257. package/src/math/Vector3.js +11 -12
  258. package/src/objects/BatchedMesh.js +1020 -0
  259. package/src/objects/Skeleton.js +1 -3
  260. package/src/objects/SkinnedMesh.js +6 -7
  261. package/src/renderers/WebGL3DRenderTarget.js +2 -2
  262. package/src/renderers/WebGLArrayRenderTarget.js +2 -2
  263. package/src/renderers/WebGLRenderer.js +165 -43
  264. package/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js +8 -0
  265. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +19 -0
  266. package/src/renderers/shaders/ShaderChunk/batching_vertex.glsl.js +5 -0
  267. package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +3 -2
  268. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +0 -5
  269. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +31 -4
  270. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +1 -1
  271. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +9 -4
  272. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +8 -6
  273. package/src/renderers/shaders/ShaderChunk/project_vertex.glsl.js +6 -0
  274. package/src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl.js +9 -17
  275. package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +84 -0
  276. package/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js +6 -0
  277. package/src/renderers/shaders/ShaderChunk.js +4 -0
  278. package/src/renderers/shaders/ShaderLib/depth.glsl.js +2 -0
  279. package/src/renderers/shaders/ShaderLib/distanceRGBA.glsl.js +2 -0
  280. package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +2 -0
  281. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +2 -0
  282. package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +3 -0
  283. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +2 -0
  284. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +2 -0
  285. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -2
  286. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +2 -0
  287. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +3 -0
  288. package/src/renderers/webgl/WebGLAttributes.js +39 -5
  289. package/src/renderers/webgl/WebGLBufferRenderer.js +31 -0
  290. package/src/renderers/webgl/WebGLCubeMaps.js +1 -1
  291. package/src/renderers/webgl/WebGLExtensions.js +1 -0
  292. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +31 -0
  293. package/src/renderers/webgl/WebGLLights.js +11 -2
  294. package/src/renderers/webgl/WebGLProgram.js +100 -51
  295. package/src/renderers/webgl/WebGLPrograms.js +8 -0
  296. package/src/renderers/webgl/WebGLShadowMap.js +35 -0
  297. package/src/renderers/webgl/WebGLState.js +25 -4
  298. package/src/renderers/webgl/WebGLTextures.js +7 -11
  299. package/src/renderers/webgl/WebGLUniforms.js +11 -1
  300. package/src/renderers/webgl/WebGLUniformsGroups.js +72 -93
  301. package/src/renderers/webxr/WebXRManager.js +16 -0
  302. package/examples/jsm/nodes/accessors/ExtendedMaterialNode.js +0 -76
  303. package/examples/jsm/nodes/accessors/LineMaterialNode.js +0 -29
@@ -36,10 +36,12 @@ import {
36
36
  Texture,
37
37
  TextureLoader,
38
38
  Uint16BufferAttribute,
39
+ Vector2,
39
40
  Vector3,
40
41
  Vector4,
41
42
  VectorKeyframeTrack,
42
- SRGBColorSpace
43
+ SRGBColorSpace,
44
+ ShapeUtils
43
45
  } from 'three';
44
46
  import * as fflate from '../libs/fflate.module.js';
45
47
  import { NURBSCurve } from '../curves/NURBSCurve.js';
@@ -443,6 +445,22 @@ class FBXTreeParser {
443
445
 
444
446
  }
445
447
 
448
+ } else if ( extension === 'dds' ) {
449
+
450
+ const loader = this.manager.getHandler( '.dds' );
451
+
452
+ if ( loader === null ) {
453
+
454
+ console.warn( 'FBXLoader: DDS loader not found, creating placeholder texture for', textureNode.RelativeFilename );
455
+ texture = new Texture();
456
+
457
+ } else {
458
+
459
+ loader.setPath( this.textureLoader.path );
460
+ texture = loader.load( fileName );
461
+
462
+ }
463
+
446
464
  } else if ( extension === 'psd' ) {
447
465
 
448
466
  console.warn( 'FBXLoader: PSD textures are not supported, creating placeholder texture for', textureNode.RelativeFilename );
@@ -883,7 +901,7 @@ class FBXTreeParser {
883
901
 
884
902
  this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
885
903
 
886
- this.createAmbientLight();
904
+ this.addGlobalSceneSettings();
887
905
 
888
906
  sceneGraph.traverse( function ( node ) {
889
907
 
@@ -1466,20 +1484,31 @@ class FBXTreeParser {
1466
1484
 
1467
1485
  }
1468
1486
 
1469
- // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light
1470
- createAmbientLight() {
1487
+ addGlobalSceneSettings() {
1488
+
1489
+ if ( 'GlobalSettings' in fbxTree ) {
1471
1490
 
1472
- if ( 'GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings ) {
1491
+ if ( 'AmbientColor' in fbxTree.GlobalSettings ) {
1473
1492
 
1474
- const ambientColor = fbxTree.GlobalSettings.AmbientColor.value;
1475
- const r = ambientColor[ 0 ];
1476
- const g = ambientColor[ 1 ];
1477
- const b = ambientColor[ 2 ];
1493
+ // Parse ambient color - if it's not set to black (default), create an ambient light
1478
1494
 
1479
- if ( r !== 0 || g !== 0 || b !== 0 ) {
1495
+ const ambientColor = fbxTree.GlobalSettings.AmbientColor.value;
1496
+ const r = ambientColor[ 0 ];
1497
+ const g = ambientColor[ 1 ];
1498
+ const b = ambientColor[ 2 ];
1480
1499
 
1481
- const color = new Color( r, g, b ).convertSRGBToLinear();
1482
- sceneGraph.add( new AmbientLight( color, 1 ) );
1500
+ if ( r !== 0 || g !== 0 || b !== 0 ) {
1501
+
1502
+ const color = new Color( r, g, b ).convertSRGBToLinear();
1503
+ sceneGraph.add( new AmbientLight( color, 1 ) );
1504
+
1505
+ }
1506
+
1507
+ }
1508
+
1509
+ if ( 'UnitScaleFactor' in fbxTree.GlobalSettings ) {
1510
+
1511
+ sceneGraph.userData.unitScaleFactor = fbxTree.GlobalSettings.UnitScaleFactor.value;
1483
1512
 
1484
1513
  }
1485
1514
 
@@ -1944,8 +1973,6 @@ class GeometryParser {
1944
1973
 
1945
1974
  if ( endOfFace ) {
1946
1975
 
1947
- if ( faceLength > 4 ) console.warn( 'THREE.FBXLoader: Polygons with more than four sides are not supported. Make sure to triangulate the geometry during export.' );
1948
-
1949
1976
  scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength );
1950
1977
 
1951
1978
  polygonIndex ++;
@@ -1967,70 +1994,153 @@ class GeometryParser {
1967
1994
 
1968
1995
  }
1969
1996
 
1997
+ // See https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
1998
+ getNormalNewell( vertices ) {
1999
+
2000
+ const normal = new Vector3( 0.0, 0.0, 0.0 );
2001
+
2002
+ for ( let i = 0; i < vertices.length; i ++ ) {
2003
+
2004
+ const current = vertices[ i ];
2005
+ const next = vertices[ ( i + 1 ) % vertices.length ];
2006
+
2007
+ normal.x += ( current.y - next.y ) * ( current.z + next.z );
2008
+ normal.y += ( current.z - next.z ) * ( current.x + next.x );
2009
+ normal.z += ( current.x - next.x ) * ( current.y + next.y );
2010
+
2011
+ }
2012
+
2013
+ normal.normalize();
2014
+
2015
+ return normal;
2016
+
2017
+ }
2018
+
2019
+ getNormalTangentAndBitangent( vertices ) {
2020
+
2021
+ const normalVector = this.getNormalNewell( vertices );
2022
+ // Avoid up being equal or almost equal to normalVector
2023
+ const up = Math.abs( normalVector.z ) > 0.5 ? new Vector3( 0.0, 1.0, 0.0 ) : new Vector3( 0.0, 0.0, 1.0 );
2024
+ const tangent = up.cross( normalVector ).normalize();
2025
+ const bitangent = normalVector.clone().cross( tangent ).normalize();
2026
+
2027
+ return {
2028
+ normal: normalVector,
2029
+ tangent: tangent,
2030
+ bitangent: bitangent
2031
+ };
2032
+
2033
+ }
2034
+
2035
+ flattenVertex( vertex, normalTangent, normalBitangent ) {
2036
+
2037
+ return new Vector2(
2038
+ vertex.dot( normalTangent ),
2039
+ vertex.dot( normalBitangent )
2040
+ );
2041
+
2042
+ }
2043
+
1970
2044
  // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
1971
2045
  genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) {
1972
2046
 
1973
- for ( let i = 2; i < faceLength; i ++ ) {
2047
+ let triangles;
2048
+
2049
+ if ( faceLength > 3 ) {
2050
+
2051
+ // Triangulate n-gon using earcut
1974
2052
 
1975
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 0 ] ] );
1976
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 1 ] ] );
1977
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 2 ] ] );
2053
+ const vertices = [];
1978
2054
 
1979
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 ] ] );
1980
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 1 ] ] );
1981
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 2 ] ] );
2055
+ for ( let i = 0; i < facePositionIndexes.length; i += 3 ) {
2056
+
2057
+ vertices.push( new Vector3(
2058
+ geoInfo.vertexPositions[ facePositionIndexes[ i ] ],
2059
+ geoInfo.vertexPositions[ facePositionIndexes[ i + 1 ] ],
2060
+ geoInfo.vertexPositions[ facePositionIndexes[ i + 2 ] ]
2061
+ ) );
2062
+
2063
+ }
1982
2064
 
1983
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 ] ] );
1984
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 1 ] ] );
1985
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 2 ] ] );
2065
+ const { tangent, bitangent } = this.getNormalTangentAndBitangent( vertices );
2066
+ const triangulationInput = [];
2067
+
2068
+ for ( const vertex of vertices ) {
2069
+
2070
+ triangulationInput.push( this.flattenVertex( vertex, tangent, bitangent ) );
2071
+
2072
+ }
2073
+
2074
+ triangles = ShapeUtils.triangulateShape( triangulationInput, [] );
2075
+
2076
+ } else {
2077
+
2078
+ // Regular triangle, skip earcut triangulation step
2079
+ triangles = [[ 0, 1, 2 ]];
2080
+
2081
+ }
2082
+
2083
+ for ( const [ i0, i1, i2 ] of triangles ) {
2084
+
2085
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i0 * 3 ] ] );
2086
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i0 * 3 + 1 ] ] );
2087
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i0 * 3 + 2 ] ] );
2088
+
2089
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i1 * 3 ] ] );
2090
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i1 * 3 + 1 ] ] );
2091
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i1 * 3 + 2 ] ] );
2092
+
2093
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i2 * 3 ] ] );
2094
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i2 * 3 + 1 ] ] );
2095
+ buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i2 * 3 + 2 ] ] );
1986
2096
 
1987
2097
  if ( geoInfo.skeleton ) {
1988
2098
 
1989
- buffers.vertexWeights.push( faceWeights[ 0 ] );
1990
- buffers.vertexWeights.push( faceWeights[ 1 ] );
1991
- buffers.vertexWeights.push( faceWeights[ 2 ] );
1992
- buffers.vertexWeights.push( faceWeights[ 3 ] );
2099
+ buffers.vertexWeights.push( faceWeights[ i0 * 4 ] );
2100
+ buffers.vertexWeights.push( faceWeights[ i0 * 4 + 1 ] );
2101
+ buffers.vertexWeights.push( faceWeights[ i0 * 4 + 2 ] );
2102
+ buffers.vertexWeights.push( faceWeights[ i0 * 4 + 3 ] );
1993
2103
 
1994
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 ] );
1995
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 1 ] );
1996
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 2 ] );
1997
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 3 ] );
2104
+ buffers.vertexWeights.push( faceWeights[ i1 * 4 ] );
2105
+ buffers.vertexWeights.push( faceWeights[ i1 * 4 + 1 ] );
2106
+ buffers.vertexWeights.push( faceWeights[ i1 * 4 + 2 ] );
2107
+ buffers.vertexWeights.push( faceWeights[ i1 * 4 + 3 ] );
1998
2108
 
1999
- buffers.vertexWeights.push( faceWeights[ i * 4 ] );
2000
- buffers.vertexWeights.push( faceWeights[ i * 4 + 1 ] );
2001
- buffers.vertexWeights.push( faceWeights[ i * 4 + 2 ] );
2002
- buffers.vertexWeights.push( faceWeights[ i * 4 + 3 ] );
2109
+ buffers.vertexWeights.push( faceWeights[ i2 * 4 ] );
2110
+ buffers.vertexWeights.push( faceWeights[ i2 * 4 + 1 ] );
2111
+ buffers.vertexWeights.push( faceWeights[ i2 * 4 + 2 ] );
2112
+ buffers.vertexWeights.push( faceWeights[ i2 * 4 + 3 ] );
2003
2113
 
2004
- buffers.weightsIndices.push( faceWeightIndices[ 0 ] );
2005
- buffers.weightsIndices.push( faceWeightIndices[ 1 ] );
2006
- buffers.weightsIndices.push( faceWeightIndices[ 2 ] );
2007
- buffers.weightsIndices.push( faceWeightIndices[ 3 ] );
2114
+ buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 ] );
2115
+ buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 + 1 ] );
2116
+ buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 + 2 ] );
2117
+ buffers.weightsIndices.push( faceWeightIndices[ i0 * 4 + 3 ] );
2008
2118
 
2009
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 ] );
2010
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 1 ] );
2011
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 2 ] );
2012
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 3 ] );
2119
+ buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 ] );
2120
+ buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 + 1 ] );
2121
+ buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 + 2 ] );
2122
+ buffers.weightsIndices.push( faceWeightIndices[ i1 * 4 + 3 ] );
2013
2123
 
2014
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 ] );
2015
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 1 ] );
2016
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 2 ] );
2017
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 3 ] );
2124
+ buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 ] );
2125
+ buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 + 1 ] );
2126
+ buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 + 2 ] );
2127
+ buffers.weightsIndices.push( faceWeightIndices[ i2 * 4 + 3 ] );
2018
2128
 
2019
2129
  }
2020
2130
 
2021
2131
  if ( geoInfo.color ) {
2022
2132
 
2023
- buffers.colors.push( faceColors[ 0 ] );
2024
- buffers.colors.push( faceColors[ 1 ] );
2025
- buffers.colors.push( faceColors[ 2 ] );
2133
+ buffers.colors.push( faceColors[ i0 * 3 ] );
2134
+ buffers.colors.push( faceColors[ i0 * 3 + 1 ] );
2135
+ buffers.colors.push( faceColors[ i0 * 3 + 2 ] );
2026
2136
 
2027
- buffers.colors.push( faceColors[ ( i - 1 ) * 3 ] );
2028
- buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 1 ] );
2029
- buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 2 ] );
2137
+ buffers.colors.push( faceColors[ i1 * 3 ] );
2138
+ buffers.colors.push( faceColors[ i1 * 3 + 1 ] );
2139
+ buffers.colors.push( faceColors[ i1 * 3 + 2 ] );
2030
2140
 
2031
- buffers.colors.push( faceColors[ i * 3 ] );
2032
- buffers.colors.push( faceColors[ i * 3 + 1 ] );
2033
- buffers.colors.push( faceColors[ i * 3 + 2 ] );
2141
+ buffers.colors.push( faceColors[ i2 * 3 ] );
2142
+ buffers.colors.push( faceColors[ i2 * 3 + 1 ] );
2143
+ buffers.colors.push( faceColors[ i2 * 3 + 2 ] );
2034
2144
 
2035
2145
  }
2036
2146
 
@@ -2044,17 +2154,17 @@ class GeometryParser {
2044
2154
 
2045
2155
  if ( geoInfo.normal ) {
2046
2156
 
2047
- buffers.normal.push( faceNormals[ 0 ] );
2048
- buffers.normal.push( faceNormals[ 1 ] );
2049
- buffers.normal.push( faceNormals[ 2 ] );
2157
+ buffers.normal.push( faceNormals[ i0 * 3 ] );
2158
+ buffers.normal.push( faceNormals[ i0 * 3 + 1 ] );
2159
+ buffers.normal.push( faceNormals[ i0 * 3 + 2 ] );
2050
2160
 
2051
- buffers.normal.push( faceNormals[ ( i - 1 ) * 3 ] );
2052
- buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 1 ] );
2053
- buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 2 ] );
2161
+ buffers.normal.push( faceNormals[ i1 * 3 ] );
2162
+ buffers.normal.push( faceNormals[ i1 * 3 + 1 ] );
2163
+ buffers.normal.push( faceNormals[ i1 * 3 + 2 ] );
2054
2164
 
2055
- buffers.normal.push( faceNormals[ i * 3 ] );
2056
- buffers.normal.push( faceNormals[ i * 3 + 1 ] );
2057
- buffers.normal.push( faceNormals[ i * 3 + 2 ] );
2165
+ buffers.normal.push( faceNormals[ i2 * 3 ] );
2166
+ buffers.normal.push( faceNormals[ i2 * 3 + 1 ] );
2167
+ buffers.normal.push( faceNormals[ i2 * 3 + 2 ] );
2058
2168
 
2059
2169
  }
2060
2170
 
@@ -2064,14 +2174,14 @@ class GeometryParser {
2064
2174
 
2065
2175
  if ( buffers.uvs[ j ] === undefined ) buffers.uvs[ j ] = [];
2066
2176
 
2067
- buffers.uvs[ j ].push( faceUVs[ j ][ 0 ] );
2068
- buffers.uvs[ j ].push( faceUVs[ j ][ 1 ] );
2177
+ buffers.uvs[ j ].push( faceUVs[ j ][ i0 * 2 ] );
2178
+ buffers.uvs[ j ].push( faceUVs[ j ][ i0 * 2 + 1 ] );
2069
2179
 
2070
- buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 ] );
2071
- buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 + 1 ] );
2180
+ buffers.uvs[ j ].push( faceUVs[ j ][ i1 * 2 ] );
2181
+ buffers.uvs[ j ].push( faceUVs[ j ][ i1 * 2 + 1 ] );
2072
2182
 
2073
- buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 ] );
2074
- buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 + 1 ] );
2183
+ buffers.uvs[ j ].push( faceUVs[ j ][ i2 * 2 ] );
2184
+ buffers.uvs[ j ].push( faceUVs[ j ][ i2 * 2 + 1 ] );
2075
2185
 
2076
2186
  } );
2077
2187
 
@@ -2648,13 +2758,11 @@ class AnimationParser {
2648
2758
  const tracks = [];
2649
2759
 
2650
2760
  let initialPosition = new Vector3();
2651
- let initialRotation = new Quaternion();
2652
2761
  let initialScale = new Vector3();
2653
2762
 
2654
- if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition, initialRotation, initialScale );
2763
+ if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition, new Quaternion(), initialScale );
2655
2764
 
2656
2765
  initialPosition = initialPosition.toArray();
2657
- initialRotation = new Euler().setFromQuaternion( initialRotation, rawTracks.eulerOrder ).toArray();
2658
2766
  initialScale = initialScale.toArray();
2659
2767
 
2660
2768
  if ( rawTracks.T !== undefined && Object.keys( rawTracks.T.curves ).length > 0 ) {
@@ -2666,7 +2774,7 @@ class AnimationParser {
2666
2774
 
2667
2775
  if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) {
2668
2776
 
2669
- const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, initialRotation, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder );
2777
+ const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder );
2670
2778
  if ( rotationTrack !== undefined ) tracks.push( rotationTrack );
2671
2779
 
2672
2780
  }
@@ -2698,32 +2806,20 @@ class AnimationParser {
2698
2806
 
2699
2807
  }
2700
2808
 
2701
- generateRotationTrack( modelName, curves, initialValue, preRotation, postRotation, eulerOrder ) {
2702
-
2703
- if ( curves.x !== undefined ) {
2809
+ generateRotationTrack( modelName, curves, preRotation, postRotation, eulerOrder ) {
2704
2810
 
2705
- this.interpolateRotations( curves.x );
2706
- curves.x.values = curves.x.values.map( MathUtils.degToRad );
2707
-
2708
- }
2811
+ let times;
2812
+ let values;
2709
2813
 
2710
- if ( curves.y !== undefined ) {
2711
-
2712
- this.interpolateRotations( curves.y );
2713
- curves.y.values = curves.y.values.map( MathUtils.degToRad );
2714
-
2715
- }
2814
+ if ( curves.x !== undefined && curves.y !== undefined && curves.z !== undefined ) {
2716
2815
 
2717
- if ( curves.z !== undefined ) {
2816
+ const result = this.interpolateRotations( curves.x, curves.y, curves.z, eulerOrder );
2718
2817
 
2719
- this.interpolateRotations( curves.z );
2720
- curves.z.values = curves.z.values.map( MathUtils.degToRad );
2818
+ times = result[ 0 ];
2819
+ values = result[ 1 ];
2721
2820
 
2722
2821
  }
2723
2822
 
2724
- const times = this.getTimesForAllAxes( curves );
2725
- const values = this.getKeyframeTrackValues( times, curves, initialValue );
2726
-
2727
2823
  if ( preRotation !== undefined ) {
2728
2824
 
2729
2825
  preRotation = preRotation.map( MathUtils.degToRad );
@@ -2749,15 +2845,32 @@ class AnimationParser {
2749
2845
 
2750
2846
  const quaternionValues = [];
2751
2847
 
2848
+ if ( ! values || ! times ) return new QuaternionKeyframeTrack( modelName + '.quaternion', [], [] );
2849
+
2752
2850
  for ( let i = 0; i < values.length; i += 3 ) {
2753
2851
 
2754
2852
  euler.set( values[ i ], values[ i + 1 ], values[ i + 2 ], eulerOrder );
2755
-
2756
2853
  quaternion.setFromEuler( euler );
2757
2854
 
2758
2855
  if ( preRotation !== undefined ) quaternion.premultiply( preRotation );
2759
2856
  if ( postRotation !== undefined ) quaternion.multiply( postRotation );
2760
2857
 
2858
+ // Check unroll
2859
+ if ( i > 2 ) {
2860
+
2861
+ const prevQuat = new Quaternion().fromArray(
2862
+ quaternionValues,
2863
+ ( ( i - 3 ) / 3 ) * 4
2864
+ );
2865
+
2866
+ if ( prevQuat.dot( quaternion ) < 0 ) {
2867
+
2868
+ quaternion.set( - quaternion.x, - quaternion.y, - quaternion.z, - quaternion.w );
2869
+
2870
+ }
2871
+
2872
+ }
2873
+
2761
2874
  quaternion.toArray( quaternionValues, ( i / 3 ) * 4 );
2762
2875
 
2763
2876
  }
@@ -2888,47 +3001,110 @@ class AnimationParser {
2888
3001
  // Rotations are defined as Euler angles which can have values of any size
2889
3002
  // These will be converted to quaternions which don't support values greater than
2890
3003
  // PI, so we'll interpolate large rotations
2891
- interpolateRotations( curve ) {
3004
+ interpolateRotations( curvex, curvey, curvez, eulerOrder ) {
2892
3005
 
2893
- for ( let i = 1; i < curve.values.length; i ++ ) {
3006
+ const times = [];
3007
+ const values = [];
3008
+
3009
+ // Add first frame
3010
+ times.push( curvex.times[ 0 ] );
3011
+ values.push( MathUtils.degToRad( curvex.values[ 0 ] ) );
3012
+ values.push( MathUtils.degToRad( curvey.values[ 0 ] ) );
3013
+ values.push( MathUtils.degToRad( curvez.values[ 0 ] ) );
3014
+
3015
+ for ( let i = 1; i < curvex.values.length; i ++ ) {
3016
+
3017
+ const initialValue = [
3018
+ curvex.values[ i - 1 ],
3019
+ curvey.values[ i - 1 ],
3020
+ curvez.values[ i - 1 ],
3021
+ ];
3022
+
3023
+ if ( isNaN( initialValue[ 0 ] ) || isNaN( initialValue[ 1 ] ) || isNaN( initialValue[ 2 ] ) ) {
3024
+
3025
+ continue;
3026
+
3027
+ }
3028
+
3029
+ const initialValueRad = initialValue.map( MathUtils.degToRad );
3030
+
3031
+ const currentValue = [
3032
+ curvex.values[ i ],
3033
+ curvey.values[ i ],
3034
+ curvez.values[ i ],
3035
+ ];
3036
+
3037
+ if ( isNaN( currentValue[ 0 ] ) || isNaN( currentValue[ 1 ] ) || isNaN( currentValue[ 2 ] ) ) {
3038
+
3039
+ continue;
3040
+
3041
+ }
2894
3042
 
2895
- const initialValue = curve.values[ i - 1 ];
2896
- const valuesSpan = curve.values[ i ] - initialValue;
3043
+ const currentValueRad = currentValue.map( MathUtils.degToRad );
2897
3044
 
2898
- const absoluteSpan = Math.abs( valuesSpan );
3045
+ const valuesSpan = [
3046
+ currentValue[ 0 ] - initialValue[ 0 ],
3047
+ currentValue[ 1 ] - initialValue[ 1 ],
3048
+ currentValue[ 2 ] - initialValue[ 2 ],
3049
+ ];
2899
3050
 
2900
- if ( absoluteSpan >= 180 ) {
3051
+ const absoluteSpan = [
3052
+ Math.abs( valuesSpan[ 0 ] ),
3053
+ Math.abs( valuesSpan[ 1 ] ),
3054
+ Math.abs( valuesSpan[ 2 ] ),
3055
+ ];
2901
3056
 
2902
- const numSubIntervals = absoluteSpan / 180;
3057
+ if ( absoluteSpan[ 0 ] >= 180 || absoluteSpan[ 1 ] >= 180 || absoluteSpan[ 2 ] >= 180 ) {
2903
3058
 
2904
- const step = valuesSpan / numSubIntervals;
2905
- let nextValue = initialValue + step;
3059
+ const maxAbsSpan = Math.max( ...absoluteSpan );
2906
3060
 
2907
- const initialTime = curve.times[ i - 1 ];
2908
- const timeSpan = curve.times[ i ] - initialTime;
2909
- const interval = timeSpan / numSubIntervals;
2910
- let nextTime = initialTime + interval;
3061
+ const numSubIntervals = maxAbsSpan / 180;
2911
3062
 
2912
- const interpolatedTimes = [];
2913
- const interpolatedValues = [];
3063
+ const E1 = new Euler( ...initialValueRad, eulerOrder );
3064
+ const E2 = new Euler( ...currentValueRad, eulerOrder );
2914
3065
 
2915
- while ( nextTime < curve.times[ i ] ) {
3066
+ const Q1 = new Quaternion().setFromEuler( E1 );
3067
+ const Q2 = new Quaternion().setFromEuler( E2 );
2916
3068
 
2917
- interpolatedTimes.push( nextTime );
2918
- nextTime += interval;
3069
+ // Check unroll
3070
+ if ( Q1.dot( Q2 ) ) {
2919
3071
 
2920
- interpolatedValues.push( nextValue );
2921
- nextValue += step;
3072
+ Q2.set( - Q2.x, - Q2.y, - Q2.z, - Q2.w );
2922
3073
 
2923
3074
  }
2924
3075
 
2925
- curve.times = inject( curve.times, i, interpolatedTimes );
2926
- curve.values = inject( curve.values, i, interpolatedValues );
3076
+ // Interpolate
3077
+ const initialTime = curvex.times[ i - 1 ];
3078
+ const timeSpan = curvex.times[ i ] - initialTime;
3079
+
3080
+ const Q = new Quaternion();
3081
+ const E = new Euler();
3082
+ for ( let t = 0; t < 1; t += 1 / numSubIntervals ) {
3083
+
3084
+ Q.copy( Q1.clone().slerp( Q2.clone(), t ) );
3085
+
3086
+ times.push( initialTime + t * timeSpan );
3087
+ E.setFromQuaternion( Q, eulerOrder );
3088
+
3089
+ values.push( E.x );
3090
+ values.push( E.y );
3091
+ values.push( E.z );
3092
+
3093
+ }
3094
+
3095
+ } else {
3096
+
3097
+ times.push( curvex.times[ i ] );
3098
+ values.push( MathUtils.degToRad( curvex.values[ i ] ) );
3099
+ values.push( MathUtils.degToRad( curvey.values[ i ] ) );
3100
+ values.push( MathUtils.degToRad( curvez.values[ i ] ) );
2927
3101
 
2928
3102
  }
2929
3103
 
2930
3104
  }
2931
3105
 
3106
+ return [ times, values ];
3107
+
2932
3108
  }
2933
3109
 
2934
3110
  }
@@ -4134,11 +4310,5 @@ function slice( a, b, from, to ) {
4134
4310
 
4135
4311
  }
4136
4312
 
4137
- // inject array a2 into array a1 at index
4138
- function inject( a1, index, a2 ) {
4139
-
4140
- return a1.slice( 0, index ).concat( a2 ).concat( a1.slice( index ) );
4141
-
4142
- }
4143
4313
 
4144
4314
  export { FBXLoader };