Assign and update child mesh material

HI,

I import a GLTF model that consists of child meshes. I traverse the imported model and get access to childs “legs”, “seat”, “rubber” etc.

  1. How do i assign materials to these children before assigning them to the scene?

  2. How do i update the material if it’s changed by user interaction (ex. drop down menu, radiobuttons etc.)?
    Preferably without re-adding the geometry to the scene but just updating the material!

Hope you can guide me in the right direction!

Many thanks,
Henrik

Please see the three.js documentation on THREE.Mesh. Each Mesh already has a .material property that can be modified or changed. If you are replacing the material that’s already there, you will need to be careful to preserve various settings on the original material (.skinning, .morphTargets, etc.) that might be important.

1 Like

Hi,

I read the documentation and i follow what you mean but i’m not strong in the coding part, so if you can help me out a bit i would be greatful!
I’ve tried something like this:

gltf.scene.traverse(function(child){

                            if (child.isMesh){
                                let newMesh = child.getObjectByName("legs");
                                let material = new THREE.MeshPhongMaterial({ color: 0xFF0000, flatShading: true });
                            }

scene.add(newMesh, material);

Obviously i’m off… :expressionless:

Alright. I got to the point where i can assign materials to my models as i like. Now i want the material color to update with a dropdown/select menu.
My code is structured like this:

HTML dropdown onchange=update()
JS script with update() function

Now i get this message in the console:
Uncaught ReferenceError: update is not defined
at HTMLSelectElement.onchange

I have tried moving the JS before the dropdown HTML code but that doesn’t help.
How should i structure this, so that it works out?

Cheers,
Henrik

Here’s the body code:

<body>
    <div id="colorchange">
        <select id="chaircolor" onchange="dropdownUpdate()">
          <option value="#ff0000">Red</option>
          <option value="#0000ff" selected>Blue</option>
          <option value="#00ff00">Green</option>
          <option value="#cccccc">Grey</option>
        </select>
    </div>
    <div id="canvas"></div>
    <script type="module">
        import * as THREE from './threejs/build/three.module.js';
        import {GLTFLoader} from './threejs/examples/jsm/loaders/GLTFLoader.js';
        import {RGBELoader} from './threejs/examples/jsm/loaders/RGBELoader.js';
        import {RoughnessMipmapper} from './threejs/examples/jsm/utils/RoughnessMipmapper.js';

        // Declare varialbles
        let container, scene, camera, renderer, content, colorValue, width, height;
        container = document.getElementById("canvas");
        width = window.innerWidth;
        height = window.innerHeight;
        
        buildScene();
        buildRenderer();
        buildCamera(width, height);
        iblLight();
        loadModel();
        render();

        function dropdownUpdate(){
            console.log("Great!");
        }

        function buildScene(){
            scene = new THREE.Scene();
            scene.background = new THREE.Color("#000");

            return scene;
        }

        function buildRenderer(){
            renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(width, height);
            renderer.toneMapping = THREE.ACESFilmicToneMapping;
            renderer.toneMappingExposure = 1;
            renderer.outputEncoding = THREE.sRGBEncoding;
            container.appendChild(renderer.domElement);

            return renderer;
        }

        function buildCamera() {
            const aspectRatio = width / height;
            const fieldOfView = 30;
            const nearPlane = 1;
            const farPlane = 100; 
            camera = new THREE.PerspectiveCamera(fieldOfView, aspectRatio, nearPlane, farPlane);
            camera.position.set(0, 2.5, 10);

            return camera;
        }
        
        function iblLight(){
            new RGBELoader()
                .setDataType(THREE.UnsignedByteType)
                .setPath('./textures/')
                .load('env_paris_2.hdr', function(texture){

                    let pmremGenerator = new THREE.PMREMGenerator(renderer);
                    let envMap = pmremGenerator.fromEquirectangular(texture).texture;
                    pmremGenerator.compileEquirectangularShader();

                  //  scene.background = envMap;
                    scene.background = new THREE.Color( 0x000000 );
                    scene.environment = envMap;

                    texture.dispose();
                    pmremGenerator.dispose();
            });
        }

        function loadModel(){
            colorValue = document.getElementById("chaircolor").value;
            console.log(colorValue);
            colorValue = new THREE.Color(colorValue);
            //let colorValue = new THREE.Color(0x002200);
            let loader = new GLTFLoader().setPath('./models/');
                loader.load('chair3207.gltf', function(gltf){

                    gltf.scene.traverse(function(child){
                        if (child.isMesh){
                            //console.log(child);
                    
                            if (child.name == "cloth") {
                                child.material = new THREE.MeshPhongMaterial({
                            color: colorValue,    // red (can also use a CSS color string here)
                            flatShading: false
                            });
                            }
                            console.log(colorValue);


                            // roughnessMipmapper.generateMipmaps(child.material);
                        }
                    });
                

                //    scene.add(gltf.scene);
                    //scene.add(gltf.scene.legs);
                    scene.add(gltf.scene);

                //    roughnessMipmapper.dispose();

                    render();
                });
        }

        function onWindowResize() {
            
            camera.aspect = width / height;
            camera.updateProjectionMatrix();

            renderer.setSize(width, height);

            render();

        }

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

        }

    </script>
</body>