three-stdlib 2.16.0 → 2.16.2
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/BufferGeometryUtils-1a7a235c.js +655 -0
- package/BufferGeometryUtils-971dfde3.js +1 -0
- package/Nodes-4f766d71.js +471 -0
- package/Nodes-9aa16d74.js +1 -0
- package/animation/AnimationClipCreator.cjs.js +1 -0
- package/animation/AnimationClipCreator.js +52 -32
- package/animation/CCDIKSolver.cjs.js +1 -0
- package/animation/CCDIKSolver.js +143 -64
- package/animation/MMDAnimationHelper.cjs.js +1 -0
- package/animation/MMDAnimationHelper.js +341 -150
- package/animation/MMDPhysics.cjs.js +1 -0
- package/animation/MMDPhysics.js +361 -154
- package/cameras/CinematicCamera.cjs.js +1 -0
- package/cameras/CinematicCamera.js +77 -67
- package/controls/ArcballControls.cjs.js +1 -0
- package/controls/ArcballControls.js +1449 -544
- package/controls/DeviceOrientationControls.cjs.js +1 -0
- package/controls/DeviceOrientationControls.js +97 -52
- package/controls/DragControls.cjs.js +1 -0
- package/controls/DragControls.js +187 -85
- package/controls/FirstPersonControls.cjs.js +1 -0
- package/controls/FirstPersonControls.js +193 -123
- package/controls/FlyControls.cjs.js +1 -0
- package/controls/FlyControls.d.ts +5 -4
- package/controls/FlyControls.js +160 -90
- package/controls/OrbitControls.cjs.js +1 -0
- package/controls/OrbitControls.js +481 -232
- package/controls/PointerLockControls.cjs.js +1 -0
- package/controls/PointerLockControls.js +99 -63
- package/controls/TrackballControls.cjs.js +1 -0
- package/controls/TrackballControls.js +383 -211
- package/controls/TransformControls.cjs.js +1 -0
- package/controls/TransformControls.js +782 -575
- package/controls/experimental/CameraControls.cjs.js +1 -0
- package/controls/experimental/CameraControls.js +609 -329
- package/csm/CSM.cjs.js +1 -0
- package/csm/CSM.js +108 -47
- package/csm/CSMFrustum.cjs.js +1 -0
- package/csm/CSMFrustum.js +29 -14
- package/csm/CSMHelper.cjs.js +1 -0
- package/csm/CSMHelper.js +34 -20
- package/csm/CSMShader.cjs.js +1 -0
- package/csm/CSMShader.js +11 -7
- package/curves/CurveExtras.cjs.js +1 -0
- package/curves/CurveExtras.js +115 -73
- package/curves/NURBSCurve.cjs.js +1 -0
- package/curves/NURBSCurve.js +43 -15
- package/curves/NURBSSurface.cjs.js +1 -0
- package/curves/NURBSSurface.js +27 -11
- package/curves/NURBSUtils.cjs.js +1 -0
- package/curves/NURBSUtils.js +203 -54
- package/custom.d.cjs.js +1 -0
- package/{shaders/types.mjs → custom.d.js} +0 -0
- package/deprecated/Geometry.cjs.js +1 -0
- package/deprecated/Geometry.js +486 -191
- package/effects/AnaglyphEffect.cjs.js +1 -0
- package/effects/AnaglyphEffect.js +60 -95
- package/effects/AsciiEffect.cjs.js +1 -0
- package/effects/AsciiEffect.js +110 -80
- package/effects/OutlineEffect.cjs.js +1 -0
- package/effects/OutlineEffect.js +204 -121
- package/effects/ParallaxBarrierEffect.cjs.js +1 -0
- package/effects/ParallaxBarrierEffect.js +38 -39
- package/effects/PeppersGhostEffect.cjs.js +1 -0
- package/effects/PeppersGhostEffect.js +68 -19
- package/effects/StereoEffect.cjs.js +1 -0
- package/effects/StereoEffect.js +16 -12
- package/environments/RoomEnvironment.cjs.js +1 -0
- package/environments/RoomEnvironment.js +47 -52
- package/exporters/ColladaExporter.cjs.js +1 -0
- package/exporters/ColladaExporter.js +241 -115
- package/exporters/DRACOExporter.cjs.js +1 -0
- package/exporters/DRACOExporter.js +121 -67
- package/exporters/GLTFExporter.cjs.js +1 -0
- package/exporters/GLTFExporter.js +1014 -463
- package/exporters/MMDExporter.cjs.js +1 -0
- package/exporters/MMDExporter.js +102 -44
- package/exporters/OBJExporter.cjs.js +1 -0
- package/exporters/OBJExporter.js +140 -78
- package/exporters/PLYExporter.cjs.js +1 -0
- package/exporters/PLYExporter.js +154 -93
- package/exporters/STLExporter.cjs.js +1 -0
- package/exporters/STLExporter.js +81 -30
- package/exporters/USDZExporter.cjs.js +1 -0
- package/exporters/USDZExporter.js +144 -84
- package/geometries/BoxLineGeometry.cjs.js +1 -0
- package/geometries/BoxLineGeometry.js +14 -7
- package/geometries/ConvexGeometry.cjs.js +1 -0
- package/geometries/ConvexGeometry.js +23 -14
- package/geometries/DecalGeometry.cjs.js +1 -0
- package/geometries/DecalGeometry.js +162 -108
- package/geometries/LightningStrike.cjs.js +1 -0
- package/geometries/LightningStrike.js +294 -101
- package/geometries/ParametricGeometries.cjs.js +1 -0
- package/geometries/ParametricGeometries.js +76 -26
- package/geometries/ParametricGeometry.cjs.js +1 -0
- package/geometries/ParametricGeometry.js +48 -24
- package/geometries/RoundedBoxGeometry.cjs.js +1 -0
- package/geometries/RoundedBoxGeometry.js +64 -33
- package/geometries/TeapotGeometry.cjs.js +1 -0
- package/geometries/TeapotGeometry.js +174 -1434
- package/geometries/TextGeometry.cjs.js +1 -0
- package/geometries/TextGeometry.js +17 -9
- package/helpers/LightProbeHelper.cjs.js +1 -0
- package/helpers/LightProbeHelper.js +21 -53
- package/helpers/PositionalAudioHelper.cjs.js +1 -0
- package/helpers/PositionalAudioHelper.js +30 -23
- package/helpers/RectAreaLightHelper.cjs.js +1 -0
- package/helpers/RectAreaLightHelper.js +33 -17
- package/helpers/VertexNormalsHelper.cjs.js +1 -0
- package/helpers/VertexNormalsHelper.js +41 -20
- package/helpers/VertexTangentsHelper.cjs.js +1 -0
- package/helpers/VertexTangentsHelper.js +36 -18
- package/index.cjs.js +1 -0
- package/index.js +333 -969
- package/interactive/InteractiveGroup.cjs.js +1 -0
- package/interactive/InteractiveGroup.d.ts +5 -0
- package/interactive/InteractiveGroup.js +87 -0
- package/interactive/SelectionBox.cjs.js +1 -0
- package/interactive/SelectionBox.js +46 -31
- package/interactive/SelectionHelper.cjs.js +1 -0
- package/interactive/SelectionHelper.js +21 -16
- package/libs/MeshoptDecoder.cjs.js +1 -0
- package/libs/MeshoptDecoder.js +58 -147
- package/libs/MotionControllers.cjs.js +1 -0
- package/libs/MotionControllers.js +208 -66
- package/lights/LightProbeGenerator.cjs.js +1 -0
- package/lights/LightProbeGenerator.js +96 -40
- package/lights/RectAreaLightUniformsLib.cjs.js +1 -0
- package/lights/RectAreaLightUniformsLib.js +9 -32842
- package/lines/Line2.cjs.js +1 -0
- package/lines/Line2.js +12 -9
- package/lines/LineGeometry.cjs.js +1 -0
- package/lines/LineGeometry.js +19 -7
- package/lines/LineMaterial.cjs.js +1 -0
- package/lines/LineMaterial.js +89 -51
- package/lines/LineSegments2.cjs.js +1 -0
- package/lines/LineSegments2.js +165 -56
- package/lines/LineSegmentsGeometry.cjs.js +1 -0
- package/lines/LineSegmentsGeometry.js +71 -29
- package/lines/Wireframe.cjs.js +1 -0
- package/lines/Wireframe.js +29 -15
- package/lines/WireframeGeometry2.cjs.js +1 -0
- package/lines/WireframeGeometry2.js +9 -8
- package/loaders/3DMLoader.cjs.js +1 -0
- package/loaders/3DMLoader.js +469 -234
- package/loaders/3MFLoader.cjs.js +1 -0
- package/loaders/3MFLoader.js +555 -340
- package/loaders/AMFLoader.cjs.js +1 -0
- package/loaders/AMFLoader.js +219 -114
- package/loaders/AssimpLoader.cjs.js +1 -0
- package/loaders/AssimpLoader.js +725 -328
- package/loaders/BVHLoader.cjs.js +1 -0
- package/loaders/BVHLoader.js +200 -94
- package/loaders/BasisTextureLoader.cjs.js +1 -0
- package/loaders/BasisTextureLoader.js +357 -229
- package/loaders/ColladaLoader.cjs.js +1 -0
- package/loaders/ColladaLoader.js +1522 -932
- package/loaders/DDSLoader.cjs.js +1 -0
- package/loaders/DDSLoader.js +108 -42
- package/loaders/DRACOLoader.cjs.js +1 -0
- package/loaders/DRACOLoader.js +210 -103
- package/loaders/EXRLoader.cjs.js +1 -0
- package/loaders/EXRLoader.js +809 -461
- package/loaders/FBXLoader.cjs.js +1 -0
- package/loaders/FBXLoader.js +1397 -842
- package/loaders/FontLoader.cjs.js +1 -0
- package/loaders/FontLoader.js +66 -33
- package/loaders/GCodeLoader.cjs.js +1 -0
- package/loaders/GCodeLoader.js +111 -63
- package/loaders/GLTFLoader.cjs.js +1 -0
- package/loaders/GLTFLoader.js +1484 -771
- package/loaders/HDRCubeTextureLoader.cjs.js +1 -0
- package/loaders/HDRCubeTextureLoader.js +50 -45
- package/loaders/KMZLoader.cjs.js +1 -0
- package/loaders/KMZLoader.js +55 -42
- package/loaders/KTX2Loader.cjs.js +1 -0
- package/loaders/KTX2Loader.js +362 -229
- package/loaders/KTXLoader.cjs.js +1 -0
- package/loaders/KTXLoader.js +99 -37
- package/loaders/LDrawLoader.cjs.js +1 -0
- package/loaders/LDrawLoader.js +746 -313
- package/loaders/LUT3dlLoader.cjs.js +1 -0
- package/loaders/LUT3dlLoader.js +62 -50
- package/loaders/LUTCubeLoader.cjs.js +1 -0
- package/loaders/LUTCubeLoader.js +56 -45
- package/loaders/LWOLoader.cjs.js +1 -0
- package/loaders/LWOLoader.js +339 -227
- package/loaders/LottieLoader.cjs.js +1 -0
- package/loaders/LottieLoader.js +38 -36
- package/loaders/MD2Loader.cjs.js +1 -0
- package/loaders/MD2Loader.js +91 -248
- package/loaders/MDDLoader.cjs.js +1 -0
- package/loaders/MDDLoader.js +45 -25
- package/loaders/MMDLoader.cjs.js +1 -0
- package/loaders/MMDLoader.js +795 -359
- package/loaders/MTLLoader.cjs.js +1 -0
- package/loaders/MTLLoader.js +201 -91
- package/loaders/NRRDLoader.cjs.js +1 -0
- package/loaders/NRRDLoader.js +263 -182
- package/loaders/NodeMaterialLoader.cjs.js +1 -0
- package/loaders/NodeMaterialLoader.js +14 -121
- package/loaders/OBJLoader.cjs.js +1 -0
- package/loaders/OBJLoader.js +283 -161
- package/loaders/PCDLoader.cjs.js +1 -0
- package/loaders/PCDLoader.js +164 -145
- package/loaders/PDBLoader.cjs.js +1 -0
- package/loaders/PDBLoader.js +63 -45
- package/loaders/PLYLoader.cjs.js +1 -0
- package/loaders/PLYLoader.js +203 -106
- package/loaders/PRWMLoader.cjs.js +1 -0
- package/loaders/PRWMLoader.js +110 -73
- package/loaders/PVRLoader.cjs.js +1 -0
- package/loaders/PVRLoader.js +93 -32
- package/loaders/RGBELoader.cjs.js +1 -0
- package/loaders/RGBELoader.js +233 -96
- package/loaders/RGBMLoader.cjs.js +1 -0
- package/loaders/RGBMLoader.js +514 -344
- package/loaders/STLLoader.cjs.js +1 -0
- package/loaders/STLLoader.js +165 -59
- package/loaders/SVGLoader.cjs.js +1 -0
- package/loaders/SVGLoader.js +851 -481
- package/loaders/TDSLoader.cjs.js +1 -0
- package/loaders/TDSLoader.js +527 -137
- package/loaders/TGALoader.cjs.js +1 -0
- package/loaders/TGALoader.js +205 -94
- package/loaders/TTFLoader.cjs.js +1 -0
- package/loaders/TTFLoader.js +79 -58
- package/loaders/TiltLoader.cjs.js +1 -0
- package/loaders/TiltLoader.js +167 -129
- package/loaders/VOXLoader.cjs.js +1 -0
- package/loaders/VOXLoader.js +84 -320
- package/loaders/VRMLLoader.cjs.js +1 -0
- package/loaders/VRMLLoader.js +1268 -786
- package/loaders/VRMLoader.cjs.js +1 -0
- package/loaders/VRMLoader.js +31 -23
- package/loaders/VTKLoader.cjs.js +1 -0
- package/loaders/VTKLoader.js +407 -219
- package/loaders/XLoader.cjs.js +1 -0
- package/loaders/XLoader.js +1259 -1083
- package/loaders/XYZLoader.cjs.js +1 -0
- package/loaders/XYZLoader.js +34 -28
- package/loaders/lwo/IFFParser.cjs.js +1 -0
- package/loaders/lwo/IFFParser.js +492 -238
- package/loaders/lwo/LWO2Parser.cjs.js +1 -0
- package/loaders/lwo/LWO2Parser.js +279 -176
- package/loaders/lwo/LWO3Parser.cjs.js +1 -0
- package/loaders/lwo/LWO3Parser.js +247 -160
- package/math/Capsule.cjs.js +1 -0
- package/math/Capsule.js +43 -56
- package/math/ColorConverter.cjs.js +1 -0
- package/math/ColorConverter.js +32 -18
- package/math/ConvexHull.cjs.js +1 -0
- package/math/ConvexHull.js +357 -97
- package/math/ImprovedNoise.cjs.js +1 -0
- package/math/ImprovedNoise.js +32 -282
- package/math/Lut.cjs.js +1 -0
- package/math/Lut.js +35 -51
- package/math/MeshSurfaceSampler.cjs.js +1 -0
- package/math/MeshSurfaceSampler.js +68 -25
- package/math/OBB.cjs.js +1 -0
- package/math/OBB.js +152 -91
- package/math/Octree.cjs.js +1 -0
- package/math/Octree.js +139 -76
- package/math/SimplexNoise.cjs.js +1 -0
- package/math/SimplexNoise.js +238 -217
- package/misc/ConvexObjectBreaker.cjs.js +1 -0
- package/misc/ConvexObjectBreaker.js +185 -79
- package/misc/GPUComputationRenderer.cjs.js +1 -0
- package/misc/GPUComputationRenderer.js +194 -69
- package/misc/Gyroscope.cjs.js +1 -0
- package/misc/Gyroscope.js +22 -16
- package/misc/MD2Character.cjs.js +1 -0
- package/misc/MD2Character.js +74 -52
- package/misc/MD2CharacterComplex.cjs.js +1 -0
- package/misc/MD2CharacterComplex.js +163 -112
- package/misc/MorphAnimMesh.cjs.js +1 -0
- package/misc/MorphAnimMesh.js +28 -20
- package/misc/MorphBlendMesh.cjs.js +1 -0
- package/misc/MorphBlendMesh.js +69 -45
- package/misc/ProgressiveLightmap.cjs.js +1 -0
- package/misc/ProgressiveLightmap.js +187 -70
- package/misc/RollerCoaster.cjs.js +1 -0
- package/misc/RollerCoaster.js +135 -106
- package/misc/TubePainter.cjs.js +1 -0
- package/misc/TubePainter.js +92 -74
- package/misc/Volume.cjs.js +1 -0
- package/misc/Volume.js +270 -108
- package/misc/VolumeSlice.cjs.js +1 -0
- package/misc/VolumeSlice.js +122 -34
- package/misc/WebGL.cjs.js +1 -0
- package/misc/WebGL.js +34 -37
- package/modifiers/CurveModifier.cjs.js +1 -0
- package/modifiers/CurveModifier.js +151 -46
- package/modifiers/EdgeSplitModifier.cjs.js +1 -0
- package/modifiers/EdgeSplitModifier.js +90 -46
- package/modifiers/SimplifyModifier.cjs.js +1 -0
- package/modifiers/SimplifyModifier.js +202 -77
- package/modifiers/TessellateModifier.cjs.js +1 -0
- package/modifiers/TessellateModifier.js +90 -65
- package/nodes/Nodes.cjs.js +1 -0
- package/nodes/Nodes.js +140 -274
- package/nodes/ShaderNode.cjs.js +1 -0
- package/nodes/ShaderNode.js +196 -296
- package/nodes/accessors/BufferNode.cjs.js +1 -0
- package/nodes/accessors/BufferNode.js +8 -4
- package/nodes/accessors/CameraNode.cjs.js +1 -0
- package/nodes/accessors/CameraNode.js +25 -20
- package/nodes/accessors/CubeTextureNode.cjs.js +1 -0
- package/nodes/accessors/CubeTextureNode.js +26 -14
- package/nodes/accessors/MaterialNode.cjs.js +1 -0
- package/nodes/accessors/MaterialNode.js +53 -43
- package/nodes/accessors/MaterialReferenceNode.cjs.js +1 -0
- package/nodes/accessors/MaterialReferenceNode.js +6 -3
- package/nodes/accessors/ModelNode.cjs.js +1 -0
- package/nodes/accessors/ModelNode.js +5 -3
- package/nodes/accessors/ModelViewProjectionNode.cjs.js +1 -0
- package/nodes/accessors/ModelViewProjectionNode.js +13 -14
- package/nodes/accessors/NormalNode.cjs.js +1 -0
- package/nodes/accessors/NormalNode.js +39 -40
- package/nodes/accessors/Object3DNode.cjs.js +1 -0
- package/nodes/accessors/Object3DNode.js +50 -40
- package/nodes/accessors/PointUVNode.cjs.js +1 -0
- package/nodes/accessors/PointUVNode.js +9 -5
- package/nodes/accessors/PositionNode.cjs.js +1 -0
- package/nodes/accessors/PositionNode.js +41 -42
- package/nodes/accessors/ReferenceNode.cjs.js +1 -0
- package/nodes/accessors/ReferenceNode.js +17 -10
- package/nodes/accessors/ReflectNode.cjs.js +1 -0
- package/nodes/accessors/ReflectNode.js +26 -23
- package/nodes/accessors/SkinningNode.cjs.js +1 -0
- package/nodes/accessors/SkinningNode.js +48 -46
- package/nodes/accessors/TextureNode.cjs.js +1 -0
- package/nodes/accessors/TextureNode.js +29 -14
- package/nodes/accessors/UVNode.cjs.js +1 -0
- package/nodes/accessors/UVNode.js +11 -5
- package/nodes/core/ArrayUniformNode.cjs.js +1 -0
- package/nodes/core/ArrayUniformNode.js +7 -3
- package/nodes/core/AttributeNode.cjs.js +1 -0
- package/nodes/core/AttributeNode.js +12 -5
- package/nodes/core/BypassNode.cjs.js +1 -0
- package/nodes/core/BypassNode.js +12 -5
- package/nodes/core/CodeNode.cjs.js +1 -0
- package/nodes/core/CodeNode.js +12 -4
- package/nodes/core/ConstNode.cjs.js +1 -0
- package/nodes/core/ConstNode.js +7 -3
- package/nodes/core/ContextNode.cjs.js +1 -0
- package/nodes/core/ContextNode.js +8 -3
- package/nodes/core/ExpressionNode.cjs.js +1 -0
- package/nodes/core/ExpressionNode.js +9 -5
- package/nodes/core/FunctionCallNode.cjs.js +1 -0
- package/nodes/core/FunctionCallNode.js +15 -6
- package/nodes/core/FunctionNode.cjs.js +1 -0
- package/nodes/core/FunctionNode.js +25 -10
- package/nodes/core/InputNode.cjs.js +1 -0
- package/nodes/core/InputNode.js +23 -12
- package/nodes/core/Node.cjs.js +1 -0
- package/nodes/core/Node.js +75 -35
- package/nodes/core/NodeAttribute.cjs.js +1 -0
- package/nodes/core/NodeAttribute.js +4 -2
- package/nodes/core/NodeBuilder.cjs.js +1 -0
- package/nodes/core/NodeBuilder.js +224 -110
- package/nodes/core/NodeCode.cjs.js +1 -0
- package/nodes/core/NodeCode.js +7 -4
- package/nodes/core/NodeFrame.cjs.js +1 -0
- package/nodes/core/NodeFrame.js +12 -9
- package/nodes/core/NodeFunction.cjs.js +1 -0
- package/nodes/core/NodeFunction.js +17 -0
- package/nodes/core/NodeFunctionInput.cjs.js +1 -0
- package/nodes/core/NodeFunctionInput.js +5 -3
- package/nodes/core/NodeKeywords.cjs.js +1 -0
- package/nodes/core/NodeKeywords.js +16 -5
- package/nodes/core/NodeParser.cjs.js +1 -0
- package/nodes/core/NodeParser.js +8 -0
- package/nodes/core/NodeUniform.cjs.js +1 -0
- package/nodes/core/NodeUniform.js +7 -3
- package/nodes/core/NodeUtils.cjs.js +1 -0
- package/nodes/core/NodeUtils.js +43 -39
- package/nodes/core/NodeVar.cjs.js +1 -0
- package/nodes/core/NodeVar.js +4 -2
- package/nodes/core/NodeVary.cjs.js +1 -0
- package/nodes/core/NodeVary.js +4 -2
- package/nodes/core/PropertyNode.cjs.js +1 -0
- package/nodes/core/PropertyNode.js +10 -4
- package/nodes/core/TempNode.cjs.js +1 -0
- package/nodes/core/TempNode.js +11 -5
- package/nodes/core/UniformNode.cjs.js +1 -0
- package/nodes/core/UniformNode.js +10 -4
- package/nodes/core/VarNode.cjs.js +1 -0
- package/nodes/core/VarNode.js +11 -3
- package/nodes/core/VaryNode.cjs.js +1 -0
- package/nodes/core/VaryNode.js +15 -6
- package/nodes/core/constants.cjs.js +1 -0
- package/nodes/core/constants.js +7 -20
- package/nodes/display/ColorSpaceNode.cjs.js +1 -0
- package/nodes/display/ColorSpaceNode.js +38 -34
- package/nodes/display/NormalMapNode.cjs.js +1 -0
- package/nodes/display/NormalMapNode.js +53 -35
- package/nodes/fog/FogNode.cjs.js +1 -0
- package/nodes/fog/FogNode.js +9 -5
- package/nodes/fog/FogRangeNode.cjs.js +1 -0
- package/nodes/fog/FogRangeNode.js +9 -5
- package/nodes/functions/BSDFs.cjs.js +1 -0
- package/nodes/functions/BSDFs.js +118 -61
- package/nodes/functions/PhysicalMaterialFunctions.cjs.js +1 -0
- package/nodes/functions/PhysicalMaterialFunctions.js +57 -0
- package/nodes/lights/LightContextNode.cjs.js +1 -0
- package/nodes/lights/LightContextNode.js +23 -14
- package/nodes/lights/LightNode.cjs.js +1 -0
- package/nodes/lights/LightNode.js +31 -27
- package/nodes/lights/LightsNode.cjs.js +1 -0
- package/nodes/lights/LightsNode.js +28 -9
- package/nodes/loaders/NodeLoader.cjs.js +1 -0
- package/nodes/loaders/NodeLoader.js +42 -27
- package/nodes/loaders/NodeMaterialLoader.cjs.js +1 -0
- package/nodes/loaders/NodeMaterialLoader.js +10 -4
- package/nodes/loaders/NodeObjectLoader.cjs.js +1 -0
- package/nodes/loaders/NodeObjectLoader.js +19 -9
- package/nodes/materials/LineBasicNodeMaterial.cjs.js +1 -0
- package/nodes/materials/LineBasicNodeMaterial.js +10 -5
- package/nodes/materials/Materials.cjs.js +1 -0
- package/nodes/materials/Materials.js +17 -14
- package/nodes/materials/MeshBasicNodeMaterial.cjs.js +1 -0
- package/nodes/materials/MeshBasicNodeMaterial.js +10 -5
- package/nodes/materials/MeshStandardNodeMaterial.cjs.js +1 -0
- package/nodes/materials/MeshStandardNodeMaterial.js +8 -5
- package/nodes/materials/NodeMaterial.cjs.js +1 -0
- package/nodes/materials/NodeMaterial.js +36 -20
- package/nodes/materials/PointsNodeMaterial.cjs.js +1 -0
- package/nodes/materials/PointsNodeMaterial.js +10 -5
- package/nodes/math/CondNode.cjs.js +1 -0
- package/nodes/math/CondNode.js +23 -11
- package/nodes/math/MathNode.cjs.js +1 -0
- package/nodes/math/MathNode.js +142 -98
- package/nodes/math/OperatorNode.cjs.js +1 -0
- package/nodes/math/OperatorNode.js +46 -24
- package/nodes/parsers/GLSLNodeFunction.cjs.js +1 -0
- package/nodes/parsers/GLSLNodeFunction.js +101 -0
- package/nodes/parsers/GLSLNodeParser.cjs.js +1 -0
- package/nodes/parsers/GLSLNodeParser.js +13 -0
- package/nodes/parsers/WGSLNodeFunction.cjs.js +1 -0
- package/nodes/parsers/WGSLNodeFunction.js +71 -0
- package/nodes/parsers/WGSLNodeParser.cjs.js +1 -0
- package/nodes/parsers/WGSLNodeParser.js +13 -0
- package/nodes/procedural/CheckerNode.cjs.js +1 -0
- package/nodes/procedural/CheckerNode.js +19 -13
- package/nodes/utils/ArrayElementNode.cjs.js +1 -0
- package/nodes/utils/ArrayElementNode.js +8 -4
- package/nodes/utils/ConvertNode.cjs.js +1 -0
- package/nodes/utils/ConvertNode.js +8 -3
- package/nodes/utils/JoinNode.cjs.js +1 -0
- package/nodes/utils/JoinNode.js +11 -7
- package/nodes/utils/MatcapUVNode.cjs.js +1 -0
- package/nodes/utils/MatcapUVNode.js +11 -8
- package/nodes/utils/OscNode.cjs.js +1 -0
- package/nodes/utils/OscNode.js +33 -27
- package/nodes/utils/SplitNode.cjs.js +1 -0
- package/nodes/utils/SplitNode.js +20 -6
- package/nodes/utils/SpriteSheetUVNode.cjs.js +1 -0
- package/nodes/utils/SpriteSheetUVNode.js +23 -23
- package/nodes/utils/TimerNode.cjs.js +1 -0
- package/nodes/utils/TimerNode.js +24 -20
- package/objects/GroundProjectedEnv.cjs.js +1 -0
- package/objects/GroundProjectedEnv.js +37 -22
- package/objects/Lensflare.cjs.js +1 -0
- package/objects/Lensflare.js +156 -86
- package/objects/LightningStorm.cjs.js +1 -0
- package/objects/LightningStorm.js +102 -38
- package/objects/MarchingCubes.cjs.js +1 -0
- package/objects/MarchingCubes.js +303 -150
- package/objects/Reflector.cjs.js +1 -0
- package/objects/Reflector.js +72 -50
- package/objects/ReflectorForSSRPass.cjs.js +1 -0
- package/objects/ReflectorForSSRPass.js +131 -80
- package/objects/ReflectorRTT.cjs.js +1 -0
- package/objects/ReflectorRTT.js +7 -6
- package/objects/Refractor.cjs.js +1 -0
- package/objects/Refractor.js +106 -64
- package/objects/ShadowMesh.cjs.js +1 -0
- package/objects/ShadowMesh.js +17 -8
- package/objects/Sky.cjs.js +1 -0
- package/objects/Sky.js +80 -119
- package/objects/Water.cjs.js +1 -0
- package/objects/Water.js +127 -83
- package/objects/Water2.cjs.js +1 -0
- package/objects/Water2.js +108 -72
- package/offscreen/jank.cjs.js +1 -0
- package/offscreen/jank.js +14 -10
- package/offscreen/offscreen.cjs.js +1 -0
- package/offscreen/offscreen.js +5 -4
- package/offscreen/scene.cjs.js +1 -0
- package/offscreen/scene.js +48 -45
- package/package.json +3 -3
- package/physics/AmmoPhysics.cjs.js +1 -0
- package/physics/AmmoPhysics.js +71 -30
- package/postprocessing/AdaptiveToneMappingPass.cjs.js +1 -0
- package/postprocessing/AdaptiveToneMappingPass.js +123 -97
- package/postprocessing/AfterimagePass.cjs.js +1 -0
- package/postprocessing/AfterimagePass.js +49 -28
- package/postprocessing/BloomPass.cjs.js +1 -0
- package/postprocessing/BloomPass.js +69 -43
- package/postprocessing/BokehPass.cjs.js +1 -0
- package/postprocessing/BokehPass.js +69 -39
- package/postprocessing/ClearPass.cjs.js +1 -0
- package/postprocessing/ClearPass.js +25 -10
- package/postprocessing/CubeTexturePass.cjs.js +1 -0
- package/postprocessing/CubeTexturePass.js +27 -28
- package/postprocessing/DotScreenPass.cjs.js +1 -0
- package/postprocessing/DotScreenPass.js +32 -24
- package/postprocessing/EffectComposer.cjs.js +1 -0
- package/postprocessing/EffectComposer.js +86 -39
- package/postprocessing/FilmPass.cjs.js +1 -0
- package/postprocessing/FilmPass.js +30 -25
- package/postprocessing/GlitchPass.cjs.js +1 -0
- package/postprocessing/GlitchPass.js +61 -38
- package/postprocessing/HalftonePass.cjs.js +1 -0
- package/postprocessing/HalftonePass.js +39 -19
- package/postprocessing/LUTPass.cjs.js +1 -0
- package/postprocessing/LUTPass.js +38 -13
- package/postprocessing/MaskPass.cjs.js +1 -0
- package/postprocessing/MaskPass.js +38 -19
- package/postprocessing/OutlinePass.cjs.js +1 -0
- package/postprocessing/OutlinePass.js +277 -135
- package/postprocessing/Pass.cjs.js +1 -0
- package/postprocessing/Pass.js +44 -20
- package/postprocessing/RenderPass.cjs.js +1 -0
- package/postprocessing/RenderPass.js +36 -13
- package/postprocessing/RenderPixelatedPass.cjs.js +1 -0
- package/postprocessing/RenderPixelatedPass.js +58 -44
- package/postprocessing/SAOPass.cjs.js +1 -0
- package/postprocessing/SAOPass.js +189 -154
- package/postprocessing/SMAAPass.cjs.js +1 -0
- package/postprocessing/SMAAPass.js +84 -64
- package/postprocessing/SSAARenderPass.cjs.js +1 -0
- package/postprocessing/SSAARenderPass.js +69 -121
- package/postprocessing/SSAOPass.cjs.js +1 -0
- package/postprocessing/SSAOPass.js +172 -123
- package/postprocessing/SSRPass.cjs.js +1 -0
- package/postprocessing/SSRPass.js +280 -211
- package/postprocessing/SavePass.cjs.js +1 -0
- package/postprocessing/SavePass.js +25 -20
- package/postprocessing/ShaderPass.cjs.js +1 -0
- package/postprocessing/ShaderPass.js +30 -14
- package/postprocessing/TAARenderPass.cjs.js +1 -0
- package/postprocessing/TAARenderPass.js +61 -42
- package/postprocessing/TexturePass.cjs.js +1 -0
- package/postprocessing/TexturePass.js +22 -21
- package/postprocessing/UnrealBloomPass.cjs.js +1 -0
- package/postprocessing/UnrealBloomPass.js +213 -105
- package/renderers/CSS2DRenderer.cjs.js +1 -0
- package/renderers/CSS2DRenderer.js +56 -44
- package/renderers/CSS3DRenderer.cjs.js +1 -0
- package/renderers/CSS3DRenderer.js +86 -53
- package/renderers/Projector.cjs.js +1 -0
- package/renderers/Projector.js +274 -107
- package/renderers/SVGRenderer.cjs.js +1 -0
- package/renderers/SVGRenderer.js +182 -72
- package/renderers/nodes/accessors/CameraNode.cjs.js +1 -0
- package/renderers/nodes/accessors/CameraNode.js +40 -29
- package/renderers/nodes/accessors/ModelNode.cjs.js +1 -0
- package/renderers/nodes/accessors/ModelNode.js +37 -28
- package/renderers/nodes/accessors/ModelViewProjectionNode.cjs.js +1 -0
- package/renderers/nodes/accessors/ModelViewProjectionNode.js +23 -10
- package/renderers/nodes/accessors/NormalNode.cjs.js +1 -0
- package/renderers/nodes/accessors/NormalNode.js +45 -35
- package/renderers/nodes/accessors/PositionNode.cjs.js +1 -0
- package/renderers/nodes/accessors/PositionNode.js +19 -18
- package/renderers/nodes/accessors/UVNode.cjs.js +1 -0
- package/renderers/nodes/accessors/UVNode.js +10 -5
- package/renderers/nodes/core/AttributeNode.cjs.js +1 -0
- package/renderers/nodes/core/AttributeNode.js +14 -5
- package/renderers/nodes/core/InputNode.cjs.js +1 -0
- package/renderers/nodes/core/InputNode.js +14 -4
- package/renderers/nodes/core/Node.cjs.js +1 -0
- package/renderers/nodes/core/Node.js +17 -7
- package/renderers/nodes/core/NodeAttribute.cjs.js +1 -0
- package/renderers/nodes/core/NodeAttribute.js +6 -3
- package/renderers/nodes/core/NodeBuilder.cjs.js +1 -0
- package/renderers/nodes/core/NodeBuilder.js +154 -87
- package/renderers/nodes/core/NodeFrame.cjs.js +1 -0
- package/renderers/nodes/core/NodeFrame.js +12 -9
- package/renderers/nodes/core/NodeSlot.cjs.js +1 -0
- package/renderers/nodes/core/NodeSlot.js +3 -2
- package/renderers/nodes/core/NodeUniform.cjs.js +1 -0
- package/renderers/nodes/core/NodeUniform.js +9 -4
- package/renderers/nodes/core/NodeVary.cjs.js +1 -0
- package/renderers/nodes/core/NodeVary.js +7 -4
- package/renderers/nodes/core/VaryNode.cjs.js +1 -0
- package/renderers/nodes/core/VaryNode.js +12 -6
- package/renderers/nodes/core/constants.cjs.js +1 -0
- package/renderers/nodes/core/constants.js +13 -16
- package/renderers/nodes/inputs/ColorNode.cjs.js +1 -0
- package/renderers/nodes/inputs/ColorNode.js +11 -5
- package/renderers/nodes/inputs/FloatNode.cjs.js +1 -0
- package/renderers/nodes/inputs/FloatNode.js +11 -5
- package/renderers/nodes/inputs/Matrix3Node.cjs.js +1 -0
- package/renderers/nodes/inputs/Matrix3Node.js +13 -7
- package/renderers/nodes/inputs/Matrix4Node.cjs.js +1 -0
- package/renderers/nodes/inputs/Matrix4Node.js +13 -7
- package/renderers/nodes/inputs/TextureNode.cjs.js +1 -0
- package/renderers/nodes/inputs/TextureNode.js +15 -7
- package/renderers/nodes/inputs/Vector2Node.cjs.js +1 -0
- package/renderers/nodes/inputs/Vector2Node.js +11 -5
- package/renderers/nodes/inputs/Vector3Node.cjs.js +1 -0
- package/renderers/nodes/inputs/Vector3Node.js +13 -7
- package/renderers/nodes/inputs/Vector4Node.cjs.js +1 -0
- package/renderers/nodes/inputs/Vector4Node.js +13 -7
- package/renderers/nodes/math/MathNode.cjs.js +1 -0
- package/renderers/nodes/math/MathNode.js +30 -20
- package/renderers/nodes/math/OperatorNode.cjs.js +1 -0
- package/renderers/nodes/math/OperatorNode.js +20 -4
- package/renderers/nodes/utils/SwitchNode.cjs.js +1 -0
- package/renderers/nodes/utils/SwitchNode.js +9 -4
- package/renderers/nodes/utils/TimerNode.cjs.js +1 -0
- package/renderers/nodes/utils/TimerNode.js +10 -5
- package/renderers/webgpu/WebGPU.cjs.js +1 -0
- package/renderers/webgpu/WebGPU.js +16 -14
- package/renderers/webgpu/WebGPUAttributes.cjs.js +1 -0
- package/renderers/webgpu/WebGPUAttributes.js +23 -16
- package/renderers/webgpu/WebGPUBackground.cjs.js +1 -0
- package/renderers/webgpu/WebGPUBackground.js +30 -13
- package/renderers/webgpu/WebGPUBinding.cjs.js +1 -0
- package/renderers/webgpu/WebGPUBinding.js +7 -4
- package/renderers/webgpu/WebGPUBindings.cjs.js +1 -0
- package/renderers/webgpu/WebGPUBindings.js +57 -21
- package/renderers/webgpu/WebGPUComputePipelines.cjs.js +1 -0
- package/renderers/webgpu/WebGPUComputePipelines.js +25 -14
- package/renderers/webgpu/WebGPUGeometries.cjs.js +1 -0
- package/renderers/webgpu/WebGPUGeometries.js +15 -5
- package/renderers/webgpu/WebGPUInfo.cjs.js +1 -0
- package/renderers/webgpu/WebGPUInfo.js +8 -3
- package/renderers/webgpu/WebGPUObjects.cjs.js +1 -0
- package/renderers/webgpu/WebGPUObjects.js +10 -5
- package/renderers/webgpu/WebGPUProperties.cjs.js +1 -0
- package/renderers/webgpu/WebGPUProperties.js +11 -5
- package/renderers/webgpu/WebGPURenderLists.cjs.js +1 -0
- package/renderers/webgpu/WebGPURenderLists.js +36 -20
- package/renderers/webgpu/WebGPURenderPipelines.cjs.js +1 -0
- package/renderers/webgpu/WebGPURenderPipelines.js +387 -260
- package/renderers/webgpu/WebGPURenderer.cjs.js +1 -0
- package/renderers/webgpu/WebGPURenderer.js +262 -124
- package/renderers/webgpu/WebGPUSampledTexture.cjs.js +1 -0
- package/renderers/webgpu/WebGPUSampledTexture.js +31 -18
- package/renderers/webgpu/WebGPUSampler.cjs.js +1 -0
- package/renderers/webgpu/WebGPUSampler.js +12 -7
- package/renderers/webgpu/WebGPUStorageBuffer.cjs.js +1 -0
- package/renderers/webgpu/WebGPUStorageBuffer.js +12 -7
- package/renderers/webgpu/WebGPUTextureRenderer.cjs.js +1 -0
- package/renderers/webgpu/WebGPUTextureRenderer.js +11 -5
- package/renderers/webgpu/WebGPUTextureUtils.cjs.js +1 -0
- package/renderers/webgpu/WebGPUTextureUtils.js +40 -29
- package/renderers/webgpu/WebGPUTextures.cjs.js +1 -0
- package/renderers/webgpu/WebGPUTextures.js +333 -186
- package/renderers/webgpu/WebGPUUniform.cjs.js +1 -0
- package/renderers/webgpu/WebGPUUniform.js +51 -25
- package/renderers/webgpu/WebGPUUniformsGroup.cjs.js +1 -0
- package/renderers/webgpu/WebGPUUniformsGroup.js +72 -32
- package/renderers/webgpu/constants.cjs.js +1 -0
- package/renderers/webgpu/constants.js +181 -190
- package/renderers/webgpu/nodes/ShaderLib.cjs.js +1 -0
- package/renderers/webgpu/nodes/ShaderLib.js +2 -2
- package/renderers/webgpu/nodes/WebGPUNodeBuilder.cjs.js +1 -0
- package/renderers/webgpu/nodes/WebGPUNodeBuilder.js +124 -53
- package/renderers/webgpu/nodes/WebGPUNodeUniform.cjs.js +1 -0
- package/renderers/webgpu/nodes/WebGPUNodeUniform.js +31 -17
- package/renderers/webgpu/nodes/WebGPUNodeUniformsGroup.cjs.js +1 -0
- package/renderers/webgpu/nodes/WebGPUNodeUniformsGroup.js +9 -8
- package/renderers/webgpu/nodes/WebGPUNodes.cjs.js +1 -0
- package/renderers/webgpu/nodes/WebGPUNodes.js +45 -7
- package/shaders/ACESFilmicToneMappingShader.cjs.js +1 -0
- package/shaders/ACESFilmicToneMappingShader.js +24 -44
- package/shaders/AfterimageShader.cjs.js +1 -0
- package/shaders/AfterimageShader.js +18 -28
- package/shaders/BasicShader.cjs.js +1 -0
- package/shaders/BasicShader.js +7 -9
- package/shaders/BleachBypassShader.cjs.js +1 -0
- package/shaders/BleachBypassShader.js +15 -31
- package/shaders/BlendShader.cjs.js +1 -0
- package/shaders/BlendShader.js +19 -26
- package/shaders/BokehShader.cjs.js +1 -0
- package/shaders/BokehShader.js +36 -98
- package/shaders/BokehShader2.cjs.js +1 -0
- package/shaders/BokehShader2.js +90 -261
- package/shaders/BrightnessContrastShader.cjs.js +1 -0
- package/shaders/BrightnessContrastShader.js +19 -28
- package/shaders/ColorCorrectionShader.cjs.js +1 -0
- package/shaders/ColorCorrectionShader.js +22 -26
- package/shaders/ColorifyShader.cjs.js +1 -0
- package/shaders/ColorifyShader.js +16 -24
- package/shaders/ConvolutionShader.cjs.js +1 -0
- package/shaders/ConvolutionShader.js +36 -40
- package/shaders/CopyShader.cjs.js +1 -0
- package/shaders/CopyShader.js +13 -21
- package/shaders/DOFMipMapShader.cjs.js +1 -0
- package/shaders/DOFMipMapShader.js +21 -28
- package/shaders/DepthLimitedBlurShader.cjs.js +1 -0
- package/shaders/DepthLimitedBlurShader.js +40 -85
- package/shaders/DigitalGlitch.cjs.js +1 -0
- package/shaders/DigitalGlitch.js +46 -74
- package/shaders/DotScreenShader.cjs.js +1 -0
- package/shaders/DotScreenShader.js +27 -35
- package/shaders/FXAAShader.cjs.js +1 -0
- package/shaders/FXAAShader.js +19 -1094
- package/shaders/FilmShader.cjs.js +1 -0
- package/shaders/FilmShader.js +52 -38
- package/shaders/FocusShader.cjs.js +1 -0
- package/shaders/FocusShader.js +24 -51
- package/shaders/FreiChenShader.cjs.js +1 -0
- package/shaders/FreiChenShader.js +24 -57
- package/shaders/FresnelShader.cjs.js +1 -0
- package/shaders/FresnelShader.js +22 -43
- package/shaders/GammaCorrectionShader.cjs.js +1 -0
- package/shaders/GammaCorrectionShader.js +11 -19
- package/shaders/GodRaysShader.cjs.js +1 -0
- package/shaders/GodRaysShader.js +94 -103
- package/shaders/HalftoneShader.cjs.js +1 -0
- package/shaders/HalftoneShader.js +65 -208
- package/shaders/HorizontalBlurShader.cjs.js +1 -0
- package/shaders/HorizontalBlurShader.js +23 -7
- package/shaders/HorizontalTiltShiftShader.cjs.js +1 -0
- package/shaders/HorizontalTiltShiftShader.js +21 -33
- package/shaders/HueSaturationShader.cjs.js +1 -0
- package/shaders/HueSaturationShader.js +21 -37
- package/shaders/KaleidoShader.cjs.js +1 -0
- package/shaders/KaleidoShader.js +22 -30
- package/shaders/LuminosityHighPassShader.cjs.js +1 -0
- package/shaders/LuminosityHighPassShader.js +27 -33
- package/shaders/LuminosityShader.cjs.js +1 -0
- package/shaders/LuminosityShader.js +11 -21
- package/shaders/MirrorShader.cjs.js +1 -0
- package/shaders/MirrorShader.js +16 -31
- package/shaders/NormalMapShader.cjs.js +1 -0
- package/shaders/NormalMapShader.js +23 -27
- package/shaders/ParallaxShader.cjs.js +1 -0
- package/shaders/ParallaxShader.js +48 -107
- package/shaders/PixelShader.cjs.js +1 -0
- package/shaders/PixelShader.js +16 -24
- package/shaders/RGBShiftShader.cjs.js +1 -0
- package/shaders/RGBShiftShader.js +22 -26
- package/shaders/SAOShader.cjs.js +1 -0
- package/shaders/SAOShader.js +48 -132
- package/shaders/SMAAShader.cjs.js +1 -0
- package/shaders/SMAAShader.js +135 -256
- package/shaders/SSAOShader.cjs.js +1 -0
- package/shaders/SSAOShader.js +81 -153
- package/shaders/SSRShader.cjs.js +1 -0
- package/shaders/SSRShader.js +87 -32
- package/shaders/SepiaShader.cjs.js +1 -0
- package/shaders/SepiaShader.js +15 -25
- package/shaders/SobelOperatorShader.cjs.js +1 -0
- package/shaders/SobelOperatorShader.js +29 -40
- package/shaders/SubsurfaceScatteringShader.cjs.js +1 -0
- package/shaders/SubsurfaceScatteringShader.js +39 -53
- package/shaders/TechnicolorShader.cjs.js +1 -0
- package/shaders/TechnicolorShader.js +13 -20
- package/shaders/ToneMapShader.cjs.js +1 -0
- package/shaders/ToneMapShader.js +28 -44
- package/shaders/ToonShader.cjs.js +1 -0
- package/shaders/ToonShader.js +96 -172
- package/shaders/TriangleBlurShader.cjs.js +1 -0
- package/shaders/TriangleBlurShader.js +23 -32
- package/shaders/UnpackDepthRGBAShader.cjs.js +1 -0
- package/shaders/UnpackDepthRGBAShader.js +14 -22
- package/shaders/VerticalBlurShader.cjs.js +1 -0
- package/shaders/VerticalBlurShader.js +23 -7
- package/shaders/VerticalTiltShiftShader.cjs.js +1 -0
- package/shaders/VerticalTiltShiftShader.js +21 -33
- package/shaders/VignetteShader.cjs.js +1 -0
- package/shaders/VignetteShader.js +28 -24
- package/shaders/VolumeShader.cjs.js +1 -0
- package/shaders/VolumeShader.js +77 -174
- package/shaders/WaterRefractionShader.cjs.js +1 -0
- package/shaders/WaterRefractionShader.js +6 -38
- package/shaders/types.cjs.js +1 -0
- package/shaders/types.js +1 -1
- package/textures/FlakesTexture.cjs.js +1 -0
- package/textures/FlakesTexture.js +10 -8
- package/types/helpers.cjs.js +1 -0
- package/types/helpers.js +2 -3
- package/types/shared.cjs.js +1 -0
- package/types/shared.js +1 -0
- package/types/utils.cjs.js +1 -0
- package/types/utils.js +1 -0
- package/utils/BufferGeometryUtils.cjs.js +1 -0
- package/utils/BufferGeometryUtils.js +325 -251
- package/utils/GeometryCompressionUtils.cjs.js +1 -0
- package/utils/GeometryCompressionUtils.js +239 -241
- package/utils/GeometryUtils.cjs.js +1 -0
- package/utils/GeometryUtils.js +94 -41
- package/utils/LDrawUtils.cjs.js +1 -0
- package/utils/LDrawUtils.d.ts +5 -0
- package/utils/LDrawUtils.js +144 -0
- package/utils/RoughnessMipmapper.cjs.js +1 -0
- package/utils/RoughnessMipmapper.js +82 -38
- package/utils/SceneUtils.cjs.js +1 -0
- package/utils/SceneUtils.js +20 -15
- package/utils/ShadowMapViewer.cjs.js +1 -0
- package/utils/ShadowMapViewer.js +95 -49
- package/utils/SkeletonUtils.cjs.js +1 -0
- package/utils/SkeletonUtils.js +165 -74
- package/utils/UVsDebug.cjs.js +1 -0
- package/utils/UVsDebug.js +62 -32
- package/utils/WorkerPool.cjs.js +1 -0
- package/utils/WorkerPool.js +33 -13
- package/webxr/ARButton.cjs.js +1 -0
- package/webxr/ARButton.js +98 -72
- package/webxr/OculusHandModel.cjs.js +1 -0
- package/webxr/OculusHandModel.js +37 -18
- package/webxr/OculusHandPointerModel.cjs.js +1 -0
- package/webxr/OculusHandPointerModel.js +80 -58
- package/webxr/Text2D.cjs.js +1 -0
- package/webxr/Text2D.js +19 -37
- package/webxr/VRButton.cjs.js +1 -0
- package/webxr/VRButton.js +90 -59
- package/webxr/XRControllerModelFactory.cjs.js +1 -0
- package/webxr/XRControllerModelFactory.js +116 -58
- package/webxr/XREstimatedLight.cjs.js +1 -0
- package/webxr/XREstimatedLight.js +66 -39
- package/webxr/XRHandMeshModel.cjs.js +1 -0
- package/webxr/XRHandMeshModel.js +29 -40
- package/webxr/XRHandModelFactory.cjs.js +1 -0
- package/webxr/XRHandModelFactory.js +31 -28
- package/webxr/XRHandPrimitiveModel.cjs.js +1 -0
- package/webxr/XRHandPrimitiveModel.js +27 -41
- package/animation/AnimationClipCreator.mjs +0 -57
- package/animation/CCDIKSolver.mjs +0 -223
- package/animation/MMDAnimationHelper.mjs +0 -514
- package/animation/MMDPhysics.mjs +0 -769
- package/cameras/CinematicCamera.mjs +0 -129
- package/controls/ArcballControls.mjs +0 -1737
- package/controls/DeviceOrientationControls.mjs +0 -74
- package/controls/DragControls.mjs +0 -172
- package/controls/FirstPersonControls.mjs +0 -220
- package/controls/FlyControls.mjs +0 -239
- package/controls/OrbitControls.mjs +0 -731
- package/controls/PointerLockControls.mjs +0 -88
- package/controls/TrackballControls.mjs +0 -481
- package/controls/TransformControls.mjs +0 -1068
- package/controls/experimental/CameraControls.mjs +0 -673
- package/csm/CSM.mjs +0 -244
- package/csm/CSMFrustum.mjs +0 -75
- package/csm/CSMHelper.mjs +0 -114
- package/csm/CSMShader.mjs +0 -251
- package/curves/CurveExtras.mjs +0 -224
- package/curves/NURBSCurve.mjs +0 -35
- package/curves/NURBSSurface.mjs +0 -28
- package/curves/NURBSUtils.mjs +0 -226
- package/deprecated/Geometry.mjs +0 -966
- package/effects/AnaglyphEffect.mjs +0 -120
- package/effects/AsciiEffect.mjs +0 -173
- package/effects/OutlineEffect.mjs +0 -295
- package/effects/ParallaxBarrierEffect.mjs +0 -64
- package/effects/PeppersGhostEffect.mjs +0 -85
- package/effects/StereoEffect.mjs +0 -32
- package/environments/RoomEnvironment.mjs +0 -78
- package/exporters/ColladaExporter.mjs +0 -299
- package/exporters/DRACOExporter.mjs +0 -132
- package/exporters/GLTFExporter.mjs +0 -1381
- package/exporters/MMDExporter.mjs +0 -102
- package/exporters/OBJExporter.mjs +0 -166
- package/exporters/PLYExporter.mjs +0 -278
- package/exporters/STLExporter.mjs +0 -129
- package/exporters/USDZExporter.mjs +0 -328
- package/geometries/BoxLineGeometry.mjs +0 -45
- package/geometries/ConvexGeometry.mjs +0 -29
- package/geometries/DecalGeometry.mjs +0 -184
- package/geometries/LightningStrike.mjs +0 -547
- package/geometries/ParametricGeometries.mjs +0 -129
- package/geometries/ParametricGeometry.mjs +0 -63
- package/geometries/RoundedBoxGeometry.mjs +0 -91
- package/geometries/TeapotGeometry.mjs +0 -1557
- package/geometries/TextGeometry.mjs +0 -23
- package/helpers/LightProbeHelper.mjs +0 -72
- package/helpers/PositionalAudioHelper.mjs +0 -68
- package/helpers/RectAreaLightHelper.mjs +0 -44
- package/helpers/VertexNormalsHelper.mjs +0 -54
- package/helpers/VertexTangentsHelper.mjs +0 -45
- package/index.mjs +0 -969
- package/interactive/SelectionBox.mjs +0 -137
- package/interactive/SelectionHelper.mjs +0 -54
- package/libs/MeshoptDecoder.mjs +0 -210
- package/libs/MotionControllers.mjs +0 -261
- package/lights/LightProbeGenerator.mjs +0 -145
- package/lights/RectAreaLightUniformsLib.mjs +0 -32842
- package/lines/Line2.mjs +0 -13
- package/lines/LineGeometry.mjs +0 -44
- package/lines/LineMaterial.mjs +0 -539
- package/lines/LineSegments2.mjs +0 -202
- package/lines/LineSegmentsGeometry.mjs +0 -124
- package/lines/Wireframe.mjs +0 -31
- package/lines/WireframeGeometry2.mjs +0 -13
- package/loaders/3DMLoader.mjs +0 -802
- package/loaders/3MFLoader.mjs +0 -837
- package/loaders/AMFLoader.mjs +0 -284
- package/loaders/AssimpLoader.mjs +0 -1396
- package/loaders/BVHLoader.mjs +0 -207
- package/loaders/BasisTextureLoader.mjs +0 -474
- package/loaders/ColladaLoader.mjs +0 -2403
- package/loaders/DDSLoader.mjs +0 -148
- package/loaders/DRACOLoader.mjs +0 -340
- package/loaders/EXRLoader.mjs +0 -1351
- package/loaders/FBXLoader.mjs +0 -2362
- package/loaders/FontLoader.mjs +0 -111
- package/loaders/GCodeLoader.mjs +0 -141
- package/loaders/GLTFLoader.mjs +0 -2316
- package/loaders/HDRCubeTextureLoader.mjs +0 -77
- package/loaders/KMZLoader.mjs +0 -75
- package/loaders/KTX2Loader.mjs +0 -427
- package/loaders/KTXLoader.mjs +0 -87
- package/loaders/LDrawLoader.mjs +0 -1409
- package/loaders/LUT3dlLoader.mjs +0 -100
- package/loaders/LUTCubeLoader.mjs +0 -104
- package/loaders/LWOLoader.mjs +0 -625
- package/loaders/LottieLoader.mjs +0 -47
- package/loaders/MD2Loader.mjs +0 -359
- package/loaders/MDDLoader.mjs +0 -58
- package/loaders/MMDLoader.mjs +0 -998
- package/loaders/MTLLoader.mjs +0 -280
- package/loaders/NRRDLoader.mjs +0 -401
- package/loaders/NodeMaterialLoader.mjs +0 -146
- package/loaders/OBJLoader.mjs +0 -487
- package/loaders/PCDLoader.mjs +0 -248
- package/loaders/PDBLoader.mjs +0 -246
- package/loaders/PLYLoader.mjs +0 -317
- package/loaders/PRWMLoader.mjs +0 -160
- package/loaders/PVRLoader.mjs +0 -131
- package/loaders/RGBELoader.mjs +0 -244
- package/loaders/RGBMLoader.mjs +0 -998
- package/loaders/STLLoader.mjs +0 -190
- package/loaders/SVGLoader.mjs +0 -1709
- package/loaders/TDSLoader.mjs +0 -480
- package/loaders/TGALoader.mjs +0 -285
- package/loaders/TTFLoader.mjs +0 -131
- package/loaders/TiltLoader.mjs +0 -373
- package/loaders/VOXLoader.mjs +0 -431
- package/loaders/VRMLLoader.mjs +0 -2093
- package/loaders/VRMLoader.mjs +0 -38
- package/loaders/VTKLoader.mjs +0 -646
- package/loaders/XLoader.mjs +0 -1258
- package/loaders/XYZLoader.mjs +0 -60
- package/loaders/lwo/IFFParser.mjs +0 -697
- package/loaders/lwo/LWO2Parser.mjs +0 -327
- package/loaders/lwo/LWO3Parser.mjs +0 -298
- package/math/Capsule.mjs +0 -100
- package/math/ColorConverter.mjs +0 -51
- package/math/ConvexHull.mjs +0 -574
- package/math/ImprovedNoise.mjs +0 -302
- package/math/Lut.mjs +0 -135
- package/math/MeshSurfaceSampler.mjs +0 -107
- package/math/OBB.mjs +0 -235
- package/math/Octree.mjs +0 -278
- package/math/SimplexNoise.mjs +0 -425
- package/misc/ConvexObjectBreaker.mjs +0 -292
- package/misc/GPUComputationRenderer.mjs +0 -171
- package/misc/Gyroscope.mjs +0 -35
- package/misc/MD2Character.mjs +0 -162
- package/misc/MD2CharacterComplex.mjs +0 -328
- package/misc/MorphAnimMesh.mjs +0 -40
- package/misc/MorphBlendMesh.mjs +0 -179
- package/misc/ProgressiveLightmap.mjs +0 -166
- package/misc/RollerCoaster.mjs +0 -346
- package/misc/TubePainter.mjs +0 -123
- package/misc/Volume.mjs +0 -244
- package/misc/VolumeSlice.mjs +0 -106
- package/misc/WebGL.mjs +0 -74
- package/modifiers/CurveModifier.mjs +0 -182
- package/modifiers/EdgeSplitModifier.mjs +0 -162
- package/modifiers/SimplifyModifier.mjs +0 -282
- package/modifiers/TessellateModifier.mjs +0 -206
- package/nodes/Nodes.mjs +0 -400
- package/nodes/ShaderNode.mjs +0 -408
- package/nodes/accessors/BufferNode.mjs +0 -15
- package/nodes/accessors/CameraNode.mjs +0 -44
- package/nodes/accessors/CubeTextureNode.mjs +0 -42
- package/nodes/accessors/MaterialNode.mjs +0 -71
- package/nodes/accessors/MaterialReferenceNode.mjs +0 -14
- package/nodes/accessors/ModelNode.mjs +0 -9
- package/nodes/accessors/ModelViewProjectionNode.mjs +0 -24
- package/nodes/accessors/NormalNode.mjs +0 -62
- package/nodes/accessors/Object3DNode.mjs +0 -76
- package/nodes/accessors/PointUVNode.mjs +0 -13
- package/nodes/accessors/PositionNode.mjs +0 -65
- package/nodes/accessors/ReferenceNode.mjs +0 -37
- package/nodes/accessors/ReflectNode.mjs +0 -43
- package/nodes/accessors/SkinningNode.mjs +0 -58
- package/nodes/accessors/TextureNode.mjs +0 -54
- package/nodes/accessors/UVNode.mjs +0 -23
- package/nodes/core/ArrayUniformNode.mjs +0 -14
- package/nodes/core/AttributeNode.mjs +0 -30
- package/nodes/core/BypassNode.mjs +0 -22
- package/nodes/core/CodeNode.mjs +0 -28
- package/nodes/core/ConstNode.mjs +0 -14
- package/nodes/core/ContextNode.mjs +0 -22
- package/nodes/core/ExpressionNode.mjs +0 -19
- package/nodes/core/FunctionCallNode.mjs +0 -37
- package/nodes/core/FunctionNode.mjs +0 -56
- package/nodes/core/InputNode.mjs +0 -38
- package/nodes/core/Node.mjs +0 -139
- package/nodes/core/NodeAttribute.mjs +0 -10
- package/nodes/core/NodeBuilder.mjs +0 -395
- package/nodes/core/NodeCode.mjs +0 -11
- package/nodes/core/NodeFrame.mjs +0 -35
- package/nodes/core/NodeFunctionInput.mjs +0 -13
- package/nodes/core/NodeKeywords.mjs +0 -44
- package/nodes/core/NodeUniform.mjs +0 -18
- package/nodes/core/NodeUtils.mjs +0 -57
- package/nodes/core/NodeVar.mjs +0 -10
- package/nodes/core/NodeVary.mjs +0 -10
- package/nodes/core/PropertyNode.mjs +0 -21
- package/nodes/core/TempNode.mjs +0 -25
- package/nodes/core/UniformNode.mjs +0 -23
- package/nodes/core/VarNode.mjs +0 -31
- package/nodes/core/VaryNode.mjs +0 -30
- package/nodes/core/constants.mjs +0 -24
- package/nodes/display/ColorSpaceNode.mjs +0 -63
- package/nodes/display/NormalMapNode.mjs +0 -54
- package/nodes/fog/FogNode.mjs +0 -15
- package/nodes/fog/FogRangeNode.mjs +0 -17
- package/nodes/functions/BSDFs.mjs +0 -64
- package/nodes/lights/LightContextNode.mjs +0 -35
- package/nodes/lights/LightNode.mjs +0 -58
- package/nodes/lights/LightsNode.mjs +0 -59
- package/nodes/loaders/NodeLoader.mjs +0 -66
- package/nodes/loaders/NodeMaterialLoader.mjs +0 -24
- package/nodes/loaders/NodeObjectLoader.mjs +0 -40
- package/nodes/materials/LineBasicNodeMaterial.mjs +0 -27
- package/nodes/materials/Materials.mjs +0 -28
- package/nodes/materials/MeshBasicNodeMaterial.mjs +0 -28
- package/nodes/materials/MeshStandardNodeMaterial.mjs +0 -41
- package/nodes/materials/NodeMaterial.mjs +0 -64
- package/nodes/materials/PointsNodeMaterial.mjs +0 -30
- package/nodes/math/CondNode.mjs +0 -38
- package/nodes/math/MathNode.mjs +0 -163
- package/nodes/math/OperatorNode.mjs +0 -103
- package/nodes/procedural/CheckerNode.mjs +0 -21
- package/nodes/utils/ArrayElementNode.mjs +0 -19
- package/nodes/utils/ConvertNode.mjs +0 -25
- package/nodes/utils/JoinNode.mjs +0 -26
- package/nodes/utils/MatcapUVNode.mjs +0 -16
- package/nodes/utils/OscNode.mjs +0 -50
- package/nodes/utils/SplitNode.mjs +0 -45
- package/nodes/utils/SpriteSheetUVNode.mjs +0 -40
- package/nodes/utils/TimerNode.mjs +0 -44
- package/objects/GroundProjectedEnv.mjs +0 -130
- package/objects/Lensflare.mjs +0 -262
- package/objects/LightningStorm.mjs +0 -110
- package/objects/MarchingCubes.mjs +0 -457
- package/objects/Reflector.mjs +0 -166
- package/objects/ReflectorForSSRPass.mjs +0 -247
- package/objects/ReflectorRTT.mjs +0 -10
- package/objects/Refractor.mjs +0 -178
- package/objects/ShadowMesh.mjs +0 -41
- package/objects/Sky.mjs +0 -124
- package/objects/Water.mjs +0 -235
- package/objects/Water2.mjs +0 -252
- package/offscreen/jank.mjs +0 -27
- package/offscreen/offscreen.mjs +0 -5
- package/offscreen/scene.mjs +0 -52
- package/physics/AmmoPhysics.mjs +0 -165
- package/postprocessing/AdaptiveToneMappingPass.mjs +0 -221
- package/postprocessing/AfterimagePass.mjs +0 -55
- package/postprocessing/BloomPass.mjs +0 -90
- package/postprocessing/BokehPass.mjs +0 -76
- package/postprocessing/ClearPass.mjs +0 -27
- package/postprocessing/CubeTexturePass.mjs +0 -49
- package/postprocessing/DotScreenPass.mjs +0 -40
- package/postprocessing/EffectComposer.mjs +0 -139
- package/postprocessing/FilmPass.mjs +0 -42
- package/postprocessing/GlitchPass.mjs +0 -75
- package/postprocessing/HalftonePass.mjs +0 -44
- package/postprocessing/LUTPass.mjs +0 -136
- package/postprocessing/MaskPass.mjs +0 -60
- package/postprocessing/OutlinePass.mjs +0 -438
- package/postprocessing/Pass.mjs +0 -37
- package/postprocessing/RenderPass.mjs +0 -48
- package/postprocessing/RenderPixelatedPass.mjs +0 -199
- package/postprocessing/SAOPass.mjs +0 -282
- package/postprocessing/SMAAPass.mjs +0 -112
- package/postprocessing/SSAARenderPass.mjs +0 -170
- package/postprocessing/SSAOPass.mjs +0 -265
- package/postprocessing/SSRPass.mjs +0 -432
- package/postprocessing/SavePass.mjs +0 -37
- package/postprocessing/ShaderPass.mjs +0 -39
- package/postprocessing/TAARenderPass.mjs +0 -88
- package/postprocessing/TexturePass.mjs +0 -39
- package/postprocessing/UnrealBloomPass.mjs +0 -220
- package/renderers/CSS2DRenderer.mjs +0 -112
- package/renderers/CSS3DRenderer.mjs +0 -133
- package/renderers/Projector.mjs +0 -511
- package/renderers/SVGRenderer.mjs +0 -306
- package/renderers/nodes/accessors/CameraNode.mjs +0 -63
- package/renderers/nodes/accessors/ModelNode.mjs +0 -61
- package/renderers/nodes/accessors/ModelViewProjectionNode.mjs +0 -21
- package/renderers/nodes/accessors/NormalNode.mjs +0 -61
- package/renderers/nodes/accessors/PositionNode.mjs +0 -30
- package/renderers/nodes/accessors/UVNode.mjs +0 -13
- package/renderers/nodes/core/AttributeNode.mjs +0 -35
- package/renderers/nodes/core/InputNode.mjs +0 -31
- package/renderers/nodes/core/Node.mjs +0 -34
- package/renderers/nodes/core/NodeAttribute.mjs +0 -10
- package/renderers/nodes/core/NodeBuilder.mjs +0 -243
- package/renderers/nodes/core/NodeFrame.mjs +0 -35
- package/renderers/nodes/core/NodeSlot.mjs +0 -10
- package/renderers/nodes/core/NodeUniform.mjs +0 -18
- package/renderers/nodes/core/NodeVary.mjs +0 -11
- package/renderers/nodes/core/VaryNode.mjs +0 -22
- package/renderers/nodes/core/constants.mjs +0 -22
- package/renderers/nodes/inputs/ColorNode.mjs +0 -11
- package/renderers/nodes/inputs/FloatNode.mjs +0 -11
- package/renderers/nodes/inputs/Matrix3Node.mjs +0 -12
- package/renderers/nodes/inputs/Matrix4Node.mjs +0 -12
- package/renderers/nodes/inputs/TextureNode.mjs +0 -20
- package/renderers/nodes/inputs/Vector2Node.mjs +0 -11
- package/renderers/nodes/inputs/Vector3Node.mjs +0 -12
- package/renderers/nodes/inputs/Vector4Node.mjs +0 -12
- package/renderers/nodes/math/MathNode.mjs +0 -55
- package/renderers/nodes/math/OperatorNode.mjs +0 -42
- package/renderers/nodes/utils/SwitchNode.mjs +0 -20
- package/renderers/nodes/utils/TimerNode.mjs +0 -14
- package/renderers/webgpu/WebGPU.mjs +0 -24
- package/renderers/webgpu/WebGPUAttributes.mjs +0 -69
- package/renderers/webgpu/WebGPUBackground.mjs +0 -61
- package/renderers/webgpu/WebGPUBinding.mjs +0 -14
- package/renderers/webgpu/WebGPUBindings.mjs +0 -155
- package/renderers/webgpu/WebGPUComputePipelines.mjs +0 -44
- package/renderers/webgpu/WebGPUGeometries.mjs +0 -41
- package/renderers/webgpu/WebGPUInfo.mjs +0 -46
- package/renderers/webgpu/WebGPUObjects.mjs +0 -25
- package/renderers/webgpu/WebGPUProperties.mjs +0 -22
- package/renderers/webgpu/WebGPURenderLists.mjs +0 -119
- package/renderers/webgpu/WebGPURenderPipelines.mjs +0 -545
- package/renderers/webgpu/WebGPURenderer.mjs +0 -574
- package/renderers/webgpu/WebGPUSampledTexture.mjs +0 -40
- package/renderers/webgpu/WebGPUSampler.mjs +0 -15
- package/renderers/webgpu/WebGPUStorageBuffer.mjs +0 -15
- package/renderers/webgpu/WebGPUTextureRenderer.mjs +0 -23
- package/renderers/webgpu/WebGPUTextureUtils.mjs +0 -98
- package/renderers/webgpu/WebGPUTextures.mjs +0 -484
- package/renderers/webgpu/WebGPUUniform.mjs +0 -81
- package/renderers/webgpu/WebGPUUniformsGroup.mjs +0 -176
- package/renderers/webgpu/constants.mjs +0 -230
- package/renderers/webgpu/nodes/ShaderLib.mjs +0 -42
- package/renderers/webgpu/nodes/WebGPUNodeBuilder.mjs +0 -165
- package/renderers/webgpu/nodes/WebGPUNodeUniform.mjs +0 -73
- package/renderers/webgpu/nodes/WebGPUNodeUniformsGroup.mjs +0 -15
- package/renderers/webgpu/nodes/WebGPUNodes.mjs +0 -40
- package/shaders/ACESFilmicToneMappingShader.mjs +0 -48
- package/shaders/AfterimageShader.mjs +0 -32
- package/shaders/BasicShader.mjs +0 -12
- package/shaders/BleachBypassShader.mjs +0 -35
- package/shaders/BlendShader.mjs +0 -30
- package/shaders/BokehShader.mjs +0 -106
- package/shaders/BokehShader2.mjs +0 -269
- package/shaders/BrightnessContrastShader.mjs +0 -32
- package/shaders/ColorCorrectionShader.mjs +0 -30
- package/shaders/ColorifyShader.mjs +0 -28
- package/shaders/ConvolutionShader.mjs +0 -55
- package/shaders/CopyShader.mjs +0 -25
- package/shaders/DOFMipMapShader.mjs +0 -32
- package/shaders/DepthLimitedBlurShader.mjs +0 -114
- package/shaders/DigitalGlitch.mjs +0 -78
- package/shaders/DotScreenShader.mjs +0 -39
- package/shaders/FXAAShader.mjs +0 -1098
- package/shaders/FilmShader.mjs +0 -42
- package/shaders/FocusShader.mjs +0 -55
- package/shaders/FreiChenShader.mjs +0 -61
- package/shaders/FresnelShader.mjs +0 -47
- package/shaders/GammaCorrectionShader.mjs +0 -23
- package/shaders/GodRaysShader.mjs +0 -146
- package/shaders/HalftoneShader.mjs +0 -212
- package/shaders/HorizontalBlurShader.mjs +0 -43
- package/shaders/HorizontalTiltShiftShader.mjs +0 -37
- package/shaders/HueSaturationShader.mjs +0 -41
- package/shaders/KaleidoShader.mjs +0 -34
- package/shaders/LuminosityHighPassShader.mjs +0 -37
- package/shaders/LuminosityShader.mjs +0 -25
- package/shaders/MirrorShader.mjs +0 -35
- package/shaders/NormalMapShader.mjs +0 -31
- package/shaders/ParallaxShader.mjs +0 -113
- package/shaders/PixelShader.mjs +0 -28
- package/shaders/RGBShiftShader.mjs +0 -30
- package/shaders/SAOShader.mjs +0 -144
- package/shaders/SMAAShader.mjs +0 -272
- package/shaders/SSAOShader.mjs +0 -172
- package/shaders/SSRShader.mjs +0 -324
- package/shaders/SepiaShader.mjs +0 -29
- package/shaders/SobelOperatorShader.mjs +0 -44
- package/shaders/SubsurfaceScatteringShader.mjs +0 -59
- package/shaders/TechnicolorShader.mjs +0 -24
- package/shaders/ToneMapShader.mjs +0 -48
- package/shaders/ToonShader.mjs +0 -188
- package/shaders/TriangleBlurShader.mjs +0 -36
- package/shaders/UnpackDepthRGBAShader.mjs +0 -26
- package/shaders/VerticalBlurShader.mjs +0 -44
- package/shaders/VerticalTiltShiftShader.mjs +0 -37
- package/shaders/VignetteShader.mjs +0 -28
- package/shaders/VolumeShader.mjs +0 -178
- package/shaders/WaterRefractionShader.mjs +0 -57
- package/textures/FlakesTexture.mjs +0 -30
- package/types/helpers.mjs +0 -4
- package/utils/BufferGeometryUtils.mjs +0 -570
- package/utils/GeometryCompressionUtils.mjs +0 -547
- package/utils/GeometryUtils.mjs +0 -108
- package/utils/RoughnessMipmapper.mjs +0 -213
- package/utils/SceneUtils.mjs +0 -36
- package/utils/ShadowMapViewer.mjs +0 -114
- package/utils/SkeletonUtils.mjs +0 -292
- package/utils/UVsDebug.mjs +0 -85
- package/utils/WorkerPool.mjs +0 -62
- package/webxr/ARButton.mjs +0 -119
- package/webxr/OculusHandModel.mjs +0 -71
- package/webxr/OculusHandPointerModel.mjs +0 -207
- package/webxr/Text2D.mjs +0 -31
- package/webxr/VRButton.mjs +0 -105
- package/webxr/XRControllerModelFactory.mjs +0 -146
- package/webxr/XREstimatedLight.mjs +0 -126
- package/webxr/XRHandMeshModel.mjs +0 -73
- package/webxr/XRHandModelFactory.mjs +0 -61
- package/webxr/XRHandPrimitiveModel.mjs +0 -68
package/loaders/FBXLoader.js
CHANGED
|
@@ -1,63 +1,85 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { Loader, LoaderUtils, FileLoader, TextureLoader, RepeatWrapping, ClampToEdgeWrapping, Texture, MeshPhongMaterial, MeshLambertMaterial, Color, sRGBEncoding, EquirectangularReflectionMapping, Matrix4, Group, Bone, PropertyBinding, Object3D, OrthographicCamera, PerspectiveCamera, PointLight, MathUtils, SpotLight, DirectionalLight, SkinnedMesh, Mesh, LineBasicMaterial, Line, Vector3, Skeleton, AmbientLight, BufferGeometry, Float32BufferAttribute, Uint16BufferAttribute, Matrix3, Vector4, AnimationClip, Quaternion, Euler, VectorKeyframeTrack, QuaternionKeyframeTrack, NumberKeyframeTrack } from 'three';
|
|
2
|
+
import { unzlibSync } from 'fflate';
|
|
3
|
+
import { NURBSCurve } from '../curves/NURBSCurve.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Loader loads FBX file and generates Group representing FBX scene.
|
|
7
|
+
* Requires FBX file to be >= 7.0 and in ASCII or >= 6400 in Binary format
|
|
8
|
+
* Versions lower than this may load but will probably have errors
|
|
9
|
+
*
|
|
10
|
+
* Needs Support:
|
|
11
|
+
* Morph normals / blend shape normals
|
|
12
|
+
*
|
|
13
|
+
* FBX format references:
|
|
14
|
+
* https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference)
|
|
15
|
+
*
|
|
16
|
+
* Binary format specification:
|
|
17
|
+
* https://code.blender.org/2013/08/fbx-binary-file-format-specification/
|
|
18
|
+
*/
|
|
19
|
+
|
|
6
20
|
let fbxTree;
|
|
7
21
|
let connections;
|
|
8
22
|
let sceneGraph;
|
|
9
|
-
|
|
23
|
+
|
|
24
|
+
class FBXLoader extends Loader {
|
|
10
25
|
constructor(manager) {
|
|
11
26
|
super(manager);
|
|
12
27
|
}
|
|
28
|
+
|
|
13
29
|
load(url, onLoad, onProgress, onError) {
|
|
14
30
|
const scope = this;
|
|
15
|
-
const path = scope.path ===
|
|
16
|
-
const loader = new
|
|
31
|
+
const path = scope.path === '' ? LoaderUtils.extractUrlBase(url) : scope.path;
|
|
32
|
+
const loader = new FileLoader(this.manager);
|
|
17
33
|
loader.setPath(scope.path);
|
|
18
|
-
loader.setResponseType(
|
|
34
|
+
loader.setResponseType('arraybuffer');
|
|
19
35
|
loader.setRequestHeader(scope.requestHeader);
|
|
20
36
|
loader.setWithCredentials(scope.withCredentials);
|
|
21
|
-
loader.load(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} else {
|
|
30
|
-
console.error(e);
|
|
31
|
-
}
|
|
32
|
-
scope.manager.itemError(url);
|
|
37
|
+
loader.load(url, function (buffer) {
|
|
38
|
+
try {
|
|
39
|
+
onLoad(scope.parse(buffer, path));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
if (onError) {
|
|
42
|
+
onError(e);
|
|
43
|
+
} else {
|
|
44
|
+
console.error(e);
|
|
33
45
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
);
|
|
46
|
+
|
|
47
|
+
scope.manager.itemError(url);
|
|
48
|
+
}
|
|
49
|
+
}, onProgress, onError);
|
|
38
50
|
}
|
|
51
|
+
|
|
39
52
|
parse(FBXBuffer, path) {
|
|
40
53
|
if (isFbxFormatBinary(FBXBuffer)) {
|
|
41
54
|
fbxTree = new BinaryParser().parse(FBXBuffer);
|
|
42
55
|
} else {
|
|
43
56
|
const FBXText = convertArrayBufferToString(FBXBuffer);
|
|
57
|
+
|
|
44
58
|
if (!isFbxFormatASCII(FBXText)) {
|
|
45
|
-
throw new Error(
|
|
59
|
+
throw new Error('THREE.FBXLoader: Unknown format.');
|
|
46
60
|
}
|
|
47
|
-
|
|
48
|
-
|
|
61
|
+
|
|
62
|
+
if (getFbxVersion(FBXText) < 7000) {
|
|
63
|
+
throw new Error('THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion(FBXText));
|
|
49
64
|
}
|
|
65
|
+
|
|
50
66
|
fbxTree = new TextParser().parse(FBXText);
|
|
51
|
-
}
|
|
52
|
-
|
|
67
|
+
} // console.log( fbxTree );
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
const textureLoader = new TextureLoader(this.manager).setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin);
|
|
53
71
|
return new FBXTreeParser(textureLoader, this.manager).parse(fbxTree);
|
|
54
72
|
}
|
|
55
|
-
|
|
73
|
+
|
|
74
|
+
} // Parse the FBXTree object returned by the BinaryParser or TextParser and return a Group
|
|
75
|
+
|
|
76
|
+
|
|
56
77
|
class FBXTreeParser {
|
|
57
78
|
constructor(textureLoader, manager) {
|
|
58
79
|
this.textureLoader = textureLoader;
|
|
59
80
|
this.manager = manager;
|
|
60
81
|
}
|
|
82
|
+
|
|
61
83
|
parse() {
|
|
62
84
|
connections = this.parseConnections();
|
|
63
85
|
const images = this.parseImages();
|
|
@@ -67,47 +89,70 @@ class FBXTreeParser {
|
|
|
67
89
|
const geometryMap = new GeometryParser().parse(deformers);
|
|
68
90
|
this.parseScene(deformers, geometryMap, materials);
|
|
69
91
|
return sceneGraph;
|
|
70
|
-
}
|
|
92
|
+
} // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry )
|
|
93
|
+
// and details the connection type
|
|
94
|
+
|
|
95
|
+
|
|
71
96
|
parseConnections() {
|
|
72
|
-
const connectionMap =
|
|
73
|
-
|
|
97
|
+
const connectionMap = new Map();
|
|
98
|
+
|
|
99
|
+
if ('Connections' in fbxTree) {
|
|
74
100
|
const rawConnections = fbxTree.Connections.connections;
|
|
75
|
-
rawConnections.forEach(function(rawConnection) {
|
|
101
|
+
rawConnections.forEach(function (rawConnection) {
|
|
76
102
|
const fromID = rawConnection[0];
|
|
77
103
|
const toID = rawConnection[1];
|
|
78
104
|
const relationship = rawConnection[2];
|
|
105
|
+
|
|
79
106
|
if (!connectionMap.has(fromID)) {
|
|
80
107
|
connectionMap.set(fromID, {
|
|
81
108
|
parents: [],
|
|
82
109
|
children: []
|
|
83
110
|
});
|
|
84
111
|
}
|
|
85
|
-
|
|
112
|
+
|
|
113
|
+
const parentRelationship = {
|
|
114
|
+
ID: toID,
|
|
115
|
+
relationship: relationship
|
|
116
|
+
};
|
|
86
117
|
connectionMap.get(fromID).parents.push(parentRelationship);
|
|
118
|
+
|
|
87
119
|
if (!connectionMap.has(toID)) {
|
|
88
120
|
connectionMap.set(toID, {
|
|
89
121
|
parents: [],
|
|
90
122
|
children: []
|
|
91
123
|
});
|
|
92
124
|
}
|
|
93
|
-
|
|
125
|
+
|
|
126
|
+
const childRelationship = {
|
|
127
|
+
ID: fromID,
|
|
128
|
+
relationship: relationship
|
|
129
|
+
};
|
|
94
130
|
connectionMap.get(toID).children.push(childRelationship);
|
|
95
131
|
});
|
|
96
132
|
}
|
|
133
|
+
|
|
97
134
|
return connectionMap;
|
|
98
|
-
}
|
|
135
|
+
} // Parse FBXTree.Objects.Video for embedded image data
|
|
136
|
+
// These images are connected to textures in FBXTree.Objects.Textures
|
|
137
|
+
// via FBXTree.Connections.
|
|
138
|
+
|
|
139
|
+
|
|
99
140
|
parseImages() {
|
|
100
141
|
const images = {};
|
|
101
142
|
const blobs = {};
|
|
102
|
-
|
|
143
|
+
|
|
144
|
+
if ('Video' in fbxTree.Objects) {
|
|
103
145
|
const videoNodes = fbxTree.Objects.Video;
|
|
146
|
+
|
|
104
147
|
for (const nodeID in videoNodes) {
|
|
105
148
|
const videoNode = videoNodes[nodeID];
|
|
106
149
|
const id = parseInt(nodeID);
|
|
107
|
-
images[id] = videoNode.RelativeFilename || videoNode.Filename;
|
|
108
|
-
|
|
150
|
+
images[id] = videoNode.RelativeFilename || videoNode.Filename; // raw image data is in videoNode.Content
|
|
151
|
+
|
|
152
|
+
if ('Content' in videoNode) {
|
|
109
153
|
const arrayBufferContent = videoNode.Content instanceof ArrayBuffer && videoNode.Content.byteLength > 0;
|
|
110
|
-
const base64Content = typeof videoNode.Content ===
|
|
154
|
+
const base64Content = typeof videoNode.Content === 'string' && videoNode.Content !== '';
|
|
155
|
+
|
|
111
156
|
if (arrayBufferContent || base64Content) {
|
|
112
157
|
const image = this.parseImage(videoNodes[nodeID]);
|
|
113
158
|
blobs[videoNode.RelativeFilename || videoNode.Filename] = image;
|
|
@@ -115,314 +160,423 @@ class FBXTreeParser {
|
|
|
115
160
|
}
|
|
116
161
|
}
|
|
117
162
|
}
|
|
163
|
+
|
|
118
164
|
for (const id in images) {
|
|
119
165
|
const filename = images[id];
|
|
120
|
-
if (blobs[filename] !==
|
|
121
|
-
images[id] = blobs[filename];
|
|
122
|
-
else
|
|
123
|
-
images[id] = images[id].split("\\").pop();
|
|
166
|
+
if (blobs[filename] !== undefined) images[id] = blobs[filename];else images[id] = images[id].split('\\').pop();
|
|
124
167
|
}
|
|
168
|
+
|
|
125
169
|
return images;
|
|
126
|
-
}
|
|
170
|
+
} // Parse embedded image data in FBXTree.Video.Content
|
|
171
|
+
|
|
172
|
+
|
|
127
173
|
parseImage(videoNode) {
|
|
128
174
|
const content = videoNode.Content;
|
|
129
175
|
const fileName = videoNode.RelativeFilename || videoNode.Filename;
|
|
130
|
-
const extension = fileName.slice(fileName.lastIndexOf(
|
|
176
|
+
const extension = fileName.slice(fileName.lastIndexOf('.') + 1).toLowerCase();
|
|
131
177
|
let type;
|
|
178
|
+
|
|
132
179
|
switch (extension) {
|
|
133
|
-
case
|
|
134
|
-
type =
|
|
180
|
+
case 'bmp':
|
|
181
|
+
type = 'image/bmp';
|
|
135
182
|
break;
|
|
136
|
-
|
|
137
|
-
case
|
|
138
|
-
|
|
183
|
+
|
|
184
|
+
case 'jpg':
|
|
185
|
+
case 'jpeg':
|
|
186
|
+
type = 'image/jpeg';
|
|
139
187
|
break;
|
|
140
|
-
|
|
141
|
-
|
|
188
|
+
|
|
189
|
+
case 'png':
|
|
190
|
+
type = 'image/png';
|
|
142
191
|
break;
|
|
143
|
-
|
|
144
|
-
|
|
192
|
+
|
|
193
|
+
case 'tif':
|
|
194
|
+
type = 'image/tiff';
|
|
145
195
|
break;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
196
|
+
|
|
197
|
+
case 'tga':
|
|
198
|
+
if (this.manager.getHandler('.tga') === null) {
|
|
199
|
+
console.warn('FBXLoader: TGA loader not found, skipping ', fileName);
|
|
149
200
|
}
|
|
150
|
-
|
|
201
|
+
|
|
202
|
+
type = 'image/tga';
|
|
151
203
|
break;
|
|
204
|
+
|
|
152
205
|
default:
|
|
153
206
|
console.warn('FBXLoader: Image type "' + extension + '" is not supported.');
|
|
154
207
|
return;
|
|
155
208
|
}
|
|
156
|
-
|
|
157
|
-
|
|
209
|
+
|
|
210
|
+
if (typeof content === 'string') {
|
|
211
|
+
// ASCII format
|
|
212
|
+
return 'data:' + type + ';base64,' + content;
|
|
158
213
|
} else {
|
|
214
|
+
// Binary Format
|
|
159
215
|
const array = new Uint8Array(content);
|
|
160
|
-
return window.URL.createObjectURL(new Blob([array], {
|
|
161
|
-
|
|
162
|
-
|
|
216
|
+
return window.URL.createObjectURL(new Blob([array], {
|
|
217
|
+
type: type
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
} // Parse nodes in FBXTree.Objects.Texture
|
|
221
|
+
// These contain details such as UV scaling, cropping, rotation etc and are connected
|
|
222
|
+
// to images in FBXTree.Objects.Video
|
|
223
|
+
|
|
224
|
+
|
|
163
225
|
parseTextures(images) {
|
|
164
|
-
const textureMap =
|
|
165
|
-
|
|
226
|
+
const textureMap = new Map();
|
|
227
|
+
|
|
228
|
+
if ('Texture' in fbxTree.Objects) {
|
|
166
229
|
const textureNodes = fbxTree.Objects.Texture;
|
|
230
|
+
|
|
167
231
|
for (const nodeID in textureNodes) {
|
|
168
232
|
const texture = this.parseTexture(textureNodes[nodeID], images);
|
|
169
233
|
textureMap.set(parseInt(nodeID), texture);
|
|
170
234
|
}
|
|
171
235
|
}
|
|
236
|
+
|
|
172
237
|
return textureMap;
|
|
173
|
-
}
|
|
238
|
+
} // Parse individual node in FBXTree.Objects.Texture
|
|
239
|
+
|
|
240
|
+
|
|
174
241
|
parseTexture(textureNode, images) {
|
|
175
242
|
const texture = this.loadTexture(textureNode, images);
|
|
176
243
|
texture.ID = textureNode.id;
|
|
177
244
|
texture.name = textureNode.attrName;
|
|
178
245
|
const wrapModeU = textureNode.WrapModeU;
|
|
179
246
|
const wrapModeV = textureNode.WrapModeV;
|
|
180
|
-
const valueU = wrapModeU !==
|
|
181
|
-
const valueV = wrapModeV !==
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
247
|
+
const valueU = wrapModeU !== undefined ? wrapModeU.value : 0;
|
|
248
|
+
const valueV = wrapModeV !== undefined ? wrapModeV.value : 0; // http://download.autodesk.com/us/fbx/SDKdocs/FBX_SDK_Help/files/fbxsdkref/class_k_fbx_texture.html#889640e63e2e681259ea81061b85143a
|
|
249
|
+
// 0: repeat(default), 1: clamp
|
|
250
|
+
|
|
251
|
+
texture.wrapS = valueU === 0 ? RepeatWrapping : ClampToEdgeWrapping;
|
|
252
|
+
texture.wrapT = valueV === 0 ? RepeatWrapping : ClampToEdgeWrapping;
|
|
253
|
+
|
|
254
|
+
if ('Scaling' in textureNode) {
|
|
185
255
|
const values = textureNode.Scaling.value;
|
|
186
256
|
texture.repeat.x = values[0];
|
|
187
257
|
texture.repeat.y = values[1];
|
|
188
258
|
}
|
|
259
|
+
|
|
189
260
|
return texture;
|
|
190
|
-
}
|
|
261
|
+
} // load a texture specified as a blob or data URI, or via an external URL using TextureLoader
|
|
262
|
+
|
|
263
|
+
|
|
191
264
|
loadTexture(textureNode, images) {
|
|
192
265
|
let fileName;
|
|
193
266
|
const currentPath = this.textureLoader.path;
|
|
194
267
|
const children = connections.get(textureNode.id).children;
|
|
195
|
-
|
|
268
|
+
|
|
269
|
+
if (children !== undefined && children.length > 0 && images[children[0].ID] !== undefined) {
|
|
196
270
|
fileName = images[children[0].ID];
|
|
197
|
-
|
|
198
|
-
|
|
271
|
+
|
|
272
|
+
if (fileName.indexOf('blob:') === 0 || fileName.indexOf('data:') === 0) {
|
|
273
|
+
this.textureLoader.setPath(undefined);
|
|
199
274
|
}
|
|
200
275
|
}
|
|
276
|
+
|
|
201
277
|
let texture;
|
|
202
278
|
const extension = textureNode.FileName.slice(-3).toLowerCase();
|
|
203
|
-
|
|
204
|
-
|
|
279
|
+
|
|
280
|
+
if (extension === 'tga') {
|
|
281
|
+
const loader = this.manager.getHandler('.tga');
|
|
282
|
+
|
|
205
283
|
if (loader === null) {
|
|
206
|
-
console.warn(
|
|
207
|
-
texture = new
|
|
284
|
+
console.warn('FBXLoader: TGA loader not found, creating placeholder texture for', textureNode.RelativeFilename);
|
|
285
|
+
texture = new Texture();
|
|
208
286
|
} else {
|
|
209
287
|
loader.setPath(this.textureLoader.path);
|
|
210
288
|
texture = loader.load(fileName);
|
|
211
289
|
}
|
|
212
|
-
} else if (extension ===
|
|
213
|
-
console.warn(
|
|
214
|
-
|
|
215
|
-
textureNode.RelativeFilename
|
|
216
|
-
);
|
|
217
|
-
texture = new THREE.Texture();
|
|
290
|
+
} else if (extension === 'psd') {
|
|
291
|
+
console.warn('FBXLoader: PSD textures are not supported, creating placeholder texture for', textureNode.RelativeFilename);
|
|
292
|
+
texture = new Texture();
|
|
218
293
|
} else {
|
|
219
294
|
texture = this.textureLoader.load(fileName);
|
|
220
295
|
}
|
|
296
|
+
|
|
221
297
|
this.textureLoader.setPath(currentPath);
|
|
222
298
|
return texture;
|
|
223
|
-
}
|
|
299
|
+
} // Parse nodes in FBXTree.Objects.Material
|
|
300
|
+
|
|
301
|
+
|
|
224
302
|
parseMaterials(textureMap) {
|
|
225
|
-
const materialMap =
|
|
226
|
-
|
|
303
|
+
const materialMap = new Map();
|
|
304
|
+
|
|
305
|
+
if ('Material' in fbxTree.Objects) {
|
|
227
306
|
const materialNodes = fbxTree.Objects.Material;
|
|
307
|
+
|
|
228
308
|
for (const nodeID in materialNodes) {
|
|
229
309
|
const material = this.parseMaterial(materialNodes[nodeID], textureMap);
|
|
230
|
-
if (material !== null)
|
|
231
|
-
materialMap.set(parseInt(nodeID), material);
|
|
310
|
+
if (material !== null) materialMap.set(parseInt(nodeID), material);
|
|
232
311
|
}
|
|
233
312
|
}
|
|
313
|
+
|
|
234
314
|
return materialMap;
|
|
235
|
-
}
|
|
315
|
+
} // Parse single node in FBXTree.Objects.Material
|
|
316
|
+
// Materials are connected to texture maps in FBXTree.Objects.Textures
|
|
317
|
+
// FBX format currently only supports Lambert and Phong shading models
|
|
318
|
+
|
|
319
|
+
|
|
236
320
|
parseMaterial(materialNode, textureMap) {
|
|
237
321
|
const ID = materialNode.id;
|
|
238
322
|
const name = materialNode.attrName;
|
|
239
|
-
let type = materialNode.ShadingModel;
|
|
240
|
-
|
|
323
|
+
let type = materialNode.ShadingModel; // Case where FBX wraps shading model in property object.
|
|
324
|
+
|
|
325
|
+
if (typeof type === 'object') {
|
|
241
326
|
type = type.value;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
327
|
+
} // Ignore unused materials which don't have any connections.
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
if (!connections.has(ID)) return null;
|
|
245
331
|
const parameters = this.parseParameters(materialNode, textureMap, ID);
|
|
246
332
|
let material;
|
|
333
|
+
|
|
247
334
|
switch (type.toLowerCase()) {
|
|
248
|
-
case
|
|
249
|
-
material = new
|
|
335
|
+
case 'phong':
|
|
336
|
+
material = new MeshPhongMaterial();
|
|
250
337
|
break;
|
|
251
|
-
|
|
252
|
-
|
|
338
|
+
|
|
339
|
+
case 'lambert':
|
|
340
|
+
material = new MeshLambertMaterial();
|
|
253
341
|
break;
|
|
342
|
+
|
|
254
343
|
default:
|
|
255
344
|
console.warn('THREE.FBXLoader: unknown material type "%s". Defaulting to MeshPhongMaterial.', type);
|
|
256
|
-
material = new
|
|
345
|
+
material = new MeshPhongMaterial();
|
|
257
346
|
break;
|
|
258
347
|
}
|
|
348
|
+
|
|
259
349
|
material.setValues(parameters);
|
|
260
350
|
material.name = name;
|
|
261
351
|
return material;
|
|
262
|
-
}
|
|
352
|
+
} // Parse FBX material and return parameters suitable for a three.js material
|
|
353
|
+
// Also parse the texture map and return any textures associated with the material
|
|
354
|
+
|
|
355
|
+
|
|
263
356
|
parseParameters(materialNode, textureMap, ID) {
|
|
264
357
|
const parameters = {};
|
|
358
|
+
|
|
265
359
|
if (materialNode.BumpFactor) {
|
|
266
360
|
parameters.bumpScale = materialNode.BumpFactor.value;
|
|
267
361
|
}
|
|
362
|
+
|
|
268
363
|
if (materialNode.Diffuse) {
|
|
269
|
-
parameters.color = new
|
|
270
|
-
} else if (materialNode.DiffuseColor && (materialNode.DiffuseColor.type ===
|
|
271
|
-
|
|
364
|
+
parameters.color = new Color().fromArray(materialNode.Diffuse.value);
|
|
365
|
+
} else if (materialNode.DiffuseColor && (materialNode.DiffuseColor.type === 'Color' || materialNode.DiffuseColor.type === 'ColorRGB')) {
|
|
366
|
+
// The blender exporter exports diffuse here instead of in materialNode.Diffuse
|
|
367
|
+
parameters.color = new Color().fromArray(materialNode.DiffuseColor.value);
|
|
272
368
|
}
|
|
369
|
+
|
|
273
370
|
if (materialNode.DisplacementFactor) {
|
|
274
371
|
parameters.displacementScale = materialNode.DisplacementFactor.value;
|
|
275
372
|
}
|
|
373
|
+
|
|
276
374
|
if (materialNode.Emissive) {
|
|
277
|
-
parameters.emissive = new
|
|
278
|
-
} else if (materialNode.EmissiveColor && (materialNode.EmissiveColor.type ===
|
|
279
|
-
|
|
375
|
+
parameters.emissive = new Color().fromArray(materialNode.Emissive.value);
|
|
376
|
+
} else if (materialNode.EmissiveColor && (materialNode.EmissiveColor.type === 'Color' || materialNode.EmissiveColor.type === 'ColorRGB')) {
|
|
377
|
+
// The blender exporter exports emissive color here instead of in materialNode.Emissive
|
|
378
|
+
parameters.emissive = new Color().fromArray(materialNode.EmissiveColor.value);
|
|
280
379
|
}
|
|
380
|
+
|
|
281
381
|
if (materialNode.EmissiveFactor) {
|
|
282
382
|
parameters.emissiveIntensity = parseFloat(materialNode.EmissiveFactor.value);
|
|
283
383
|
}
|
|
384
|
+
|
|
284
385
|
if (materialNode.Opacity) {
|
|
285
386
|
parameters.opacity = parseFloat(materialNode.Opacity.value);
|
|
286
387
|
}
|
|
287
|
-
|
|
388
|
+
|
|
389
|
+
if (parameters.opacity < 1.0) {
|
|
288
390
|
parameters.transparent = true;
|
|
289
391
|
}
|
|
392
|
+
|
|
290
393
|
if (materialNode.ReflectionFactor) {
|
|
291
394
|
parameters.reflectivity = materialNode.ReflectionFactor.value;
|
|
292
395
|
}
|
|
396
|
+
|
|
293
397
|
if (materialNode.Shininess) {
|
|
294
398
|
parameters.shininess = materialNode.Shininess.value;
|
|
295
399
|
}
|
|
400
|
+
|
|
296
401
|
if (materialNode.Specular) {
|
|
297
|
-
parameters.specular = new
|
|
298
|
-
} else if (materialNode.SpecularColor && materialNode.SpecularColor.type ===
|
|
299
|
-
|
|
402
|
+
parameters.specular = new Color().fromArray(materialNode.Specular.value);
|
|
403
|
+
} else if (materialNode.SpecularColor && materialNode.SpecularColor.type === 'Color') {
|
|
404
|
+
// The blender exporter exports specular color here instead of in materialNode.Specular
|
|
405
|
+
parameters.specular = new Color().fromArray(materialNode.SpecularColor.value);
|
|
300
406
|
}
|
|
407
|
+
|
|
301
408
|
const scope = this;
|
|
302
|
-
connections.get(ID).children.forEach(function(child) {
|
|
409
|
+
connections.get(ID).children.forEach(function (child) {
|
|
303
410
|
const type = child.relationship;
|
|
411
|
+
|
|
304
412
|
switch (type) {
|
|
305
|
-
case
|
|
413
|
+
case 'Bump':
|
|
306
414
|
parameters.bumpMap = scope.getTexture(textureMap, child.ID);
|
|
307
415
|
break;
|
|
308
|
-
|
|
416
|
+
|
|
417
|
+
case 'Maya|TEX_ao_map':
|
|
309
418
|
parameters.aoMap = scope.getTexture(textureMap, child.ID);
|
|
310
419
|
break;
|
|
311
|
-
|
|
312
|
-
case
|
|
420
|
+
|
|
421
|
+
case 'DiffuseColor':
|
|
422
|
+
case 'Maya|TEX_color_map':
|
|
313
423
|
parameters.map = scope.getTexture(textureMap, child.ID);
|
|
314
|
-
|
|
315
|
-
|
|
424
|
+
|
|
425
|
+
if (parameters.map !== undefined) {
|
|
426
|
+
parameters.map.encoding = sRGBEncoding;
|
|
316
427
|
}
|
|
428
|
+
|
|
317
429
|
break;
|
|
318
|
-
|
|
430
|
+
|
|
431
|
+
case 'DisplacementColor':
|
|
319
432
|
parameters.displacementMap = scope.getTexture(textureMap, child.ID);
|
|
320
433
|
break;
|
|
321
|
-
|
|
434
|
+
|
|
435
|
+
case 'EmissiveColor':
|
|
322
436
|
parameters.emissiveMap = scope.getTexture(textureMap, child.ID);
|
|
323
|
-
|
|
324
|
-
|
|
437
|
+
|
|
438
|
+
if (parameters.emissiveMap !== undefined) {
|
|
439
|
+
parameters.emissiveMap.encoding = sRGBEncoding;
|
|
325
440
|
}
|
|
441
|
+
|
|
326
442
|
break;
|
|
327
|
-
|
|
328
|
-
case
|
|
443
|
+
|
|
444
|
+
case 'NormalMap':
|
|
445
|
+
case 'Maya|TEX_normal_map':
|
|
329
446
|
parameters.normalMap = scope.getTexture(textureMap, child.ID);
|
|
330
447
|
break;
|
|
331
|
-
|
|
448
|
+
|
|
449
|
+
case 'ReflectionColor':
|
|
332
450
|
parameters.envMap = scope.getTexture(textureMap, child.ID);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
parameters.envMap.
|
|
451
|
+
|
|
452
|
+
if (parameters.envMap !== undefined) {
|
|
453
|
+
parameters.envMap.mapping = EquirectangularReflectionMapping;
|
|
454
|
+
parameters.envMap.encoding = sRGBEncoding;
|
|
336
455
|
}
|
|
456
|
+
|
|
337
457
|
break;
|
|
338
|
-
|
|
458
|
+
|
|
459
|
+
case 'SpecularColor':
|
|
339
460
|
parameters.specularMap = scope.getTexture(textureMap, child.ID);
|
|
340
|
-
|
|
341
|
-
|
|
461
|
+
|
|
462
|
+
if (parameters.specularMap !== undefined) {
|
|
463
|
+
parameters.specularMap.encoding = sRGBEncoding;
|
|
342
464
|
}
|
|
465
|
+
|
|
343
466
|
break;
|
|
344
|
-
|
|
345
|
-
case
|
|
467
|
+
|
|
468
|
+
case 'TransparentColor':
|
|
469
|
+
case 'TransparencyFactor':
|
|
346
470
|
parameters.alphaMap = scope.getTexture(textureMap, child.ID);
|
|
347
471
|
parameters.transparent = true;
|
|
348
472
|
break;
|
|
349
|
-
|
|
350
|
-
case
|
|
351
|
-
case
|
|
352
|
-
|
|
473
|
+
|
|
474
|
+
case 'AmbientColor':
|
|
475
|
+
case 'ShininessExponent': // AKA glossiness map
|
|
476
|
+
|
|
477
|
+
case 'SpecularFactor': // AKA specularLevel
|
|
478
|
+
|
|
479
|
+
case 'VectorDisplacementColor': // NOTE: Seems to be a copy of DisplacementColor
|
|
480
|
+
|
|
353
481
|
default:
|
|
354
|
-
console.warn(
|
|
482
|
+
console.warn('THREE.FBXLoader: %s map is not supported in three.js, skipping texture.', type);
|
|
355
483
|
break;
|
|
356
484
|
}
|
|
357
485
|
});
|
|
358
486
|
return parameters;
|
|
359
|
-
}
|
|
487
|
+
} // get a texture from the textureMap for use by a material.
|
|
488
|
+
|
|
489
|
+
|
|
360
490
|
getTexture(textureMap, id) {
|
|
361
|
-
if
|
|
362
|
-
|
|
491
|
+
// if the texture is a layered texture, just use the first layer and issue a warning
|
|
492
|
+
if ('LayeredTexture' in fbxTree.Objects && id in fbxTree.Objects.LayeredTexture) {
|
|
493
|
+
console.warn('THREE.FBXLoader: layered textures are not supported in three.js. Discarding all but first layer.');
|
|
363
494
|
id = connections.get(id).children[0].ID;
|
|
364
495
|
}
|
|
496
|
+
|
|
365
497
|
return textureMap.get(id);
|
|
366
|
-
}
|
|
498
|
+
} // Parse nodes in FBXTree.Objects.Deformer
|
|
499
|
+
// Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here
|
|
500
|
+
// Generates map of Skeleton-like objects for use later when generating and binding skeletons.
|
|
501
|
+
|
|
502
|
+
|
|
367
503
|
parseDeformers() {
|
|
368
504
|
const skeletons = {};
|
|
369
505
|
const morphTargets = {};
|
|
370
|
-
|
|
506
|
+
|
|
507
|
+
if ('Deformer' in fbxTree.Objects) {
|
|
371
508
|
const DeformerNodes = fbxTree.Objects.Deformer;
|
|
509
|
+
|
|
372
510
|
for (const nodeID in DeformerNodes) {
|
|
373
511
|
const deformerNode = DeformerNodes[nodeID];
|
|
374
512
|
const relationships = connections.get(parseInt(nodeID));
|
|
375
|
-
|
|
513
|
+
|
|
514
|
+
if (deformerNode.attrType === 'Skin') {
|
|
376
515
|
const skeleton = this.parseSkeleton(relationships, DeformerNodes);
|
|
377
516
|
skeleton.ID = nodeID;
|
|
517
|
+
|
|
378
518
|
if (relationships.parents.length > 1) {
|
|
379
|
-
console.warn(
|
|
519
|
+
console.warn('THREE.FBXLoader: skeleton attached to more than one geometry is not supported.');
|
|
380
520
|
}
|
|
521
|
+
|
|
381
522
|
skeleton.geometryID = relationships.parents[0].ID;
|
|
382
523
|
skeletons[nodeID] = skeleton;
|
|
383
|
-
} else if (deformerNode.attrType ===
|
|
524
|
+
} else if (deformerNode.attrType === 'BlendShape') {
|
|
384
525
|
const morphTarget = {
|
|
385
526
|
id: nodeID
|
|
386
527
|
};
|
|
387
528
|
morphTarget.rawTargets = this.parseMorphTargets(relationships, DeformerNodes);
|
|
388
529
|
morphTarget.id = nodeID;
|
|
530
|
+
|
|
389
531
|
if (relationships.parents.length > 1) {
|
|
390
|
-
console.warn(
|
|
532
|
+
console.warn('THREE.FBXLoader: morph target attached to more than one geometry is not supported.');
|
|
391
533
|
}
|
|
534
|
+
|
|
392
535
|
morphTargets[nodeID] = morphTarget;
|
|
393
536
|
}
|
|
394
537
|
}
|
|
395
538
|
}
|
|
539
|
+
|
|
396
540
|
return {
|
|
397
|
-
skeletons,
|
|
398
|
-
morphTargets
|
|
541
|
+
skeletons: skeletons,
|
|
542
|
+
morphTargets: morphTargets
|
|
399
543
|
};
|
|
400
|
-
}
|
|
544
|
+
} // Parse single nodes in FBXTree.Objects.Deformer
|
|
545
|
+
// The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster'
|
|
546
|
+
// Each skin node represents a skeleton and each cluster node represents a bone
|
|
547
|
+
|
|
548
|
+
|
|
401
549
|
parseSkeleton(relationships, deformerNodes) {
|
|
402
550
|
const rawBones = [];
|
|
403
|
-
relationships.children.forEach(function(child) {
|
|
551
|
+
relationships.children.forEach(function (child) {
|
|
404
552
|
const boneNode = deformerNodes[child.ID];
|
|
405
|
-
if (boneNode.attrType !==
|
|
406
|
-
return;
|
|
553
|
+
if (boneNode.attrType !== 'Cluster') return;
|
|
407
554
|
const rawBone = {
|
|
408
555
|
ID: child.ID,
|
|
409
556
|
indices: [],
|
|
410
557
|
weights: [],
|
|
411
|
-
transformLink: new
|
|
558
|
+
transformLink: new Matrix4().fromArray(boneNode.TransformLink.a) // transform: new Matrix4().fromArray( boneNode.Transform.a ),
|
|
559
|
+
// linkMode: boneNode.Mode,
|
|
560
|
+
|
|
412
561
|
};
|
|
413
|
-
|
|
562
|
+
|
|
563
|
+
if ('Indexes' in boneNode) {
|
|
414
564
|
rawBone.indices = boneNode.Indexes.a;
|
|
415
565
|
rawBone.weights = boneNode.Weights.a;
|
|
416
566
|
}
|
|
567
|
+
|
|
417
568
|
rawBones.push(rawBone);
|
|
418
569
|
});
|
|
419
570
|
return {
|
|
420
|
-
rawBones,
|
|
571
|
+
rawBones: rawBones,
|
|
421
572
|
bones: []
|
|
422
573
|
};
|
|
423
|
-
}
|
|
574
|
+
} // The top level morph deformer node has type "BlendShape" and sub nodes have type "BlendShapeChannel"
|
|
575
|
+
|
|
576
|
+
|
|
424
577
|
parseMorphTargets(relationships, deformerNodes) {
|
|
425
578
|
const rawMorphTargets = [];
|
|
579
|
+
|
|
426
580
|
for (let i = 0; i < relationships.children.length; i++) {
|
|
427
581
|
const child = relationships.children[i];
|
|
428
582
|
const morphTargetNode = deformerNodes[child.ID];
|
|
@@ -432,105 +586,126 @@ class FBXTreeParser {
|
|
|
432
586
|
id: morphTargetNode.id,
|
|
433
587
|
fullWeights: morphTargetNode.FullWeights.a
|
|
434
588
|
};
|
|
435
|
-
if (morphTargetNode.attrType !==
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return child2.relationship === void 0;
|
|
589
|
+
if (morphTargetNode.attrType !== 'BlendShapeChannel') return;
|
|
590
|
+
rawMorphTarget.geoID = connections.get(parseInt(child.ID)).children.filter(function (child) {
|
|
591
|
+
return child.relationship === undefined;
|
|
439
592
|
})[0].ID;
|
|
440
593
|
rawMorphTargets.push(rawMorphTarget);
|
|
441
594
|
}
|
|
595
|
+
|
|
442
596
|
return rawMorphTargets;
|
|
443
|
-
}
|
|
597
|
+
} // create the main Group() to be returned by the loader
|
|
598
|
+
|
|
599
|
+
|
|
444
600
|
parseScene(deformers, geometryMap, materialMap) {
|
|
445
|
-
sceneGraph = new
|
|
601
|
+
sceneGraph = new Group();
|
|
446
602
|
const modelMap = this.parseModels(deformers.skeletons, geometryMap, materialMap);
|
|
447
603
|
const modelNodes = fbxTree.Objects.Model;
|
|
448
604
|
const scope = this;
|
|
449
|
-
modelMap.forEach(function(model) {
|
|
605
|
+
modelMap.forEach(function (model) {
|
|
450
606
|
const modelNode = modelNodes[model.ID];
|
|
451
607
|
scope.setLookAtProperties(model, modelNode);
|
|
452
608
|
const parentConnections = connections.get(model.ID).parents;
|
|
453
|
-
parentConnections.forEach(function(connection) {
|
|
609
|
+
parentConnections.forEach(function (connection) {
|
|
454
610
|
const parent = modelMap.get(connection.ID);
|
|
455
|
-
if (parent !==
|
|
456
|
-
parent.add(model);
|
|
611
|
+
if (parent !== undefined) parent.add(model);
|
|
457
612
|
});
|
|
613
|
+
|
|
458
614
|
if (model.parent === null) {
|
|
459
615
|
sceneGraph.add(model);
|
|
460
616
|
}
|
|
461
617
|
});
|
|
462
618
|
this.bindSkeleton(deformers.skeletons, geometryMap, modelMap);
|
|
463
619
|
this.createAmbientLight();
|
|
464
|
-
sceneGraph.traverse(function(node) {
|
|
620
|
+
sceneGraph.traverse(function (node) {
|
|
465
621
|
if (node.userData.transformData) {
|
|
466
622
|
if (node.parent) {
|
|
467
623
|
node.userData.transformData.parentMatrix = node.parent.matrix;
|
|
468
624
|
node.userData.transformData.parentMatrixWorld = node.parent.matrixWorld;
|
|
469
625
|
}
|
|
626
|
+
|
|
470
627
|
const transform = generateTransform(node.userData.transformData);
|
|
471
628
|
node.applyMatrix4(transform);
|
|
472
629
|
node.updateWorldMatrix();
|
|
473
630
|
}
|
|
474
631
|
});
|
|
475
|
-
const animations = new AnimationParser().parse();
|
|
632
|
+
const animations = new AnimationParser().parse(); // if all the models where already combined in a single group, just return that
|
|
633
|
+
|
|
476
634
|
if (sceneGraph.children.length === 1 && sceneGraph.children[0].isGroup) {
|
|
477
635
|
sceneGraph.children[0].animations = animations;
|
|
478
636
|
sceneGraph = sceneGraph.children[0];
|
|
479
637
|
}
|
|
638
|
+
|
|
480
639
|
sceneGraph.animations = animations;
|
|
481
|
-
}
|
|
640
|
+
} // parse nodes in FBXTree.Objects.Model
|
|
641
|
+
|
|
642
|
+
|
|
482
643
|
parseModels(skeletons, geometryMap, materialMap) {
|
|
483
|
-
const modelMap =
|
|
644
|
+
const modelMap = new Map();
|
|
484
645
|
const modelNodes = fbxTree.Objects.Model;
|
|
646
|
+
|
|
485
647
|
for (const nodeID in modelNodes) {
|
|
486
648
|
const id = parseInt(nodeID);
|
|
487
649
|
const node = modelNodes[nodeID];
|
|
488
650
|
const relationships = connections.get(id);
|
|
489
651
|
let model = this.buildSkeleton(relationships, skeletons, id, node.attrName);
|
|
652
|
+
|
|
490
653
|
if (!model) {
|
|
491
654
|
switch (node.attrType) {
|
|
492
|
-
case
|
|
655
|
+
case 'Camera':
|
|
493
656
|
model = this.createCamera(relationships);
|
|
494
657
|
break;
|
|
495
|
-
|
|
658
|
+
|
|
659
|
+
case 'Light':
|
|
496
660
|
model = this.createLight(relationships);
|
|
497
661
|
break;
|
|
498
|
-
|
|
662
|
+
|
|
663
|
+
case 'Mesh':
|
|
499
664
|
model = this.createMesh(relationships, geometryMap, materialMap);
|
|
500
665
|
break;
|
|
501
|
-
|
|
666
|
+
|
|
667
|
+
case 'NurbsCurve':
|
|
502
668
|
model = this.createCurve(relationships, geometryMap);
|
|
503
669
|
break;
|
|
504
|
-
|
|
505
|
-
case
|
|
506
|
-
|
|
670
|
+
|
|
671
|
+
case 'LimbNode':
|
|
672
|
+
case 'Root':
|
|
673
|
+
model = new Bone();
|
|
507
674
|
break;
|
|
508
|
-
|
|
675
|
+
|
|
676
|
+
case 'Null':
|
|
509
677
|
default:
|
|
510
|
-
model = new
|
|
678
|
+
model = new Group();
|
|
511
679
|
break;
|
|
512
680
|
}
|
|
513
|
-
|
|
681
|
+
|
|
682
|
+
model.name = node.attrName ? PropertyBinding.sanitizeNodeName(node.attrName) : '';
|
|
514
683
|
model.ID = id;
|
|
515
684
|
}
|
|
685
|
+
|
|
516
686
|
this.getTransformData(model, node);
|
|
517
687
|
modelMap.set(id, model);
|
|
518
688
|
}
|
|
689
|
+
|
|
519
690
|
return modelMap;
|
|
520
691
|
}
|
|
692
|
+
|
|
521
693
|
buildSkeleton(relationships, skeletons, id, name) {
|
|
522
694
|
let bone = null;
|
|
523
|
-
relationships.parents.forEach(function(parent) {
|
|
695
|
+
relationships.parents.forEach(function (parent) {
|
|
524
696
|
for (const ID in skeletons) {
|
|
525
697
|
const skeleton = skeletons[ID];
|
|
526
|
-
skeleton.rawBones.forEach(function(rawBone, i) {
|
|
698
|
+
skeleton.rawBones.forEach(function (rawBone, i) {
|
|
527
699
|
if (rawBone.ID === parent.ID) {
|
|
528
700
|
const subBone = bone;
|
|
529
|
-
bone = new
|
|
530
|
-
bone.matrixWorld.copy(rawBone.transformLink);
|
|
531
|
-
|
|
701
|
+
bone = new Bone();
|
|
702
|
+
bone.matrixWorld.copy(rawBone.transformLink); // set name and id here - otherwise in cases where "subBone" is created it will not have a name / id
|
|
703
|
+
|
|
704
|
+
bone.name = name ? PropertyBinding.sanitizeNodeName(name) : '';
|
|
532
705
|
bone.ID = id;
|
|
533
|
-
skeleton.bones[i] = bone;
|
|
706
|
+
skeleton.bones[i] = bone; // In cases where a bone is shared between multiple meshes
|
|
707
|
+
// duplicate the bone here and and it as a child of the first bone
|
|
708
|
+
|
|
534
709
|
if (subBone !== null) {
|
|
535
710
|
bone.add(subBone);
|
|
536
711
|
}
|
|
@@ -539,415 +714,502 @@ class FBXTreeParser {
|
|
|
539
714
|
}
|
|
540
715
|
});
|
|
541
716
|
return bone;
|
|
542
|
-
}
|
|
717
|
+
} // create a PerspectiveCamera or OrthographicCamera
|
|
718
|
+
|
|
719
|
+
|
|
543
720
|
createCamera(relationships) {
|
|
544
721
|
let model;
|
|
545
722
|
let cameraAttribute;
|
|
546
|
-
relationships.children.forEach(function(child) {
|
|
723
|
+
relationships.children.forEach(function (child) {
|
|
547
724
|
const attr = fbxTree.Objects.NodeAttribute[child.ID];
|
|
548
|
-
|
|
725
|
+
|
|
726
|
+
if (attr !== undefined) {
|
|
549
727
|
cameraAttribute = attr;
|
|
550
728
|
}
|
|
551
729
|
});
|
|
552
|
-
|
|
553
|
-
|
|
730
|
+
|
|
731
|
+
if (cameraAttribute === undefined) {
|
|
732
|
+
model = new Object3D();
|
|
554
733
|
} else {
|
|
555
734
|
let type = 0;
|
|
556
|
-
|
|
735
|
+
|
|
736
|
+
if (cameraAttribute.CameraProjectionType !== undefined && cameraAttribute.CameraProjectionType.value === 1) {
|
|
557
737
|
type = 1;
|
|
558
738
|
}
|
|
739
|
+
|
|
559
740
|
let nearClippingPlane = 1;
|
|
560
|
-
|
|
561
|
-
|
|
741
|
+
|
|
742
|
+
if (cameraAttribute.NearPlane !== undefined) {
|
|
743
|
+
nearClippingPlane = cameraAttribute.NearPlane.value / 1000;
|
|
562
744
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
745
|
+
|
|
746
|
+
let farClippingPlane = 1000;
|
|
747
|
+
|
|
748
|
+
if (cameraAttribute.FarPlane !== undefined) {
|
|
749
|
+
farClippingPlane = cameraAttribute.FarPlane.value / 1000;
|
|
566
750
|
}
|
|
751
|
+
|
|
567
752
|
let width = window.innerWidth;
|
|
568
753
|
let height = window.innerHeight;
|
|
569
|
-
|
|
754
|
+
|
|
755
|
+
if (cameraAttribute.AspectWidth !== undefined && cameraAttribute.AspectHeight !== undefined) {
|
|
570
756
|
width = cameraAttribute.AspectWidth.value;
|
|
571
757
|
height = cameraAttribute.AspectHeight.value;
|
|
572
758
|
}
|
|
759
|
+
|
|
573
760
|
const aspect = width / height;
|
|
574
761
|
let fov = 45;
|
|
575
|
-
|
|
762
|
+
|
|
763
|
+
if (cameraAttribute.FieldOfView !== undefined) {
|
|
576
764
|
fov = cameraAttribute.FieldOfView.value;
|
|
577
765
|
}
|
|
766
|
+
|
|
578
767
|
const focalLength = cameraAttribute.FocalLength ? cameraAttribute.FocalLength.value : null;
|
|
768
|
+
|
|
579
769
|
switch (type) {
|
|
580
770
|
case 0:
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
771
|
+
// Perspective
|
|
772
|
+
model = new PerspectiveCamera(fov, aspect, nearClippingPlane, farClippingPlane);
|
|
773
|
+
if (focalLength !== null) model.setFocalLength(focalLength);
|
|
584
774
|
break;
|
|
775
|
+
|
|
585
776
|
case 1:
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
width / 2,
|
|
589
|
-
height / 2,
|
|
590
|
-
-height / 2,
|
|
591
|
-
nearClippingPlane,
|
|
592
|
-
farClippingPlane
|
|
593
|
-
);
|
|
777
|
+
// Orthographic
|
|
778
|
+
model = new OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, nearClippingPlane, farClippingPlane);
|
|
594
779
|
break;
|
|
780
|
+
|
|
595
781
|
default:
|
|
596
|
-
console.warn(
|
|
597
|
-
model = new
|
|
782
|
+
console.warn('THREE.FBXLoader: Unknown camera type ' + type + '.');
|
|
783
|
+
model = new Object3D();
|
|
598
784
|
break;
|
|
599
785
|
}
|
|
600
786
|
}
|
|
787
|
+
|
|
601
788
|
return model;
|
|
602
|
-
}
|
|
789
|
+
} // Create a DirectionalLight, PointLight or SpotLight
|
|
790
|
+
|
|
791
|
+
|
|
603
792
|
createLight(relationships) {
|
|
604
793
|
let model;
|
|
605
794
|
let lightAttribute;
|
|
606
|
-
relationships.children.forEach(function(child) {
|
|
795
|
+
relationships.children.forEach(function (child) {
|
|
607
796
|
const attr = fbxTree.Objects.NodeAttribute[child.ID];
|
|
608
|
-
|
|
797
|
+
|
|
798
|
+
if (attr !== undefined) {
|
|
609
799
|
lightAttribute = attr;
|
|
610
800
|
}
|
|
611
801
|
});
|
|
612
|
-
|
|
613
|
-
|
|
802
|
+
|
|
803
|
+
if (lightAttribute === undefined) {
|
|
804
|
+
model = new Object3D();
|
|
614
805
|
} else {
|
|
615
|
-
let type;
|
|
616
|
-
|
|
806
|
+
let type; // LightType can be undefined for Point lights
|
|
807
|
+
|
|
808
|
+
if (lightAttribute.LightType === undefined) {
|
|
617
809
|
type = 0;
|
|
618
810
|
} else {
|
|
619
811
|
type = lightAttribute.LightType.value;
|
|
620
812
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
813
|
+
|
|
814
|
+
let color = 0xffffff;
|
|
815
|
+
|
|
816
|
+
if (lightAttribute.Color !== undefined) {
|
|
817
|
+
color = new Color().fromArray(lightAttribute.Color.value);
|
|
624
818
|
}
|
|
625
|
-
|
|
626
|
-
|
|
819
|
+
|
|
820
|
+
let intensity = lightAttribute.Intensity === undefined ? 1 : lightAttribute.Intensity.value / 100; // light disabled
|
|
821
|
+
|
|
822
|
+
if (lightAttribute.CastLightOnObject !== undefined && lightAttribute.CastLightOnObject.value === 0) {
|
|
627
823
|
intensity = 0;
|
|
628
824
|
}
|
|
825
|
+
|
|
629
826
|
let distance = 0;
|
|
630
|
-
|
|
631
|
-
|
|
827
|
+
|
|
828
|
+
if (lightAttribute.FarAttenuationEnd !== undefined) {
|
|
829
|
+
if (lightAttribute.EnableFarAttenuation !== undefined && lightAttribute.EnableFarAttenuation.value === 0) {
|
|
632
830
|
distance = 0;
|
|
633
831
|
} else {
|
|
634
832
|
distance = lightAttribute.FarAttenuationEnd.value;
|
|
635
833
|
}
|
|
636
|
-
}
|
|
834
|
+
} // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd?
|
|
835
|
+
|
|
836
|
+
|
|
637
837
|
const decay = 1;
|
|
838
|
+
|
|
638
839
|
switch (type) {
|
|
639
840
|
case 0:
|
|
640
|
-
|
|
841
|
+
// Point
|
|
842
|
+
model = new PointLight(color, intensity, distance, decay);
|
|
641
843
|
break;
|
|
844
|
+
|
|
642
845
|
case 1:
|
|
643
|
-
|
|
846
|
+
// Directional
|
|
847
|
+
model = new DirectionalLight(color, intensity);
|
|
644
848
|
break;
|
|
849
|
+
|
|
645
850
|
case 2:
|
|
851
|
+
// Spot
|
|
646
852
|
let angle = Math.PI / 3;
|
|
647
|
-
|
|
648
|
-
|
|
853
|
+
|
|
854
|
+
if (lightAttribute.InnerAngle !== undefined) {
|
|
855
|
+
angle = MathUtils.degToRad(lightAttribute.InnerAngle.value);
|
|
649
856
|
}
|
|
857
|
+
|
|
650
858
|
let penumbra = 0;
|
|
651
|
-
|
|
652
|
-
|
|
859
|
+
|
|
860
|
+
if (lightAttribute.OuterAngle !== undefined) {
|
|
861
|
+
// TODO: this is not correct - FBX calculates outer and inner angle in degrees
|
|
862
|
+
// with OuterAngle > InnerAngle && OuterAngle <= Math.PI
|
|
863
|
+
// while three.js uses a penumbra between (0, 1) to attenuate the inner angle
|
|
864
|
+
penumbra = MathUtils.degToRad(lightAttribute.OuterAngle.value);
|
|
653
865
|
penumbra = Math.max(penumbra, 1);
|
|
654
866
|
}
|
|
655
|
-
|
|
867
|
+
|
|
868
|
+
model = new SpotLight(color, intensity, distance, angle, penumbra, decay);
|
|
656
869
|
break;
|
|
870
|
+
|
|
657
871
|
default:
|
|
658
|
-
console.warn(
|
|
659
|
-
|
|
660
|
-
);
|
|
661
|
-
model = new THREE.PointLight(color, intensity);
|
|
872
|
+
console.warn('THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a PointLight.');
|
|
873
|
+
model = new PointLight(color, intensity);
|
|
662
874
|
break;
|
|
663
875
|
}
|
|
664
|
-
|
|
876
|
+
|
|
877
|
+
if (lightAttribute.CastShadows !== undefined && lightAttribute.CastShadows.value === 1) {
|
|
665
878
|
model.castShadow = true;
|
|
666
879
|
}
|
|
667
880
|
}
|
|
881
|
+
|
|
668
882
|
return model;
|
|
669
883
|
}
|
|
884
|
+
|
|
670
885
|
createMesh(relationships, geometryMap, materialMap) {
|
|
671
886
|
let model;
|
|
672
887
|
let geometry = null;
|
|
673
888
|
let material = null;
|
|
674
|
-
const materials = [];
|
|
675
|
-
|
|
889
|
+
const materials = []; // get geometry and materials(s) from connections
|
|
890
|
+
|
|
891
|
+
relationships.children.forEach(function (child) {
|
|
676
892
|
if (geometryMap.has(child.ID)) {
|
|
677
893
|
geometry = geometryMap.get(child.ID);
|
|
678
894
|
}
|
|
895
|
+
|
|
679
896
|
if (materialMap.has(child.ID)) {
|
|
680
897
|
materials.push(materialMap.get(child.ID));
|
|
681
898
|
}
|
|
682
899
|
});
|
|
900
|
+
|
|
683
901
|
if (materials.length > 1) {
|
|
684
902
|
material = materials;
|
|
685
903
|
} else if (materials.length > 0) {
|
|
686
904
|
material = materials[0];
|
|
687
905
|
} else {
|
|
688
|
-
material = new
|
|
906
|
+
material = new MeshPhongMaterial({
|
|
907
|
+
color: 0xcccccc
|
|
908
|
+
});
|
|
689
909
|
materials.push(material);
|
|
690
910
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
911
|
+
|
|
912
|
+
if ('color' in geometry.attributes) {
|
|
913
|
+
materials.forEach(function (material) {
|
|
914
|
+
material.vertexColors = true;
|
|
694
915
|
});
|
|
695
916
|
}
|
|
917
|
+
|
|
696
918
|
if (geometry.FBX_Deformer) {
|
|
697
|
-
model = new
|
|
919
|
+
model = new SkinnedMesh(geometry, material);
|
|
698
920
|
model.normalizeSkinWeights();
|
|
699
921
|
} else {
|
|
700
|
-
model = new
|
|
922
|
+
model = new Mesh(geometry, material);
|
|
701
923
|
}
|
|
924
|
+
|
|
702
925
|
return model;
|
|
703
926
|
}
|
|
927
|
+
|
|
704
928
|
createCurve(relationships, geometryMap) {
|
|
705
|
-
const geometry = relationships.children.reduce(function(geo, child) {
|
|
706
|
-
if (geometryMap.has(child.ID))
|
|
707
|
-
geo = geometryMap.get(child.ID);
|
|
929
|
+
const geometry = relationships.children.reduce(function (geo, child) {
|
|
930
|
+
if (geometryMap.has(child.ID)) geo = geometryMap.get(child.ID);
|
|
708
931
|
return geo;
|
|
709
|
-
}, null);
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
932
|
+
}, null); // FBX does not list materials for Nurbs lines, so we'll just put our own in here.
|
|
933
|
+
|
|
934
|
+
const material = new LineBasicMaterial({
|
|
935
|
+
color: 0x3300ff,
|
|
936
|
+
linewidth: 1
|
|
937
|
+
});
|
|
938
|
+
return new Line(geometry, material);
|
|
939
|
+
} // parse the model node for transform data
|
|
940
|
+
|
|
941
|
+
|
|
713
942
|
getTransformData(model, modelNode) {
|
|
714
943
|
const transformData = {};
|
|
715
|
-
if (
|
|
716
|
-
|
|
717
|
-
if (
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
if (
|
|
722
|
-
|
|
723
|
-
if (
|
|
724
|
-
|
|
725
|
-
if (
|
|
726
|
-
transformData.rotation = modelNode.Lcl_Rotation.value;
|
|
727
|
-
if ("PostRotation" in modelNode)
|
|
728
|
-
transformData.postRotation = modelNode.PostRotation.value;
|
|
729
|
-
if ("Lcl_Scaling" in modelNode)
|
|
730
|
-
transformData.scale = modelNode.Lcl_Scaling.value;
|
|
731
|
-
if ("ScalingOffset" in modelNode)
|
|
732
|
-
transformData.scalingOffset = modelNode.ScalingOffset.value;
|
|
733
|
-
if ("ScalingPivot" in modelNode)
|
|
734
|
-
transformData.scalingPivot = modelNode.ScalingPivot.value;
|
|
735
|
-
if ("RotationOffset" in modelNode)
|
|
736
|
-
transformData.rotationOffset = modelNode.RotationOffset.value;
|
|
737
|
-
if ("RotationPivot" in modelNode)
|
|
738
|
-
transformData.rotationPivot = modelNode.RotationPivot.value;
|
|
944
|
+
if ('InheritType' in modelNode) transformData.inheritType = parseInt(modelNode.InheritType.value);
|
|
945
|
+
if ('RotationOrder' in modelNode) transformData.eulerOrder = getEulerOrder(modelNode.RotationOrder.value);else transformData.eulerOrder = 'ZYX';
|
|
946
|
+
if ('Lcl_Translation' in modelNode) transformData.translation = modelNode.Lcl_Translation.value;
|
|
947
|
+
if ('PreRotation' in modelNode) transformData.preRotation = modelNode.PreRotation.value;
|
|
948
|
+
if ('Lcl_Rotation' in modelNode) transformData.rotation = modelNode.Lcl_Rotation.value;
|
|
949
|
+
if ('PostRotation' in modelNode) transformData.postRotation = modelNode.PostRotation.value;
|
|
950
|
+
if ('Lcl_Scaling' in modelNode) transformData.scale = modelNode.Lcl_Scaling.value;
|
|
951
|
+
if ('ScalingOffset' in modelNode) transformData.scalingOffset = modelNode.ScalingOffset.value;
|
|
952
|
+
if ('ScalingPivot' in modelNode) transformData.scalingPivot = modelNode.ScalingPivot.value;
|
|
953
|
+
if ('RotationOffset' in modelNode) transformData.rotationOffset = modelNode.RotationOffset.value;
|
|
954
|
+
if ('RotationPivot' in modelNode) transformData.rotationPivot = modelNode.RotationPivot.value;
|
|
739
955
|
model.userData.transformData = transformData;
|
|
740
956
|
}
|
|
957
|
+
|
|
741
958
|
setLookAtProperties(model, modelNode) {
|
|
742
|
-
if (
|
|
959
|
+
if ('LookAtProperty' in modelNode) {
|
|
743
960
|
const children = connections.get(model.ID).children;
|
|
744
|
-
children.forEach(function(child) {
|
|
745
|
-
if (child.relationship ===
|
|
961
|
+
children.forEach(function (child) {
|
|
962
|
+
if (child.relationship === 'LookAtProperty') {
|
|
746
963
|
const lookAtTarget = fbxTree.Objects.Model[child.ID];
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
964
|
+
|
|
965
|
+
if ('Lcl_Translation' in lookAtTarget) {
|
|
966
|
+
const pos = lookAtTarget.Lcl_Translation.value; // DirectionalLight, SpotLight
|
|
967
|
+
|
|
968
|
+
if (model.target !== undefined) {
|
|
750
969
|
model.target.position.fromArray(pos);
|
|
751
970
|
sceneGraph.add(model.target);
|
|
752
971
|
} else {
|
|
753
|
-
|
|
972
|
+
// Cameras and other Object3Ds
|
|
973
|
+
model.lookAt(new Vector3().fromArray(pos));
|
|
754
974
|
}
|
|
755
975
|
}
|
|
756
976
|
}
|
|
757
977
|
});
|
|
758
978
|
}
|
|
759
979
|
}
|
|
980
|
+
|
|
760
981
|
bindSkeleton(skeletons, geometryMap, modelMap) {
|
|
761
982
|
const bindMatrices = this.parsePoseNodes();
|
|
983
|
+
|
|
762
984
|
for (const ID in skeletons) {
|
|
763
985
|
const skeleton = skeletons[ID];
|
|
764
986
|
const parents = connections.get(parseInt(skeleton.ID)).parents;
|
|
765
|
-
parents.forEach(function(parent) {
|
|
987
|
+
parents.forEach(function (parent) {
|
|
766
988
|
if (geometryMap.has(parent.ID)) {
|
|
767
989
|
const geoID = parent.ID;
|
|
768
990
|
const geoRelationships = connections.get(geoID);
|
|
769
|
-
geoRelationships.parents.forEach(function(geoConnParent) {
|
|
991
|
+
geoRelationships.parents.forEach(function (geoConnParent) {
|
|
770
992
|
if (modelMap.has(geoConnParent.ID)) {
|
|
771
993
|
const model = modelMap.get(geoConnParent.ID);
|
|
772
|
-
model.bind(new
|
|
994
|
+
model.bind(new Skeleton(skeleton.bones), bindMatrices[geoConnParent.ID]);
|
|
773
995
|
}
|
|
774
996
|
});
|
|
775
997
|
}
|
|
776
998
|
});
|
|
777
999
|
}
|
|
778
1000
|
}
|
|
1001
|
+
|
|
779
1002
|
parsePoseNodes() {
|
|
780
1003
|
const bindMatrices = {};
|
|
781
|
-
|
|
1004
|
+
|
|
1005
|
+
if ('Pose' in fbxTree.Objects) {
|
|
782
1006
|
const BindPoseNode = fbxTree.Objects.Pose;
|
|
1007
|
+
|
|
783
1008
|
for (const nodeID in BindPoseNode) {
|
|
784
|
-
if (BindPoseNode[nodeID].attrType ===
|
|
1009
|
+
if (BindPoseNode[nodeID].attrType === 'BindPose' && BindPoseNode[nodeID].NbPoseNodes > 0) {
|
|
785
1010
|
const poseNodes = BindPoseNode[nodeID].PoseNode;
|
|
1011
|
+
|
|
786
1012
|
if (Array.isArray(poseNodes)) {
|
|
787
|
-
poseNodes.forEach(function(poseNode) {
|
|
788
|
-
bindMatrices[poseNode.Node] = new
|
|
1013
|
+
poseNodes.forEach(function (poseNode) {
|
|
1014
|
+
bindMatrices[poseNode.Node] = new Matrix4().fromArray(poseNode.Matrix.a);
|
|
789
1015
|
});
|
|
790
1016
|
} else {
|
|
791
|
-
bindMatrices[poseNodes.Node] = new
|
|
1017
|
+
bindMatrices[poseNodes.Node] = new Matrix4().fromArray(poseNodes.Matrix.a);
|
|
792
1018
|
}
|
|
793
1019
|
}
|
|
794
1020
|
}
|
|
795
1021
|
}
|
|
1022
|
+
|
|
796
1023
|
return bindMatrices;
|
|
797
|
-
}
|
|
1024
|
+
} // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light
|
|
1025
|
+
|
|
1026
|
+
|
|
798
1027
|
createAmbientLight() {
|
|
799
|
-
if (
|
|
1028
|
+
if ('GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings) {
|
|
800
1029
|
const ambientColor = fbxTree.GlobalSettings.AmbientColor.value;
|
|
801
1030
|
const r = ambientColor[0];
|
|
802
1031
|
const g = ambientColor[1];
|
|
803
1032
|
const b = ambientColor[2];
|
|
1033
|
+
|
|
804
1034
|
if (r !== 0 || g !== 0 || b !== 0) {
|
|
805
|
-
const color = new
|
|
806
|
-
sceneGraph.add(new
|
|
1035
|
+
const color = new Color(r, g, b);
|
|
1036
|
+
sceneGraph.add(new AmbientLight(color, 1));
|
|
807
1037
|
}
|
|
808
1038
|
}
|
|
809
1039
|
}
|
|
810
|
-
|
|
1040
|
+
|
|
1041
|
+
} // parse Geometry data from FBXTree and return map of BufferGeometries
|
|
1042
|
+
|
|
1043
|
+
|
|
811
1044
|
class GeometryParser {
|
|
1045
|
+
// Parse nodes in FBXTree.Objects.Geometry
|
|
812
1046
|
parse(deformers) {
|
|
813
|
-
const geometryMap =
|
|
814
|
-
|
|
1047
|
+
const geometryMap = new Map();
|
|
1048
|
+
|
|
1049
|
+
if ('Geometry' in fbxTree.Objects) {
|
|
815
1050
|
const geoNodes = fbxTree.Objects.Geometry;
|
|
1051
|
+
|
|
816
1052
|
for (const nodeID in geoNodes) {
|
|
817
1053
|
const relationships = connections.get(parseInt(nodeID));
|
|
818
1054
|
const geo = this.parseGeometry(relationships, geoNodes[nodeID], deformers);
|
|
819
1055
|
geometryMap.set(parseInt(nodeID), geo);
|
|
820
1056
|
}
|
|
821
1057
|
}
|
|
1058
|
+
|
|
822
1059
|
return geometryMap;
|
|
823
|
-
}
|
|
1060
|
+
} // Parse single node in FBXTree.Objects.Geometry
|
|
1061
|
+
|
|
1062
|
+
|
|
824
1063
|
parseGeometry(relationships, geoNode, deformers) {
|
|
825
1064
|
switch (geoNode.attrType) {
|
|
826
|
-
case
|
|
1065
|
+
case 'Mesh':
|
|
827
1066
|
return this.parseMeshGeometry(relationships, geoNode, deformers);
|
|
828
|
-
|
|
829
|
-
case
|
|
1067
|
+
|
|
1068
|
+
case 'NurbsCurve':
|
|
830
1069
|
return this.parseNurbsGeometry(geoNode);
|
|
831
|
-
break;
|
|
832
1070
|
}
|
|
833
|
-
}
|
|
1071
|
+
} // Parse single node mesh geometry in FBXTree.Objects.Geometry
|
|
1072
|
+
|
|
1073
|
+
|
|
834
1074
|
parseMeshGeometry(relationships, geoNode, deformers) {
|
|
835
1075
|
const skeletons = deformers.skeletons;
|
|
836
1076
|
const morphTargets = [];
|
|
837
|
-
const modelNodes = relationships.parents.map(function(parent) {
|
|
1077
|
+
const modelNodes = relationships.parents.map(function (parent) {
|
|
838
1078
|
return fbxTree.Objects.Model[parent.ID];
|
|
839
|
-
});
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const skeleton = relationships.children.reduce(function(
|
|
843
|
-
if (skeletons[child.ID] !==
|
|
844
|
-
|
|
845
|
-
return skeleton2;
|
|
1079
|
+
}); // don't create geometry if it is not associated with any models
|
|
1080
|
+
|
|
1081
|
+
if (modelNodes.length === 0) return;
|
|
1082
|
+
const skeleton = relationships.children.reduce(function (skeleton, child) {
|
|
1083
|
+
if (skeletons[child.ID] !== undefined) skeleton = skeletons[child.ID];
|
|
1084
|
+
return skeleton;
|
|
846
1085
|
}, null);
|
|
847
|
-
relationships.children.forEach(function(child) {
|
|
848
|
-
if (deformers.morphTargets[child.ID] !==
|
|
1086
|
+
relationships.children.forEach(function (child) {
|
|
1087
|
+
if (deformers.morphTargets[child.ID] !== undefined) {
|
|
849
1088
|
morphTargets.push(deformers.morphTargets[child.ID]);
|
|
850
1089
|
}
|
|
851
|
-
});
|
|
1090
|
+
}); // Assume one model and get the preRotation from that
|
|
1091
|
+
// if there is more than one model associated with the geometry this may cause problems
|
|
1092
|
+
|
|
852
1093
|
const modelNode = modelNodes[0];
|
|
853
1094
|
const transformData = {};
|
|
854
|
-
if (
|
|
855
|
-
|
|
856
|
-
if (
|
|
857
|
-
|
|
858
|
-
if (
|
|
859
|
-
transformData.translation = modelNode.GeometricTranslation.value;
|
|
860
|
-
if ("GeometricRotation" in modelNode)
|
|
861
|
-
transformData.rotation = modelNode.GeometricRotation.value;
|
|
862
|
-
if ("GeometricScaling" in modelNode)
|
|
863
|
-
transformData.scale = modelNode.GeometricScaling.value;
|
|
1095
|
+
if ('RotationOrder' in modelNode) transformData.eulerOrder = getEulerOrder(modelNode.RotationOrder.value);
|
|
1096
|
+
if ('InheritType' in modelNode) transformData.inheritType = parseInt(modelNode.InheritType.value);
|
|
1097
|
+
if ('GeometricTranslation' in modelNode) transformData.translation = modelNode.GeometricTranslation.value;
|
|
1098
|
+
if ('GeometricRotation' in modelNode) transformData.rotation = modelNode.GeometricRotation.value;
|
|
1099
|
+
if ('GeometricScaling' in modelNode) transformData.scale = modelNode.GeometricScaling.value;
|
|
864
1100
|
const transform = generateTransform(transformData);
|
|
865
1101
|
return this.genGeometry(geoNode, skeleton, morphTargets, transform);
|
|
866
|
-
}
|
|
1102
|
+
} // Generate a BufferGeometry from a node in FBXTree.Objects.Geometry
|
|
1103
|
+
|
|
1104
|
+
|
|
867
1105
|
genGeometry(geoNode, skeleton, morphTargets, preTransform) {
|
|
868
|
-
const geo = new
|
|
869
|
-
if (geoNode.attrName)
|
|
870
|
-
geo.name = geoNode.attrName;
|
|
1106
|
+
const geo = new BufferGeometry();
|
|
1107
|
+
if (geoNode.attrName) geo.name = geoNode.attrName;
|
|
871
1108
|
const geoInfo = this.parseGeoNode(geoNode, skeleton);
|
|
872
1109
|
const buffers = this.genBuffers(geoInfo);
|
|
873
|
-
const positionAttribute = new
|
|
1110
|
+
const positionAttribute = new Float32BufferAttribute(buffers.vertex, 3);
|
|
874
1111
|
positionAttribute.applyMatrix4(preTransform);
|
|
875
|
-
geo.setAttribute(
|
|
1112
|
+
geo.setAttribute('position', positionAttribute);
|
|
1113
|
+
|
|
876
1114
|
if (buffers.colors.length > 0) {
|
|
877
|
-
geo.setAttribute(
|
|
1115
|
+
geo.setAttribute('color', new Float32BufferAttribute(buffers.colors, 3));
|
|
878
1116
|
}
|
|
1117
|
+
|
|
879
1118
|
if (skeleton) {
|
|
880
|
-
geo.setAttribute(
|
|
881
|
-
geo.setAttribute(
|
|
1119
|
+
geo.setAttribute('skinIndex', new Uint16BufferAttribute(buffers.weightsIndices, 4));
|
|
1120
|
+
geo.setAttribute('skinWeight', new Float32BufferAttribute(buffers.vertexWeights, 4)); // used later to bind the skeleton to the model
|
|
1121
|
+
|
|
882
1122
|
geo.FBX_Deformer = skeleton;
|
|
883
1123
|
}
|
|
1124
|
+
|
|
884
1125
|
if (buffers.normal.length > 0) {
|
|
885
|
-
const normalMatrix = new
|
|
886
|
-
const normalAttribute = new
|
|
1126
|
+
const normalMatrix = new Matrix3().getNormalMatrix(preTransform);
|
|
1127
|
+
const normalAttribute = new Float32BufferAttribute(buffers.normal, 3);
|
|
887
1128
|
normalAttribute.applyNormalMatrix(normalMatrix);
|
|
888
|
-
geo.setAttribute(
|
|
1129
|
+
geo.setAttribute('normal', normalAttribute);
|
|
889
1130
|
}
|
|
890
|
-
|
|
891
|
-
|
|
1131
|
+
|
|
1132
|
+
buffers.uvs.forEach(function (uvBuffer, i) {
|
|
1133
|
+
// subsequent uv buffers are called 'uv1', 'uv2', ...
|
|
1134
|
+
let name = 'uv' + (i + 1).toString(); // the first uv buffer is just called 'uv'
|
|
1135
|
+
|
|
892
1136
|
if (i === 0) {
|
|
893
|
-
name =
|
|
1137
|
+
name = 'uv';
|
|
894
1138
|
}
|
|
895
|
-
|
|
1139
|
+
|
|
1140
|
+
geo.setAttribute(name, new Float32BufferAttribute(buffers.uvs[i], 2));
|
|
896
1141
|
});
|
|
897
|
-
|
|
1142
|
+
|
|
1143
|
+
if (geoInfo.material && geoInfo.material.mappingType !== 'AllSame') {
|
|
1144
|
+
// Convert the material indices of each vertex into rendering groups on the geometry.
|
|
898
1145
|
let prevMaterialIndex = buffers.materialIndex[0];
|
|
899
1146
|
let startIndex = 0;
|
|
900
|
-
buffers.materialIndex.forEach(function(currentIndex, i) {
|
|
1147
|
+
buffers.materialIndex.forEach(function (currentIndex, i) {
|
|
901
1148
|
if (currentIndex !== prevMaterialIndex) {
|
|
902
1149
|
geo.addGroup(startIndex, i - startIndex, prevMaterialIndex);
|
|
903
1150
|
prevMaterialIndex = currentIndex;
|
|
904
1151
|
startIndex = i;
|
|
905
1152
|
}
|
|
906
|
-
});
|
|
1153
|
+
}); // the loop above doesn't add the last group, do that here.
|
|
1154
|
+
|
|
907
1155
|
if (geo.groups.length > 0) {
|
|
908
1156
|
const lastGroup = geo.groups[geo.groups.length - 1];
|
|
909
1157
|
const lastIndex = lastGroup.start + lastGroup.count;
|
|
1158
|
+
|
|
910
1159
|
if (lastIndex !== buffers.materialIndex.length) {
|
|
911
1160
|
geo.addGroup(lastIndex, buffers.materialIndex.length - lastIndex, prevMaterialIndex);
|
|
912
1161
|
}
|
|
913
|
-
}
|
|
1162
|
+
} // case where there are multiple materials but the whole geometry is only
|
|
1163
|
+
// using one of them
|
|
1164
|
+
|
|
1165
|
+
|
|
914
1166
|
if (geo.groups.length === 0) {
|
|
915
1167
|
geo.addGroup(0, buffers.materialIndex.length, buffers.materialIndex[0]);
|
|
916
1168
|
}
|
|
917
1169
|
}
|
|
1170
|
+
|
|
918
1171
|
this.addMorphTargets(geo, geoNode, morphTargets, preTransform);
|
|
919
1172
|
return geo;
|
|
920
1173
|
}
|
|
1174
|
+
|
|
921
1175
|
parseGeoNode(geoNode, skeleton) {
|
|
922
1176
|
const geoInfo = {};
|
|
923
|
-
geoInfo.vertexPositions = geoNode.Vertices !==
|
|
924
|
-
geoInfo.vertexIndices = geoNode.PolygonVertexIndex !==
|
|
1177
|
+
geoInfo.vertexPositions = geoNode.Vertices !== undefined ? geoNode.Vertices.a : [];
|
|
1178
|
+
geoInfo.vertexIndices = geoNode.PolygonVertexIndex !== undefined ? geoNode.PolygonVertexIndex.a : [];
|
|
1179
|
+
|
|
925
1180
|
if (geoNode.LayerElementColor) {
|
|
926
1181
|
geoInfo.color = this.parseVertexColors(geoNode.LayerElementColor[0]);
|
|
927
1182
|
}
|
|
1183
|
+
|
|
928
1184
|
if (geoNode.LayerElementMaterial) {
|
|
929
1185
|
geoInfo.material = this.parseMaterialIndices(geoNode.LayerElementMaterial[0]);
|
|
930
1186
|
}
|
|
1187
|
+
|
|
931
1188
|
if (geoNode.LayerElementNormal) {
|
|
932
1189
|
geoInfo.normal = this.parseNormals(geoNode.LayerElementNormal[0]);
|
|
933
1190
|
}
|
|
1191
|
+
|
|
934
1192
|
if (geoNode.LayerElementUV) {
|
|
935
1193
|
geoInfo.uv = [];
|
|
936
1194
|
let i = 0;
|
|
1195
|
+
|
|
937
1196
|
while (geoNode.LayerElementUV[i]) {
|
|
938
1197
|
if (geoNode.LayerElementUV[i].UV) {
|
|
939
1198
|
geoInfo.uv.push(this.parseUVs(geoNode.LayerElementUV[i]));
|
|
940
1199
|
}
|
|
1200
|
+
|
|
941
1201
|
i++;
|
|
942
1202
|
}
|
|
943
1203
|
}
|
|
1204
|
+
|
|
944
1205
|
geoInfo.weightTable = {};
|
|
1206
|
+
|
|
945
1207
|
if (skeleton !== null) {
|
|
946
1208
|
geoInfo.skeleton = skeleton;
|
|
947
|
-
skeleton.rawBones.forEach(function(rawBone, i) {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1209
|
+
skeleton.rawBones.forEach(function (rawBone, i) {
|
|
1210
|
+
// loop over the bone's vertex indices and weights
|
|
1211
|
+
rawBone.indices.forEach(function (index, j) {
|
|
1212
|
+
if (geoInfo.weightTable[index] === undefined) geoInfo.weightTable[index] = [];
|
|
951
1213
|
geoInfo.weightTable[index].push({
|
|
952
1214
|
id: i,
|
|
953
1215
|
weight: rawBone.weights[j]
|
|
@@ -955,8 +1217,10 @@ class GeometryParser {
|
|
|
955
1217
|
});
|
|
956
1218
|
});
|
|
957
1219
|
}
|
|
1220
|
+
|
|
958
1221
|
return geoInfo;
|
|
959
1222
|
}
|
|
1223
|
+
|
|
960
1224
|
genBuffers(geoInfo) {
|
|
961
1225
|
const buffers = {
|
|
962
1226
|
vertex: [],
|
|
@@ -969,7 +1233,8 @@ class GeometryParser {
|
|
|
969
1233
|
};
|
|
970
1234
|
let polygonIndex = 0;
|
|
971
1235
|
let faceLength = 0;
|
|
972
|
-
let displayedWeightsWarning = false;
|
|
1236
|
+
let displayedWeightsWarning = false; // these will hold data for a single face
|
|
1237
|
+
|
|
973
1238
|
let facePositionIndexes = [];
|
|
974
1239
|
let faceNormals = [];
|
|
975
1240
|
let faceColors = [];
|
|
@@ -977,40 +1242,51 @@ class GeometryParser {
|
|
|
977
1242
|
let faceWeights = [];
|
|
978
1243
|
let faceWeightIndices = [];
|
|
979
1244
|
const scope = this;
|
|
980
|
-
geoInfo.vertexIndices.forEach(function(vertexIndex, polygonVertexIndex) {
|
|
1245
|
+
geoInfo.vertexIndices.forEach(function (vertexIndex, polygonVertexIndex) {
|
|
981
1246
|
let materialIndex;
|
|
982
|
-
let endOfFace = false;
|
|
1247
|
+
let endOfFace = false; // Face index and vertex index arrays are combined in a single array
|
|
1248
|
+
// A cube with quad faces looks like this:
|
|
1249
|
+
// PolygonVertexIndex: *24 {
|
|
1250
|
+
// 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
|
|
1251
|
+
// }
|
|
1252
|
+
// Negative numbers mark the end of a face - first face here is 0, 1, 3, -3
|
|
1253
|
+
// to find index of last vertex bit shift the index: ^ - 1
|
|
1254
|
+
|
|
983
1255
|
if (vertexIndex < 0) {
|
|
984
|
-
vertexIndex = vertexIndex ^ -1;
|
|
1256
|
+
vertexIndex = vertexIndex ^ -1; // equivalent to ( x * -1 ) - 1
|
|
1257
|
+
|
|
985
1258
|
endOfFace = true;
|
|
986
1259
|
}
|
|
1260
|
+
|
|
987
1261
|
let weightIndices = [];
|
|
988
1262
|
let weights = [];
|
|
989
1263
|
facePositionIndexes.push(vertexIndex * 3, vertexIndex * 3 + 1, vertexIndex * 3 + 2);
|
|
1264
|
+
|
|
990
1265
|
if (geoInfo.color) {
|
|
991
1266
|
const data = getData(polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.color);
|
|
992
1267
|
faceColors.push(data[0], data[1], data[2]);
|
|
993
1268
|
}
|
|
1269
|
+
|
|
994
1270
|
if (geoInfo.skeleton) {
|
|
995
|
-
if (geoInfo.weightTable[vertexIndex] !==
|
|
996
|
-
geoInfo.weightTable[vertexIndex].forEach(function(wt) {
|
|
1271
|
+
if (geoInfo.weightTable[vertexIndex] !== undefined) {
|
|
1272
|
+
geoInfo.weightTable[vertexIndex].forEach(function (wt) {
|
|
997
1273
|
weights.push(wt.weight);
|
|
998
1274
|
weightIndices.push(wt.id);
|
|
999
1275
|
});
|
|
1000
1276
|
}
|
|
1277
|
+
|
|
1001
1278
|
if (weights.length > 4) {
|
|
1002
1279
|
if (!displayedWeightsWarning) {
|
|
1003
|
-
console.warn(
|
|
1004
|
-
"THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights."
|
|
1005
|
-
);
|
|
1280
|
+
console.warn('THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights.');
|
|
1006
1281
|
displayedWeightsWarning = true;
|
|
1007
1282
|
}
|
|
1283
|
+
|
|
1008
1284
|
const wIndex = [0, 0, 0, 0];
|
|
1009
1285
|
const Weight = [0, 0, 0, 0];
|
|
1010
|
-
weights.forEach(function(weight, weightIndex) {
|
|
1286
|
+
weights.forEach(function (weight, weightIndex) {
|
|
1011
1287
|
let currentWeight = weight;
|
|
1012
1288
|
let currentIndex = weightIndices[weightIndex];
|
|
1013
|
-
Weight.forEach(function(comparedWeight, comparedWeightIndex, comparedWeightArray) {
|
|
1289
|
+
Weight.forEach(function (comparedWeight, comparedWeightIndex, comparedWeightArray) {
|
|
1014
1290
|
if (currentWeight > comparedWeight) {
|
|
1015
1291
|
comparedWeightArray[comparedWeightIndex] = currentWeight;
|
|
1016
1292
|
currentWeight = comparedWeight;
|
|
@@ -1022,49 +1298,49 @@ class GeometryParser {
|
|
|
1022
1298
|
});
|
|
1023
1299
|
weightIndices = wIndex;
|
|
1024
1300
|
weights = Weight;
|
|
1025
|
-
}
|
|
1301
|
+
} // if the weight array is shorter than 4 pad with 0s
|
|
1302
|
+
|
|
1303
|
+
|
|
1026
1304
|
while (weights.length < 4) {
|
|
1027
1305
|
weights.push(0);
|
|
1028
1306
|
weightIndices.push(0);
|
|
1029
1307
|
}
|
|
1308
|
+
|
|
1030
1309
|
for (let i = 0; i < 4; ++i) {
|
|
1031
1310
|
faceWeights.push(weights[i]);
|
|
1032
1311
|
faceWeightIndices.push(weightIndices[i]);
|
|
1033
1312
|
}
|
|
1034
1313
|
}
|
|
1314
|
+
|
|
1035
1315
|
if (geoInfo.normal) {
|
|
1036
1316
|
const data = getData(polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.normal);
|
|
1037
1317
|
faceNormals.push(data[0], data[1], data[2]);
|
|
1038
1318
|
}
|
|
1039
|
-
|
|
1319
|
+
|
|
1320
|
+
if (geoInfo.material && geoInfo.material.mappingType !== 'AllSame') {
|
|
1040
1321
|
materialIndex = getData(polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material)[0];
|
|
1041
1322
|
}
|
|
1323
|
+
|
|
1042
1324
|
if (geoInfo.uv) {
|
|
1043
|
-
geoInfo.uv.forEach(function(uv, i) {
|
|
1325
|
+
geoInfo.uv.forEach(function (uv, i) {
|
|
1044
1326
|
const data = getData(polygonVertexIndex, polygonIndex, vertexIndex, uv);
|
|
1045
|
-
|
|
1327
|
+
|
|
1328
|
+
if (faceUVs[i] === undefined) {
|
|
1046
1329
|
faceUVs[i] = [];
|
|
1047
1330
|
}
|
|
1331
|
+
|
|
1048
1332
|
faceUVs[i].push(data[0]);
|
|
1049
1333
|
faceUVs[i].push(data[1]);
|
|
1050
1334
|
});
|
|
1051
1335
|
}
|
|
1336
|
+
|
|
1052
1337
|
faceLength++;
|
|
1338
|
+
|
|
1053
1339
|
if (endOfFace) {
|
|
1054
|
-
scope.genFace(
|
|
1055
|
-
buffers,
|
|
1056
|
-
geoInfo,
|
|
1057
|
-
facePositionIndexes,
|
|
1058
|
-
materialIndex,
|
|
1059
|
-
faceNormals,
|
|
1060
|
-
faceColors,
|
|
1061
|
-
faceUVs,
|
|
1062
|
-
faceWeights,
|
|
1063
|
-
faceWeightIndices,
|
|
1064
|
-
faceLength
|
|
1065
|
-
);
|
|
1340
|
+
scope.genFace(buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength);
|
|
1066
1341
|
polygonIndex++;
|
|
1067
|
-
faceLength = 0;
|
|
1342
|
+
faceLength = 0; // reset arrays for the next face
|
|
1343
|
+
|
|
1068
1344
|
facePositionIndexes = [];
|
|
1069
1345
|
faceNormals = [];
|
|
1070
1346
|
faceColors = [];
|
|
@@ -1074,7 +1350,9 @@ class GeometryParser {
|
|
|
1074
1350
|
}
|
|
1075
1351
|
});
|
|
1076
1352
|
return buffers;
|
|
1077
|
-
}
|
|
1353
|
+
} // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris
|
|
1354
|
+
|
|
1355
|
+
|
|
1078
1356
|
genFace(buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength) {
|
|
1079
1357
|
for (let i = 2; i < faceLength; i++) {
|
|
1080
1358
|
buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[0]]);
|
|
@@ -1086,6 +1364,7 @@ class GeometryParser {
|
|
|
1086
1364
|
buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[i * 3]]);
|
|
1087
1365
|
buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[i * 3 + 1]]);
|
|
1088
1366
|
buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[i * 3 + 2]]);
|
|
1367
|
+
|
|
1089
1368
|
if (geoInfo.skeleton) {
|
|
1090
1369
|
buffers.vertexWeights.push(faceWeights[0]);
|
|
1091
1370
|
buffers.vertexWeights.push(faceWeights[1]);
|
|
@@ -1112,6 +1391,7 @@ class GeometryParser {
|
|
|
1112
1391
|
buffers.weightsIndices.push(faceWeightIndices[i * 4 + 2]);
|
|
1113
1392
|
buffers.weightsIndices.push(faceWeightIndices[i * 4 + 3]);
|
|
1114
1393
|
}
|
|
1394
|
+
|
|
1115
1395
|
if (geoInfo.color) {
|
|
1116
1396
|
buffers.colors.push(faceColors[0]);
|
|
1117
1397
|
buffers.colors.push(faceColors[1]);
|
|
@@ -1123,11 +1403,13 @@ class GeometryParser {
|
|
|
1123
1403
|
buffers.colors.push(faceColors[i * 3 + 1]);
|
|
1124
1404
|
buffers.colors.push(faceColors[i * 3 + 2]);
|
|
1125
1405
|
}
|
|
1126
|
-
|
|
1406
|
+
|
|
1407
|
+
if (geoInfo.material && geoInfo.material.mappingType !== 'AllSame') {
|
|
1127
1408
|
buffers.materialIndex.push(materialIndex);
|
|
1128
1409
|
buffers.materialIndex.push(materialIndex);
|
|
1129
1410
|
buffers.materialIndex.push(materialIndex);
|
|
1130
1411
|
}
|
|
1412
|
+
|
|
1131
1413
|
if (geoInfo.normal) {
|
|
1132
1414
|
buffers.normal.push(faceNormals[0]);
|
|
1133
1415
|
buffers.normal.push(faceNormals[1]);
|
|
@@ -1139,10 +1421,10 @@ class GeometryParser {
|
|
|
1139
1421
|
buffers.normal.push(faceNormals[i * 3 + 1]);
|
|
1140
1422
|
buffers.normal.push(faceNormals[i * 3 + 2]);
|
|
1141
1423
|
}
|
|
1424
|
+
|
|
1142
1425
|
if (geoInfo.uv) {
|
|
1143
|
-
geoInfo.uv.forEach(function(uv, j) {
|
|
1144
|
-
if (buffers.uvs[j] ===
|
|
1145
|
-
buffers.uvs[j] = [];
|
|
1426
|
+
geoInfo.uv.forEach(function (uv, j) {
|
|
1427
|
+
if (buffers.uvs[j] === undefined) buffers.uvs[j] = [];
|
|
1146
1428
|
buffers.uvs[j].push(faceUVs[j][0]);
|
|
1147
1429
|
buffers.uvs[j].push(faceUVs[j][1]);
|
|
1148
1430
|
buffers.uvs[j].push(faceUVs[j][(i - 1) * 2]);
|
|
@@ -1153,181 +1435,234 @@ class GeometryParser {
|
|
|
1153
1435
|
}
|
|
1154
1436
|
}
|
|
1155
1437
|
}
|
|
1438
|
+
|
|
1156
1439
|
addMorphTargets(parentGeo, parentGeoNode, morphTargets, preTransform) {
|
|
1157
|
-
if (morphTargets.length === 0)
|
|
1158
|
-
return;
|
|
1440
|
+
if (morphTargets.length === 0) return;
|
|
1159
1441
|
parentGeo.morphTargetsRelative = true;
|
|
1160
|
-
parentGeo.morphAttributes.position = [];
|
|
1442
|
+
parentGeo.morphAttributes.position = []; // parentGeo.morphAttributes.normal = []; // not implemented
|
|
1443
|
+
|
|
1161
1444
|
const scope = this;
|
|
1162
|
-
morphTargets.forEach(function(morphTarget) {
|
|
1163
|
-
morphTarget.rawTargets.forEach(function(rawTarget) {
|
|
1445
|
+
morphTargets.forEach(function (morphTarget) {
|
|
1446
|
+
morphTarget.rawTargets.forEach(function (rawTarget) {
|
|
1164
1447
|
const morphGeoNode = fbxTree.Objects.Geometry[rawTarget.geoID];
|
|
1165
|
-
|
|
1448
|
+
|
|
1449
|
+
if (morphGeoNode !== undefined) {
|
|
1166
1450
|
scope.genMorphGeometry(parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name);
|
|
1167
1451
|
}
|
|
1168
1452
|
});
|
|
1169
1453
|
});
|
|
1170
|
-
}
|
|
1454
|
+
} // a morph geometry node is similar to a standard node, and the node is also contained
|
|
1455
|
+
// in FBXTree.Objects.Geometry, however it can only have attributes for position, normal
|
|
1456
|
+
// and a special attribute Index defining which vertices of the original geometry are affected
|
|
1457
|
+
// Normal and position attributes only have data for the vertices that are affected by the morph
|
|
1458
|
+
|
|
1459
|
+
|
|
1171
1460
|
genMorphGeometry(parentGeo, parentGeoNode, morphGeoNode, preTransform, name) {
|
|
1172
|
-
const vertexIndices = parentGeoNode.PolygonVertexIndex !==
|
|
1173
|
-
const morphPositionsSparse = morphGeoNode.Vertices !==
|
|
1174
|
-
const indices = morphGeoNode.Indexes !==
|
|
1461
|
+
const vertexIndices = parentGeoNode.PolygonVertexIndex !== undefined ? parentGeoNode.PolygonVertexIndex.a : [];
|
|
1462
|
+
const morphPositionsSparse = morphGeoNode.Vertices !== undefined ? morphGeoNode.Vertices.a : [];
|
|
1463
|
+
const indices = morphGeoNode.Indexes !== undefined ? morphGeoNode.Indexes.a : [];
|
|
1175
1464
|
const length = parentGeo.attributes.position.count * 3;
|
|
1176
1465
|
const morphPositions = new Float32Array(length);
|
|
1466
|
+
|
|
1177
1467
|
for (let i = 0; i < indices.length; i++) {
|
|
1178
1468
|
const morphIndex = indices[i] * 3;
|
|
1179
1469
|
morphPositions[morphIndex] = morphPositionsSparse[i * 3];
|
|
1180
1470
|
morphPositions[morphIndex + 1] = morphPositionsSparse[i * 3 + 1];
|
|
1181
1471
|
morphPositions[morphIndex + 2] = morphPositionsSparse[i * 3 + 2];
|
|
1182
|
-
}
|
|
1472
|
+
} // TODO: add morph normal support
|
|
1473
|
+
|
|
1474
|
+
|
|
1183
1475
|
const morphGeoInfo = {
|
|
1184
|
-
vertexIndices,
|
|
1476
|
+
vertexIndices: vertexIndices,
|
|
1185
1477
|
vertexPositions: morphPositions
|
|
1186
1478
|
};
|
|
1187
1479
|
const morphBuffers = this.genBuffers(morphGeoInfo);
|
|
1188
|
-
const positionAttribute = new
|
|
1480
|
+
const positionAttribute = new Float32BufferAttribute(morphBuffers.vertex, 3);
|
|
1189
1481
|
positionAttribute.name = name || morphGeoNode.attrName;
|
|
1190
1482
|
positionAttribute.applyMatrix4(preTransform);
|
|
1191
1483
|
parentGeo.morphAttributes.position.push(positionAttribute);
|
|
1192
|
-
}
|
|
1484
|
+
} // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists
|
|
1485
|
+
|
|
1486
|
+
|
|
1193
1487
|
parseNormals(NormalNode) {
|
|
1194
1488
|
const mappingType = NormalNode.MappingInformationType;
|
|
1195
1489
|
const referenceType = NormalNode.ReferenceInformationType;
|
|
1196
1490
|
const buffer = NormalNode.Normals.a;
|
|
1197
1491
|
let indexBuffer = [];
|
|
1198
|
-
|
|
1199
|
-
|
|
1492
|
+
|
|
1493
|
+
if (referenceType === 'IndexToDirect') {
|
|
1494
|
+
if ('NormalIndex' in NormalNode) {
|
|
1200
1495
|
indexBuffer = NormalNode.NormalIndex.a;
|
|
1201
|
-
} else if (
|
|
1496
|
+
} else if ('NormalsIndex' in NormalNode) {
|
|
1202
1497
|
indexBuffer = NormalNode.NormalsIndex.a;
|
|
1203
1498
|
}
|
|
1204
1499
|
}
|
|
1500
|
+
|
|
1205
1501
|
return {
|
|
1206
1502
|
dataSize: 3,
|
|
1207
|
-
buffer,
|
|
1503
|
+
buffer: buffer,
|
|
1208
1504
|
indices: indexBuffer,
|
|
1209
|
-
mappingType,
|
|
1210
|
-
referenceType
|
|
1505
|
+
mappingType: mappingType,
|
|
1506
|
+
referenceType: referenceType
|
|
1211
1507
|
};
|
|
1212
|
-
}
|
|
1508
|
+
} // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists
|
|
1509
|
+
|
|
1510
|
+
|
|
1213
1511
|
parseUVs(UVNode) {
|
|
1214
1512
|
const mappingType = UVNode.MappingInformationType;
|
|
1215
1513
|
const referenceType = UVNode.ReferenceInformationType;
|
|
1216
1514
|
const buffer = UVNode.UV.a;
|
|
1217
1515
|
let indexBuffer = [];
|
|
1218
|
-
|
|
1516
|
+
|
|
1517
|
+
if (referenceType === 'IndexToDirect') {
|
|
1219
1518
|
indexBuffer = UVNode.UVIndex.a;
|
|
1220
1519
|
}
|
|
1520
|
+
|
|
1221
1521
|
return {
|
|
1222
1522
|
dataSize: 2,
|
|
1223
|
-
buffer,
|
|
1523
|
+
buffer: buffer,
|
|
1224
1524
|
indices: indexBuffer,
|
|
1225
|
-
mappingType,
|
|
1226
|
-
referenceType
|
|
1525
|
+
mappingType: mappingType,
|
|
1526
|
+
referenceType: referenceType
|
|
1227
1527
|
};
|
|
1228
|
-
}
|
|
1528
|
+
} // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists
|
|
1529
|
+
|
|
1530
|
+
|
|
1229
1531
|
parseVertexColors(ColorNode) {
|
|
1230
1532
|
const mappingType = ColorNode.MappingInformationType;
|
|
1231
1533
|
const referenceType = ColorNode.ReferenceInformationType;
|
|
1232
1534
|
const buffer = ColorNode.Colors.a;
|
|
1233
1535
|
let indexBuffer = [];
|
|
1234
|
-
|
|
1536
|
+
|
|
1537
|
+
if (referenceType === 'IndexToDirect') {
|
|
1235
1538
|
indexBuffer = ColorNode.ColorIndex.a;
|
|
1236
1539
|
}
|
|
1540
|
+
|
|
1237
1541
|
return {
|
|
1238
1542
|
dataSize: 4,
|
|
1239
|
-
buffer,
|
|
1543
|
+
buffer: buffer,
|
|
1240
1544
|
indices: indexBuffer,
|
|
1241
|
-
mappingType,
|
|
1242
|
-
referenceType
|
|
1545
|
+
mappingType: mappingType,
|
|
1546
|
+
referenceType: referenceType
|
|
1243
1547
|
};
|
|
1244
|
-
}
|
|
1548
|
+
} // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists
|
|
1549
|
+
|
|
1550
|
+
|
|
1245
1551
|
parseMaterialIndices(MaterialNode) {
|
|
1246
1552
|
const mappingType = MaterialNode.MappingInformationType;
|
|
1247
1553
|
const referenceType = MaterialNode.ReferenceInformationType;
|
|
1248
|
-
|
|
1554
|
+
|
|
1555
|
+
if (mappingType === 'NoMappingInformation') {
|
|
1249
1556
|
return {
|
|
1250
1557
|
dataSize: 1,
|
|
1251
1558
|
buffer: [0],
|
|
1252
1559
|
indices: [0],
|
|
1253
|
-
mappingType:
|
|
1254
|
-
referenceType
|
|
1560
|
+
mappingType: 'AllSame',
|
|
1561
|
+
referenceType: referenceType
|
|
1255
1562
|
};
|
|
1256
1563
|
}
|
|
1257
|
-
|
|
1564
|
+
|
|
1565
|
+
const materialIndexBuffer = MaterialNode.Materials.a; // Since materials are stored as indices, there's a bit of a mismatch between FBX and what
|
|
1566
|
+
// we expect.So we create an intermediate buffer that points to the index in the buffer,
|
|
1567
|
+
// for conforming with the other functions we've written for other data.
|
|
1568
|
+
|
|
1258
1569
|
const materialIndices = [];
|
|
1570
|
+
|
|
1259
1571
|
for (let i = 0; i < materialIndexBuffer.length; ++i) {
|
|
1260
1572
|
materialIndices.push(i);
|
|
1261
1573
|
}
|
|
1574
|
+
|
|
1262
1575
|
return {
|
|
1263
1576
|
dataSize: 1,
|
|
1264
1577
|
buffer: materialIndexBuffer,
|
|
1265
1578
|
indices: materialIndices,
|
|
1266
|
-
mappingType,
|
|
1267
|
-
referenceType
|
|
1579
|
+
mappingType: mappingType,
|
|
1580
|
+
referenceType: referenceType
|
|
1268
1581
|
};
|
|
1269
|
-
}
|
|
1582
|
+
} // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry
|
|
1583
|
+
|
|
1584
|
+
|
|
1270
1585
|
parseNurbsGeometry(geoNode) {
|
|
1271
|
-
if (NURBSCurve
|
|
1272
|
-
console.error(
|
|
1273
|
-
|
|
1274
|
-
);
|
|
1275
|
-
return new THREE.BufferGeometry();
|
|
1586
|
+
if (NURBSCurve === undefined) {
|
|
1587
|
+
console.error('THREE.FBXLoader: The loader relies on NURBSCurve for any nurbs present in the model. Nurbs will show up as empty geometry.');
|
|
1588
|
+
return new BufferGeometry();
|
|
1276
1589
|
}
|
|
1590
|
+
|
|
1277
1591
|
const order = parseInt(geoNode.Order);
|
|
1592
|
+
|
|
1278
1593
|
if (isNaN(order)) {
|
|
1279
|
-
console.error(
|
|
1280
|
-
return new
|
|
1594
|
+
console.error('THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geoNode.Order, geoNode.id);
|
|
1595
|
+
return new BufferGeometry();
|
|
1281
1596
|
}
|
|
1597
|
+
|
|
1282
1598
|
const degree = order - 1;
|
|
1283
1599
|
const knots = geoNode.KnotVector.a;
|
|
1284
1600
|
const controlPoints = [];
|
|
1285
1601
|
const pointsValues = geoNode.Points.a;
|
|
1602
|
+
|
|
1286
1603
|
for (let i = 0, l = pointsValues.length; i < l; i += 4) {
|
|
1287
|
-
controlPoints.push(new
|
|
1604
|
+
controlPoints.push(new Vector4().fromArray(pointsValues, i));
|
|
1288
1605
|
}
|
|
1606
|
+
|
|
1289
1607
|
let startKnot, endKnot;
|
|
1290
|
-
|
|
1608
|
+
|
|
1609
|
+
if (geoNode.Form === 'Closed') {
|
|
1291
1610
|
controlPoints.push(controlPoints[0]);
|
|
1292
|
-
} else if (geoNode.Form ===
|
|
1611
|
+
} else if (geoNode.Form === 'Periodic') {
|
|
1293
1612
|
startKnot = degree;
|
|
1294
1613
|
endKnot = knots.length - 1 - startKnot;
|
|
1614
|
+
|
|
1295
1615
|
for (let i = 0; i < degree; ++i) {
|
|
1296
1616
|
controlPoints.push(controlPoints[i]);
|
|
1297
1617
|
}
|
|
1298
1618
|
}
|
|
1299
|
-
|
|
1619
|
+
|
|
1620
|
+
const curve = new NURBSCurve(degree, knots, controlPoints, startKnot, endKnot);
|
|
1300
1621
|
const points = curve.getPoints(controlPoints.length * 12);
|
|
1301
|
-
return new
|
|
1622
|
+
return new BufferGeometry().setFromPoints(points);
|
|
1302
1623
|
}
|
|
1303
|
-
|
|
1624
|
+
|
|
1625
|
+
} // parse animation data from FBXTree
|
|
1626
|
+
|
|
1627
|
+
|
|
1304
1628
|
class AnimationParser {
|
|
1629
|
+
// take raw animation clips and turn them into three.js animation clips
|
|
1305
1630
|
parse() {
|
|
1306
1631
|
const animationClips = [];
|
|
1307
1632
|
const rawClips = this.parseClips();
|
|
1308
|
-
|
|
1633
|
+
|
|
1634
|
+
if (rawClips !== undefined) {
|
|
1309
1635
|
for (const key in rawClips) {
|
|
1310
1636
|
const rawClip = rawClips[key];
|
|
1311
1637
|
const clip = this.addClip(rawClip);
|
|
1312
1638
|
animationClips.push(clip);
|
|
1313
1639
|
}
|
|
1314
1640
|
}
|
|
1641
|
+
|
|
1315
1642
|
return animationClips;
|
|
1316
1643
|
}
|
|
1644
|
+
|
|
1317
1645
|
parseClips() {
|
|
1318
|
-
|
|
1319
|
-
|
|
1646
|
+
// since the actual transformation data is stored in FBXTree.Objects.AnimationCurve,
|
|
1647
|
+
// if this is undefined we can safely assume there are no animations
|
|
1648
|
+
if (fbxTree.Objects.AnimationCurve === undefined) return undefined;
|
|
1320
1649
|
const curveNodesMap = this.parseAnimationCurveNodes();
|
|
1321
1650
|
this.parseAnimationCurves(curveNodesMap);
|
|
1322
1651
|
const layersMap = this.parseAnimationLayers(curveNodesMap);
|
|
1323
1652
|
const rawClips = this.parseAnimStacks(layersMap);
|
|
1324
1653
|
return rawClips;
|
|
1325
|
-
}
|
|
1654
|
+
} // parse nodes in FBXTree.Objects.AnimationCurveNode
|
|
1655
|
+
// each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation )
|
|
1656
|
+
// and is referenced by an AnimationLayer
|
|
1657
|
+
|
|
1658
|
+
|
|
1326
1659
|
parseAnimationCurveNodes() {
|
|
1327
1660
|
const rawCurveNodes = fbxTree.Objects.AnimationCurveNode;
|
|
1328
|
-
const curveNodesMap =
|
|
1661
|
+
const curveNodesMap = new Map();
|
|
1662
|
+
|
|
1329
1663
|
for (const nodeID in rawCurveNodes) {
|
|
1330
1664
|
const rawCurveNode = rawCurveNodes[nodeID];
|
|
1665
|
+
|
|
1331
1666
|
if (rawCurveNode.attrName.match(/S|R|T|DeformPercent/) !== null) {
|
|
1332
1667
|
const curveNode = {
|
|
1333
1668
|
id: rawCurveNode.id,
|
|
@@ -1337,10 +1672,21 @@ class AnimationParser {
|
|
|
1337
1672
|
curveNodesMap.set(curveNode.id, curveNode);
|
|
1338
1673
|
}
|
|
1339
1674
|
}
|
|
1675
|
+
|
|
1340
1676
|
return curveNodesMap;
|
|
1341
|
-
}
|
|
1677
|
+
} // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to
|
|
1678
|
+
// previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated
|
|
1679
|
+
// axis ( e.g. times and values of x rotation)
|
|
1680
|
+
|
|
1681
|
+
|
|
1342
1682
|
parseAnimationCurves(curveNodesMap) {
|
|
1343
|
-
const rawCurves = fbxTree.Objects.AnimationCurve;
|
|
1683
|
+
const rawCurves = fbxTree.Objects.AnimationCurve; // TODO: Many values are identical up to roundoff error, but won't be optimised
|
|
1684
|
+
// e.g. position times: [0, 0.4, 0. 8]
|
|
1685
|
+
// position values: [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.235384487103147e-7, 93.67520904541016, -0.9982695579528809]
|
|
1686
|
+
// clearly, this should be optimised to
|
|
1687
|
+
// times: [0], positions [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809]
|
|
1688
|
+
// this shows up in nearly every FBX file, and generally time array is length > 100
|
|
1689
|
+
|
|
1344
1690
|
for (const nodeID in rawCurves) {
|
|
1345
1691
|
const animationCurve = {
|
|
1346
1692
|
id: rawCurves[nodeID].id,
|
|
@@ -1348,83 +1694,96 @@ class AnimationParser {
|
|
|
1348
1694
|
values: rawCurves[nodeID].KeyValueFloat.a
|
|
1349
1695
|
};
|
|
1350
1696
|
const relationships = connections.get(animationCurve.id);
|
|
1351
|
-
|
|
1697
|
+
|
|
1698
|
+
if (relationships !== undefined) {
|
|
1352
1699
|
const animationCurveID = relationships.parents[0].ID;
|
|
1353
1700
|
const animationCurveRelationship = relationships.parents[0].relationship;
|
|
1701
|
+
|
|
1354
1702
|
if (animationCurveRelationship.match(/X/)) {
|
|
1355
|
-
curveNodesMap.get(animationCurveID).curves[
|
|
1703
|
+
curveNodesMap.get(animationCurveID).curves['x'] = animationCurve;
|
|
1356
1704
|
} else if (animationCurveRelationship.match(/Y/)) {
|
|
1357
|
-
curveNodesMap.get(animationCurveID).curves[
|
|
1705
|
+
curveNodesMap.get(animationCurveID).curves['y'] = animationCurve;
|
|
1358
1706
|
} else if (animationCurveRelationship.match(/Z/)) {
|
|
1359
|
-
curveNodesMap.get(animationCurveID).curves[
|
|
1707
|
+
curveNodesMap.get(animationCurveID).curves['z'] = animationCurve;
|
|
1360
1708
|
} else if (animationCurveRelationship.match(/d|DeformPercent/) && curveNodesMap.has(animationCurveID)) {
|
|
1361
|
-
curveNodesMap.get(animationCurveID).curves[
|
|
1709
|
+
curveNodesMap.get(animationCurveID).curves['morph'] = animationCurve;
|
|
1362
1710
|
}
|
|
1363
1711
|
}
|
|
1364
1712
|
}
|
|
1365
|
-
}
|
|
1713
|
+
} // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references
|
|
1714
|
+
// to various AnimationCurveNodes and is referenced by an AnimationStack node
|
|
1715
|
+
// note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack
|
|
1716
|
+
|
|
1717
|
+
|
|
1366
1718
|
parseAnimationLayers(curveNodesMap) {
|
|
1367
1719
|
const rawLayers = fbxTree.Objects.AnimationLayer;
|
|
1368
|
-
const layersMap =
|
|
1720
|
+
const layersMap = new Map();
|
|
1721
|
+
|
|
1369
1722
|
for (const nodeID in rawLayers) {
|
|
1370
1723
|
const layerCurveNodes = [];
|
|
1371
1724
|
const connection = connections.get(parseInt(nodeID));
|
|
1372
|
-
|
|
1725
|
+
|
|
1726
|
+
if (connection !== undefined) {
|
|
1727
|
+
// all the animationCurveNodes used in the layer
|
|
1373
1728
|
const children = connection.children;
|
|
1374
|
-
children.forEach(function(child, i) {
|
|
1729
|
+
children.forEach(function (child, i) {
|
|
1375
1730
|
if (curveNodesMap.has(child.ID)) {
|
|
1376
|
-
const curveNode = curveNodesMap.get(child.ID);
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1731
|
+
const curveNode = curveNodesMap.get(child.ID); // check that the curves are defined for at least one axis, otherwise ignore the curveNode
|
|
1732
|
+
|
|
1733
|
+
if (curveNode.curves.x !== undefined || curveNode.curves.y !== undefined || curveNode.curves.z !== undefined) {
|
|
1734
|
+
if (layerCurveNodes[i] === undefined) {
|
|
1735
|
+
const modelID = connections.get(child.ID).parents.filter(function (parent) {
|
|
1736
|
+
return parent.relationship !== undefined;
|
|
1381
1737
|
})[0].ID;
|
|
1382
|
-
|
|
1738
|
+
|
|
1739
|
+
if (modelID !== undefined) {
|
|
1383
1740
|
const rawModel = fbxTree.Objects.Model[modelID.toString()];
|
|
1384
|
-
|
|
1385
|
-
|
|
1741
|
+
|
|
1742
|
+
if (rawModel === undefined) {
|
|
1743
|
+
console.warn('THREE.FBXLoader: Encountered a unused curve.', child);
|
|
1386
1744
|
return;
|
|
1387
1745
|
}
|
|
1746
|
+
|
|
1388
1747
|
const node = {
|
|
1389
|
-
modelName: rawModel.attrName ?
|
|
1748
|
+
modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName(rawModel.attrName) : '',
|
|
1390
1749
|
ID: rawModel.id,
|
|
1391
1750
|
initialPosition: [0, 0, 0],
|
|
1392
1751
|
initialRotation: [0, 0, 0],
|
|
1393
1752
|
initialScale: [1, 1, 1]
|
|
1394
1753
|
};
|
|
1395
|
-
sceneGraph.traverse(function(
|
|
1396
|
-
if (
|
|
1397
|
-
node.transform =
|
|
1398
|
-
if (
|
|
1399
|
-
node.eulerOrder = child2.userData.transformData.eulerOrder;
|
|
1754
|
+
sceneGraph.traverse(function (child) {
|
|
1755
|
+
if (child.ID === rawModel.id) {
|
|
1756
|
+
node.transform = child.matrix;
|
|
1757
|
+
if (child.userData.transformData) node.eulerOrder = child.userData.transformData.eulerOrder;
|
|
1400
1758
|
}
|
|
1401
1759
|
});
|
|
1402
|
-
if (!node.transform)
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
if (
|
|
1407
|
-
node.postRotation = rawModel.PostRotation.value;
|
|
1760
|
+
if (!node.transform) node.transform = new Matrix4(); // if the animated model is pre rotated, we'll have to apply the pre rotations to every
|
|
1761
|
+
// animation value as well
|
|
1762
|
+
|
|
1763
|
+
if ('PreRotation' in rawModel) node.preRotation = rawModel.PreRotation.value;
|
|
1764
|
+
if ('PostRotation' in rawModel) node.postRotation = rawModel.PostRotation.value;
|
|
1408
1765
|
layerCurveNodes[i] = node;
|
|
1409
1766
|
}
|
|
1410
1767
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
} else if (curveNode.curves.morph !==
|
|
1414
|
-
if (layerCurveNodes[i] ===
|
|
1415
|
-
const deformerID = connections.get(child.ID).parents.filter(function(parent) {
|
|
1416
|
-
return parent.relationship !==
|
|
1768
|
+
|
|
1769
|
+
if (layerCurveNodes[i]) layerCurveNodes[i][curveNode.attr] = curveNode;
|
|
1770
|
+
} else if (curveNode.curves.morph !== undefined) {
|
|
1771
|
+
if (layerCurveNodes[i] === undefined) {
|
|
1772
|
+
const deformerID = connections.get(child.ID).parents.filter(function (parent) {
|
|
1773
|
+
return parent.relationship !== undefined;
|
|
1417
1774
|
})[0].ID;
|
|
1418
1775
|
const morpherID = connections.get(deformerID).parents[0].ID;
|
|
1419
|
-
const geoID = connections.get(morpherID).parents[0].ID;
|
|
1776
|
+
const geoID = connections.get(morpherID).parents[0].ID; // assuming geometry is not used in more than one model
|
|
1777
|
+
|
|
1420
1778
|
const modelID = connections.get(geoID).parents[0].ID;
|
|
1421
1779
|
const rawModel = fbxTree.Objects.Model[modelID];
|
|
1422
1780
|
const node = {
|
|
1423
|
-
modelName: rawModel.attrName ?
|
|
1781
|
+
modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName(rawModel.attrName) : '',
|
|
1424
1782
|
morphName: fbxTree.Objects.Deformer[deformerID].attrName
|
|
1425
1783
|
};
|
|
1426
1784
|
layerCurveNodes[i] = node;
|
|
1427
1785
|
}
|
|
1786
|
+
|
|
1428
1787
|
layerCurveNodes[i][curveNode.attr] = curveNode;
|
|
1429
1788
|
}
|
|
1430
1789
|
}
|
|
@@ -1432,182 +1791,194 @@ class AnimationParser {
|
|
|
1432
1791
|
layersMap.set(parseInt(nodeID), layerCurveNodes);
|
|
1433
1792
|
}
|
|
1434
1793
|
}
|
|
1794
|
+
|
|
1435
1795
|
return layersMap;
|
|
1436
|
-
}
|
|
1796
|
+
} // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation
|
|
1797
|
+
// hierarchy. Each Stack node will be used to create a AnimationClip
|
|
1798
|
+
|
|
1799
|
+
|
|
1437
1800
|
parseAnimStacks(layersMap) {
|
|
1438
|
-
const rawStacks = fbxTree.Objects.AnimationStack;
|
|
1801
|
+
const rawStacks = fbxTree.Objects.AnimationStack; // connect the stacks (clips) up to the layers
|
|
1802
|
+
|
|
1439
1803
|
const rawClips = {};
|
|
1804
|
+
|
|
1440
1805
|
for (const nodeID in rawStacks) {
|
|
1441
1806
|
const children = connections.get(parseInt(nodeID)).children;
|
|
1807
|
+
|
|
1442
1808
|
if (children.length > 1) {
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
);
|
|
1809
|
+
// it seems like stacks will always be associated with a single layer. But just in case there are files
|
|
1810
|
+
// where there are multiple layers per stack, we'll display a warning
|
|
1811
|
+
console.warn('THREE.FBXLoader: Encountered an animation stack with multiple layers, this is currently not supported. Ignoring subsequent layers.');
|
|
1446
1812
|
}
|
|
1813
|
+
|
|
1447
1814
|
const layer = layersMap.get(children[0].ID);
|
|
1448
1815
|
rawClips[nodeID] = {
|
|
1449
1816
|
name: rawStacks[nodeID].attrName,
|
|
1450
|
-
layer
|
|
1817
|
+
layer: layer
|
|
1451
1818
|
};
|
|
1452
1819
|
}
|
|
1820
|
+
|
|
1453
1821
|
return rawClips;
|
|
1454
1822
|
}
|
|
1823
|
+
|
|
1455
1824
|
addClip(rawClip) {
|
|
1456
1825
|
let tracks = [];
|
|
1457
1826
|
const scope = this;
|
|
1458
|
-
rawClip.layer.forEach(function(rawTracks) {
|
|
1827
|
+
rawClip.layer.forEach(function (rawTracks) {
|
|
1459
1828
|
tracks = tracks.concat(scope.generateTracks(rawTracks));
|
|
1460
1829
|
});
|
|
1461
|
-
return new
|
|
1830
|
+
return new AnimationClip(rawClip.name, -1, tracks);
|
|
1462
1831
|
}
|
|
1832
|
+
|
|
1463
1833
|
generateTracks(rawTracks) {
|
|
1464
1834
|
const tracks = [];
|
|
1465
|
-
let initialPosition = new
|
|
1466
|
-
let initialRotation = new
|
|
1467
|
-
let initialScale = new
|
|
1468
|
-
if (rawTracks.transform)
|
|
1469
|
-
rawTracks.transform.decompose(initialPosition, initialRotation, initialScale);
|
|
1835
|
+
let initialPosition = new Vector3();
|
|
1836
|
+
let initialRotation = new Quaternion();
|
|
1837
|
+
let initialScale = new Vector3();
|
|
1838
|
+
if (rawTracks.transform) rawTracks.transform.decompose(initialPosition, initialRotation, initialScale);
|
|
1470
1839
|
initialPosition = initialPosition.toArray();
|
|
1471
|
-
initialRotation = new
|
|
1840
|
+
initialRotation = new Euler().setFromQuaternion(initialRotation, rawTracks.eulerOrder).toArray();
|
|
1472
1841
|
initialScale = initialScale.toArray();
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
rawTracks.eulerOrder
|
|
1491
|
-
);
|
|
1492
|
-
if (rotationTrack !== void 0)
|
|
1493
|
-
tracks.push(rotationTrack);
|
|
1494
|
-
}
|
|
1495
|
-
if (rawTracks.S !== void 0 && Object.keys(rawTracks.S.curves).length > 0) {
|
|
1496
|
-
const scaleTrack = this.generateVectorTrack(rawTracks.modelName, rawTracks.S.curves, initialScale, "scale");
|
|
1497
|
-
if (scaleTrack !== void 0)
|
|
1498
|
-
tracks.push(scaleTrack);
|
|
1499
|
-
}
|
|
1500
|
-
if (rawTracks.DeformPercent !== void 0) {
|
|
1842
|
+
|
|
1843
|
+
if (rawTracks.T !== undefined && Object.keys(rawTracks.T.curves).length > 0) {
|
|
1844
|
+
const positionTrack = this.generateVectorTrack(rawTracks.modelName, rawTracks.T.curves, initialPosition, 'position');
|
|
1845
|
+
if (positionTrack !== undefined) tracks.push(positionTrack);
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
if (rawTracks.R !== undefined && Object.keys(rawTracks.R.curves).length > 0) {
|
|
1849
|
+
const rotationTrack = this.generateRotationTrack(rawTracks.modelName, rawTracks.R.curves, initialRotation, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder);
|
|
1850
|
+
if (rotationTrack !== undefined) tracks.push(rotationTrack);
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
if (rawTracks.S !== undefined && Object.keys(rawTracks.S.curves).length > 0) {
|
|
1854
|
+
const scaleTrack = this.generateVectorTrack(rawTracks.modelName, rawTracks.S.curves, initialScale, 'scale');
|
|
1855
|
+
if (scaleTrack !== undefined) tracks.push(scaleTrack);
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
if (rawTracks.DeformPercent !== undefined) {
|
|
1501
1859
|
const morphTrack = this.generateMorphTrack(rawTracks);
|
|
1502
|
-
if (morphTrack !==
|
|
1503
|
-
tracks.push(morphTrack);
|
|
1860
|
+
if (morphTrack !== undefined) tracks.push(morphTrack);
|
|
1504
1861
|
}
|
|
1862
|
+
|
|
1505
1863
|
return tracks;
|
|
1506
1864
|
}
|
|
1865
|
+
|
|
1507
1866
|
generateVectorTrack(modelName, curves, initialValue, type) {
|
|
1508
1867
|
const times = this.getTimesForAllAxes(curves);
|
|
1509
1868
|
const values = this.getKeyframeTrackValues(times, curves, initialValue);
|
|
1510
|
-
return new
|
|
1869
|
+
return new VectorKeyframeTrack(modelName + '.' + type, times, values);
|
|
1511
1870
|
}
|
|
1871
|
+
|
|
1512
1872
|
generateRotationTrack(modelName, curves, initialValue, preRotation, postRotation, eulerOrder) {
|
|
1513
|
-
if (curves.x !==
|
|
1873
|
+
if (curves.x !== undefined) {
|
|
1514
1874
|
this.interpolateRotations(curves.x);
|
|
1515
|
-
curves.x.values = curves.x.values.map(
|
|
1875
|
+
curves.x.values = curves.x.values.map(MathUtils.degToRad);
|
|
1516
1876
|
}
|
|
1517
|
-
|
|
1877
|
+
|
|
1878
|
+
if (curves.y !== undefined) {
|
|
1518
1879
|
this.interpolateRotations(curves.y);
|
|
1519
|
-
curves.y.values = curves.y.values.map(
|
|
1880
|
+
curves.y.values = curves.y.values.map(MathUtils.degToRad);
|
|
1520
1881
|
}
|
|
1521
|
-
|
|
1882
|
+
|
|
1883
|
+
if (curves.z !== undefined) {
|
|
1522
1884
|
this.interpolateRotations(curves.z);
|
|
1523
|
-
curves.z.values = curves.z.values.map(
|
|
1885
|
+
curves.z.values = curves.z.values.map(MathUtils.degToRad);
|
|
1524
1886
|
}
|
|
1887
|
+
|
|
1525
1888
|
const times = this.getTimesForAllAxes(curves);
|
|
1526
1889
|
const values = this.getKeyframeTrackValues(times, curves, initialValue);
|
|
1527
|
-
|
|
1528
|
-
|
|
1890
|
+
|
|
1891
|
+
if (preRotation !== undefined) {
|
|
1892
|
+
preRotation = preRotation.map(MathUtils.degToRad);
|
|
1529
1893
|
preRotation.push(eulerOrder);
|
|
1530
|
-
preRotation = new
|
|
1531
|
-
preRotation = new
|
|
1894
|
+
preRotation = new Euler().fromArray(preRotation);
|
|
1895
|
+
preRotation = new Quaternion().setFromEuler(preRotation);
|
|
1532
1896
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1897
|
+
|
|
1898
|
+
if (postRotation !== undefined) {
|
|
1899
|
+
postRotation = postRotation.map(MathUtils.degToRad);
|
|
1535
1900
|
postRotation.push(eulerOrder);
|
|
1536
|
-
postRotation = new
|
|
1537
|
-
postRotation = new
|
|
1901
|
+
postRotation = new Euler().fromArray(postRotation);
|
|
1902
|
+
postRotation = new Quaternion().setFromEuler(postRotation).invert();
|
|
1538
1903
|
}
|
|
1539
|
-
|
|
1540
|
-
const
|
|
1904
|
+
|
|
1905
|
+
const quaternion = new Quaternion();
|
|
1906
|
+
const euler = new Euler();
|
|
1541
1907
|
const quaternionValues = [];
|
|
1908
|
+
|
|
1542
1909
|
for (let i = 0; i < values.length; i += 3) {
|
|
1543
1910
|
euler.set(values[i], values[i + 1], values[i + 2], eulerOrder);
|
|
1544
1911
|
quaternion.setFromEuler(euler);
|
|
1545
|
-
if (preRotation !==
|
|
1546
|
-
|
|
1547
|
-
if (postRotation !== void 0)
|
|
1548
|
-
quaternion.multiply(postRotation);
|
|
1912
|
+
if (preRotation !== undefined) quaternion.premultiply(preRotation);
|
|
1913
|
+
if (postRotation !== undefined) quaternion.multiply(postRotation);
|
|
1549
1914
|
quaternion.toArray(quaternionValues, i / 3 * 4);
|
|
1550
1915
|
}
|
|
1551
|
-
|
|
1916
|
+
|
|
1917
|
+
return new QuaternionKeyframeTrack(modelName + '.quaternion', times, quaternionValues);
|
|
1552
1918
|
}
|
|
1919
|
+
|
|
1553
1920
|
generateMorphTrack(rawTracks) {
|
|
1554
1921
|
const curves = rawTracks.DeformPercent.curves.morph;
|
|
1555
|
-
const values = curves.values.map(function(val) {
|
|
1922
|
+
const values = curves.values.map(function (val) {
|
|
1556
1923
|
return val / 100;
|
|
1557
1924
|
});
|
|
1558
1925
|
const morphNum = sceneGraph.getObjectByName(rawTracks.modelName).morphTargetDictionary[rawTracks.morphName];
|
|
1559
|
-
return new
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
}
|
|
1926
|
+
return new NumberKeyframeTrack(rawTracks.modelName + '.morphTargetInfluences[' + morphNum + ']', curves.times, values);
|
|
1927
|
+
} // For all animated objects, times are defined separately for each axis
|
|
1928
|
+
// Here we'll combine the times into one sorted array without duplicates
|
|
1929
|
+
|
|
1930
|
+
|
|
1565
1931
|
getTimesForAllAxes(curves) {
|
|
1566
|
-
let times = [];
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
if (curves.y !==
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
times = times.sort(function(a, b) {
|
|
1932
|
+
let times = []; // first join together the times for each axis, if defined
|
|
1933
|
+
|
|
1934
|
+
if (curves.x !== undefined) times = times.concat(curves.x.times);
|
|
1935
|
+
if (curves.y !== undefined) times = times.concat(curves.y.times);
|
|
1936
|
+
if (curves.z !== undefined) times = times.concat(curves.z.times); // then sort them
|
|
1937
|
+
|
|
1938
|
+
times = times.sort(function (a, b) {
|
|
1574
1939
|
return a - b;
|
|
1575
|
-
});
|
|
1940
|
+
}); // and remove duplicates
|
|
1941
|
+
|
|
1576
1942
|
if (times.length > 1) {
|
|
1577
1943
|
let targetIndex = 1;
|
|
1578
1944
|
let lastValue = times[0];
|
|
1945
|
+
|
|
1579
1946
|
for (let i = 1; i < times.length; i++) {
|
|
1580
1947
|
const currentValue = times[i];
|
|
1948
|
+
|
|
1581
1949
|
if (currentValue !== lastValue) {
|
|
1582
1950
|
times[targetIndex] = currentValue;
|
|
1583
1951
|
lastValue = currentValue;
|
|
1584
1952
|
targetIndex++;
|
|
1585
1953
|
}
|
|
1586
1954
|
}
|
|
1955
|
+
|
|
1587
1956
|
times = times.slice(0, targetIndex);
|
|
1588
1957
|
}
|
|
1958
|
+
|
|
1589
1959
|
return times;
|
|
1590
1960
|
}
|
|
1961
|
+
|
|
1591
1962
|
getKeyframeTrackValues(times, curves, initialValue) {
|
|
1592
1963
|
const prevValue = initialValue;
|
|
1593
1964
|
const values = [];
|
|
1594
1965
|
let xIndex = -1;
|
|
1595
1966
|
let yIndex = -1;
|
|
1596
1967
|
let zIndex = -1;
|
|
1597
|
-
times.forEach(function(time) {
|
|
1598
|
-
if (curves.x)
|
|
1599
|
-
|
|
1600
|
-
if (curves.
|
|
1601
|
-
|
|
1602
|
-
if (curves.z)
|
|
1603
|
-
zIndex = curves.z.times.indexOf(time);
|
|
1968
|
+
times.forEach(function (time) {
|
|
1969
|
+
if (curves.x) xIndex = curves.x.times.indexOf(time);
|
|
1970
|
+
if (curves.y) yIndex = curves.y.times.indexOf(time);
|
|
1971
|
+
if (curves.z) zIndex = curves.z.times.indexOf(time); // if there is an x value defined for this frame, use that
|
|
1972
|
+
|
|
1604
1973
|
if (xIndex !== -1) {
|
|
1605
1974
|
const xValue = curves.x.values[xIndex];
|
|
1606
1975
|
values.push(xValue);
|
|
1607
1976
|
prevValue[0] = xValue;
|
|
1608
1977
|
} else {
|
|
1978
|
+
// otherwise use the x value from the previous frame
|
|
1609
1979
|
values.push(prevValue[0]);
|
|
1610
1980
|
}
|
|
1981
|
+
|
|
1611
1982
|
if (yIndex !== -1) {
|
|
1612
1983
|
const yValue = curves.y.values[yIndex];
|
|
1613
1984
|
values.push(yValue);
|
|
@@ -1615,6 +1986,7 @@ class AnimationParser {
|
|
|
1615
1986
|
} else {
|
|
1616
1987
|
values.push(prevValue[1]);
|
|
1617
1988
|
}
|
|
1989
|
+
|
|
1618
1990
|
if (zIndex !== -1) {
|
|
1619
1991
|
const zValue = curves.z.values[zIndex];
|
|
1620
1992
|
values.push(zValue);
|
|
@@ -1624,12 +1996,17 @@ class AnimationParser {
|
|
|
1624
1996
|
}
|
|
1625
1997
|
});
|
|
1626
1998
|
return values;
|
|
1627
|
-
}
|
|
1999
|
+
} // Rotations are defined as Euler angles which can have values of any size
|
|
2000
|
+
// These will be converted to quaternions which don't support values greater than
|
|
2001
|
+
// PI, so we'll interpolate large rotations
|
|
2002
|
+
|
|
2003
|
+
|
|
1628
2004
|
interpolateRotations(curve) {
|
|
1629
2005
|
for (let i = 1; i < curve.values.length; i++) {
|
|
1630
2006
|
const initialValue = curve.values[i - 1];
|
|
1631
2007
|
const valuesSpan = curve.values[i] - initialValue;
|
|
1632
2008
|
const absoluteSpan = Math.abs(valuesSpan);
|
|
2009
|
+
|
|
1633
2010
|
if (absoluteSpan >= 180) {
|
|
1634
2011
|
const numSubIntervals = absoluteSpan / 180;
|
|
1635
2012
|
const step = valuesSpan / numSubIntervals;
|
|
@@ -1640,56 +2017,67 @@ class AnimationParser {
|
|
|
1640
2017
|
let nextTime = initialTime + interval;
|
|
1641
2018
|
const interpolatedTimes = [];
|
|
1642
2019
|
const interpolatedValues = [];
|
|
2020
|
+
|
|
1643
2021
|
while (nextTime < curve.times[i]) {
|
|
1644
2022
|
interpolatedTimes.push(nextTime);
|
|
1645
2023
|
nextTime += interval;
|
|
1646
2024
|
interpolatedValues.push(nextValue);
|
|
1647
2025
|
nextValue += step;
|
|
1648
2026
|
}
|
|
2027
|
+
|
|
1649
2028
|
curve.times = inject(curve.times, i, interpolatedTimes);
|
|
1650
2029
|
curve.values = inject(curve.values, i, interpolatedValues);
|
|
1651
2030
|
}
|
|
1652
2031
|
}
|
|
1653
2032
|
}
|
|
1654
|
-
|
|
2033
|
+
|
|
2034
|
+
} // parse an FBX file in ASCII format
|
|
2035
|
+
|
|
2036
|
+
|
|
1655
2037
|
class TextParser {
|
|
1656
2038
|
getPrevNode() {
|
|
1657
2039
|
return this.nodeStack[this.currentIndent - 2];
|
|
1658
2040
|
}
|
|
2041
|
+
|
|
1659
2042
|
getCurrentNode() {
|
|
1660
2043
|
return this.nodeStack[this.currentIndent - 1];
|
|
1661
2044
|
}
|
|
2045
|
+
|
|
1662
2046
|
getCurrentProp() {
|
|
1663
2047
|
return this.currentProp;
|
|
1664
2048
|
}
|
|
2049
|
+
|
|
1665
2050
|
pushStack(node) {
|
|
1666
2051
|
this.nodeStack.push(node);
|
|
1667
2052
|
this.currentIndent += 1;
|
|
1668
2053
|
}
|
|
2054
|
+
|
|
1669
2055
|
popStack() {
|
|
1670
2056
|
this.nodeStack.pop();
|
|
1671
2057
|
this.currentIndent -= 1;
|
|
1672
2058
|
}
|
|
2059
|
+
|
|
1673
2060
|
setCurrentProp(val, name) {
|
|
1674
2061
|
this.currentProp = val;
|
|
1675
2062
|
this.currentPropName = name;
|
|
1676
2063
|
}
|
|
2064
|
+
|
|
1677
2065
|
parse(text) {
|
|
1678
2066
|
this.currentIndent = 0;
|
|
1679
2067
|
this.allNodes = new FBXTree();
|
|
1680
2068
|
this.nodeStack = [];
|
|
1681
2069
|
this.currentProp = [];
|
|
1682
|
-
this.currentPropName =
|
|
2070
|
+
this.currentPropName = '';
|
|
1683
2071
|
const scope = this;
|
|
1684
2072
|
const split = text.split(/[\r\n]+/);
|
|
1685
|
-
split.forEach(function(line, i) {
|
|
2073
|
+
split.forEach(function (line, i) {
|
|
1686
2074
|
const matchComment = line.match(/^[\s\t]*;/);
|
|
1687
2075
|
const matchEmpty = line.match(/^[\s\t]*$/);
|
|
1688
|
-
if (matchComment || matchEmpty)
|
|
1689
|
-
|
|
1690
|
-
const
|
|
1691
|
-
const
|
|
1692
|
-
|
|
2076
|
+
if (matchComment || matchEmpty) return;
|
|
2077
|
+
const matchBeginning = line.match('^\\t{' + scope.currentIndent + '}(\\w+):(.*){', '');
|
|
2078
|
+
const matchProperty = line.match('^\\t{' + scope.currentIndent + '}(\\w+):[\\s\\t\\r\\n](.*)');
|
|
2079
|
+
const matchEnd = line.match('^\\t{' + (scope.currentIndent - 1) + '}}');
|
|
2080
|
+
|
|
1693
2081
|
if (matchBeginning) {
|
|
1694
2082
|
scope.parseNodeBegin(line, matchBeginning);
|
|
1695
2083
|
} else if (matchProperty) {
|
|
@@ -1697,141 +2085,179 @@ class TextParser {
|
|
|
1697
2085
|
} else if (matchEnd) {
|
|
1698
2086
|
scope.popStack();
|
|
1699
2087
|
} else if (line.match(/^[^\s\t}]/)) {
|
|
2088
|
+
// large arrays are split over multiple lines terminated with a ',' character
|
|
2089
|
+
// if this is encountered the line needs to be joined to the previous line
|
|
1700
2090
|
scope.parseNodePropertyContinued(line);
|
|
1701
2091
|
}
|
|
1702
2092
|
});
|
|
1703
2093
|
return this.allNodes;
|
|
1704
2094
|
}
|
|
2095
|
+
|
|
1705
2096
|
parseNodeBegin(line, property) {
|
|
1706
|
-
const nodeName = property[1].trim().replace(/^"/,
|
|
1707
|
-
const nodeAttrs = property[2].split(
|
|
1708
|
-
return attr.trim().replace(/^"/,
|
|
2097
|
+
const nodeName = property[1].trim().replace(/^"/, '').replace(/"$/, '');
|
|
2098
|
+
const nodeAttrs = property[2].split(',').map(function (attr) {
|
|
2099
|
+
return attr.trim().replace(/^"/, '').replace(/"$/, '');
|
|
1709
2100
|
});
|
|
1710
|
-
const node = {
|
|
2101
|
+
const node = {
|
|
2102
|
+
name: nodeName
|
|
2103
|
+
};
|
|
1711
2104
|
const attrs = this.parseNodeAttr(nodeAttrs);
|
|
1712
|
-
const currentNode = this.getCurrentNode();
|
|
2105
|
+
const currentNode = this.getCurrentNode(); // a top node
|
|
2106
|
+
|
|
1713
2107
|
if (this.currentIndent === 0) {
|
|
1714
2108
|
this.allNodes.add(nodeName, node);
|
|
1715
2109
|
} else {
|
|
2110
|
+
// a subnode
|
|
2111
|
+
// if the subnode already exists, append it
|
|
1716
2112
|
if (nodeName in currentNode) {
|
|
1717
|
-
|
|
2113
|
+
// special case Pose needs PoseNodes as an array
|
|
2114
|
+
if (nodeName === 'PoseNode') {
|
|
1718
2115
|
currentNode.PoseNode.push(node);
|
|
1719
|
-
} else if (currentNode[nodeName].id !==
|
|
2116
|
+
} else if (currentNode[nodeName].id !== undefined) {
|
|
1720
2117
|
currentNode[nodeName] = {};
|
|
1721
2118
|
currentNode[nodeName][currentNode[nodeName].id] = currentNode[nodeName];
|
|
1722
2119
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
} else if (typeof attrs.id ===
|
|
2120
|
+
|
|
2121
|
+
if (attrs.id !== '') currentNode[nodeName][attrs.id] = node;
|
|
2122
|
+
} else if (typeof attrs.id === 'number') {
|
|
1726
2123
|
currentNode[nodeName] = {};
|
|
1727
2124
|
currentNode[nodeName][attrs.id] = node;
|
|
1728
|
-
} else if (nodeName !==
|
|
1729
|
-
if (nodeName ===
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
if (
|
|
1736
|
-
node.id = attrs.id;
|
|
1737
|
-
if (attrs.name !== "")
|
|
1738
|
-
node.attrName = attrs.name;
|
|
1739
|
-
if (attrs.type !== "")
|
|
1740
|
-
node.attrType = attrs.type;
|
|
2125
|
+
} else if (nodeName !== 'Properties70') {
|
|
2126
|
+
if (nodeName === 'PoseNode') currentNode[nodeName] = [node];else currentNode[nodeName] = node;
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
if (typeof attrs.id === 'number') node.id = attrs.id;
|
|
2131
|
+
if (attrs.name !== '') node.attrName = attrs.name;
|
|
2132
|
+
if (attrs.type !== '') node.attrType = attrs.type;
|
|
1741
2133
|
this.pushStack(node);
|
|
1742
2134
|
}
|
|
2135
|
+
|
|
1743
2136
|
parseNodeAttr(attrs) {
|
|
1744
2137
|
let id = attrs[0];
|
|
1745
|
-
|
|
2138
|
+
|
|
2139
|
+
if (attrs[0] !== '') {
|
|
1746
2140
|
id = parseInt(attrs[0]);
|
|
2141
|
+
|
|
1747
2142
|
if (isNaN(id)) {
|
|
1748
2143
|
id = attrs[0];
|
|
1749
2144
|
}
|
|
1750
2145
|
}
|
|
1751
|
-
|
|
2146
|
+
|
|
2147
|
+
let name = '',
|
|
2148
|
+
type = '';
|
|
2149
|
+
|
|
1752
2150
|
if (attrs.length > 1) {
|
|
1753
|
-
name = attrs[1].replace(/^(\w+)::/,
|
|
2151
|
+
name = attrs[1].replace(/^(\w+)::/, '');
|
|
1754
2152
|
type = attrs[2];
|
|
1755
2153
|
}
|
|
1756
|
-
|
|
2154
|
+
|
|
2155
|
+
return {
|
|
2156
|
+
id: id,
|
|
2157
|
+
name: name,
|
|
2158
|
+
type: type
|
|
2159
|
+
};
|
|
1757
2160
|
}
|
|
2161
|
+
|
|
1758
2162
|
parseNodeProperty(line, property, contentLine) {
|
|
1759
|
-
let propName = property[1].replace(/^"/,
|
|
1760
|
-
let propValue = property[2].replace(/^"/,
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
2163
|
+
let propName = property[1].replace(/^"/, '').replace(/"$/, '').trim();
|
|
2164
|
+
let propValue = property[2].replace(/^"/, '').replace(/"$/, '').trim(); // for special case: base64 image data follows "Content: ," line
|
|
2165
|
+
// Content: ,
|
|
2166
|
+
// "/9j/4RDaRXhpZgAATU0A..."
|
|
2167
|
+
|
|
2168
|
+
if (propName === 'Content' && propValue === ',') {
|
|
2169
|
+
propValue = contentLine.replace(/"/g, '').replace(/,$/, '').trim();
|
|
2170
|
+
}
|
|
2171
|
+
|
|
1764
2172
|
const currentNode = this.getCurrentNode();
|
|
1765
2173
|
const parentName = currentNode.name;
|
|
1766
|
-
|
|
2174
|
+
|
|
2175
|
+
if (parentName === 'Properties70') {
|
|
1767
2176
|
this.parseNodeSpecialProperty(line, propName, propValue);
|
|
1768
2177
|
return;
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
|
|
2178
|
+
} // Connections
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
if (propName === 'C') {
|
|
2182
|
+
const connProps = propValue.split(',').slice(1);
|
|
1772
2183
|
const from = parseInt(connProps[0]);
|
|
1773
2184
|
const to = parseInt(connProps[1]);
|
|
1774
|
-
let rest = propValue.split(
|
|
1775
|
-
rest = rest.map(function(elem) {
|
|
1776
|
-
return elem.trim().replace(/^"/,
|
|
2185
|
+
let rest = propValue.split(',').slice(3);
|
|
2186
|
+
rest = rest.map(function (elem) {
|
|
2187
|
+
return elem.trim().replace(/^"/, '');
|
|
1777
2188
|
});
|
|
1778
|
-
propName =
|
|
2189
|
+
propName = 'connections';
|
|
1779
2190
|
propValue = [from, to];
|
|
1780
2191
|
append(propValue, rest);
|
|
1781
|
-
|
|
2192
|
+
|
|
2193
|
+
if (currentNode[propName] === undefined) {
|
|
1782
2194
|
currentNode[propName] = [];
|
|
1783
2195
|
}
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
|
|
2196
|
+
} // Node
|
|
2197
|
+
|
|
2198
|
+
|
|
2199
|
+
if (propName === 'Node') currentNode.id = propValue; // connections
|
|
2200
|
+
|
|
1787
2201
|
if (propName in currentNode && Array.isArray(currentNode[propName])) {
|
|
1788
2202
|
currentNode[propName].push(propValue);
|
|
1789
2203
|
} else {
|
|
1790
|
-
if (propName !==
|
|
1791
|
-
currentNode[propName] = propValue;
|
|
1792
|
-
else
|
|
1793
|
-
currentNode.a = propValue;
|
|
2204
|
+
if (propName !== 'a') currentNode[propName] = propValue;else currentNode.a = propValue;
|
|
1794
2205
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
2206
|
+
|
|
2207
|
+
this.setCurrentProp(currentNode, propName); // convert string to array, unless it ends in ',' in which case more will be added to it
|
|
2208
|
+
|
|
2209
|
+
if (propName === 'a' && propValue.slice(-1) !== ',') {
|
|
1797
2210
|
currentNode.a = parseNumberArray(propValue);
|
|
1798
2211
|
}
|
|
1799
2212
|
}
|
|
2213
|
+
|
|
1800
2214
|
parseNodePropertyContinued(line) {
|
|
1801
2215
|
const currentNode = this.getCurrentNode();
|
|
1802
|
-
currentNode.a += line;
|
|
1803
|
-
|
|
2216
|
+
currentNode.a += line; // if the line doesn't end in ',' we have reached the end of the property value
|
|
2217
|
+
// so convert the string to an array
|
|
2218
|
+
|
|
2219
|
+
if (line.slice(-1) !== ',') {
|
|
1804
2220
|
currentNode.a = parseNumberArray(currentNode.a);
|
|
1805
2221
|
}
|
|
1806
|
-
}
|
|
2222
|
+
} // parse "Property70"
|
|
2223
|
+
|
|
2224
|
+
|
|
1807
2225
|
parseNodeSpecialProperty(line, propName, propValue) {
|
|
1808
|
-
|
|
1809
|
-
|
|
2226
|
+
// split this
|
|
2227
|
+
// P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1
|
|
2228
|
+
// into array like below
|
|
2229
|
+
// ["Lcl Scaling", "Lcl Scaling", "", "A", "1,1,1" ]
|
|
2230
|
+
const props = propValue.split('",').map(function (prop) {
|
|
2231
|
+
return prop.trim().replace(/^\"/, '').replace(/\s/, '_');
|
|
1810
2232
|
});
|
|
1811
2233
|
const innerPropName = props[0];
|
|
1812
2234
|
const innerPropType1 = props[1];
|
|
1813
2235
|
const innerPropType2 = props[2];
|
|
1814
2236
|
const innerPropFlag = props[3];
|
|
1815
|
-
let innerPropValue = props[4];
|
|
2237
|
+
let innerPropValue = props[4]; // cast values where needed, otherwise leave as strings
|
|
2238
|
+
|
|
1816
2239
|
switch (innerPropType1) {
|
|
1817
|
-
case
|
|
1818
|
-
case
|
|
1819
|
-
case
|
|
1820
|
-
case
|
|
1821
|
-
case
|
|
1822
|
-
case
|
|
1823
|
-
case
|
|
2240
|
+
case 'int':
|
|
2241
|
+
case 'enum':
|
|
2242
|
+
case 'bool':
|
|
2243
|
+
case 'ULongLong':
|
|
2244
|
+
case 'double':
|
|
2245
|
+
case 'Number':
|
|
2246
|
+
case 'FieldOfView':
|
|
1824
2247
|
innerPropValue = parseFloat(innerPropValue);
|
|
1825
2248
|
break;
|
|
1826
|
-
|
|
1827
|
-
case
|
|
1828
|
-
case
|
|
1829
|
-
case
|
|
1830
|
-
case
|
|
1831
|
-
case
|
|
2249
|
+
|
|
2250
|
+
case 'Color':
|
|
2251
|
+
case 'ColorRGB':
|
|
2252
|
+
case 'Vector3D':
|
|
2253
|
+
case 'Lcl_Translation':
|
|
2254
|
+
case 'Lcl_Rotation':
|
|
2255
|
+
case 'Lcl_Scaling':
|
|
1832
2256
|
innerPropValue = parseNumberArray(innerPropValue);
|
|
1833
2257
|
break;
|
|
1834
|
-
}
|
|
2258
|
+
} // CAUTION: these props must append to parent's parent
|
|
2259
|
+
|
|
2260
|
+
|
|
1835
2261
|
this.getPrevNode()[innerPropName] = {
|
|
1836
2262
|
type: innerPropType1,
|
|
1837
2263
|
type2: innerPropType2,
|
|
@@ -1840,272 +2266,361 @@ class TextParser {
|
|
|
1840
2266
|
};
|
|
1841
2267
|
this.setCurrentProp(this.getPrevNode(), innerPropName);
|
|
1842
2268
|
}
|
|
1843
|
-
|
|
2269
|
+
|
|
2270
|
+
} // Parse an FBX file in Binary format
|
|
2271
|
+
|
|
2272
|
+
|
|
1844
2273
|
class BinaryParser {
|
|
1845
2274
|
parse(buffer) {
|
|
1846
2275
|
const reader = new BinaryReader(buffer);
|
|
1847
|
-
reader.skip(23);
|
|
2276
|
+
reader.skip(23); // skip magic 23 bytes
|
|
2277
|
+
|
|
1848
2278
|
const version = reader.getUint32();
|
|
2279
|
+
|
|
1849
2280
|
if (version < 6400) {
|
|
1850
|
-
throw new Error(
|
|
2281
|
+
throw new Error('THREE.FBXLoader: FBX version not supported, FileVersion: ' + version);
|
|
1851
2282
|
}
|
|
2283
|
+
|
|
1852
2284
|
const allNodes = new FBXTree();
|
|
2285
|
+
|
|
1853
2286
|
while (!this.endOfContent(reader)) {
|
|
1854
2287
|
const node = this.parseNode(reader, version);
|
|
1855
|
-
if (node !== null)
|
|
1856
|
-
allNodes.add(node.name, node);
|
|
2288
|
+
if (node !== null) allNodes.add(node.name, node);
|
|
1857
2289
|
}
|
|
2290
|
+
|
|
1858
2291
|
return allNodes;
|
|
1859
|
-
}
|
|
2292
|
+
} // Check if reader has reached the end of content.
|
|
2293
|
+
|
|
2294
|
+
|
|
1860
2295
|
endOfContent(reader) {
|
|
2296
|
+
// footer size: 160bytes + 16-byte alignment padding
|
|
2297
|
+
// - 16bytes: magic
|
|
2298
|
+
// - padding til 16-byte alignment (at least 1byte?)
|
|
2299
|
+
// (seems like some exporters embed fixed 15 or 16bytes?)
|
|
2300
|
+
// - 4bytes: magic
|
|
2301
|
+
// - 4bytes: version
|
|
2302
|
+
// - 120bytes: zero
|
|
2303
|
+
// - 16bytes: magic
|
|
1861
2304
|
if (reader.size() % 16 === 0) {
|
|
1862
|
-
return (reader.getOffset() + 160 + 16 & ~
|
|
2305
|
+
return (reader.getOffset() + 160 + 16 & ~0xf) >= reader.size();
|
|
1863
2306
|
} else {
|
|
1864
2307
|
return reader.getOffset() + 160 + 16 >= reader.size();
|
|
1865
2308
|
}
|
|
1866
|
-
}
|
|
2309
|
+
} // recursively parse nodes until the end of the file is reached
|
|
2310
|
+
|
|
2311
|
+
|
|
1867
2312
|
parseNode(reader, version) {
|
|
1868
|
-
const node = {};
|
|
2313
|
+
const node = {}; // The first three data sizes depends on version.
|
|
2314
|
+
|
|
1869
2315
|
const endOffset = version >= 7500 ? reader.getUint64() : reader.getUint32();
|
|
1870
2316
|
const numProperties = version >= 7500 ? reader.getUint64() : reader.getUint32();
|
|
1871
|
-
version >= 7500 ? reader.getUint64() : reader.getUint32();
|
|
2317
|
+
version >= 7500 ? reader.getUint64() : reader.getUint32(); // the returned propertyListLen is not used
|
|
2318
|
+
|
|
1872
2319
|
const nameLen = reader.getUint8();
|
|
1873
|
-
const name = reader.getString(nameLen);
|
|
1874
|
-
|
|
1875
|
-
|
|
2320
|
+
const name = reader.getString(nameLen); // Regards this node as NULL-record if endOffset is zero
|
|
2321
|
+
|
|
2322
|
+
if (endOffset === 0) return null;
|
|
1876
2323
|
const propertyList = [];
|
|
2324
|
+
|
|
1877
2325
|
for (let i = 0; i < numProperties; i++) {
|
|
1878
2326
|
propertyList.push(this.parseProperty(reader));
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
const
|
|
2327
|
+
} // Regards the first three elements in propertyList as id, attrName, and attrType
|
|
2328
|
+
|
|
2329
|
+
|
|
2330
|
+
const id = propertyList.length > 0 ? propertyList[0] : '';
|
|
2331
|
+
const attrName = propertyList.length > 1 ? propertyList[1] : '';
|
|
2332
|
+
const attrType = propertyList.length > 2 ? propertyList[2] : ''; // check if this node represents just a single property
|
|
2333
|
+
// like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]}
|
|
2334
|
+
|
|
1883
2335
|
node.singleProperty = numProperties === 1 && reader.getOffset() === endOffset ? true : false;
|
|
2336
|
+
|
|
1884
2337
|
while (endOffset > reader.getOffset()) {
|
|
1885
2338
|
const subNode = this.parseNode(reader, version);
|
|
1886
|
-
if (subNode !== null)
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
node.propertyList = propertyList;
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
if (attrName !==
|
|
1893
|
-
|
|
1894
|
-
if (
|
|
1895
|
-
node.attrType = attrType;
|
|
1896
|
-
if (name !== "")
|
|
1897
|
-
node.name = name;
|
|
2339
|
+
if (subNode !== null) this.parseSubNode(name, node, subNode);
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
node.propertyList = propertyList; // raw property list used by parent
|
|
2343
|
+
|
|
2344
|
+
if (typeof id === 'number') node.id = id;
|
|
2345
|
+
if (attrName !== '') node.attrName = attrName;
|
|
2346
|
+
if (attrType !== '') node.attrType = attrType;
|
|
2347
|
+
if (name !== '') node.name = name;
|
|
1898
2348
|
return node;
|
|
1899
2349
|
}
|
|
2350
|
+
|
|
1900
2351
|
parseSubNode(name, node, subNode) {
|
|
2352
|
+
// special case: child node is single property
|
|
1901
2353
|
if (subNode.singleProperty === true) {
|
|
1902
2354
|
const value = subNode.propertyList[0];
|
|
2355
|
+
|
|
1903
2356
|
if (Array.isArray(value)) {
|
|
1904
2357
|
node[subNode.name] = subNode;
|
|
1905
2358
|
subNode.a = value;
|
|
1906
2359
|
} else {
|
|
1907
2360
|
node[subNode.name] = value;
|
|
1908
2361
|
}
|
|
1909
|
-
} else if (name ===
|
|
2362
|
+
} else if (name === 'Connections' && subNode.name === 'C') {
|
|
1910
2363
|
const array = [];
|
|
1911
|
-
subNode.propertyList.forEach(function(property, i) {
|
|
1912
|
-
|
|
1913
|
-
|
|
2364
|
+
subNode.propertyList.forEach(function (property, i) {
|
|
2365
|
+
// first Connection is FBX type (OO, OP, etc.). We'll discard these
|
|
2366
|
+
if (i !== 0) array.push(property);
|
|
1914
2367
|
});
|
|
1915
|
-
|
|
2368
|
+
|
|
2369
|
+
if (node.connections === undefined) {
|
|
1916
2370
|
node.connections = [];
|
|
1917
2371
|
}
|
|
2372
|
+
|
|
1918
2373
|
node.connections.push(array);
|
|
1919
|
-
} else if (subNode.name ===
|
|
2374
|
+
} else if (subNode.name === 'Properties70') {
|
|
1920
2375
|
const keys = Object.keys(subNode);
|
|
1921
|
-
keys.forEach(function(key) {
|
|
2376
|
+
keys.forEach(function (key) {
|
|
1922
2377
|
node[key] = subNode[key];
|
|
1923
2378
|
});
|
|
1924
|
-
} else if (name ===
|
|
2379
|
+
} else if (name === 'Properties70' && subNode.name === 'P') {
|
|
1925
2380
|
let innerPropName = subNode.propertyList[0];
|
|
1926
2381
|
let innerPropType1 = subNode.propertyList[1];
|
|
1927
2382
|
const innerPropType2 = subNode.propertyList[2];
|
|
1928
2383
|
const innerPropFlag = subNode.propertyList[3];
|
|
1929
2384
|
let innerPropValue;
|
|
1930
|
-
if (innerPropName.indexOf(
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
if (innerPropType1 === "Color" || innerPropType1 === "ColorRGB" || innerPropType1 === "Vector" || innerPropType1 === "Vector3D" || innerPropType1.indexOf("Lcl_") === 0) {
|
|
2385
|
+
if (innerPropName.indexOf('Lcl ') === 0) innerPropName = innerPropName.replace('Lcl ', 'Lcl_');
|
|
2386
|
+
if (innerPropType1.indexOf('Lcl ') === 0) innerPropType1 = innerPropType1.replace('Lcl ', 'Lcl_');
|
|
2387
|
+
|
|
2388
|
+
if (innerPropType1 === 'Color' || innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf('Lcl_') === 0) {
|
|
1935
2389
|
innerPropValue = [subNode.propertyList[4], subNode.propertyList[5], subNode.propertyList[6]];
|
|
1936
2390
|
} else {
|
|
1937
2391
|
innerPropValue = subNode.propertyList[4];
|
|
1938
|
-
}
|
|
2392
|
+
} // this will be copied to parent, see above
|
|
2393
|
+
|
|
2394
|
+
|
|
1939
2395
|
node[innerPropName] = {
|
|
1940
2396
|
type: innerPropType1,
|
|
1941
2397
|
type2: innerPropType2,
|
|
1942
2398
|
flag: innerPropFlag,
|
|
1943
2399
|
value: innerPropValue
|
|
1944
2400
|
};
|
|
1945
|
-
} else if (node[subNode.name] ===
|
|
1946
|
-
if (typeof subNode.id ===
|
|
2401
|
+
} else if (node[subNode.name] === undefined) {
|
|
2402
|
+
if (typeof subNode.id === 'number') {
|
|
1947
2403
|
node[subNode.name] = {};
|
|
1948
2404
|
node[subNode.name][subNode.id] = subNode;
|
|
1949
2405
|
} else {
|
|
1950
2406
|
node[subNode.name] = subNode;
|
|
1951
2407
|
}
|
|
1952
2408
|
} else {
|
|
1953
|
-
if (subNode.name ===
|
|
2409
|
+
if (subNode.name === 'PoseNode') {
|
|
1954
2410
|
if (!Array.isArray(node[subNode.name])) {
|
|
1955
2411
|
node[subNode.name] = [node[subNode.name]];
|
|
1956
2412
|
}
|
|
2413
|
+
|
|
1957
2414
|
node[subNode.name].push(subNode);
|
|
1958
|
-
} else if (node[subNode.name][subNode.id] ===
|
|
2415
|
+
} else if (node[subNode.name][subNode.id] === undefined) {
|
|
1959
2416
|
node[subNode.name][subNode.id] = subNode;
|
|
1960
2417
|
}
|
|
1961
2418
|
}
|
|
1962
2419
|
}
|
|
2420
|
+
|
|
1963
2421
|
parseProperty(reader) {
|
|
1964
2422
|
const type = reader.getString(1);
|
|
1965
2423
|
let length;
|
|
2424
|
+
|
|
1966
2425
|
switch (type) {
|
|
1967
|
-
case
|
|
2426
|
+
case 'C':
|
|
1968
2427
|
return reader.getBoolean();
|
|
1969
|
-
|
|
2428
|
+
|
|
2429
|
+
case 'D':
|
|
1970
2430
|
return reader.getFloat64();
|
|
1971
|
-
|
|
2431
|
+
|
|
2432
|
+
case 'F':
|
|
1972
2433
|
return reader.getFloat32();
|
|
1973
|
-
|
|
2434
|
+
|
|
2435
|
+
case 'I':
|
|
1974
2436
|
return reader.getInt32();
|
|
1975
|
-
|
|
2437
|
+
|
|
2438
|
+
case 'L':
|
|
1976
2439
|
return reader.getInt64();
|
|
1977
|
-
|
|
2440
|
+
|
|
2441
|
+
case 'R':
|
|
1978
2442
|
length = reader.getUint32();
|
|
1979
2443
|
return reader.getArrayBuffer(length);
|
|
1980
|
-
|
|
2444
|
+
|
|
2445
|
+
case 'S':
|
|
1981
2446
|
length = reader.getUint32();
|
|
1982
2447
|
return reader.getString(length);
|
|
1983
|
-
|
|
2448
|
+
|
|
2449
|
+
case 'Y':
|
|
1984
2450
|
return reader.getInt16();
|
|
1985
|
-
|
|
1986
|
-
case
|
|
1987
|
-
case
|
|
1988
|
-
case
|
|
1989
|
-
case
|
|
1990
|
-
case
|
|
2451
|
+
|
|
2452
|
+
case 'b':
|
|
2453
|
+
case 'c':
|
|
2454
|
+
case 'd':
|
|
2455
|
+
case 'f':
|
|
2456
|
+
case 'i':
|
|
2457
|
+
case 'l':
|
|
1991
2458
|
const arrayLength = reader.getUint32();
|
|
1992
|
-
const encoding = reader.getUint32();
|
|
2459
|
+
const encoding = reader.getUint32(); // 0: non-compressed, 1: compressed
|
|
2460
|
+
|
|
1993
2461
|
const compressedLength = reader.getUint32();
|
|
2462
|
+
|
|
1994
2463
|
if (encoding === 0) {
|
|
1995
2464
|
switch (type) {
|
|
1996
|
-
case
|
|
1997
|
-
case
|
|
2465
|
+
case 'b':
|
|
2466
|
+
case 'c':
|
|
1998
2467
|
return reader.getBooleanArray(arrayLength);
|
|
1999
|
-
|
|
2468
|
+
|
|
2469
|
+
case 'd':
|
|
2000
2470
|
return reader.getFloat64Array(arrayLength);
|
|
2001
|
-
|
|
2471
|
+
|
|
2472
|
+
case 'f':
|
|
2002
2473
|
return reader.getFloat32Array(arrayLength);
|
|
2003
|
-
|
|
2474
|
+
|
|
2475
|
+
case 'i':
|
|
2004
2476
|
return reader.getInt32Array(arrayLength);
|
|
2005
|
-
|
|
2477
|
+
|
|
2478
|
+
case 'l':
|
|
2006
2479
|
return reader.getInt64Array(arrayLength);
|
|
2007
2480
|
}
|
|
2008
2481
|
}
|
|
2009
|
-
|
|
2482
|
+
|
|
2483
|
+
const data = unzlibSync(new Uint8Array(reader.getArrayBuffer(compressedLength))); // eslint-disable-line no-undef
|
|
2484
|
+
|
|
2010
2485
|
const reader2 = new BinaryReader(data.buffer);
|
|
2486
|
+
|
|
2011
2487
|
switch (type) {
|
|
2012
|
-
case
|
|
2013
|
-
case
|
|
2488
|
+
case 'b':
|
|
2489
|
+
case 'c':
|
|
2014
2490
|
return reader2.getBooleanArray(arrayLength);
|
|
2015
|
-
|
|
2491
|
+
|
|
2492
|
+
case 'd':
|
|
2016
2493
|
return reader2.getFloat64Array(arrayLength);
|
|
2017
|
-
|
|
2494
|
+
|
|
2495
|
+
case 'f':
|
|
2018
2496
|
return reader2.getFloat32Array(arrayLength);
|
|
2019
|
-
|
|
2497
|
+
|
|
2498
|
+
case 'i':
|
|
2020
2499
|
return reader2.getInt32Array(arrayLength);
|
|
2021
|
-
|
|
2500
|
+
|
|
2501
|
+
case 'l':
|
|
2022
2502
|
return reader2.getInt64Array(arrayLength);
|
|
2023
2503
|
}
|
|
2504
|
+
|
|
2024
2505
|
default:
|
|
2025
|
-
throw new Error(
|
|
2506
|
+
throw new Error('THREE.FBXLoader: Unknown property type ' + type);
|
|
2026
2507
|
}
|
|
2027
2508
|
}
|
|
2509
|
+
|
|
2028
2510
|
}
|
|
2511
|
+
|
|
2029
2512
|
class BinaryReader {
|
|
2030
2513
|
constructor(buffer, littleEndian) {
|
|
2031
2514
|
this.dv = new DataView(buffer);
|
|
2032
2515
|
this.offset = 0;
|
|
2033
|
-
this.littleEndian = littleEndian !==
|
|
2516
|
+
this.littleEndian = littleEndian !== undefined ? littleEndian : true;
|
|
2034
2517
|
}
|
|
2518
|
+
|
|
2035
2519
|
getOffset() {
|
|
2036
2520
|
return this.offset;
|
|
2037
2521
|
}
|
|
2522
|
+
|
|
2038
2523
|
size() {
|
|
2039
2524
|
return this.dv.buffer.byteLength;
|
|
2040
2525
|
}
|
|
2526
|
+
|
|
2041
2527
|
skip(length) {
|
|
2042
2528
|
this.offset += length;
|
|
2043
|
-
}
|
|
2529
|
+
} // seems like true/false representation depends on exporter.
|
|
2530
|
+
// true: 1 or 'Y'(=0x59), false: 0 or 'T'(=0x54)
|
|
2531
|
+
// then sees LSB.
|
|
2532
|
+
|
|
2533
|
+
|
|
2044
2534
|
getBoolean() {
|
|
2045
2535
|
return (this.getUint8() & 1) === 1;
|
|
2046
2536
|
}
|
|
2537
|
+
|
|
2047
2538
|
getBooleanArray(size) {
|
|
2048
2539
|
const a = [];
|
|
2540
|
+
|
|
2049
2541
|
for (let i = 0; i < size; i++) {
|
|
2050
2542
|
a.push(this.getBoolean());
|
|
2051
2543
|
}
|
|
2544
|
+
|
|
2052
2545
|
return a;
|
|
2053
2546
|
}
|
|
2547
|
+
|
|
2054
2548
|
getUint8() {
|
|
2055
2549
|
const value = this.dv.getUint8(this.offset);
|
|
2056
2550
|
this.offset += 1;
|
|
2057
2551
|
return value;
|
|
2058
2552
|
}
|
|
2553
|
+
|
|
2059
2554
|
getInt16() {
|
|
2060
2555
|
const value = this.dv.getInt16(this.offset, this.littleEndian);
|
|
2061
2556
|
this.offset += 2;
|
|
2062
2557
|
return value;
|
|
2063
2558
|
}
|
|
2559
|
+
|
|
2064
2560
|
getInt32() {
|
|
2065
2561
|
const value = this.dv.getInt32(this.offset, this.littleEndian);
|
|
2066
2562
|
this.offset += 4;
|
|
2067
2563
|
return value;
|
|
2068
2564
|
}
|
|
2565
|
+
|
|
2069
2566
|
getInt32Array(size) {
|
|
2070
2567
|
const a = [];
|
|
2568
|
+
|
|
2071
2569
|
for (let i = 0; i < size; i++) {
|
|
2072
2570
|
a.push(this.getInt32());
|
|
2073
2571
|
}
|
|
2572
|
+
|
|
2074
2573
|
return a;
|
|
2075
2574
|
}
|
|
2575
|
+
|
|
2076
2576
|
getUint32() {
|
|
2077
2577
|
const value = this.dv.getUint32(this.offset, this.littleEndian);
|
|
2078
2578
|
this.offset += 4;
|
|
2079
2579
|
return value;
|
|
2080
|
-
}
|
|
2580
|
+
} // JavaScript doesn't support 64-bit integer so calculate this here
|
|
2581
|
+
// 1 << 32 will return 1 so using multiply operation instead here.
|
|
2582
|
+
// There's a possibility that this method returns wrong value if the value
|
|
2583
|
+
// is out of the range between Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER.
|
|
2584
|
+
// TODO: safely handle 64-bit integer
|
|
2585
|
+
|
|
2586
|
+
|
|
2081
2587
|
getInt64() {
|
|
2082
2588
|
let low, high;
|
|
2589
|
+
|
|
2083
2590
|
if (this.littleEndian) {
|
|
2084
2591
|
low = this.getUint32();
|
|
2085
2592
|
high = this.getUint32();
|
|
2086
2593
|
} else {
|
|
2087
2594
|
high = this.getUint32();
|
|
2088
2595
|
low = this.getUint32();
|
|
2089
|
-
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
low =
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2596
|
+
} // calculate negative value
|
|
2597
|
+
|
|
2598
|
+
|
|
2599
|
+
if (high & 0x80000000) {
|
|
2600
|
+
high = ~high & 0xffffffff;
|
|
2601
|
+
low = ~low & 0xffffffff;
|
|
2602
|
+
if (low === 0xffffffff) high = high + 1 & 0xffffffff;
|
|
2603
|
+
low = low + 1 & 0xffffffff;
|
|
2604
|
+
return -(high * 0x100000000 + low);
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
return high * 0x100000000 + low;
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2100
2610
|
getInt64Array(size) {
|
|
2101
2611
|
const a = [];
|
|
2612
|
+
|
|
2102
2613
|
for (let i = 0; i < size; i++) {
|
|
2103
2614
|
a.push(this.getInt64());
|
|
2104
2615
|
}
|
|
2616
|
+
|
|
2105
2617
|
return a;
|
|
2106
|
-
}
|
|
2618
|
+
} // Note: see getInt64() comment
|
|
2619
|
+
|
|
2620
|
+
|
|
2107
2621
|
getUint64() {
|
|
2108
2622
|
let low, high;
|
|
2623
|
+
|
|
2109
2624
|
if (this.littleEndian) {
|
|
2110
2625
|
low = this.getUint32();
|
|
2111
2626
|
high = this.getUint32();
|
|
@@ -2113,250 +2628,290 @@ class BinaryReader {
|
|
|
2113
2628
|
high = this.getUint32();
|
|
2114
2629
|
low = this.getUint32();
|
|
2115
2630
|
}
|
|
2116
|
-
|
|
2631
|
+
|
|
2632
|
+
return high * 0x100000000 + low;
|
|
2117
2633
|
}
|
|
2634
|
+
|
|
2118
2635
|
getFloat32() {
|
|
2119
2636
|
const value = this.dv.getFloat32(this.offset, this.littleEndian);
|
|
2120
2637
|
this.offset += 4;
|
|
2121
2638
|
return value;
|
|
2122
2639
|
}
|
|
2640
|
+
|
|
2123
2641
|
getFloat32Array(size) {
|
|
2124
2642
|
const a = [];
|
|
2643
|
+
|
|
2125
2644
|
for (let i = 0; i < size; i++) {
|
|
2126
2645
|
a.push(this.getFloat32());
|
|
2127
2646
|
}
|
|
2647
|
+
|
|
2128
2648
|
return a;
|
|
2129
2649
|
}
|
|
2650
|
+
|
|
2130
2651
|
getFloat64() {
|
|
2131
2652
|
const value = this.dv.getFloat64(this.offset, this.littleEndian);
|
|
2132
2653
|
this.offset += 8;
|
|
2133
2654
|
return value;
|
|
2134
2655
|
}
|
|
2656
|
+
|
|
2135
2657
|
getFloat64Array(size) {
|
|
2136
2658
|
const a = [];
|
|
2659
|
+
|
|
2137
2660
|
for (let i = 0; i < size; i++) {
|
|
2138
2661
|
a.push(this.getFloat64());
|
|
2139
2662
|
}
|
|
2663
|
+
|
|
2140
2664
|
return a;
|
|
2141
2665
|
}
|
|
2666
|
+
|
|
2142
2667
|
getArrayBuffer(size) {
|
|
2143
2668
|
const value = this.dv.buffer.slice(this.offset, this.offset + size);
|
|
2144
2669
|
this.offset += size;
|
|
2145
2670
|
return value;
|
|
2146
2671
|
}
|
|
2672
|
+
|
|
2147
2673
|
getString(size) {
|
|
2674
|
+
// note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead
|
|
2148
2675
|
let a = [];
|
|
2676
|
+
|
|
2149
2677
|
for (let i = 0; i < size; i++) {
|
|
2150
2678
|
a[i] = this.getUint8();
|
|
2151
2679
|
}
|
|
2680
|
+
|
|
2152
2681
|
const nullByte = a.indexOf(0);
|
|
2153
|
-
if (nullByte >= 0)
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
}
|
|
2682
|
+
if (nullByte >= 0) a = a.slice(0, nullByte);
|
|
2683
|
+
return LoaderUtils.decodeText(new Uint8Array(a));
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
} // FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format)
|
|
2687
|
+
// and BinaryParser( FBX Binary format)
|
|
2688
|
+
|
|
2689
|
+
|
|
2158
2690
|
class FBXTree {
|
|
2159
2691
|
add(key, val) {
|
|
2160
2692
|
this[key] = val;
|
|
2161
2693
|
}
|
|
2162
|
-
|
|
2694
|
+
|
|
2695
|
+
} // ************** UTILITY FUNCTIONS **************
|
|
2696
|
+
|
|
2697
|
+
|
|
2163
2698
|
function isFbxFormatBinary(buffer) {
|
|
2164
|
-
const CORRECT =
|
|
2699
|
+
const CORRECT = 'Kaydara\u0020FBX\u0020Binary\u0020\u0020\0';
|
|
2165
2700
|
return buffer.byteLength >= CORRECT.length && CORRECT === convertArrayBufferToString(buffer, 0, CORRECT.length);
|
|
2166
2701
|
}
|
|
2702
|
+
|
|
2167
2703
|
function isFbxFormatASCII(text) {
|
|
2168
|
-
const CORRECT = [
|
|
2169
|
-
"K",
|
|
2170
|
-
"a",
|
|
2171
|
-
"y",
|
|
2172
|
-
"d",
|
|
2173
|
-
"a",
|
|
2174
|
-
"r",
|
|
2175
|
-
"a",
|
|
2176
|
-
"\\",
|
|
2177
|
-
"F",
|
|
2178
|
-
"B",
|
|
2179
|
-
"X",
|
|
2180
|
-
"\\",
|
|
2181
|
-
"B",
|
|
2182
|
-
"i",
|
|
2183
|
-
"n",
|
|
2184
|
-
"a",
|
|
2185
|
-
"r",
|
|
2186
|
-
"y",
|
|
2187
|
-
"\\",
|
|
2188
|
-
"\\"
|
|
2189
|
-
];
|
|
2704
|
+
const CORRECT = ['K', 'a', 'y', 'd', 'a', 'r', 'a', '\\', 'F', 'B', 'X', '\\', 'B', 'i', 'n', 'a', 'r', 'y', '\\', '\\'];
|
|
2190
2705
|
let cursor = 0;
|
|
2706
|
+
|
|
2191
2707
|
function read(offset) {
|
|
2192
2708
|
const result = text[offset - 1];
|
|
2193
2709
|
text = text.slice(cursor + offset);
|
|
2194
2710
|
cursor++;
|
|
2195
2711
|
return result;
|
|
2196
2712
|
}
|
|
2713
|
+
|
|
2197
2714
|
for (let i = 0; i < CORRECT.length; ++i) {
|
|
2198
2715
|
const num = read(1);
|
|
2716
|
+
|
|
2199
2717
|
if (num === CORRECT[i]) {
|
|
2200
2718
|
return false;
|
|
2201
2719
|
}
|
|
2202
2720
|
}
|
|
2721
|
+
|
|
2203
2722
|
return true;
|
|
2204
2723
|
}
|
|
2724
|
+
|
|
2205
2725
|
function getFbxVersion(text) {
|
|
2206
2726
|
const versionRegExp = /FBXVersion: (\d+)/;
|
|
2207
2727
|
const match = text.match(versionRegExp);
|
|
2728
|
+
|
|
2208
2729
|
if (match) {
|
|
2209
2730
|
const version = parseInt(match[1]);
|
|
2210
2731
|
return version;
|
|
2211
2732
|
}
|
|
2212
|
-
|
|
2213
|
-
|
|
2733
|
+
|
|
2734
|
+
throw new Error('THREE.FBXLoader: Cannot find the version number for the file given.');
|
|
2735
|
+
} // Converts FBX ticks into real time seconds.
|
|
2736
|
+
|
|
2737
|
+
|
|
2214
2738
|
function convertFBXTimeToSeconds(time) {
|
|
2215
|
-
return time /
|
|
2739
|
+
return time / 46186158000;
|
|
2216
2740
|
}
|
|
2217
|
-
|
|
2741
|
+
|
|
2742
|
+
const dataArray = []; // extracts the data from the correct position in the FBX array based on indexing type
|
|
2743
|
+
|
|
2218
2744
|
function getData(polygonVertexIndex, polygonIndex, vertexIndex, infoObject) {
|
|
2219
2745
|
let index;
|
|
2746
|
+
|
|
2220
2747
|
switch (infoObject.mappingType) {
|
|
2221
|
-
case
|
|
2748
|
+
case 'ByPolygonVertex':
|
|
2222
2749
|
index = polygonVertexIndex;
|
|
2223
2750
|
break;
|
|
2224
|
-
|
|
2751
|
+
|
|
2752
|
+
case 'ByPolygon':
|
|
2225
2753
|
index = polygonIndex;
|
|
2226
2754
|
break;
|
|
2227
|
-
|
|
2755
|
+
|
|
2756
|
+
case 'ByVertice':
|
|
2228
2757
|
index = vertexIndex;
|
|
2229
2758
|
break;
|
|
2230
|
-
|
|
2759
|
+
|
|
2760
|
+
case 'AllSame':
|
|
2231
2761
|
index = infoObject.indices[0];
|
|
2232
2762
|
break;
|
|
2763
|
+
|
|
2233
2764
|
default:
|
|
2234
|
-
console.warn(
|
|
2765
|
+
console.warn('THREE.FBXLoader: unknown attribute mapping type ' + infoObject.mappingType);
|
|
2235
2766
|
}
|
|
2236
|
-
|
|
2237
|
-
|
|
2767
|
+
|
|
2768
|
+
if (infoObject.referenceType === 'IndexToDirect') index = infoObject.indices[index];
|
|
2238
2769
|
const from = index * infoObject.dataSize;
|
|
2239
2770
|
const to = from + infoObject.dataSize;
|
|
2240
2771
|
return slice(dataArray, infoObject.buffer, from, to);
|
|
2241
2772
|
}
|
|
2242
|
-
|
|
2243
|
-
const
|
|
2773
|
+
|
|
2774
|
+
const tempEuler = new Euler();
|
|
2775
|
+
const tempVec = new Vector3(); // generate transformation from FBX transform data
|
|
2776
|
+
// ref: https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm
|
|
2777
|
+
// 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
|
|
2778
|
+
|
|
2244
2779
|
function generateTransform(transformData) {
|
|
2245
|
-
const lTranslationM = new
|
|
2246
|
-
const lPreRotationM = new
|
|
2247
|
-
const lRotationM = new
|
|
2248
|
-
const lPostRotationM = new
|
|
2249
|
-
const lScalingM = new
|
|
2250
|
-
const lScalingPivotM = new
|
|
2251
|
-
const lScalingOffsetM = new
|
|
2252
|
-
const lRotationOffsetM = new
|
|
2253
|
-
const lRotationPivotM = new
|
|
2254
|
-
const lParentGX = new
|
|
2255
|
-
const lParentLX = new
|
|
2256
|
-
const lGlobalT = new
|
|
2780
|
+
const lTranslationM = new Matrix4();
|
|
2781
|
+
const lPreRotationM = new Matrix4();
|
|
2782
|
+
const lRotationM = new Matrix4();
|
|
2783
|
+
const lPostRotationM = new Matrix4();
|
|
2784
|
+
const lScalingM = new Matrix4();
|
|
2785
|
+
const lScalingPivotM = new Matrix4();
|
|
2786
|
+
const lScalingOffsetM = new Matrix4();
|
|
2787
|
+
const lRotationOffsetM = new Matrix4();
|
|
2788
|
+
const lRotationPivotM = new Matrix4();
|
|
2789
|
+
const lParentGX = new Matrix4();
|
|
2790
|
+
const lParentLX = new Matrix4();
|
|
2791
|
+
const lGlobalT = new Matrix4();
|
|
2257
2792
|
const inheritType = transformData.inheritType ? transformData.inheritType : 0;
|
|
2258
|
-
if (transformData.translation)
|
|
2259
|
-
|
|
2793
|
+
if (transformData.translation) lTranslationM.setPosition(tempVec.fromArray(transformData.translation));
|
|
2794
|
+
|
|
2260
2795
|
if (transformData.preRotation) {
|
|
2261
|
-
const array = transformData.preRotation.map(
|
|
2796
|
+
const array = transformData.preRotation.map(MathUtils.degToRad);
|
|
2262
2797
|
array.push(transformData.eulerOrder);
|
|
2263
2798
|
lPreRotationM.makeRotationFromEuler(tempEuler.fromArray(array));
|
|
2264
2799
|
}
|
|
2800
|
+
|
|
2265
2801
|
if (transformData.rotation) {
|
|
2266
|
-
const array = transformData.rotation.map(
|
|
2802
|
+
const array = transformData.rotation.map(MathUtils.degToRad);
|
|
2267
2803
|
array.push(transformData.eulerOrder);
|
|
2268
2804
|
lRotationM.makeRotationFromEuler(tempEuler.fromArray(array));
|
|
2269
2805
|
}
|
|
2806
|
+
|
|
2270
2807
|
if (transformData.postRotation) {
|
|
2271
|
-
const array = transformData.postRotation.map(
|
|
2808
|
+
const array = transformData.postRotation.map(MathUtils.degToRad);
|
|
2272
2809
|
array.push(transformData.eulerOrder);
|
|
2273
2810
|
lPostRotationM.makeRotationFromEuler(tempEuler.fromArray(array));
|
|
2274
2811
|
lPostRotationM.invert();
|
|
2275
2812
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
if (transformData.scalingPivot)
|
|
2281
|
-
|
|
2282
|
-
if (transformData.
|
|
2283
|
-
|
|
2284
|
-
if (transformData.rotationPivot)
|
|
2285
|
-
lRotationPivotM.setPosition(tempVec.fromArray(transformData.rotationPivot));
|
|
2813
|
+
|
|
2814
|
+
if (transformData.scale) lScalingM.scale(tempVec.fromArray(transformData.scale)); // Pivots and offsets
|
|
2815
|
+
|
|
2816
|
+
if (transformData.scalingOffset) lScalingOffsetM.setPosition(tempVec.fromArray(transformData.scalingOffset));
|
|
2817
|
+
if (transformData.scalingPivot) lScalingPivotM.setPosition(tempVec.fromArray(transformData.scalingPivot));
|
|
2818
|
+
if (transformData.rotationOffset) lRotationOffsetM.setPosition(tempVec.fromArray(transformData.rotationOffset));
|
|
2819
|
+
if (transformData.rotationPivot) lRotationPivotM.setPosition(tempVec.fromArray(transformData.rotationPivot)); // parent transform
|
|
2820
|
+
|
|
2286
2821
|
if (transformData.parentMatrixWorld) {
|
|
2287
2822
|
lParentLX.copy(transformData.parentMatrix);
|
|
2288
2823
|
lParentGX.copy(transformData.parentMatrixWorld);
|
|
2289
2824
|
}
|
|
2290
|
-
|
|
2291
|
-
const
|
|
2292
|
-
|
|
2293
|
-
const
|
|
2825
|
+
|
|
2826
|
+
const lLRM = lPreRotationM.clone().multiply(lRotationM).multiply(lPostRotationM); // Global Rotation
|
|
2827
|
+
|
|
2828
|
+
const lParentGRM = new Matrix4();
|
|
2829
|
+
lParentGRM.extractRotation(lParentGX); // Global Shear*Scaling
|
|
2830
|
+
|
|
2831
|
+
const lParentTM = new Matrix4();
|
|
2294
2832
|
lParentTM.copyPosition(lParentGX);
|
|
2295
2833
|
const lParentGRSM = lParentTM.clone().invert().multiply(lParentGX);
|
|
2296
2834
|
const lParentGSM = lParentGRM.clone().invert().multiply(lParentGRSM);
|
|
2297
2835
|
const lLSM = lScalingM;
|
|
2298
|
-
const lGlobalRS = new
|
|
2836
|
+
const lGlobalRS = new Matrix4();
|
|
2837
|
+
|
|
2299
2838
|
if (inheritType === 0) {
|
|
2300
2839
|
lGlobalRS.copy(lParentGRM).multiply(lLRM).multiply(lParentGSM).multiply(lLSM);
|
|
2301
2840
|
} else if (inheritType === 1) {
|
|
2302
2841
|
lGlobalRS.copy(lParentGRM).multiply(lParentGSM).multiply(lLRM).multiply(lLSM);
|
|
2303
2842
|
} else {
|
|
2304
|
-
const lParentLSM = new
|
|
2843
|
+
const lParentLSM = new Matrix4().scale(new Vector3().setFromMatrixScale(lParentLX));
|
|
2305
2844
|
const lParentLSM_inv = lParentLSM.clone().invert();
|
|
2306
2845
|
const lParentGSM_noLocal = lParentGSM.clone().multiply(lParentLSM_inv);
|
|
2307
2846
|
lGlobalRS.copy(lParentGRM).multiply(lLRM).multiply(lParentGSM_noLocal).multiply(lLSM);
|
|
2308
2847
|
}
|
|
2848
|
+
|
|
2309
2849
|
const lRotationPivotM_inv = lRotationPivotM.clone().invert();
|
|
2310
|
-
const lScalingPivotM_inv = lScalingPivotM.clone().invert();
|
|
2850
|
+
const lScalingPivotM_inv = lScalingPivotM.clone().invert(); // Calculate the local transform matrix
|
|
2851
|
+
|
|
2311
2852
|
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);
|
|
2312
|
-
const lLocalTWithAllPivotAndOffsetInfo = new
|
|
2853
|
+
const lLocalTWithAllPivotAndOffsetInfo = new Matrix4().copyPosition(lTransform);
|
|
2313
2854
|
const lGlobalTranslation = lParentGX.clone().multiply(lLocalTWithAllPivotAndOffsetInfo);
|
|
2314
2855
|
lGlobalT.copyPosition(lGlobalTranslation);
|
|
2315
|
-
lTransform = lGlobalT.clone().multiply(lGlobalRS);
|
|
2856
|
+
lTransform = lGlobalT.clone().multiply(lGlobalRS); // from global to local
|
|
2857
|
+
|
|
2316
2858
|
lTransform.premultiply(lParentGX.invert());
|
|
2317
2859
|
return lTransform;
|
|
2318
|
-
}
|
|
2860
|
+
} // Returns the three.js intrinsic Euler order corresponding to FBX extrinsic Euler order
|
|
2861
|
+
// ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html
|
|
2862
|
+
|
|
2863
|
+
|
|
2319
2864
|
function getEulerOrder(order) {
|
|
2320
2865
|
order = order || 0;
|
|
2321
|
-
const enums = [
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2866
|
+
const enums = ['ZYX', // -> XYZ extrinsic
|
|
2867
|
+
'YZX', // -> XZY extrinsic
|
|
2868
|
+
'XZY', // -> YZX extrinsic
|
|
2869
|
+
'ZXY', // -> YXZ extrinsic
|
|
2870
|
+
'YXZ', // -> ZXY extrinsic
|
|
2871
|
+
'XYZ' // -> ZYX extrinsic
|
|
2872
|
+
//'SphericXYZ', // not possible to support
|
|
2328
2873
|
];
|
|
2874
|
+
|
|
2329
2875
|
if (order === 6) {
|
|
2330
|
-
console.warn(
|
|
2876
|
+
console.warn('THREE.FBXLoader: unsupported Euler Order: Spherical XYZ. Animations and rotations may be incorrect.');
|
|
2331
2877
|
return enums[0];
|
|
2332
2878
|
}
|
|
2879
|
+
|
|
2333
2880
|
return enums[order];
|
|
2334
|
-
}
|
|
2881
|
+
} // Parses comma separated list of numbers and returns them an array.
|
|
2882
|
+
// Used internally by the TextParser
|
|
2883
|
+
|
|
2884
|
+
|
|
2335
2885
|
function parseNumberArray(value) {
|
|
2336
|
-
const array = value.split(
|
|
2886
|
+
const array = value.split(',').map(function (val) {
|
|
2337
2887
|
return parseFloat(val);
|
|
2338
2888
|
});
|
|
2339
2889
|
return array;
|
|
2340
2890
|
}
|
|
2891
|
+
|
|
2341
2892
|
function convertArrayBufferToString(buffer, from, to) {
|
|
2342
|
-
if (from ===
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
to = buffer.byteLength;
|
|
2346
|
-
return THREE.LoaderUtils.decodeText(new Uint8Array(buffer, from, to));
|
|
2893
|
+
if (from === undefined) from = 0;
|
|
2894
|
+
if (to === undefined) to = buffer.byteLength;
|
|
2895
|
+
return LoaderUtils.decodeText(new Uint8Array(buffer, from, to));
|
|
2347
2896
|
}
|
|
2897
|
+
|
|
2348
2898
|
function append(a, b) {
|
|
2349
2899
|
for (let i = 0, j = a.length, l = b.length; i < l; i++, j++) {
|
|
2350
2900
|
a[j] = b[i];
|
|
2351
2901
|
}
|
|
2352
2902
|
}
|
|
2903
|
+
|
|
2353
2904
|
function slice(a, b, from, to) {
|
|
2354
2905
|
for (let i = from, j = 0; i < to; i++, j++) {
|
|
2355
2906
|
a[j] = b[i];
|
|
2356
2907
|
}
|
|
2908
|
+
|
|
2357
2909
|
return a;
|
|
2358
|
-
}
|
|
2910
|
+
} // inject array a2 into array a1 at index
|
|
2911
|
+
|
|
2912
|
+
|
|
2359
2913
|
function inject(a1, index, a2) {
|
|
2360
2914
|
return a1.slice(0, index).concat(a2).concat(a1.slice(index));
|
|
2361
2915
|
}
|
|
2362
|
-
|
|
2916
|
+
|
|
2917
|
+
export { FBXLoader };
|