@needle-tools/three 0.146.10 → 0.153.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 (865) hide show
  1. package/LICENSE +1 -1
  2. package/build/three.cjs +39486 -20286
  3. package/build/three.js +39471 -20270
  4. package/build/three.min.js +3 -2
  5. package/build/three.module.js +6717 -5427
  6. package/build/three.module.min.js +6 -0
  7. package/examples/jsm/animation/AnimationClipCreator.js +5 -3
  8. package/examples/jsm/cameras/CinematicCamera.js +1 -2
  9. package/examples/jsm/capabilities/WebGPU.js +17 -5
  10. package/examples/jsm/controls/ArcballControls.js +1828 -1821
  11. package/examples/jsm/controls/MapControls.js +28 -0
  12. package/examples/jsm/controls/OrbitControls.js +26 -53
  13. package/examples/jsm/controls/PointerLockControls.js +70 -65
  14. package/examples/jsm/controls/TrackballControls.js +18 -4
  15. package/examples/jsm/controls/TransformControls.js +0 -1
  16. package/examples/jsm/csm/CSM.js +11 -5
  17. package/examples/jsm/csm/CSMShader.js +7 -6
  18. package/examples/jsm/effects/AnaglyphEffect.js +6 -20
  19. package/examples/jsm/effects/AsciiEffect.js +3 -6
  20. package/examples/jsm/effects/OutlineEffect.js +1 -15
  21. package/examples/jsm/effects/ParallaxBarrierEffect.js +3 -0
  22. package/examples/jsm/exporters/DRACOExporter.js +53 -11
  23. package/examples/jsm/exporters/EXRExporter.js +3 -9
  24. package/examples/jsm/exporters/GLTFExporter.js +561 -154
  25. package/examples/jsm/exporters/KTX2Exporter.js +34 -23
  26. package/examples/jsm/exporters/MMDExporter.js +1 -1
  27. package/examples/jsm/exporters/PLYExporter.js +8 -1
  28. package/examples/jsm/exporters/STLExporter.js +8 -4
  29. package/examples/jsm/exporters/USDZExporter.js +305 -792
  30. package/examples/jsm/geometries/ConvexGeometry.js +0 -6
  31. package/examples/jsm/geometries/ParametricGeometry.js +10 -0
  32. package/examples/jsm/helpers/OctreeHelper.js +1 -0
  33. package/examples/jsm/helpers/ViewHelper.js +71 -57
  34. package/examples/jsm/interactive/HTMLMesh.js +16 -3
  35. package/examples/jsm/interactive/InteractiveGroup.js +1 -1
  36. package/examples/{js → jsm}/libs/basis/README.md +4 -4
  37. package/examples/jsm/libs/draco/draco_decoder.js +34 -0
  38. package/examples/jsm/libs/draco/draco_decoder.wasm +0 -0
  39. package/examples/jsm/libs/draco/draco_wasm_wrapper.js +117 -0
  40. package/examples/jsm/libs/draco/gltf/draco_decoder.js +33 -0
  41. package/examples/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
  42. package/examples/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
  43. package/examples/jsm/libs/lil-gui.module.min.js +2 -2
  44. package/examples/jsm/libs/tween.module.js +803 -0
  45. package/examples/jsm/lights/IESSpotLight.js +25 -0
  46. package/examples/jsm/lights/LightProbeGenerator.js +11 -9
  47. package/examples/jsm/lines/LineSegments2.js +16 -10
  48. package/examples/jsm/loaders/3DMLoader.js +8 -5
  49. package/examples/jsm/loaders/3MFLoader.js +12 -11
  50. package/examples/jsm/loaders/AMFLoader.js +2 -3
  51. package/examples/jsm/loaders/BVHLoader.js +2 -2
  52. package/examples/jsm/loaders/ColladaLoader.js +15 -16
  53. package/examples/jsm/loaders/DRACOLoader.js +69 -18
  54. package/examples/jsm/loaders/EXRLoader.js +23 -24
  55. package/examples/jsm/loaders/FBXLoader.js +34 -50
  56. package/examples/jsm/loaders/GCodeLoader.js +1 -2
  57. package/examples/jsm/loaders/GLTFLoader.js +417 -895
  58. package/examples/jsm/loaders/GLTFLoaderAnimationPointer.js +684 -0
  59. package/examples/jsm/loaders/HDRCubeTextureLoader.js +4 -4
  60. package/examples/jsm/loaders/IESLoader.js +337 -0
  61. package/examples/jsm/loaders/KMZLoader.js +4 -4
  62. package/examples/jsm/loaders/KTX2Loader.js +145 -69
  63. package/examples/jsm/loaders/LDrawLoader.js +20 -18
  64. package/examples/jsm/loaders/LWOLoader.js +12 -29
  65. package/examples/jsm/loaders/LottieLoader.js +3 -1
  66. package/examples/jsm/loaders/MMDLoader.js +49 -18
  67. package/examples/jsm/loaders/MTLLoader.js +2 -2
  68. package/examples/jsm/loaders/MaterialXLoader.js +9 -3
  69. package/examples/jsm/loaders/NRRDLoader.js +33 -5
  70. package/examples/jsm/loaders/OBJLoader.js +1 -1
  71. package/examples/jsm/loaders/PCDLoader.js +26 -12
  72. package/examples/jsm/loaders/PDBLoader.js +7 -2
  73. package/examples/jsm/loaders/PLYLoader.js +254 -109
  74. package/examples/jsm/loaders/RGBELoader.js +3 -3
  75. package/examples/jsm/loaders/STLLoader.js +9 -5
  76. package/examples/jsm/loaders/SVGLoader.js +36 -27
  77. package/examples/jsm/loaders/TTFLoader.js +1 -8
  78. package/examples/jsm/loaders/TiltLoader.js +13 -7
  79. package/examples/jsm/loaders/USDZLoader.js +6 -6
  80. package/examples/jsm/loaders/VOXLoader.js +8 -2
  81. package/examples/jsm/loaders/VRMLLoader.js +44 -16
  82. package/examples/jsm/loaders/VTKLoader.js +19 -10
  83. package/examples/jsm/loaders/XYZLoader.js +9 -3
  84. package/examples/jsm/loaders/lwo/IFFParser.js +19 -19
  85. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -3
  86. package/examples/jsm/math/ConvexHull.js +3 -3
  87. package/examples/jsm/math/Lut.js +5 -4
  88. package/examples/jsm/math/MeshSurfaceSampler.js +7 -9
  89. package/examples/jsm/math/Octree.js +1 -1
  90. package/examples/jsm/misc/ConvexObjectBreaker.js +2 -8
  91. package/examples/jsm/misc/GPUComputationRenderer.js +6 -5
  92. package/examples/jsm/misc/MD2Character.js +2 -2
  93. package/examples/jsm/misc/MD2CharacterComplex.js +2 -2
  94. package/examples/jsm/misc/ProgressiveLightMap.js +12 -10
  95. package/examples/jsm/misc/RollerCoaster.js +7 -1
  96. package/examples/jsm/misc/Volume.js +20 -5
  97. package/examples/jsm/misc/VolumeSlice.js +3 -1
  98. package/examples/jsm/modifiers/CurveModifier.js +1 -0
  99. package/examples/jsm/modifiers/TessellateModifier.js +19 -19
  100. package/examples/jsm/nodes/Nodes.js +144 -335
  101. package/examples/jsm/nodes/accessors/BitangentNode.js +43 -16
  102. package/examples/jsm/nodes/accessors/BufferAttributeNode.js +86 -0
  103. package/examples/jsm/nodes/accessors/BufferNode.js +6 -0
  104. package/examples/jsm/nodes/accessors/CameraNode.js +12 -2
  105. package/examples/jsm/nodes/accessors/CubeTextureNode.js +27 -33
  106. package/examples/jsm/nodes/accessors/ExtendedMaterialNode.js +58 -0
  107. package/examples/jsm/nodes/accessors/InstanceNode.js +41 -26
  108. package/examples/jsm/nodes/accessors/MaterialNode.js +155 -38
  109. package/examples/jsm/nodes/accessors/MaterialReferenceNode.js +16 -0
  110. package/examples/jsm/nodes/accessors/ModelNode.js +11 -0
  111. package/examples/jsm/nodes/accessors/ModelViewProjectionNode.js +13 -14
  112. package/examples/jsm/nodes/accessors/NormalNode.js +35 -19
  113. package/examples/jsm/nodes/accessors/Object3DNode.js +32 -12
  114. package/examples/jsm/nodes/accessors/PointUVNode.js +6 -1
  115. package/examples/jsm/nodes/accessors/PositionNode.js +38 -23
  116. package/examples/jsm/nodes/accessors/ReferenceNode.js +21 -14
  117. package/examples/jsm/nodes/accessors/ReflectVectorNode.js +11 -7
  118. package/examples/jsm/nodes/accessors/SkinningNode.js +43 -40
  119. package/examples/jsm/nodes/accessors/StorageBufferNode.js +6 -0
  120. package/examples/jsm/nodes/accessors/TangentNode.js +28 -20
  121. package/examples/jsm/nodes/accessors/TextureNode.js +80 -12
  122. package/examples/jsm/nodes/accessors/UVNode.js +6 -0
  123. package/examples/jsm/nodes/accessors/UserDataNode.js +6 -0
  124. package/examples/jsm/nodes/code/CodeNode.js +75 -0
  125. package/examples/jsm/nodes/code/ExpressionNode.js +37 -0
  126. package/examples/jsm/nodes/{core → code}/FunctionCallNode.js +15 -1
  127. package/examples/jsm/nodes/{core → code}/FunctionNode.js +8 -7
  128. package/examples/jsm/nodes/code/ScriptableNode.js +488 -0
  129. package/examples/jsm/nodes/code/ScriptableValueNode.js +167 -0
  130. package/examples/jsm/nodes/core/ArrayUniformNode.js +3 -0
  131. package/examples/jsm/nodes/core/AttributeNode.js +17 -9
  132. package/examples/jsm/nodes/core/BypassNode.js +9 -2
  133. package/examples/jsm/nodes/core/CacheNode.js +46 -0
  134. package/examples/jsm/nodes/core/ConstNode.js +3 -0
  135. package/examples/jsm/nodes/core/ContextNode.js +8 -1
  136. package/examples/jsm/nodes/core/InputNode.js +26 -5
  137. package/examples/jsm/nodes/core/InstanceIndexNode.js +26 -2
  138. package/examples/jsm/nodes/core/LightingModel.js +16 -0
  139. package/examples/jsm/nodes/core/Node.js +129 -35
  140. package/examples/jsm/nodes/core/NodeAttribute.js +2 -1
  141. package/examples/jsm/nodes/core/NodeBuilder.js +271 -121
  142. package/examples/jsm/nodes/core/NodeCache.js +26 -0
  143. package/examples/jsm/nodes/core/NodeFrame.js +56 -5
  144. package/examples/jsm/nodes/core/NodeUtils.js +115 -28
  145. package/examples/jsm/nodes/core/PropertyNode.js +19 -2
  146. package/examples/jsm/nodes/core/StackNode.js +99 -0
  147. package/examples/jsm/nodes/core/TempNode.js +11 -3
  148. package/examples/jsm/nodes/core/UniformNode.js +16 -1
  149. package/examples/jsm/nodes/core/VarNode.js +21 -29
  150. package/examples/jsm/nodes/core/VaryingNode.js +15 -2
  151. package/examples/jsm/nodes/core/constants.js +6 -0
  152. package/examples/jsm/nodes/display/BlendModeNode.js +25 -11
  153. package/examples/jsm/nodes/display/ColorAdjustmentNode.js +30 -14
  154. package/examples/jsm/nodes/display/ColorSpaceNode.js +39 -27
  155. package/examples/jsm/nodes/display/FrontFacingNode.js +7 -1
  156. package/examples/jsm/nodes/display/NormalMapNode.js +31 -18
  157. package/examples/jsm/nodes/display/PosterizeNode.js +10 -3
  158. package/examples/jsm/nodes/display/ToneMappingNode.js +101 -11
  159. package/examples/jsm/nodes/display/ViewportNode.js +27 -18
  160. package/examples/jsm/nodes/display/ViewportSharedTextureNode.js +30 -0
  161. package/examples/jsm/nodes/display/ViewportTextureNode.js +67 -0
  162. package/examples/jsm/nodes/fog/FogExp2Node.js +35 -0
  163. package/examples/jsm/nodes/fog/FogNode.js +12 -6
  164. package/examples/jsm/nodes/fog/FogRangeNode.js +12 -5
  165. package/examples/jsm/nodes/functions/BSDF/BRDF_BlinnPhong.js +30 -0
  166. package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +10 -13
  167. package/examples/jsm/nodes/functions/BSDF/BRDF_Lambert.js +2 -2
  168. package/examples/jsm/nodes/functions/BSDF/DFGApprox.js +8 -6
  169. package/examples/jsm/nodes/functions/BSDF/D_GGX.js +4 -4
  170. package/examples/jsm/nodes/functions/BSDF/F_Schlick.js +3 -3
  171. package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +7 -5
  172. package/examples/jsm/nodes/functions/PhongLightingModel.js +28 -0
  173. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +35 -36
  174. package/examples/jsm/nodes/functions/material/getGeometryRoughness.js +4 -3
  175. package/examples/jsm/nodes/functions/material/getRoughness.js +4 -4
  176. package/examples/jsm/nodes/geometry/RangeNode.js +50 -55
  177. package/examples/jsm/nodes/gpgpu/ComputeNode.js +9 -2
  178. package/examples/jsm/nodes/lighting/AONode.js +5 -3
  179. package/examples/jsm/nodes/lighting/AmbientLightNode.js +27 -0
  180. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +114 -5
  181. package/examples/jsm/nodes/lighting/DirectionalLightNode.js +43 -0
  182. package/examples/jsm/nodes/lighting/EnvironmentNode.js +121 -35
  183. package/examples/jsm/nodes/lighting/HemisphereLightNode.js +15 -10
  184. package/examples/jsm/nodes/lighting/IESSpotLightNode.js +39 -0
  185. package/examples/jsm/nodes/lighting/LightNode.js +57 -0
  186. package/examples/jsm/nodes/lighting/LightUtils.js +17 -0
  187. package/examples/jsm/nodes/lighting/LightingContextNode.js +30 -8
  188. package/examples/jsm/nodes/lighting/LightingNode.js +3 -1
  189. package/examples/jsm/nodes/lighting/LightsNode.js +18 -10
  190. package/examples/jsm/nodes/lighting/PointLightNode.js +71 -0
  191. package/examples/jsm/nodes/lighting/SpotLightNode.js +92 -0
  192. package/examples/jsm/nodes/loaders/NodeLoader.js +5 -4
  193. package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +4 -20
  194. package/examples/jsm/nodes/materials/LineBasicNodeMaterial.js +6 -9
  195. package/examples/jsm/nodes/materials/Materials.js +11 -55
  196. package/examples/jsm/nodes/materials/MeshBasicNodeMaterial.js +5 -11
  197. package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +48 -0
  198. package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +74 -0
  199. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +6 -6
  200. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +21 -96
  201. package/examples/jsm/nodes/materials/NodeMaterial.js +284 -62
  202. package/examples/jsm/nodes/materials/PointsNodeMaterial.js +7 -1
  203. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +29 -25
  204. package/examples/jsm/nodes/materialx/MaterialXNodes.js +31 -22
  205. package/examples/jsm/nodes/materialx/lib/mx_hsv.js +1 -1
  206. package/examples/jsm/nodes/materialx/lib/mx_noise.js +2 -1
  207. package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +2 -1
  208. package/examples/jsm/nodes/math/CondNode.js +43 -17
  209. package/examples/jsm/nodes/math/MathNode.js +178 -73
  210. package/examples/jsm/nodes/math/OperatorNode.js +52 -2
  211. package/examples/jsm/nodes/procedural/CheckerNode.js +14 -6
  212. package/examples/jsm/nodes/shadernode/ShaderNode.js +186 -63
  213. package/examples/jsm/nodes/utils/ArrayElementNode.js +4 -2
  214. package/examples/jsm/nodes/utils/ConvertNode.js +19 -1
  215. package/examples/jsm/nodes/utils/DiscardNode.js +26 -0
  216. package/examples/jsm/nodes/utils/EquirectUVNode.js +10 -4
  217. package/examples/jsm/nodes/utils/JoinNode.js +4 -1
  218. package/examples/jsm/nodes/utils/LoopNode.js +186 -0
  219. package/examples/jsm/nodes/utils/MatcapUVNode.js +11 -4
  220. package/examples/jsm/nodes/utils/MaxMipLevelNode.js +18 -5
  221. package/examples/jsm/nodes/utils/OscNode.js +21 -14
  222. package/examples/jsm/nodes/utils/PackingNode.js +55 -0
  223. package/examples/jsm/nodes/utils/RemapNode.js +13 -5
  224. package/examples/jsm/nodes/utils/RotateUVNode.js +18 -7
  225. package/examples/jsm/nodes/utils/SpecularMIPLevelNode.js +37 -0
  226. package/examples/jsm/nodes/utils/SplitNode.js +7 -5
  227. package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +15 -30
  228. package/examples/jsm/nodes/utils/TimerNode.js +16 -6
  229. package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +21 -10
  230. package/examples/jsm/objects/GroundProjectedSkybox.js +172 -0
  231. package/examples/jsm/objects/Lensflare.js +3 -4
  232. package/examples/jsm/objects/MarchingCubes.js +5 -1
  233. package/examples/jsm/objects/Reflector.js +7 -4
  234. package/examples/jsm/objects/Refractor.js +4 -4
  235. package/examples/jsm/objects/ShadowMesh.js +3 -3
  236. package/examples/jsm/objects/Water.js +2 -1
  237. package/examples/jsm/physics/AmmoPhysics.js +27 -28
  238. package/examples/jsm/physics/RapierPhysics.js +199 -0
  239. package/examples/jsm/postprocessing/AfterimagePass.js +3 -2
  240. package/examples/jsm/postprocessing/BloomPass.js +7 -4
  241. package/examples/jsm/postprocessing/BokehPass.js +3 -8
  242. package/examples/jsm/postprocessing/DotScreenPass.js +1 -2
  243. package/examples/jsm/postprocessing/EffectComposer.js +5 -95
  244. package/examples/jsm/postprocessing/FilmPass.js +1 -2
  245. package/examples/jsm/postprocessing/GlitchPass.js +0 -2
  246. package/examples/jsm/postprocessing/HalftonePass.js +0 -6
  247. package/examples/jsm/postprocessing/OutlinePass.js +7 -7
  248. package/examples/jsm/postprocessing/OutputPass.js +72 -0
  249. package/examples/jsm/postprocessing/Pass.js +2 -0
  250. package/examples/jsm/postprocessing/RenderPixelatedPass.js +4 -3
  251. package/examples/jsm/postprocessing/SAOPass.js +4 -26
  252. package/examples/jsm/postprocessing/SMAAPass.js +5 -8
  253. package/examples/jsm/postprocessing/SSAARenderPass.js +15 -6
  254. package/examples/jsm/postprocessing/SSAOPass.js +4 -14
  255. package/examples/jsm/postprocessing/SSRPass.js +3 -7
  256. package/examples/jsm/postprocessing/SavePass.js +2 -3
  257. package/examples/jsm/postprocessing/ShaderPass.js +1 -0
  258. package/examples/jsm/postprocessing/TAARenderPass.js +3 -2
  259. package/examples/jsm/postprocessing/TexturePass.js +0 -2
  260. package/examples/jsm/postprocessing/UnrealBloomPass.js +4 -11
  261. package/examples/jsm/renderers/CSS2DRenderer.js +6 -1
  262. package/examples/jsm/renderers/CSS3DRenderer.js +27 -5
  263. package/examples/jsm/renderers/{webgpu/WebGPUAnimation.js → common/Animation.js} +4 -4
  264. package/examples/jsm/renderers/common/Attributes.js +75 -0
  265. package/examples/jsm/renderers/common/Backend.js +160 -0
  266. package/examples/jsm/renderers/common/Background.js +133 -0
  267. package/examples/jsm/renderers/common/Binding.js +11 -0
  268. package/examples/jsm/renderers/common/Bindings.js +169 -0
  269. package/examples/jsm/renderers/common/Buffer.js +38 -0
  270. package/examples/jsm/renderers/{webgpu/WebGPUBufferUtils.js → common/BufferUtils.js} +2 -2
  271. package/examples/jsm/renderers/common/ChainMap.js +89 -0
  272. package/examples/jsm/renderers/common/ComputePipeline.js +17 -0
  273. package/examples/jsm/renderers/common/Constants.js +14 -0
  274. package/examples/jsm/renderers/common/CubeRenderTarget.js +65 -0
  275. package/examples/jsm/renderers/common/DataMap.js +54 -0
  276. package/examples/jsm/renderers/common/Geometries.js +215 -0
  277. package/examples/jsm/renderers/{webgpu/WebGPUInfo.js → common/Info.js} +2 -3
  278. package/examples/jsm/renderers/common/Pipeline.js +13 -0
  279. package/examples/jsm/renderers/common/Pipelines.js +309 -0
  280. package/examples/jsm/renderers/common/ProgrammableStage.js +18 -0
  281. package/examples/jsm/renderers/common/RenderContext.js +37 -0
  282. package/examples/jsm/renderers/common/RenderContexts.js +38 -0
  283. package/examples/jsm/renderers/{webgpu/WebGPURenderLists.js → common/RenderList.js} +26 -47
  284. package/examples/jsm/renderers/common/RenderLists.js +38 -0
  285. package/examples/jsm/renderers/common/RenderObject.js +95 -0
  286. package/examples/jsm/renderers/common/RenderObjects.js +92 -0
  287. package/examples/jsm/renderers/common/RenderPipeline.js +16 -0
  288. package/examples/jsm/renderers/common/RenderTarget.js +15 -0
  289. package/examples/jsm/renderers/common/Renderer.js +822 -0
  290. package/examples/jsm/renderers/common/SampledTexture.js +80 -0
  291. package/examples/jsm/renderers/common/Sampler.js +18 -0
  292. package/examples/jsm/renderers/common/StorageBuffer.js +17 -0
  293. package/examples/jsm/renderers/common/Textures.js +206 -0
  294. package/examples/jsm/renderers/{webgpu/WebGPUUniform.js → common/Uniform.js} +13 -9
  295. package/examples/jsm/renderers/common/UniformBuffer.js +15 -0
  296. package/examples/jsm/renderers/{webgpu/WebGPUUniformsGroup.js → common/UniformsGroup.js} +13 -13
  297. package/examples/jsm/renderers/common/nodes/NodeRender.js +302 -0
  298. package/examples/jsm/renderers/{webgpu/nodes/WebGPUNodeSampledTexture.js → common/nodes/NodeSampledTexture.js} +4 -4
  299. package/examples/jsm/renderers/{webgpu/nodes/WebGPUNodeSampler.js → common/nodes/NodeSampler.js} +3 -3
  300. package/examples/jsm/renderers/{webgpu/nodes/WebGPUNodeUniform.js → common/nodes/NodeUniform.js} +1 -1
  301. package/examples/jsm/renderers/common/nodes/Nodes.js +319 -0
  302. package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +35 -31
  303. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +765 -0
  304. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +15 -987
  305. package/examples/jsm/renderers/webgpu/nodes/{WebGPUNodeBuilder.js → WGSLNodeBuilder.js} +117 -90
  306. package/examples/jsm/{nodes/parsers → renderers/webgpu/nodes}/WGSLNodeFunction.js +2 -2
  307. package/examples/jsm/{nodes/parsers → renderers/webgpu/nodes}/WGSLNodeParser.js +1 -1
  308. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +251 -0
  309. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +145 -0
  310. package/examples/jsm/renderers/webgpu/{constants.js → utils/WebGPUConstants.js} +73 -12
  311. package/examples/jsm/renderers/webgpu/{WebGPURenderPipeline.js → utils/WebGPUPipelineUtils.js} +135 -285
  312. package/examples/jsm/renderers/webgpu/{WebGPUTextureUtils.js → utils/WebGPUTextureMipmapUtils.js} +5 -25
  313. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +855 -0
  314. package/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js +88 -0
  315. package/examples/jsm/shaders/BleachBypassShader.js +2 -0
  316. package/examples/jsm/shaders/BokehShader2.js +3 -0
  317. package/examples/jsm/shaders/ColorifyShader.js +2 -0
  318. package/examples/jsm/shaders/ConvolutionShader.js +2 -0
  319. package/examples/jsm/shaders/CopyShader.js +2 -0
  320. package/examples/jsm/shaders/DotScreenShader.js +2 -0
  321. package/examples/jsm/shaders/ExposureShader.js +44 -0
  322. package/examples/jsm/shaders/FilmShader.js +2 -0
  323. package/examples/jsm/shaders/GammaCorrectionShader.js +2 -0
  324. package/examples/jsm/shaders/HorizontalBlurShader.js +2 -0
  325. package/examples/jsm/shaders/MMDToonShader.js +15 -4
  326. package/examples/jsm/shaders/OutputShader.js +61 -0
  327. package/examples/jsm/shaders/RGBShiftShader.js +4 -2
  328. package/examples/jsm/shaders/SepiaShader.js +2 -0
  329. package/examples/jsm/shaders/ToonShader.js +13 -5
  330. package/examples/jsm/shaders/VelocityShader.js +1 -1
  331. package/examples/jsm/shaders/VerticalBlurShader.js +2 -0
  332. package/examples/jsm/shaders/VignetteShader.js +2 -0
  333. package/examples/jsm/shaders/WaterRefractionShader.js +5 -2
  334. package/examples/jsm/utils/BufferGeometryUtils.js +54 -36
  335. package/examples/jsm/utils/LDrawUtils.js +4 -4
  336. package/examples/jsm/utils/PackedPhongMaterial.js +5 -78
  337. package/examples/jsm/utils/SceneUtils.js +8 -4
  338. package/examples/jsm/utils/SkeletonUtils.js +27 -210
  339. package/examples/jsm/utils/TextureUtils.js +41 -40
  340. package/examples/jsm/webxr/VRButton.js +1 -2
  341. package/examples/jsm/webxr/XRButton.js +198 -0
  342. package/examples/jsm/webxr/XRHandPrimitiveModel.js +1 -0
  343. package/examples/jsm/webxr/XRPlanes.js +100 -0
  344. package/package.json +34 -87
  345. package/src/Three.Legacy.js +19 -110
  346. package/src/Three.js +4 -3
  347. package/src/animation/AnimationUtils.js +13 -1
  348. package/src/audio/Audio.js +7 -2
  349. package/src/audio/PositionalAudio.js +8 -0
  350. package/src/cameras/Camera.js +5 -0
  351. package/src/cameras/CubeCamera.js +76 -13
  352. package/src/cameras/OrthographicCamera.js +1 -1
  353. package/src/cameras/PerspectiveCamera.js +1 -1
  354. package/src/constants.js +22 -2
  355. package/src/core/BufferAttribute.js +150 -9
  356. package/src/core/BufferGeometry.js +4 -10
  357. package/src/core/GLBufferAttribute.js +2 -0
  358. package/src/core/InterleavedBufferAttribute.js +5 -5
  359. package/src/core/Object3D.js +37 -8
  360. package/src/extras/DataUtils.js +7 -1
  361. package/src/extras/ImageUtils.js +2 -2
  362. package/src/extras/PMREMGenerator.js +5 -5
  363. package/src/extras/core/Curve.js +1 -1
  364. package/src/extras/curves/LineCurve.js +6 -4
  365. package/src/extras/curves/LineCurve3.js +13 -0
  366. package/src/geometries/BoxGeometry.js +10 -0
  367. package/src/geometries/CircleGeometry.js +11 -1
  368. package/src/geometries/ConeGeometry.js +1 -1
  369. package/src/geometries/CylinderGeometry.js +11 -1
  370. package/src/geometries/EdgesGeometry.js +10 -0
  371. package/src/geometries/ExtrudeGeometry.js +11 -1
  372. package/src/geometries/LatheGeometry.js +10 -0
  373. package/src/geometries/PlaneGeometry.js +10 -0
  374. package/src/geometries/PolyhedronGeometry.js +11 -1
  375. package/src/geometries/RingGeometry.js +11 -1
  376. package/src/geometries/ShapeGeometry.js +11 -1
  377. package/src/geometries/SphereGeometry.js +12 -2
  378. package/src/geometries/TorusGeometry.js +11 -1
  379. package/src/geometries/TorusKnotGeometry.js +10 -0
  380. package/src/geometries/TubeGeometry.js +10 -0
  381. package/src/geometries/WireframeGeometry.js +10 -0
  382. package/src/helpers/Box3Helper.js +1 -2
  383. package/src/lights/DirectionalLight.js +1 -1
  384. package/src/lights/HemisphereLight.js +1 -1
  385. package/src/lights/SpotLight.js +1 -1
  386. package/src/loaders/AudioLoader.js +14 -8
  387. package/src/loaders/CubeTextureLoader.js +2 -0
  388. package/src/loaders/DataTextureLoader.js +5 -1
  389. package/src/loaders/MaterialLoader.js +8 -0
  390. package/src/loaders/ObjectLoader.js +10 -2
  391. package/src/materials/LineBasicMaterial.js +4 -0
  392. package/src/materials/Material.js +16 -4
  393. package/src/materials/MeshDistanceMaterial.js +0 -9
  394. package/src/materials/MeshPhysicalMaterial.js +32 -6
  395. package/src/materials/ShaderMaterial.js +6 -1
  396. package/src/math/Box2.js +3 -2
  397. package/src/math/Box3.js +49 -64
  398. package/src/math/Color.js +88 -66
  399. package/src/math/ColorManagement.js +75 -16
  400. package/src/math/Euler.js +2 -11
  401. package/src/math/Frustum.js +29 -5
  402. package/src/math/MathUtils.js +43 -1
  403. package/src/math/Matrix3.js +26 -6
  404. package/src/math/Matrix4.js +74 -19
  405. package/src/math/Plane.js +2 -2
  406. package/src/math/Quaternion.js +6 -0
  407. package/src/math/Ray.js +7 -7
  408. package/src/math/Triangle.js +37 -7
  409. package/src/math/Vector2.js +16 -0
  410. package/src/math/Vector3.js +10 -0
  411. package/src/math/interpolants/CubicInterpolant.js +1 -2
  412. package/src/objects/InstancedMesh.js +82 -1
  413. package/src/objects/Mesh.js +108 -76
  414. package/src/objects/Skeleton.js +1 -1
  415. package/src/objects/SkinnedMesh.js +123 -8
  416. package/src/objects/Sprite.js +1 -1
  417. package/src/renderers/WebGLCubeRenderTarget.js +12 -3
  418. package/src/renderers/WebGLMultipleRenderTargets.js +4 -2
  419. package/src/renderers/WebGLRenderTarget.js +14 -2
  420. package/src/renderers/WebGLRenderer.js +1433 -1236
  421. package/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js +1 -1
  422. package/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js +1 -1
  423. package/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +0 -271
  424. package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +5 -5
  425. package/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js +2 -10
  426. package/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js +5 -5
  427. package/src/renderers/shaders/ShaderChunk/common.glsl.js +32 -0
  428. package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +1 -1
  429. package/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js +1 -1
  430. package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +1 -1
  431. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +26 -3
  432. package/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +1 -1
  433. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +3 -3
  434. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +10 -2
  435. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +11 -11
  436. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +39 -13
  437. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +306 -10
  438. package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +2 -10
  439. package/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js +9 -1
  440. package/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js +10 -2
  441. package/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js +1 -1
  442. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +32 -10
  443. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +5 -13
  444. package/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js +7 -7
  445. package/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js +1 -2
  446. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +11 -5
  447. package/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js +1 -1
  448. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +4 -11
  449. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +2 -2
  450. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +39 -34
  451. package/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js +1 -1
  452. package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +1 -1
  453. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +5 -5
  454. package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +101 -16
  455. package/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js +113 -1
  456. package/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js +134 -6
  457. package/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js +116 -1
  458. package/src/renderers/shaders/ShaderChunk.js +0 -6
  459. package/src/renderers/shaders/ShaderLib/background.glsl.js +0 -8
  460. package/src/renderers/shaders/ShaderLib/linedashed.glsl.js +5 -0
  461. package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +1 -4
  462. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -3
  463. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +3 -3
  464. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -3
  465. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +16 -12
  466. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +0 -3
  467. package/src/renderers/shaders/ShaderLib/points.glsl.js +13 -0
  468. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +5 -0
  469. package/src/renderers/shaders/ShaderLib.js +18 -4
  470. package/src/renderers/shaders/UniformsLib.js +27 -15
  471. package/src/renderers/shaders/UniformsUtils.js +12 -3
  472. package/src/renderers/webgl/WebGLBackground.js +23 -12
  473. package/src/renderers/webgl/WebGLBindingStates.js +13 -5
  474. package/src/renderers/webgl/WebGLCapabilities.js +1 -2
  475. package/src/renderers/webgl/WebGLClipping.js +7 -3
  476. package/src/renderers/webgl/WebGLGeometries.js +12 -0
  477. package/src/renderers/webgl/WebGLInfo.js +0 -1
  478. package/src/renderers/webgl/WebGLLights.js +2 -2
  479. package/src/renderers/webgl/WebGLMaterials.js +123 -234
  480. package/src/renderers/webgl/WebGLMorphtargets.js +1 -1
  481. package/src/renderers/webgl/WebGLProgram.js +130 -48
  482. package/src/renderers/webgl/WebGLPrograms.js +210 -130
  483. package/src/renderers/webgl/WebGLRenderStates.js +2 -2
  484. package/src/renderers/webgl/WebGLShadowMap.js +40 -27
  485. package/src/renderers/webgl/WebGLState.js +23 -9
  486. package/src/renderers/webgl/WebGLTextures.js +39 -19
  487. package/src/renderers/webgl/WebGLUniformsGroups.js +74 -33
  488. package/src/renderers/webgl/WebGLUtils.js +41 -29
  489. package/src/renderers/webxr/WebXRController.js +3 -0
  490. package/src/renderers/webxr/WebXRManager.js +85 -141
  491. package/src/scenes/Scene.js +4 -6
  492. package/src/textures/CompressedTexture.js +2 -2
  493. package/src/textures/CubeTexture.js +2 -2
  494. package/src/textures/DataTexture.js +2 -2
  495. package/src/textures/DepthTexture.js +22 -0
  496. package/src/textures/FramebufferTexture.js +1 -3
  497. package/src/textures/Source.js +4 -0
  498. package/src/textures/Texture.js +43 -13
  499. package/src/utils.js +13 -1
  500. package/examples/fonts/open-sans/open-sans-v15-cyrillic-ext_greek_greek-ext_cyrillic_latin_latin-ext_vietnamese-regular.woff +0 -0
  501. package/examples/fonts/open-sans/open-sans-v15-cyrillic-ext_greek_greek-ext_cyrillic_latin_latin-ext_vietnamese-regular.woff2 +0 -0
  502. package/examples/fonts/open-sans/open-sans.css +0 -9
  503. package/examples/fonts/tabler-icons/fonts/tabler-icons.eot +0 -0
  504. package/examples/fonts/tabler-icons/fonts/tabler-icons.svg +0 -3966
  505. package/examples/fonts/tabler-icons/fonts/tabler-icons.ttf +0 -0
  506. package/examples/fonts/tabler-icons/fonts/tabler-icons.woff +0 -0
  507. package/examples/fonts/tabler-icons/fonts/tabler-icons.woff2 +0 -0
  508. package/examples/fonts/tabler-icons/tabler-icons.min.css +0 -4
  509. package/examples/js/animation/AnimationClipCreator.js +0 -89
  510. package/examples/js/animation/CCDIKSolver.js +0 -416
  511. package/examples/js/animation/MMDAnimationHelper.js +0 -1046
  512. package/examples/js/animation/MMDPhysics.js +0 -1174
  513. package/examples/js/cameras/CinematicCamera.js +0 -168
  514. package/examples/js/controls/ArcballControls.js +0 -2770
  515. package/examples/js/controls/DragControls.js +0 -205
  516. package/examples/js/controls/FirstPersonControls.js +0 -312
  517. package/examples/js/controls/FlyControls.js +0 -321
  518. package/examples/js/controls/OrbitControls.js +0 -1065
  519. package/examples/js/controls/PointerLockControls.js +0 -144
  520. package/examples/js/controls/TrackballControls.js +0 -729
  521. package/examples/js/controls/TransformControls.js +0 -1301
  522. package/examples/js/csm/CSM.js +0 -347
  523. package/examples/js/csm/CSMFrustum.js +0 -127
  524. package/examples/js/csm/CSMHelper.js +0 -165
  525. package/examples/js/csm/CSMShader.js +0 -253
  526. package/examples/js/curves/CurveExtras.js +0 -348
  527. package/examples/js/curves/NURBSCurve.js +0 -63
  528. package/examples/js/curves/NURBSSurface.js +0 -48
  529. package/examples/js/curves/NURBSUtils.js +0 -439
  530. package/examples/js/effects/AnaglyphEffect.js +0 -86
  531. package/examples/js/effects/AsciiEffect.js +0 -260
  532. package/examples/js/effects/OutlineEffect.js +0 -450
  533. package/examples/js/effects/ParallaxBarrierEffect.js +0 -62
  534. package/examples/js/effects/PeppersGhostEffect.js +0 -139
  535. package/examples/js/effects/StereoEffect.js +0 -46
  536. package/examples/js/environments/DebugEnvironment.js +0 -53
  537. package/examples/js/environments/RoomEnvironment.js +0 -124
  538. package/examples/js/exporters/ColladaExporter.js +0 -487
  539. package/examples/js/exporters/DRACOExporter.js +0 -212
  540. package/examples/js/exporters/EXRExporter.js +0 -455
  541. package/examples/js/exporters/GLTFExporter.js +0 -2425
  542. package/examples/js/exporters/MMDExporter.js +0 -187
  543. package/examples/js/exporters/OBJExporter.js +0 -260
  544. package/examples/js/exporters/PLYExporter.js +0 -427
  545. package/examples/js/exporters/STLExporter.js +0 -188
  546. package/examples/js/exporters/USDZExporter.js +0 -608
  547. package/examples/js/geometries/BoxLineGeometry.js +0 -59
  548. package/examples/js/geometries/ConvexGeometry.js +0 -53
  549. package/examples/js/geometries/DecalGeometry.js +0 -324
  550. package/examples/js/geometries/LightningStrike.js +0 -861
  551. package/examples/js/geometries/ParametricGeometries.js +0 -216
  552. package/examples/js/geometries/ParametricGeometry.js +0 -121
  553. package/examples/js/geometries/RoundedBoxGeometry.js +0 -142
  554. package/examples/js/geometries/TeapotGeometry.js +0 -335
  555. package/examples/js/geometries/TextGeometry.js +0 -53
  556. package/examples/js/helpers/LightProbeHelper.js +0 -48
  557. package/examples/js/helpers/OctreeHelper.js +0 -76
  558. package/examples/js/helpers/PositionalAudioHelper.js +0 -91
  559. package/examples/js/helpers/RectAreaLightHelper.js +0 -73
  560. package/examples/js/helpers/VertexNormalsHelper.js +0 -74
  561. package/examples/js/helpers/VertexTangentsHelper.js +0 -68
  562. package/examples/js/helpers/ViewHelper.js +0 -281
  563. package/examples/js/interactive/HTMLMesh.js +0 -497
  564. package/examples/js/interactive/InteractiveGroup.js +0 -95
  565. package/examples/js/interactive/SelectionBox.js +0 -195
  566. package/examples/js/interactive/SelectionHelper.js +0 -83
  567. package/examples/js/libs/chevrotain.min.js +0 -3
  568. package/examples/js/libs/draco/draco_decoder.js +0 -52
  569. package/examples/js/libs/draco/draco_decoder.wasm +0 -0
  570. package/examples/js/libs/draco/draco_wasm_wrapper.js +0 -104
  571. package/examples/js/libs/draco/gltf/draco_decoder.js +0 -48
  572. package/examples/js/libs/draco/gltf/draco_decoder.wasm +0 -0
  573. package/examples/js/libs/draco/gltf/draco_wasm_wrapper.js +0 -104
  574. package/examples/js/libs/fflate.min.js +0 -7
  575. package/examples/js/libs/ktx-parse.umd.js +0 -1
  576. package/examples/js/libs/meshopt_decoder.js +0 -188
  577. package/examples/js/libs/opentype.min.js +0 -1
  578. package/examples/js/libs/stats.min.js +0 -5
  579. package/examples/js/lights/LightProbeGenerator.js +0 -221
  580. package/examples/js/lights/RectAreaLightUniformsLib.js +0 -60
  581. package/examples/js/lines/Line2.js +0 -19
  582. package/examples/js/lines/LineGeometry.js +0 -69
  583. package/examples/js/lines/LineMaterial.js +0 -635
  584. package/examples/js/lines/LineSegments2.js +0 -311
  585. package/examples/js/lines/LineSegmentsGeometry.js +0 -198
  586. package/examples/js/lines/Wireframe.js +0 -47
  587. package/examples/js/lines/WireframeGeometry2.js +0 -20
  588. package/examples/js/loaders/3DMLoader.js +0 -1273
  589. package/examples/js/loaders/3MFLoader.js +0 -1306
  590. package/examples/js/loaders/AMFLoader.js +0 -504
  591. package/examples/js/loaders/BVHLoader.js +0 -395
  592. package/examples/js/loaders/BasisTextureLoader.js +0 -706
  593. package/examples/js/loaders/ColladaLoader.js +0 -3663
  594. package/examples/js/loaders/DDSLoader.js +0 -244
  595. package/examples/js/loaders/DRACOLoader.js +0 -511
  596. package/examples/js/loaders/EXRLoader.js +0 -2039
  597. package/examples/js/loaders/FBXLoader.js +0 -3680
  598. package/examples/js/loaders/FontLoader.js +0 -160
  599. package/examples/js/loaders/GCodeLoader.js +0 -255
  600. package/examples/js/loaders/GLTFLoader.js +0 -4108
  601. package/examples/js/loaders/HDRCubeTextureLoader.js +0 -87
  602. package/examples/js/loaders/KMZLoader.js +0 -121
  603. package/examples/js/loaders/KTXLoader.js +0 -159
  604. package/examples/js/loaders/LDrawLoader.js +0 -2263
  605. package/examples/js/loaders/LUT3dlLoader.js +0 -135
  606. package/examples/js/loaders/LUTCubeLoader.js +0 -132
  607. package/examples/js/loaders/LWOLoader.js +0 -901
  608. package/examples/js/loaders/LogLuvLoader.js +0 -715
  609. package/examples/js/loaders/LottieLoader.js +0 -62
  610. package/examples/js/loaders/MD2Loader.js +0 -248
  611. package/examples/js/loaders/MDDLoader.js +0 -91
  612. package/examples/js/loaders/MMDLoader.js +0 -1915
  613. package/examples/js/loaders/MTLLoader.js +0 -472
  614. package/examples/js/loaders/MaterialXLoader.js +0 -392
  615. package/examples/js/loaders/NRRDLoader.js +0 -609
  616. package/examples/js/loaders/OBJLoader.js +0 -789
  617. package/examples/js/loaders/PCDLoader.js +0 -413
  618. package/examples/js/loaders/PDBLoader.js +0 -317
  619. package/examples/js/loaders/PLYLoader.js +0 -532
  620. package/examples/js/loaders/PRWMLoader.js +0 -249
  621. package/examples/js/loaders/PVRLoader.js +0 -218
  622. package/examples/js/loaders/RGBELoader.js +0 -442
  623. package/examples/js/loaders/RGBMLoader.js +0 -1354
  624. package/examples/js/loaders/STLLoader.js +0 -364
  625. package/examples/js/loaders/SVGLoader.js +0 -2783
  626. package/examples/js/loaders/TDSLoader.js +0 -992
  627. package/examples/js/loaders/TGALoader.js +0 -484
  628. package/examples/js/loaders/TIFFLoader.js +0 -30
  629. package/examples/js/loaders/TTFLoader.js +0 -203
  630. package/examples/js/loaders/TiltLoader.js +0 -459
  631. package/examples/js/loaders/VOXLoader.js +0 -240
  632. package/examples/js/loaders/VRMLLoader.js +0 -3140
  633. package/examples/js/loaders/VTKLoader.js +0 -1078
  634. package/examples/js/loaders/XYZLoader.js +0 -89
  635. package/examples/js/loaders/lwo/IFFParser.js +0 -1067
  636. package/examples/js/loaders/lwo/LWO2Parser.js +0 -397
  637. package/examples/js/loaders/lwo/LWO3Parser.js +0 -360
  638. package/examples/js/materials/MeshGouraudMaterial.js +0 -387
  639. package/examples/js/math/Capsule.js +0 -103
  640. package/examples/js/math/ColorConverter.js +0 -33
  641. package/examples/js/math/ConvexHull.js +0 -1154
  642. package/examples/js/math/ImprovedNoise.js +0 -66
  643. package/examples/js/math/Lut.js +0 -164
  644. package/examples/js/math/MeshSurfaceSampler.js +0 -171
  645. package/examples/js/math/OBB.js +0 -382
  646. package/examples/js/math/Octree.js +0 -410
  647. package/examples/js/math/SimplexNoise.js +0 -445
  648. package/examples/js/misc/ConvexObjectBreaker.js +0 -474
  649. package/examples/js/misc/GPUComputationRenderer.js +0 -393
  650. package/examples/js/misc/Gyroscope.js +0 -56
  651. package/examples/js/misc/MD2Character.js +0 -235
  652. package/examples/js/misc/MD2CharacterComplex.js +0 -513
  653. package/examples/js/misc/MorphAnimMesh.js +0 -63
  654. package/examples/js/misc/MorphBlendMesh.js +0 -265
  655. package/examples/js/misc/ProgressiveLightMap.js +0 -335
  656. package/examples/js/misc/RollerCoaster.js +0 -430
  657. package/examples/js/misc/TubePainter.js +0 -167
  658. package/examples/js/misc/Volume.js +0 -437
  659. package/examples/js/misc/VolumeSlice.js +0 -214
  660. package/examples/js/modifiers/CurveModifier.js +0 -309
  661. package/examples/js/modifiers/EdgeSplitModifier.js +0 -228
  662. package/examples/js/modifiers/SimplifyModifier.js +0 -465
  663. package/examples/js/modifiers/TessellateModifier.js +0 -276
  664. package/examples/js/objects/GroundProjectedEnv.js +0 -181
  665. package/examples/js/objects/Lensflare.js +0 -356
  666. package/examples/js/objects/LightningStorm.js +0 -206
  667. package/examples/js/objects/MarchingCubes.js +0 -759
  668. package/examples/js/objects/Reflector.js +0 -216
  669. package/examples/js/objects/ReflectorForSSRPass.js +0 -315
  670. package/examples/js/objects/Refractor.js +0 -283
  671. package/examples/js/objects/ShadowMesh.js +0 -59
  672. package/examples/js/objects/Sky.js +0 -218
  673. package/examples/js/objects/Water.js +0 -292
  674. package/examples/js/objects/Water2.js +0 -307
  675. package/examples/js/physics/AmmoPhysics.js +0 -259
  676. package/examples/js/physics/OimoPhysics.js +0 -217
  677. package/examples/js/postprocessing/AdaptiveToneMappingPass.js +0 -335
  678. package/examples/js/postprocessing/AfterimagePass.js +0 -77
  679. package/examples/js/postprocessing/BloomPass.js +0 -135
  680. package/examples/js/postprocessing/BokehPass.js +0 -120
  681. package/examples/js/postprocessing/ClearPass.js +0 -39
  682. package/examples/js/postprocessing/CubeTexturePass.js +0 -60
  683. package/examples/js/postprocessing/DotScreenPass.js +0 -51
  684. package/examples/js/postprocessing/EffectComposer.js +0 -272
  685. package/examples/js/postprocessing/FilmPass.js +0 -52
  686. package/examples/js/postprocessing/GlitchPass.js +0 -104
  687. package/examples/js/postprocessing/HalftonePass.js +0 -75
  688. package/examples/js/postprocessing/LUTPass.js +0 -171
  689. package/examples/js/postprocessing/MaskPass.js +0 -95
  690. package/examples/js/postprocessing/OutlinePass.js +0 -598
  691. package/examples/js/postprocessing/Pass.js +0 -72
  692. package/examples/js/postprocessing/RenderPass.js +0 -70
  693. package/examples/js/postprocessing/SAOPass.js +0 -374
  694. package/examples/js/postprocessing/SMAAPass.js +0 -170
  695. package/examples/js/postprocessing/SSAARenderPass.js +0 -156
  696. package/examples/js/postprocessing/SSAOPass.js +0 -365
  697. package/examples/js/postprocessing/SSRPass.js +0 -567
  698. package/examples/js/postprocessing/SavePass.js +0 -59
  699. package/examples/js/postprocessing/ShaderPass.js +0 -64
  700. package/examples/js/postprocessing/TAARenderPass.js +0 -130
  701. package/examples/js/postprocessing/TexturePass.js +0 -49
  702. package/examples/js/postprocessing/UnrealBloomPass.js +0 -375
  703. package/examples/js/renderers/CSS2DRenderer.js +0 -178
  704. package/examples/js/renderers/CSS3DRenderer.js +0 -237
  705. package/examples/js/renderers/Projector.js +0 -818
  706. package/examples/js/renderers/SVGRenderer.js +0 -491
  707. package/examples/js/shaders/ACESFilmicToneMappingShader.js +0 -89
  708. package/examples/js/shaders/AfterimageShader.js +0 -60
  709. package/examples/js/shaders/BasicShader.js +0 -27
  710. package/examples/js/shaders/BleachBypassShader.js +0 -62
  711. package/examples/js/shaders/BlendShader.js +0 -54
  712. package/examples/js/shaders/BokehShader.js +0 -156
  713. package/examples/js/shaders/BokehShader2.js +0 -419
  714. package/examples/js/shaders/BrightnessContrastShader.js +0 -58
  715. package/examples/js/shaders/ColorCorrectionShader.js +0 -52
  716. package/examples/js/shaders/ColorifyShader.js +0 -47
  717. package/examples/js/shaders/ConvolutionShader.js +0 -92
  718. package/examples/js/shaders/CopyShader.js +0 -45
  719. package/examples/js/shaders/DOFMipMapShader.js +0 -60
  720. package/examples/js/shaders/DepthLimitedBlurShader.js +0 -173
  721. package/examples/js/shaders/DigitalGlitch.js +0 -127
  722. package/examples/js/shaders/DotScreenShader.js +0 -72
  723. package/examples/js/shaders/FXAAShader.js +0 -284
  724. package/examples/js/shaders/FilmShader.js +0 -110
  725. package/examples/js/shaders/FocusShader.js +0 -95
  726. package/examples/js/shaders/FreiChenShader.js +0 -93
  727. package/examples/js/shaders/GammaCorrectionShader.js +0 -41
  728. package/examples/js/shaders/GodRaysShader.js +0 -284
  729. package/examples/js/shaders/HalftoneShader.js +0 -336
  730. package/examples/js/shaders/HorizontalBlurShader.js +0 -59
  731. package/examples/js/shaders/HorizontalTiltShiftShader.js +0 -65
  732. package/examples/js/shaders/HueSaturationShader.js +0 -69
  733. package/examples/js/shaders/KaleidoShader.js +0 -60
  734. package/examples/js/shaders/LuminosityHighPassShader.js +0 -67
  735. package/examples/js/shaders/LuminosityShader.js +0 -46
  736. package/examples/js/shaders/MMDToonShader.js +0 -96
  737. package/examples/js/shaders/MirrorShader.js +0 -56
  738. package/examples/js/shaders/NormalMapShader.js +0 -55
  739. package/examples/js/shaders/RGBShiftShader.js +0 -56
  740. package/examples/js/shaders/SAOShader.js +0 -209
  741. package/examples/js/shaders/SMAAShader.js +0 -454
  742. package/examples/js/shaders/SSAOShader.js +0 -295
  743. package/examples/js/shaders/SSRShader.js +0 -381
  744. package/examples/js/shaders/SepiaShader.js +0 -52
  745. package/examples/js/shaders/SobelOperatorShader.js +0 -88
  746. package/examples/js/shaders/SubsurfaceScatteringShader.js +0 -49
  747. package/examples/js/shaders/TechnicolorShader.js +0 -43
  748. package/examples/js/shaders/ToneMapShader.js +0 -84
  749. package/examples/js/shaders/ToonShader.js +0 -335
  750. package/examples/js/shaders/TriangleBlurShader.js +0 -70
  751. package/examples/js/shaders/UnpackDepthRGBAShader.js +0 -47
  752. package/examples/js/shaders/VelocityShader.js +0 -126
  753. package/examples/js/shaders/VerticalBlurShader.js +0 -59
  754. package/examples/js/shaders/VerticalTiltShiftShader.js +0 -65
  755. package/examples/js/shaders/VignetteShader.js +0 -53
  756. package/examples/js/shaders/VolumeShader.js +0 -296
  757. package/examples/js/shaders/WaterRefractionShader.js +0 -84
  758. package/examples/js/textures/FlakesTexture.js +0 -40
  759. package/examples/js/utils/BufferGeometryUtils.js +0 -1160
  760. package/examples/js/utils/CameraUtils.js +0 -71
  761. package/examples/js/utils/GPUStatsPanel.js +0 -125
  762. package/examples/js/utils/GeometryCompressionUtils.js +0 -549
  763. package/examples/js/utils/GeometryUtils.js +0 -168
  764. package/examples/js/utils/LDrawUtils.js +0 -179
  765. package/examples/js/utils/PackedPhongMaterial.js +0 -109
  766. package/examples/js/utils/SceneUtils.js +0 -214
  767. package/examples/js/utils/ShadowMapViewer.js +0 -183
  768. package/examples/js/utils/SkeletonUtils.js +0 -493
  769. package/examples/js/utils/UVsDebug.js +0 -143
  770. package/examples/js/utils/WorkerPool.js +0 -105
  771. package/examples/jsm/exporters/ColladaExporter.js +0 -713
  772. package/examples/jsm/geometries/LightningStrike.js +0 -1017
  773. package/examples/jsm/libs/OimoPhysics/OimoPhysics.js +0 -37071
  774. package/examples/jsm/libs/OimoPhysics/index.js +0 -43
  775. package/examples/jsm/libs/flow.module.js +0 -4552
  776. package/examples/jsm/libs/tween.module.min.js +0 -3
  777. package/examples/jsm/loaders/BasisTextureLoader.js +0 -790
  778. package/examples/jsm/loaders/IFCLoader.js +0 -2431
  779. package/examples/jsm/loaders/PRWMLoader.js +0 -299
  780. package/examples/jsm/loaders/ifc/web-ifc-api.js +0 -47504
  781. package/examples/jsm/loaders/ifc/web-ifc.wasm +0 -0
  782. package/examples/jsm/node-editor/NodeEditor.js +0 -857
  783. package/examples/jsm/node-editor/accessors/MatcapUVEditor.js +0 -14
  784. package/examples/jsm/node-editor/accessors/NormalEditor.js +0 -30
  785. package/examples/jsm/node-editor/accessors/PositionEditor.js +0 -30
  786. package/examples/jsm/node-editor/accessors/UVEditor.js +0 -25
  787. package/examples/jsm/node-editor/core/BaseNode.js +0 -96
  788. package/examples/jsm/node-editor/core/DataFile.js +0 -59
  789. package/examples/jsm/node-editor/core/FileEditor.js +0 -20
  790. package/examples/jsm/node-editor/core/FileURLEditor.js +0 -29
  791. package/examples/jsm/node-editor/display/BlendEditor.js +0 -44
  792. package/examples/jsm/node-editor/display/NormalMapEditor.js +0 -49
  793. package/examples/jsm/node-editor/examples/animate-uv.json +0 -1
  794. package/examples/jsm/node-editor/examples/fake-top-light.json +0 -1
  795. package/examples/jsm/node-editor/examples/matcap.json +0 -1
  796. package/examples/jsm/node-editor/examples/oscillator-color.json +0 -1
  797. package/examples/jsm/node-editor/examples/rim.json +0 -1
  798. package/examples/jsm/node-editor/inputs/ColorEditor.js +0 -96
  799. package/examples/jsm/node-editor/inputs/FloatEditor.js +0 -23
  800. package/examples/jsm/node-editor/inputs/SliderEditor.js +0 -67
  801. package/examples/jsm/node-editor/inputs/TextureEditor.js +0 -155
  802. package/examples/jsm/node-editor/inputs/Vector2Editor.js +0 -28
  803. package/examples/jsm/node-editor/inputs/Vector3Editor.js +0 -30
  804. package/examples/jsm/node-editor/inputs/Vector4Editor.js +0 -37
  805. package/examples/jsm/node-editor/materials/BasicMaterialEditor.js +0 -84
  806. package/examples/jsm/node-editor/materials/PointsMaterialEditor.js +0 -102
  807. package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +0 -118
  808. package/examples/jsm/node-editor/math/AngleEditor.js +0 -40
  809. package/examples/jsm/node-editor/math/DotEditor.js +0 -35
  810. package/examples/jsm/node-editor/math/InvertEditor.js +0 -39
  811. package/examples/jsm/node-editor/math/LimiterEditor.js +0 -62
  812. package/examples/jsm/node-editor/math/NormalizeEditor.js +0 -28
  813. package/examples/jsm/node-editor/math/OperatorEditor.js +0 -63
  814. package/examples/jsm/node-editor/math/PowerEditor.js +0 -44
  815. package/examples/jsm/node-editor/math/TrigonometryEditor.js +0 -45
  816. package/examples/jsm/node-editor/procedural/CheckerEditor.js +0 -27
  817. package/examples/jsm/node-editor/scene/MeshEditor.js +0 -102
  818. package/examples/jsm/node-editor/scene/Object3DEditor.js +0 -160
  819. package/examples/jsm/node-editor/scene/PointsEditor.js +0 -99
  820. package/examples/jsm/node-editor/utils/JoinEditor.js +0 -58
  821. package/examples/jsm/node-editor/utils/OscillatorEditor.js +0 -43
  822. package/examples/jsm/node-editor/utils/PreviewEditor.js +0 -170
  823. package/examples/jsm/node-editor/utils/SplitEditor.js +0 -39
  824. package/examples/jsm/node-editor/utils/TimerEditor.js +0 -58
  825. package/examples/jsm/nodes/core/CodeNode.js +0 -50
  826. package/examples/jsm/nodes/core/ExpressionNode.js +0 -32
  827. package/examples/jsm/nodes/functions/light/getDistanceAttenuation.js +0 -22
  828. package/examples/jsm/nodes/lighting/PunctualLightNode.js +0 -68
  829. package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +0 -301
  830. package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +0 -149
  831. package/examples/jsm/objects/GroundProjectedEnv.js +0 -186
  832. package/examples/jsm/objects/LightningStorm.js +0 -245
  833. package/examples/jsm/physics/OimoPhysics.js +0 -231
  834. package/examples/jsm/postprocessing/AdaptiveToneMappingPass.js +0 -369
  835. package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +0 -187
  836. package/examples/jsm/renderers/webgpu/WebGPUBackground.js +0 -173
  837. package/examples/jsm/renderers/webgpu/WebGPUBinding.js +0 -22
  838. package/examples/jsm/renderers/webgpu/WebGPUBindings.js +0 -255
  839. package/examples/jsm/renderers/webgpu/WebGPUBuffer.js +0 -43
  840. package/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js +0 -78
  841. package/examples/jsm/renderers/webgpu/WebGPUGeometries.js +0 -82
  842. package/examples/jsm/renderers/webgpu/WebGPUObjects.js +0 -36
  843. package/examples/jsm/renderers/webgpu/WebGPUProgrammableStage.js +0 -22
  844. package/examples/jsm/renderers/webgpu/WebGPUProperties.js +0 -38
  845. package/examples/jsm/renderers/webgpu/WebGPURenderPipelines.js +0 -296
  846. package/examples/jsm/renderers/webgpu/WebGPURenderStates.js +0 -66
  847. package/examples/jsm/renderers/webgpu/WebGPUSampledTexture.js +0 -73
  848. package/examples/jsm/renderers/webgpu/WebGPUSampler.js +0 -29
  849. package/examples/jsm/renderers/webgpu/WebGPUStorageBuffer.js +0 -20
  850. package/examples/jsm/renderers/webgpu/WebGPUTextureRenderer.js +0 -40
  851. package/examples/jsm/renderers/webgpu/WebGPUTextures.js +0 -794
  852. package/examples/jsm/renderers/webgpu/WebGPUUniformBuffer.js +0 -18
  853. package/examples/jsm/renderers/webgpu/WebGPUUtils.js +0 -81
  854. package/examples/jsm/renderers/webgpu/nodes/WebGPUNodes.js +0 -83
  855. package/examples/jsm/shaders/ToneMapShader.js +0 -73
  856. package/src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl.js +0 -7
  857. package/src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl.js +0 -10
  858. package/src/renderers/shaders/ShaderChunk/uv2_vertex.glsl.js +0 -7
  859. /package/examples/{js → jsm}/libs/ammo.wasm.js +0 -0
  860. /package/examples/{js → jsm}/libs/ammo.wasm.wasm +0 -0
  861. /package/examples/{js → jsm}/libs/basis/basis_transcoder.js +0 -0
  862. /package/examples/{js → jsm}/libs/basis/basis_transcoder.wasm +0 -0
  863. /package/examples/{js → jsm}/libs/draco/README.md +0 -0
  864. /package/examples/{js → jsm}/libs/draco/draco_encoder.js +0 -0
  865. /package/examples/{js → jsm}/libs/draco/gltf/draco_encoder.js +0 -0
