ThreeJS 为 .obj 上传多个纹理

Posted

技术标签:

【中文标题】ThreeJS 为 .obj 上传多个纹理【英文标题】:ThreeJS Upload multiple textures for .obj 【发布时间】:2021-05-12 17:57:43 【问题描述】:

所以我正在尝试上传一个 .obj 文件,该文件也有多个 .png 和 .jpg 文件,它们是它的纹理。问题是我不知道在上传这些纹理时如何处理它们。

到目前为止,这是我的代码:

var loader = new THREE.OBJLoader(manager);
loader.load(obj_path, function (obj) 

  model = obj;
  modelWithTextures = true;


  model.traverse( function ( child ) 

    if ( child.isMesh ) child.material.map = texture;

   );

  var textureLoader = new THREE.TextureLoader( manager );
  var i;
  for (var i = 0; i < files.length; i++) 
    file = files[i];
    console.log('Texture Files:' + files[i].name);
    var texture = textureLoader.load(files[i].name);
  
  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  setCamera(model);
  setSmooth(model);

  model.position.set(0, 0, 0);

  setBoundBox(model);
  setPolarGrid(model);
  setGrid(model);
  setAxis(model);

  scaleUp(model);
  scaleDown(model);

  fixRotation(model);
  resetRotation(model);

  selectedObject = model;
  outlinePass.selectedObjects = [selectedObject];
  outlinePass.enabled = false;

  renderer.render( scene, camera );
  scene.add(model);
);

如您所见,我正在使用 textureLoader,但不知道该怎么做。

我对 threeJS 和 3d 模型非常陌生。

任何帮助或建议将不胜感激。

谢谢。

【问题讨论】:

你的OBJ资产有对应的MTL文件吗? 不,它是一个没有 MTL 文件的 OBJ。另一个开发人员告诉我,我需要手动添加这些纹理。 能否请您先确定您的OBJ文件是否有纹理坐标? 是的,我的 obj 文件确实有纹理坐标,也有几个 png 文件就是它的纹理。 【参考方案1】:

在您的代码中,您可能看不到太多内容,因为您在将模型添加到场景之前渲染了场景。您应该在进行任何更改后渲染场景(除非您有一个带有requestAnimationFrame 的渲染循环)。加载纹理也是异步的。使用 .load 方法的回调来更好地在加载完成时做出反应,例如触发render()

我会在model.traverse() 回调中加载纹理。但是您必须确定哪个纹理属于哪个网格。这取决于您的数据的结构。

var files = ['mesh1_tex.jpg', 'mesh2_tex.jpg'];

var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );

var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, -100); // depends on the size and location of your loaded model

var renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );

var scene = new THREE.Scene();

loader.load(obj_path, function ( model ) 

  model.traverse( function ( child ) 

    if ( child instanceof THREE.Mesh ) 
    
      // here you have to find a way how to choose the correct texture for the mesh
      // the following is just an example, how it could be done, but it depends on your data
      const file = files.find( f => f === child.name + '_tex.jpg');
      if (!file) 
        console.warn(`Couldn't find texture file.`);
        return;
      
      
      textureLoader.load(file, ( texture ) => 
      
        child.material.map = texture;
        child.material.needsupdate = true;
        
        render(); // only if there is no render loop
      
      );
    
    

   );
  
  scene.add( model );
  
  camera.lookAt( model ); // depends on the location of your loaded model
  
  render(); // only if there is no render loop
  
);

function render() 

  renderer.render( scene, camera );
  

免责声明:我只是写下了这段代码,没有经过测试。

【讨论】:

以上是关于ThreeJS 为 .obj 上传多个纹理的主要内容,如果未能解决你的问题,请参考以下文章

ThreeJS - 洗掉的纹理

如何将带有 mtl 和纹理的 obj 上传到存储桶?

Threejs多重纹理与过程纹理实现

threejs深究动画,纹理,control等

如何在加载到场景之前将 OBJ/FBX 转换为 GLTF(使用 Threejs)

使用fabric js canvas作为threejs 3d模型纹理