Skip to content

Commit

Permalink
Merge pull request #1555 from pixiv/improve-sort-joints
Browse files Browse the repository at this point in the history
perf: Improve init performance with a model with a massive amount of spring bones
  • Loading branch information
0b5vr authored Dec 19, 2024
2 parents c0e7a95 + 4b8fd89 commit 4f434c9
Showing 1 changed file with 21 additions and 2 deletions.
23 changes: 21 additions & 2 deletions packages/three-vrm-springbone/src/VRMSpringBoneManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class VRMSpringBoneManager {
}

private _objectSpringBonesMap = new Map<THREE.Object3D, Set<VRMSpringBoneJoint>>();
private _isSortedJointsDirty = false;

constructor() {
this._relevantChildrenUpdated = this._relevantChildrenUpdated.bind(this);
Expand All @@ -68,7 +69,8 @@ export class VRMSpringBoneManager {
this._objectSpringBonesMap.set(joint.bone, objectSet);
}
objectSet.add(joint);
this._sortJoints();

this._isSortedJointsDirty = true;
}

/**
Expand All @@ -85,7 +87,8 @@ export class VRMSpringBoneManager {

const objectSet = this._objectSpringBonesMap.get(joint.bone)!;
objectSet.delete(joint);
this._sortJoints();

this._isSortedJointsDirty = true;
}

/**
Expand All @@ -98,6 +101,8 @@ export class VRMSpringBoneManager {
}

public setInitState(): void {
this._sortJoints();

for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
Expand All @@ -107,6 +112,8 @@ export class VRMSpringBoneManager {
}

public reset(): void {
this._sortJoints();

for (let i = 0; i < this._sortedJoints.length; i++) {
const springBone = this._sortedJoints[i];
springBone.bone.updateMatrix();
Expand All @@ -116,6 +123,8 @@ export class VRMSpringBoneManager {
}

public update(delta: number): void {
this._sortJoints();

for (let i = 0; i < this._ancestors.length; i++) {
this._ancestors[i].updateWorldMatrix(i === 0, false);
}
Expand All @@ -135,12 +144,20 @@ export class VRMSpringBoneManager {

/**
* Sorts the joints ensuring they are updated in the correct order taking dependencies into account.
*
* This method updates {@link _sortedJoints} and {@link _ancestors}.
* Make sure to call this before using them.
*/
private _sortJoints() {
if (!this._isSortedJointsDirty) {
return;
}

const springBoneOrder: Array<VRMSpringBoneJoint> = [];
const springBonesTried = new Set<VRMSpringBoneJoint>();
const springBonesDone = new Set<VRMSpringBoneJoint>();
const ancestors = new Set<THREE.Object3D>();

for (const springBone of this._joints) {
this._insertJointSort(springBone, springBonesTried, springBonesDone, springBoneOrder, ancestors);
}
Expand All @@ -159,6 +176,8 @@ export class VRMSpringBoneManager {
return false;
});
}

this._isSortedJointsDirty = false;
}

private _insertJointSort(
Expand Down

0 comments on commit 4f434c9

Please sign in to comment.