Three.js Изменение текстуры

135
17 ноября 2020, 23:50

Как можно изменить текущую текстуру (установил программно) у 3d объекта, используя textureObjLoader?

textureObjLoader = new THREE.TextureLoader(),
        map = textureObjLoader.load(`./models/${allTextures[i][0]}`);
        material = new THREE.MeshPhongMaterial({map: map});
        objLoader = new THREE.OBJLoader();
        objLoader.load(`./models/${objects[i]}`, function (obj) {
            obj.traverse( node=>{if (node.isMesh) node.material = material});
            obj.name = names[i];
            scene.add(obj);
        });
Answer 1

Чтобы изменить текстуру y THREE.MeshPhongMaterial достаточно изменить параметр map и поставить флаг needsUpdate у уже существующего материала

   material.map = texture;
   material.needsUpdate = true;

Однако загрузка текстуры - асинхронная операция, и по этому выставлять эти параметры необходимо после загрузки изображения, в случае когда оно еще не загружено.

Я поправил функцию из Вашего примера и теперь при нажатии на круги у банана меняется текстура.

Вторым аргументом у метода load() в textureLoader идет колбек загрузки текстуры, я поместил в него код, который не создает новый материал и только меняю текстуру в уже существующем.

function changeTexture(i) {
    let colorBlocks = document.querySelectorAll('.color_scheme__block');
    colorBlocks.forEach((val) => {
        val.onclick = () => {
            let value= val.style.background,
                arr = value.split('/'),
                result=arr[arr.length-1].slice(0,-2);
            textureObjLoader.load(`./models/${result}`, function(texture){
                var mat = scene.getObjectByName( names[i], true).children[0].material;
                mat.map = texture;
                mat.needsUpdate = true;
            });
        };
    });
}

использование .children[0] в общем случае некорректно, однако я не стал с этим мудрить, по хорошему надо проехаться по всем мешам в объекте в поисках необходимого материала, т.к. в общем же случае материалы могут быть у отдельных объектов в модели разные и не одни. но это лирика, для Вашего примера код работает корректно

Так же может быть не оптимально каждый раз создавать новые текстуры при клике на кнопку, но тут палка о двух концах, все зависит от количества и размера текстур и от характера их использования в приложении (как часто они меняются итд)

READ ALSO
Появление блока при наведении на другой блок javascript

Появление блока при наведении на другой блок javascript

Нашел на просторах интернета данный код

206
Поиск нескольких имен в цикле

Поиск нескольких имен в цикле

Что есть Набор данных в виде: Тема пиьма – Имя / комментарий, наборов может быть несколько, выполняется split по \n

97
Добавление атрибутa muted к тегу <audio> через JavaScript

Добавление атрибутa muted к тегу <audio> через JavaScript

пытался через js добавить атрибут 'muted' к аудио тегу, но попытки тщетныПри просмотре элементов все работает, но на деле же музыка продолжает...

127