首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Three.js如何添加多个Mixamo动画没有皮肤到一个FBX模型?

Three.js如何添加多个Mixamo动画没有皮肤到一个FBX模型?
EN

Stack Overflow用户
提问于 2022-04-09 17:39:03
回答 1查看 1.3K关注 0票数 1

我试图创建一个游戏,其中有一个动画角色,有多个动画来自Mixamo。我希望动画能够根据用户在游戏中所做的事情而改变,比如WalkingRunningIdle。下面是我如何加载FBX模型(没有动画):

代码语言:javascript
复制
loader.load('Assets/Animations/Main.fbx', function(object){
    object.traverse(function (child){
        if (child.isMesh) {
           child.castShadow = true;
           child.receiveShadow = true;
           child.frustumCulled = false;
        }
   });

   object.rotation.x = Math.PI / 2
   object.position.x = 11;
   scene.add(object);
});

我也有以下文件,它们是没有皮肤的动画。

代码语言:javascript
复制
Idle.fbx
Walking.fbx
Running.fbx

我的目标是尝试制作类似的东西。这两个链接的唯一问题是,在第一个链接中,它们使用的是一个带有多个动画的模型(我有一个没有皮肤的普通模型,有3个动画),在第二个链接中,代码是用TypeScript编写的(我更喜欢JavaScript)。

我是一个新手三维造型,所以我不知道如何把所有的动画没有皮肤的主要fbx模型。如何在混合器中将动画组合成一个模型,或者有什么方法可以在three.js?中完成?

我很感谢您的帮助,谢谢!

编辑:

据GuyNachshon说,这是我应该怎么处理的吗?

因此,首先,我加载没有动画的模型(yourMesh),并创建一个AnimationMixer

代码语言:javascript
复制
var mixer;

loader.load('Assets/Animations/Main.fbx', function(object){
    object.traverse(function (child){
        if (child.isMesh) {
           child.castShadow = true;
           child.receiveShadow = true;
           child.frustumCulled = false;
        }
   });

   mixer = new THREE.AnimationMixer(object);
   object.rotation.x = Math.PI / 2
   object.position.x = 11;
   scene.add(object);
});

然后,我必须加载没有皮肤的3个动画文件,并将它们添加到animationsArray中。(不确定是否正确加载动画.):

代码语言:javascript
复制
loader.load('Assets/Animations/Idle.fbx', function(object){
    object.traverse(function (child){
        if (child.isMesh) {
           child.castShadow = true;
           child.receiveShadow = true;
           child.frustumCulled = false;
        }
   });

   object.rotation.x = Math.PI / 2
   object.position.x = 11;

   animationsArray.push(object);
   scene.add(object);
});

loader.load('Assets/Animations/Walking.fbx', function(object){
    object.traverse(function (child){
        if (child.isMesh) {
           child.castShadow = true;
           child.receiveShadow = true;
           child.frustumCulled = false;
        }
   });

   object.rotation.x = Math.PI / 2
   object.position.x = 11;

   animationsArray.push(object);
   scene.add(object);
});

loader.load('Assets/Animations/Running.fbx', function(object){
    object.traverse(function (child){
        if (child.isMesh) {
           child.castShadow = true;
           child.receiveShadow = true;
           child.frustumCulled = false;
        }
   });

   object.rotation.x = Math.PI / 2
   object.position.x = 11;

   animationsArray.push(object);
   scene.add(object);
});

在全部加载完之后,我创建了actions

代码语言:javascript
复制
let actions = mixer.clipAction(animationsArray).play();

但是,在你说了之后:

代码语言:javascript
复制
actions.play();

那句台词要放什么?它会在animationsArray中播放第一个动画吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-14 18:04:10

您需要创建一个AnimationMixer

因此,假设您已经创建了一个场景,添加了一个网格等等,现在您可以在一个动画混合器中使用它。

代码语言:javascript
复制
let mixer = new THREE.AnimationMixer(yourMesh);

然后使用clipActions添加动画,

代码语言:javascript
复制
let actions = mixer.clipAction(animationsArray).play();

现在玩吧

代码语言:javascript
复制
actions.play();

但是要真正知道如何使用它,您应该阅读文档(附在上面:)

编辑-响应您的编辑

为了控制动画的播放,您可以做几件事情,下面是来自文档 的一个例子

代码语言:javascript
复制
const mixer = new THREE.AnimationMixer( mesh );
const clips = mesh.animations;

// Update the mixer on each frame
function update () {
    mixer.update( deltaSeconds );
}

// Play a specific animation
const clip = THREE.AnimationClip.findByName( clips, 'dance' );
const action = mixer.clipAction( clip );
action.play();

// Play all animations
clips.forEach( function ( clip ) {
    mixer.clipAction( clip ).play();
} );

现在,如果您在构造代码时遇到了问题,下面是一个关于如何将动画附加到fbx并控制它们的一般示例:

代码语言:javascript
复制
let mixer = THREE.AnimationMixer
let modelReady = false
const animationActions = THREE.AnimationAction
let activeAction = THREE.AnimationAction
let lastAction = THREE.AnimationAction
const fbxLoader = new FBXLoader()

在我们启动所需的一切之后,让我们加载所有内容:

