Jiggle Bone Physics Spring Damper

It applies spring damper physics to bone animation of gltf object, however it does so for all bones of gltf, I tried modifying ZboingZboingPhysics.js to make it apply physics only to specified bones while other bones should continue with played animation without physics. I tried many different things with more or less success, but nothing worked good. Ofc I have difficulty implementing this because I don’t understand most of this code. Does anyone have some idea how can this be achieved?

This almost works good, with problem that at random some bones get rotated completley wrong breaking parts of the gltf model.
In example I tried to make only bone_23 and bone_26 to use physics, Code of my last attempt:

import * as THREE from 'three';
import * as SkeletonUtils from './SkeletonUtils.js';

const strengthSpring = new THREE.Vector3();
const strengthDamper = new THREE.Vector3();
const strength = new THREE.Vector3();
const strengthInternal = new THREE.Vector3();
const strengthSum = new THREE.Vector3();
const strengthGravity = new THREE.Vector3();
const dv = new THREE.Vector3();
const dp = new THREE.Vector3();

const boneVecFrom = new THREE.Vector3();
const boneVecTo = new THREE.Vector3();
const quat = new THREE.Quaternion();

function pick_randomFloatInRange(range){
  return range[0] + Math.random() * (range[1] - range[0]);
}

function update_worldPosition(bone){
  bone.getWorldPosition(bone.userData.startWorldPosition);
  if (bone.children.length === 0) return;
  bone.userData.endWorldPosition.set(0,0,0);
  bone.children.forEach(function(child){
    child.getWorldPosition(dp);
    bone.userData.endWorldPosition.add(dp);
  });
  bone.userData.endWorldPosition.divideScalar(bone.children.length);
}

function compute_strength(physicsSettings, restPosition, position, velocity, strength){
  strengthSpring.copy(position).sub(restPosition).multiplyScalar(-physicsSettings.spring);
  strengthDamper.copy(velocity).multiplyScalar(-physicsSettings.damper);
  strength.copy(strengthSpring).add(strengthDamper);
}

function update_physicsPosition(dt, strength, position, velocity, bone, rigidBone) {
  if (bone.name === 'bone_23' || bone.name === 'bone_26') {
    dv.copy(strength).multiplyScalar(2 * dt);
    velocity.add(dv);
  
    dp.copy(velocity).multiplyScalar(dt);
    position.add(dp);
  
    velocity.add(dv);
  }
}

function update_bonePhysics(dt, k, gravity, bone, rigidBone){
  if (!(bone.name === 'bone_23' || bone.name === 'bone_26')) return;

  if (bone.userData.physicsSettings === null) {
    bone.position.copy(rigidBone.userData.startWorldPosition);
    return;
  }  
  if (bone.userData.isRoot){
    return;
  }
  const physicsSettings = bone.userData.physicsSettings;
  
  compute_strength(physicsSettings, rigidBone.userData.startWorldPosition, bone.position, bone.userData.startWorldVelocity, strength);
  strengthSum.copy(strength);

  if (rigidBone.children.length > 0 && k !== 0){
    compute_strength(physicsSettings, bone.userData.endWorldPosition, bone.position, bone.userData.endWorldVelocity, strengthInternal);
    strengthInternal.multiplyScalar(k);
    strengthSum.add(strengthInternal);
  }

  if (gravity !== 0){
    strengthGravity.set(0, -gravity, 0);
    strengthSum.add(strengthGravity);
  }

  update_physicsPosition(dt, strengthSum, bone.userData.nextStartWorldPosition, bone.userData.startWorldVelocity, bone, rigidBone);

  if (rigidBone.children.length > 0) {
    if (k === 0)
      strengthSum.set(0.0, 0.0, 0.0);
    else
      strengthSum.copy(strengthInternal).multiplyScalar(-1);

    compute_strength(physicsSettings, rigidBone.userData.endWorldPosition, bone.userData.endWorldPosition, bone.userData.endWorldVelocity, strength);
    strengthSum.add(strength);

    if (k !== 0){
      bone.userData.children.forEach(function(boneChild){
        if (!boneChild?.position) return;

        compute_strength(physicsSettings, boneChild.position, bone.userData.endWorldPosition, bone.userData.endWorldVelocity, strength);
        strength.multiplyScalar(k / bone.userData.children.length);
        strengthSum.add(strength);
      });
    }

    update_physicsPosition(dt, strengthSum, bone.userData.nextEndWorldPosition, bone.userData.endWorldVelocity, bone, rigidBone);
  }
}

