Как динамически наложить текстуру из модели GLTF - Three.js

Я хочу наложить / включить или выключить текстуру из модели GLTF, но не могу найти, как и возможно ли это. Мне удалось загрузить его отлично, но когда я пытаюсь перезагрузить или наложить текстуру, ничего не происходит или возникают ошибки. Последнее, что я пробовал, не дает мне никаких ошибок, но модель сохраняет исходную текстуру. Я также попытался выгрузить модель и снова загрузить с другой текстурой, тоже безуспешно.

Я использую стандартный пример THREE.GLTFLoader из документации three.js, просто изменил загруженную 3D-модель и добавил функцию для внесения этих изменений через некоторое время. Я, наверное, все путаю, если поможете, буду признателен, заранее спасибо.

Доступные ссылки, которые мне не помогают: ThreeJS: удалить объект со сцены; three.js Переключение объектов при нажатии; Как мне динамически изменять текстуру модели GLTF?; Изменить текстуру загруженного .obj в three.js во время выполнения; Импортируйте другую текстуру во время выполнения в THREE.JS и GLTF

Код, который я использую:

<!DOCTYPE html>
<html lang = "en">
<head>
    <title>three.js webgl - glTF loader</title>
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #000;
            color: #fff;
            margin: 0px;
            overflow: hidden;
        }
        #info {
            color: #fff;
            position: absolute;
            top: 10px;
            width: 100%;
            text-align: center;
            z-index: 100;
            display:block;
        }
        #info a {
            color: #75ddc1;
            font-weight: bold;
        }
    </style>
</head>

<body>
    <div id = "info"><!--
        <a href = "http://threejs.org" target = "_blank" rel = "noopener">three.js</a> - GLTFLoader<br />
        Battle Damaged Sci-fi Helmet by
        <a href = "https://sketchfab.com/theblueturtle_" target = "_blank" rel = "noopener">theblueturtle_</a><br /> -->
    </div>

    <script src = "build/three.js"></script>

    <script src = "js/controls/OrbitControls.js"></script>
    <script src = "js/loaders/GLTFLoader.js"></script>

    <script src = "js/Detector.js"></script>
    <script src = "js/libs/stats.min.js"></script>

    <script>

        if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

        var container, stats, controls;
        var camera, scene, renderer, light;
        var globalObject;

        init();
        animate();

        function init() {

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

            camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 2000 );
            camera.position.set( -250.8, 260.9, 262.7 );


            controls = new THREE.OrbitControls( camera );
            controls.target.set( 0, -0.2, -0.2 );
            controls.update();

            // envmap
            var path = 'textures/cube/Bridge2/';
            var format = '.jpg';
            var envMap = new THREE.CubeTextureLoader().load( [
                path + 'posx' + format, path + 'negx' + format,
                path + 'posy' + format, path + 'negy' + format,
                path + 'posz' + format, path + 'negz' + format
            ] );

            scene = new THREE.Scene();
            scene.background = envMap;

            light = new THREE.HemisphereLight( 0xbbbbff, 0x444422 );
            light.position.set( 0, 1, 0 );
            scene.add( light );

            // model
            var loader = new THREE.GLTFLoader();
            loader.load( 'models/testeFinal2-1/testeFinal2-1.gltf', function ( gltf ) {

                globalObject = gltf.scene;

                gltf.scene.traverse( function ( child ) {

                    if ( child.isMesh ) {

                        child.material.envMap = envMap;

                    }

                } );

                scene.add( gltf.scene );

            } );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            renderer.gammaOutput = true;
            container.appendChild( renderer.domElement );

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

            // stats
            stats = new Stats();
            container.appendChild( stats.dom );

        }

        function onWindowResize() {

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

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

        }

        //

        function animate() {

            requestAnimationFrame( animate );

            renderer.render( scene, camera );

            stats.update();

        }

        setTimeout(newTexture(), 7000); //Do the changes after 7s.

        function newTexture() {

            scene.remove( globalObject ); //This don't give me any error, but does nothing.

            // envmap
            var path = 'textures/cube/Bridge2/';
            var format = '.jpg';
            var envMap = new THREE.CubeTextureLoader().load( [
                path + 'posx' + format, path + 'negx' + format,
                path + 'posy' + format, path + 'negy' + format,
                path + 'posz' + format, path + 'negz' + format
            ] );

            var loader = new THREE.GLTFLoader(); //Trying to reload the second time, does nothing either.
            loader.load( 'models/testeFinal2-1/2/testeFinal2-1.gltf', function ( gltf ) {

                gltf.scene.traverse( function ( child ) {

                    if ( child.isMesh ) {

                        child.material.envMap = envMap;

                    }

                } );

                scene.add( gltf.scene );

            } );
        }           

    </script>