代码语言:javascript
复制
fbxLoader.load(
    (object) => {
        'path/to/your/model.fbx',
        object.scale.set(0.01, 0.01, 0.01)
        mixer = new THREE.AnimationMixer(object)

        const animationAction = mixer.clipAction(animations[0])
        animationActions.push(animationAction)
        animationsFolder.add(animations, 'default')
        activeAction = animationActions[0]  // sets current animation

        scene.add(object)  // adds animated object to your scene

        //add an animation from another file
        fbxLoader.load(
            'path/to/animation.fbx',
            (object) => {
                console.log('loaded animation')

                const animationAction = mixer.clipAction(.animations[0])
                animationActions.push(animationAction)
                animationsFolder.add(animations, 'animationName')

                //add an animation from another file
                fbxLoader.load(
                    'path/to/other/animation.fbx',
                    (object) => {
                        console.log('loaded second animation')
                        const animationAction = mixer.clipAction(animations[0])
                        animationActions.push(animationAction)
                        animationsFolder.add(animations, 'animationName')

                        //add an animation from another file
                        fbxLoader.load(
                            'path/to/animation.fbx',
                            (object) => {
                                console.log('loaded third animation');
                                const animationAction = mixer.clipAction(animations[0])
                                animationActions.push(animationAction)
                                animationsFolder.add(animations, 'animationName')

                                modelReady = true
                            },
                            (xhr) => {
                                console.log(
                                    (xhr.loaded / xhr.total) * 100 + '% loaded'
                                )
                            },
                            (error) => {
                                console.log(error)
                            }
                        )
                    },
                    (xhr) => {
                        console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
                    },
                    (error) => {
                        console.log(error)
                    }
                )
            },
            (xhr) => {
                console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
            },
            (error) => {
                console.log(error)
            }
        )
    },
    (xhr) => {
        console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
    },
    (error) => {
        console.log(error)
    }
)

现在我们应该确定我们的动画和动作是什么:

代码语言:javascript
复制
const animations = {
   function default() {
        setAction(animationActions[0])
    },
    function firstAnimation() {
        setAction(animationActions[1])
    },
   function sceondAnimation() {
        setAction(animationActions[2])
    },
   function thirdAnimation() {
        setAction(animationActions[3])
    }
}

const setAction = {
    if (toAction != activeAction) {
        lastAction = activeAction
        activeAction = toAction
        //lastAction.stop()
        lastAction.fadeOut(1)
        activeAction.reset()
        activeAction.fadeIn(1)
        activeAction.play()
    }
}

让我们动起来!

代码语言:javascript
复制
const clock = new THREE.Clock()

function animate() {
    requestAnimationFrame(animate)

    controls.update()

    if (modelReady) {mixer.update(clock.getDelta())}

    render()

}

function render() {
    renderer.render(scene, camera)
}

animate()

把所有东西放在一起:

代码语言:javascript
复制
import * as THREE from 'three'

import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'


let mixer = THREE.AnimationMixer
    let modelReady = false
    const animationActions = THREE.AnimationAction
    let activeAction = THREE.AnimationAction
    let lastAction = THREE.AnimationAction
    const fbxLoader = new FBXLoader()

fbxLoader.load(
        (object) => {
            'path/to/your/model.fbx',
            object.scale.set(0.01, 0.01, 0.01)
            mixer = new THREE.AnimationMixer(object)
    
            const animationAction = mixer.clipAction(animations[0])
            animationActions.push(animationAction)
            animationsFolder.add(animations, 'default')
            activeAction = animationActions[0]  // sets current animation
    
            scene.add(object)  // adds animated object to your scene
    
            //add an animation from another file
            fbxLoader.load(
                'path/to/animation.fbx',
                (object) => {
                    console.log('loaded animation')
    
                    const animationAction = mixer.clipAction(.animations[0])
                    animationActions.push(animationAction)
                    animationsFolder.add(animations, 'animationName')
    
                    //add an animation from another file
                    fbxLoader.load(
                        'path/to/other/animation.fbx',
                        (object) => {
                            console.log('loaded second animation')
                            const animationAction = mixer.clipAction(animations[0])
                            animationActions.push(animationAction)
                            animationsFolder.add(animations, 'animationName')
    
                            //add an animation from another file
                            fbxLoader.load(
                                'path/to/animation.fbx',
                                (object) => {
                                    console.log('loaded third animation');
                                    const animationAction = mixer.clipAction(animations[0])
                                    animationActions.push(animationAction)
                                    animationsFolder.add(animations, 'animationName')
    
                                    modelReady = true
                                },
                                (xhr) => {
                                    console.log(
                                        (xhr.loaded / xhr.total) * 100 + '% loaded'
                                    )
                                },
                                (error) => {
                                    console.log(error)
                                }
                            )
                        },
                        (xhr) => {
                            console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
                        },
                        (error) => {
                            console.log(error)
                        }
                    )
                },
                (xhr) => {
                    console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
                },
                (error) => {
                    console.log(error)
                }
            )
        },
        (xhr) => {
            console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
        },
        (error) => {
            console.log(error)
        }
    )

const animations = {
       function default() {
            setAction(animationActions[0])
        },
        function firstAnimation() {
            setAction(animationActions[1])
        },
       function sceondAnimation() {
            setAction(animationActions[2])
        },
       function thirdAnimation() {
            setAction(animationActions[3])
        }
    }
    
    const setAction = {
        if (toAction != activeAction) {
            lastAction = activeAction
            activeAction = toAction
            //lastAction.stop()
            lastAction.fadeOut(1)
            activeAction.reset()
            activeAction.fadeIn(1)
            activeAction.play()
        }
    }

const clock = new THREE.Clock()
    
    function animate() {
        requestAnimationFrame(animate)
    
        controls.update()
    
        if (modelReady) {mixer.update(clock.getDelta())}
    
        render()
    
    }
    
    function render() {
        renderer.render(scene, camera)
    }
    
    animate()

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71810443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档