function apply_bonePhysics(bone, rigidBone){
  if (!(bone.name === 'bone_23' || bone.name === 'bone_26'))
    return;
  
  if (bone.userData.physicsSettings === null)
    return;

  bone.position.copy(bone.userData.nextStartWorldPosition);
  bone.userData.endWorldPosition.copy(bone.userData.nextEndWorldPosition);
}

function update_boneRotation(bone, rigidBone){
  if (!(bone.name === 'bone_23' || bone.name === 'bone_26')) {
    rigidBone.attach(bone);
    return;
  }

  if (rigidBone.children.length === 0 || bone.userData.physicsSettings === null) {
    rigidBone.getWorldQuaternion(bone.quaternion);
    return;
  }

  rigidBone.getWorldQuaternion(bone.quaternion);

  const endPosition = bone.userData.endWorldPosition;
  const endRestPosition = rigidBone.userData.endWorldPosition;
  const startPosition = bone.position;
  const startRestPosition = rigidBone.userData.startWorldPosition;

  boneVecFrom.copy(endRestPosition).sub(startRestPosition).normalize();
  boneVecTo.copy(endPosition).sub(startPosition).normalize();
  
  quat.setFromUnitVectors ( boneVecFrom, boneVecTo );
  bone.quaternion.multiply(quat);
}

