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