Skip to content

Commit

Permalink
Merge pull request #1553 from pixiv/improve-combinemorphs
Browse files Browse the repository at this point in the history
Improve performance of combineMorphs
  • Loading branch information
0b5vr authored Dec 18, 2024
2 parents 81b6991 + 2dfda5c commit c0e7a95
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions packages/three-vrm/src/VRMUtils/combineMorphs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ function collectMeshes(scene: THREE.Group): Set<THREE.Mesh> {

function combineMorph(
positionAttributes: (THREE.BufferAttribute | THREE.InterleavedBufferAttribute)[],
binds: Iterable<VRMExpressionMorphTargetBind>,
binds: Set<VRMExpressionMorphTargetBind>,
morphTargetsRelative: boolean,
): THREE.BufferAttribute {
): THREE.BufferAttribute | THREE.InterleavedBufferAttribute {
// if there is only one morph target and the weight is 1.0, we can use the original as-is
if (binds.size === 1) {
const bind = binds.values().next().value!;
if (bind.weight === 1.0) {
return positionAttributes[bind.index];
}
}

const newArray = new Float32Array(positionAttributes[0].count * 3);
let weightSum = 0.0;

Expand Down Expand Up @@ -108,14 +116,18 @@ export function combineMorphs(vrm: VRMCore): void {
continue;
}

// prevent cloning morph attributes
const originalMorphAttributes = mesh.geometry.morphAttributes;
mesh.geometry.morphAttributes = {};

const geometry = mesh.geometry.clone();
mesh.geometry = geometry;
const morphTargetsRelative = geometry.morphTargetsRelative;

const hasPMorph = geometry.morphAttributes.position != null;
const hasNMorph = geometry.morphAttributes.normal != null;
const hasPMorph = originalMorphAttributes.position != null;
const hasNMorph = originalMorphAttributes.normal != null;

const morphAttributes: typeof geometry.morphAttributes = {};
const morphAttributes: typeof originalMorphAttributes = {};
const morphTargetDictionary: typeof mesh.morphTargetDictionary = {};
const morphTargetInfluences: typeof mesh.morphTargetInfluences = [];

Expand All @@ -130,10 +142,10 @@ export function combineMorphs(vrm: VRMCore): void {
let i = 0;
for (const [name, bindSet] of nameBindSetMap) {
if (hasPMorph) {
morphAttributes.position[i] = combineMorph(geometry.morphAttributes.position, bindSet, morphTargetsRelative);
morphAttributes.position[i] = combineMorph(originalMorphAttributes.position, bindSet, morphTargetsRelative);
}
if (hasNMorph) {
morphAttributes.normal[i] = combineMorph(geometry.morphAttributes.normal, bindSet, morphTargetsRelative);
morphAttributes.normal[i] = combineMorph(originalMorphAttributes.normal, bindSet, morphTargetsRelative);
}

expressionMap?.[name].addBind(
Expand Down

0 comments on commit c0e7a95

Please sign in to comment.