Issues animating multiple .glb models

I am having issues getting my second model (alex_circle.glb) to animate. The first model (roomChanged.glb) animates just fine, and I notice that the circle model animates on load, but then stops and the roommodel takes over the animation. I am having issues finding solutions online to my problem and wanted to see if anyone here has a solution.

Any help is greatly appreciated.

Link to code and models: new.zip - Google Drive

import "./style.css";
import * as THREE from "three";
import oc from "three-orbit-controls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

let camera, scene, renderer, mixer;
var clock = new THREE.Clock();
init();
animate();
function init() {
  //camera
  camera = new THREE.PerspectiveCamera(
    5,
    window.innerWidth / window.innerHeight,
    1,
    10000
  );
  camera.position.set(80, 55, 80);

  //scene
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x87ceeb);

  //clickbox for laptop

  var geometry1 = new THREE.SphereGeometry(0.22);
  var material1 = new THREE.MeshLambertMaterial({
    transparent: true,
    opacity: 0.5,
  });
  var sphere1 = new THREE.Mesh(geometry1, material1);
  sphere1.position.set(-0.6, 0.8, -1.25);

  //click box for arm

  var geometry2 = new THREE.SphereGeometry(0.25);
  var material2 = new THREE.MeshLambertMaterial({
    transparent: true,
    opacity: 0.5,
  });
  var sphere2 = new THREE.Mesh(geometry2, material2);
  sphere2.position.set(-1.05, 0.85, -1.25);

  //loader

  let loader = new GLTFLoader();
  loader.load("roomchanged.glb", function (gltf) {
    const model = gltf.scene;
    mixer = new THREE.AnimationMixer(model);
    console.log(gltf.animations);
    mixer.clipAction(gltf.animations[0]).play();
    scene.add(model, sphere1, sphere2);
  });

  loader.load("alex_circle.glb", function (gltf) {
    const model2 = gltf.scene;
    mixer = new THREE.AnimationMixer(model2);
    console.log(gltf.animations);
    mixer.clipAction(gltf.animations[0]).play();
    scene.add(model2);
  });

  //lights
  const hlight = new THREE.AmbientLight(0x404040, 1); // soft white light
  scene.add(hlight);
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(0, 1, 0);

  scene.add(directionalLight);
  const light = new THREE.PointLight(0xc4c4c4, 1);
  light.position.set(0, 300, 500);
  scene.add(light);
  //empty right wall to bookshelf wall
  const light2 = new THREE.PointLight(0xc4c4c4, 1);
  light2.position.set(500, 100, 0);
  scene.add(light2);
  //empty left wall to desk wall
  const light4 = new THREE.PointLight(0xc4c4c4, 2);
  light4.position.set(-500, 300, 500);
  scene.add(light4);

  //renderer
  renderer = new THREE.WebGLRenderer({ antialias: true });
  const OrbitControls = oc(THREE);
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  //dynamic resize
  window.addEventListener("resize", onWindowResize, false);

  //orbit controls
  const controls = new OrbitControls(camera, renderer.domElement);

  //zoom controls
  controls.maxDistance = 100;
  controls.minDistance = 70;

  //horiztonal limits
  controls.minAzimuthAngle = 0;
  controls.maxAzimuthAngle = 1.56;

  //veritcal limits
  controls.minPolarAngle = Math.PI / 8;
  controls.maxPolarAngle = Math.PI / 2;
  controls.enablePan = false;
  controls.update();

  var rightmousemove;

  document.addEventListener("mousemove", function (event) {
    if (rightmousemove === true) {
      // Use stopImmediatePropagation to stop the other handeller from trigerring
      event.stopImmediatePropagation();
    }
  });

  render();
}

function onWindowResize() {
  var width = window.innerWidth;
  var height = window.innerHeight;
  renderer.setSize(width, height);
  camera.aspect = width / height;
  camera.updateProjectionMatrix();
}

function animate() {
  requestAnimationFrame(animate);
  if (mixer) mixer.update(clock.getDelta());
  // required if controls.enableDamping or controls.autoRotate are set to true
  render();
}

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

please someone

you are re initialising the same mixer the second loader.

Even initializing the second mixer as mixer2 doesn’t seem to animate them.

The model still renders, but the animation still won’t play.

i’m using two animation mixers at the same time in this example and it is working fine.
Sharing Animation Clips - Three.js Tutorials (sbcode.net)

In your description you say one worked, then it stopped and the other took over. That’s because you re-instantiated your mixer variable with a complete new animation mixer.

try and make a working example using codesandbox or similar that demonstrates online.

my work around right now is I just imported the circle models into the roommodel, re-exported as .gltf and added a call to the second animation in the array:


  loader.load("room3.gltf", function (gltf) {
    const model = gltf.scene;
    mixer = new THREE.AnimationMixer(model);
    console.log(gltf.animations);
    mixer.clipAction(gltf.animations[0]).play();
    mixer.clipAction(gltf.animations[1]).play();
    scene.add(model, sphere1, sphere2);
  });

