当前位置: 首页 > 知识库问答 >
问题:

用three.js中的three.gltfloader导入和播放多个动画

贺靖
2023-03-14

从Blender中,我使用gltfExporter导出了一个动画模型(spaceship)和一个动画相机作为.glb,当我将.glb文件放入glTF查看器(gltf-viewer.donmccurdy.com)时,一切正常,所以我知道问题不在模型/Blender。

问题是当我尝试和播放我的脚本中的动画。我可以让模型完美地动画,也可以让相机完美地动画,但当我尝试做相机和模型都疯狂。我想这可能是我对动画混合器缺乏了解?也许我只需要为一个文件使用一个混合器?总之,我要做的是:

我创建了两个单独的动画混合器,一个用于宇宙飞船,一个用于摄像机:

gltfStore.mixer = new THREE.AnimationMixer(gltf.cameras[0]);
gltfStore.mixerShip = new THREE.AnimationMixer(gltf.scene.children[2]);

我使用ClipAction播放动画:

gltfStore.mixer.clipAction(gltfStore.animations[0]).play(); 
gltfStore.mixerShip.clipAction(gltfStore.animations[0]).play();

在我的循环中,我呈现动画:

gltfStore.mixer.update(clock.getDelta());
gltfStore.mixerShip.update(clock.getDelta());

它们单独工作,但合在一起就不行了。我注意到,导入到glTF动画对象中的动画数据包括glTF.animations[0]下的camera和model的动画。我的意思是gltf.animations[0]有一个tracks数组,它包含6项,每个项的位置、四元数和比例。对吗?

为方便起见,这里是主要的js文件:

var scene = new THREE.Scene();      
var mixer, animationClip;
var clock = new THREE.Clock();

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

//LIGHTS
var light = new THREE.PointLight( 0xffffff, 1, 200 );
light.position.set( 10, -10, 0 );
scene.add( light )

//OBJECT TO STORE THE GLTF ASSETS WHEN LOADED
var gltfStore = {};

var loader = new THREE.GLTFLoader();

// LOAD GLTF ASSETS
var gltfCamera = loader.load(
    'spaceship.glb',
    function ( gltf ) {

        scene.add( gltf.scene );
        gltfStore.animations =  gltf.animations;
        gltfStore.ship = gltf.scene.children[2];
        gltfStore.cam =  gltf.cameras[0];

        gltfStore.mixer = new THREE.AnimationMixer(gltf.cameras[0]);
        gltfStore.mixerShip = new THREE.AnimationMixer(gltf.scene.children[2]);

        gltfStore.mixer.clipAction(gltfStore.animations[0]).play();
        gltfStore.mixerShip.clipAction(gltfStore.animations[0]).play();
        }
);


function animate() {
    requestAnimationFrame( animate );
    if(gltfStore.mixer && gltfStore.cam){
        //gltfStore.mixer.update(clock.getDelta());
        gltfStore.mixerShip.update(clock.getDelta());
          renderer.render(scene, gltfStore.cam);
    }      
};

animate();

谢谢你的任何帮助/点子!

共有1个答案

尉迟雅昶
2023-03-14

所以,在进一步研究了一些例子之后,我找到了答案。

简单地说,不需要单独提取和尝试动画模型和相机,所需要的只是从场景本身创建一个animatiomixer:

gltfStore.mixer = new THREE.AnimationMixer(gltf.scene);
gltfStore.mixer.clipAction(gltfStore.animations[0]).play();

上面完美的动画化了所有的元素。

 类似资料:
  • 问题内容: 如何使两个CSS动画 以不同的速度 播放? 图像应同时旋转和增长。 旋转将每2秒循环一次。 生长将每4秒循环一次。 示例代码: 仅播放一个动画(声明了最后一个动画)。 问题答案: TL; DR 使用逗号,可以指定多个动画,每个动画都有自己的属性。 例: 原始答案 这里有两个问题: #1 第二行替换第一行。因此,没有任何效果。 #2 两个关键帧都应用于相同的属性 作为一种替代方法,您可以

  • 我想播放一首特定的歌曲取决于发送的参数。 在我的项目中,我有不同的播放列表,所以我想发送参数(它是一个数字,对应一个播放列表),然后只听那个播放列表中的歌曲。有什么想法可以这样做吗?提前道谢!

  • 如何在鼠标进入时停止滑动自动播放和在鼠标离开时开始自动播放?我尝试了和函数,但对我无效。 谢谢。这是代码。我面临控制台错误 未捕获的TypeError:swiper.StartautoPlay不是函数

  • 我写了一个应用程序来播放mp3文件,我有控制和一切滚动,只是一个问题,每个mp3文件是单独播放,我必须触发一个新的文件播放。 我想知道我如何(按语法)判断玩家是否已经完成了一个文件的播放,这样我就可以继续下一个文件了? 这是线程代码

  • 通过Three.js模型数据导入导出过程的学习,可以让你对Threejs解析加载外部模型的过程更为了解。 Threejs导出模型信息 你可以通过下面代码导出模型的各类信息,然后在浏览器控制台打印出来模型数据,然后复制浏览器控制台模型数据粘贴到json文件中,最后可以尝试加载解析这些Threejs导出的json文件。之所以这么做,是为了让你理解其它三维软件,比如3dmax、blender软件导出的三

  • 对文件播放动作 播放动作可以在活动文档中执行动作记录的命令。(一些动作需要先行选择才可播放;而另一些动作则可对整个文件执行。) 可以排除动作中的特定命令或只播放单个命令。如果动作包括模态控制,可以在对话框中指定值或在动作暂停时使用工具。 注意:在按钮模式下,点按一个按钮将执行整个动作,但不执行先前已排除的命令。 如果需要,可以选择要对其播放动作的对象或打开文件。 执行以下操作之一: 若要播放整个动