</body>

ОБНОВЛЕНИЕ1 (удалена функция newTexture и отредактирован загрузчик модели):

// model
            var loader = new THREE.GLTFLoader();
            loader.load( 'models/testeFinal2-1/testeFinal2-1.gltf', function ( gltf ) {

                globalObject = gltf.scene;

                gltf.scene.traverse( function ( child ) {

                    if ( child.isMesh ) {

                        child.material.envMap = envMap;

                        setTimeout(function () {
                            child.material.map.image.currentSrc = "/models/testeFinal2-1/2/finalTest2_ORTO2.jpg";
                            child.material.map.image.src = "/models/testeFinal2-1/2/finalTest2_ORTO2.jpg";
                        }, 5000);

                    }

                } );

                scene.add( gltf.scene );

            } );

Пара предложений: (1) если вы загрузите одну и ту же модель на gltf-viewer.donmccurdy.com и переключаетесь между разными картами окружения, заметите ли вы разницу? (2) вам не нужно перезагружать модель, чтобы изменить карту среды, попробуйте изменить исходные сетки, (3) для каждого дочернего элемента, где находится child.isMesh === true, попробуйте записать значение child.material. Есть ли из материалов массив, как [ Material, Material ]? Если у вас есть сетка из нескольких материалов, вам нужно добавить envMap к каждому отдельно.

Don McCurdy 10.09.2018 07:46

(1) Фон остается белым, но я заметил изменения в освещении модели. (2) Я попытался изменить только характеристики текстуры, я поставил правки как UPDATE1, если хотите. Опять не получал ошибок, но тоже ничего не происходит. (3) Я получил один элемент: «MeshStandardMaterial», без массивов.

leonardofmed 11.09.2018 02:50

(1) да, это влияет только на освещение модели, если вы не измените настройку, (2) изменение изображения .src не повлияет, вам нужно использовать здесь экземпляр TextureLoader, (3) хм, хорошо, тогда это не проблема. Может я запуталась - не работает смена .map, .envMap или и то, и другое? Вы можете переназначить .map на что-нибудь вроде: var texLoader = new THREE.TextureLoader(); var texture = texLoader.load('foo.png'); child.material.map = texture.

Don McCurdy 11.09.2018 04:47

Думаю, моя проблема связана с .map, текстурой модели (.jpg). Проблема с экземпляром TextureLoader заключается в том, что текстура занимает неправильное положение в модели, даже если я перезагружаю исходный файл текстуры. Вот почему я пытался загрузить его с помощью GLTFLoader, но безуспешно.

leonardofmed 11.09.2018 15:20

А теперь я понимаю. На текстуре baseColor (.map) обязательно установите texture.flipY=false.

Don McCurdy 11.09.2018 20:32

Вот и все! Это то, что я искал! Я очень ценю вашу помощь! Вы хотите написать ответ?

leonardofmed 11.09.2018 20:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
6
7 699
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После загрузки модели вы можете использовать THREE.TextureLoader, чтобы прикрепить к модели новую текстуру. При этом не забудьте установить texture.flipY=false в соответствии с ориентацией UV модели glTF.

var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load( 'foo.png' );
texture.flipY = false;

var loader = new THREE.GLTFLoader();
loader.load( 'foo.glb', ( gltf ) => {
  var model = gltf.scene;
  model.traverse ( ( o ) => {
    if ( o.isMesh ) {
      // note: for a multi-material mesh, `o.material` may be an array,
      // in which case you'd need to set `.map` on each value.
      o.material.map = texture;
    }
  } );
  scene.add( model );
} );

Вам нужно сохранить ссылку на модель после ее загрузки, а затем изменить ее в своем обработчике событий щелчка - если вы не знаете, как настроить обработчик событий щелчка или использовать его с three.js, я бы рекомендовал открыть новый ТАК вопрос. :)

Don McCurdy 14.09.2018 02:03

Как установить все стороны и установить различную текстуру (Пример: left: tex1, Right: tex2 ....)

vadivel a 27.02.2020 10:15

@vadivela см. stackoverflow.com/questions/17418118/….

Don McCurdy 27.02.2020 17:13

Другие вопросы по теме