OBJ模型滚动纹理材质失效问题求助:如何修复?
问题解决:OBJ模型应用滚动纹理材质失效
问题根源
OBJ模型加载后通常是一个包含多个子网格(Mesh)的Group对象,你当前代码直接获取顶层mesh对象并尝试读取其material属性,但Group本身没有material,导致后续纹理替换逻辑无法生效,模型显示默认白色;而基础立方体是单个Mesh,所以代码能正常运行。
解决方案
1. 遍历模型所有子网格,批量处理材质
修改model-loaded事件中的逻辑,遍历模型的所有子对象,筛选出Mesh类型的实体,收集它们的材质(支持单个材质或材质数组),再统一更新纹理。
2. 确保纹理加载完成后再启动动画
原代码中TextureLoader.load是异步操作,可能模型加载完成时纹理还未加载完毕,导致初始状态为白色,可通过Promise.all等待所有纹理加载完成后再启动动画。
修改后的完整代码
<script> function startPlaying(event) { // document.getElementById("scene").style.display = "block"; // document.getElementById("videoTex").play(); // event.target.style.display="none"; } AFRAME.registerComponent("slideshow", { init: function () { let loader = new THREE.TextureLoader(); let anim1_frames = 20; // 总帧数 // 用Promise封装纹理加载,等待所有纹理加载完成 const loadTexture = (url) => { return new Promise((resolve, reject) => { loader.load(url, resolve, undefined, reject); }); }; const texturePromises = []; for (var i = 0; i < anim1_frames; i++) { texturePromises.push(loadTexture(`https://urginsan.github.io/webTesting/sequence1/TextureAtlas_${i}.png`)); } Promise.all(texturePromises).then((pngArray) => { this.pngArray = pngArray; // 处理模型加载逻辑 const handleModelLoaded = () => { let model = this.el.getObject3D('mesh'); this.materials = []; // 遍历所有子网格,收集材质 model.traverse(obj => { if (obj.isMesh) { if (Array.isArray(obj.material)) { this.materials.push(...obj.material); } else { this.materials.push(obj.material); } } }); if (!this.materials || this.materials.length === 0) return; let i = 0; this.id = setInterval(() => { if (i >= this.pngArray.length) i = 0; const currentTexture = this.pngArray[i++]; // 更新所有材质的纹理 this.materials.forEach(material => { material.map = currentTexture; material.needsUpdate = true; }); }, 1000 / 25); // 25fps }; // 检查模型是否已提前加载完成 if (this.el.getObject3D('mesh')) { handleModelLoaded(); } else { this.el.addEventListener('model-loaded', handleModelLoaded); } }).catch(err => { console.error("纹理加载失败:", err); }); }, remove: function () { clearInterval(this.id); // 释放纹理内存 if (this.pngArray) { this.pngArray.forEach(texture => texture.dispose()); } } }) </script>
额外注意事项
- 如果OBJ模型的子网格使用了不支持
map属性的材质(如MeshDepthMaterial),需要先替换为MeshStandardMaterial或MeshBasicMaterial再设置纹理。 - 可以在
traverse逻辑中添加日志,确认是否正确找到所有子网格:console.log("找到子网格:", obj)
内容的提问来源于stack exchange,提问作者URGINSAN
相关产品推荐
相关产品推荐

