three.js,How to complete the animation migration of two similar bones?

31 views Asked by At

Two similar bones. The animation skeleton is a pure skeleton without SkinnedMesh and skeleton. The names are different and the levels are also slightly different. How to achieve correct animation migration and playback? I have a complete bone naming mapping table. This happened when I first tried to migrate the animation. The model is distorted. I tried to use SkeletonUtils.retargetClip to correct it but the effect was not good. How can I correct my model?

           const loader = new FBXLoader();

            loader.load('/static/resources/models/pg_actorcore_embed.fbx', function (model) {
                scene.add(model);
                // 加载动画
                loader.load('/static/resources/animations/blender_animation.fbx', function (anim) {
                    console.log(anim)
                    const clip = anim.animations[0];
                    clip.tracks.forEach(track => {
                        const boneName = track.name.split('.')[0];
                        if (SMPL2ACTORCORE2[boneName]) {
                            track.name = track.name.replace(boneName, SMPL2ACTORCORE2[boneName]);
                        }
                    });
                    mixer = new THREE.AnimationMixer(model);
                    const action = mixer.clipAction(clip);
                    action.play();
               });
            });

This is the animated image loaded by the above code, and the character model is severely distorted.

The following is my attempt to use SkeletonUtils.retargetClip for animation redirection, hoping to solve the problem of model distortion.

 const loader = new FBXLoader();

            loader.load('/static/resources/models/pg_actorcore_embed.fbx', function (model) {
                scene.add(model);
                // 加载动画
                loader.load('/static/resources/animations/blender_animation.fbx', function (anim) {
                    console.log(anim)
                    const clip = anim.animations[0];
                    clip.tracks.forEach(track => {
                        const boneName = track.name.split('.')[0];
                        if (SMPL2ACTORCORE2[boneName]) {
                            track.name = track.name.replace(boneName, SMPL2ACTORCORE2[boneName]);
                        }
                    });
                    
                    let animbones = []
                    anim.traverse(function (object) {
                        if (object.isBone) {
                            const newName = SMPL2ACTORCORE2[object.name];
                            if(newName){
                                object.name = newName
                            }
                            animbones.push(object);
                        }
                    }); 
                    let animSkinnedMesh = new THREE.SkinnedMesh();
                    let animSkeleton = new THREE.Skeleton(animbones);
                    console.log(animSkeleton)
                    animSkinnedMesh.skeleton = animSkeleton; // animbones 是从动画文件中获取的骨骼数组

                    
                    let modelskeleton;
                    model.traverse(function (object) {
                        if (object.isSkinnedMesh) {
                            modelskeleton = object;
                        }
                    });
                    const modelHelper = new THREE.SkeletonHelper(model);
                    scene.add(modelHelper)

                    // 假设 model 是目标模型,已经在场景中
                    //let targetSkinnedMesh = model.getObjectByProperty('type', 'SkinnedMesh');

                    // 使用 SkeletonUtils.retargetClip 迁移动画
                    let retargetedClip = SkeletonUtils.retargetClip(modelskeleton, animSkinnedMesh, clip,{
                        preserveMatrix: true,
                        preservePosition: true,
                        preserveHipPosition: false,
                        useTargetMatrix: false,
                    });
                    console.log(retargetedClip)
                    // 创建动画操作并播放
                    mixer = new THREE.AnimationMixer(modelskeleton);
                    const action = mixer.clipAction(retargetedClip);
                    action.play();
                });
            });

This is an animated picture using retargetClip

It can solve the problem that the model is distorted by animation data, enable normal animation playback, and realize animation migration using similar bones.

0

There are 0 answers