{"version":3,"file":"FBXLoader.cjs","sources":["../../src/loaders/FBXLoader.js"],"sourcesContent":["import {\n  AmbientLight,\n  AnimationClip,\n  Bone,\n  BufferGeometry,\n  ClampToEdgeWrapping,\n  Color,\n  DirectionalLight,\n  EquirectangularReflectionMapping,\n  Euler,\n  FileLoader,\n  Float32BufferAttribute,\n  Group,\n  Line,\n  LineBasicMaterial,\n  Loader,\n  LoaderUtils,\n  MathUtils,\n  Matrix3,\n  Matrix4,\n  Mesh,\n  MeshLambertMaterial,\n  MeshPhongMaterial,\n  NumberKeyframeTrack,\n  Object3D,\n  OrthographicCamera,\n  PerspectiveCamera,\n  PointLight,\n  PropertyBinding,\n  Quaternion,\n  QuaternionKeyframeTrack,\n  RepeatWrapping,\n  Skeleton,\n  SkinnedMesh,\n  SpotLight,\n  Texture,\n  TextureLoader,\n  Uint16BufferAttribute,\n  Vector3,\n  Vector4,\n  VectorKeyframeTrack,\n} from 'three'\nimport { unzlibSync } from 'fflate'\nimport { NURBSCurve } from '../curves/NURBSCurve'\nimport { decodeText } from '../_polyfill/LoaderUtils'\nimport { UV1 } from '../_polyfill/uv1'\n\n/**\n * Loader loads FBX file and generates Group representing FBX scene.\n * Requires FBX file to be >= 7.0 and in ASCII or >= 6400 in Binary format\n * Versions lower than this may load but will probably have errors\n *\n * Needs Support:\n *  Morph normals / blend shape normals\n *\n * FBX format references:\n * \thttps://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_index_html (C++ SDK reference)\n *\n * Binary format specification:\n *\thttps://code.blender.org/2013/08/fbx-binary-file-format-specification/\n */\n\nlet fbxTree\nlet connections\nlet sceneGraph\n\nclass FBXLoader extends Loader {\n  constructor(manager) {\n    super(manager)\n  }\n\n  load(url, onLoad, onProgress, onError) {\n    const scope = this\n\n    const path = scope.path === '' ? LoaderUtils.extractUrlBase(url) : scope.path\n\n    const loader = new FileLoader(this.manager)\n    loader.setPath(scope.path)\n    loader.setResponseType('arraybuffer')\n    loader.setRequestHeader(scope.requestHeader)\n    loader.setWithCredentials(scope.withCredentials)\n\n    loader.load(\n      url,\n      function (buffer) {\n        try {\n          onLoad(scope.parse(buffer, path))\n        } catch (e) {\n          if (onError) {\n            onError(e)\n          } else {\n            console.error(e)\n          }\n\n          scope.manager.itemError(url)\n        }\n      },\n      onProgress,\n      onError,\n    )\n  }\n\n  parse(FBXBuffer, path) {\n    if (isFbxFormatBinary(FBXBuffer)) {\n      fbxTree = new BinaryParser().parse(FBXBuffer)\n    } else {\n      const FBXText = convertArrayBufferToString(FBXBuffer)\n\n      if (!isFbxFormatASCII(FBXText)) {\n        throw new Error('THREE.FBXLoader: Unknown format.')\n      }\n\n      if (getFbxVersion(FBXText) < 7000) {\n        throw new Error('THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion(FBXText))\n      }\n\n      fbxTree = new TextParser().parse(FBXText)\n    }\n\n    // console.log( fbxTree );\n\n    const textureLoader = new TextureLoader(this.manager)\n      .setPath(this.resourcePath || path)\n      .setCrossOrigin(this.crossOrigin)\n\n    return new FBXTreeParser(textureLoader, this.manager).parse(fbxTree)\n  }\n}\n\n// Parse the FBXTree object returned by the BinaryParser or TextParser and return a Group\nclass FBXTreeParser {\n  constructor(textureLoader, manager) {\n    this.textureLoader = textureLoader\n    this.manager = manager\n  }\n\n  parse() {\n    connections = this.parseConnections()\n\n    const images = this.parseImages()\n    const textures = this.parseTextures(images)\n    const materials = this.parseMaterials(textures)\n    const deformers = this.parseDeformers()\n    const geometryMap = new GeometryParser().parse(deformers)\n\n    this.parseScene(deformers, geometryMap, materials)\n\n    return sceneGraph\n  }\n\n  // Parses FBXTree.Connections which holds parent-child connections between objects (e.g. material -> texture, model->geometry )\n  // and details the connection type\n  parseConnections() {\n    const connectionMap = new Map()\n\n    if ('Connections' in fbxTree) {\n      const rawConnections = fbxTree.Connections.connections\n\n      rawConnections.forEach(function (rawConnection) {\n        const fromID = rawConnection[0]\n        const toID = rawConnection[1]\n        const relationship = rawConnection[2]\n\n        if (!connectionMap.has(fromID)) {\n          connectionMap.set(fromID, {\n            parents: [],\n            children: [],\n          })\n        }\n\n        const parentRelationship = { ID: toID, relationship: relationship }\n        connectionMap.get(fromID).parents.push(parentRelationship)\n\n        if (!connectionMap.has(toID)) {\n          connectionMap.set(toID, {\n            parents: [],\n            children: [],\n          })\n        }\n\n        const childRelationship = { ID: fromID, relationship: relationship }\n        connectionMap.get(toID).children.push(childRelationship)\n      })\n    }\n\n    return connectionMap\n  }\n\n  // Parse FBXTree.Objects.Video for embedded image data\n  // These images are connected to textures in FBXTree.Objects.Textures\n  // via FBXTree.Connections.\n  parseImages() {\n    const images = {}\n    const blobs = {}\n\n    if ('Video' in fbxTree.Objects) {\n      const videoNodes = fbxTree.Objects.Video\n\n      for (const nodeID in videoNodes) {\n        const videoNode = videoNodes[nodeID]\n\n        const id = parseInt(nodeID)\n\n        images[id] = videoNode.RelativeFilename || videoNode.Filename\n\n        // raw image data is in videoNode.Content\n        if ('Content' in videoNode) {\n          const arrayBufferContent = videoNode.Content instanceof ArrayBuffer && videoNode.Content.byteLength > 0\n          const base64Content = typeof videoNode.Content === 'string' && videoNode.Content !== ''\n\n          if (arrayBufferContent || base64Content) {\n            const image = this.parseImage(videoNodes[nodeID])\n\n            blobs[videoNode.RelativeFilename || videoNode.Filename] = image\n          }\n        }\n      }\n    }\n\n    for (const id in images) {\n      const filename = images[id]\n\n      if (blobs[filename] !== undefined) images[id] = blobs[filename]\n      else images[id] = images[id].split('\\\\').pop()\n    }\n\n    return images\n  }\n\n  // Parse embedded image data in FBXTree.Video.Content\n  parseImage(videoNode) {\n    const content = videoNode.Content\n    const fileName = videoNode.RelativeFilename || videoNode.Filename\n    const extension = fileName.slice(fileName.lastIndexOf('.') + 1).toLowerCase()\n\n    let type\n\n    switch (extension) {\n      case 'bmp':\n        type = 'image/bmp'\n        break\n\n      case 'jpg':\n      case 'jpeg':\n        type = 'image/jpeg'\n        break\n\n      case 'png':\n        type = 'image/png'\n        break\n\n      case 'tif':\n        type = 'image/tiff'\n        break\n\n      case 'tga':\n        if (this.manager.getHandler('.tga') === null) {\n          console.warn('FBXLoader: TGA loader not found, skipping ', fileName)\n        }\n\n        type = 'image/tga'\n        break\n\n      default:\n        console.warn('FBXLoader: Image type \"' + extension + '\" is not supported.')\n        return\n    }\n\n    if (typeof content === 'string') {\n      // ASCII format\n\n      return 'data:' + type + ';base64,' + content\n    } else {\n      // Binary Format\n\n      const array = new Uint8Array(content)\n      return window.URL.createObjectURL(new Blob([array], { type: type }))\n    }\n  }\n\n  // Parse nodes in FBXTree.Objects.Texture\n  // These contain details such as UV scaling, cropping, rotation etc and are connected\n  // to images in FBXTree.Objects.Video\n  parseTextures(images) {\n    const textureMap = new Map()\n\n    if ('Texture' in fbxTree.Objects) {\n      const textureNodes = fbxTree.Objects.Texture\n      for (const nodeID in textureNodes) {\n        const texture = this.parseTexture(textureNodes[nodeID], images)\n        textureMap.set(parseInt(nodeID), texture)\n      }\n    }\n\n    return textureMap\n  }\n\n  // Parse individual node in FBXTree.Objects.Texture\n  parseTexture(textureNode, images) {\n    const texture = this.loadTexture(textureNode, images)\n\n    texture.ID = textureNode.id\n\n    texture.name = textureNode.attrName\n\n    const wrapModeU = textureNode.WrapModeU\n    const wrapModeV = textureNode.WrapModeV\n\n    const valueU = wrapModeU !== undefined ? wrapModeU.value : 0\n    const valueV = wrapModeV !== undefined ? wrapModeV.value : 0\n\n    // http://download.autodesk.com/us/fbx/SDKdocs/FBX_SDK_Help/files/fbxsdkref/class_k_fbx_texture.html#889640e63e2e681259ea81061b85143a\n    // 0: repeat(default), 1: clamp\n\n    texture.wrapS = valueU === 0 ? RepeatWrapping : ClampToEdgeWrapping\n    texture.wrapT = valueV === 0 ? RepeatWrapping : ClampToEdgeWrapping\n\n    if ('Scaling' in textureNode) {\n      const values = textureNode.Scaling.value\n\n      texture.repeat.x = values[0]\n      texture.repeat.y = values[1]\n    }\n\n    return texture\n  }\n\n  // load a texture specified as a blob or data URI, or via an external URL using TextureLoader\n  loadTexture(textureNode, images) {\n    let fileName\n\n    const currentPath = this.textureLoader.path\n\n    const children = connections.get(textureNode.id).children\n\n    if (children !== undefined && children.length > 0 && images[children[0].ID] !== undefined) {\n      fileName = images[children[0].ID]\n\n      if (fileName.indexOf('blob:') === 0 || fileName.indexOf('data:') === 0) {\n        this.textureLoader.setPath(undefined)\n      }\n    }\n\n    let texture\n\n    const extension = textureNode.FileName.slice(-3).toLowerCase()\n\n    if (extension === 'tga') {\n      const loader = this.manager.getHandler('.tga')\n\n      if (loader === null) {\n        console.warn('FBXLoader: TGA loader not found, creating placeholder texture for', textureNode.RelativeFilename)\n        texture = new Texture()\n      } else {\n        loader.setPath(this.textureLoader.path)\n        texture = loader.load(fileName)\n      }\n    } else if (extension === 'psd') {\n      console.warn(\n        'FBXLoader: PSD textures are not supported, creating placeholder texture for',\n        textureNode.RelativeFilename,\n      )\n      texture = new Texture()\n    } else {\n      texture = this.textureLoader.load(fileName)\n    }\n\n    this.textureLoader.setPath(currentPath)\n\n    return texture\n  }\n\n  // Parse nodes in FBXTree.Objects.Material\n  parseMaterials(textureMap) {\n    const materialMap = new Map()\n\n    if ('Material' in fbxTree.Objects) {\n      const materialNodes = fbxTree.Objects.Material\n\n      for (const nodeID in materialNodes) {\n        const material = this.parseMaterial(materialNodes[nodeID], textureMap)\n\n        if (material !== null) materialMap.set(parseInt(nodeID), material)\n      }\n    }\n\n    return materialMap\n  }\n\n  // Parse single node in FBXTree.Objects.Material\n  // Materials are connected to texture maps in FBXTree.Objects.Textures\n  // FBX format currently only supports Lambert and Phong shading models\n  parseMaterial(materialNode, textureMap) {\n    const ID = materialNode.id\n    const name = materialNode.attrName\n    let type = materialNode.ShadingModel\n\n    // Case where FBX wraps shading model in property object.\n    if (typeof type === 'object') {\n      type = type.value\n    }\n\n    // Ignore unused materials which don't have any connections.\n    if (!connections.has(ID)) return null\n\n    const parameters = this.parseParameters(materialNode, textureMap, ID)\n\n    let material\n\n    switch (type.toLowerCase()) {\n      case 'phong':\n        material = new MeshPhongMaterial()\n        break\n      case 'lambert':\n        material = new MeshLambertMaterial()\n        break\n      default:\n        console.warn('THREE.FBXLoader: unknown material type \"%s\". Defaulting to MeshPhongMaterial.', type)\n        material = new MeshPhongMaterial()\n        break\n    }\n\n    material.setValues(parameters)\n    material.name = name\n\n    return material\n  }\n\n  // Parse FBX material and return parameters suitable for a three.js material\n  // Also parse the texture map and return any textures associated with the material\n  parseParameters(materialNode, textureMap, ID) {\n    const parameters = {}\n\n    if (materialNode.BumpFactor) {\n      parameters.bumpScale = materialNode.BumpFactor.value\n    }\n\n    if (materialNode.Diffuse) {\n      parameters.color = new Color().fromArray(materialNode.Diffuse.value)\n    } else if (\n      materialNode.DiffuseColor &&\n      (materialNode.DiffuseColor.type === 'Color' || materialNode.DiffuseColor.type === 'ColorRGB')\n    ) {\n      // The blender exporter exports diffuse here instead of in materialNode.Diffuse\n      parameters.color = new Color().fromArray(materialNode.DiffuseColor.value)\n    }\n\n    if (materialNode.DisplacementFactor) {\n      parameters.displacementScale = materialNode.DisplacementFactor.value\n    }\n\n    if (materialNode.Emissive) {\n      parameters.emissive = new Color().fromArray(materialNode.Emissive.value)\n    } else if (\n      materialNode.EmissiveColor &&\n      (materialNode.EmissiveColor.type === 'Color' || materialNode.EmissiveColor.type === 'ColorRGB')\n    ) {\n      // The blender exporter exports emissive color here instead of in materialNode.Emissive\n      parameters.emissive = new Color().fromArray(materialNode.EmissiveColor.value)\n    }\n\n    if (materialNode.EmissiveFactor) {\n      parameters.emissiveIntensity = parseFloat(materialNode.EmissiveFactor.value)\n    }\n\n    if (materialNode.Opacity) {\n      parameters.opacity = parseFloat(materialNode.Opacity.value)\n    }\n\n    if (parameters.opacity < 1.0) {\n      parameters.transparent = true\n    }\n\n    if (materialNode.ReflectionFactor) {\n      parameters.reflectivity = materialNode.ReflectionFactor.value\n    }\n\n    if (materialNode.Shininess) {\n      parameters.shininess = materialNode.Shininess.value\n    }\n\n    if (materialNode.Specular) {\n      parameters.specular = new Color().fromArray(materialNode.Specular.value)\n    } else if (materialNode.SpecularColor && materialNode.SpecularColor.type === 'Color') {\n      // The blender exporter exports specular color here instead of in materialNode.Specular\n      parameters.specular = new Color().fromArray(materialNode.SpecularColor.value)\n    }\n\n    const scope = this\n    connections.get(ID).children.forEach(function (child) {\n      const type = child.relationship\n\n      switch (type) {\n        case 'Bump':\n          parameters.bumpMap = scope.getTexture(textureMap, child.ID)\n          break\n\n        case 'Maya|TEX_ao_map':\n          parameters.aoMap = scope.getTexture(textureMap, child.ID)\n          break\n\n        case 'DiffuseColor':\n        case 'Maya|TEX_color_map':\n          parameters.map = scope.getTexture(textureMap, child.ID)\n          if (parameters.map !== undefined) {\n            if ('colorSpace' in parameters.map) parameters.map.colorSpace = 'srgb'\n            else parameters.map.encoding = 3001 // sRGBEncoding\n          }\n\n          break\n\n        case 'DisplacementColor':\n          parameters.displacementMap = scope.getTexture(textureMap, child.ID)\n          break\n\n        case 'EmissiveColor':\n          parameters.emissiveMap = scope.getTexture(textureMap, child.ID)\n          if (parameters.emissiveMap !== undefined) {\n            if ('colorSpace' in parameters.emissiveMap) parameters.emissiveMap.colorSpace = 'srgb'\n            else parameters.emissiveMap.encoding = 3001 // sRGBEncoding\n          }\n\n          break\n\n        case 'NormalMap':\n        case 'Maya|TEX_normal_map':\n          parameters.normalMap = scope.getTexture(textureMap, child.ID)\n          break\n\n        case 'ReflectionColor':\n          parameters.envMap = scope.getTexture(textureMap, child.ID)\n          if (parameters.envMap !== undefined) {\n            parameters.envMap.mapping = EquirectangularReflectionMapping\n\n            if ('colorSpace' in parameters.envMap) parameters.envMap.colorSpace = 'srgb'\n            else parameters.envMap.encoding = 3001 // sRGBEncoding\n          }\n\n          break\n\n        case 'SpecularColor':\n          parameters.specularMap = scope.getTexture(textureMap, child.ID)\n          if (parameters.specularMap !== undefined) {\n            if ('colorSpace' in parameters.specularMap) parameters.specularMap.colorSpace = 'srgb'\n            else parameters.specularMap.encoding = 3001 // sRGBEncoding\n          }\n\n          break\n\n        case 'TransparentColor':\n        case 'TransparencyFactor':\n          parameters.alphaMap = scope.getTexture(textureMap, child.ID)\n          parameters.transparent = true\n          break\n\n        case 'AmbientColor':\n        case 'ShininessExponent': // AKA glossiness map\n        case 'SpecularFactor': // AKA specularLevel\n        case 'VectorDisplacementColor': // NOTE: Seems to be a copy of DisplacementColor\n        default:\n          console.warn('THREE.FBXLoader: %s map is not supported in three.js, skipping texture.', type)\n          break\n      }\n    })\n\n    return parameters\n  }\n\n  // get a texture from the textureMap for use by a material.\n  getTexture(textureMap, id) {\n    // if the texture is a layered texture, just use the first layer and issue a warning\n    if ('LayeredTexture' in fbxTree.Objects && id in fbxTree.Objects.LayeredTexture) {\n      console.warn('THREE.FBXLoader: layered textures are not supported in three.js. Discarding all but first layer.')\n      id = connections.get(id).children[0].ID\n    }\n\n    return textureMap.get(id)\n  }\n\n  // Parse nodes in FBXTree.Objects.Deformer\n  // Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here\n  // Generates map of Skeleton-like objects for use later when generating and binding skeletons.\n  parseDeformers() {\n    const skeletons = {}\n    const morphTargets = {}\n\n    if ('Deformer' in fbxTree.Objects) {\n      const DeformerNodes = fbxTree.Objects.Deformer\n\n      for (const nodeID in DeformerNodes) {\n        const deformerNode = DeformerNodes[nodeID]\n\n        const relationships = connections.get(parseInt(nodeID))\n\n        if (deformerNode.attrType === 'Skin') {\n          const skeleton = this.parseSkeleton(relationships, DeformerNodes)\n          skeleton.ID = nodeID\n\n          if (relationships.parents.length > 1) {\n            console.warn('THREE.FBXLoader: skeleton attached to more than one geometry is not supported.')\n          }\n          skeleton.geometryID = relationships.parents[0].ID\n\n          skeletons[nodeID] = skeleton\n        } else if (deformerNode.attrType === 'BlendShape') {\n          const morphTarget = {\n            id: nodeID,\n          }\n\n          morphTarget.rawTargets = this.parseMorphTargets(relationships, DeformerNodes)\n          morphTarget.id = nodeID\n\n          if (relationships.parents.length > 1) {\n            console.warn('THREE.FBXLoader: morph target attached to more than one geometry is not supported.')\n          }\n\n          morphTargets[nodeID] = morphTarget\n        }\n      }\n    }\n\n    return {\n      skeletons: skeletons,\n      morphTargets: morphTargets,\n    }\n  }\n\n  // Parse single nodes in FBXTree.Objects.Deformer\n  // The top level skeleton node has type 'Skin' and sub nodes have type 'Cluster'\n  // Each skin node represents a skeleton and each cluster node represents a bone\n  parseSkeleton(relationships, deformerNodes) {\n    const rawBones = []\n\n    relationships.children.forEach(function (child) {\n      const boneNode = deformerNodes[child.ID]\n\n      if (boneNode.attrType !== 'Cluster') return\n\n      const rawBone = {\n        ID: child.ID,\n        indices: [],\n        weights: [],\n        transformLink: new Matrix4().fromArray(boneNode.TransformLink.a),\n        // transform: new Matrix4().fromArray( boneNode.Transform.a ),\n        // linkMode: boneNode.Mode,\n      }\n\n      if ('Indexes' in boneNode) {\n        rawBone.indices = boneNode.Indexes.a\n        rawBone.weights = boneNode.Weights.a\n      }\n\n      rawBones.push(rawBone)\n    })\n\n    return {\n      rawBones: rawBones,\n      bones: [],\n    }\n  }\n\n  // The top level morph deformer node has type \"BlendShape\" and sub nodes have type \"BlendShapeChannel\"\n  parseMorphTargets(relationships, deformerNodes) {\n    const rawMorphTargets = []\n\n    for (let i = 0; i < relationships.children.length; i++) {\n      const child = relationships.children[i]\n\n      const morphTargetNode = deformerNodes[child.ID]\n\n      const rawMorphTarget = {\n        name: morphTargetNode.attrName,\n        initialWeight: morphTargetNode.DeformPercent,\n        id: morphTargetNode.id,\n        fullWeights: morphTargetNode.FullWeights.a,\n      }\n\n      if (morphTargetNode.attrType !== 'BlendShapeChannel') return\n\n      rawMorphTarget.geoID = connections.get(parseInt(child.ID)).children.filter(function (child) {\n        return child.relationship === undefined\n      })[0].ID\n\n      rawMorphTargets.push(rawMorphTarget)\n    }\n\n    return rawMorphTargets\n  }\n\n  // create the main Group() to be returned by the loader\n  parseScene(deformers, geometryMap, materialMap) {\n    sceneGraph = new Group()\n\n    const modelMap = this.parseModels(deformers.skeletons, geometryMap, materialMap)\n\n    const modelNodes = fbxTree.Objects.Model\n\n    const scope = this\n    modelMap.forEach(function (model) {\n      const modelNode = modelNodes[model.ID]\n      scope.setLookAtProperties(model, modelNode)\n\n      const parentConnections = connections.get(model.ID).parents\n\n      parentConnections.forEach(function (connection) {\n        const parent = modelMap.get(connection.ID)\n        if (parent !== undefined) parent.add(model)\n      })\n\n      if (model.parent === null) {\n        sceneGraph.add(model)\n      }\n    })\n\n    this.bindSkeleton(deformers.skeletons, geometryMap, modelMap)\n\n    this.createAmbientLight()\n\n    sceneGraph.traverse(function (node) {\n      if (node.userData.transformData) {\n        if (node.parent) {\n          node.userData.transformData.parentMatrix = node.parent.matrix\n          node.userData.transformData.parentMatrixWorld = node.parent.matrixWorld\n        }\n\n        const transform = generateTransform(node.userData.transformData)\n\n        node.applyMatrix4(transform)\n        node.updateWorldMatrix()\n      }\n    })\n\n    const animations = new AnimationParser().parse()\n\n    // if all the models where already combined in a single group, just return that\n    if (sceneGraph.children.length === 1 && sceneGraph.children[0].isGroup) {\n      sceneGraph.children[0].animations = animations\n      sceneGraph = sceneGraph.children[0]\n    }\n\n    sceneGraph.animations = animations\n  }\n\n  // parse nodes in FBXTree.Objects.Model\n  parseModels(skeletons, geometryMap, materialMap) {\n    const modelMap = new Map()\n    const modelNodes = fbxTree.Objects.Model\n\n    for (const nodeID in modelNodes) {\n      const id = parseInt(nodeID)\n      const node = modelNodes[nodeID]\n      const relationships = connections.get(id)\n\n      let model = this.buildSkeleton(relationships, skeletons, id, node.attrName)\n\n      if (!model) {\n        switch (node.attrType) {\n          case 'Camera':\n            model = this.createCamera(relationships)\n            break\n          case 'Light':\n            model = this.createLight(relationships)\n            break\n          case 'Mesh':\n            model = this.createMesh(relationships, geometryMap, materialMap)\n            break\n          case 'NurbsCurve':\n            model = this.createCurve(relationships, geometryMap)\n            break\n          case 'LimbNode':\n          case 'Root':\n            model = new Bone()\n            break\n          case 'Null':\n          default:\n            model = new Group()\n            break\n        }\n\n        model.name = node.attrName ? PropertyBinding.sanitizeNodeName(node.attrName) : ''\n\n        model.ID = id\n      }\n\n      this.getTransformData(model, node)\n      modelMap.set(id, model)\n    }\n\n    return modelMap\n  }\n\n  buildSkeleton(relationships, skeletons, id, name) {\n    let bone = null\n\n    relationships.parents.forEach(function (parent) {\n      for (const ID in skeletons) {\n        const skeleton = skeletons[ID]\n\n        skeleton.rawBones.forEach(function (rawBone, i) {\n          if (rawBone.ID === parent.ID) {\n            const subBone = bone\n            bone = new Bone()\n\n            bone.matrixWorld.copy(rawBone.transformLink)\n\n            // set name and id here - otherwise in cases where \"subBone\" is created it will not have a name / id\n\n            bone.name = name ? PropertyBinding.sanitizeNodeName(name) : ''\n            bone.ID = id\n\n            skeleton.bones[i] = bone\n\n            // In cases where a bone is shared between multiple meshes\n            // duplicate the bone here and and it as a child of the first bone\n            if (subBone !== null) {\n              bone.add(subBone)\n            }\n          }\n        })\n      }\n    })\n\n    return bone\n  }\n\n  // create a PerspectiveCamera or OrthographicCamera\n  createCamera(relationships) {\n    let model\n    let cameraAttribute\n\n    relationships.children.forEach(function (child) {\n      const attr = fbxTree.Objects.NodeAttribute[child.ID]\n\n      if (attr !== undefined) {\n        cameraAttribute = attr\n      }\n    })\n\n    if (cameraAttribute === undefined) {\n      model = new Object3D()\n    } else {\n      let type = 0\n      if (cameraAttribute.CameraProjectionType !== undefined && cameraAttribute.CameraProjectionType.value === 1) {\n        type = 1\n      }\n\n      let nearClippingPlane = 1\n      if (cameraAttribute.NearPlane !== undefined) {\n        nearClippingPlane = cameraAttribute.NearPlane.value / 1000\n      }\n\n      let farClippingPlane = 1000\n      if (cameraAttribute.FarPlane !== undefined) {\n        farClippingPlane = cameraAttribute.FarPlane.value / 1000\n      }\n\n      let width = window.innerWidth\n      let height = window.innerHeight\n\n      if (cameraAttribute.AspectWidth !== undefined && cameraAttribute.AspectHeight !== undefined) {\n        width = cameraAttribute.AspectWidth.value\n        height = cameraAttribute.AspectHeight.value\n      }\n\n      const aspect = width / height\n\n      let fov = 45\n      if (cameraAttribute.FieldOfView !== undefined) {\n        fov = cameraAttribute.FieldOfView.value\n      }\n\n      const focalLength = cameraAttribute.FocalLength ? cameraAttribute.FocalLength.value : null\n\n      switch (type) {\n        case 0: // Perspective\n          model = new PerspectiveCamera(fov, aspect, nearClippingPlane, farClippingPlane)\n          if (focalLength !== null) model.setFocalLength(focalLength)\n          break\n\n        case 1: // Orthographic\n          model = new OrthographicCamera(\n            -width / 2,\n            width / 2,\n            height / 2,\n            -height / 2,\n            nearClippingPlane,\n            farClippingPlane,\n          )\n          break\n\n        default:\n          console.warn('THREE.FBXLoader: Unknown camera type ' + type + '.')\n          model = new Object3D()\n          break\n      }\n    }\n\n    return model\n  }\n\n  // Create a DirectionalLight, PointLight or SpotLight\n  createLight(relationships) {\n    let model\n    let lightAttribute\n\n    relationships.children.forEach(function (child) {\n      const attr = fbxTree.Objects.NodeAttribute[child.ID]\n\n      if (attr !== undefined) {\n        lightAttribute = attr\n      }\n    })\n\n    if (lightAttribute === undefined) {\n      model = new Object3D()\n    } else {\n      let type\n\n      // LightType can be undefined for Point lights\n      if (lightAttribute.LightType === undefined) {\n        type = 0\n      } else {\n        type = lightAttribute.LightType.value\n      }\n\n      let color = 0xffffff\n\n      if (lightAttribute.Color !== undefined) {\n        color = new Color().fromArray(lightAttribute.Color.value)\n      }\n\n      let intensity = lightAttribute.Intensity === undefined ? 1 : lightAttribute.Intensity.value / 100\n\n      // light disabled\n      if (lightAttribute.CastLightOnObject !== undefined && lightAttribute.CastLightOnObject.value === 0) {\n        intensity = 0\n      }\n\n      let distance = 0\n      if (lightAttribute.FarAttenuationEnd !== undefined) {\n        if (lightAttribute.EnableFarAttenuation !== undefined && lightAttribute.EnableFarAttenuation.value === 0) {\n          distance = 0\n        } else {\n          distance = lightAttribute.FarAttenuationEnd.value\n        }\n      }\n\n      // TODO: could this be calculated linearly from FarAttenuationStart to FarAttenuationEnd?\n      const decay = 1\n\n      switch (type) {\n        case 0: // Point\n          model = new PointLight(color, intensity, distance, decay)\n          break\n\n        case 1: // Directional\n          model = new DirectionalLight(color, intensity)\n          break\n\n        case 2: // Spot\n          let angle = Math.PI / 3\n\n          if (lightAttribute.InnerAngle !== undefined) {\n            angle = MathUtils.degToRad(lightAttribute.InnerAngle.value)\n          }\n\n          let penumbra = 0\n          if (lightAttribute.OuterAngle !== undefined) {\n            // TODO: this is not correct - FBX calculates outer and inner angle in degrees\n            // with OuterAngle > InnerAngle && OuterAngle <= Math.PI\n            // while three.js uses a penumbra between (0, 1) to attenuate the inner angle\n            penumbra = MathUtils.degToRad(lightAttribute.OuterAngle.value)\n            penumbra = Math.max(penumbra, 1)\n          }\n\n          model = new SpotLight(color, intensity, distance, angle, penumbra, decay)\n          break\n\n        default:\n          console.warn(\n            'THREE.FBXLoader: Unknown light type ' + lightAttribute.LightType.value + ', defaulting to a PointLight.',\n          )\n          model = new PointLight(color, intensity)\n          break\n      }\n\n      if (lightAttribute.CastShadows !== undefined && lightAttribute.CastShadows.value === 1) {\n        model.castShadow = true\n      }\n    }\n\n    return model\n  }\n\n  createMesh(relationships, geometryMap, materialMap) {\n    let model\n    let geometry = null\n    let material = null\n    const materials = []\n\n    // get geometry and materials(s) from connections\n    relationships.children.forEach(function (child) {\n      if (geometryMap.has(child.ID)) {\n        geometry = geometryMap.get(child.ID)\n      }\n\n      if (materialMap.has(child.ID)) {\n        materials.push(materialMap.get(child.ID))\n      }\n    })\n\n    if (materials.length > 1) {\n      material = materials\n    } else if (materials.length > 0) {\n      material = materials[0]\n    } else {\n      material = new MeshPhongMaterial({ color: 0xcccccc })\n      materials.push(material)\n    }\n\n    if ('color' in geometry.attributes) {\n      materials.forEach(function (material) {\n        material.vertexColors = true\n      })\n    }\n\n    if (geometry.FBX_Deformer) {\n      model = new SkinnedMesh(geometry, material)\n      model.normalizeSkinWeights()\n    } else {\n      model = new Mesh(geometry, material)\n    }\n\n    return model\n  }\n\n  createCurve(relationships, geometryMap) {\n    const geometry = relationships.children.reduce(function (geo, child) {\n      if (geometryMap.has(child.ID)) geo = geometryMap.get(child.ID)\n\n      return geo\n    }, null)\n\n    // FBX does not list materials for Nurbs lines, so we'll just put our own in here.\n    const material = new LineBasicMaterial({ color: 0x3300ff, linewidth: 1 })\n    return new Line(geometry, material)\n  }\n\n  // parse the model node for transform data\n  getTransformData(model, modelNode) {\n    const transformData = {}\n\n    if ('InheritType' in modelNode) transformData.inheritType = parseInt(modelNode.InheritType.value)\n\n    if ('RotationOrder' in modelNode) transformData.eulerOrder = getEulerOrder(modelNode.RotationOrder.value)\n    else transformData.eulerOrder = 'ZYX'\n\n    if ('Lcl_Translation' in modelNode) transformData.translation = modelNode.Lcl_Translation.value\n\n    if ('PreRotation' in modelNode) transformData.preRotation = modelNode.PreRotation.value\n    if ('Lcl_Rotation' in modelNode) transformData.rotation = modelNode.Lcl_Rotation.value\n    if ('PostRotation' in modelNode) transformData.postRotation = modelNode.PostRotation.value\n\n    if ('Lcl_Scaling' in modelNode) transformData.scale = modelNode.Lcl_Scaling.value\n\n    if ('ScalingOffset' in modelNode) transformData.scalingOffset = modelNode.ScalingOffset.value\n    if ('ScalingPivot' in modelNode) transformData.scalingPivot = modelNode.ScalingPivot.value\n\n    if ('RotationOffset' in modelNode) transformData.rotationOffset = modelNode.RotationOffset.value\n    if ('RotationPivot' in modelNode) transformData.rotationPivot = modelNode.RotationPivot.value\n\n    model.userData.transformData = transformData\n  }\n\n  setLookAtProperties(model, modelNode) {\n    if ('LookAtProperty' in modelNode) {\n      const children = connections.get(model.ID).children\n\n      children.forEach(function (child) {\n        if (child.relationship === 'LookAtProperty') {\n          const lookAtTarget = fbxTree.Objects.Model[child.ID]\n\n          if ('Lcl_Translation' in lookAtTarget) {\n            const pos = lookAtTarget.Lcl_Translation.value\n\n            // DirectionalLight, SpotLight\n            if (model.target !== undefined) {\n              model.target.position.fromArray(pos)\n              sceneGraph.add(model.target)\n            } else {\n              // Cameras and other Object3Ds\n\n              model.lookAt(new Vector3().fromArray(pos))\n            }\n          }\n        }\n      })\n    }\n  }\n\n  bindSkeleton(skeletons, geometryMap, modelMap) {\n    const bindMatrices = this.parsePoseNodes()\n\n    for (const ID in skeletons) {\n      const skeleton = skeletons[ID]\n\n      const parents = connections.get(parseInt(skeleton.ID)).parents\n\n      parents.forEach(function (parent) {\n        if (geometryMap.has(parent.ID)) {\n          const geoID = parent.ID\n          const geoRelationships = connections.get(geoID)\n\n          geoRelationships.parents.forEach(function (geoConnParent) {\n            if (modelMap.has(geoConnParent.ID)) {\n              const model = modelMap.get(geoConnParent.ID)\n\n              model.bind(new Skeleton(skeleton.bones), bindMatrices[geoConnParent.ID])\n            }\n          })\n        }\n      })\n    }\n  }\n\n  parsePoseNodes() {\n    const bindMatrices = {}\n\n    if ('Pose' in fbxTree.Objects) {\n      const BindPoseNode = fbxTree.Objects.Pose\n\n      for (const nodeID in BindPoseNode) {\n        if (BindPoseNode[nodeID].attrType === 'BindPose' && BindPoseNode[nodeID].NbPoseNodes > 0) {\n          const poseNodes = BindPoseNode[nodeID].PoseNode\n\n          if (Array.isArray(poseNodes)) {\n            poseNodes.forEach(function (poseNode) {\n              bindMatrices[poseNode.Node] = new Matrix4().fromArray(poseNode.Matrix.a)\n            })\n          } else {\n            bindMatrices[poseNodes.Node] = new Matrix4().fromArray(poseNodes.Matrix.a)\n          }\n        }\n      }\n    }\n\n    return bindMatrices\n  }\n\n  // Parse ambient color in FBXTree.GlobalSettings - if it's not set to black (default), create an ambient light\n  createAmbientLight() {\n    if ('GlobalSettings' in fbxTree && 'AmbientColor' in fbxTree.GlobalSettings) {\n      const ambientColor = fbxTree.GlobalSettings.AmbientColor.value\n      const r = ambientColor[0]\n      const g = ambientColor[1]\n      const b = ambientColor[2]\n\n      if (r !== 0 || g !== 0 || b !== 0) {\n        const color = new Color(r, g, b)\n        sceneGraph.add(new AmbientLight(color, 1))\n      }\n    }\n  }\n}\n\n// parse Geometry data from FBXTree and return map of BufferGeometries\nclass GeometryParser {\n  // Parse nodes in FBXTree.Objects.Geometry\n  parse(deformers) {\n    const geometryMap = new Map()\n\n    if ('Geometry' in fbxTree.Objects) {\n      const geoNodes = fbxTree.Objects.Geometry\n\n      for (const nodeID in geoNodes) {\n        const relationships = connections.get(parseInt(nodeID))\n        const geo = this.parseGeometry(relationships, geoNodes[nodeID], deformers)\n\n        geometryMap.set(parseInt(nodeID), geo)\n      }\n    }\n\n    return geometryMap\n  }\n\n  // Parse single node in FBXTree.Objects.Geometry\n  parseGeometry(relationships, geoNode, deformers) {\n    switch (geoNode.attrType) {\n      case 'Mesh':\n        return this.parseMeshGeometry(relationships, geoNode, deformers)\n        break\n\n      case 'NurbsCurve':\n        return this.parseNurbsGeometry(geoNode)\n        break\n    }\n  }\n\n  // Parse single node mesh geometry in FBXTree.Objects.Geometry\n  parseMeshGeometry(relationships, geoNode, deformers) {\n    const skeletons = deformers.skeletons\n    const morphTargets = []\n\n    const modelNodes = relationships.parents.map(function (parent) {\n      return fbxTree.Objects.Model[parent.ID]\n    })\n\n    // don't create geometry if it is not associated with any models\n    if (modelNodes.length === 0) return\n\n    const skeleton = relationships.children.reduce(function (skeleton, child) {\n      if (skeletons[child.ID] !== undefined) skeleton = skeletons[child.ID]\n\n      return skeleton\n    }, null)\n\n    relationships.children.forEach(function (child) {\n      if (deformers.morphTargets[child.ID] !== undefined) {\n        morphTargets.push(deformers.morphTargets[child.ID])\n      }\n    })\n\n    // Assume one model and get the preRotation from that\n    // if there is more than one model associated with the geometry this may cause problems\n    const modelNode = modelNodes[0]\n\n    const transformData = {}\n\n    if ('RotationOrder' in modelNode) transformData.eulerOrder = getEulerOrder(modelNode.RotationOrder.value)\n    if ('InheritType' in modelNode) transformData.inheritType = parseInt(modelNode.InheritType.value)\n\n    if ('GeometricTranslation' in modelNode) transformData.translation = modelNode.GeometricTranslation.value\n    if ('GeometricRotation' in modelNode) transformData.rotation = modelNode.GeometricRotation.value\n    if ('GeometricScaling' in modelNode) transformData.scale = modelNode.GeometricScaling.value\n\n    const transform = generateTransform(transformData)\n\n    return this.genGeometry(geoNode, skeleton, morphTargets, transform)\n  }\n\n  // Generate a BufferGeometry from a node in FBXTree.Objects.Geometry\n  genGeometry(geoNode, skeleton, morphTargets, preTransform) {\n    const geo = new BufferGeometry()\n    if (geoNode.attrName) geo.name = geoNode.attrName\n\n    const geoInfo = this.parseGeoNode(geoNode, skeleton)\n    const buffers = this.genBuffers(geoInfo)\n\n    const positionAttribute = new Float32BufferAttribute(buffers.vertex, 3)\n\n    positionAttribute.applyMatrix4(preTransform)\n\n    geo.setAttribute('position', positionAttribute)\n\n    if (buffers.colors.length > 0) {\n      geo.setAttribute('color', new Float32BufferAttribute(buffers.colors, 3))\n    }\n\n    if (skeleton) {\n      geo.setAttribute('skinIndex', new Uint16BufferAttribute(buffers.weightsIndices, 4))\n\n      geo.setAttribute('skinWeight', new Float32BufferAttribute(buffers.vertexWeights, 4))\n\n      // used later to bind the skeleton to the model\n      geo.FBX_Deformer = skeleton\n    }\n\n    if (buffers.normal.length > 0) {\n      const normalMatrix = new Matrix3().getNormalMatrix(preTransform)\n\n      const normalAttribute = new Float32BufferAttribute(buffers.normal, 3)\n      normalAttribute.applyNormalMatrix(normalMatrix)\n\n      geo.setAttribute('normal', normalAttribute)\n    }\n\n    buffers.uvs.forEach(function (uvBuffer, i) {\n      if (UV1 === 'uv2') i++\n      const name = i === 0 ? 'uv' : `uv${i}`\n\n      geo.setAttribute(name, new Float32BufferAttribute(buffers.uvs[i], 2))\n    })\n\n    if (geoInfo.material && geoInfo.material.mappingType !== 'AllSame') {\n      // Convert the material indices of each vertex into rendering groups on the geometry.\n      let prevMaterialIndex = buffers.materialIndex[0]\n      let startIndex = 0\n\n      buffers.materialIndex.forEach(function (currentIndex, i) {\n        if (currentIndex !== prevMaterialIndex) {\n          geo.addGroup(startIndex, i - startIndex, prevMaterialIndex)\n\n          prevMaterialIndex = currentIndex\n          startIndex = i\n        }\n      })\n\n      // the loop above doesn't add the last group, do that here.\n      if (geo.groups.length > 0) {\n        const lastGroup = geo.groups[geo.groups.length - 1]\n        const lastIndex = lastGroup.start + lastGroup.count\n\n        if (lastIndex !== buffers.materialIndex.length) {\n          geo.addGroup(lastIndex, buffers.materialIndex.length - lastIndex, prevMaterialIndex)\n        }\n      }\n\n      // case where there are multiple materials but the whole geometry is only\n      // using one of them\n      if (geo.groups.length === 0) {\n        geo.addGroup(0, buffers.materialIndex.length, buffers.materialIndex[0])\n      }\n    }\n\n    this.addMorphTargets(geo, geoNode, morphTargets, preTransform)\n\n    return geo\n  }\n\n  parseGeoNode(geoNode, skeleton) {\n    const geoInfo = {}\n\n    geoInfo.vertexPositions = geoNode.Vertices !== undefined ? geoNode.Vertices.a : []\n    geoInfo.vertexIndices = geoNode.PolygonVertexIndex !== undefined ? geoNode.PolygonVertexIndex.a : []\n\n    if (geoNode.LayerElementColor) {\n      geoInfo.color = this.parseVertexColors(geoNode.LayerElementColor[0])\n    }\n\n    if (geoNode.LayerElementMaterial) {\n      geoInfo.material = this.parseMaterialIndices(geoNode.LayerElementMaterial[0])\n    }\n\n    if (geoNode.LayerElementNormal) {\n      geoInfo.normal = this.parseNormals(geoNode.LayerElementNormal[0])\n    }\n\n    if (geoNode.LayerElementUV) {\n      geoInfo.uv = []\n\n      let i = 0\n      while (geoNode.LayerElementUV[i]) {\n        if (geoNode.LayerElementUV[i].UV) {\n          geoInfo.uv.push(this.parseUVs(geoNode.LayerElementUV[i]))\n        }\n\n        i++\n      }\n    }\n\n    geoInfo.weightTable = {}\n\n    if (skeleton !== null) {\n      geoInfo.skeleton = skeleton\n\n      skeleton.rawBones.forEach(function (rawBone, i) {\n        // loop over the bone's vertex indices and weights\n        rawBone.indices.forEach(function (index, j) {\n          if (geoInfo.weightTable[index] === undefined) geoInfo.weightTable[index] = []\n\n          geoInfo.weightTable[index].push({\n            id: i,\n            weight: rawBone.weights[j],\n          })\n        })\n      })\n    }\n\n    return geoInfo\n  }\n\n  genBuffers(geoInfo) {\n    const buffers = {\n      vertex: [],\n      normal: [],\n      colors: [],\n      uvs: [],\n      materialIndex: [],\n      vertexWeights: [],\n      weightsIndices: [],\n    }\n\n    let polygonIndex = 0\n    let faceLength = 0\n    let displayedWeightsWarning = false\n\n    // these will hold data for a single face\n    let facePositionIndexes = []\n    let faceNormals = []\n    let faceColors = []\n    let faceUVs = []\n    let faceWeights = []\n    let faceWeightIndices = []\n\n    const scope = this\n    geoInfo.vertexIndices.forEach(function (vertexIndex, polygonVertexIndex) {\n      let materialIndex\n      let endOfFace = false\n\n      // Face index and vertex index arrays are combined in a single array\n      // A cube with quad faces looks like this:\n      // PolygonVertexIndex: *24 {\n      //  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\n      //  }\n      // Negative numbers mark the end of a face - first face here is 0, 1, 3, -3\n      // to find index of last vertex bit shift the index: ^ - 1\n      if (vertexIndex < 0) {\n        vertexIndex = vertexIndex ^ -1 // equivalent to ( x * -1 ) - 1\n        endOfFace = true\n      }\n\n      let weightIndices = []\n      let weights = []\n\n      facePositionIndexes.push(vertexIndex * 3, vertexIndex * 3 + 1, vertexIndex * 3 + 2)\n\n      if (geoInfo.color) {\n        const data = getData(polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.color)\n\n        faceColors.push(data[0], data[1], data[2])\n      }\n\n      if (geoInfo.skeleton) {\n        if (geoInfo.weightTable[vertexIndex] !== undefined) {\n          geoInfo.weightTable[vertexIndex].forEach(function (wt) {\n            weights.push(wt.weight)\n            weightIndices.push(wt.id)\n          })\n        }\n\n        if (weights.length > 4) {\n          if (!displayedWeightsWarning) {\n            console.warn(\n              'THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights.',\n            )\n            displayedWeightsWarning = true\n          }\n\n          const wIndex = [0, 0, 0, 0]\n          const Weight = [0, 0, 0, 0]\n\n          weights.forEach(function (weight, weightIndex) {\n            let currentWeight = weight\n            let currentIndex = weightIndices[weightIndex]\n\n            Weight.forEach(function (comparedWeight, comparedWeightIndex, comparedWeightArray) {\n              if (currentWeight > comparedWeight) {\n                comparedWeightArray[comparedWeightIndex] = currentWeight\n                currentWeight = comparedWeight\n\n                const tmp = wIndex[comparedWeightIndex]\n                wIndex[comparedWeightIndex] = currentIndex\n                currentIndex = tmp\n              }\n            })\n          })\n\n          weightIndices = wIndex\n          weights = Weight\n        }\n\n        // if the weight array is shorter than 4 pad with 0s\n        while (weights.length < 4) {\n          weights.push(0)\n          weightIndices.push(0)\n        }\n\n        for (let i = 0; i < 4; ++i) {\n          faceWeights.push(weights[i])\n          faceWeightIndices.push(weightIndices[i])\n        }\n      }\n\n      if (geoInfo.normal) {\n        const data = getData(polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.normal)\n\n        faceNormals.push(data[0], data[1], data[2])\n      }\n\n      if (geoInfo.material && geoInfo.material.mappingType !== 'AllSame') {\n        materialIndex = getData(polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material)[0]\n      }\n\n      if (geoInfo.uv) {\n        geoInfo.uv.forEach(function (uv, i) {\n          const data = getData(polygonVertexIndex, polygonIndex, vertexIndex, uv)\n\n          if (faceUVs[i] === undefined) {\n            faceUVs[i] = []\n          }\n\n          faceUVs[i].push(data[0])\n          faceUVs[i].push(data[1])\n        })\n      }\n\n      faceLength++\n\n      if (endOfFace) {\n        scope.genFace(\n          buffers,\n          geoInfo,\n          facePositionIndexes,\n          materialIndex,\n          faceNormals,\n          faceColors,\n          faceUVs,\n          faceWeights,\n          faceWeightIndices,\n          faceLength,\n        )\n\n        polygonIndex++\n        faceLength = 0\n\n        // reset arrays for the next face\n        facePositionIndexes = []\n        faceNormals = []\n        faceColors = []\n        faceUVs = []\n        faceWeights = []\n        faceWeightIndices = []\n      }\n    })\n\n    return buffers\n  }\n\n  // Generate data for a single face in a geometry. If the face is a quad then split it into 2 tris\n  genFace(\n    buffers,\n    geoInfo,\n    facePositionIndexes,\n    materialIndex,\n    faceNormals,\n    faceColors,\n    faceUVs,\n    faceWeights,\n    faceWeightIndices,\n    faceLength,\n  ) {\n    for (let i = 2; i < faceLength; i++) {\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[0]])\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[1]])\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[2]])\n\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[(i - 1) * 3]])\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[(i - 1) * 3 + 1]])\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[(i - 1) * 3 + 2]])\n\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[i * 3]])\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[i * 3 + 1]])\n      buffers.vertex.push(geoInfo.vertexPositions[facePositionIndexes[i * 3 + 2]])\n\n      if (geoInfo.skeleton) {\n        buffers.vertexWeights.push(faceWeights[0])\n        buffers.vertexWeights.push(faceWeights[1])\n        buffers.vertexWeights.push(faceWeights[2])\n        buffers.vertexWeights.push(faceWeights[3])\n\n        buffers.vertexWeights.push(faceWeights[(i - 1) * 4])\n        buffers.vertexWeights.push(faceWeights[(i - 1) * 4 + 1])\n        buffers.vertexWeights.push(faceWeights[(i - 1) * 4 + 2])\n        buffers.vertexWeights.push(faceWeights[(i - 1) * 4 + 3])\n\n        buffers.vertexWeights.push(faceWeights[i * 4])\n        buffers.vertexWeights.push(faceWeights[i * 4 + 1])\n        buffers.vertexWeights.push(faceWeights[i * 4 + 2])\n        buffers.vertexWeights.push(faceWeights[i * 4 + 3])\n\n        buffers.weightsIndices.push(faceWeightIndices[0])\n        buffers.weightsIndices.push(faceWeightIndices[1])\n        buffers.weightsIndices.push(faceWeightIndices[2])\n        buffers.weightsIndices.push(faceWeightIndices[3])\n\n        buffers.weightsIndices.push(faceWeightIndices[(i - 1) * 4])\n        buffers.weightsIndices.push(faceWeightIndices[(i - 1) * 4 + 1])\n        buffers.weightsIndices.push(faceWeightIndices[(i - 1) * 4 + 2])\n        buffers.weightsIndices.push(faceWeightIndices[(i - 1) * 4 + 3])\n\n        buffers.weightsIndices.push(faceWeightIndices[i * 4])\n        buffers.weightsIndices.push(faceWeightIndices[i * 4 + 1])\n        buffers.weightsIndices.push(faceWeightIndices[i * 4 + 2])\n        buffers.weightsIndices.push(faceWeightIndices[i * 4 + 3])\n      }\n\n      if (geoInfo.color) {\n        buffers.colors.push(faceColors[0])\n        buffers.colors.push(faceColors[1])\n        buffers.colors.push(faceColors[2])\n\n        buffers.colors.push(faceColors[(i - 1) * 3])\n        buffers.colors.push(faceColors[(i - 1) * 3 + 1])\n        buffers.colors.push(faceColors[(i - 1) * 3 + 2])\n\n        buffers.colors.push(faceColors[i * 3])\n        buffers.colors.push(faceColors[i * 3 + 1])\n        buffers.colors.push(faceColors[i * 3 + 2])\n      }\n\n      if (geoInfo.material && geoInfo.material.mappingType !== 'AllSame') {\n        buffers.materialIndex.push(materialIndex)\n        buffers.materialIndex.push(materialIndex)\n        buffers.materialIndex.push(materialIndex)\n      }\n\n      if (geoInfo.normal) {\n        buffers.normal.push(faceNormals[0])\n        buffers.normal.push(faceNormals[1])\n        buffers.normal.push(faceNormals[2])\n\n        buffers.normal.push(faceNormals[(i - 1) * 3])\n        buffers.normal.push(faceNormals[(i - 1) * 3 + 1])\n        buffers.normal.push(faceNormals[(i - 1) * 3 + 2])\n\n        buffers.normal.push(faceNormals[i * 3])\n        buffers.normal.push(faceNormals[i * 3 + 1])\n        buffers.normal.push(faceNormals[i * 3 + 2])\n      }\n\n      if (geoInfo.uv) {\n        geoInfo.uv.forEach(function (uv, j) {\n          if (buffers.uvs[j] === undefined) buffers.uvs[j] = []\n\n          buffers.uvs[j].push(faceUVs[j][0])\n          buffers.uvs[j].push(faceUVs[j][1])\n\n          buffers.uvs[j].push(faceUVs[j][(i - 1) * 2])\n          buffers.uvs[j].push(faceUVs[j][(i - 1) * 2 + 1])\n\n          buffers.uvs[j].push(faceUVs[j][i * 2])\n          buffers.uvs[j].push(faceUVs[j][i * 2 + 1])\n        })\n      }\n    }\n  }\n\n  addMorphTargets(parentGeo, parentGeoNode, morphTargets, preTransform) {\n    if (morphTargets.length === 0) return\n\n    parentGeo.morphTargetsRelative = true\n\n    parentGeo.morphAttributes.position = []\n    // parentGeo.morphAttributes.normal = []; // not implemented\n\n    const scope = this\n    morphTargets.forEach(function (morphTarget) {\n      morphTarget.rawTargets.forEach(function (rawTarget) {\n        const morphGeoNode = fbxTree.Objects.Geometry[rawTarget.geoID]\n\n        if (morphGeoNode !== undefined) {\n          scope.genMorphGeometry(parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name)\n        }\n      })\n    })\n  }\n\n  // a morph geometry node is similar to a standard  node, and the node is also contained\n  // in FBXTree.Objects.Geometry, however it can only have attributes for position, normal\n  // and a special attribute Index defining which vertices of the original geometry are affected\n  // Normal and position attributes only have data for the vertices that are affected by the morph\n  genMorphGeometry(parentGeo, parentGeoNode, morphGeoNode, preTransform, name) {\n    const vertexIndices = parentGeoNode.PolygonVertexIndex !== undefined ? parentGeoNode.PolygonVertexIndex.a : []\n\n    const morphPositionsSparse = morphGeoNode.Vertices !== undefined ? morphGeoNode.Vertices.a : []\n    const indices = morphGeoNode.Indexes !== undefined ? morphGeoNode.Indexes.a : []\n\n    const length = parentGeo.attributes.position.count * 3\n    const morphPositions = new Float32Array(length)\n\n    for (let i = 0; i < indices.length; i++) {\n      const morphIndex = indices[i] * 3\n\n      morphPositions[morphIndex] = morphPositionsSparse[i * 3]\n      morphPositions[morphIndex + 1] = morphPositionsSparse[i * 3 + 1]\n      morphPositions[morphIndex + 2] = morphPositionsSparse[i * 3 + 2]\n    }\n\n    // TODO: add morph normal support\n    const morphGeoInfo = {\n      vertexIndices: vertexIndices,\n      vertexPositions: morphPositions,\n    }\n\n    const morphBuffers = this.genBuffers(morphGeoInfo)\n\n    const positionAttribute = new Float32BufferAttribute(morphBuffers.vertex, 3)\n    positionAttribute.name = name || morphGeoNode.attrName\n\n    positionAttribute.applyMatrix4(preTransform)\n\n    parentGeo.morphAttributes.position.push(positionAttribute)\n  }\n\n  // Parse normal from FBXTree.Objects.Geometry.LayerElementNormal if it exists\n  parseNormals(NormalNode) {\n    const mappingType = NormalNode.MappingInformationType\n    const referenceType = NormalNode.ReferenceInformationType\n    const buffer = NormalNode.Normals.a\n    let indexBuffer = []\n    if (referenceType === 'IndexToDirect') {\n      if ('NormalIndex' in NormalNode) {\n        indexBuffer = NormalNode.NormalIndex.a\n      } else if ('NormalsIndex' in NormalNode) {\n        indexBuffer = NormalNode.NormalsIndex.a\n      }\n    }\n\n    return {\n      dataSize: 3,\n      buffer: buffer,\n      indices: indexBuffer,\n      mappingType: mappingType,\n      referenceType: referenceType,\n    }\n  }\n\n  // Parse UVs from FBXTree.Objects.Geometry.LayerElementUV if it exists\n  parseUVs(UVNode) {\n    const mappingType = UVNode.MappingInformationType\n    const referenceType = UVNode.ReferenceInformationType\n    const buffer = UVNode.UV.a\n    let indexBuffer = []\n    if (referenceType === 'IndexToDirect') {\n      indexBuffer = UVNode.UVIndex.a\n    }\n\n    return {\n      dataSize: 2,\n      buffer: buffer,\n      indices: indexBuffer,\n      mappingType: mappingType,\n      referenceType: referenceType,\n    }\n  }\n\n  // Parse Vertex Colors from FBXTree.Objects.Geometry.LayerElementColor if it exists\n  parseVertexColors(ColorNode) {\n    const mappingType = ColorNode.MappingInformationType\n    const referenceType = ColorNode.ReferenceInformationType\n    const buffer = ColorNode.Colors.a\n    let indexBuffer = []\n    if (referenceType === 'IndexToDirect') {\n      indexBuffer = ColorNode.ColorIndex.a\n    }\n\n    return {\n      dataSize: 4,\n      buffer: buffer,\n      indices: indexBuffer,\n      mappingType: mappingType,\n      referenceType: referenceType,\n    }\n  }\n\n  // Parse mapping and material data in FBXTree.Objects.Geometry.LayerElementMaterial if it exists\n  parseMaterialIndices(MaterialNode) {\n    const mappingType = MaterialNode.MappingInformationType\n    const referenceType = MaterialNode.ReferenceInformationType\n\n    if (mappingType === 'NoMappingInformation') {\n      return {\n        dataSize: 1,\n        buffer: [0],\n        indices: [0],\n        mappingType: 'AllSame',\n        referenceType: referenceType,\n      }\n    }\n\n    const materialIndexBuffer = MaterialNode.Materials.a\n\n    // Since materials are stored as indices, there's a bit of a mismatch between FBX and what\n    // we expect.So we create an intermediate buffer that points to the index in the buffer,\n    // for conforming with the other functions we've written for other data.\n    const materialIndices = []\n\n    for (let i = 0; i < materialIndexBuffer.length; ++i) {\n      materialIndices.push(i)\n    }\n\n    return {\n      dataSize: 1,\n      buffer: materialIndexBuffer,\n      indices: materialIndices,\n      mappingType: mappingType,\n      referenceType: referenceType,\n    }\n  }\n\n  // Generate a NurbGeometry from a node in FBXTree.Objects.Geometry\n  parseNurbsGeometry(geoNode) {\n    if (NURBSCurve === undefined) {\n      console.error(\n        'THREE.FBXLoader: The loader relies on NURBSCurve for any nurbs present in the model. Nurbs will show up as empty geometry.',\n      )\n      return new BufferGeometry()\n    }\n\n    const order = parseInt(geoNode.Order)\n\n    if (isNaN(order)) {\n      console.error('THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geoNode.Order, geoNode.id)\n      return new BufferGeometry()\n    }\n\n    const degree = order - 1\n\n    const knots = geoNode.KnotVector.a\n    const controlPoints = []\n    const pointsValues = geoNode.Points.a\n\n    for (let i = 0, l = pointsValues.length; i < l; i += 4) {\n      controlPoints.push(new Vector4().fromArray(pointsValues, i))\n    }\n\n    let startKnot, endKnot\n\n    if (geoNode.Form === 'Closed') {\n      controlPoints.push(controlPoints[0])\n    } else if (geoNode.Form === 'Periodic') {\n      startKnot = degree\n      endKnot = knots.length - 1 - startKnot\n\n      for (let i = 0; i < degree; ++i) {\n        controlPoints.push(controlPoints[i])\n      }\n    }\n\n    const curve = new NURBSCurve(degree, knots, controlPoints, startKnot, endKnot)\n    const points = curve.getPoints(controlPoints.length * 12)\n\n    return new BufferGeometry().setFromPoints(points)\n  }\n}\n\n// parse animation data from FBXTree\nclass AnimationParser {\n  // take raw animation clips and turn them into three.js animation clips\n  parse() {\n    const animationClips = []\n\n    const rawClips = this.parseClips()\n\n    if (rawClips !== undefined) {\n      for (const key in rawClips) {\n        const rawClip = rawClips[key]\n\n        const clip = this.addClip(rawClip)\n\n        animationClips.push(clip)\n      }\n    }\n\n    return animationClips\n  }\n\n  parseClips() {\n    // since the actual transformation data is stored in FBXTree.Objects.AnimationCurve,\n    // if this is undefined we can safely assume there are no animations\n    if (fbxTree.Objects.AnimationCurve === undefined) return undefined\n\n    const curveNodesMap = this.parseAnimationCurveNodes()\n\n    this.parseAnimationCurves(curveNodesMap)\n\n    const layersMap = this.parseAnimationLayers(curveNodesMap)\n    const rawClips = this.parseAnimStacks(layersMap)\n\n    return rawClips\n  }\n\n  // parse nodes in FBXTree.Objects.AnimationCurveNode\n  // each AnimationCurveNode holds data for an animation transform for a model (e.g. left arm rotation )\n  // and is referenced by an AnimationLayer\n  parseAnimationCurveNodes() {\n    const rawCurveNodes = fbxTree.Objects.AnimationCurveNode\n\n    const curveNodesMap = new Map()\n\n    for (const nodeID in rawCurveNodes) {\n      const rawCurveNode = rawCurveNodes[nodeID]\n\n      if (rawCurveNode.attrName.match(/S|R|T|DeformPercent/) !== null) {\n        const curveNode = {\n          id: rawCurveNode.id,\n          attr: rawCurveNode.attrName,\n          curves: {},\n        }\n\n        curveNodesMap.set(curveNode.id, curveNode)\n      }\n    }\n\n    return curveNodesMap\n  }\n\n  // parse nodes in FBXTree.Objects.AnimationCurve and connect them up to\n  // previously parsed AnimationCurveNodes. Each AnimationCurve holds data for a single animated\n  // axis ( e.g. times and values of x rotation)\n  parseAnimationCurves(curveNodesMap) {\n    const rawCurves = fbxTree.Objects.AnimationCurve\n\n    // TODO: Many values are identical up to roundoff error, but won't be optimised\n    // e.g. position times: [0, 0.4, 0. 8]\n    // position values: [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.23538335023477e-7, 93.67518615722656, -0.9982695579528809, 7.235384487103147e-7, 93.67520904541016, -0.9982695579528809]\n    // clearly, this should be optimised to\n    // times: [0], positions [7.23538335023477e-7, 93.67518615722656, -0.9982695579528809]\n    // this shows up in nearly every FBX file, and generally time array is length > 100\n\n    for (const nodeID in rawCurves) {\n      const animationCurve = {\n        id: rawCurves[nodeID].id,\n        times: rawCurves[nodeID].KeyTime.a.map(convertFBXTimeToSeconds),\n        values: rawCurves[nodeID].KeyValueFloat.a,\n      }\n\n      const relationships = connections.get(animationCurve.id)\n\n      if (relationships !== undefined) {\n        const animationCurveID = relationships.parents[0].ID\n        const animationCurveRelationship = relationships.parents[0].relationship\n\n        if (animationCurveRelationship.match(/X/)) {\n          curveNodesMap.get(animationCurveID).curves['x'] = animationCurve\n        } else if (animationCurveRelationship.match(/Y/)) {\n          curveNodesMap.get(animationCurveID).curves['y'] = animationCurve\n        } else if (animationCurveRelationship.match(/Z/)) {\n          curveNodesMap.get(animationCurveID).curves['z'] = animationCurve\n        } else if (animationCurveRelationship.match(/d|DeformPercent/) && curveNodesMap.has(animationCurveID)) {\n          curveNodesMap.get(animationCurveID).curves['morph'] = animationCurve\n        }\n      }\n    }\n  }\n\n  // parse nodes in FBXTree.Objects.AnimationLayer. Each layers holds references\n  // to various AnimationCurveNodes and is referenced by an AnimationStack node\n  // note: theoretically a stack can have multiple layers, however in practice there always seems to be one per stack\n  parseAnimationLayers(curveNodesMap) {\n    const rawLayers = fbxTree.Objects.AnimationLayer\n\n    const layersMap = new Map()\n\n    for (const nodeID in rawLayers) {\n      const layerCurveNodes = []\n\n      const connection = connections.get(parseInt(nodeID))\n\n      if (connection !== undefined) {\n        // all the animationCurveNodes used in the layer\n        const children = connection.children\n\n        children.forEach(function (child, i) {\n          if (curveNodesMap.has(child.ID)) {\n            const curveNode = curveNodesMap.get(child.ID)\n\n            // check that the curves are defined for at least one axis, otherwise ignore the curveNode\n            if (\n              curveNode.curves.x !== undefined ||\n              curveNode.curves.y !== undefined ||\n              curveNode.curves.z !== undefined\n            ) {\n              if (layerCurveNodes[i] === undefined) {\n                const modelID = connections.get(child.ID).parents.filter(function (parent) {\n                  return parent.relationship !== undefined\n                })[0].ID\n\n                if (modelID !== undefined) {\n                  const rawModel = fbxTree.Objects.Model[modelID.toString()]\n\n                  if (rawModel === undefined) {\n                    console.warn('THREE.FBXLoader: Encountered a unused curve.', child)\n                    return\n                  }\n\n                  const node = {\n                    modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName(rawModel.attrName) : '',\n                    ID: rawModel.id,\n                    initialPosition: [0, 0, 0],\n                    initialRotation: [0, 0, 0],\n                    initialScale: [1, 1, 1],\n                  }\n\n                  sceneGraph.traverse(function (child) {\n                    if (child.ID === rawModel.id) {\n                      node.transform = child.matrix\n\n                      if (child.userData.transformData) node.eulerOrder = child.userData.transformData.eulerOrder\n                    }\n                  })\n\n                  if (!node.transform) node.transform = new Matrix4()\n\n                  // if the animated model is pre rotated, we'll have to apply the pre rotations to every\n                  // animation value as well\n                  if ('PreRotation' in rawModel) node.preRotation = rawModel.PreRotation.value\n                  if ('PostRotation' in rawModel) node.postRotation = rawModel.PostRotation.value\n\n                  layerCurveNodes[i] = node\n                }\n              }\n\n              if (layerCurveNodes[i]) layerCurveNodes[i][curveNode.attr] = curveNode\n            } else if (curveNode.curves.morph !== undefined) {\n              if (layerCurveNodes[i] === undefined) {\n                const deformerID = connections.get(child.ID).parents.filter(function (parent) {\n                  return parent.relationship !== undefined\n                })[0].ID\n\n                const morpherID = connections.get(deformerID).parents[0].ID\n                const geoID = connections.get(morpherID).parents[0].ID\n\n                // assuming geometry is not used in more than one model\n                const modelID = connections.get(geoID).parents[0].ID\n\n                const rawModel = fbxTree.Objects.Model[modelID]\n\n                const node = {\n                  modelName: rawModel.attrName ? PropertyBinding.sanitizeNodeName(rawModel.attrName) : '',\n                  morphName: fbxTree.Objects.Deformer[deformerID].attrName,\n                }\n\n                layerCurveNodes[i] = node\n              }\n\n              layerCurveNodes[i][curveNode.attr] = curveNode\n            }\n          }\n        })\n\n        layersMap.set(parseInt(nodeID), layerCurveNodes)\n      }\n    }\n\n    return layersMap\n  }\n\n  // parse nodes in FBXTree.Objects.AnimationStack. These are the top level node in the animation\n  // hierarchy. Each Stack node will be used to create a AnimationClip\n  parseAnimStacks(layersMap) {\n    const rawStacks = fbxTree.Objects.AnimationStack\n\n    // connect the stacks (clips) up to the layers\n    const rawClips = {}\n\n    for (const nodeID in rawStacks) {\n      const children = connections.get(parseInt(nodeID)).children\n\n      if (children.length > 1) {\n        // it seems like stacks will always be associated with a single layer. But just in case there are files\n        // where there are multiple layers per stack, we'll display a warning\n        console.warn(\n          'THREE.FBXLoader: Encountered an animation stack with multiple layers, this is currently not supported. Ignoring subsequent layers.',\n        )\n      }\n\n      const layer = layersMap.get(children[0].ID)\n\n      rawClips[nodeID] = {\n        name: rawStacks[nodeID].attrName,\n        layer: layer,\n      }\n    }\n\n    return rawClips\n  }\n\n  addClip(rawClip) {\n    let tracks = []\n\n    const scope = this\n    rawClip.layer.forEach(function (rawTracks) {\n      tracks = tracks.concat(scope.generateTracks(rawTracks))\n    })\n\n    return new AnimationClip(rawClip.name, -1, tracks)\n  }\n\n  generateTracks(rawTracks) {\n    const tracks = []\n\n    let initialPosition = new Vector3()\n    let initialRotation = new Quaternion()\n    let initialScale = new Vector3()\n\n    if (rawTracks.transform) rawTracks.transform.decompose(initialPosition, initialRotation, initialScale)\n\n    initialPosition = initialPosition.toArray()\n    initialRotation = new Euler().setFromQuaternion(initialRotation, rawTracks.eulerOrder).toArray()\n    initialScale = initialScale.toArray()\n\n    if (rawTracks.T !== undefined && Object.keys(rawTracks.T.curves).length > 0) {\n      const positionTrack = this.generateVectorTrack(\n        rawTracks.modelName,\n        rawTracks.T.curves,\n        initialPosition,\n        'position',\n      )\n      if (positionTrack !== undefined) tracks.push(positionTrack)\n    }\n\n    if (rawTracks.R !== undefined && Object.keys(rawTracks.R.curves).length > 0) {\n      const rotationTrack = this.generateRotationTrack(\n        rawTracks.modelName,\n        rawTracks.R.curves,\n        initialRotation,\n        rawTracks.preRotation,\n        rawTracks.postRotation,\n        rawTracks.eulerOrder,\n      )\n      if (rotationTrack !== undefined) tracks.push(rotationTrack)\n    }\n\n    if (rawTracks.S !== undefined && Object.keys(rawTracks.S.curves).length > 0) {\n      const scaleTrack = this.generateVectorTrack(rawTracks.modelName, rawTracks.S.curves, initialScale, 'scale')\n      if (scaleTrack !== undefined) tracks.push(scaleTrack)\n    }\n\n    if (rawTracks.DeformPercent !== undefined) {\n      const morphTrack = this.generateMorphTrack(rawTracks)\n      if (morphTrack !== undefined) tracks.push(morphTrack)\n    }\n\n    return tracks\n  }\n\n  generateVectorTrack(modelName, curves, initialValue, type) {\n    const times = this.getTimesForAllAxes(curves)\n    const values = this.getKeyframeTrackValues(times, curves, initialValue)\n\n    return new VectorKeyframeTrack(modelName + '.' + type, times, values)\n  }\n\n  generateRotationTrack(modelName, curves, initialValue, preRotation, postRotation, eulerOrder) {\n    if (curves.x !== undefined) {\n      this.interpolateRotations(curves.x)\n      curves.x.values = curves.x.values.map(MathUtils.degToRad)\n    }\n\n    if (curves.y !== undefined) {\n      this.interpolateRotations(curves.y)\n      curves.y.values = curves.y.values.map(MathUtils.degToRad)\n    }\n\n    if (curves.z !== undefined) {\n      this.interpolateRotations(curves.z)\n      curves.z.values = curves.z.values.map(MathUtils.degToRad)\n    }\n\n    const times = this.getTimesForAllAxes(curves)\n    const values = this.getKeyframeTrackValues(times, curves, initialValue)\n\n    if (preRotation !== undefined) {\n      preRotation = preRotation.map(MathUtils.degToRad)\n      preRotation.push(eulerOrder)\n\n      preRotation = new Euler().fromArray(preRotation)\n      preRotation = new Quaternion().setFromEuler(preRotation)\n    }\n\n    if (postRotation !== undefined) {\n      postRotation = postRotation.map(MathUtils.degToRad)\n      postRotation.push(eulerOrder)\n\n      postRotation = new Euler().fromArray(postRotation)\n      postRotation = new Quaternion().setFromEuler(postRotation).invert()\n    }\n\n    const quaternion = new Quaternion()\n    const euler = new Euler()\n\n    const quaternionValues = []\n\n    for (let i = 0; i < values.length; i += 3) {\n      euler.set(values[i], values[i + 1], values[i + 2], eulerOrder)\n\n      quaternion.setFromEuler(euler)\n\n      if (preRotation !== undefined) quaternion.premultiply(preRotation)\n      if (postRotation !== undefined) quaternion.multiply(postRotation)\n\n      quaternion.toArray(quaternionValues, (i / 3) * 4)\n    }\n\n    return new QuaternionKeyframeTrack(modelName + '.quaternion', times, quaternionValues)\n  }\n\n  generateMorphTrack(rawTracks) {\n    const curves = rawTracks.DeformPercent.curves.morph\n    const values = curves.values.map(function (val) {\n      return val / 100\n    })\n\n    const morphNum = sceneGraph.getObjectByName(rawTracks.modelName).morphTargetDictionary[rawTracks.morphName]\n\n    return new NumberKeyframeTrack(\n      rawTracks.modelName + '.morphTargetInfluences[' + morphNum + ']',\n      curves.times,\n      values,\n    )\n  }\n\n  // For all animated objects, times are defined separately for each axis\n  // Here we'll combine the times into one sorted array without duplicates\n  getTimesForAllAxes(curves) {\n    let times = []\n\n    // first join together the times for each axis, if defined\n    if (curves.x !== undefined) times = times.concat(curves.x.times)\n    if (curves.y !== undefined) times = times.concat(curves.y.times)\n    if (curves.z !== undefined) times = times.concat(curves.z.times)\n\n    // then sort them\n    times = times.sort(function (a, b) {\n      return a - b\n    })\n\n    // and remove duplicates\n    if (times.length > 1) {\n      let targetIndex = 1\n      let lastValue = times[0]\n      for (let i = 1; i < times.length; i++) {\n        const currentValue = times[i]\n        if (currentValue !== lastValue) {\n          times[targetIndex] = currentValue\n          lastValue = currentValue\n          targetIndex++\n        }\n      }\n\n      times = times.slice(0, targetIndex)\n    }\n\n    return times\n  }\n\n  getKeyframeTrackValues(times, curves, initialValue) {\n    const prevValue = initialValue\n\n    const values = []\n\n    let xIndex = -1\n    let yIndex = -1\n    let zIndex = -1\n\n    times.forEach(function (time) {\n      if (curves.x) xIndex = curves.x.times.indexOf(time)\n      if (curves.y) yIndex = curves.y.times.indexOf(time)\n      if (curves.z) zIndex = curves.z.times.indexOf(time)\n\n      // if there is an x value defined for this frame, use that\n      if (xIndex !== -1) {\n        const xValue = curves.x.values[xIndex]\n        values.push(xValue)\n        prevValue[0] = xValue\n      } else {\n        // otherwise use the x value from the previous frame\n        values.push(prevValue[0])\n      }\n\n      if (yIndex !== -1) {\n        const yValue = curves.y.values[yIndex]\n        values.push(yValue)\n        prevValue[1] = yValue\n      } else {\n        values.push(prevValue[1])\n      }\n\n      if (zIndex !== -1) {\n        const zValue = curves.z.values[zIndex]\n        values.push(zValue)\n        prevValue[2] = zValue\n      } else {\n        values.push(prevValue[2])\n      }\n    })\n\n    return values\n  }\n\n  // Rotations are defined as Euler angles which can have values  of any size\n  // These will be converted to quaternions which don't support values greater than\n  // PI, so we'll interpolate large rotations\n  interpolateRotations(curve) {\n    for (let i = 1; i < curve.values.length; i++) {\n      const initialValue = curve.values[i - 1]\n      const valuesSpan = curve.values[i] - initialValue\n\n      const absoluteSpan = Math.abs(valuesSpan)\n\n      if (absoluteSpan >= 180) {\n        const numSubIntervals = absoluteSpan / 180\n\n        const step = valuesSpan / numSubIntervals\n        let nextValue = initialValue + step\n\n        const initialTime = curve.times[i - 1]\n        const timeSpan = curve.times[i] - initialTime\n        const interval = timeSpan / numSubIntervals\n        let nextTime = initialTime + interval\n\n        const interpolatedTimes = []\n        const interpolatedValues = []\n\n        while (nextTime < curve.times[i]) {\n          interpolatedTimes.push(nextTime)\n          nextTime += interval\n\n          interpolatedValues.push(nextValue)\n          nextValue += step\n        }\n\n        curve.times = inject(curve.times, i, interpolatedTimes)\n        curve.values = inject(curve.values, i, interpolatedValues)\n      }\n    }\n  }\n}\n\n// parse an FBX file in ASCII format\nclass TextParser {\n  getPrevNode() {\n    return this.nodeStack[this.currentIndent - 2]\n  }\n\n  getCurrentNode() {\n    return this.nodeStack[this.currentIndent - 1]\n  }\n\n  getCurrentProp() {\n    return this.currentProp\n  }\n\n  pushStack(node) {\n    this.nodeStack.push(node)\n    this.currentIndent += 1\n  }\n\n  popStack() {\n    this.nodeStack.pop()\n    this.currentIndent -= 1\n  }\n\n  setCurrentProp(val, name) {\n    this.currentProp = val\n    this.currentPropName = name\n  }\n\n  parse(text) {\n    this.currentIndent = 0\n\n    this.allNodes = new FBXTree()\n    this.nodeStack = []\n    this.currentProp = []\n    this.currentPropName = ''\n\n    const scope = this\n\n    const split = text.split(/[\\r\\n]+/)\n\n    split.forEach(function (line, i) {\n      const matchComment = line.match(/^[\\s\\t]*;/)\n      const matchEmpty = line.match(/^[\\s\\t]*$/)\n\n      if (matchComment || matchEmpty) return\n\n      const matchBeginning = line.match('^\\\\t{' + scope.currentIndent + '}(\\\\w+):(.*){', '')\n      const matchProperty = line.match('^\\\\t{' + scope.currentIndent + '}(\\\\w+):[\\\\s\\\\t\\\\r\\\\n](.*)')\n      const matchEnd = line.match('^\\\\t{' + (scope.currentIndent - 1) + '}}')\n\n      if (matchBeginning) {\n        scope.parseNodeBegin(line, matchBeginning)\n      } else if (matchProperty) {\n        scope.parseNodeProperty(line, matchProperty, split[++i])\n      } else if (matchEnd) {\n        scope.popStack()\n      } else if (line.match(/^[^\\s\\t}]/)) {\n        // large arrays are split over multiple lines terminated with a ',' character\n        // if this is encountered the line needs to be joined to the previous line\n        scope.parseNodePropertyContinued(line)\n      }\n    })\n\n    return this.allNodes\n  }\n\n  parseNodeBegin(line, property) {\n    const nodeName = property[1].trim().replace(/^\"/, '').replace(/\"$/, '')\n\n    const nodeAttrs = property[2].split(',').map(function (attr) {\n      return attr.trim().replace(/^\"/, '').replace(/\"$/, '')\n    })\n\n    const node = { name: nodeName }\n    const attrs = this.parseNodeAttr(nodeAttrs)\n\n    const currentNode = this.getCurrentNode()\n\n    // a top node\n    if (this.currentIndent === 0) {\n      this.allNodes.add(nodeName, node)\n    } else {\n      // a subnode\n\n      // if the subnode already exists, append it\n      if (nodeName in currentNode) {\n        // special case Pose needs PoseNodes as an array\n        if (nodeName === 'PoseNode') {\n          currentNode.PoseNode.push(node)\n        } else if (currentNode[nodeName].id !== undefined) {\n          currentNode[nodeName] = {}\n          currentNode[nodeName][currentNode[nodeName].id] = currentNode[nodeName]\n        }\n\n        if (attrs.id !== '') currentNode[nodeName][attrs.id] = node\n      } else if (typeof attrs.id === 'number') {\n        currentNode[nodeName] = {}\n        currentNode[nodeName][attrs.id] = node\n      } else if (nodeName !== 'Properties70') {\n        if (nodeName === 'PoseNode') currentNode[nodeName] = [node]\n        else currentNode[nodeName] = node\n      }\n    }\n\n    if (typeof attrs.id === 'number') node.id = attrs.id\n    if (attrs.name !== '') node.attrName = attrs.name\n    if (attrs.type !== '') node.attrType = attrs.type\n\n    this.pushStack(node)\n  }\n\n  parseNodeAttr(attrs) {\n    let id = attrs[0]\n\n    if (attrs[0] !== '') {\n      id = parseInt(attrs[0])\n\n      if (isNaN(id)) {\n        id = attrs[0]\n      }\n    }\n\n    let name = '',\n      type = ''\n\n    if (attrs.length > 1) {\n      name = attrs[1].replace(/^(\\w+)::/, '')\n      type = attrs[2]\n    }\n\n    return { id: id, name: name, type: type }\n  }\n\n  parseNodeProperty(line, property, contentLine) {\n    let propName = property[1].replace(/^\"/, '').replace(/\"$/, '').trim()\n    let propValue = property[2].replace(/^\"/, '').replace(/\"$/, '').trim()\n\n    // for special case: base64 image data follows \"Content: ,\" line\n    //\tContent: ,\n    //\t \"/9j/4RDaRXhpZgAATU0A...\"\n    if (propName === 'Content' && propValue === ',') {\n      propValue = contentLine.replace(/\"/g, '').replace(/,$/, '').trim()\n    }\n\n    const currentNode = this.getCurrentNode()\n    const parentName = currentNode.name\n\n    if (parentName === 'Properties70') {\n      this.parseNodeSpecialProperty(line, propName, propValue)\n      return\n    }\n\n    // Connections\n    if (propName === 'C') {\n      const connProps = propValue.split(',').slice(1)\n      const from = parseInt(connProps[0])\n      const to = parseInt(connProps[1])\n\n      let rest = propValue.split(',').slice(3)\n\n      rest = rest.map(function (elem) {\n        return elem.trim().replace(/^\"/, '')\n      })\n\n      propName = 'connections'\n      propValue = [from, to]\n      append(propValue, rest)\n\n      if (currentNode[propName] === undefined) {\n        currentNode[propName] = []\n      }\n    }\n\n    // Node\n    if (propName === 'Node') currentNode.id = propValue\n\n    // connections\n    if (propName in currentNode && Array.isArray(currentNode[propName])) {\n      currentNode[propName].push(propValue)\n    } else {\n      if (propName !== 'a') currentNode[propName] = propValue\n      else currentNode.a = propValue\n    }\n\n    this.setCurrentProp(currentNode, propName)\n\n    // convert string to array, unless it ends in ',' in which case more will be added to it\n    if (propName === 'a' && propValue.slice(-1) !== ',') {\n      currentNode.a = parseNumberArray(propValue)\n    }\n  }\n\n  parseNodePropertyContinued(line) {\n    const currentNode = this.getCurrentNode()\n\n    currentNode.a += line\n\n    // if the line doesn't end in ',' we have reached the end of the property value\n    // so convert the string to an array\n    if (line.slice(-1) !== ',') {\n      currentNode.a = parseNumberArray(currentNode.a)\n    }\n  }\n\n  // parse \"Property70\"\n  parseNodeSpecialProperty(line, propName, propValue) {\n    // split this\n    // P: \"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\",1,1,1\n    // into array like below\n    // [\"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\", \"1,1,1\" ]\n    const props = propValue.split('\",').map(function (prop) {\n      return prop.trim().replace(/^\\\"/, '').replace(/\\s/, '_')\n    })\n\n    const innerPropName = props[0]\n    const innerPropType1 = props[1]\n    const innerPropType2 = props[2]\n    const innerPropFlag = props[3]\n    let innerPropValue = props[4]\n\n    // cast values where needed, otherwise leave as strings\n    switch (innerPropType1) {\n      case 'int':\n      case 'enum':\n      case 'bool':\n      case 'ULongLong':\n      case 'double':\n      case 'Number':\n      case 'FieldOfView':\n        innerPropValue = parseFloat(innerPropValue)\n        break\n\n      case 'Color':\n      case 'ColorRGB':\n      case 'Vector3D':\n      case 'Lcl_Translation':\n      case 'Lcl_Rotation':\n      case 'Lcl_Scaling':\n        innerPropValue = parseNumberArray(innerPropValue)\n        break\n    }\n\n    // CAUTION: these props must append to parent's parent\n    this.getPrevNode()[innerPropName] = {\n      type: innerPropType1,\n      type2: innerPropType2,\n      flag: innerPropFlag,\n      value: innerPropValue,\n    }\n\n    this.setCurrentProp(this.getPrevNode(), innerPropName)\n  }\n}\n\n// Parse an FBX file in Binary format\nclass BinaryParser {\n  parse(buffer) {\n    const reader = new BinaryReader(buffer)\n    reader.skip(23) // skip magic 23 bytes\n\n    const version = reader.getUint32()\n\n    if (version < 6400) {\n      throw new Error('THREE.FBXLoader: FBX version not supported, FileVersion: ' + version)\n    }\n\n    const allNodes = new FBXTree()\n\n    while (!this.endOfContent(reader)) {\n      const node = this.parseNode(reader, version)\n      if (node !== null) allNodes.add(node.name, node)\n    }\n\n    return allNodes\n  }\n\n  // Check if reader has reached the end of content.\n  endOfContent(reader) {\n    // footer size: 160bytes + 16-byte alignment padding\n    // - 16bytes: magic\n    // - padding til 16-byte alignment (at least 1byte?)\n    //\t(seems like some exporters embed fixed 15 or 16bytes?)\n    // - 4bytes: magic\n    // - 4bytes: version\n    // - 120bytes: zero\n    // - 16bytes: magic\n    if (reader.size() % 16 === 0) {\n      return ((reader.getOffset() + 160 + 16) & ~0xf) >= reader.size()\n    } else {\n      return reader.getOffset() + 160 + 16 >= reader.size()\n    }\n  }\n\n  // recursively parse nodes until the end of the file is reached\n  parseNode(reader, version) {\n    const node = {}\n\n    // The first three data sizes depends on version.\n    const endOffset = version >= 7500 ? reader.getUint64() : reader.getUint32()\n    const numProperties = version >= 7500 ? reader.getUint64() : reader.getUint32()\n\n    version >= 7500 ? reader.getUint64() : reader.getUint32() // the returned propertyListLen is not used\n\n    const nameLen = reader.getUint8()\n    const name = reader.getString(nameLen)\n\n    // Regards this node as NULL-record if endOffset is zero\n    if (endOffset === 0) return null\n\n    const propertyList = []\n\n    for (let i = 0; i < numProperties; i++) {\n      propertyList.push(this.parseProperty(reader))\n    }\n\n    // Regards the first three elements in propertyList as id, attrName, and attrType\n    const id = propertyList.length > 0 ? propertyList[0] : ''\n    const attrName = propertyList.length > 1 ? propertyList[1] : ''\n    const attrType = propertyList.length > 2 ? propertyList[2] : ''\n\n    // check if this node represents just a single property\n    // like (name, 0) set or (name2, [0, 1, 2]) set of {name: 0, name2: [0, 1, 2]}\n    node.singleProperty = numProperties === 1 && reader.getOffset() === endOffset ? true : false\n\n    while (endOffset > reader.getOffset()) {\n      const subNode = this.parseNode(reader, version)\n\n      if (subNode !== null) this.parseSubNode(name, node, subNode)\n    }\n\n    node.propertyList = propertyList // raw property list used by parent\n\n    if (typeof id === 'number') node.id = id\n    if (attrName !== '') node.attrName = attrName\n    if (attrType !== '') node.attrType = attrType\n    if (name !== '') node.name = name\n\n    return node\n  }\n\n  parseSubNode(name, node, subNode) {\n    // special case: child node is single property\n    if (subNode.singleProperty === true) {\n      const value = subNode.propertyList[0]\n\n      if (Array.isArray(value)) {\n        node[subNode.name] = subNode\n\n        subNode.a = value\n      } else {\n        node[subNode.name] = value\n      }\n    } else if (name === 'Connections' && subNode.name === 'C') {\n      const array = []\n\n      subNode.propertyList.forEach(function (property, i) {\n        // first Connection is FBX type (OO, OP, etc.). We'll discard these\n        if (i !== 0) array.push(property)\n      })\n\n      if (node.connections === undefined) {\n        node.connections = []\n      }\n\n      node.connections.push(array)\n    } else if (subNode.name === 'Properties70') {\n      const keys = Object.keys(subNode)\n\n      keys.forEach(function (key) {\n        node[key] = subNode[key]\n      })\n    } else if (name === 'Properties70' && subNode.name === 'P') {\n      let innerPropName = subNode.propertyList[0]\n      let innerPropType1 = subNode.propertyList[1]\n      const innerPropType2 = subNode.propertyList[2]\n      const innerPropFlag = subNode.propertyList[3]\n      let innerPropValue\n\n      if (innerPropName.indexOf('Lcl ') === 0) innerPropName = innerPropName.replace('Lcl ', 'Lcl_')\n      if (innerPropType1.indexOf('Lcl ') === 0) innerPropType1 = innerPropType1.replace('Lcl ', 'Lcl_')\n\n      if (\n        innerPropType1 === 'Color' ||\n        innerPropType1 === 'ColorRGB' ||\n        innerPropType1 === 'Vector' ||\n        innerPropType1 === 'Vector3D' ||\n        innerPropType1.indexOf('Lcl_') === 0\n      ) {\n        innerPropValue = [subNode.propertyList[4], subNode.propertyList[5], subNode.propertyList[6]]\n      } else {\n        innerPropValue = subNode.propertyList[4]\n      }\n\n      // this will be copied to parent, see above\n      node[innerPropName] = {\n        type: innerPropType1,\n        type2: innerPropType2,\n        flag: innerPropFlag,\n        value: innerPropValue,\n      }\n    } else if (node[subNode.name] === undefined) {\n      if (typeof subNode.id === 'number') {\n        node[subNode.name] = {}\n        node[subNode.name][subNode.id] = subNode\n      } else {\n        node[subNode.name] = subNode\n      }\n    } else {\n      if (subNode.name === 'PoseNode') {\n        if (!Array.isArray(node[subNode.name])) {\n          node[subNode.name] = [node[subNode.name]]\n        }\n\n        node[subNode.name].push(subNode)\n      } else if (node[subNode.name][subNode.id] === undefined) {\n        node[subNode.name][subNode.id] = subNode\n      }\n    }\n  }\n\n  parseProperty(reader) {\n    const type = reader.getString(1)\n    let length\n\n    switch (type) {\n      case 'C':\n        return reader.getBoolean()\n\n      case 'D':\n        return reader.getFloat64()\n\n      case 'F':\n        return reader.getFloat32()\n\n      case 'I':\n        return reader.getInt32()\n\n      case 'L':\n        return reader.getInt64()\n\n      case 'R':\n        length = reader.getUint32()\n        return reader.getArrayBuffer(length)\n\n      case 'S':\n        length = reader.getUint32()\n        return reader.getString(length)\n\n      case 'Y':\n        return reader.getInt16()\n\n      case 'b':\n      case 'c':\n      case 'd':\n      case 'f':\n      case 'i':\n      case 'l':\n        const arrayLength = reader.getUint32()\n        const encoding = reader.getUint32() // 0: non-compressed, 1: compressed\n        const compressedLength = reader.getUint32()\n\n        if (encoding === 0) {\n          switch (type) {\n            case 'b':\n            case 'c':\n              return reader.getBooleanArray(arrayLength)\n\n            case 'd':\n              return reader.getFloat64Array(arrayLength)\n\n            case 'f':\n              return reader.getFloat32Array(arrayLength)\n\n            case 'i':\n              return reader.getInt32Array(arrayLength)\n\n            case 'l':\n              return reader.getInt64Array(arrayLength)\n          }\n        }\n\n        const data = unzlibSync(new Uint8Array(reader.getArrayBuffer(compressedLength)))\n        const reader2 = new BinaryReader(data.buffer)\n\n        switch (type) {\n          case 'b':\n          case 'c':\n            return reader2.getBooleanArray(arrayLength)\n\n          case 'd':\n            return reader2.getFloat64Array(arrayLength)\n\n          case 'f':\n            return reader2.getFloat32Array(arrayLength)\n\n          case 'i':\n            return reader2.getInt32Array(arrayLength)\n\n          case 'l':\n            return reader2.getInt64Array(arrayLength)\n        }\n\n      default:\n        throw new Error('THREE.FBXLoader: Unknown property type ' + type)\n    }\n  }\n}\n\nclass BinaryReader {\n  constructor(buffer, littleEndian) {\n    this.dv = new DataView(buffer)\n    this.offset = 0\n    this.littleEndian = littleEndian !== undefined ? littleEndian : true\n  }\n\n  getOffset() {\n    return this.offset\n  }\n\n  size() {\n    return this.dv.buffer.byteLength\n  }\n\n  skip(length) {\n    this.offset += length\n  }\n\n  // seems like true/false representation depends on exporter.\n  // true: 1 or 'Y'(=0x59), false: 0 or 'T'(=0x54)\n  // then sees LSB.\n  getBoolean() {\n    return (this.getUint8() & 1) === 1\n  }\n\n  getBooleanArray(size) {\n    const a = []\n\n    for (let i = 0; i < size; i++) {\n      a.push(this.getBoolean())\n    }\n\n    return a\n  }\n\n  getUint8() {\n    const value = this.dv.getUint8(this.offset)\n    this.offset += 1\n    return value\n  }\n\n  getInt16() {\n    const value = this.dv.getInt16(this.offset, this.littleEndian)\n    this.offset += 2\n    return value\n  }\n\n  getInt32() {\n    const value = this.dv.getInt32(this.offset, this.littleEndian)\n    this.offset += 4\n    return value\n  }\n\n  getInt32Array(size) {\n    const a = []\n\n    for (let i = 0; i < size; i++) {\n      a.push(this.getInt32())\n    }\n\n    return a\n  }\n\n  getUint32() {\n    const value = this.dv.getUint32(this.offset, this.littleEndian)\n    this.offset += 4\n    return value\n  }\n\n  // JavaScript doesn't support 64-bit integer so calculate this here\n  // 1 << 32 will return 1 so using multiply operation instead here.\n  // There's a possibility that this method returns wrong value if the value\n  // is out of the range between Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER.\n  // TODO: safely handle 64-bit integer\n  getInt64() {\n    let low, high\n\n    if (this.littleEndian) {\n      low = this.getUint32()\n      high = this.getUint32()\n    } else {\n      high = this.getUint32()\n      low = this.getUint32()\n    }\n\n    // calculate negative value\n    if (high & 0x80000000) {\n      high = ~high & 0xffffffff\n      low = ~low & 0xffffffff\n\n      if (low === 0xffffffff) high = (high + 1) & 0xffffffff\n\n      low = (low + 1) & 0xffffffff\n\n      return -(high * 0x100000000 + low)\n    }\n\n    return high * 0x100000000 + low\n  }\n\n  getInt64Array(size) {\n    const a = []\n\n    for (let i = 0; i < size; i++) {\n      a.push(this.getInt64())\n    }\n\n    return a\n  }\n\n  // Note: see getInt64() comment\n  getUint64() {\n    let low, high\n\n    if (this.littleEndian) {\n      low = this.getUint32()\n      high = this.getUint32()\n    } else {\n      high = this.getUint32()\n      low = this.getUint32()\n    }\n\n    return high * 0x100000000 + low\n  }\n\n  getFloat32() {\n    const value = this.dv.getFloat32(this.offset, this.littleEndian)\n    this.offset += 4\n    return value\n  }\n\n  getFloat32Array(size) {\n    const a = []\n\n    for (let i = 0; i < size; i++) {\n      a.push(this.getFloat32())\n    }\n\n    return a\n  }\n\n  getFloat64() {\n    const value = this.dv.getFloat64(this.offset, this.littleEndian)\n    this.offset += 8\n    return value\n  }\n\n  getFloat64Array(size) {\n    const a = []\n\n    for (let i = 0; i < size; i++) {\n      a.push(this.getFloat64())\n    }\n\n    return a\n  }\n\n  getArrayBuffer(size) {\n    const value = this.dv.buffer.slice(this.offset, this.offset + size)\n    this.offset += size\n    return value\n  }\n\n  getString(size) {\n    // note: safari 9 doesn't support Uint8Array.indexOf; create intermediate array instead\n    let a = []\n\n    for (let i = 0; i < size; i++) {\n      a[i] = this.getUint8()\n    }\n\n    const nullByte = a.indexOf(0)\n    if (nullByte >= 0) a = a.slice(0, nullByte)\n\n    return decodeText(new Uint8Array(a))\n  }\n}\n\n// FBXTree holds a representation of the FBX data, returned by the TextParser ( FBX ASCII format)\n// and BinaryParser( FBX Binary format)\nclass FBXTree {\n  add(key, val) {\n    this[key] = val\n  }\n}\n\n// ************** UTILITY FUNCTIONS **************\n\nfunction isFbxFormatBinary(buffer) {\n  const CORRECT = 'Kaydara\\u0020FBX\\u0020Binary\\u0020\\u0020\\0'\n\n  return buffer.byteLength >= CORRECT.length && CORRECT === convertArrayBufferToString(buffer, 0, CORRECT.length)\n}\n\nfunction isFbxFormatASCII(text) {\n  const CORRECT = [\n    'K',\n    'a',\n    'y',\n    'd',\n    'a',\n    'r',\n    'a',\n    '\\\\',\n    'F',\n    'B',\n    'X',\n    '\\\\',\n    'B',\n    'i',\n    'n',\n    'a',\n    'r',\n    'y',\n    '\\\\',\n    '\\\\',\n  ]\n\n  let cursor = 0\n\n  function read(offset) {\n    const result = text[offset - 1]\n    text = text.slice(cursor + offset)\n    cursor++\n    return result\n  }\n\n  for (let i = 0; i < CORRECT.length; ++i) {\n    const num = read(1)\n    if (num === CORRECT[i]) {\n      return false\n    }\n  }\n\n  return true\n}\n\nfunction getFbxVersion(text) {\n  const versionRegExp = /FBXVersion: (\\d+)/\n  const match = text.match(versionRegExp)\n\n  if (match) {\n    const version = parseInt(match[1])\n    return version\n  }\n\n  throw new Error('THREE.FBXLoader: Cannot find the version number for the file given.')\n}\n\n// Converts FBX ticks into real time seconds.\nfunction convertFBXTimeToSeconds(time) {\n  return time / 46186158000\n}\n\nconst dataArray = []\n\n// extracts the data from the correct position in the FBX array based on indexing type\nfunction getData(polygonVertexIndex, polygonIndex, vertexIndex, infoObject) {\n  let index\n\n  switch (infoObject.mappingType) {\n    case 'ByPolygonVertex':\n      index = polygonVertexIndex\n      break\n    case 'ByPolygon':\n      index = polygonIndex\n      break\n    case 'ByVertice':\n      index = vertexIndex\n      break\n    case 'AllSame':\n      index = infoObject.indices[0]\n      break\n    default:\n      console.warn('THREE.FBXLoader: unknown attribute mapping type ' + infoObject.mappingType)\n  }\n\n  if (infoObject.referenceType === 'IndexToDirect') index = infoObject.indices[index]\n\n  const from = index * infoObject.dataSize\n  const to = from + infoObject.dataSize\n\n  return slice(dataArray, infoObject.buffer, from, to)\n}\n\nconst tempEuler = /* @__PURE__ */ new Euler()\nconst tempVec = /* @__PURE__ */ new Vector3()\n\n// generate transformation from FBX transform data\n// ref: https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_10CDD63C_79C1_4F2D_BB28_AD2BE65A02ED_htm\n// 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\nfunction generateTransform(transformData) {\n  const lTranslationM = new Matrix4()\n  const lPreRotationM = new Matrix4()\n  const lRotationM = new Matrix4()\n  const lPostRotationM = new Matrix4()\n\n  const lScalingM = new Matrix4()\n  const lScalingPivotM = new Matrix4()\n  const lScalingOffsetM = new Matrix4()\n  const lRotationOffsetM = new Matrix4()\n  const lRotationPivotM = new Matrix4()\n\n  const lParentGX = new Matrix4()\n  const lParentLX = new Matrix4()\n  const lGlobalT = new Matrix4()\n\n  const inheritType = transformData.inheritType ? transformData.inheritType : 0\n\n  if (transformData.translation) lTranslationM.setPosition(tempVec.fromArray(transformData.translation))\n\n  if (transformData.preRotation) {\n    const array = transformData.preRotation.map(MathUtils.degToRad)\n    array.push(transformData.eulerOrder)\n    lPreRotationM.makeRotationFromEuler(tempEuler.fromArray(array))\n  }\n\n  if (transformData.rotation) {\n    const array = transformData.rotation.map(MathUtils.degToRad)\n    array.push(transformData.eulerOrder)\n    lRotationM.makeRotationFromEuler(tempEuler.fromArray(array))\n  }\n\n  if (transformData.postRotation) {\n    const array = transformData.postRotation.map(MathUtils.degToRad)\n    array.push(transformData.eulerOrder)\n    lPostRotationM.makeRotationFromEuler(tempEuler.fromArray(array))\n    lPostRotationM.invert()\n  }\n\n  if (transformData.scale) lScalingM.scale(tempVec.fromArray(transformData.scale))\n\n  // Pivots and offsets\n  if (transformData.scalingOffset) lScalingOffsetM.setPosition(tempVec.fromArray(transformData.scalingOffset))\n  if (transformData.scalingPivot) lScalingPivotM.setPosition(tempVec.fromArray(transformData.scalingPivot))\n  if (transformData.rotationOffset) lRotationOffsetM.setPosition(tempVec.fromArray(transformData.rotationOffset))\n  if (transformData.rotationPivot) lRotationPivotM.setPosition(tempVec.fromArray(transformData.rotationPivot))\n\n  // parent transform\n  if (transformData.parentMatrixWorld) {\n    lParentLX.copy(transformData.parentMatrix)\n    lParentGX.copy(transformData.parentMatrixWorld)\n  }\n\n  const lLRM = lPreRotationM.clone().multiply(lRotationM).multiply(lPostRotationM)\n  // Global Rotation\n  const lParentGRM = new Matrix4()\n  lParentGRM.extractRotation(lParentGX)\n\n  // Global Shear*Scaling\n  const lParentTM = new Matrix4()\n  lParentTM.copyPosition(lParentGX)\n\n  const lParentGRSM = lParentTM.clone().invert().multiply(lParentGX)\n  const lParentGSM = lParentGRM.clone().invert().multiply(lParentGRSM)\n  const lLSM = lScalingM\n\n  const lGlobalRS = new Matrix4()\n\n  if (inheritType === 0) {\n    lGlobalRS.copy(lParentGRM).multiply(lLRM).multiply(lParentGSM).multiply(lLSM)\n  } else if (inheritType === 1) {\n    lGlobalRS.copy(lParentGRM).multiply(lParentGSM).multiply(lLRM).multiply(lLSM)\n  } else {\n    const lParentLSM = new Matrix4().scale(new Vector3().setFromMatrixScale(lParentLX))\n    const lParentLSM_inv = lParentLSM.clone().invert()\n    const lParentGSM_noLocal = lParentGSM.clone().multiply(lParentLSM_inv)\n\n    lGlobalRS.copy(lParentGRM).multiply(lLRM).multiply(lParentGSM_noLocal).multiply(lLSM)\n  }\n\n  const lRotationPivotM_inv = lRotationPivotM.clone().invert()\n  const lScalingPivotM_inv = lScalingPivotM.clone().invert()\n  // Calculate the local transform matrix\n  let lTransform = lTranslationM\n    .clone()\n    .multiply(lRotationOffsetM)\n    .multiply(lRotationPivotM)\n    .multiply(lPreRotationM)\n    .multiply(lRotationM)\n    .multiply(lPostRotationM)\n    .multiply(lRotationPivotM_inv)\n    .multiply(lScalingOffsetM)\n    .multiply(lScalingPivotM)\n    .multiply(lScalingM)\n    .multiply(lScalingPivotM_inv)\n\n  const lLocalTWithAllPivotAndOffsetInfo = new Matrix4().copyPosition(lTransform)\n\n  const lGlobalTranslation = lParentGX.clone().multiply(lLocalTWithAllPivotAndOffsetInfo)\n  lGlobalT.copyPosition(lGlobalTranslation)\n\n  lTransform = lGlobalT.clone().multiply(lGlobalRS)\n\n  // from global to local\n  lTransform.premultiply(lParentGX.invert())\n\n  return lTransform\n}\n\n// Returns the three.js intrinsic Euler order corresponding to FBX extrinsic Euler order\n// ref: http://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_euler_html\nfunction getEulerOrder(order) {\n  order = order || 0\n\n  const enums = [\n    'ZYX', // -> XYZ extrinsic\n    'YZX', // -> XZY extrinsic\n    'XZY', // -> YZX extrinsic\n    'ZXY', // -> YXZ extrinsic\n    'YXZ', // -> ZXY extrinsic\n    'XYZ', // -> ZYX extrinsic\n    //'SphericXYZ', // not possible to support\n  ]\n\n  if (order === 6) {\n    console.warn('THREE.FBXLoader: unsupported Euler Order: Spherical XYZ. Animations and rotations may be incorrect.')\n    return enums[0]\n  }\n\n  return enums[order]\n}\n\n// Parses comma separated list of numbers and returns them an array.\n// Used internally by the TextParser\nfunction parseNumberArray(value) {\n  const array = value.split(',').map(function (val) {\n    return parseFloat(val)\n  })\n\n  return array\n}\n\nfunction convertArrayBufferToString(buffer, from, to) {\n  if (from === undefined) from = 0\n  if (to === undefined) to = buffer.byteLength\n\n  return decodeText(new Uint8Array(buffer, from, to))\n}\n\nfunction append(a, b) {\n  for (let i = 0, j = a.length, l = b.length; i < l; i++, j++) {\n    a[j] = b[i]\n  }\n}\n\nfunction slice(a, b, from, to) {\n  for (let i = from, j = 0; i < to; i++, j++) {\n    a[j] = b[i]\n  }\n\n  return a\n}\n\n// inject array a2 into array a1 at index\nfunction inject(a1, index, a2) {\n  return a1.slice(0, index).concat(a2).concat(a1.slice(index))\n}\n\nexport { FBXLoader }\n"],"names":["Loader","LoaderUtils","FileLoader","TextureLoader","RepeatWrapping","ClampToEdgeWrapping","Texture","MeshPhongMaterial","MeshLambertMaterial","Color","EquirectangularReflectionMapping","Matrix4","child","Group","Bone","PropertyBinding","Object3D","PerspectiveCamera","OrthographicCamera","PointLight","DirectionalLight","MathUtils","SpotLight","material","SkinnedMesh","Mesh","LineBasicMaterial","Line","Vector3","Skeleton","AmbientLight","skeleton","BufferGeometry","Float32BufferAttribute","Uint16BufferAttribute","Matrix3","UV1","NURBSCurve","Vector4","AnimationClip","Quaternion","Euler","VectorKeyframeTrack","QuaternionKeyframeTrack","NumberKeyframeTrack","unzlibSync","decodeText"],"mappings":"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"}