Как изменить текстуру 3D модели по клику?

Не получается изменить текстуру 3Д модели по клику в Realtime, не могу найти ответ, что отвечает за перерисовку объекта. Смотрел в справочнике Three.js примеры, не могу все равно понять что и за что отвечает :( Помогите разобраться. Функция работает, и переменная получает значение новой текстуры, но изменения не происходят.

// Сhange material color
   
          const color_white = { materials: "white" };
          const color_grey  = { materials: "grey"  };
          const color_craft = { materials: "craft" };

          changeColor = function(input) {
            if (input.value === "craft") {
              materials = color_craft.materials;
            } else if (input.value === "grey") {
              materials = color_grey.materials;
            } else if (input.value === "white") {
              materials = color_white.materials;
            }
            console.log(materials);
          };
        // Create Camera
          camera = new THREE.PerspectiveCamera(current_box.perCam, window.innerWidth / window.innerHeight, 0.25, 20);
          camera.position.x = current_box.posX;
          camera.position.y = current_box.posY;
          camera.position.z = current_box.posZ;
          camera.rotation.y += 1 * (Math.PI/180);
        // Create a Controls 
          controls = new THREE.OrbitControls(camera, container);
          controls.enablePan = false;
          controls.enableZoom = true;
          controls.minDistance = current_box.minDistance;
          controls.maxDistance = current_box.maxDistance;
          controls.update();

        // Object resize
        function resize() {
          camera.aspect = w / h;
          camera.updateProjectionMatrix();
          
          renderer.setSize( w, h );

          animate();
          console.log('element resized: ' + w + 'x' + h);
        }
        window.addEventListener('resize', resize);

        // Create a Lights 
        const pointLight = new THREE.PointLight( 0xffffff, 1.0, 3000 );
              pointLight.position.set( 1500, 1500, 1300 );

        const ambientLight = new THREE.AmbientLight( 0x999999 ); // soft white light

          scene.add(ambientLight, pointLight, );
          var onProgress = function ( xhr ) {

          if ( xhr.lengthComputable ) {

            var percentComplete = xhr.loaded / xhr.total * 100;
            console.log( Math.round( percentComplete, 2 ) + '% downloaded' );

          }
        };
        renderer = new THREE.WebGLRenderer();
        renderer.setPixelRatio( window.devicePixelRatio);
        container.append( renderer.domElement );

       function loadModel() {

          object.traverse( function ( obj ) {

            if ( obj.isMesh )
                obj.material.map = texture;
                material.needsUpdate = true;
          } );

          object.position.y = 0;
          object.position.x = 0;
          object.position.z = 0;
          
          scene.add( object );
          resize();
          animate();
        }

        var manager = new THREE.LoadingManager( loadModel );

        manager.onProgress = function ( item, loaded, total ) {

          console.log( item, loaded, total );

        };
        // Load texture
        var textureLoader = new THREE.TextureLoader( manager );
        var texture = textureLoader.load(basePath+'materials/'+materials+'.jpg', function(){
          material.map = texture;
          material.needsUpdate = true;
        });
        
        var mtlLoader = new THREE.MTLLoader( manager );
        mtlLoader.load(basePath+models+'.mtl', function(materials) {
  
          materials.preload();

          var loader = new THREE.OBJLoader( manager );
          loader.load(basePath+models+'.obj', function ( obj ) {
           
            object = obj;
            scene.add(obj);
            scene.updateMatrixWorld(true);

          }, onProgress, onError);
        });
        function onProgress( xhr ) {

          if ( xhr.lengthComputable ) {

            var percentComplete = xhr.loaded / xhr.total * 100;
            console.log( 'model ' + Math.round( percentComplete, 2 ) + '% downloaded' );

          }

        }
        function onError() {}
        
        // Render scene
        function animate() {
        renderer.render(scene,camera);
        requestAnimationFrame(animate);
      }


Ответы (1 шт):

Автор решения: prisoner849

Вот такой вариант: загружать текстуры в массив и потом по нажатию на кнопку назначать материалу ту или иную текстуру в свойство .map.

body {
  overflow: hidden;
  margin: 0;
}
button {
  position: absolute;
}
<button id="tex_0">Texture0</button>
<button id="tex_1" style="left: 100px;">Texture1</button>
<script type="module">
import * as THREE from 'https://threejs.org/build/three.module.js';
import { OBJLoader } from 'https://threejs.org/examples/jsm/loaders/OBJLoader.js';

var container;

var camera, scene, renderer;

var mouseX = 0,
  mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

var object;

init();
animate();


function init() {

  container = document.createElement('div');
  document.body.appendChild(container);

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
  camera.position.z = 250;

  // scene

  scene = new THREE.Scene();

  var ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
  scene.add(ambientLight);

  var pointLight = new THREE.PointLight(0xffffff, 0.8);
  camera.add(pointLight);
  scene.add(camera);

  // manager

  function loadModel() {

    setTexture(0);

    object.position.y = -95;
    scene.add(object);

  }

  var manager = new THREE.LoadingManager(loadModel);

  manager.onProgress = function(item, loaded, total) {

    console.log(item, loaded, total);

  };

  // texture
  var textures = [];

  var textureLoader = new THREE.TextureLoader(manager);
  textures.push(
    textureLoader.load('https://threejs.org/examples/textures/uv_grid_opengl.jpg'),
    textureLoader.load('https://threejs.org/examples/textures/colors.png')
    );
    
    tex_0.addEventListener("click", function(){setTexture(0);});
    tex_1.addEventListener("click", function(){setTexture(1);});
  function setTexture (texIdx){
    object.traverse(function(child) {

      if (child.isMesh) {
        child.material.map = textures[texIdx];
      }

    });
  }
  // model

  function onProgress(xhr) {

    if (xhr.lengthComputable) {

      var percentComplete = xhr.loaded / xhr.total * 100;
      console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');

    }

  }

  function onError() {}

  var loader = new OBJLoader(manager);

  loader.load('https://threejs.org/examples/models/obj/male02/male02.obj', function(obj) {

    object = obj;

  }, onProgress, onError);

  //

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);

  document.addEventListener('mousemove', onDocumentMouseMove, false);

  //

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

}

function onWindowResize() {

  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

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

}

function onDocumentMouseMove(event) {

  mouseX = (event.clientX - windowHalfX) / 2;
  mouseY = (event.clientY - windowHalfY) / 2;

}

//

function animate() {

  requestAnimationFrame(animate);
  render();

}

function render() {

  camera.position.x += (mouseX - camera.position.x) * .05;
  camera.position.y += (-mouseY - camera.position.y) * .05;

  camera.lookAt(scene.position);

  renderer.render(scene, camera);

}
</script>

→ Ссылка