@@ -1,3680 +0,0 @@
1
- ( function () {
2
-
3
- /**
4
- * THREE.Loader loads FBX file and generates THREE.Group representing FBX scene.
5
- * Requires FBX file to be >= 7.0 and in ASCII or >= 6400 in Binary format
6
- * Versions lower than this may load but will probably have errors
7
- *
8
- * Needs Support:
9
- * Morph normals / blend shape normals
10
- *
11
- * FBX format references:
12
- * https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference)
13
- *
14
- * Binary format specification:
15
- * https://code.blender.org/2013/08/fbx-binary-file-format-specification/
16
- */
17
-
18
- let fbxTree;
19
- let connections;
20
- let sceneGraph;
21
- class FBXLoader extends THREE.Loader {
22
-
23
- constructor( manager ) {
24
-
25
- super( manager );
26
-
27
- }
28
- load( url, onLoad, onProgress, onError ) {
29
-
30
- const scope = this;
31
- const path = scope.path === '' ? THREE.LoaderUtils.extractUrlBase( url ) : scope.path;
32
- const loader = new THREE.FileLoader( this.manager );
33
- loader.setPath( scope.path );
34
- loader.setResponseType( 'arraybuffer' );
35
- loader.setRequestHeader( scope.requestHeader );
36
- loader.setWithCredentials( scope.withCredentials );
37
- loader.load( url, function ( buffer ) {
38
-
39
- try {
40
-
41
- onLoad( scope.parse( buffer, path ) );
42
-
43
- } catch ( e ) {
44
-
45
- if ( onError ) {
46
-
47
- onError( e );
48
-
49
- } else {
50
-
51
- console.error( e );
52
-
53
- }
54
-
55
- scope.manager.itemError( url );
56
-
57
- }
58
-
59
- }, onProgress, onError );
60
-
61
- }
62
- parse( FBXBuffer, path ) {
63
-
64
- if ( isFbxFormatBinary( FBXBuffer ) ) {
65
-
66
- fbxTree = new BinaryParser().parse( FBXBuffer );
67
-
68
- } else {
69
-
70
- const FBXText = convertArrayBufferToString( FBXBuffer );
71
- if ( ! isFbxFormatASCII( FBXText ) ) {
72
-
73
- throw new Error( 'THREE.FBXLoader: Unknown format.' );
74
-
75
- }
76
-
77
- if ( getFbxVersion( FBXText ) < 7000 ) {
78
-
79
- throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion( FBXText ) );
80
-
81
- }
82
-
83
- fbxTree = new TextParser().parse( FBXText );
84
-
85
- }
86
-
87
- // console.log( fbxTree );
88
-
89
- const textureLoader = new THREE.TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
90
- return new FBXTreeParser( textureLoader, this.manager ).parse( fbxTree );
91
-
92
- }
93
-
94
- }
95
-
96
- // Parse the FBXTree object returned by the BinaryParser or TextParser and return a THREE.Group
97
- class FBXTreeParser {
98
-
99
- constructor( textureLoader, manager ) {
100
-
101
- this.textureLoader = textureLoader;
102
- this.manager = manager;
103
-
104
- }
105
- parse() {
106
-
107
- connections = this.parseConnections();
108
- const images = this.parseImages();
109
- const textures = this.parseTextures( images );
110
- const materials = this.parseMaterials( textures );
111
- const deformers = this.parseDeformers();
112
- const geometryMap = new GeometryParser().parse( deformers );
113
- this.parseScene( deformers, geometryMap, materials );
114
- return sceneGraph;
115
-
116
- }
117
-
118
- // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry )
119
- // and details the connection type
120
- parseConnections() {
121
-
122
- const connectionMap = new Map();
123
- if ( 'Connections' in fbxTree ) {
124
-
125
- const rawConnections = fbxTree.Connections.connections;
126
- rawConnections.forEach( function ( rawConnection ) {
127
-
128
- const fromID = rawConnection[ 0 ];
129
- const toID = rawConnection[ 1 ];
130
- const relationship = rawConnection[ 2 ];
131
- if ( ! connectionMap.has( fromID ) ) {
132
-
133
- connectionMap.set( fromID, {
134
- parents: [],
135
- children: []
136
- } );
137
-
138
- }
139
-
140
- const parentRelationship = {
141
- ID: toID,
142
- relationship: relationship
143
- };
144
- connectionMap.get( fromID ).parents.push( parentRelationship );
145
- if ( ! connectionMap.has( toID ) ) {
146
-
147
- connectionMap.set( toID, {
148
- parents: [],
149
- children: []
150
- } );
151
-
152
- }
153
-
154
- const childRelationship = {
155
- ID: fromID,
156
- relationship: relationship
157
- };
158
- connectionMap.get( toID ).children.push( childRelationship );
159
-
160
- } );
161
-
162
- }
163
-
164
- return connectionMap;
165
-
166
- }
167
-
168
- // Parse FBXTree.Objects.Video for embedded image data
169
- // These images are connected to textures in FBXTree.Objects.Textures
170
- // via FBXTree.Connections.
171
- parseImages() {
172
-
173
- const images = {};
174
- const blobs = {};
175
- if ( 'Video' in fbxTree.Objects ) {
176
-
177
- const videoNodes = fbxTree.Objects.Video;
178
- for ( const nodeID in videoNodes ) {
179
-
180
- const videoNode = videoNodes[ nodeID ];
181
- const id = parseInt( nodeID );
182
- images[ id ] = videoNode.RelativeFilename || videoNode.Filename;
183
-
184
- // raw image data is in videoNode.Content
185
- if ( 'Content' in videoNode ) {
186
-
187
- const arrayBufferContent = videoNode.Content instanceof ArrayBuffer && videoNode.Content.byteLength > 0;
188
- const base64Content = typeof videoNode.Content === 'string' && videoNode.Content !== '';
189
- if ( arrayBufferContent || base64Content ) {
190
-
191
- const image = this.parseImage( videoNodes[ nodeID ] );
192
- blobs[ videoNode.RelativeFilename || videoNode.Filename ] = image;
193
-
194
- }
195
-
196
- }
197
-
198
- }
199
-
200
- }
201
-
202
- for ( const id in images ) {
203
-
204
- const filename = images[ id ];
205
- if ( blobs[ filename ] !== undefined ) images[ id ] = blobs[ filename ]; else images[ id ] = images[ id ].split( '\\' ).pop();
206
-
207
- }
208
-
209
- return images;
210
-
211
- }
212
-
213
- // Parse embedded image data in FBXTree.Video.Content
214
- parseImage( videoNode ) {
215
-
216
- const content = videoNode.Content;
217
- const fileName = videoNode.RelativeFilename || videoNode.Filename;
218
- const extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase();
219
- let type;
220
- switch ( extension ) {
221
-
222
- case 'bmp':
223
- type = 'image/bmp';
224
- break;
225
- case 'jpg':
226
- case 'jpeg':
227
- type = 'image/jpeg';
228
- break;
229
- case 'png':
230
- type = 'image/png';
231
- break;
232
- case 'tif':
233
- type = 'image/tiff';
234
- break;
235
- case 'tga':
236
- if ( this.manager.getHandler( '.tga' ) === null ) {
237
-
238
- console.warn( 'FBXLoader: TGA loader not found, skipping ', fileName );
239
-
240
- }
241
-
242
- type = 'image/tga';
243
- break;
244
- default:
245
- console.warn( 'FBXLoader: Image type "' + extension + '" is not supported.' );
246
- return;
247
-
248
- }
249
-
250
- if ( typeof content === 'string' ) {
251
-
252
- // ASCII format
253
-
254
- return 'data:' + type + ';base64,' + content;
255
-
256
- } else {
257
-
258
- // Binary Format
259
-
260
- const array = new Uint8Array( content );
261
- return window.URL.createObjectURL( new Blob( [ array ], {
262
- type: type
263
- } ) );
264
-
265
- }
266
-
267
- }
268
-
269
- // Parse nodes in FBXTree.Objects.Texture
270
- // These contain details such as UV scaling, cropping, rotation etc and are connected
271
- // to images in FBXTree.Objects.Video
272
- parseTextures( images ) {
273
-
274
- const textureMap = new Map();
275
- if ( 'Texture' in fbxTree.Objects ) {
276
-
277
- const textureNodes = fbxTree.Objects.Texture;
278
- for ( const nodeID in textureNodes ) {
279
-
280
- const texture = this.parseTexture( textureNodes[ nodeID ], images );
281
- textureMap.set( parseInt( nodeID ), texture );
282
-
283
- }
284
-
285
- }
286
-
287
- return textureMap;
288
-
289
- }
290
-
291
- // Parse individual node in FBXTree.Objects.Texture
292
- parseTexture( textureNode, images ) {
293
-
294
- const texture = this.loadTexture( textureNode, images );
295
- texture.ID = textureNode.id;
296
- texture.name = textureNode.attrName;
297
- const wrapModeU = textureNode.WrapModeU;
298
- const wrapModeV = textureNode.WrapModeV;
299
- const valueU = wrapModeU !== undefined ? wrapModeU.value : 0;
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
303
- // 0: repeat(default), 1: clamp
304
-
305
- texture.wrapS = valueU === 0 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
306
- texture.wrapT = valueV === 0 ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
307
- if ( 'Scaling' in textureNode ) {
308
-
309
- const values = textureNode.Scaling.value;
310
- texture.repeat.x = values[ 0 ];
311
- texture.repeat.y = values[ 1 ];
312
-
313
- }
314
-
315
- if ( 'Translation' in textureNode ) {
316
-
317
- const values = textureNode.Translation.value;
318
- texture.offset.x = values[ 0 ];
319
- texture.offset.y = values[ 1 ];
320
-
321
- }
322
-
323
- return texture;
324
-
325
- }
326
-
327
- // load a texture specified as a blob or data URI, or via an external URL using THREE.TextureLoader
328
- loadTexture( textureNode, images ) {
329
-
330
- let fileName;
331
- const currentPath = this.textureLoader.path;
332
- const children = connections.get( textureNode.id ).children;
333
- if ( children !== undefined && children.length > 0 && images[ children[ 0 ].ID ] !== undefined ) {
334
-
335
- fileName = images[ children[ 0 ].ID ];
336
- if ( fileName.indexOf( 'blob:' ) === 0 || fileName.indexOf( 'data:' ) === 0 ) {
337
-
338
- this.textureLoader.setPath( undefined );
339
-
340
- }
341
-
342
- }
343
-
344
- let texture;
345
- const extension = textureNode.FileName.slice( - 3 ).toLowerCase();
346
- if ( extension === 'tga' ) {
347
-
348
- const loader = this.manager.getHandler( '.tga' );
349
- if ( loader === null ) {
350
-
351
- console.warn( 'FBXLoader: TGA loader not found, creating placeholder texture for', textureNode.RelativeFilename );
352
- texture = new THREE.Texture();
353
-
354
- } else {
355
-
356
- loader.setPath( this.textureLoader.path );
357
- texture = loader.load( fileName );
358
-
359
- }
360
-
361
- } else if ( extension === 'psd' ) {
362
-
363
- console.warn( 'FBXLoader: PSD textures are not supported, creating placeholder texture for', textureNode.RelativeFilename );
364
- texture = new THREE.Texture();
365
-
366
- } else {
367
-
368
- texture = this.textureLoader.load( fileName );
369
-
370
- }
371
-
372
- this.textureLoader.setPath( currentPath );
373
- return texture;
374
-
375
- }
376
-
377
- // Parse nodes in FBXTree.Objects.Material
378
- parseMaterials( textureMap ) {
379
-
380
- const materialMap = new Map();
381
- if ( 'Material' in fbxTree.Objects ) {
382
-
383
- const materialNodes = fbxTree.Objects.Material;
384
- for ( const nodeID in materialNodes ) {
385
-
386
- const material = this.parseMaterial( materialNodes[ nodeID ], textureMap );
387
- if ( material !== null ) materialMap.set( parseInt( nodeID ), material );
388
-
389
- }
390
-
391
- }
392
-
393
- return materialMap;
394
-
395
- }
396
-
397
- // Parse single node in FBXTree.Objects.Material
398
- // Materials are connected to texture maps in FBXTree.Objects.Textures
399
- // FBX format currently only supports Lambert and Phong shading models
400
- parseMaterial( materialNode, textureMap ) {
401
-
402
- const ID = materialNode.id;
403
- const name = materialNode.attrName;
404
- let type = materialNode.ShadingModel;
405
-
406
- // Case where FBX wraps shading model in property object.
407
- if ( typeof type === 'object' ) {
408
-
409
- type = type.value;
410
-
411
- }
412
-
413
- // Ignore unused materials which don't have any connections.
414
- if ( ! connections.has( ID ) ) return null;
415
- const parameters = this.parseParameters( materialNode, textureMap, ID );
416
- let material;
417
- switch ( type.toLowerCase() ) {
418
-
419
- case 'phong':
420
- material = new THREE.MeshPhongMaterial();
421
- break;
422
- case 'lambert':
423
- material = new THREE.MeshLambertMaterial();
424
- break;
425
- default:
426
- console.warn( 'THREE.FBXLoader: unknown material type "%s". Defaulting to THREE.MeshPhongMaterial.', type );
427
- material = new THREE.MeshPhongMaterial();
428
- break;
429
-
430
- }
431
-
432
- material.setValues( parameters );
433
- material.name = name;
434
- return material;
435
-
436
- }
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
440
- parseParameters( materialNode, textureMap, ID ) {
441
-
442
- const parameters = {};
443
- if ( materialNode.BumpFactor ) {
444
-
445
- parameters.bumpScale = materialNode.BumpFactor.value;
446
-
447
- }
448
-
449
- if ( materialNode.Diffuse ) {
450
-
451
- parameters.color = new THREE.Color().fromArray( materialNode.Diffuse.value );
452
-
453
- } else if ( materialNode.DiffuseColor && ( materialNode.DiffuseColor.type === 'Color' || materialNode.DiffuseColor.type === 'ColorRGB' ) ) {
454
-
455
- // The blender exporter exports diffuse here instead of in materialNode.Diffuse
456
- parameters.color = new THREE.Color().fromArray( materialNode.DiffuseColor.value );
457
-
458
- }
459
-
460
- if ( materialNode.DisplacementFactor ) {
461
-
462
- parameters.displacementScale = materialNode.DisplacementFactor.value;
463
-
464
- }
465
-
466
- if ( materialNode.Emissive ) {
467
-
468
- parameters.emissive = new THREE.Color().fromArray( materialNode.Emissive.value );
469
-
470
- } else if ( materialNode.EmissiveColor && ( materialNode.EmissiveColor.type === 'Color' || materialNode.EmissiveColor.type === 'ColorRGB' ) ) {
471
-
472
- // The blender exporter exports emissive color here instead of in materialNode.Emissive
473
- parameters.emissive = new THREE.Color().fromArray( materialNode.EmissiveColor.value );
474
-
475
- }
476
-
477
- if ( materialNode.EmissiveFactor ) {
478
-
479
- parameters.emissiveIntensity = parseFloat( materialNode.EmissiveFactor.value );
480
-
481
- }
482
-
483
- if ( materialNode.Opacity ) {
484
-
485
- parameters.opacity = parseFloat( materialNode.Opacity.value );
486
-
487
- }
488
-
489
- if ( parameters.opacity < 1.0 ) {
490
-
491
- parameters.transparent = true;
492
-
493
- }
494
-
495
- if ( materialNode.ReflectionFactor ) {
496
-
497
- parameters.reflectivity = materialNode.ReflectionFactor.value;
498
-
499
- }
500
-
501
- if ( materialNode.Shininess ) {
502
-
503
- parameters.shininess = materialNode.Shininess.value;
504
-
505
- }
506
-
507
- if ( materialNode.Specular ) {
508
-
509
- parameters.specular = new THREE.Color().fromArray( materialNode.Specular.value );
510
-
511
- } else if ( materialNode.SpecularColor && materialNode.SpecularColor.type === 'Color' ) {
512
-
513
- // The blender exporter exports specular color here instead of in materialNode.Specular
514
- parameters.specular = new THREE.Color().fromArray( materialNode.SpecularColor.value );
515
-
516
- }
517
-
518
- const scope = this;
519
- connections.get( ID ).children.forEach( function ( child ) {
520
-
521
- const type = child.relationship;
522
- switch ( type ) {
523
-
524
- case 'Bump':
525
- parameters.bumpMap = scope.getTexture( textureMap, child.ID );
526
- break;
527
- case 'Maya|TEX_ao_map':
528
- parameters.aoMap = scope.getTexture( textureMap, child.ID );
529
- break;
530
- case 'DiffuseColor':
531
- case 'Maya|TEX_color_map':
532
- parameters.map = scope.getTexture( textureMap, child.ID );
533
- if ( parameters.map !== undefined ) {
534
-
535
- parameters.map.encoding = THREE.sRGBEncoding;
536
-
537
- }
538
-
539
- break;
540
- case 'DisplacementColor':
541
- parameters.displacementMap = scope.getTexture( textureMap, child.ID );
542
- break;
543
- case 'EmissiveColor':
544
- parameters.emissiveMap = scope.getTexture( textureMap, child.ID );
545
- if ( parameters.emissiveMap !== undefined ) {
546
-
547
- parameters.emissiveMap.encoding = THREE.sRGBEncoding;
548
-
549
- }
550
-
551
- break;
552
- case 'NormalMap':
553
- case 'Maya|TEX_normal_map':
554
- parameters.normalMap = scope.getTexture( textureMap, child.ID );
555
- break;
556
- case 'ReflectionColor':
557
- parameters.envMap = scope.getTexture( textureMap, child.ID );
558
- if ( parameters.envMap !== undefined ) {
559
-
560
- parameters.envMap.mapping = THREE.EquirectangularReflectionMapping;
561
- parameters.envMap.encoding = THREE.sRGBEncoding;
562
-
563
- }
564
-
565
- break;
566
- case 'SpecularColor':
567
- parameters.specularMap = scope.getTexture( textureMap, child.ID );
568
- if ( parameters.specularMap !== undefined ) {
569
-
570
- parameters.specularMap.encoding = THREE.sRGBEncoding;
571
-
572
- }
573
-
574
- break;
575
- case 'TransparentColor':
576
- case 'TransparencyFactor':
577
- parameters.alphaMap = scope.getTexture( textureMap, child.ID );
578
- parameters.transparent = true;
579
- break;
580
- case 'AmbientColor':
581
- case 'ShininessExponent': // AKA glossiness map
582
- case 'SpecularFactor': // AKA specularLevel
583
- case 'VectorDisplacementColor': // NOTE: Seems to be a copy of DisplacementColor
584
- default:
585
- console.warn( 'THREE.FBXLoader: %s map is not supported in three.js, skipping texture.', type );
586
- break;
587
-
588
- }
589
-
590
- } );
591
- return parameters;
592
-
593
- }
594
-
595
- // get a texture from the textureMap for use by a material.
596
- getTexture( textureMap, id ) {
597
-
598
- // if the texture is a layered texture, just use the first layer and issue a warning
599
- if ( 'LayeredTexture' in fbxTree.Objects && id in fbxTree.Objects.LayeredTexture ) {
600
-
601
- console.warn( 'THREE.FBXLoader: layered textures are not supported in three.js. Discarding all but first layer.' );
602
- id = connections.get( id ).children[ 0 ].ID;
603
-
604
- }
605
-
606
- return textureMap.get( id );
607
-
608
- }
609
-
610
- // Parse nodes in FBXTree.Objects.Deformer
611
- // Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here
612
- // Generates map of THREE.Skeleton-like objects for use later when generating and binding skeletons.
613
- parseDeformers() {
614
-
615
- const skeletons = {};
616
- const morphTargets = {};
617
- if ( 'Deformer' in fbxTree.Objects ) {
618
-
619
- const DeformerNodes = fbxTree.Objects.Deformer;
620
- for ( const nodeID in DeformerNodes ) {
621
-
622
- const deformerNode = DeformerNodes[ nodeID ];
623
- const relationships = connections.get( parseInt( nodeID ) );
624
- if ( deformerNode.attrType === 'Skin' ) {
625
-
626
- const skeleton = this.parseSkeleton( relationships, DeformerNodes );
627
- skeleton.ID = nodeID;
628
- if ( relationships.parents.length > 1 ) console.warn( 'THREE.FBXLoader: skeleton attached to more than one geometry is not supported.' );
629
- skeleton.geometryID = relationships.parents[ 0 ].ID;
630
- skeletons[ nodeID ] = skeleton;
631
-
632
- } else if ( deformerNode.attrType === 'BlendShape' ) {
633
-
634
- const morphTarget = {
635
- id: nodeID
636
- };
637
- morphTarget.rawTargets = this.parseMorphTargets( relationships, DeformerNodes );
638
- morphTarget.id = nodeID;
639
- if ( relationships.parents.length > 1 ) console.warn( 'THREE.FBXLoader: morph target attached to more than one geometry is not supported.' );
640
- morphTargets[ nodeID ] = morphTarget;
641
-
642
- }
643
-
644
- }
645
-
646
- }
647
-
648
- return {
649
- skeletons: skeletons,
650
- morphTargets: morphTargets
651
- };
652
-
653
- }
654
-
655
- // Parse single nodes in FBXTree.Objects.Deformer
656
- // The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster'
657
- // Each skin node represents a skeleton and each cluster node represents a bone
658
- parseSkeleton( relationships, deformerNodes ) {
659
-
660
- const rawBones = [];
661
- relationships.children.forEach( function ( child ) {
662
-
663
- const boneNode = deformerNodes[ child.ID ];
664
- if ( boneNode.attrType !== 'Cluster' ) return;
665
- const rawBone = {
666
- ID: child.ID,
667
- indices: [],
668
- weights: [],
669
- transformLink: new THREE.Matrix4().fromArray( boneNode.TransformLink.a )
670
- // transform: new THREE.Matrix4().fromArray( boneNode.Transform.a ),
671
- // linkMode: boneNode.Mode,
672
- };
673
-
674
- if ( 'Indexes' in boneNode ) {
675
-
676
- rawBone.indices = boneNode.Indexes.a;
677
- rawBone.weights = boneNode.Weights.a;
678
-
679
- }
680
-
681
- rawBones.push( rawBone );
682
-
683
- } );
684
- return {
685
- rawBones: rawBones,
686
- bones: []
687
- };
688
-
689
- }
690
-
691
- // The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel"
692
- parseMorphTargets( relationships, deformerNodes ) {
693
-
694
- const rawMorphTargets = [];
695
- for ( let i = 0; i < relationships.children.length; i ++ ) {
696
-
697
- const child = relationships.children[ i ];
698
- const morphTargetNode = deformerNodes[ child.ID ];
699
- const rawMorphTarget = {
700
- name: morphTargetNode.attrName,
701
- initialWeight: morphTargetNode.DeformPercent,
702
- id: morphTargetNode.id,
703
- fullWeights: morphTargetNode.FullWeights.a
704
- };
705
- if ( morphTargetNode.attrType !== 'BlendShapeChannel' ) return;
706
- rawMorphTarget.geoID = connections.get( parseInt( child.ID ) ).children.filter( function ( child ) {
707
-
708
- return child.relationship === undefined;
709
-
710
- } )[ 0 ].ID;
711
- rawMorphTargets.push( rawMorphTarget );
712
-
713
- }
714
-
715
- return rawMorphTargets;
716
-
717
- }
718
-
719
- // create the main THREE.Group() to be returned by the loader
720
- parseScene( deformers, geometryMap, materialMap ) {
721
-
722
- sceneGraph = new THREE.Group();
723
- const modelMap = this.parseModels( deformers.skeletons, geometryMap, materialMap );
724
- const modelNodes = fbxTree.Objects.Model;
725
- const scope = this;
726
- modelMap.forEach( function ( model ) {
727
-
728
- const modelNode = modelNodes[ model.ID ];
729
- scope.setLookAtProperties( model, modelNode );
730
- const parentConnections = connections.get( model.ID ).parents;
731
- parentConnections.forEach( function ( connection ) {
732
-
733
- const parent = modelMap.get( connection.ID );
734
- if ( parent !== undefined ) parent.add( model );
735
-
736
- } );
737
- if ( model.parent === null ) {
738
-
739
- sceneGraph.add( model );
740
-
741
- }
742
-
743
- } );
744
- this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
745
- this.createAmbientLight();
746
- sceneGraph.traverse( function ( node ) {
747
-
748
- if ( node.userData.transformData ) {
749
-
750
- if ( node.parent ) {
751
-
752
- node.userData.transformData.parentMatrix = node.parent.matrix;
753
- node.userData.transformData.parentMatrixWorld = node.parent.matrixWorld;
754
-
755
- }
756
-
757
- const transform = generateTransform( node.userData.transformData );
758
- node.applyMatrix4( transform );
759
- node.updateWorldMatrix();
760
-
761
- }
762
-
763
- } );
764
- const animations = new AnimationParser().parse();
765
-
766
- // if all the models where already combined in a single group, just return that
767
- if ( sceneGraph.children.length === 1 && sceneGraph.children[ 0 ].isGroup ) {
768
-
769
- sceneGraph.children[ 0 ].animations = animations;
770
- sceneGraph = sceneGraph.children[ 0 ];
771
-
772
- }
773
-
774
- sceneGraph.animations = animations;
775
-
776
- }
777
-
778
- // parse nodes in FBXTree.Objects.Model
779
- parseModels( skeletons, geometryMap, materialMap ) {
780
-
781
- const modelMap = new Map();
782
- const modelNodes = fbxTree.Objects.Model;
783
- for ( const nodeID in modelNodes ) {
784
-
785
- const id = parseInt( nodeID );
786
- const node = modelNodes[ nodeID ];
787
- const relationships = connections.get( id );
788
- let model = this.buildSkeleton( relationships, skeletons, id, node.attrName );
789
- if ( ! model ) {
790
-
791
- switch ( node.attrType ) {
792
-
793
- case 'Camera':
794
- model = this.createCamera( relationships );
795
- break;
796
- case 'Light':
797
- model = this.createLight( relationships );
798
- break;
799
- case 'Mesh':
800
- model = this.createMesh( relationships, geometryMap, materialMap );
801
- break;
802
- case 'NurbsCurve':
803
- model = this.createCurve( relationships, geometryMap );
804
- break;
805
- case 'LimbNode':
806
- case 'Root':
807
- model = new THREE.Bone();
808
- break;
809
- case 'Null':
810
- default:
811
- model = new THREE.Group();
812
- break;
813
-
814
- }
815
-
816
- model.name = node.attrName ? THREE.PropertyBinding.sanitizeNodeName( node.attrName ) : '';
817
- model.ID = id;
818
-
819
- }
820
-
821
- this.getTransformData( model, node );
822
- modelMap.set( id, model );
823
-
824
- }
825
-
826
- return modelMap;
827
-
828
- }
829
- buildSkeleton( relationships, skeletons, id, name ) {
830
-
831
- let bone = null;
832
- relationships.parents.forEach( function ( parent ) {
833
-
834
- for ( const ID in skeletons ) {
835
-
836
- const skeleton = skeletons[ ID ];
837
- skeleton.rawBones.forEach( function ( rawBone, i ) {
838
-
839
- if ( rawBone.ID === parent.ID ) {
840
-
841
- const subBone = bone;
842
- bone = new THREE.Bone();
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
846
-
847
- bone.name = name ? THREE.PropertyBinding.sanitizeNodeName( name ) : '';
848
- bone.ID = id;
849
- skeleton.bones[ i ] = bone;
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
853
- if ( subBone !== null ) {
854
-
855
- bone.add( subBone );
856
-
857
- }
858
-
859
- }
860
-
861
- } );
862
-
863
- }
864
-
865
- } );
866
- return bone;
867
-
868
- }
869
-
870
- // create a THREE.PerspectiveCamera or THREE.OrthographicCamera
871
- createCamera( relationships ) {
872
-
873
- let model;
874
- let cameraAttribute;
875
- relationships.children.forEach( function ( child ) {
876
-
877
- const attr = fbxTree.Objects.NodeAttribute[ child.ID ];
878
- if ( attr !== undefined ) {
879
-
880
- cameraAttribute = attr;
881
-
882
- }
883
-
884
- } );
885
- if ( cameraAttribute === undefined ) {
886
-
887
- model = new THREE.Object3D();
888
-
889
- } else {
890
-
891
- let type = 0;
892
- if ( cameraAttribute.CameraProjectionType !== undefined && cameraAttribute.CameraProjectionType.value === 1 ) {
893
-
894
- type = 1;
895
-
896
- }
897
-
898
- let nearClippingPlane = 1;
899
- if ( cameraAttribute.NearPlane !== undefined ) {
900
-
901
- nearClippingPlane = cameraAttribute.NearPlane.value / 1000;
902
-
903
- }
904
-
905
- let farClippingPlane = 1000;
906
- if ( cameraAttribute.FarPlane !== undefined ) {
907
-
908
- farClippingPlane = cameraAttribute.FarPlane.value / 1000;
909
-
910
- }
911
-
912
- let width = window.innerWidth;
913
- let height = window.innerHeight;
914
- if ( cameraAttribute.AspectWidth !== undefined && cameraAttribute.AspectHeight !== undefined ) {
915
-
916
- width = cameraAttribute.AspectWidth.value;
917
- height = cameraAttribute.AspectHeight.value;
918
-
919
- }
920
-
921
- const aspect = width / height;
922
- let fov = 45;
923
- if ( cameraAttribute.FieldOfView !== undefined ) {
924
-
925
- fov = cameraAttribute.FieldOfView.value;
926
-
927
- }
928
-
929
- const focalLength = cameraAttribute.FocalLength ? cameraAttribute.FocalLength.value : null;
930
- switch ( type ) {
931
-
932
- case 0:
933
- // Perspective
934
- model = new THREE.PerspectiveCamera( fov, aspect, nearClippingPlane, farClippingPlane );
935
- if ( focalLength !== null ) model.setFocalLength( focalLength );
936
- break;
937
- case 1:
938
- // Orthographic
939
- model = new THREE.OrthographicCamera( - width / 2, width / 2, height / 2, - height / 2, nearClippingPlane, farClippingPlane );
940
- break;
941
- default:
942
- console.warn( 'THREE.FBXLoader: Unknown camera type ' + type + '.' );
943
- model = new THREE.Object3D();
944
- break;
945
-
946
- }
947
-
948
- }
949
-
950
- return model;
951
-
952
- }
953
-
954
- // Create a THREE.DirectionalLight, THREE.PointLight or THREE.SpotLight
955
- createLight( relationships ) {
956
-
957
- let model;
958
- let lightAttribute;
959
- relationships.children.forEach( function ( child ) {
960
-
961
- const attr = fbxTree.Objects.NodeAttribute[ child.ID ];
962
- if ( attr !== undefined ) {
963
-
964
- lightAttribute = attr;
965
-
966
- }
967
-
968
- } );
969
- if ( lightAttribute === undefined ) {
970
-
971
- model = new THREE.Object3D();
972
-
973
- } else {
974
-
975
- let type;
976
-
977
- // LightType can be undefined for Point lights
978
- if ( lightAttribute.LightType === undefined ) {
979
-
980
- type = 0;
981
-
982
- } else {
983
-
984
- type = lightAttribute.LightType.value;
985
-
986
- }
987
-
988
- let color = 0xffffff;
989
- if ( lightAttribute.Color !== undefined ) {
990
-
991
- color = new THREE.Color().fromArray( lightAttribute.Color.value );
992
-
993
- }
994
-
995
- let intensity = lightAttribute.Intensity === undefined ? 1 : lightAttribute.Intensity.value / 100;
996
-
997
- // light disabled
998
- if ( lightAttribute.CastLightOnObject !== undefined && lightAttribute.CastLightOnObject.value === 0 ) {
999
-
1000
- intensity = 0;
1001
-
1002
- }
1003
-
1004
- let distance = 0;
1005
- if ( lightAttribute.FarAttenuationEnd !== undefined ) {
1006
-
1007
- if ( lightAttribute.EnableFarAttenuation !== undefined && lightAttribute.EnableFarAttenuation.value === 0 ) {
1008
-
1009
- distance = 0;
1010
-
1011
- } else {
1012
-
1013
- distance = lightAttribute.FarAttenuationEnd.value;
1014
-
1015
- }
1016
-
1017
- }
1018
-
1019
- // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd?
1020
- const decay = 1;
1021
- switch ( type ) {
1022
-
1023
- case 0:
1024
- // Point
1025
- model = new THREE.PointLight( color, intensity, distance, decay );
1026
- break;
1027
- case 1:
1028
- // Directional
1029
- model = new THREE.DirectionalLight( color, intensity );
1030
- break;
1031
- case 2:
1032
- // Spot
1033
- let angle = Math.PI / 3;
1034
- if ( lightAttribute.InnerAngle !== undefined ) {
1035
-
1036
- angle = THREE.MathUtils.degToRad( lightAttribute.InnerAngle.value );
1037
-
1038
- }
1039
-
1040
- let penumbra = 0;
1041
- if ( lightAttribute.OuterAngle !== undefined ) {
1042
-
1043
- // TODO: this is not correct - FBX calculates outer and inner angle in degrees
1044
- // with OuterAngle > InnerAngle && OuterAngle <= Math.PI
1045
- // while three.js uses a penumbra between (0, 1) to attenuate the inner angle
1046
- penumbra = THREE.MathUtils.degToRad( lightAttribute.OuterAngle.value );
1047
- penumbra = Math.max( penumbra, 1 );
1048
-
1049
- }
1050
-
1051
- model = new THREE.SpotLight( color, intensity, distance, angle, penumbra, decay );
1052
- break;
1053
- default:
1054
- console.warn( 'THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a THREE.PointLight.' );
1055
- model = new THREE.PointLight( color, intensity );
1056
- break;
1057
-
1058
- }
1059
-
1060
- if ( lightAttribute.CastShadows !== undefined && lightAttribute.CastShadows.value === 1 ) {
1061
-
1062
- model.castShadow = true;
1063
-
1064
- }
1065
-
1066
- }
1067
-
1068
- return model;
1069
-
1070
- }
1071
- createMesh( relationships, geometryMap, materialMap ) {
1072
-
1073
- let model;
1074
- let geometry = null;
1075
- let material = null;
1076
- const materials = [];
1077
-
1078
- // get geometry and materials(s) from connections
1079
- relationships.children.forEach( function ( child ) {
1080
-
1081
- if ( geometryMap.has( child.ID ) ) {
1082
-
1083
- geometry = geometryMap.get( child.ID );
1084
-
1085
- }
1086
-
1087
- if ( materialMap.has( child.ID ) ) {
1088
-
1089
- materials.push( materialMap.get( child.ID ) );
1090
-
1091
- }
1092
-
1093
- } );
1094
- if ( materials.length > 1 ) {
1095
-
1096
- material = materials;
1097
-
1098
- } else if ( materials.length > 0 ) {
1099
-
1100
- material = materials[ 0 ];
1101
-
1102
- } else {
1103
-
1104
- material = new THREE.MeshPhongMaterial( {
1105
- color: 0xcccccc
1106
- } );
1107
- materials.push( material );
1108
-
1109
- }
1110
-
1111
- if ( 'color' in geometry.attributes ) {
1112
-
1113
- materials.forEach( function ( material ) {
1114
-
1115
- material.vertexColors = true;
1116
-
1117
- } );
1118
-
1119
- }
1120
-
1121
- if ( geometry.FBX_Deformer ) {
1122
-
1123
- model = new THREE.SkinnedMesh( geometry, material );
1124
- model.normalizeSkinWeights();
1125
-
1126
- } else {
1127
-
1128
- model = new THREE.Mesh( geometry, material );
1129
-
1130
- }
1131
-
1132
- return model;
1133
-
1134
- }
1135
- createCurve( relationships, geometryMap ) {
1136
-
1137
- const geometry = relationships.children.reduce( function ( geo, child ) {
1138
-
1139
- if ( geometryMap.has( child.ID ) ) geo = geometryMap.get( child.ID );
1140
- return geo;
1141
-
1142
- }, null );
1143
-
1144
- // FBX does not list materials for Nurbs lines, so we'll just put our own in here.
1145
- const material = new THREE.LineBasicMaterial( {
1146
- color: 0x3300ff,
1147
- linewidth: 1
1148
- } );
1149
- return new THREE.Line( geometry, material );
1150
-
1151
- }
1152
-
1153
- // parse the model node for transform data
1154
- getTransformData( model, modelNode ) {
1155
-
1156
- const transformData = {};
1157
- if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value );
1158
- if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value ); else transformData.eulerOrder = 'ZYX';
1159
- if ( 'Lcl_Translation' in modelNode ) transformData.translation = modelNode.Lcl_Translation.value;
1160
- if ( 'PreRotation' in modelNode ) transformData.preRotation = modelNode.PreRotation.value;
1161
- if ( 'Lcl_Rotation' in modelNode ) transformData.rotation = modelNode.Lcl_Rotation.value;
1162
- if ( 'PostRotation' in modelNode ) transformData.postRotation = modelNode.PostRotation.value;
1163
- if ( 'Lcl_Scaling' in modelNode ) transformData.scale = modelNode.Lcl_Scaling.value;
1164
- if ( 'ScalingOffset' in modelNode ) transformData.scalingOffset = modelNode.ScalingOffset.value;
1165
- if ( 'ScalingPivot' in modelNode ) transformData.scalingPivot = modelNode.ScalingPivot.value;
1166
- if ( 'RotationOffset' in modelNode ) transformData.rotationOffset = modelNode.RotationOffset.value;
1167
- if ( 'RotationPivot' in modelNode ) transformData.rotationPivot = modelNode.RotationPivot.value;
1168
- model.userData.transformData = transformData;
1169
-
1170
- }
1171
- setLookAtProperties( model, modelNode ) {
1172
-
1173
- if ( 'LookAtProperty' in modelNode ) {
1174
-
1175
- const children = connections.get( model.ID ).children;
1176
- children.forEach( function ( child ) {
1177
-
1178
- if ( child.relationship === 'LookAtProperty' ) {
1179
-
1180
- const lookAtTarget = fbxTree.Objects.Model[ child.ID ];
1181
- if ( 'Lcl_Translation' in lookAtTarget ) {
1182
-
1183
- const pos = lookAtTarget.Lcl_Translation.value;
1184
-
1185
- // THREE.DirectionalLight, THREE.SpotLight
1186
- if ( model.target !== undefined ) {
1187
-
1188
- model.target.position.fromArray( pos );
1189
- sceneGraph.add( model.target );
1190
-
1191
- } else {
1192
-
1193
- // Cameras and other Object3Ds
1194
-
1195
- model.lookAt( new THREE.Vector3().fromArray( pos ) );
1196
-
1197
- }
1198
-
1199
- }
1200
-
1201
- }
1202
-
1203
- } );
1204
-
1205
- }
1206
-
1207
- }
1208
- bindSkeleton( skeletons, geometryMap, modelMap ) {
1209
-
1210
- const bindMatrices = this.parsePoseNodes();
1211
- for ( const ID in skeletons ) {
1212
-
1213
- const skeleton = skeletons[ ID ];
1214
- const parents = connections.get( parseInt( skeleton.ID ) ).parents;
1215
- parents.forEach( function ( parent ) {
1216
-
1217
- if ( geometryMap.has( parent.ID ) ) {
1218
-
1219
- const geoID = parent.ID;
1220
- const geoRelationships = connections.get( geoID );
1221
- geoRelationships.parents.forEach( function ( geoConnParent ) {
1222
-
1223
- if ( modelMap.has( geoConnParent.ID ) ) {
1224
-
1225
- const model = modelMap.get( geoConnParent.ID );
1226
- model.bind( new THREE.Skeleton( skeleton.bones ), bindMatrices[ geoConnParent.ID ] );
1227
-
1228
- }
1229
-
1230
- } );
1231
-
1232
- }
1233
-
1234
- } );
1235
-
1236
- }
1237
-
1238
- }
1239
- parsePoseNodes() {
1240
-
1241
- const bindMatrices = {};
1242
- if ( 'Pose' in fbxTree.Objects ) {
1243
-
1244
- const BindPoseNode = fbxTree.Objects.Pose;
1245
- for ( const nodeID in BindPoseNode ) {
1246
-
1247
- if ( BindPoseNode[ nodeID ].attrType === 'BindPose' && BindPoseNode[ nodeID ].NbPoseNodes > 0 ) {
1248
-
1249
- const poseNodes = BindPoseNode[ nodeID ].PoseNode;
1250
- if ( Array.isArray( poseNodes ) ) {
1251
-
1252
- poseNodes.forEach( function ( poseNode ) {
1253
-
1254
- bindMatrices[ poseNode.Node ] = new THREE.Matrix4().fromArray( poseNode.Matrix.a );
1255
-
1256
- } );
1257
-
1258
- } else {
1259
-
1260
- bindMatrices[ poseNodes.Node ] = new THREE.Matrix4().fromArray( poseNodes.Matrix.a );
1261
-
1262
- }
1263
-
1264
- }
1265
-
1266
- }
1267
-
1268
- }
1269
-
1270
- return bindMatrices;
1271
-
1272
- }
1273
-
1274
- // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light
1275
- createAmbientLight() {
1276
-
1277
- if ( 'GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings ) {
1278
-
1279
- const ambientColor = fbxTree.GlobalSettings.AmbientColor.value;
1280
- const r = ambientColor[ 0 ];
1281
- const g = ambientColor[ 1 ];
1282
- const b = ambientColor[ 2 ];
1283
- if ( r !== 0 || g !== 0 || b !== 0 ) {
1284
-
1285
- const color = new THREE.Color( r, g, b );
1286
- sceneGraph.add( new THREE.AmbientLight( color, 1 ) );
1287
-
1288
- }
1289
-
1290
- }
1291
-
1292
- }
1293
-
1294
- }
1295
-
1296
- // parse Geometry data from FBXTree and return map of BufferGeometries
1297
- class GeometryParser {
1298
-
1299
- constructor() {
1300
-
1301
- this.negativeMaterialIndices = false;
1302
-
1303
- }
1304
-
1305
- // Parse nodes in FBXTree.Objects.Geometry
1306
- parse( deformers ) {
1307
-
1308
- const geometryMap = new Map();
1309
- if ( 'Geometry' in fbxTree.Objects ) {
1310
-
1311
- const geoNodes = fbxTree.Objects.Geometry;
1312
- for ( const nodeID in geoNodes ) {
1313
-
1314
- const relationships = connections.get( parseInt( nodeID ) );
1315
- const geo = this.parseGeometry( relationships, geoNodes[ nodeID ], deformers );
1316
- geometryMap.set( parseInt( nodeID ), geo );
1317
-
1318
- }
1319
-
1320
- }
1321
-
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
- }
1329
-
1330
- return geometryMap;
1331
-
1332
- }
1333
-
1334
- // Parse single node in FBXTree.Objects.Geometry
1335
- parseGeometry( relationships, geoNode, deformers ) {
1336
-
1337
- switch ( geoNode.attrType ) {
1338
-
1339
- case 'Mesh':
1340
- return this.parseMeshGeometry( relationships, geoNode, deformers );
1341
- break;
1342
- case 'NurbsCurve':
1343
- return this.parseNurbsGeometry( geoNode );
1344
- break;
1345
-
1346
- }
1347
-
1348
- }
1349
-
1350
- // Parse single node mesh geometry in FBXTree.Objects.Geometry
1351
- parseMeshGeometry( relationships, geoNode, deformers ) {
1352
-
1353
- const skeletons = deformers.skeletons;
1354
- const morphTargets = [];
1355
- const modelNodes = relationships.parents.map( function ( parent ) {
1356
-
1357
- return fbxTree.Objects.Model[ parent.ID ];
1358
-
1359
- } );
1360
-
1361
- // don't create geometry if it is not associated with any models
1362
- if ( modelNodes.length === 0 ) return;
1363
- const skeleton = relationships.children.reduce( function ( skeleton, child ) {
1364
-
1365
- if ( skeletons[ child.ID ] !== undefined ) skeleton = skeletons[ child.ID ];
1366
- return skeleton;
1367
-
1368
- }, null );
1369
- relationships.children.forEach( function ( child ) {
1370
-
1371
- if ( deformers.morphTargets[ child.ID ] !== undefined ) {
1372
-
1373
- morphTargets.push( deformers.morphTargets[ child.ID ] );
1374
-
1375
- }
1376
-
1377
- } );
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
1381
- const modelNode = modelNodes[ 0 ];
1382
- const transformData = {};
1383
- if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value );
1384
- if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value );
1385
- if ( 'GeometricTranslation' in modelNode ) transformData.translation = modelNode.GeometricTranslation.value;
1386
- if ( 'GeometricRotation' in modelNode ) transformData.rotation = modelNode.GeometricRotation.value;
1387
- if ( 'GeometricScaling' in modelNode ) transformData.scale = modelNode.GeometricScaling.value;
1388
- const transform = generateTransform( transformData );
1389
- return this.genGeometry( geoNode, skeleton, morphTargets, transform );
1390
-
1391
- }
1392
-
1393
- // Generate a THREE.BufferGeometry from a node in FBXTree.Objects.Geometry
1394
- genGeometry( geoNode, skeleton, morphTargets, preTransform ) {
1395
-
1396
- const geo = new THREE.BufferGeometry();
1397
- if ( geoNode.attrName ) geo.name = geoNode.attrName;
1398
- const geoInfo = this.parseGeoNode( geoNode, skeleton );
1399
- const buffers = this.genBuffers( geoInfo );
1400
- const positionAttribute = new THREE.Float32BufferAttribute( buffers.vertex, 3 );
1401
- positionAttribute.applyMatrix4( preTransform );
1402
- geo.setAttribute( 'position', positionAttribute );
1403
- if ( buffers.colors.length > 0 ) {
1404
-
1405
- geo.setAttribute( 'color', new THREE.Float32BufferAttribute( buffers.colors, 3 ) );
1406
-
1407
- }
1408
-
1409
- if ( skeleton ) {
1410
-
1411
- geo.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( buffers.weightsIndices, 4 ) );
1412
- geo.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( buffers.vertexWeights, 4 ) );
1413
-
1414
- // used later to bind the skeleton to the model
1415
- geo.FBX_Deformer = skeleton;
1416
-
1417
- }
1418
-
1419
- if ( buffers.normal.length > 0 ) {
1420
-
1421
- const normalMatrix = new THREE.Matrix3().getNormalMatrix( preTransform );
1422
- const normalAttribute = new THREE.Float32BufferAttribute( buffers.normal, 3 );
1423
- normalAttribute.applyNormalMatrix( normalMatrix );
1424
- geo.setAttribute( 'normal', normalAttribute );
1425
-
1426
- }
1427
-
1428
- buffers.uvs.forEach( function ( uvBuffer, i ) {
1429
-
1430
- // subsequent uv buffers are called 'uv1', 'uv2', ...
1431
- let name = 'uv' + ( i + 1 ).toString();
1432
-
1433
- // the first uv buffer is just called 'uv'
1434
- if ( i === 0 ) {
1435
-
1436
- name = 'uv';
1437
-
1438
- }
1439
-
1440
- geo.setAttribute( name, new THREE.Float32BufferAttribute( buffers.uvs[ i ], 2 ) );
1441
-
1442
- } );
1443
- if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) {
1444
-
1445
- // Convert the material indices of each vertex into rendering groups on the geometry.
1446
- let prevMaterialIndex = buffers.materialIndex[ 0 ];
1447
- let startIndex = 0;
1448
- buffers.materialIndex.forEach( function ( currentIndex, i ) {
1449
-
1450
- if ( currentIndex !== prevMaterialIndex ) {
1451
-
1452
- geo.addGroup( startIndex, i - startIndex, prevMaterialIndex );
1453
- prevMaterialIndex = currentIndex;
1454
- startIndex = i;
1455
-
1456
- }
1457
-
1458
- } );
1459
-
1460
- // the loop above doesn't add the last group, do that here.
1461
- if ( geo.groups.length > 0 ) {
1462
-
1463
- const lastGroup = geo.groups[ geo.groups.length - 1 ];
1464
- const lastIndex = lastGroup.start + lastGroup.count;
1465
- if ( lastIndex !== buffers.materialIndex.length ) {
1466
-
1467
- geo.addGroup( lastIndex, buffers.materialIndex.length - lastIndex, prevMaterialIndex );
1468
-
1469
- }
1470
-
1471
- }
1472
-
1473
- // case where there are multiple materials but the whole geometry is only
1474
- // using one of them
1475
- if ( geo.groups.length === 0 ) {
1476
-
1477
- geo.addGroup( 0, buffers.materialIndex.length, buffers.materialIndex[ 0 ] );
1478
-
1479
- }
1480
-
1481
- }
1482
-
1483
- this.addMorphTargets( geo, geoNode, morphTargets, preTransform );
1484
- return geo;
1485
-
1486
- }
1487
- parseGeoNode( geoNode, skeleton ) {
1488
-
1489
- const geoInfo = {};
1490
- geoInfo.vertexPositions = geoNode.Vertices !== undefined ? geoNode.Vertices.a : [];
1491
- geoInfo.vertexIndices = geoNode.PolygonVertexIndex !== undefined ? geoNode.PolygonVertexIndex.a : [];
1492
- if ( geoNode.LayerElementColor ) {
1493
-
1494
- geoInfo.color = this.parseVertexColors( geoNode.LayerElementColor[ 0 ] );
1495
-
1496
- }
1497
-
1498
- if ( geoNode.LayerElementMaterial ) {
1499
-
1500
- geoInfo.material = this.parseMaterialIndices( geoNode.LayerElementMaterial[ 0 ] );
1501
-
1502
- }
1503
-
1504
- if ( geoNode.LayerElementNormal ) {
1505
-
1506
- geoInfo.normal = this.parseNormals( geoNode.LayerElementNormal[ 0 ] );
1507
-
1508
- }
1509
-
1510
- if ( geoNode.LayerElementUV ) {
1511
-
1512
- geoInfo.uv = [];
1513
- let i = 0;
1514
- while ( geoNode.LayerElementUV[ i ] ) {
1515
-
1516
- if ( geoNode.LayerElementUV[ i ].UV ) {
1517
-
1518
- geoInfo.uv.push( this.parseUVs( geoNode.LayerElementUV[ i ] ) );
1519
-
1520
- }
1521
-
1522
- i ++;
1523
-
1524
- }
1525
-
1526
- }
1527
-
1528
- geoInfo.weightTable = {};
1529
- if ( skeleton !== null ) {
1530
-
1531
- geoInfo.skeleton = skeleton;
1532
- skeleton.rawBones.forEach( function ( rawBone, i ) {
1533
-
1534
- // loop over the bone's vertex indices and weights
1535
- rawBone.indices.forEach( function ( index, j ) {
1536
-
1537
- if ( geoInfo.weightTable[ index ] === undefined ) geoInfo.weightTable[ index ] = [];
1538
- geoInfo.weightTable[ index ].push( {
1539
- id: i,
1540
- weight: rawBone.weights[ j ]
1541
- } );
1542
-
1543
- } );
1544
-
1545
- } );
1546
-
1547
- }
1548
-
1549
- return geoInfo;
1550
-
1551
- }
1552
- genBuffers( geoInfo ) {
1553
-
1554
- const buffers = {
1555
- vertex: [],
1556
- normal: [],
1557
- colors: [],
1558
- uvs: [],
1559
- materialIndex: [],
1560
- vertexWeights: [],
1561
- weightsIndices: []
1562
- };
1563
- let polygonIndex = 0;
1564
- let faceLength = 0;
1565
- let displayedWeightsWarning = false;
1566
-
1567
- // these will hold data for a single face
1568
- let facePositionIndexes = [];
1569
- let faceNormals = [];
1570
- let faceColors = [];
1571
- let faceUVs = [];
1572
- let faceWeights = [];
1573
- let faceWeightIndices = [];
1574
- const scope = this;
1575
- geoInfo.vertexIndices.forEach( function ( vertexIndex, polygonVertexIndex ) {
1576
-
1577
- let materialIndex;
1578
- let endOfFace = false;
1579
-
1580
- // Face index and vertex index arrays are combined in a single array
1581
- // A cube with quad faces looks like this:
1582
- // PolygonVertexIndex: *24 {
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
1584
- // }
1585
- // Negative numbers mark the end of a face - first face here is 0, 1, 3, -3
1586
- // to find index of last vertex bit shift the index: ^ - 1
1587
- if ( vertexIndex < 0 ) {
1588
-
1589
- vertexIndex = vertexIndex ^ - 1; // equivalent to ( x * -1 ) - 1
1590
- endOfFace = true;
1591
-
1592
- }
1593
-
1594
- let weightIndices = [];
1595
- let weights = [];
1596
- facePositionIndexes.push( vertexIndex * 3, vertexIndex * 3 + 1, vertexIndex * 3 + 2 );
1597
- if ( geoInfo.color ) {
1598
-
1599
- const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.color );
1600
- faceColors.push( data[ 0 ], data[ 1 ], data[ 2 ] );
1601
-
1602
- }
1603
-
1604
- if ( geoInfo.skeleton ) {
1605
-
1606
- if ( geoInfo.weightTable[ vertexIndex ] !== undefined ) {
1607
-
1608
- geoInfo.weightTable[ vertexIndex ].forEach( function ( wt ) {
1609
-
1610
- weights.push( wt.weight );
1611
- weightIndices.push( wt.id );
1612
-
1613
- } );
1614
-
1615
- }
1616
-
1617
- if ( weights.length > 4 ) {
1618
-
1619
- if ( ! displayedWeightsWarning ) {
1620
-
1621
- console.warn( 'THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights.' );
1622
- displayedWeightsWarning = true;
1623
-
1624
- }
1625
-
1626
- const wIndex = [ 0, 0, 0, 0 ];
1627
- const Weight = [ 0, 0, 0, 0 ];
1628
- weights.forEach( function ( weight, weightIndex ) {
1629
-
1630
- let currentWeight = weight;
1631
- let currentIndex = weightIndices[ weightIndex ];
1632
- Weight.forEach( function ( comparedWeight, comparedWeightIndex, comparedWeightArray ) {
1633
-
1634
- if ( currentWeight > comparedWeight ) {
1635
-
1636
- comparedWeightArray[ comparedWeightIndex ] = currentWeight;
1637
- currentWeight = comparedWeight;
1638
- const tmp = wIndex[ comparedWeightIndex ];
1639
- wIndex[ comparedWeightIndex ] = currentIndex;
1640
- currentIndex = tmp;
1641
-
1642
- }
1643
-
1644
- } );
1645
-
1646
- } );
1647
- weightIndices = wIndex;
1648
- weights = Weight;
1649
-
1650
- }
1651
-
1652
- // if the weight array is shorter than 4 pad with 0s
1653
- while ( weights.length < 4 ) {
1654
-
1655
- weights.push( 0 );
1656
- weightIndices.push( 0 );
1657
-
1658
- }
1659
-
1660
- for ( let i = 0; i < 4; ++ i ) {
1661
-
1662
- faceWeights.push( weights[ i ] );
1663
- faceWeightIndices.push( weightIndices[ i ] );
1664
-
1665
- }
1666
-
1667
- }
1668
-
1669
- if ( geoInfo.normal ) {
1670
-
1671
- const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.normal );
1672
- faceNormals.push( data[ 0 ], data[ 1 ], data[ 2 ] );
1673
-
1674
- }
1675
-
1676
- if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) {
1677
-
1678
- materialIndex = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material )[ 0 ];
1679
- if ( materialIndex < 0 ) {
1680
-
1681
- scope.negativeMaterialIndices = true;
1682
- materialIndex = 0; // fallback
1683
-
1684
- }
1685
-
1686
- }
1687
-
1688
- if ( geoInfo.uv ) {
1689
-
1690
- geoInfo.uv.forEach( function ( uv, i ) {
1691
-
1692
- const data = getData( polygonVertexIndex, polygonIndex, vertexIndex, uv );
1693
- if ( faceUVs[ i ] === undefined ) {
1694
-
1695
- faceUVs[ i ] = [];
1696
-
1697
- }
1698
-
1699
- faceUVs[ i ].push( data[ 0 ] );
1700
- faceUVs[ i ].push( data[ 1 ] );
1701
-
1702
- } );
1703
-
1704
- }
1705
-
1706
- faceLength ++;
1707
- if ( endOfFace ) {
1708
-
1709
- scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength );
1710
- polygonIndex ++;
1711
- faceLength = 0;
1712
-
1713
- // reset arrays for the next face
1714
- facePositionIndexes = [];
1715
- faceNormals = [];
1716
- faceColors = [];
1717
- faceUVs = [];
1718
- faceWeights = [];
1719
- faceWeightIndices = [];
1720
-
1721
- }
1722
-
1723
- } );
1724
- return buffers;
1725
-
1726
- }
1727
-
1728
- // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
1729
- genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength ) {
1730
-
1731
- for ( let i = 2; i < faceLength; i ++ ) {
1732
-
1733
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 0 ] ] );
1734
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 1 ] ] );
1735
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ 2 ] ] );
1736
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 ] ] );
1737
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 1 ] ] );
1738
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ ( i - 1 ) * 3 + 2 ] ] );
1739
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 ] ] );
1740
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 1 ] ] );
1741
- buffers.vertex.push( geoInfo.vertexPositions[ facePositionIndexes[ i * 3 + 2 ] ] );
1742
- if ( geoInfo.skeleton ) {
1743
-
1744
- buffers.vertexWeights.push( faceWeights[ 0 ] );
1745
- buffers.vertexWeights.push( faceWeights[ 1 ] );
1746
- buffers.vertexWeights.push( faceWeights[ 2 ] );
1747
- buffers.vertexWeights.push( faceWeights[ 3 ] );
1748
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 ] );
1749
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 1 ] );
1750
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 2 ] );
1751
- buffers.vertexWeights.push( faceWeights[ ( i - 1 ) * 4 + 3 ] );
1752
- buffers.vertexWeights.push( faceWeights[ i * 4 ] );
1753
- buffers.vertexWeights.push( faceWeights[ i * 4 + 1 ] );
1754
- buffers.vertexWeights.push( faceWeights[ i * 4 + 2 ] );
1755
- buffers.vertexWeights.push( faceWeights[ i * 4 + 3 ] );
1756
- buffers.weightsIndices.push( faceWeightIndices[ 0 ] );
1757
- buffers.weightsIndices.push( faceWeightIndices[ 1 ] );
1758
- buffers.weightsIndices.push( faceWeightIndices[ 2 ] );
1759
- buffers.weightsIndices.push( faceWeightIndices[ 3 ] );
1760
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 ] );
1761
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 1 ] );
1762
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 2 ] );
1763
- buffers.weightsIndices.push( faceWeightIndices[ ( i - 1 ) * 4 + 3 ] );
1764
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 ] );
1765
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 1 ] );
1766
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 2 ] );
1767
- buffers.weightsIndices.push( faceWeightIndices[ i * 4 + 3 ] );
1768
-
1769
- }
1770
-
1771
- if ( geoInfo.color ) {
1772
-
1773
- buffers.colors.push( faceColors[ 0 ] );
1774
- buffers.colors.push( faceColors[ 1 ] );
1775
- buffers.colors.push( faceColors[ 2 ] );
1776
- buffers.colors.push( faceColors[ ( i - 1 ) * 3 ] );
1777
- buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 1 ] );
1778
- buffers.colors.push( faceColors[ ( i - 1 ) * 3 + 2 ] );
1779
- buffers.colors.push( faceColors[ i * 3 ] );
1780
- buffers.colors.push( faceColors[ i * 3 + 1 ] );
1781
- buffers.colors.push( faceColors[ i * 3 + 2 ] );
1782
-
1783
- }
1784
-
1785
- if ( geoInfo.material && geoInfo.material.mappingType !== 'AllSame' ) {
1786
-
1787
- buffers.materialIndex.push( materialIndex );
1788
- buffers.materialIndex.push( materialIndex );
1789
- buffers.materialIndex.push( materialIndex );
1790
-
1791
- }
1792
-
1793
- if ( geoInfo.normal ) {
1794
-
1795
- buffers.normal.push( faceNormals[ 0 ] );
1796
- buffers.normal.push( faceNormals[ 1 ] );
1797
- buffers.normal.push( faceNormals[ 2 ] );
1798
- buffers.normal.push( faceNormals[ ( i - 1 ) * 3 ] );
1799
- buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 1 ] );
1800
- buffers.normal.push( faceNormals[ ( i - 1 ) * 3 + 2 ] );
1801
- buffers.normal.push( faceNormals[ i * 3 ] );
1802
- buffers.normal.push( faceNormals[ i * 3 + 1 ] );
1803
- buffers.normal.push( faceNormals[ i * 3 + 2 ] );
1804
-
1805
- }
1806
-
1807
- if ( geoInfo.uv ) {
1808
-
1809
- geoInfo.uv.forEach( function ( uv, j ) {
1810
-
1811
- if ( buffers.uvs[ j ] === undefined ) buffers.uvs[ j ] = [];
1812
- buffers.uvs[ j ].push( faceUVs[ j ][ 0 ] );
1813
- buffers.uvs[ j ].push( faceUVs[ j ][ 1 ] );
1814
- buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 ] );
1815
- buffers.uvs[ j ].push( faceUVs[ j ][ ( i - 1 ) * 2 + 1 ] );
1816
- buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 ] );
1817
- buffers.uvs[ j ].push( faceUVs[ j ][ i * 2 + 1 ] );
1818
-
1819
- } );
1820
-
1821
- }
1822
-
1823
- }
1824
-
1825
- }
1826
- addMorphTargets( parentGeo, parentGeoNode, morphTargets, preTransform ) {
1827
-
1828
- if ( morphTargets.length === 0 ) return;
1829
- parentGeo.morphTargetsRelative = true;
1830
- parentGeo.morphAttributes.position = [];
1831
- // parentGeo.morphAttributes.normal = []; // not implemented
1832
-
1833
- const scope = this;
1834
- morphTargets.forEach( function ( morphTarget ) {
1835
-
1836
- morphTarget.rawTargets.forEach( function ( rawTarget ) {
1837
-
1838
- const morphGeoNode = fbxTree.Objects.Geometry[ rawTarget.geoID ];
1839
- if ( morphGeoNode !== undefined ) {
1840
-
1841
- scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name );
1842
-
1843
- }
1844
-
1845
- } );
1846
-
1847
- } );
1848
-
1849
- }
1850
-
1851
- // a morph geometry node is similar to a standard node, and the node is also contained
1852
- // in FBXTree.Objects.Geometry, however it can only have attributes for position, normal
1853
- // and a special attribute Index defining which vertices of the original geometry are affected
1854
- // Normal and position attributes only have data for the vertices that are affected by the morph
1855
- genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, name ) {
1856
-
1857
- const vertexIndices = parentGeoNode.PolygonVertexIndex !== undefined ? parentGeoNode.PolygonVertexIndex.a : [];
1858
- const morphPositionsSparse = morphGeoNode.Vertices !== undefined ? morphGeoNode.Vertices.a : [];
1859
- const indices = morphGeoNode.Indexes !== undefined ? morphGeoNode.Indexes.a : [];
1860
- const length = parentGeo.attributes.position.count * 3;
1861
- const morphPositions = new Float32Array( length );
1862
- for ( let i = 0; i < indices.length; i ++ ) {
1863
-
1864
- const morphIndex = indices[ i ] * 3;
1865
- morphPositions[ morphIndex ] = morphPositionsSparse[ i * 3 ];
1866
- morphPositions[ morphIndex + 1 ] = morphPositionsSparse[ i * 3 + 1 ];
1867
- morphPositions[ morphIndex + 2 ] = morphPositionsSparse[ i * 3 + 2 ];
1868
-
1869
- }
1870
-
1871
- // TODO: add morph normal support
1872
- const morphGeoInfo = {
1873
- vertexIndices: vertexIndices,
1874
- vertexPositions: morphPositions
1875
- };
1876
- const morphBuffers = this.genBuffers( morphGeoInfo );
1877
- const positionAttribute = new THREE.Float32BufferAttribute( morphBuffers.vertex, 3 );
1878
- positionAttribute.name = name || morphGeoNode.attrName;
1879
- positionAttribute.applyMatrix4( preTransform );
1880
- parentGeo.morphAttributes.position.push( positionAttribute );
1881
-
1882
- }
1883
-
1884
- // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists
1885
- parseNormals( NormalNode ) {
1886
-
1887
- const mappingType = NormalNode.MappingInformationType;
1888
- const referenceType = NormalNode.ReferenceInformationType;
1889
- const buffer = NormalNode.Normals.a;
1890
- let indexBuffer = [];
1891
- if ( referenceType === 'IndexToDirect' ) {
1892
-
1893
- if ( 'NormalIndex' in NormalNode ) {
1894
-
1895
- indexBuffer = NormalNode.NormalIndex.a;
1896
-
1897
- } else if ( 'NormalsIndex' in NormalNode ) {
1898
-
1899
- indexBuffer = NormalNode.NormalsIndex.a;
1900
-
1901
- }
1902
-
1903
- }
1904
-
1905
- return {
1906
- dataSize: 3,
1907
- buffer: buffer,
1908
- indices: indexBuffer,
1909
- mappingType: mappingType,
1910
- referenceType: referenceType
1911
- };
1912
-
1913
- }
1914
-
1915
- // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists
1916
- parseUVs( UVNode ) {
1917
-
1918
- const mappingType = UVNode.MappingInformationType;
1919
- const referenceType = UVNode.ReferenceInformationType;
1920
- const buffer = UVNode.UV.a;
1921
- let indexBuffer = [];
1922
- if ( referenceType === 'IndexToDirect' ) {
1923
-
1924
- indexBuffer = UVNode.UVIndex.a;
1925
-
1926
- }
1927
-
1928
- return {
1929
- dataSize: 2,
1930
- buffer: buffer,
1931
- indices: indexBuffer,
1932
- mappingType: mappingType,
1933
- referenceType: referenceType
1934
- };
1935
-
1936
- }
1937
-
1938
- // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists
1939
- parseVertexColors( ColorNode ) {
1940
-
1941
- const mappingType = ColorNode.MappingInformationType;
1942
- const referenceType = ColorNode.ReferenceInformationType;
1943
- const buffer = ColorNode.Colors.a;
1944
- let indexBuffer = [];
1945
- if ( referenceType === 'IndexToDirect' ) {
1946
-
1947
- indexBuffer = ColorNode.ColorIndex.a;
1948
-
1949
- }
1950
-
1951
- return {
1952
- dataSize: 4,
1953
- buffer: buffer,
1954
- indices: indexBuffer,
1955
- mappingType: mappingType,
1956
- referenceType: referenceType
1957
- };
1958
-
1959
- }
1960
-
1961
- // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists
1962
- parseMaterialIndices( MaterialNode ) {
1963
-
1964
- const mappingType = MaterialNode.MappingInformationType;
1965
- const referenceType = MaterialNode.ReferenceInformationType;
1966
- if ( mappingType === 'NoMappingInformation' ) {
1967
-
1968
- return {
1969
- dataSize: 1,
1970
- buffer: [ 0 ],
1971
- indices: [ 0 ],
1972
- mappingType: 'AllSame',
1973
- referenceType: referenceType
1974
- };
1975
-
1976
- }
1977
-
1978
- const materialIndexBuffer = MaterialNode.Materials.a;
1979
-
1980
- // Since materials are stored as indices, there's a bit of a mismatch between FBX and what
1981
- // we expect.So we create an intermediate buffer that points to the index in the buffer,
1982
- // for conforming with the other functions we've written for other data.
1983
- const materialIndices = [];
1984
- for ( let i = 0; i < materialIndexBuffer.length; ++ i ) {
1985
-
1986
- materialIndices.push( i );
1987
-
1988
- }
1989
-
1990
- return {
1991
- dataSize: 1,
1992
- buffer: materialIndexBuffer,
1993
- indices: materialIndices,
1994
- mappingType: mappingType,
1995
- referenceType: referenceType
1996
- };
1997
-
1998
- }
1999
-
2000
- // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry
2001
- parseNurbsGeometry( geoNode ) {
2002
-
2003
- if ( THREE.NURBSCurve === undefined ) {
2004
-
2005
- console.error( 'THREE.FBXLoader: The loader relies on THREE.NURBSCurve for any nurbs present in the model. Nurbs will show up as empty geometry.' );
2006
- return new THREE.BufferGeometry();
2007
-
2008
- }
2009
-
2010
- const order = parseInt( geoNode.Order );
2011
- if ( isNaN( order ) ) {
2012
-
2013
- console.error( 'THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geoNode.Order, geoNode.id );
2014
- return new THREE.BufferGeometry();
2015
-
2016
- }
2017
-
2018
- const degree = order - 1;
2019
- const knots = geoNode.KnotVector.a;
2020
- const controlPoints = [];
2021
- const pointsValues = geoNode.Points.a;
2022
- for ( let i = 0, l = pointsValues.length; i < l; i += 4 ) {
2023
-
2024
- controlPoints.push( new THREE.Vector4().fromArray( pointsValues, i ) );
2025
-
2026
- }
2027
-
2028
- let startKnot, endKnot;
2029
- if ( geoNode.Form === 'Closed' ) {
2030
-
2031
- controlPoints.push( controlPoints[ 0 ] );
2032
-
2033
- } else if ( geoNode.Form === 'Periodic' ) {
2034
-
2035
- startKnot = degree;
2036
- endKnot = knots.length - 1 - startKnot;
2037
- for ( let i = 0; i < degree; ++ i ) {
2038
-
2039
- controlPoints.push( controlPoints[ i ] );
2040
-
2041
- }
2042
-
2043
- }
2044
-
2045
- const curve = new THREE.NURBSCurve( degree, knots, controlPoints, startKnot, endKnot );
2046
- const points = curve.getPoints( controlPoints.length * 12 );
2047
- return new THREE.BufferGeometry().setFromPoints( points );
2048
-
2049
- }
2050
-
2051
- }
2052
-
2053
- // parse animation data from FBXTree
2054
- class AnimationParser {
2055
-
2056
- // take raw animation clips and turn them into three.js animation clips
2057
- parse() {
2058
-
2059
- const animationClips = [];
2060
- const rawClips = this.parseClips();
2061
- if ( rawClips !== undefined ) {
2062
-
2063
- for ( const key in rawClips ) {
2064
-
2065
- const rawClip = rawClips[ key ];
2066
- const clip = this.addClip( rawClip );
2067
- animationClips.push( clip );
2068
-
2069
- }
2070
-
2071
- }
2072
-
2073
- return animationClips;
2074
-
2075
- }
2076
- parseClips() {
2077
-
2078
- // since the actual transformation data is stored in FBXTree.Objects.AnimationCurve,
2079
- // if this is undefined we can safely assume there are no animations
2080
- if ( fbxTree.Objects.AnimationCurve === undefined ) return undefined;
2081
- const curveNodesMap = this.parseAnimationCurveNodes();
2082
- this.parseAnimationCurves( curveNodesMap );
2083
- const layersMap = this.parseAnimationLayers( curveNodesMap );
2084
- const rawClips = this.parseAnimStacks( layersMap );
2085
- return rawClips;
2086
-
2087
- }
2088
-
2089
- // parse nodes in FBXTree.Objects.AnimationCurveNode
2090
- // each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation )
2091
- // and is referenced by an AnimationLayer
2092
- parseAnimationCurveNodes() {
2093
-
2094
- const rawCurveNodes = fbxTree.Objects.AnimationCurveNode;
2095
- const curveNodesMap = new Map();
2096
- for ( const nodeID in rawCurveNodes ) {
2097
-
2098
- const rawCurveNode = rawCurveNodes[ nodeID ];
2099
- if ( rawCurveNode.attrName.match( /S|R|T|DeformPercent/ ) !== null ) {
2100
-
2101
- const curveNode = {
2102
- id: rawCurveNode.id,
2103
- attr: rawCurveNode.attrName,
2104
- curves: {}
2105
- };
2106
- curveNodesMap.set( curveNode.id, curveNode );
2107
-
2108
- }
2109
-
2110
- }
2111
-
2112
- return curveNodesMap;
2113
-
2114
- }
2115
-
2116
- // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to
2117
- // previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated
2118
- // axis ( e.g. times and values of x rotation)
2119
- parseAnimationCurves( curveNodesMap ) {
2120
-
2121
- const rawCurves = fbxTree.Objects.AnimationCurve;
2122
-
2123
- // TODO: Many values are identical up to roundoff error, but won't be optimised
2124
- // e.g. position times: [0, 0.4, 0. 8]
2125
- // position values: [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.235384487103147e-7, 93.67520904541016, -0.9982695579528809]
2126
- // clearly, this should be optimised to
2127
- // times: [0], positions [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809]
2128
- // this shows up in nearly every FBX file, and generally time array is length > 100
2129
-
2130
- for ( const nodeID in rawCurves ) {
2131
-
2132
- const animationCurve = {
2133
- id: rawCurves[ nodeID ].id,
2134
- times: rawCurves[ nodeID ].KeyTime.a.map( convertFBXTimeToSeconds ),
2135
- values: rawCurves[ nodeID ].KeyValueFloat.a
2136
- };
2137
- const relationships = connections.get( animationCurve.id );
2138
- if ( relationships !== undefined ) {
2139
-
2140
- const animationCurveID = relationships.parents[ 0 ].ID;
2141
- const animationCurveRelationship = relationships.parents[ 0 ].relationship;
2142
- if ( animationCurveRelationship.match( /X/ ) ) {
2143
-
2144
- curveNodesMap.get( animationCurveID ).curves[ 'x' ] = animationCurve;
2145
-
2146
- } else if ( animationCurveRelationship.match( /Y/ ) ) {
2147
-
2148
- curveNodesMap.get( animationCurveID ).curves[ 'y' ] = animationCurve;
2149
-
2150
- } else if ( animationCurveRelationship.match( /Z/ ) ) {
2151
-
2152
- curveNodesMap.get( animationCurveID ).curves[ 'z' ] = animationCurve;
2153
-
2154
- } else if ( animationCurveRelationship.match( /d|DeformPercent/ ) && curveNodesMap.has( animationCurveID ) ) {
2155
-
2156
- curveNodesMap.get( animationCurveID ).curves[ 'morph' ] = animationCurve;
2157
-
2158
- }
2159
-
2160
- }
2161
-
2162
- }
2163
-
2164
- }
2165
-
2166
- // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references
2167
- // to various AnimationCurveNodes and is referenced by an AnimationStack node
2168
- // note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack
2169
- parseAnimationLayers( curveNodesMap ) {
2170
-
2171
- const rawLayers = fbxTree.Objects.AnimationLayer;
2172
- const layersMap = new Map();
2173
- for ( const nodeID in rawLayers ) {
2174
-
2175
- const layerCurveNodes = [];
2176
- const connection = connections.get( parseInt( nodeID ) );
2177
- if ( connection !== undefined ) {
2178
-
2179
- // all the animationCurveNodes used in the layer
2180
- const children = connection.children;
2181
- children.forEach( function ( child, i ) {
2182
-
2183
- if ( curveNodesMap.has( child.ID ) ) {
2184
-
2185
- const curveNode = curveNodesMap.get( child.ID );
2186
-
2187
- // check that the curves are defined for at least one axis, otherwise ignore the curveNode
2188
- if ( curveNode.curves.x !== undefined || curveNode.curves.y !== undefined || curveNode.curves.z !== undefined ) {
2189
-
2190
- if ( layerCurveNodes[ i ] === undefined ) {
2191
-
2192
- const modelID = connections.get( child.ID ).parents.filter( function ( parent ) {
2193
-
2194
- return parent.relationship !== undefined;
2195
-
2196
- } )[ 0 ].ID;
2197
- if ( modelID !== undefined ) {
2198
-
2199
- const rawModel = fbxTree.Objects.Model[ modelID.toString() ];
2200
- if ( rawModel === undefined ) {
2201
-
2202
- console.warn( 'THREE.FBXLoader: Encountered a unused curve.', child );
2203
- return;
2204
-
2205
- }
2206
-
2207
- const node = {
2208
- modelName: rawModel.attrName ? THREE.PropertyBinding.sanitizeNodeName( rawModel.attrName ) : '',
2209
- ID: rawModel.id,
2210
- initialPosition: [ 0, 0, 0 ],
2211
- initialRotation: [ 0, 0, 0 ],
2212
- initialScale: [ 1, 1, 1 ]
2213
- };
2214
- sceneGraph.traverse( function ( child ) {
2215
-
2216
- if ( child.ID === rawModel.id ) {
2217
-
2218
- node.transform = child.matrix;
2219
- if ( child.userData.transformData ) node.eulerOrder = child.userData.transformData.eulerOrder;
2220
-
2221
- }
2222
-
2223
- } );
2224
- if ( ! node.transform ) node.transform = new THREE.Matrix4();
2225
-
2226
- // if the animated model is pre rotated, we'll have to apply the pre rotations to every
2227
- // animation value as well
2228
- if ( 'PreRotation' in rawModel ) node.preRotation = rawModel.PreRotation.value;
2229
- if ( 'PostRotation' in rawModel ) node.postRotation = rawModel.PostRotation.value;
2230
- layerCurveNodes[ i ] = node;
2231
-
2232
- }
2233
-
2234
- }
2235
-
2236
- if ( layerCurveNodes[ i ] ) layerCurveNodes[ i ][ curveNode.attr ] = curveNode;
2237
-
2238
- } else if ( curveNode.curves.morph !== undefined ) {
2239
-
2240
- if ( layerCurveNodes[ i ] === undefined ) {
2241
-
2242
- const deformerID = connections.get( child.ID ).parents.filter( function ( parent ) {
2243
-
2244
- return parent.relationship !== undefined;
2245
-
2246
- } )[ 0 ].ID;
2247
- const morpherID = connections.get( deformerID ).parents[ 0 ].ID;
2248
- const geoID = connections.get( morpherID ).parents[ 0 ].ID;
2249
-
2250
- // assuming geometry is not used in more than one model
2251
- const modelID = connections.get( geoID ).parents[ 0 ].ID;
2252
- const rawModel = fbxTree.Objects.Model[ modelID ];
2253
- const node = {
2254
- modelName: rawModel.attrName ? THREE.PropertyBinding.sanitizeNodeName( rawModel.attrName ) : '',
2255
- morphName: fbxTree.Objects.Deformer[ deformerID ].attrName
2256
- };
2257
- layerCurveNodes[ i ] = node;
2258
-
2259
- }
2260
-
2261
- layerCurveNodes[ i ][ curveNode.attr ] = curveNode;
2262
-
2263
- }
2264
-
2265
- }
2266
-
2267
- } );
2268
- layersMap.set( parseInt( nodeID ), layerCurveNodes );
2269
-
2270
- }
2271
-
2272
- }
2273
-
2274
- return layersMap;
2275
-
2276
- }
2277
-
2278
- // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation
2279
- // hierarchy. Each Stack node will be used to create a THREE.AnimationClip
2280
- parseAnimStacks( layersMap ) {
2281
-
2282
- const rawStacks = fbxTree.Objects.AnimationStack;
2283
-
2284
- // connect the stacks (clips) up to the layers
2285
- const rawClips = {};
2286
- for ( const nodeID in rawStacks ) {
2287
-
2288
- const children = connections.get( parseInt( nodeID ) ).children;
2289
- if ( children.length > 1 ) {
2290
-
2291
- // it seems like stacks will always be associated with a single layer. But just in case there are files
2292
- // where there are multiple layers per stack, we'll display a warning
2293
- console.warn( 'THREE.FBXLoader: Encountered an animation stack with multiple layers, this is currently not supported. Ignoring subsequent layers.' );
2294
-
2295
- }
2296
-
2297
- const layer = layersMap.get( children[ 0 ].ID );
2298
- rawClips[ nodeID ] = {
2299
- name: rawStacks[ nodeID ].attrName,
2300
- layer: layer
2301
- };
2302
-
2303
- }
2304
-
2305
- return rawClips;
2306
-
2307
- }
2308
- addClip( rawClip ) {
2309
-
2310
- let tracks = [];
2311
- const scope = this;
2312
- rawClip.layer.forEach( function ( rawTracks ) {
2313
-
2314
- tracks = tracks.concat( scope.generateTracks( rawTracks ) );
2315
-
2316
- } );
2317
- return new THREE.AnimationClip( rawClip.name, - 1, tracks );
2318
-
2319
- }
2320
- generateTracks( rawTracks ) {
2321
-
2322
- const tracks = [];
2323
- let initialPosition = new THREE.Vector3();
2324
- let initialRotation = new THREE.Quaternion();
2325
- let initialScale = new THREE.Vector3();
2326
- if ( rawTracks.transform ) rawTracks.transform.decompose( initialPosition, initialRotation, initialScale );
2327
- initialPosition = initialPosition.toArray();
2328
- initialRotation = new THREE.Euler().setFromQuaternion( initialRotation, rawTracks.eulerOrder ).toArray();
2329
- initialScale = initialScale.toArray();
2330
- if ( rawTracks.T !== undefined && Object.keys( rawTracks.T.curves ).length > 0 ) {
2331
-
2332
- const positionTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.T.curves, initialPosition, 'position' );
2333
- if ( positionTrack !== undefined ) tracks.push( positionTrack );
2334
-
2335
- }
2336
-
2337
- if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) {
2338
-
2339
- const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, initialRotation, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder );
2340
- if ( rotationTrack !== undefined ) tracks.push( rotationTrack );
2341
-
2342
- }
2343
-
2344
- if ( rawTracks.S !== undefined && Object.keys( rawTracks.S.curves ).length > 0 ) {
2345
-
2346
- const scaleTrack = this.generateVectorTrack( rawTracks.modelName, rawTracks.S.curves, initialScale, 'scale' );
2347
- if ( scaleTrack !== undefined ) tracks.push( scaleTrack );
2348
-
2349
- }
2350
-
2351
- if ( rawTracks.DeformPercent !== undefined ) {
2352
-
2353
- const morphTrack = this.generateMorphTrack( rawTracks );
2354
- if ( morphTrack !== undefined ) tracks.push( morphTrack );
2355
-
2356
- }
2357
-
2358
- return tracks;
2359
-
2360
- }
2361
- generateVectorTrack( modelName, curves, initialValue, type ) {
2362
-
2363
- const times = this.getTimesForAllAxes( curves );
2364
- const values = this.getKeyframeTrackValues( times, curves, initialValue );
2365
- return new THREE.VectorKeyframeTrack( modelName + '.' + type, times, values );
2366
-
2367
- }
2368
- generateRotationTrack( modelName, curves, initialValue, preRotation, postRotation, eulerOrder ) {
2369
-
2370
- if ( curves.x !== undefined ) {
2371
-
2372
- this.interpolateRotations( curves.x );
2373
- curves.x.values = curves.x.values.map( THREE.MathUtils.degToRad );
2374
-
2375
- }
2376
-
2377
- if ( curves.y !== undefined ) {
2378
-
2379
- this.interpolateRotations( curves.y );
2380
- curves.y.values = curves.y.values.map( THREE.MathUtils.degToRad );
2381
-
2382
- }
2383
-
2384
- if ( curves.z !== undefined ) {
2385
-
2386
- this.interpolateRotations( curves.z );
2387
- curves.z.values = curves.z.values.map( THREE.MathUtils.degToRad );
2388
-
2389
- }
2390
-
2391
- const times = this.getTimesForAllAxes( curves );
2392
- const values = this.getKeyframeTrackValues( times, curves, initialValue );
2393
- if ( preRotation !== undefined ) {
2394
-
2395
- preRotation = preRotation.map( THREE.MathUtils.degToRad );
2396
- preRotation.push( eulerOrder );
2397
- preRotation = new THREE.Euler().fromArray( preRotation );
2398
- preRotation = new THREE.Quaternion().setFromEuler( preRotation );
2399
-
2400
- }
2401
-
2402
- if ( postRotation !== undefined ) {
2403
-
2404
- postRotation = postRotation.map( THREE.MathUtils.degToRad );
2405
- postRotation.push( eulerOrder );
2406
- postRotation = new THREE.Euler().fromArray( postRotation );
2407
- postRotation = new THREE.Quaternion().setFromEuler( postRotation ).invert();
2408
-
2409
- }
2410
-
2411
- const quaternion = new THREE.Quaternion();
2412
- const euler = new THREE.Euler();
2413
- const quaternionValues = [];
2414
- for ( let i = 0; i < values.length; i += 3 ) {
2415
-
2416
- euler.set( values[ i ], values[ i + 1 ], values[ i + 2 ], eulerOrder );
2417
- quaternion.setFromEuler( euler );
2418
- if ( preRotation !== undefined ) quaternion.premultiply( preRotation );
2419
- if ( postRotation !== undefined ) quaternion.multiply( postRotation );
2420
- quaternion.toArray( quaternionValues, i / 3 * 4 );
2421
-
2422
- }
2423
-
2424
- return new THREE.QuaternionKeyframeTrack( modelName + '.quaternion', times, quaternionValues );
2425
-
2426
- }
2427
- generateMorphTrack( rawTracks ) {
2428
-
2429
- const curves = rawTracks.DeformPercent.curves.morph;
2430
- const values = curves.values.map( function ( val ) {
2431
-
2432
- return val / 100;
2433
-
2434
- } );
2435
- const morphNum = sceneGraph.getObjectByName( rawTracks.modelName ).morphTargetDictionary[ rawTracks.morphName ];
2436
- return new THREE.NumberKeyframeTrack( rawTracks.modelName + '.morphTargetInfluences[' + morphNum + ']', curves.times, values );
2437
-
2438
- }
2439
-
2440
- // For all animated objects, times are defined separately for each axis
2441
- // Here we'll combine the times into one sorted array without duplicates
2442
- getTimesForAllAxes( curves ) {
2443
-
2444
- let times = [];
2445
-
2446
- // first join together the times for each axis, if defined
2447
- if ( curves.x !== undefined ) times = times.concat( curves.x.times );
2448
- if ( curves.y !== undefined ) times = times.concat( curves.y.times );
2449
- if ( curves.z !== undefined ) times = times.concat( curves.z.times );
2450
-
2451
- // then sort them
2452
- times = times.sort( function ( a, b ) {
2453
-
2454
- return a - b;
2455
-
2456
- } );
2457
-
2458
- // and remove duplicates
2459
- if ( times.length > 1 ) {
2460
-
2461
- let targetIndex = 1;
2462
- let lastValue = times[ 0 ];
2463
- for ( let i = 1; i < times.length; i ++ ) {
2464
-
2465
- const currentValue = times[ i ];
2466
- if ( currentValue !== lastValue ) {
2467
-
2468
- times[ targetIndex ] = currentValue;
2469
- lastValue = currentValue;
2470
- targetIndex ++;
2471
-
2472
- }
2473
-
2474
- }
2475
-
2476
- times = times.slice( 0, targetIndex );
2477
-
2478
- }
2479
-
2480
- return times;
2481
-
2482
- }
2483
- getKeyframeTrackValues( times, curves, initialValue ) {
2484
-
2485
- const prevValue = initialValue;
2486
- const values = [];
2487
- let xIndex = - 1;
2488
- let yIndex = - 1;
2489
- let zIndex = - 1;
2490
- times.forEach( function ( time ) {
2491
-
2492
- if ( curves.x ) xIndex = curves.x.times.indexOf( time );
2493
- if ( curves.y ) yIndex = curves.y.times.indexOf( time );
2494
- if ( curves.z ) zIndex = curves.z.times.indexOf( time );
2495
-
2496
- // if there is an x value defined for this frame, use that
2497
- if ( xIndex !== - 1 ) {
2498
-
2499
- const xValue = curves.x.values[ xIndex ];
2500
- values.push( xValue );
2501
- prevValue[ 0 ] = xValue;
2502
-
2503
- } else {
2504
-
2505
- // otherwise use the x value from the previous frame
2506
- values.push( prevValue[ 0 ] );
2507
-
2508
- }
2509
-
2510
- if ( yIndex !== - 1 ) {
2511
-
2512
- const yValue = curves.y.values[ yIndex ];
2513
- values.push( yValue );
2514
- prevValue[ 1 ] = yValue;
2515
-
2516
- } else {
2517
-
2518
- values.push( prevValue[ 1 ] );
2519
-
2520
- }
2521
-
2522
- if ( zIndex !== - 1 ) {
2523
-
2524
- const zValue = curves.z.values[ zIndex ];
2525
- values.push( zValue );
2526
- prevValue[ 2 ] = zValue;
2527
-
2528
- } else {
2529
-
2530
- values.push( prevValue[ 2 ] );
2531
-
2532
- }
2533
-
2534
- } );
2535
- return values;
2536
-
2537
- }
2538
-
2539
- // Rotations are defined as THREE.Euler angles which can have values of any size
2540
- // These will be converted to quaternions which don't support values greater than
2541
- // PI, so we'll interpolate large rotations
2542
- interpolateRotations( curve ) {
2543
-
2544
- for ( let i = 1; i < curve.values.length; i ++ ) {
2545
-
2546
- const initialValue = curve.values[ i - 1 ];
2547
- const valuesSpan = curve.values[ i ] - initialValue;
2548
- const absoluteSpan = Math.abs( valuesSpan );
2549
- if ( absoluteSpan >= 180 ) {
2550
-
2551
- const numSubIntervals = absoluteSpan / 180;
2552
- const step = valuesSpan / numSubIntervals;
2553
- let nextValue = initialValue + step;
2554
- const initialTime = curve.times[ i - 1 ];
2555
- const timeSpan = curve.times[ i ] - initialTime;
2556
- const interval = timeSpan / numSubIntervals;
2557
- let nextTime = initialTime + interval;
2558
- const interpolatedTimes = [];
2559
- const interpolatedValues = [];
2560
- while ( nextTime < curve.times[ i ] ) {
2561
-
2562
- interpolatedTimes.push( nextTime );
2563
- nextTime += interval;
2564
- interpolatedValues.push( nextValue );
2565
- nextValue += step;
2566
-
2567
- }
2568
-
2569
- curve.times = inject( curve.times, i, interpolatedTimes );
2570
- curve.values = inject( curve.values, i, interpolatedValues );
2571
-
2572
- }
2573
-
2574
- }
2575
-
2576
- }
2577
-
2578
- }
2579
-
2580
- // parse an FBX file in ASCII format
2581
- class TextParser {
2582
-
2583
- getPrevNode() {
2584
-
2585
- return this.nodeStack[ this.currentIndent - 2 ];
2586
-
2587
- }
2588
- getCurrentNode() {
2589
-
2590
- return this.nodeStack[ this.currentIndent - 1 ];
2591
-
2592
- }
2593
- getCurrentProp() {
2594
-
2595
- return this.currentProp;
2596
-
2597
- }
2598
- pushStack( node ) {
2599
-
2600
- this.nodeStack.push( node );
2601
- this.currentIndent += 1;
2602
-
2603
- }
2604
- popStack() {
2605
-
2606
- this.nodeStack.pop();
2607
- this.currentIndent -= 1;
2608
-
2609
- }
2610
- setCurrentProp( val, name ) {
2611
-
2612
- this.currentProp = val;
2613
- this.currentPropName = name;
2614
-
2615
- }
2616
- parse( text ) {
2617
-
2618
- this.currentIndent = 0;
2619
- this.allNodes = new FBXTree();
2620
- this.nodeStack = [];
2621
- this.currentProp = [];
2622
- this.currentPropName = '';
2623
- const scope = this;
2624
- const split = text.split( /[\r\n]+/ );
2625
- split.forEach( function ( line, i ) {
2626
-
2627
- const matchComment = line.match( /^[\s\t]*;/ );
2628
- const matchEmpty = line.match( /^[\s\t]*$/ );
2629
- if ( matchComment || matchEmpty ) return;
2630
- const matchBeginning = line.match( '^\\t{' + scope.currentIndent + '}(\\w+):(.*){', '' );
2631
- const matchProperty = line.match( '^\\t{' + scope.currentIndent + '}(\\w+):[\\s\\t\\r\\n](.*)' );
2632
- const matchEnd = line.match( '^\\t{' + ( scope.currentIndent - 1 ) + '}}' );
2633
- if ( matchBeginning ) {
2634
-
2635
- scope.parseNodeBegin( line, matchBeginning );
2636
-
2637
- } else if ( matchProperty ) {
2638
-
2639
- scope.parseNodeProperty( line, matchProperty, split[ ++ i ] );
2640
-
2641
- } else if ( matchEnd ) {
2642
-
2643
- scope.popStack();
2644
-
2645
- } else if ( line.match( /^[^\s\t}]/ ) ) {
2646
-
2647
- // large arrays are split over multiple lines terminated with a ',' character
2648
- // if this is encountered the line needs to be joined to the previous line
2649
- scope.parseNodePropertyContinued( line );
2650
-
2651
- }
2652
-
2653
- } );
2654
- return this.allNodes;
2655
-
2656
- }
2657
- parseNodeBegin( line, property ) {
2658
-
2659
- const nodeName = property[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' );
2660
- const nodeAttrs = property[ 2 ].split( ',' ).map( function ( attr ) {
2661
-
2662
- return attr.trim().replace( /^"/, '' ).replace( /"$/, '' );
2663
-
2664
- } );
2665
- const node = {
2666
- name: nodeName
2667
- };
2668
- const attrs = this.parseNodeAttr( nodeAttrs );
2669
- const currentNode = this.getCurrentNode();
2670
-
2671
- // a top node
2672
- if ( this.currentIndent === 0 ) {
2673
-
2674
- this.allNodes.add( nodeName, node );
2675
-
2676
- } else {
2677
-
2678
- // a subnode
2679
-
2680
- // if the subnode already exists, append it
2681
- if ( nodeName in currentNode ) {
2682
-
2683
- // special case Pose needs PoseNodes as an array
2684
- if ( nodeName === 'PoseNode' ) {
2685
-
2686
- currentNode.PoseNode.push( node );
2687
-
2688
- } else if ( currentNode[ nodeName ].id !== undefined ) {
2689
-
2690
- currentNode[ nodeName ] = {};
2691
- currentNode[ nodeName ][ currentNode[ nodeName ].id ] = currentNode[ nodeName ];
2692
-
2693
- }
2694
-
2695
- if ( attrs.id !== '' ) currentNode[ nodeName ][ attrs.id ] = node;
2696
-
2697
- } else if ( typeof attrs.id === 'number' ) {
2698
-
2699
- currentNode[ nodeName ] = {};
2700
- currentNode[ nodeName ][ attrs.id ] = node;
2701
-
2702
- } else if ( nodeName !== 'Properties70' ) {
2703
-
2704
- if ( nodeName === 'PoseNode' ) currentNode[ nodeName ] = [ node ]; else currentNode[ nodeName ] = node;
2705
-
2706
- }
2707
-
2708
- }
2709
-
2710
- if ( typeof attrs.id === 'number' ) node.id = attrs.id;
2711
- if ( attrs.name !== '' ) node.attrName = attrs.name;
2712
- if ( attrs.type !== '' ) node.attrType = attrs.type;
2713
- this.pushStack( node );
2714
-
2715
- }
2716
- parseNodeAttr( attrs ) {
2717
-
2718
- let id = attrs[ 0 ];
2719
- if ( attrs[ 0 ] !== '' ) {
2720
-
2721
- id = parseInt( attrs[ 0 ] );
2722
- if ( isNaN( id ) ) {
2723
-
2724
- id = attrs[ 0 ];
2725
-
2726
- }
2727
-
2728
- }
2729
-
2730
- let name = '',
2731
- type = '';
2732
- if ( attrs.length > 1 ) {
2733
-
2734
- name = attrs[ 1 ].replace( /^(\w+)::/, '' );
2735
- type = attrs[ 2 ];
2736
-
2737
- }
2738
-
2739
- return {
2740
- id: id,
2741
- name: name,
2742
- type: type
2743
- };
2744
-
2745
- }
2746
- parseNodeProperty( line, property, contentLine ) {
2747
-
2748
- let propName = property[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
2749
- let propValue = property[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
2750
-
2751
- // for special case: base64 image data follows "Content: ," line
2752
- // Content: ,
2753
- // "/9j/4RDaRXhpZgAATU0A..."
2754
- if ( propName === 'Content' && propValue === ',' ) {
2755
-
2756
- propValue = contentLine.replace( /"/g, '' ).replace( /,$/, '' ).trim();
2757
-
2758
- }
2759
-
2760
- const currentNode = this.getCurrentNode();
2761
- const parentName = currentNode.name;
2762
- if ( parentName === 'Properties70' ) {
2763
-
2764
- this.parseNodeSpecialProperty( line, propName, propValue );
2765
- return;
2766
-
2767
- }
2768
-
2769
- // Connections
2770
- if ( propName === 'C' ) {
2771
-
2772
- const connProps = propValue.split( ',' ).slice( 1 );
2773
- const from = parseInt( connProps[ 0 ] );
2774
- const to = parseInt( connProps[ 1 ] );
2775
- let rest = propValue.split( ',' ).slice( 3 );
2776
- rest = rest.map( function ( elem ) {
2777
-
2778
- return elem.trim().replace( /^"/, '' );
2779
-
2780
- } );
2781
- propName = 'connections';
2782
- propValue = [ from, to ];
2783
- append( propValue, rest );
2784
- if ( currentNode[ propName ] === undefined ) {
2785
-
2786
- currentNode[ propName ] = [];
2787
-
2788
- }
2789
-
2790
- }
2791
-
2792
- // Node
2793
- if ( propName === 'Node' ) currentNode.id = propValue;
2794
-
2795
- // connections
2796
- if ( propName in currentNode && Array.isArray( currentNode[ propName ] ) ) {
2797
-
2798
- currentNode[ propName ].push( propValue );
2799
-
2800
- } else {
2801
-
2802
- if ( propName !== 'a' ) currentNode[ propName ] = propValue; else currentNode.a = propValue;
2803
-
2804
- }
2805
-
2806
- this.setCurrentProp( currentNode, propName );
2807
-
2808
- // convert string to array, unless it ends in ',' in which case more will be added to it
2809
- if ( propName === 'a' && propValue.slice( - 1 ) !== ',' ) {
2810
-
2811
- currentNode.a = parseNumberArray( propValue );
2812
-
2813
- }
2814
-
2815
- }
2816
- parseNodePropertyContinued( line ) {
2817
-
2818
- const currentNode = this.getCurrentNode();
2819
- currentNode.a += line;
2820
-
2821
- // if the line doesn't end in ',' we have reached the end of the property value
2822
- // so convert the string to an array
2823
- if ( line.slice( - 1 ) !== ',' ) {
2824
-
2825
- currentNode.a = parseNumberArray( currentNode.a );
2826
-
2827
- }
2828
-
2829
- }
2830
-
2831
- // parse "Property70"
2832
- parseNodeSpecialProperty( line, propName, propValue ) {
2833
-
2834
- // split this
2835
- // P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1
2836
- // into array like below
2837
- // ["Lcl Scaling", "Lcl Scaling", "", "A", "1,1,1" ]
2838
- const props = propValue.split( '",' ).map( function ( prop ) {
2839
-
2840
- return prop.trim().replace( /^\"/, '' ).replace( /\s/, '_' );
2841
-
2842
- } );
2843
- const innerPropName = props[ 0 ];
2844
- const innerPropType1 = props[ 1 ];
2845
- const innerPropType2 = props[ 2 ];
2846
- const innerPropFlag = props[ 3 ];
2847
- let innerPropValue = props[ 4 ];
2848
-
2849
- // cast values where needed, otherwise leave as strings
2850
- switch ( innerPropType1 ) {
2851
-
2852
- case 'int':
2853
- case 'enum':
2854
- case 'bool':
2855
- case 'ULongLong':
2856
- case 'double':
2857
- case 'Number':
2858
- case 'FieldOfView':
2859
- innerPropValue = parseFloat( innerPropValue );
2860
- break;
2861
- case 'Color':
2862
- case 'ColorRGB':
2863
- case 'Vector3D':
2864
- case 'Lcl_Translation':
2865
- case 'Lcl_Rotation':
2866
- case 'Lcl_Scaling':
2867
- innerPropValue = parseNumberArray( innerPropValue );
2868
- break;
2869
-
2870
- }
2871
-
2872
- // CAUTION: these props must append to parent's parent
2873
- this.getPrevNode()[ innerPropName ] = {
2874
- 'type': innerPropType1,
2875
- 'type2': innerPropType2,
2876
- 'flag': innerPropFlag,
2877
- 'value': innerPropValue
2878
- };
2879
- this.setCurrentProp( this.getPrevNode(), innerPropName );
2880
-
2881
- }
2882
-
2883
- }
2884
-
2885
- // Parse an FBX file in Binary format
2886
- class BinaryParser {
2887
-
2888
- parse( buffer ) {
2889
-
2890
- const reader = new BinaryReader( buffer );
2891
- reader.skip( 23 ); // skip magic 23 bytes
2892
-
2893
- const version = reader.getUint32();
2894
- if ( version < 6400 ) {
2895
-
2896
- throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + version );
2897
-
2898
- }
2899
-
2900
- const allNodes = new FBXTree();
2901
- while ( ! this.endOfContent( reader ) ) {
2902
-
2903
- const node = this.parseNode( reader, version );
2904
- if ( node !== null ) allNodes.add( node.name, node );
2905
-
2906
- }
2907
-
2908
- return allNodes;
2909
-
2910
- }
2911
-
2912
- // Check if reader has reached the end of content.
2913
- endOfContent( reader ) {
2914
-
2915
- // footer size: 160bytes + 16-byte alignment padding
2916
- // - 16bytes: magic
2917
- // - padding til 16-byte alignment (at least 1byte?)
2918
- // (seems like some exporters embed fixed 15 or 16bytes?)
2919
- // - 4bytes: magic
2920
- // - 4bytes: version
2921
- // - 120bytes: zero
2922
- // - 16bytes: magic
2923
- if ( reader.size() % 16 === 0 ) {
2924
-
2925
- return ( reader.getOffset() + 160 + 16 & ~ 0xf ) >= reader.size();
2926
-
2927
- } else {
2928
-
2929
- return reader.getOffset() + 160 + 16 >= reader.size();
2930
-
2931
- }
2932
-
2933
- }
2934
-
2935
- // recursively parse nodes until the end of the file is reached
2936
- parseNode( reader, version ) {
2937
-
2938
- const node = {};
2939
-
2940
- // The first three data sizes depends on version.
2941
- const endOffset = version >= 7500 ? reader.getUint64() : reader.getUint32();
2942
- const numProperties = version >= 7500 ? reader.getUint64() : reader.getUint32();
2943
- version >= 7500 ? reader.getUint64() : reader.getUint32(); // the returned propertyListLen is not used
2944
-
2945
- const nameLen = reader.getUint8();
2946
- const name = reader.getString( nameLen );
2947
-
2948
- // Regards this node as NULL-record if endOffset is zero
2949
- if ( endOffset === 0 ) return null;
2950
- const propertyList = [];
2951
- for ( let i = 0; i < numProperties; i ++ ) {
2952
-
2953
- propertyList.push( this.parseProperty( reader ) );
2954
-
2955
- }
2956
-
2957
- // Regards the first three elements in propertyList as id, attrName, and attrType
2958
- const id = propertyList.length > 0 ? propertyList[ 0 ] : '';
2959
- const attrName = propertyList.length > 1 ? propertyList[ 1 ] : '';
2960
- const attrType = propertyList.length > 2 ? propertyList[ 2 ] : '';
2961
-
2962
- // check if this node represents just a single property
2963
- // like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]}
2964
- node.singleProperty = numProperties === 1 && reader.getOffset() === endOffset ? true : false;
2965
- while ( endOffset > reader.getOffset() ) {
2966
-
2967
- const subNode = this.parseNode( reader, version );
2968
- if ( subNode !== null ) this.parseSubNode( name, node, subNode );
2969
-
2970
- }
2971
-
2972
- node.propertyList = propertyList; // raw property list used by parent
2973
-
2974
- if ( typeof id === 'number' ) node.id = id;
2975
- if ( attrName !== '' ) node.attrName = attrName;
2976
- if ( attrType !== '' ) node.attrType = attrType;
2977
- if ( name !== '' ) node.name = name;
2978
- return node;
2979
-
2980
- }
2981
- parseSubNode( name, node, subNode ) {
2982
-
2983
- // special case: child node is single property
2984
- if ( subNode.singleProperty === true ) {
2985
-
2986
- const value = subNode.propertyList[ 0 ];
2987
- if ( Array.isArray( value ) ) {
2988
-
2989
- node[ subNode.name ] = subNode;
2990
- subNode.a = value;
2991
-
2992
- } else {
2993
-
2994
- node[ subNode.name ] = value;
2995
-
2996
- }
2997
-
2998
- } else if ( name === 'Connections' && subNode.name === 'C' ) {
2999
-
3000
- const array = [];
3001
- subNode.propertyList.forEach( function ( property, i ) {
3002
-
3003
- // first Connection is FBX type (OO, OP, etc.). We'll discard these
3004
- if ( i !== 0 ) array.push( property );
3005
-
3006
- } );
3007
- if ( node.connections === undefined ) {
3008
-
3009
- node.connections = [];
3010
-
3011
- }
3012
-
3013
- node.connections.push( array );
3014
-
3015
- } else if ( subNode.name === 'Properties70' ) {
3016
-
3017
- const keys = Object.keys( subNode );
3018
- keys.forEach( function ( key ) {
3019
-
3020
- node[ key ] = subNode[ key ];
3021
-
3022
- } );
3023
-
3024
- } else if ( name === 'Properties70' && subNode.name === 'P' ) {
3025
-
3026
- let innerPropName = subNode.propertyList[ 0 ];
3027
- let innerPropType1 = subNode.propertyList[ 1 ];
3028
- const innerPropType2 = subNode.propertyList[ 2 ];
3029
- const innerPropFlag = subNode.propertyList[ 3 ];
3030
- let innerPropValue;
3031
- if ( innerPropName.indexOf( 'Lcl ' ) === 0 ) innerPropName = innerPropName.replace( 'Lcl ', 'Lcl_' );
3032
- if ( innerPropType1.indexOf( 'Lcl ' ) === 0 ) innerPropType1 = innerPropType1.replace( 'Lcl ', 'Lcl_' );
3033
- if ( innerPropType1 === 'Color' || innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) {
3034
-
3035
- innerPropValue = [ subNode.propertyList[ 4 ], subNode.propertyList[ 5 ], subNode.propertyList[ 6 ] ];
3036
-
3037
- } else {
3038
-
3039
- innerPropValue = subNode.propertyList[ 4 ];
3040
-
3041
- }
3042
-
3043
- // this will be copied to parent, see above
3044
- node[ innerPropName ] = {
3045
- 'type': innerPropType1,
3046
- 'type2': innerPropType2,
3047
- 'flag': innerPropFlag,
3048
- 'value': innerPropValue
3049
- };
3050
-
3051
- } else if ( node[ subNode.name ] === undefined ) {
3052
-
3053
- if ( typeof subNode.id === 'number' ) {
3054
-
3055
- node[ subNode.name ] = {};
3056
- node[ subNode.name ][ subNode.id ] = subNode;
3057
-
3058
- } else {
3059
-
3060
- node[ subNode.name ] = subNode;
3061
-
3062
- }
3063
-
3064
- } else {
3065
-
3066
- if ( subNode.name === 'PoseNode' ) {
3067
-
3068
- if ( ! Array.isArray( node[ subNode.name ] ) ) {
3069
-
3070
- node[ subNode.name ] = [ node[ subNode.name ] ];
3071
-
3072
- }
3073
-
3074
- node[ subNode.name ].push( subNode );
3075
-
3076
- } else if ( node[ subNode.name ][ subNode.id ] === undefined ) {
3077
-
3078
- node[ subNode.name ][ subNode.id ] = subNode;
3079
-
3080
- }
3081
-
3082
- }
3083
-
3084
- }
3085
- parseProperty( reader ) {
3086
-
3087
- const type = reader.getString( 1 );
3088
- let length;
3089
- switch ( type ) {
3090
-
3091
- case 'C':
3092
- return reader.getBoolean();
3093
- case 'D':
3094
- return reader.getFloat64();
3095
- case 'F':
3096
- return reader.getFloat32();
3097
- case 'I':
3098
- return reader.getInt32();
3099
- case 'L':
3100
- return reader.getInt64();
3101
- case 'R':
3102
- length = reader.getUint32();
3103
- return reader.getArrayBuffer( length );
3104
- case 'S':
3105
- length = reader.getUint32();
3106
- return reader.getString( length );
3107
- case 'Y':
3108
- return reader.getInt16();
3109
- case 'b':
3110
- case 'c':
3111
- case 'd':
3112
- case 'f':
3113
- case 'i':
3114
- case 'l':
3115
- const arrayLength = reader.getUint32();
3116
- const encoding = reader.getUint32(); // 0: non-compressed, 1: compressed
3117
- const compressedLength = reader.getUint32();
3118
- if ( encoding === 0 ) {
3119
-
3120
- switch ( type ) {
3121
-
3122
- case 'b':
3123
- case 'c':
3124
- return reader.getBooleanArray( arrayLength );
3125
- case 'd':
3126
- return reader.getFloat64Array( arrayLength );
3127
- case 'f':
3128
- return reader.getFloat32Array( arrayLength );
3129
- case 'i':
3130
- return reader.getInt32Array( arrayLength );
3131
- case 'l':
3132
- return reader.getInt64Array( arrayLength );
3133
-
3134
- }
3135
-
3136
- }
3137
-
3138
- if ( typeof fflate === 'undefined' ) {
3139
-
3140
- console.error( 'THREE.FBXLoader: External library fflate.min.js required.' );
3141
-
3142
- }
3143
-
3144
- const data = fflate.unzlibSync( new Uint8Array( reader.getArrayBuffer( compressedLength ) ) ); // eslint-disable-line no-undef
3145
- const reader2 = new BinaryReader( data.buffer );
3146
- switch ( type ) {
3147
-
3148
- case 'b':
3149
- case 'c':
3150
- return reader2.getBooleanArray( arrayLength );
3151
- case 'd':
3152
- return reader2.getFloat64Array( arrayLength );
3153
- case 'f':
3154
- return reader2.getFloat32Array( arrayLength );
3155
- case 'i':
3156
- return reader2.getInt32Array( arrayLength );
3157
- case 'l':
3158
- return reader2.getInt64Array( arrayLength );
3159
-
3160
- }
3161
-
3162
- break;
3163
- // cannot happen but is required by the DeepScan
3164
-
3165
- default:
3166
- throw new Error( 'THREE.FBXLoader: Unknown property type ' + type );
3167
-
3168
- }
3169
-
3170
- }
3171
-
3172
- }
3173
- class BinaryReader {
3174
-
3175
- constructor( buffer, littleEndian ) {
3176
-
3177
- this.dv = new DataView( buffer );
3178
- this.offset = 0;
3179
- this.littleEndian = littleEndian !== undefined ? littleEndian : true;
3180
-
3181
- }
3182
- getOffset() {
3183
-
3184
- return this.offset;
3185
-
3186
- }
3187
- size() {
3188
-
3189
- return this.dv.buffer.byteLength;
3190
-
3191
- }
3192
- skip( length ) {
3193
-
3194
- this.offset += length;
3195
-
3196
- }
3197
-
3198
- // seems like true/false representation depends on exporter.
3199
- // true: 1 or 'Y'(=0x59), false: 0 or 'T'(=0x54)
3200
- // then sees LSB.
3201
- getBoolean() {
3202
-
3203
- return ( this.getUint8() & 1 ) === 1;
3204
-
3205
- }
3206
- getBooleanArray( size ) {
3207
-
3208
- const a = [];
3209
- for ( let i = 0; i < size; i ++ ) {
3210
-
3211
- a.push( this.getBoolean() );
3212
-
3213
- }
3214
-
3215
- return a;
3216
-
3217
- }
3218
- getUint8() {
3219
-
3220
- const value = this.dv.getUint8( this.offset );
3221
- this.offset += 1;
3222
- return value;
3223
-
3224
- }
3225
- getInt16() {
3226
-
3227
- const value = this.dv.getInt16( this.offset, this.littleEndian );
3228
- this.offset += 2;
3229
- return value;
3230
-
3231
- }
3232
- getInt32() {
3233
-
3234
- const value = this.dv.getInt32( this.offset, this.littleEndian );
3235
- this.offset += 4;
3236
- return value;
3237
-
3238
- }
3239
- getInt32Array( size ) {
3240
-
3241
- const a = [];
3242
- for ( let i = 0; i < size; i ++ ) {
3243
-
3244
- a.push( this.getInt32() );
3245
-
3246
- }
3247
-
3248
- return a;
3249
-
3250
- }
3251
- getUint32() {
3252
-
3253
- const value = this.dv.getUint32( this.offset, this.littleEndian );
3254
- this.offset += 4;
3255
- return value;
3256
-
3257
- }
3258
-
3259
- // JavaScript doesn't support 64-bit integer so calculate this here
3260
- // 1 << 32 will return 1 so using multiply operation instead here.
3261
- // There's a possibility that this method returns wrong value if the value
3262
- // is out of the range between Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER.
3263
- // TODO: safely handle 64-bit integer
3264
- getInt64() {
3265
-
3266
- let low, high;
3267
- if ( this.littleEndian ) {
3268
-
3269
- low = this.getUint32();
3270
- high = this.getUint32();
3271
-
3272
- } else {
3273
-
3274
- high = this.getUint32();
3275
- low = this.getUint32();
3276
-
3277
- }
3278
-
3279
- // calculate negative value
3280
- if ( high & 0x80000000 ) {
3281
-
3282
- high = ~ high & 0xFFFFFFFF;
3283
- low = ~ low & 0xFFFFFFFF;
3284
- if ( low === 0xFFFFFFFF ) high = high + 1 & 0xFFFFFFFF;
3285
- low = low + 1 & 0xFFFFFFFF;
3286
- return - ( high * 0x100000000 + low );
3287
-
3288
- }
3289
-
3290
- return high * 0x100000000 + low;
3291
-
3292
- }
3293
- getInt64Array( size ) {
3294
-
3295
- const a = [];
3296
- for ( let i = 0; i < size; i ++ ) {
3297
-
3298
- a.push( this.getInt64() );
3299
-
3300
- }
3301
-
3302
- return a;
3303
-
3304
- }
3305
-
3306
- // Note: see getInt64() comment
3307
- getUint64() {
3308
-
3309
- let low, high;
3310
- if ( this.littleEndian ) {
3311
-
3312
- low = this.getUint32();
3313
- high = this.getUint32();
3314
-
3315
- } else {
3316
-
3317
- high = this.getUint32();
3318
- low = this.getUint32();
3319
-
3320
- }
3321
-
3322
- return high * 0x100000000 + low;
3323
-
3324
- }
3325
- getFloat32() {
3326
-
3327
- const value = this.dv.getFloat32( this.offset, this.littleEndian );
3328
- this.offset += 4;
3329
- return value;
3330
-
3331
- }
3332
- getFloat32Array( size ) {
3333
-
3334
- const a = [];
3335
- for ( let i = 0; i < size; i ++ ) {
3336
-
3337
- a.push( this.getFloat32() );
3338
-
3339
- }
3340
-
3341
- return a;
3342
-
3343
- }
3344
- getFloat64() {
3345
-
3346
- const value = this.dv.getFloat64( this.offset, this.littleEndian );
3347
- this.offset += 8;
3348
- return value;
3349
-
3350
- }
3351
- getFloat64Array( size ) {
3352
-
3353
- const a = [];
3354
- for ( let i = 0; i < size; i ++ ) {
3355
-
3356
- a.push( this.getFloat64() );
3357
-
3358
- }
3359
-
3360
- return a;
3361
-
3362
- }
3363
- getArrayBuffer( size ) {
3364
-
3365
- const value = this.dv.buffer.slice( this.offset, this.offset + size );
3366
- this.offset += size;
3367
- return value;
3368
-
3369
- }
3370
- getString( size ) {
3371
-
3372
- // note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead
3373
- let a = [];
3374
- for ( let i = 0; i < size; i ++ ) {
3375
-
3376
- a[ i ] = this.getUint8();
3377
-
3378
- }
3379
-
3380
- const nullByte = a.indexOf( 0 );
3381
- if ( nullByte >= 0 ) a = a.slice( 0, nullByte );
3382
- return THREE.LoaderUtils.decodeText( new Uint8Array( a ) );
3383
-
3384
- }
3385
-
3386
- }
3387
-
3388
- // FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format)
3389
- // and BinaryParser( FBX Binary format)
3390
- class FBXTree {
3391
-
3392
- add( key, val ) {
3393
-
3394
- this[ key ] = val;
3395
-
3396
- }
3397
-
3398
- }
3399
-
3400
- // ************** UTILITY FUNCTIONS **************
3401
-
3402
- function isFbxFormatBinary( buffer ) {
3403
-
3404
- const CORRECT = 'Kaydara\u0020FBX\u0020Binary\u0020\u0020\0';
3405
- return buffer.byteLength >= CORRECT.length && CORRECT === convertArrayBufferToString( buffer, 0, CORRECT.length );
3406
-
3407
- }
3408
-
3409
- function isFbxFormatASCII( text ) {
3410
-
3411
- const CORRECT = [ 'K', 'a', 'y', 'd', 'a', 'r', 'a', '\\', 'F', 'B', 'X', '\\', 'B', 'i', 'n', 'a', 'r', 'y', '\\', '\\' ];
3412
- let cursor = 0;
3413
- function read( offset ) {
3414
-
3415
- const result = text[ offset - 1 ];
3416
- text = text.slice( cursor + offset );
3417
- cursor ++;
3418
- return result;
3419
-
3420
- }
3421
-
3422
- for ( let i = 0; i < CORRECT.length; ++ i ) {
3423
-
3424
- const num = read( 1 );
3425
- if ( num === CORRECT[ i ] ) {
3426
-
3427
- return false;
3428
-
3429
- }
3430
-
3431
- }
3432
-
3433
- return true;
3434
-
3435
- }
3436
-
3437
- function getFbxVersion( text ) {
3438
-
3439
- const versionRegExp = /FBXVersion: (\d+)/;
3440
- const match = text.match( versionRegExp );
3441
- if ( match ) {
3442
-
3443
- const version = parseInt( match[ 1 ] );
3444
- return version;
3445
-
3446
- }
3447
-
3448
- throw new Error( 'THREE.FBXLoader: Cannot find the version number for the file given.' );
3449
-
3450
- }
3451
-
3452
- // Converts FBX ticks into real time seconds.
3453
- function convertFBXTimeToSeconds( time ) {
3454
-
3455
- return time / 46186158000;
3456
-
3457
- }
3458
-
3459
- const dataArray = [];
3460
-
3461
- // extracts the data from the correct position in the FBX array based on indexing type
3462
- function getData( polygonVertexIndex, polygonIndex, vertexIndex, infoObject ) {
3463
-
3464
- let index;
3465
- switch ( infoObject.mappingType ) {
3466
-
3467
- case 'ByPolygonVertex':
3468
- index = polygonVertexIndex;
3469
- break;
3470
- case 'ByPolygon':
3471
- index = polygonIndex;
3472
- break;
3473
- case 'ByVertice':
3474
- index = vertexIndex;
3475
- break;
3476
- case 'AllSame':
3477
- index = infoObject.indices[ 0 ];
3478
- break;
3479
- default:
3480
- console.warn( 'THREE.FBXLoader: unknown attribute mapping type ' + infoObject.mappingType );
3481
-
3482
- }
3483
-
3484
- if ( infoObject.referenceType === 'IndexToDirect' ) index = infoObject.indices[ index ];
3485
- const from = index * infoObject.dataSize;
3486
- const to = from + infoObject.dataSize;
3487
- return slice( dataArray, infoObject.buffer, from, to );
3488
-
3489
- }
3490
-
3491
- const tempEuler = new THREE.Euler();
3492
- const tempVec = new THREE.Vector3();
3493
-
3494
- // generate transformation from FBX transform data
3495
- // ref: https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm
3496
- // 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
3497
- function generateTransform( transformData ) {
3498
-
3499
- const lTranslationM = new THREE.Matrix4();
3500
- const lPreRotationM = new THREE.Matrix4();
3501
- const lRotationM = new THREE.Matrix4();
3502
- const lPostRotationM = new THREE.Matrix4();
3503
- const lScalingM = new THREE.Matrix4();
3504
- const lScalingPivotM = new THREE.Matrix4();
3505
- const lScalingOffsetM = new THREE.Matrix4();
3506
- const lRotationOffsetM = new THREE.Matrix4();
3507
- const lRotationPivotM = new THREE.Matrix4();
3508
- const lParentGX = new THREE.Matrix4();
3509
- const lParentLX = new THREE.Matrix4();
3510
- const lGlobalT = new THREE.Matrix4();
3511
- const inheritType = transformData.inheritType ? transformData.inheritType : 0;
3512
- if ( transformData.translation ) lTranslationM.setPosition( tempVec.fromArray( transformData.translation ) );
3513
- if ( transformData.preRotation ) {
3514
-
3515
- const array = transformData.preRotation.map( THREE.MathUtils.degToRad );
3516
- array.push( transformData.eulerOrder || THREE.Euler.DefaultOrder );
3517
- lPreRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) );
3518
-
3519
- }
3520
-
3521
- if ( transformData.rotation ) {
3522
-
3523
- const array = transformData.rotation.map( THREE.MathUtils.degToRad );
3524
- array.push( transformData.eulerOrder || THREE.Euler.DefaultOrder );
3525
- lRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) );
3526
-
3527
- }
3528
-
3529
- if ( transformData.postRotation ) {
3530
-
3531
- const array = transformData.postRotation.map( THREE.MathUtils.degToRad );
3532
- array.push( transformData.eulerOrder || THREE.Euler.DefaultOrder );
3533
- lPostRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) );
3534
- lPostRotationM.invert();
3535
-
3536
- }
3537
-
3538
- if ( transformData.scale ) lScalingM.scale( tempVec.fromArray( transformData.scale ) );
3539
-
3540
- // Pivots and offsets
3541
- if ( transformData.scalingOffset ) lScalingOffsetM.setPosition( tempVec.fromArray( transformData.scalingOffset ) );
3542
- if ( transformData.scalingPivot ) lScalingPivotM.setPosition( tempVec.fromArray( transformData.scalingPivot ) );
3543
- if ( transformData.rotationOffset ) lRotationOffsetM.setPosition( tempVec.fromArray( transformData.rotationOffset ) );
3544
- if ( transformData.rotationPivot ) lRotationPivotM.setPosition( tempVec.fromArray( transformData.rotationPivot ) );
3545
-
3546
- // parent transform
3547
- if ( transformData.parentMatrixWorld ) {
3548
-
3549
- lParentLX.copy( transformData.parentMatrix );
3550
- lParentGX.copy( transformData.parentMatrixWorld );
3551
-
3552
- }
3553
-
3554
- const lLRM = lPreRotationM.clone().multiply( lRotationM ).multiply( lPostRotationM );
3555
- // Global Rotation
3556
- const lParentGRM = new THREE.Matrix4();
3557
- lParentGRM.extractRotation( lParentGX );
3558
-
3559
- // Global Shear*Scaling
3560
- const lParentTM = new THREE.Matrix4();
3561
- lParentTM.copyPosition( lParentGX );
3562
- const lParentGRSM = lParentTM.clone().invert().multiply( lParentGX );
3563
- const lParentGSM = lParentGRM.clone().invert().multiply( lParentGRSM );
3564
- const lLSM = lScalingM;
3565
- const lGlobalRS = new THREE.Matrix4();
3566
- if ( inheritType === 0 ) {
3567
-
3568
- lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM ).multiply( lLSM );
3569
-
3570
- } else if ( inheritType === 1 ) {
3571
-
3572
- lGlobalRS.copy( lParentGRM ).multiply( lParentGSM ).multiply( lLRM ).multiply( lLSM );
3573
-
3574
- } else {
3575
-
3576
- const lParentLSM = new THREE.Matrix4().scale( new THREE.Vector3().setFromMatrixScale( lParentLX ) );
3577
- const lParentLSM_inv = lParentLSM.clone().invert();
3578
- const lParentGSM_noLocal = lParentGSM.clone().multiply( lParentLSM_inv );
3579
- lGlobalRS.copy( lParentGRM ).multiply( lLRM ).multiply( lParentGSM_noLocal ).multiply( lLSM );
3580
-
3581
- }
3582
-
3583
- const lRotationPivotM_inv = lRotationPivotM.clone().invert();
3584
- const lScalingPivotM_inv = lScalingPivotM.clone().invert();
3585
- // Calculate the local transform matrix
3586
- 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 );
3587
- const lLocalTWithAllPivotAndOffsetInfo = new THREE.Matrix4().copyPosition( lTransform );
3588
- const lGlobalTranslation = lParentGX.clone().multiply( lLocalTWithAllPivotAndOffsetInfo );
3589
- lGlobalT.copyPosition( lGlobalTranslation );
3590
- lTransform = lGlobalT.clone().multiply( lGlobalRS );
3591
-
3592
- // from global to local
3593
- lTransform.premultiply( lParentGX.invert() );
3594
- return lTransform;
3595
-
3596
- }
3597
-
3598
- // Returns the three.js intrinsic THREE.Euler order corresponding to FBX extrinsic THREE.Euler order
3599
- // ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html
3600
- function getEulerOrder( order ) {
3601
-
3602
- order = order || 0;
3603
- const enums = [ 'ZYX',
3604
- // -> XYZ extrinsic
3605
- 'YZX',
3606
- // -> XZY extrinsic
3607
- 'XZY',
3608
- // -> YZX extrinsic
3609
- 'ZXY',
3610
- // -> YXZ extrinsic
3611
- 'YXZ',
3612
- // -> ZXY extrinsic
3613
- 'XYZ' // -> ZYX extrinsic
3614
- //'SphericXYZ', // not possible to support
3615
- ];
3616
-
3617
- if ( order === 6 ) {
3618
-
3619
- console.warn( 'THREE.FBXLoader: unsupported THREE.Euler Order: Spherical XYZ. Animations and rotations may be incorrect.' );
3620
- return enums[ 0 ];
3621
-
3622
- }
3623
-
3624
- return enums[ order ];
3625
-
3626
- }
3627
-
3628
- // Parses comma separated list of numbers and returns them an array.
3629
- // Used internally by the TextParser
3630
- function parseNumberArray( value ) {
3631
-
3632
- const array = value.split( ',' ).map( function ( val ) {
3633
-
3634
- return parseFloat( val );
3635
-
3636
- } );
3637
- return array;
3638
-
3639
- }
3640
-
3641
- function convertArrayBufferToString( buffer, from, to ) {
3642
-
3643
- if ( from === undefined ) from = 0;
3644
- if ( to === undefined ) to = buffer.byteLength;
3645
- return THREE.LoaderUtils.decodeText( new Uint8Array( buffer, from, to ) );
3646
-
3647
- }
3648
-
3649
- function append( a, b ) {
3650
-
3651
- for ( let i = 0, j = a.length, l = b.length; i < l; i ++, j ++ ) {
3652
-
3653
- a[ j ] = b[ i ];
3654
-
3655
- }
3656
-
3657
- }
3658
-
3659
- function slice( a, b, from, to ) {
3660
-
3661
- for ( let i = from, j = 0; i < to; i ++, j ++ ) {
3662
-
3663
- a[ j ] = b[ i ];
3664
-
3665
- }
3666
-
3667
- return a;
3668
-
3669
- }
3670
-
3671
- // inject array a2 into array a1 at index
3672
- function inject( a1, index, a2 ) {
3673
-
3674
- return a1.slice( 0, index ).concat( a2 ).concat( a1.slice( index ) );
3675
-
3676
- }
3677
-
3678
- THREE.FBXLoader = FBXLoader;
3679
-
3680
- } )();