now both animations are playing but the issue remains is that I’m not sure if I can add onclick events to those circle icons since they are part of the roommodel now. That is why I ended up createing those sphere models to act as click boxes for on click events

The structure of my code is not much different than what you were originally trying.
Also check how you were updating the two mixers in your animation loop.
See how I do it my example. The JavaScript source code is viewable from the working example if you press the <> button bottom right.

Here is a codesanbox. Couldn’t figure out how to get the GLTFLoader to work in it though.

I couldn’t get your codesandbox to work either
so I reworked your original from the zip link you added.
Using below code I see a yellow arm moving around and an exclamation bobbing up and down at the same time

import "./style.css";

import * as THREE from "three";

import oc from "three-orbit-controls";

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";

let camera, scene, renderer, mixerA, mixerB, delta;

var clock = new THREE.Clock();

init();

animate();

function init() {

  //camera

  camera = new THREE.PerspectiveCamera(

    5,

    window.innerWidth / window.innerHeight,

    1,

    10000

  );

  camera.position.set(80, 55, 80);

  //scene

  scene = new THREE.Scene();

  scene.background = new THREE.Color(0x87ceeb);

  //clickbox for laptop

  var geometry1 = new THREE.SphereGeometry(0.22);

  var material1 = new THREE.MeshLambertMaterial({

    transparent: true,

    opacity: 0.5,

  });

  var sphere1 = new THREE.Mesh(geometry1, material1);

  sphere1.position.set(-0.6, 0.8, -1.25);

  //click box for arm

  var geometry2 = new THREE.SphereGeometry(0.25);

  var material2 = new THREE.MeshLambertMaterial({

    transparent: true,

    opacity: 0.5,

  });

  var sphere2 = new THREE.Mesh(geometry2, material2);

  sphere2.position.set(-1.05, 0.85, -1.25);

  //loader

  let loader = new GLTFLoader();

  loader.load("roomchanged.glb", function (gltf) {

    const model = gltf.scene;

    mixerA = new THREE.AnimationMixer(model);

    console.log(gltf.animations);

    mixerA.clipAction(gltf.animations[0]).play();

    scene.add(model, sphere1, sphere2);

  });

  loader.load("alex_circle.glb", function (gltf) {

    const model2 = gltf.scene;

    mixerB = new THREE.AnimationMixer(model2);

    console.log(gltf.animations);

    mixerB.clipAction(gltf.animations[0]).play();

    scene.add(model2);

  });

  //lights

  const hlight = new THREE.AmbientLight(0x404040, 1); // soft white light

  scene.add(hlight);

  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);

  directionalLight.position.set(0, 1, 0);

  scene.add(directionalLight);

  const light = new THREE.PointLight(0xc4c4c4, 1);

  light.position.set(0, 300, 500);

  scene.add(light);

  //empty right wall to bookshelf wall

  const light2 = new THREE.PointLight(0xc4c4c4, 1);

  light2.position.set(500, 100, 0);

  scene.add(light2);

  //empty left wall to desk wall

  const light4 = new THREE.PointLight(0xc4c4c4, 2);

  light4.position.set(-500, 300, 500);

  scene.add(light4);

  //renderer

  renderer = new THREE.WebGLRenderer({ antialias: true });

  const OrbitControls = oc(THREE);

  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  //dynamic resize

  window.addEventListener("resize", onWindowResize, false);

  //orbit controls

  const controls = new OrbitControls(camera, renderer.domElement);

  //zoom controls

  controls.maxDistance = 100;

  controls.minDistance = 70;

  //horiztonal limits

  controls.minAzimuthAngle = 0;

  controls.maxAzimuthAngle = 1.56;

  //veritcal limits

  controls.minPolarAngle = Math.PI / 8;

  controls.maxPolarAngle = Math.PI / 2;

  controls.enablePan = false;

  controls.update();

  var rightmousemove;

  document.addEventListener("mousemove", function (event) {

    if (rightmousemove === true) {

      // Use stopImmediatePropagation to stop the other handeller from trigerring

      event.stopImmediatePropagation();

    }

  });

  render();

}

function onWindowResize() {

  var width = window.innerWidth;

  var height = window.innerHeight;

  renderer.setSize(width, height);

  camera.aspect = width / height;

  camera.updateProjectionMatrix();

}

function animate() {

  requestAnimationFrame(animate);

  delta = clock.getDelta()

  if (mixerA)

    mixerA.update(delta);

  if (mixerB)

    mixerB.update(delta);

  // required if controls.enableDamping or controls.autoRotate are set to true

  render();

}

function render() {

  renderer.render(scene, camera);

}

I see how you implemented both mixers in the animation function but I’m not really grasping what is occurring there?

Can you explain what I was doing wrong versus what your changes are doing so I can understand this better