{"version":3,"file":"MMDAnimationHelper.cjs","sources":["../../src/animation/MMDAnimationHelper.js"],"sourcesContent":["import { AnimationMixer, Object3D, Quaternion, Vector3 } from 'three'\nimport { CCDIKSolver } from '../animation/CCDIKSolver'\nimport { MMDPhysics } from '../animation/MMDPhysics'\n\n/**\n * MMDAnimationHelper handles animation of MMD assets loaded by MMDLoader\n * with MMD special features as IK, Grant, and Physics.\n *\n * Dependencies\n *  - ammo.js https://github.com/kripken/ammo.js\n *  - MMDPhysics\n *  - CCDIKSolver\n *\n * TODO\n *  - more precise grant skinning support.\n */\nclass MMDAnimationHelper {\n  /**\n   * @param {Object} params - (optional)\n   * @param {boolean} params.sync - Whether animation durations of added objects are synched. Default is true.\n   * @param {Number} params.afterglow - Default is 0.0.\n   * @param {boolean} params.resetPhysicsOnLoop - Default is true.\n   */\n  constructor(params = {}) {\n    this.meshes = []\n\n    this.camera = null\n    this.cameraTarget = new Object3D()\n    this.cameraTarget.name = 'target'\n\n    this.audio = null\n    this.audioManager = null\n\n    this.objects = new WeakMap()\n\n    this.configuration = {\n      sync: params.sync !== undefined ? params.sync : true,\n      afterglow: params.afterglow !== undefined ? params.afterglow : 0.0,\n      resetPhysicsOnLoop: params.resetPhysicsOnLoop !== undefined ? params.resetPhysicsOnLoop : true,\n      pmxAnimation: params.pmxAnimation !== undefined ? params.pmxAnimation : false,\n    }\n\n    this.enabled = {\n      animation: true,\n      ik: true,\n      grant: true,\n      physics: true,\n      cameraAnimation: true,\n    }\n\n    this.onBeforePhysics = function (/* mesh */) {}\n\n    // experimental\n    this.sharedPhysics = false\n    this.masterPhysics = null\n  }\n\n  /**\n   * Adds an Three.js Object to helper and setups animation.\n   * The anmation durations of added objects are synched\n   * if this.configuration.sync is true.\n   *\n   * @param {THREE.SkinnedMesh|THREE.Camera|THREE.Audio} object\n   * @param {Object} params - (optional)\n   * @param {THREE.AnimationClip|Array<THREE.AnimationClip>} params.animation - Only for THREE.SkinnedMesh and THREE.Camera. Default is undefined.\n   * @param {boolean} params.physics - Only for THREE.SkinnedMesh. Default is true.\n   * @param {Integer} params.warmup - Only for THREE.SkinnedMesh and physics is true. Default is 60.\n   * @param {Number} params.unitStep - Only for THREE.SkinnedMesh and physics is true. Default is 1 / 65.\n   * @param {Integer} params.maxStepNum - Only for THREE.SkinnedMesh and physics is true. Default is 3.\n   * @param {Vector3} params.gravity - Only for THREE.SkinnedMesh and physics is true. Default ( 0, - 9.8 * 10, 0 ).\n   * @param {Number} params.delayTime - Only for THREE.Audio. Default is 0.0.\n   * @return {MMDAnimationHelper}\n   */\n  add(object, params = {}) {\n    if (object.isSkinnedMesh) {\n      this._addMesh(object, params)\n    } else if (object.isCamera) {\n      this._setupCamera(object, params)\n    } else if (object.type === 'Audio') {\n      this._setupAudio(object, params)\n    } else {\n      throw new Error(\n        'THREE.MMDAnimationHelper.add: ' +\n          'accepts only ' +\n          'THREE.SkinnedMesh or ' +\n          'THREE.Camera or ' +\n          'THREE.Audio instance.',\n      )\n    }\n\n    if (this.configuration.sync) this._syncDuration()\n\n    return this\n  }\n\n  /**\n   * Removes an Three.js Object from helper.\n   *\n   * @param {THREE.SkinnedMesh|THREE.Camera|THREE.Audio} object\n   * @return {MMDAnimationHelper}\n   */\n  remove(object) {\n    if (object.isSkinnedMesh) {\n      this._removeMesh(object)\n    } else if (object.isCamera) {\n      this._clearCamera(object)\n    } else if (object.type === 'Audio') {\n      this._clearAudio(object)\n    } else {\n      throw new Error(\n        'THREE.MMDAnimationHelper.remove: ' +\n          'accepts only ' +\n          'THREE.SkinnedMesh or ' +\n          'THREE.Camera or ' +\n          'THREE.Audio instance.',\n      )\n    }\n\n    if (this.configuration.sync) this._syncDuration()\n\n    return this\n  }\n\n  /**\n   * Updates the animation.\n   *\n   * @param {Number} delta\n   * @return {MMDAnimationHelper}\n   */\n  update(delta) {\n    if (this.audioManager !== null) this.audioManager.control(delta)\n\n    for (let i = 0; i < this.meshes.length; i++) {\n      this._animateMesh(this.meshes[i], delta)\n    }\n\n    if (this.sharedPhysics) this._updateSharedPhysics(delta)\n\n    if (this.camera !== null) this._animateCamera(this.camera, delta)\n\n    return this\n  }\n\n  /**\n   * Changes the pose of SkinnedMesh as VPD specifies.\n   *\n   * @param {THREE.SkinnedMesh} mesh\n   * @param {Object} vpd - VPD content parsed MMDParser\n   * @param {Object} params - (optional)\n   * @param {boolean} params.resetPose - Default is true.\n   * @param {boolean} params.ik - Default is true.\n   * @param {boolean} params.grant - Default is true.\n   * @return {MMDAnimationHelper}\n   */\n  pose(mesh, vpd, params = {}) {\n    if (params.resetPose !== false) mesh.pose()\n\n    const bones = mesh.skeleton.bones\n    const boneParams = vpd.bones\n\n    const boneNameDictionary = {}\n\n    for (let i = 0, il = bones.length; i < il; i++) {\n      boneNameDictionary[bones[i].name] = i\n    }\n\n    const vector = new Vector3()\n    const quaternion = new Quaternion()\n\n    for (let i = 0, il = boneParams.length; i < il; i++) {\n      const boneParam = boneParams[i]\n      const boneIndex = boneNameDictionary[boneParam.name]\n\n      if (boneIndex === undefined) continue\n\n      const bone = bones[boneIndex]\n      bone.position.add(vector.fromArray(boneParam.translation))\n      bone.quaternion.multiply(quaternion.fromArray(boneParam.quaternion))\n    }\n\n    mesh.updateMatrixWorld(true)\n\n    // PMX animation system special path\n    if (this.configuration.pmxAnimation && mesh.geometry.userData.MMD && mesh.geometry.userData.MMD.format === 'pmx') {\n      const sortedBonesData = this._sortBoneDataArray(mesh.geometry.userData.MMD.bones.slice())\n      const ikSolver = params.ik !== false ? this._createCCDIKSolver(mesh) : null\n      const grantSolver = params.grant !== false ? this.createGrantSolver(mesh) : null\n      this._animatePMXMesh(mesh, sortedBonesData, ikSolver, grantSolver)\n    } else {\n      if (params.ik !== false) {\n        this._createCCDIKSolver(mesh).update()\n      }\n\n      if (params.grant !== false) {\n        this.createGrantSolver(mesh).update()\n      }\n    }\n\n    return this\n  }\n\n  /**\n   * Enabes/Disables an animation feature.\n   *\n   * @param {string} key\n   * @param {boolean} enabled\n   * @return {MMDAnimationHelper}\n   */\n  enable(key, enabled) {\n    if (this.enabled[key] === undefined) {\n      throw new Error('THREE.MMDAnimationHelper.enable: ' + 'unknown key ' + key)\n    }\n\n    this.enabled[key] = enabled\n\n    if (key === 'physics') {\n      for (let i = 0, il = this.meshes.length; i < il; i++) {\n        this._optimizeIK(this.meshes[i], enabled)\n      }\n    }\n\n    return this\n  }\n\n  /**\n   * Creates an GrantSolver instance.\n   *\n   * @param {THREE.SkinnedMesh} mesh\n   * @return {GrantSolver}\n   */\n  createGrantSolver(mesh) {\n    return new GrantSolver(mesh, mesh.geometry.userData.MMD.grants)\n  }\n\n  // private methods\n\n  _addMesh(mesh, params) {\n    if (this.meshes.indexOf(mesh) >= 0) {\n      throw new Error('THREE.MMDAnimationHelper._addMesh: ' + \"SkinnedMesh '\" + mesh.name + \"' has already been added.\")\n    }\n\n    this.meshes.push(mesh)\n    this.objects.set(mesh, { looped: false })\n\n    this._setupMeshAnimation(mesh, params.animation)\n\n    if (params.physics !== false) {\n      this._setupMeshPhysics(mesh, params)\n    }\n\n    return this\n  }\n\n  _setupCamera(camera, params) {\n    if (this.camera === camera) {\n      throw new Error('THREE.MMDAnimationHelper._setupCamera: ' + \"Camera '\" + camera.name + \"' has already been set.\")\n    }\n\n    if (this.camera) this.clearCamera(this.camera)\n\n    this.camera = camera\n\n    camera.add(this.cameraTarget)\n\n    this.objects.set(camera, {})\n\n    if (params.animation !== undefined) {\n      this._setupCameraAnimation(camera, params.animation)\n    }\n\n    return this\n  }\n\n  _setupAudio(audio, params) {\n    if (this.audio === audio) {\n      throw new Error('THREE.MMDAnimationHelper._setupAudio: ' + \"Audio '\" + audio.name + \"' has already been set.\")\n    }\n\n    if (this.audio) this.clearAudio(this.audio)\n\n    this.audio = audio\n    this.audioManager = new AudioManager(audio, params)\n\n    this.objects.set(this.audioManager, {\n      duration: this.audioManager.duration,\n    })\n\n    return this\n  }\n\n  _removeMesh(mesh) {\n    let found = false\n    let writeIndex = 0\n\n    for (let i = 0, il = this.meshes.length; i < il; i++) {\n      if (this.meshes[i] === mesh) {\n        this.objects.delete(mesh)\n        found = true\n\n        continue\n      }\n\n      this.meshes[writeIndex++] = this.meshes[i]\n    }\n\n    if (!found) {\n      throw new Error(\n        'THREE.MMDAnimationHelper._removeMesh: ' + \"SkinnedMesh '\" + mesh.name + \"' has not been added yet.\",\n      )\n    }\n\n    this.meshes.length = writeIndex\n\n    return this\n  }\n\n  _clearCamera(camera) {\n    if (camera !== this.camera) {\n      throw new Error('THREE.MMDAnimationHelper._clearCamera: ' + \"Camera '\" + camera.name + \"' has not been set yet.\")\n    }\n\n    this.camera.remove(this.cameraTarget)\n\n    this.objects.delete(this.camera)\n    this.camera = null\n\n    return this\n  }\n\n  _clearAudio(audio) {\n    if (audio !== this.audio) {\n      throw new Error('THREE.MMDAnimationHelper._clearAudio: ' + \"Audio '\" + audio.name + \"' has not been set yet.\")\n    }\n\n    this.objects.delete(this.audioManager)\n\n    this.audio = null\n    this.audioManager = null\n\n    return this\n  }\n\n  _setupMeshAnimation(mesh, animation) {\n    const objects = this.objects.get(mesh)\n\n    if (animation !== undefined) {\n      const animations = Array.isArray(animation) ? animation : [animation]\n\n      objects.mixer = new AnimationMixer(mesh)\n\n      for (let i = 0, il = animations.length; i < il; i++) {\n        objects.mixer.clipAction(animations[i]).play()\n      }\n\n      // TODO: find a workaround not to access ._clip looking like a private property\n      objects.mixer.addEventListener('loop', function (event) {\n        const tracks = event.action._clip.tracks\n\n        if (tracks.length > 0 && tracks[0].name.slice(0, 6) !== '.bones') return\n\n        objects.looped = true\n      })\n    }\n\n    objects.ikSolver = this._createCCDIKSolver(mesh)\n    objects.grantSolver = this.createGrantSolver(mesh)\n\n    return this\n  }\n\n  _setupCameraAnimation(camera, animation) {\n    const animations = Array.isArray(animation) ? animation : [animation]\n\n    const objects = this.objects.get(camera)\n\n    objects.mixer = new AnimationMixer(camera)\n\n    for (let i = 0, il = animations.length; i < il; i++) {\n      objects.mixer.clipAction(animations[i]).play()\n    }\n  }\n\n  _setupMeshPhysics(mesh, params) {\n    const objects = this.objects.get(mesh)\n\n    // shared physics is experimental\n\n    if (params.world === undefined && this.sharedPhysics) {\n      const masterPhysics = this._getMasterPhysics()\n\n      if (masterPhysics !== null) world = masterPhysics.world // eslint-disable-line no-undef\n    }\n\n    objects.physics = this._createMMDPhysics(mesh, params)\n\n    if (objects.mixer && params.animationWarmup !== false) {\n      this._animateMesh(mesh, 0)\n      objects.physics.reset()\n    }\n\n    objects.physics.warmup(params.warmup !== undefined ? params.warmup : 60)\n\n    this._optimizeIK(mesh, true)\n  }\n\n  _animateMesh(mesh, delta) {\n    const objects = this.objects.get(mesh)\n\n    const mixer = objects.mixer\n    const ikSolver = objects.ikSolver\n    const grantSolver = objects.grantSolver\n    const physics = objects.physics\n    const looped = objects.looped\n\n    if (mixer && this.enabled.animation) {\n      // alternate solution to save/restore bones but less performant?\n      //mesh.pose();\n      //this._updatePropertyMixersBuffer( mesh );\n\n      this._restoreBones(mesh)\n\n      mixer.update(delta)\n\n      this._saveBones(mesh)\n\n      // PMX animation system special path\n      if (\n        this.configuration.pmxAnimation &&\n        mesh.geometry.userData.MMD &&\n        mesh.geometry.userData.MMD.format === 'pmx'\n      ) {\n        if (!objects.sortedBonesData)\n          objects.sortedBonesData = this._sortBoneDataArray(mesh.geometry.userData.MMD.bones.slice())\n\n        this._animatePMXMesh(\n          mesh,\n          objects.sortedBonesData,\n          ikSolver && this.enabled.ik ? ikSolver : null,\n          grantSolver && this.enabled.grant ? grantSolver : null,\n        )\n      } else {\n        if (ikSolver && this.enabled.ik) {\n          mesh.updateMatrixWorld(true)\n          ikSolver.update()\n        }\n\n        if (grantSolver && this.enabled.grant) {\n          grantSolver.update()\n        }\n      }\n    }\n\n    if (looped === true && this.enabled.physics) {\n      if (physics && this.configuration.resetPhysicsOnLoop) physics.reset()\n\n      objects.looped = false\n    }\n\n    if (physics && this.enabled.physics && !this.sharedPhysics) {\n      this.onBeforePhysics(mesh)\n      physics.update(delta)\n    }\n  }\n\n  // Sort bones in order by 1. transformationClass and 2. bone index.\n  // In PMX animation system, bone transformations should be processed\n  // in this order.\n  _sortBoneDataArray(boneDataArray) {\n    return boneDataArray.sort(function (a, b) {\n      if (a.transformationClass !== b.transformationClass) {\n        return a.transformationClass - b.transformationClass\n      } else {\n        return a.index - b.index\n      }\n    })\n  }\n\n  // PMX Animation system is a bit too complex and doesn't great match to\n  // Three.js Animation system. This method attempts to simulate it as much as\n  // possible but doesn't perfectly simulate.\n  // This method is more costly than the regular one so\n  // you are recommended to set constructor parameter \"pmxAnimation: true\"\n  // only if your PMX model animation doesn't work well.\n  // If you need better method you would be required to write your own.\n  _animatePMXMesh(mesh, sortedBonesData, ikSolver, grantSolver) {\n    _quaternionIndex = 0\n    _grantResultMap.clear()\n\n    for (let i = 0, il = sortedBonesData.length; i < il; i++) {\n      updateOne(mesh, sortedBonesData[i].index, ikSolver, grantSolver)\n    }\n\n    mesh.updateMatrixWorld(true)\n    return this\n  }\n\n  _animateCamera(camera, delta) {\n    const mixer = this.objects.get(camera).mixer\n\n    if (mixer && this.enabled.cameraAnimation) {\n      mixer.update(delta)\n\n      camera.updateProjectionMatrix()\n\n      camera.up.set(0, 1, 0)\n      camera.up.applyQuaternion(camera.quaternion)\n      camera.lookAt(this.cameraTarget.position)\n    }\n  }\n\n  _optimizeIK(mesh, physicsEnabled) {\n    const iks = mesh.geometry.userData.MMD.iks\n    const bones = mesh.geometry.userData.MMD.bones\n\n    for (let i = 0, il = iks.length; i < il; i++) {\n      const ik = iks[i]\n      const links = ik.links\n\n      for (let j = 0, jl = links.length; j < jl; j++) {\n        const link = links[j]\n\n        if (physicsEnabled === true) {\n          // disable IK of the bone the corresponding rigidBody type of which is 1 or 2\n          // because its rotation will be overriden by physics\n          link.enabled = bones[link.index].rigidBodyType > 0 ? false : true\n        } else {\n          link.enabled = true\n        }\n      }\n    }\n  }\n\n  _createCCDIKSolver(mesh) {\n    if (CCDIKSolver === undefined) {\n      throw new Error('THREE.MMDAnimationHelper: Import CCDIKSolver.')\n    }\n\n    return new CCDIKSolver(mesh, mesh.geometry.userData.MMD.iks)\n  }\n\n  _createMMDPhysics(mesh, params) {\n    if (MMDPhysics === undefined) {\n      throw new Error('THREE.MMDPhysics: Import MMDPhysics.')\n    }\n\n    return new MMDPhysics(mesh, mesh.geometry.userData.MMD.rigidBodies, mesh.geometry.userData.MMD.constraints, params)\n  }\n\n  /*\n   * Detects the longest duration and then sets it to them to sync.\n   * TODO: Not to access private properties ( ._actions and ._clip )\n   */\n  _syncDuration() {\n    let max = 0.0\n\n    const objects = this.objects\n    const meshes = this.meshes\n    const camera = this.camera\n    const audioManager = this.audioManager\n\n    // get the longest duration\n\n    for (let i = 0, il = meshes.length; i < il; i++) {\n      const mixer = this.objects.get(meshes[i]).mixer\n\n      if (mixer === undefined) continue\n\n      for (let j = 0; j < mixer._actions.length; j++) {\n        const clip = mixer._actions[j]._clip\n\n        if (!objects.has(clip)) {\n          objects.set(clip, {\n            duration: clip.duration,\n          })\n        }\n\n        max = Math.max(max, objects.get(clip).duration)\n      }\n    }\n\n    if (camera !== null) {\n      const mixer = this.objects.get(camera).mixer\n\n      if (mixer !== undefined) {\n        for (let i = 0, il = mixer._actions.length; i < il; i++) {\n          const clip = mixer._actions[i]._clip\n\n          if (!objects.has(clip)) {\n            objects.set(clip, {\n              duration: clip.duration,\n            })\n          }\n\n          max = Math.max(max, objects.get(clip).duration)\n        }\n      }\n    }\n\n    if (audioManager !== null) {\n      max = Math.max(max, objects.get(audioManager).duration)\n    }\n\n    max += this.configuration.afterglow\n\n    // update the duration\n\n    for (let i = 0, il = this.meshes.length; i < il; i++) {\n      const mixer = this.objects.get(this.meshes[i]).mixer\n\n      if (mixer === undefined) continue\n\n      for (let j = 0, jl = mixer._actions.length; j < jl; j++) {\n        mixer._actions[j]._clip.duration = max\n      }\n    }\n\n    if (camera !== null) {\n      const mixer = this.objects.get(camera).mixer\n\n      if (mixer !== undefined) {\n        for (let i = 0, il = mixer._actions.length; i < il; i++) {\n          mixer._actions[i]._clip.duration = max\n        }\n      }\n    }\n\n    if (audioManager !== null) {\n      audioManager.duration = max\n    }\n  }\n\n  // workaround\n\n  _updatePropertyMixersBuffer(mesh) {\n    const mixer = this.objects.get(mesh).mixer\n\n    const propertyMixers = mixer._bindings\n    const accuIndex = mixer._accuIndex\n\n    for (let i = 0, il = propertyMixers.length; i < il; i++) {\n      const propertyMixer = propertyMixers[i]\n      const buffer = propertyMixer.buffer\n      const stride = propertyMixer.valueSize\n      const offset = (accuIndex + 1) * stride\n\n      propertyMixer.binding.getValue(buffer, offset)\n    }\n  }\n\n  /*\n   * Avoiding these two issues by restore/save bones before/after mixer animation.\n   *\n   * 1. PropertyMixer used by AnimationMixer holds cache value in .buffer.\n   *    Calculating IK, Grant, and Physics after mixer animation can break\n   *    the cache coherency.\n   *\n   * 2. Applying Grant two or more times without reset the posing breaks model.\n   */\n  _saveBones(mesh) {\n    const objects = this.objects.get(mesh)\n\n    const bones = mesh.skeleton.bones\n\n    let backupBones = objects.backupBones\n\n    if (backupBones === undefined) {\n      backupBones = new Float32Array(bones.length * 7)\n      objects.backupBones = backupBones\n    }\n\n    for (let i = 0, il = bones.length; i < il; i++) {\n      const bone = bones[i]\n      bone.position.toArray(backupBones, i * 7)\n      bone.quaternion.toArray(backupBones, i * 7 + 3)\n    }\n  }\n\n  _restoreBones(mesh) {\n    const objects = this.objects.get(mesh)\n\n    const backupBones = objects.backupBones\n\n    if (backupBones === undefined) return\n\n    const bones = mesh.skeleton.bones\n\n    for (let i = 0, il = bones.length; i < il; i++) {\n      const bone = bones[i]\n      bone.position.fromArray(backupBones, i * 7)\n      bone.quaternion.fromArray(backupBones, i * 7 + 3)\n    }\n  }\n\n  // experimental\n\n  _getMasterPhysics() {\n    if (this.masterPhysics !== null) return this.masterPhysics\n\n    for (let i = 0, il = this.meshes.length; i < il; i++) {\n      const physics = this.meshes[i].physics\n\n      if (physics !== undefined && physics !== null) {\n        this.masterPhysics = physics\n        return this.masterPhysics\n      }\n    }\n\n    return null\n  }\n\n  _updateSharedPhysics(delta) {\n    if (this.meshes.length === 0 || !this.enabled.physics || !this.sharedPhysics) return\n\n    const physics = this._getMasterPhysics()\n\n    if (physics === null) return\n\n    for (let i = 0, il = this.meshes.length; i < il; i++) {\n      const p = this.meshes[i].physics\n\n      if (p !== null && p !== undefined) {\n        p.updateRigidBodies()\n      }\n    }\n\n    physics.stepSimulation(delta)\n\n    for (let i = 0, il = this.meshes.length; i < il; i++) {\n      const p = this.meshes[i].physics\n\n      if (p !== null && p !== undefined) {\n        p.updateBones()\n      }\n    }\n  }\n}\n\n// Keep working quaternions for less GC\nconst _quaternions = []\nlet _quaternionIndex = 0\n\nfunction getQuaternion() {\n  if (_quaternionIndex >= _quaternions.length) {\n    _quaternions.push(new Quaternion())\n  }\n\n  return _quaternions[_quaternionIndex++]\n}\n\n// Save rotation whose grant and IK are already applied\n// used by grant children\nconst _grantResultMap = new Map()\n\nfunction updateOne(mesh, boneIndex, ikSolver, grantSolver) {\n  const bones = mesh.skeleton.bones\n  const bonesData = mesh.geometry.userData.MMD.bones\n  const boneData = bonesData[boneIndex]\n  const bone = bones[boneIndex]\n\n  // Return if already updated by being referred as a grant parent.\n  if (_grantResultMap.has(boneIndex)) return\n\n  const quaternion = getQuaternion()\n\n  // Initialize grant result here to prevent infinite loop.\n  // If it's referred before updating with actual result later\n  // result without applyting IK or grant is gotten\n  // but better than composing of infinite loop.\n  _grantResultMap.set(boneIndex, quaternion.copy(bone.quaternion))\n\n  // @TODO: Support global grant and grant position\n  if (grantSolver && boneData.grant && !boneData.grant.isLocal && boneData.grant.affectRotation) {\n    const parentIndex = boneData.grant.parentIndex\n    const ratio = boneData.grant.ratio\n\n    if (!_grantResultMap.has(parentIndex)) {\n      updateOne(mesh, parentIndex, ikSolver, grantSolver)\n    }\n\n    grantSolver.addGrantRotation(bone, _grantResultMap.get(parentIndex), ratio)\n  }\n\n  if (ikSolver && boneData.ik) {\n    // @TODO: Updating world matrices every time solving an IK bone is\n    // costly. Optimize if possible.\n    mesh.updateMatrixWorld(true)\n    ikSolver.updateOne(boneData.ik)\n\n    // No confident, but it seems the grant results with ik links should be updated?\n    const links = boneData.ik.links\n\n    for (let i = 0, il = links.length; i < il; i++) {\n      const link = links[i]\n\n      if (link.enabled === false) continue\n\n      const linkIndex = link.index\n\n      if (_grantResultMap.has(linkIndex)) {\n        _grantResultMap.set(linkIndex, _grantResultMap.get(linkIndex).copy(bones[linkIndex].quaternion))\n      }\n    }\n  }\n\n  // Update with the actual result here\n  quaternion.copy(bone.quaternion)\n}\n\n//\n\nclass AudioManager {\n  /**\n   * @param {THREE.Audio} audio\n   * @param {Object} params - (optional)\n   * @param {Nuumber} params.delayTime\n   */\n  constructor(audio, params = {}) {\n    this.audio = audio\n\n    this.elapsedTime = 0.0\n    this.currentTime = 0.0\n    this.delayTime = params.delayTime !== undefined ? params.delayTime : 0.0\n\n    this.audioDuration = this.audio.buffer.duration\n    this.duration = this.audioDuration + this.delayTime\n  }\n\n  /**\n   * @param {Number} delta\n   * @return {AudioManager}\n   */\n  control(delta) {\n    this.elapsed += delta\n    this.currentTime += delta\n\n    if (this._shouldStopAudio()) this.audio.stop()\n    if (this._shouldStartAudio()) this.audio.play()\n\n    return this\n  }\n\n  // private methods\n\n  _shouldStartAudio() {\n    if (this.audio.isPlaying) return false\n\n    while (this.currentTime >= this.duration) {\n      this.currentTime -= this.duration\n    }\n\n    if (this.currentTime < this.delayTime) return false\n\n    // 'duration' can be bigger than 'audioDuration + delayTime' because of sync configuration\n    if (this.currentTime - this.delayTime > this.audioDuration) return false\n\n    return true\n  }\n\n  _shouldStopAudio() {\n    return this.audio.isPlaying && this.currentTime >= this.duration\n  }\n}\n\nconst _q = new Quaternion()\n\n/**\n * Solver for Grant (Fuyo in Japanese. I just google translated because\n * Fuyo may be MMD specific term and may not be common word in 3D CG terms.)\n * Grant propagates a bone's transform to other bones transforms even if\n * they are not children.\n * @param {THREE.SkinnedMesh} mesh\n * @param {Array<Object>} grants\n */\nclass GrantSolver {\n  constructor(mesh, grants = []) {\n    this.mesh = mesh\n    this.grants = grants\n  }\n\n  /**\n   * Solve all the grant bones\n   * @return {GrantSolver}\n   */\n  update() {\n    const grants = this.grants\n\n    for (let i = 0, il = grants.length; i < il; i++) {\n      this.updateOne(grants[i])\n    }\n\n    return this\n  }\n\n  /**\n   * Solve a grant bone\n   * @param {Object} grant - grant parameter\n   * @return {GrantSolver}\n   */\n  updateOne(grant) {\n    const bones = this.mesh.skeleton.bones\n    const bone = bones[grant.index]\n    const parentBone = bones[grant.parentIndex]\n\n    if (grant.isLocal) {\n      // TODO: implement\n      if (grant.affectPosition) {\n      }\n\n      // TODO: implement\n      if (grant.affectRotation) {\n      }\n    } else {\n      // TODO: implement\n      if (grant.affectPosition) {\n      }\n\n      if (grant.affectRotation) {\n        this.addGrantRotation(bone, parentBone.quaternion, grant.ratio)\n      }\n    }\n\n    return this\n  }\n\n  addGrantRotation(bone, q, ratio) {\n    _q.set(0, 0, 0, 1)\n    _q.slerp(q, ratio)\n    bone.quaternion.multiply(_q)\n\n    return this\n  }\n}\n\nexport { MMDAnimationHelper }\n"],"names":["Object3D","Vector3","Quaternion","AnimationMixer","CCDIKSolver","MMDPhysics"],"mappings":"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"}