Search code examples
javascriptthree.js

Make the child of a loaded gltf file transparent dynamically using THREE.JS


I’m new to Three.js but have some experience with javascript. I’m loading a gltf model with an async loader function. This all seems to function correctly. I’m them creating a series of timer events to act upon the loaded object and/or the camera. Again this seems to work well until I come to making a particular child of the loadedObject transparent. I’ve managed a partial success but would like the function to ease the child transparency not just jump the change abruptly This is the function as it stands

  loadedObject.traverse((child) => {
    if (child.material) {
      console.log('Alpha', child.name);
      if (child.name === 'Crossbars') {
        let newMaterial = child.material.clone();
        newMaterial.transparent = true;
        newMaterial.opacity = 0.1;
        child.material = newMaterial;
      }
    }
  });

But when I add a tween like this: Nothing happens. What am I doing wrong?

  loadedObject.traverse((child) => {
    if (child.material) {
      console.log('Alpha', child.name);
      if (child.name === 'Crossbars') {
        let newMaterial = child.material.clone();
        newMaterial.transparent = true;
        child.material = newMaterial;
        new TWEEN.Tween(child.material).to({ opacity: 0.1 }, 50000).start();
      }
    }
  });

Solution

  • ...but would like the function to ease the child transparency not just jump the change abruptly...

    What you are writing about looks like a situation where you created an animation but did not update it in the animation loop, which meant that the change in opacity was not visible. Therefore, there is most likely a sudden change in opacity.

    Try set TWEEN.update() in animation loop

    <script type="importmap">
      {
    "imports": {
      "three": "https://unpkg.com/[email protected]/build/three.module.js",
      "three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
    }
      }
    </script>
    
    <script type="module">
    import * as THREE from 'three';
    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
    import { Tween, Easing } from 'https://unpkg.com/@tweenjs/[email protected]/dist/tween.esm.js';
    
          const scene = new THREE.Scene();
          scene.background = new THREE.Color(0xaaaaaa);
    
          const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
          camera.position.set(0, 2, 5);
    
          const renderer = new THREE.WebGLRenderer({ antialias: true });
          renderer.setSize(window.innerWidth, window.innerHeight);
          document.body.appendChild(renderer.domElement);
    
          const l = new THREE.DirectionalLight(0xffffff, 0.8);
          l.position.set(5, 10, 10);
          scene.add(l);
          let torsoTween;
          const loader = new GLTFLoader();
          loader.load(    'https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb',
            (gltf) => {
              const model = gltf.scene;
              scene.add(model);
              model.traverse((child) => {
                if (child.isMesh && child.name === 'Torso_3') {
                  child.material = child.material.clone();
                  child.material.transparent = true;
                  torsoTween = new Tween(child.material, false)
                    .to({ opacity: 0.1 }, 5000)
                    .easing(Easing.Quadratic.InOut)
                    .start();
                }
              });
            },
          );
          function animate(time) {
            requestAnimationFrame(animate);  
            if (torsoTween) torsoTween.update(time);
            renderer.render(scene, camera); 
          }
          animate();
    
          window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
          });
    </script>