Как я могу поместить текстуру в нужное место при изменении текстуры в формате gltf с помощью Three.js ?

#javascript #graphics #three.js #3d #gltf

#javascript #графика #three.js #3D #gltf

Вопрос:

Я попытался динамически изменить текстуру модели glTF, заменив текстуру на THREE.TextureLoader . Цвет текстуры изменился, как я и ожидал, однако рисунок текстуры был несколько смешанным.

Я впервые занимаюсь веб-графикой. Я переделывал пример просмотра 3D-моделей с помощью three.js это может загружать модели glTF. Я хотел динамически изменять текстуру с помощью кнопок. Из различных форматов я выбрал glTF, потому что он казался новым стандартом. Лучшим решением, которое я мог найти до сих пор, было добавить texture.flipY = false; под моим загрузчиком текстур, но это не сработало. Я также пытался изменить некоторые значения внутри объекта текстуры, но ничего не произошло.

Здесь я загружаю свою модель:

 loader.load( urls, function (texture) {
    var pmremGenerator = new THREE.PMREMGenerator( texture );
    pmremGenerator.update( renderer );

    var pmremCubeUVPacker = new THREE.PMREMCubeUVPacker(pmremGenerator.cubeLods);
    pmremCubeUVPacker.update( renderer );

    var envMap = pmremCubeUVPacker.CubeUVRenderTarget.texture;
    var loader = new THREE.GLTFLoader().setPath( `models/${modelName}/`);

    loader.load(`${modelName}.gltf`, (gltf) => {

        gltf.scene.traverse((child) => {
            if (child.isMesh) {
                child.material.envMap = envMap;
            }
        });

        gltf.scene.scale.set(0.01,0.01,0.01)
        scene.add(gltf.scene);
    });
  

и я попытался изменить ее текстуру, реализовав эту функцию:

 function changeColor(color) {

    const textureLoader = new THREE.TextureLoader();
    const texture = textureLoader.load(`models/${modelName}/textures/fabric-${color}.jpg`);

    texture.flipY = false;

    scene.traverse((child) => {
        if (child.isMesh) {
            if (child.material.map.format === 1022) {
                child.material.map = texture;
            }
        }
    });
}
  

Хотя я смог настроить таргетинг на нужную мне сетку и изменил ее цвет, шаблон текстуры был очень неудобным. Это была верхняя часть стула, сделанная из ткани.

чтобы нарисовать это в тексте, это выглядело так…

Что это должно было быть:

 -------------------
| / / / / / / / / |
| / / / / / / / / |
| / / / / / / / / |
| / / / / / / / / |
| / / / / / / / / |
| / / / / / / / / |
| / / / / / / / / |
-------------------
Figure 1
  

Реальность:

 -------------------
|                 |
|                 |
|                 |
|                 |
|                 |
|                 |
|                 |
-------------------
Figure 2
  

Для ясности:
Как я могу сохранить шаблон текстуры, как показано на рисунке 1, при изменении файла текстуры с помощью функции выше?

Комментарии:

1. Хотя мне нравятся иллюстрации в формате ASCII, немного сложно понять, что вы здесь видите. 😉 Вы правильно настроили flipY=false . Помимо этого, есть ли у модели текстура изначально, которую вы меняете? Или текстура не встроена, но вы ее добавляете? Если сетки в модели не имеют UVS ( mesh.geometry.attributes.uv ), это будет проблемой. Обычно UV-отображение — это способ управления расположением текстуры в сетке, и это лучше всего делать в таком инструменте, как Blender.

2. @DonMcCurdy извините за мой плохой рисунок: ( если вы не возражаете, вы можете посетить эту ссылку , чтобы посмотреть, как это выглядит. Да, у модели изначально есть текстура, и я пытался просто изменить material.map с помощью нового файла JPG, который я покрасил по-другому. Я попробую что-нибудь с UV-отображениями. Спасибо за помощь.

Ответ №1:

Благодаря помощи DonMcCurdy я наконец получил ответ.

Это действительно была проблема с отображением UV.

Чтобы получить текстуру в нужном месте, мне нужно было добавить эти: wrapS, wrapT и RepeatWrapping

 function changeColor(color) {

    const textureLoader = new THREE.TextureLoader();
    const texture = textureLoader.load(`models/${modelName}/textures/fabric-${color}.jpg`);

    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;
    texture.flipY = false;

    scene.traverse((child) => {
        if (child.isMesh) {
            if (child.material.map.format === 1022) {
                child.material.map = texture;
            }
        }
    });
}
  

Официальная документация:
https://threejs.org/docs/#api/en/textures/Texture