Skip to content

Commit

Permalink
Merge pull request #177 from Benjythebee/fix/blendshapes-affected-by-…
Browse files Browse the repository at this point in the history
…expression

Working and looking good, merging! :)
  • Loading branch information
memelotsqui authored Oct 24, 2024
2 parents 8df3039 + aef0cb1 commit c9e5dcb
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 21 deletions.
58 changes: 49 additions & 9 deletions src/library/characterManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
import { AnimationManager } from "./animationManager"
import { ScreenshotManager } from "./screenshotManager";
import { BlinkManager } from "./blinkManager";
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
import { VRMLoaderPlugin } from "@pixiv/three-vrm";
import { getAsArray, disposeVRM, renameVRMBones, addModelData } from "./utils";
import { downloadGLB, downloadVRMWithAvatar } from "../library/download-utils"
import { saveVRMCollidersToUserData } from "./load-utils";
import { saveVRMCollidersToUserData, renameMorphTargets} from "./load-utils";
import { cullHiddenMeshes, setTextureToChildMeshes, addChildAtFirst } from "./utils";
import { LipSync } from "./lipsync";
import { LookAtManager } from "./lookatManager";
Expand Down Expand Up @@ -554,7 +554,21 @@ export class CharacterManager {
console.error("Error loading blendshape trait "+traitGroupID, blendshapeGroupId, blendshapeTraitId);
}
}

/**
* remove blendshape trait
* @param {string} traitGroupID
* @param {string} blendshapeGroupId
* @returns
*/
removeBlendShapeTrait(groupTraitID, blendShapeGroupId){
const currentTrait = this.avatar[groupTraitID];
if (currentTrait){
this._loadBlendShapeTrait(groupTraitID,blendShapeGroupId,null);
}
else{
console.warn(`No trait with name: ${ groupTraitID } was found.`)
}
}
/**
* Loads a specific trait based on group and trait IDs.
*
Expand Down Expand Up @@ -971,6 +985,7 @@ export class CharacterManager {
toggleBinaryBlendShape = (model,blendshape,enable)=>{
model.traverse((child)=>{
if(child.isMesh || child.isSkinnedMesh){

const mesh = child;
if(!mesh.morphTargetDictionary || !mesh.morphTargetInfluences) return
const blendShapeIndex = mesh.morphTargetDictionary[blendshape.id];
Expand Down Expand Up @@ -1089,6 +1104,14 @@ export class CharacterManager {
saveVRMCollidersToUserData(m);

renameVRMBones(vrm);

renameMorphTargets(m);

/**
* unregister the Blendshapes from the manifest -if any.
* This is to avoid BlendshapeTraits being affected by the vrm.ExpressionManager
*/
this._unregisterMorphTargetsFromManifest(vrm);

