Я хочу наложить / включить или выключить текстуру из модели 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) Фон остается белым, но я заметил изменения в освещении модели. (2) Я попытался изменить только характеристики текстуры, я поставил правки как UPDATE1, если хотите. Опять не получал ошибок, но тоже ничего не происходит. (3) Я получил один элемент: «MeshStandardMaterial», без массивов.
(1) да, это влияет только на освещение модели, если вы не измените настройку, (2) изменение изображения .src не повлияет, вам нужно использовать здесь экземпляр TextureLoader, (3) хм, хорошо, тогда это не проблема. Может я запуталась - не работает смена .map, .envMap или и то, и другое? Вы можете переназначить .map на что-нибудь вроде: var texLoader = new THREE.TextureLoader(); var texture = texLoader.load('foo.png'); child.material.map = texture.
Думаю, моя проблема связана с .map, текстурой модели (.jpg). Проблема с экземпляром TextureLoader заключается в том, что текстура занимает неправильное положение в модели, даже если я перезагружаю исходный файл текстуры. Вот почему я пытался загрузить его с помощью GLTFLoader, но безуспешно.
А теперь я понимаю. На текстуре baseColor (.map) обязательно установите texture.flipY=false.
Вот и все! Это то, что я искал! Я очень ценю вашу помощь! Вы хотите написать ответ?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


После загрузки модели вы можете использовать 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, я бы рекомендовал открыть новый ТАК вопрос. :)
Как установить все стороны и установить различную текстуру (Пример: left: tex1, Right: tex2 ....)
@vadivela см. stackoverflow.com/questions/17418118/….
Пара предложений: (1) если вы загрузите одну и ту же модель на gltf-viewer.donmccurdy.com и переключаетесь между разными картами окружения, заметите ли вы разницу? (2) вам не нужно перезагружать модель, чтобы изменить карту среды, попробуйте изменить исходные сетки, (3) для каждого дочернего элемента, где находится
child.isMesh === true, попробуйте записать значениеchild.material. Есть ли из материалов массив, как[ Material, Material ]? Если у вас есть сетка из нескольких материалов, вам нужно добавить envMap к каждому отдельно.