const ZboingZboingPhysics = function(threeScene, threeSkinnedMesh, bonesPhysicsSettings, optionsArg){
  const options = Object.assign({
    gravity: 0,
    simuStepsCount: 3,
    isDebug: false,
    internalStrengthFactor: 0.5,
    bonesNamesShouldContain: null
  }, optionsArg || {});

  this.threeClock = new THREE.Clock();
  this.threeClock.start();

  this.skinnedMesh = threeSkinnedMesh.children.find(e => e.type === 'SkinnedMesh');
  this.rigidSkeleton = this.skinnedMesh.skeleton;
  this.parent = this.skinnedMesh.parent;

  this.rigidParent = SkeletonUtils.clone(threeSkinnedMesh);
  this.rigidSkinnedMesh = this.rigidParent.children.find(e => e.type === 'SkinnedMesh');
  this.skeleton = this.rigidSkinnedMesh.skeleton;

  this.parent.add(this.rigidSkinnedMesh);
  this.skeleton.pose();
  this.parent.remove(this.rigidSkinnedMesh);

  this.skeleton.bones = this.rigidSkeleton.bones.map(function(rigidBone){
    const isRoot = (rigidBone.parent && !rigidBone.parent.isBone);

    const bone = new THREE.Bone();
    bone.name = rigidBone.name;
    bone.userData.isRoot = isRoot;
    rigidBone.getWorldScale(bone.scale);
    threeScene.add(bone);

    return bone;
  });
  
  if (options.isDebug){
    this.rigidSkinnedMesh.material = this.rigidSkinnedMesh.material.clone();
    this.rigidSkinnedMesh.material.color.setRGB(0xff0000);
    this.parent.add(this.rigidSkinnedMesh);
    window.debugPhysics = this;
    window.THREE = THREE;
  }

  const bindMatrix = this.skinnedMesh.bindMatrix;
  this.rigidSkinnedMesh.bind(this.rigidSkeleton, bindMatrix);
  this.skinnedMesh.bind(this.skeleton, bindMatrix);

  const that = this;

  this.skeleton.bones.forEach(function(bone, boneIndex){
    let physicsSettings = bonesPhysicsSettings[bone.name] || bonesPhysicsSettings['DEFAULT'] || null;
    if (bonesPhysicsSettings[bone.name] === null
      || (options.bonesNamesShouldContain !== null && bone.name.indexOf(options.bonesNamesShouldContain) === -1)){
      physicsSettings = null;
    }

    let debugEndPositionMesh = null;
    if (options.isDebug && physicsSettings){
      debugEndPositionMesh = new THREE.Mesh(new THREE.BoxGeometry(0.5,0.1,0.5), new THREE.MeshNormalMaterial());
      threeScene.add(debugEndPositionMesh);
    }

    if (physicsSettings){
      physicsSettings = Object.assign({
        damper: (physicsSettings.damperRange) ? pick_randomFloatInRange(physicsSettings.damperRange) : physicsSettings.damper,
        spring: (physicsSettings.springRange) ? pick_randomFloatInRange(physicsSettings.springRange) : physicsSettings.spring,
      });
    }

    Object.assign(bone.userData, {
      physicsSettings: physicsSettings,
      startWorldVelocity: new THREE.Vector3(),
      endWorldVelocity: new THREE.Vector3(),
      endWorldPosition: (options.isDebug && debugEndPositionMesh) ? debugEndPositionMesh.position : new THREE.Vector3(),
      nextStartWorldPosition: new THREE.Vector3(),
      nextEndWorldPosition: new THREE.Vector3(),
      ind: boneIndex,
      parent: null,
      children: []
    });
  });

  this.rigidSkeleton.bones.forEach(function(bone, boneIndex){
    Object.assign(bone.userData, {
      startWorldPosition: new THREE.Vector3(),
      endWorldPosition: new THREE.Vector3(),
      ind: boneIndex
    });
  });

  this.skeleton.bones.forEach(function(bone, boneIndex){    
    const rigidBone = that.rigidSkeleton.bones[boneIndex];
    if (rigidBone.parent && rigidBone.parent.isBone){
      const parentInd = rigidBone.parent.userData.ind;
      bone.userData.parent = that.skeleton.bones[parentInd];
    }
    rigidBone.children.forEach(function(child){
      const childInd = child.userData.ind;
      bone.userData.children.push(that.skeleton.bones[childInd]);
    });
  });

  this.needsReset = true;

  this.create_animationMixer = ()=>{
    return new THREE.AnimationMixer(this.rigidSkinnedMesh);
  }

  this.update = function(){
    const dt = Math.min(this.threeClock.getDelta(), 0.1);
    this.rigidSkeleton.bones.forEach(update_worldPosition);

    if (this.needsReset){
      this.reset();
      this.needsReset = false;
      return;
    }

    const dtStep = dt / options.simuStepsCount;
    for(let i = 0; i<options.simuStepsCount; ++i){
      this.skeleton.bones.forEach(function(bone, boneIndex){
        const rigidBone = that.rigidSkeleton.bones[boneIndex];
        update_bonePhysics(dtStep, options.internalStrengthFactor, options.gravity, bone, rigidBone);
      });
      const bindApply = apply_bonePhysics.bind(this);
      this.skeleton.bones.forEach(function (bone, boneIndex) {
        const rigidBone = that.rigidSkeleton.bones[boneIndex];
        bindApply(bone, rigidBone);
      });
    }

    this.skeleton.bones.forEach(function(bone, boneIndex){
      if (bone.userData.isRoot || options.gravity === 0.0)
        update_boneRotation(bone, that.rigidSkeleton.bones[boneIndex]);
    });
  }

  this.reset = function(){
    this.skeleton.bones.forEach(function(bone, boneIndex){
      const rigidBone = that.rigidSkeleton.bones[boneIndex];

      bone.userData.endWorldPosition.copy(rigidBone.userData.endWorldPosition);
      bone.position.copy(rigidBone.userData.startWorldPosition);
      bone.userData.nextStartWorldPosition.copy(bone.position);
      bone.userData.nextEndWorldPosition.copy(bone.userData.endWorldPosition);
      rigidBone.getWorldQuaternion(bone.quaternion);
      bone.userData.startWorldVelocity.set(0, 0, 0);
      bone.userData.endWorldVelocity.set(0, 0, 0);
    });
  }

  this.destroy = function(){
    this.threeClock.stop();
    this.skeleton.bones.forEach(function(bone){
      threeScene.remove(bone);
    });

    this.skinnedMesh.bind(this.rigidSkeleton, new THREE.Matrix4());
    this.skeleton.dispose();
  }
}

export { ZboingZboingPhysics }

Have you got an example we can see? Thanks!