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

Я попытался динамически изменить текстуру модели 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, при изменении файла текстуры с помощью функции выше?


person Jesung Koo    schedule 01.04.2019    source источник
comment
Хотя мне нравятся иллюстрации в кодировке ASCII, довольно сложно понять, что вы здесь видите. ;) Ты прав в установке flipY=false. Кроме того, есть ли у модели изначально изменяемая текстура? Или нет встроенной текстуры, но вы ее добавляете? Если сетки в модели не имеют UV (mesh.geometry.attributes.uv), это будет проблемой. Обычно UV-отображение - это способ управления расположением текстуры на сетке, и это лучше всего сделать с помощью такого инструмента, как Blender.   -  person Don McCurdy    schedule 01.04.2019
comment
@DonMcCurdy извините за мой плохой рисунок :( если вы не возражаете, вы можете посетить эту ссылку, чтобы увидеть, как это выглядит. Да, модель изначально имеет текстуру, и я пытался просто заменить material.map новым файлом JPG, который я раскрасил по-другому. Я попробую что-нибудь с сопоставлением UV. Спасибо за помощь.   -  person Jesung Koo    schedule 02.04.2019


Ответы (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

person Jesung Koo    schedule 11.04.2019