@anov/3d 0.0.4-alpha.1 → 0.0.4-alpha13

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