-1

I would like to ask how to load animated 3D model on webpage using THREE.js? Currently I had managed to load my own 3D model (it named 'aaa.gltf') using THREE.js on webpage with auto rotate and able to click to move around the model using orbitcontrol.js. However, my model is static. Then, I tried to load my another 3D model which is animated 3D model, it named "bbb.glb", but it turns out couldn't be displayed at all.

Here is html file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="./style.css" />
    <title>Document</title>
  </head>
  <body>
    <div class="scene"></div>
    <script src="./three.min.js"></script>
    <script src="./GLTFLoader.js"></script>
    <script src="./OrbitControls.js"></script>
    <script src="./app.js"></script>
  </body>
</html>

Here is js file:

//Variables for setup

let container;
let camera;
let renderer;
let scene;
let house;
let mixer;

function init() {
  container = document.querySelector(".scene");

  //Create scene
  scene = new THREE.Scene();

  const fov = 35;
  const aspect = container.clientWidth / container.clientHeight;
  const near = 0.1;
  const far = 1000;

  //Camera setup
  camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(0, 0, 100);

  const ambient = new THREE.AmbientLight(0x404040, 2);
  scene.add(ambient);

  const light = new THREE.DirectionalLight(0xffffff, 2);
  light.position.set(50, 50, 100);
  scene.add(light);
  
  
  // controls.addEventListener('change', renderer);
        
        
  //Renderer
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  renderer.setSize(container.clientWidth, container.clientHeight);
  renderer.setPixelRatio(window.devicePixelRatio);
  
  controls = new THREE.OrbitControls(camera, renderer.domElement);

  container.appendChild(renderer.domElement);

  const clock = new THREE.Clock();

  //Load Model
  let loader = new THREE.GLTFLoader();
  loader.load("./house/bbb.glb", function(gltf) {
    scene.add(gltf.scene);
    house = gltf.scene.children[0];

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

    animate();
  });
}

function animate() {
  requestAnimationFrame(animate);

  const delta = clock.getDelta();
  mixer.update( delta );

  house.rotation.z += 0.005;
  renderer.render(scene, camera);
}

init();

function onWindowResize() {
  camera.aspect = container.clientWidth / container.clientHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(container.clientWidth, container.clientHeight);
}

window.addEventListener("resize", onWindowResize);

Here is css file:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: sans-serif;
  overflow: hidden;
  background: url("https://wallpaperaccess.com/full/1155041.jpg");
}

.scene,
canvas {
  position: absolute;
  width: 100%;
  height: 100%;
}

I only change the source of 3D model from 'aaa.gltf' into 'bbb.glb' at the line 46 of js file:

from this

  loader.load("./house/aaa.gltf", function(gltf) {

into this

  loader.load("./house/bbb.glb", function(gltf) {

Here is the attachments of 'aaa.gltf': https://drive.google.com/file/d/1RCO8iSvYwTZdcTC55EVzJ0rBLl6aZy9L/view?usp=sharing

Here is the attachments of 'bbb.glb': https://drive.google.com/file/d/1fzk7AZl2VHwTvZm0Gl0m-oyaIZUmHyeB/view?usp=sharing

Anyone knows how to solve it? Thanks in advance!

Edison Toh
  • 87
  • 1
  • 11

1 Answers1

3

Your code is very incomplete to animate the 3D model, basically you are only loading it but not playing the embedded animation. For that, you need to create an AnimationMixer, select the clip action to play (the animation) and then update the animation.

Apart from that, the model is encoded with DRACO so I added it too. Some more changes like THREE.sRGBEncoding to get real colors of the model, and reduced the illumination as it was too intense...

EDIT: FULL PAGE CODE

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: sans-serif;
            overflow: hidden;
        }

        .scene,
        canvas {
            position: absolute;
            width: 100%;
            height: 100%;
        }
    </style>

</head>
<body>
    <div class="scene"></div>
    <script src="https://threejs.org/build/three.min.js"></script>
    <script src="https://threejs.org/examples/js/loaders/GLTFLoader.js"></script>
    <script src="https://threejs.org/examples/js/loaders/DRACOLoader.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

    <script>

        //Variables for setup

        let container;
        let camera;
        let renderer;
        let scene;
        let house;
        let mixer;
        const clock = new THREE.Clock();

        function init() {
            container = document.querySelector(".scene");

            //Create scene
            scene = new THREE.Scene();

            const fov = 35;
            const aspect = container.clientWidth / container.clientHeight;
            const near = 1;
            const far = 10000;

            //Camera setup
            camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
            camera.position.set(0, 0, 1000);

            const ambient = new THREE.AmbientLight(0x404040, 1);
            scene.add(ambient);

            const light = new THREE.DirectionalLight(0xffffff, 1);
            light.position.set(50, 50, 100);
            scene.add(light);

            //Renderer
            renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
            renderer.setSize(container.clientWidth, container.clientHeight);
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.outputEncoding = THREE.sRGBEncoding;
            container.appendChild(renderer.domElement);

            const controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.target.set(0, 0.5, 0);
            controls.update();
            controls.enablePan = false;
            controls.enableDamping = true;

            const dracoLoader = new THREE.DRACOLoader();
            dracoLoader.setDecoderPath('https://threejs.org/examples/js/libs/draco/gltf/');

            //Load Model
            let loader = new THREE.GLTFLoader();
            loader.setDRACOLoader(dracoLoader);
            loader.load("./house/bbb.glb", function (gltf) {
                scene.add(gltf.scene);
                house = gltf.scene.children[0];

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

                animate();
            });
        }

        function animate() {
            requestAnimationFrame(animate);

            const delta = clock.getDelta();
            mixer.update(delta);

            house.rotation.z += 0.005;
            renderer.render(scene, camera);
        }

        init();

        function onWindowResize() {
            camera.aspect = container.clientWidth / container.clientHeight;
            camera.updateProjectionMatrix();

            renderer.setSize(container.clientWidth, container.clientHeight);
        }

        window.addEventListener("resize", onWindowResize);

    </script>
</body>
</html>

If you do so, you'll see the animation of different objects, tram, cat and more... enter image description here

jscastro
  • 3,422
  • 1
  • 9
  • 27
  • Hi, I am actually want to add 'bbb.glb' instead adding 'aaa.gltf', should i change ```loader.load("./house/aaa.gltf", function(gltf) {``` into ```loader.load("./house/bbb.glb", function(gltf) {```? – Edison Toh Apr 29 '21 at 10:50
  • where should i put these lines ```let mixer;``` ```const clock = new THREE.Clock();```? – Edison Toh Apr 29 '21 at 11:25
  • You have to add it at the same level you added the other script variables such as `let renderer`. Yes, you have to load bbb.glb is the file I used. Modified in my answer – jscastro Apr 29 '21 at 14:46
  • I had edited the code according to your guidelines but still no luck.. Could you please help me to take a look on the modified js file? I don't know which part i did mistake but still can't display the animated model, really appreciate if you can take a look on it, thanks! – Edison Toh Apr 29 '21 at 16:17
  • Please, next time provide a Minimum Reproducible Example. Updated my answer with a full functional code. You're welcome! – jscastro Apr 29 '21 at 17:27
  • okay, understood, thanks a lot! Really appreciate for your help! – Edison Toh Apr 29 '21 at 17:31