if (this.manifestData.isLipsyncTrait(traitID))
this.lipSync = new LipSync(vrm);
Expand All @@ -1112,12 +1135,6 @@ export class CharacterManager {

vrm.scene.traverse((child) => {
if (child.isSkinnedMesh) {
const newMorphTargets = {};
const targetNames = getAsArray(child.geometry.userData?.targetNames);
for (let i =0; i < targetNames.length;i++){
newMorphTargets[targetNames[i]] = child.morphTargetDictionary[i];
}
child.morphTargetDictionary = newMorphTargets;
for (let i =0; i < child.skeleton.bones.length;i++){
child.skeleton.bones[i].userData.vrm0RestPosition = { ... child.skeleton.bones[i].position }
}
Expand All @@ -1132,6 +1149,29 @@ export class CharacterManager {

return vrm;
}

/**
*
* @param {import("@pixiv/three-vrm").VRM} vrm
* @returns
*/
_unregisterMorphTargetsFromManifest(vrm){
const manifestBlendShapes = this.manifestData.getAllBlendShapeTraits()
const expressions = vrm.expressionManager?.expressions
if(manifestBlendShapes.length == 0) return
if(!expressions) return
const expressionToRemove = []
for(const expression of expressions){
if(manifestBlendShapes.map((b)=>b.id).includes(expression.expressionName)){
expressionToRemove.push(expression)
}
}

for(const expression of expressionToRemove){
vrm.expressionManager.unregisterExpression(expression)
}
}

_modelBaseSetup(model, item, traitID, textures, colors){

const meshTargets = [];
Expand Down
4 changes: 2 additions & 2 deletions src/library/load-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const renameMorphTargets = (gltf) => {
const json = gltf.parser.json
const meshesJson = json.meshes;
const associations = gltf.parser.associations

gltf.scene.traverse((child) => {
if(child instanceof SkinnedMesh){
if(child.morphTargetDictionary){
Expand All @@ -47,7 +47,6 @@ export const renameMorphTargets = (gltf) => {
const meshJson = meshesJson[meshIndex]

const primitives = meshJson?.primitives[primitivesIndex]

if(primitives?.extras?.targetNames){
const targetNames = primitives.extras.targetNames;
for (let i = 0; i < targetNames.length; i++){
Expand All @@ -58,6 +57,7 @@ export const renameMorphTargets = (gltf) => {
}

if(hasEditedMorphs){
// remove all morph target keys that are numbers
for(const key in child.morphTargetDictionary){
if(!isNaN(parseInt(key))){
delete child.morphTargetDictionary[key]
Expand Down
25 changes: 15 additions & 10 deletions src/pages/Appearance.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -461,21 +461,26 @@ const BlendShapeTraitView = ({selectedTrait,onBack,selectedBlendShapeTrait,setSe
const groups = characterManager.getBlendShapeGroupTraits(selectedTrait?.traitGroup.trait||"",selectedTrait?.id||"");

/**
*
*
* @param {string} traitGroup
* @param {import('../library/CharacterManifestData').BlendShapeGroup} blendShapeGroupTrait
*/
const removeBlendShapeTrait = (traitGroup,blendShapeGroupTrait)=>{
characterManager.removeBlendShapeTrait(traitGroup,blendShapeGroupTrait.trait);
const blendShapeTraitCopy = {...selectedBlendShapeTrait};
delete blendShapeTraitCopy[blendShapeGroupTrait.trait]
setSelectedBlendshapeTrait(blendShapeTraitCopy);
}
/**
* @param {import('../library/CharacterManifestData').BlendShapeTrait} newBlendShape
*/
const selectBlendShapeTrait = (newBlendShape)=>{
if(newBlendShape.id==null){
const parent = newBlendShape.parentGroup;
characterManager.loadBlendShapeTrait(selectedTrait?.traitGroup.trait||"",parent.trait||"",null);
return
}
const parent = newBlendShape.parentGroup;
characterManager.loadBlendShapeTrait(selectedTrait?.traitGroup.trait||"",parent.trait||"",newBlendShape?.id||'');
moveCamera({ targetY: parent.cameraTarget.height, distance: parent.cameraTarget.distance})
const prev = {...selectedBlendShapeTrait};
prev[parent.trait||''] = newBlendShape.id;
setSelectedBlendshapeTrait(prev);
const blendShapeTraitCopy = {...selectedBlendShapeTrait};
blendShapeTraitCopy[parent.trait||''] = newBlendShape.id;
setSelectedBlendshapeTrait(blendShapeTraitCopy);
}

return (
Expand All @@ -496,7 +501,7 @@ const BlendShapeTraitView = ({selectedTrait,onBack,selectedBlendShapeTrait,setSe
src={cancel}
active={!selectedBlendShapeTrait[group.trait]}
blendshapeID="cancel"
select={()=>selectBlendShapeTrait(new BlendShapeTrait(group,{id:null}))}
select={()=>removeBlendShapeTrait(selectedTrait.traitGroup.trait,group)}
/>
{group.collection.map((blendShapeTrait)=>{
let active = blendShapeTrait.id === selectedBlendShapeTrait[group.trait]
Expand Down

0 comments on commit c9e5dcb

Please sign in to comment.