How to make the animation of multi-gltf model?

I am working on a DOTA2 website and try to add heros' 3D model in the web. I extracted a hero's model, but it includes many gltf files and textures. One of files is the hero's body and the rest are asscesories, such as hat, weapon, clouth.

I try to play the animation of the model, but only the body part gltf file includes animations, the rest part doesn't have any animation. Thus, when I play the animation, only the hero's body is acting, the rest part is fixed.

Here is my code:

import * as THREE from 'three'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { useRef, useEffect } from 'react'
import './App.css'
import { AmbientLight } from 'three'; 
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

const modelList = [
  'warlock.gltf',
  'warlock_bag.gltf',
  'warlock_bracers.gltf',
  'warlock_cape.gltf',
  'warlock_lantern.gltf',
  'warlock_robe.gltf',
  'warlock_shoulder.gltf',
  'warlock_staff.gltf'];

function App() {
  const mount = useRef(null);
  
  const mixer = useRef(null);


  useEffect(() => {
    const loader = new GLTFLoader();
    const scene = new THREE.Scene();
    const clock = new THREE.Clock();
    const camera = new THREE.PerspectiveCamera(
      45,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );  

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    mount.current.appendChild(renderer.domElement);

    const ambientLight = new AmbientLight(0xffffff, 1);
    scene.add(ambientLight);
    
    const grayColor = new THREE.Color(0.5, 0.5, 0.5);
    scene.background = grayColor; 

    camera.position.z = 5;
    camera.position.y = 5;
    camera.position.x = 5;
    camera.lookAt(0, 0, 0);

    const axesHelper = new THREE.AxesHelper(5);
    scene.add(axesHelper);

    const controls = new OrbitControls(camera, renderer.domElement); 
    controls.enableDamping = true; 
    controls.dampingFactor = 0.05;

    var character = null;

    loader.load(`model/warlock.gltf`, (gltf) => { 
        character = gltf.scene;
        scene.add(character);
        mixer.current = new THREE.AnimationMixer(gltf.scene);  

        const animation = gltf.animations[1];  
        if (animation) {  
          const action = mixer.current.clipAction(animation); 
          action.play();
        } 

        LoadOtherPart();

        console.log(gltf);
        animate();
    });

    function LoadOtherPart() {
      modelList.forEach((model) => {
        loader.load(`model/${model}`, (gltf) => {
          if(model !== 'warlock.gltf'){
            character.add(gltf.scene);
          }
        });
      })
    }
  
    function animate() {  
      requestAnimationFrame(animate); 

      if(mixer.current){
        const delta = clock.getDelta();
        mixer.current.update(delta);  
      }
      
      renderer.render(scene, camera);  
      controls.update(); 
    }

    return () => {  
      mount.current.removeChild(renderer.domElement);  
    };
  }, []);

  return (
    <div ref={mount}>
    </div>
  )
}

export default App;

I thought the rest part should be the children of the body part, and the gltf file may include the relative position data. I try it, but it still doesn't work. Is it possible only use the threejs to achieve that accessories animate with the body properly? How can I solve the problem?

Thank you so much!

Upvotes: 0

Views: 41

Answers (0)

Related Questions