将材料应用于已加载的.obj

时间:2018-01-15 11:11:13

标签: three.js

这是我前几天提出的问题question,结果如下:



(function onLoad() {
  var canvasElement;
  var width, height;
  var scene, camera;
  var renderer;
  var controls;

  var pivot;
  var bagMesh;
  var planeMesh;

  const objLoader = new THREE.OBJLoader2();
  const fileLoader = new THREE.FileLoader();
  const textureLoader = new THREE.TextureLoader();

  init();

  function init() {
    container = document.getElementById('container');
    initScene();
    addGridHelper();
    addCamera();
    addLighting();
    addRenderer();
    addOrbitControls();

    loadCubeObj();

    // Logic
    var update = function() {};

    // Draw scene
    var render = function() {
      renderer.render(scene, camera);
    };

    // Run game logic (update, render, repeat)
    var gameLoop = function() {
      requestAnimationFrame(gameLoop);
      update();
      render();
    };
    gameLoop();
  }

  /**** Basic Scene Setup ****/
  function initScene() {
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xd3d3d3);
    var axis = new THREE.AxesHelper();
    scene.add(axis);
  }

  function addCamera() {
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(3, 3, 3);
    scene.add(camera);
  }

  function addGridHelper() {
    var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
    planeGeometry.rotateX(-Math.PI / 2);

    var planeMaterial = new THREE.ShadowMaterial({
      opacity: 0.2
    });
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.position.y = -200;
    plane.receiveShadow = true;
    scene.add(plane);

    var helper = new THREE.GridHelper(2000, 100);
    helper.material.opacity = 0.25;
    helper.material.transparent = true;
    scene.add(helper);

    var axis = new THREE.AxesHelper();
    scene.add(axis);
  }

  // *********** Lighting settings **********************
  function addLighting() {
    var light = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
    scene.add(light);
  }

  //************** End of materials ***************

  function addRenderer() {
    renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    container.appendChild(renderer.domElement);
  }

  function addOrbitControls() {
    var controls = new THREE.OrbitControls(camera, renderer.domElement);
  }

  function addPivot() {
    var cubeGeo = new THREE.BoxBufferGeometry(5, 5, 5);
    var cubeMat = new THREE.MeshBasicMaterial();
    pivot = new THREE.Mesh(cubeGeo, cubeMat);
    bagMesh.position.x -= 15;
    bagMesh.position.z -= 55;

    pivot.add(bagMesh);
    pivot.add(handle);
    scene.add(pivot);
  }
  
  function loadCubeObj() {
    loadObjWithMtl('LetterBox',
        'https://raw.githubusercontent.com/Katana24/threejs-experimentation/master/models/cube/letter-block.obj',
        'https://raw.githubusercontent.com/Katana24/threejs-experimentation/master/models/cube/letter-block.mtl')
      .then(function(mesh) {
        mesh.traverse(function(child) {
          if (child instanceof THREE.Mesh) {
            var materials = [
              new THREE.MeshBasicMaterial({
                map: new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/master/img/cube-diffuse-texture.png')
              })
            ];
            child.material = materials[0];
          }
        });
        scene.add(mesh);
      });
  }

  function loadObjWithMtl(modelName, modelUrl, mtlUrl, modificationFunc) {
    return new Promise(function(resolve, reject) {
      var callbackOnLoad = function(event) {
        var mesh = event.detail.loaderRootNode;
        if (modificationFunc) {
          modificationFunc(mesh);
          resolve(mesh);
        } else {
          resolve(mesh);
        }
      };
      var onLoadMtl = function(materials) {
        objLoader.setModelName(modelName);
        objLoader.setMaterials(materials);
        objLoader.getLogger().setDebug(true);
        objLoader.load(modelUrl, callbackOnLoad, null, null, null, false);
      };
      objLoader.loadMtl(mtlUrl, null, onLoadMtl);
    });
  }

})();

body {
  background: transparent;
  padding: 0;
  margin: 0;
  font-family: sans-serif;
}

#canvas {
  margin: 10px auto;
  width: 800px;
  height: 350px;
  margin-top: -44px;
}

<body>
  <div id="container"></div>
  <img src="https://github.com/Katana24/threejs-experimentation/blob/master/img/cube-diffuse-texture.png">

  <script src="https://threejs.org/build/three.js"></script>
  <script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
  <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
  <script src="https://threejs.org/examples/js/loaders/MTLLoader.js"></script>
  <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/LoaderSupport.js"></script>
  <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader2.js"></script>
</body>
&#13;
&#13;
&#13;

正如你所看到的那样,我将一个带有纹理的材质添加到立方体上 - 很棒。我有几个问题。

  1. 如何在每个外侧涂抹不同的材料?在Blender中构建模型时,我是否需要单独打开每一面并为每个面分配一个单独的材料?
  2. 为什么只有一种材料可以使用?
  3. 如何为每一方使用不同的材料,包括内部?
  4. 我问了一个关于第三个问题的另一个问题,因为我已经制作了另一个未包装的立方体(我复制了两侧并翻转了法线并将不同的材料应用到内部和外部(使用节点)这个。),除非有人能在这里回答。

    我尝试了以下1:

      mesh.traverse( function (child) {
        if( child instanceof THREE.Mesh ) {
          var materials = [
            new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('img/1.jpg')}),
            new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('img/2.jpg')}),
            new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('img/3.jpg')}),
            new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('img/4.jpg')}),
            new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('img/5.jpg')}),
            new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load('img/6.jpg')})
          ];
          child.material = materials;
        }
      });
      _this.scene.add(mesh);
    

    但根本没有任何东西出现。我还尝试为每个材质分配THREE.DoubleSide属性,但结果相同。

    修改

    回答我自己的问题:

    1. 在我需要的每一面放置不同的材料(在Blender中):

      • 通过标记接缝打开立方体
      • 将每个面部导出为&#34; UV布局&#34;
      • 在GIMP中打开脸部并填充颜色以区分每个脸部
      • 返回Blender,选择一面并创建新材料
      • 将渲染器类型设置为&#34; Cycles Renderer&#34;
      • 创建一种新材料并称之为“#34; front&#34;正面
      • 选择&#34;分配&#34;把它设置在前面
      • 拖动&#34;节点编辑器&#34;屏幕并单击&#34;使用节点&#34;
      • 添加&#34;图像纹理&#34;节点
      • 打开&#34;前面&#34;我们在GIMP中创建的图片
      • 最后在3D视图中将视图设置为&#34; Texture&#34;看到它反映了
      • 重申所有方面
    2. 这导致了这个:

      &#13;
      &#13;
      (function onLoad() {
        var canvasElement;
        var width, height;
        var scene, camera;
        var renderer;
        var controls;
      
        var pivot;
        var bagMesh;
        var planeMesh;
      
        const objLoader = new THREE.OBJLoader2();
        const fileLoader = new THREE.FileLoader();
        const textureLoader = new THREE.TextureLoader();
      
        init();
      
        function init() {
          container = document.getElementById('container');
          initScene();
          addGridHelper();
          addCamera();
          addLighting();
          addRenderer();
          addOrbitControls();
      
          loadCubeObj();
      
          // Logic
          var update = function() {};
      
          // Draw scene
          var render = function() {
            renderer.render(scene, camera);
          };
      
          // Run game logic (update, render, repeat)
          var gameLoop = function() {
            requestAnimationFrame(gameLoop);
            update();
            render();
          };
          gameLoop();
        }
      
        /**** Basic Scene Setup ****/
        function initScene() {
          scene = new THREE.Scene();
          scene.background = new THREE.Color(0xd3d3d3);
          var axis = new THREE.AxesHelper();
          scene.add(axis);
        }
      
        function addCamera() {
          camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
          camera.position.set(3, 3, 3);
          scene.add(camera);
        }
      
        function addGridHelper() {
          var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
          planeGeometry.rotateX(-Math.PI / 2);
      
          var planeMaterial = new THREE.ShadowMaterial({
            opacity: 0.2
          });
          var plane = new THREE.Mesh(planeGeometry, planeMaterial);
          plane.position.y = -200;
          plane.receiveShadow = true;
          scene.add(plane);
      
          var helper = new THREE.GridHelper(2000, 100);
          helper.material.opacity = 0.25;
          helper.material.transparent = true;
          scene.add(helper);
      
          var axis = new THREE.AxesHelper();
          scene.add(axis);
        }
      
        // *********** Lighting settings **********************
        function addLighting() {
          var light = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
          scene.add(light);
        }
      
        //************** End of materials ***************
      
        function addRenderer() {
          renderer = new THREE.WebGLRenderer({
            antialias: true
          });
          renderer.setPixelRatio(window.devicePixelRatio);
          renderer.setSize(window.innerWidth, window.innerHeight);
          renderer.shadowMap.enabled = true;
          container.appendChild(renderer.domElement);
        }
      
        function addOrbitControls() {
          var controls = new THREE.OrbitControls(camera, renderer.domElement);
        }
      
        function addPivot() {
          var cubeGeo = new THREE.BoxBufferGeometry(5, 5, 5);
          var cubeMat = new THREE.MeshBasicMaterial();
          pivot = new THREE.Mesh(cubeGeo, cubeMat);
          bagMesh.position.x -= 15;
          bagMesh.position.z -= 55;
      
          pivot.add(bagMesh);
          pivot.add(handle);
          scene.add(pivot);
        }
        
        function loadCubeObj() {
          loadObjWithMtl('LetterBox',
              'https://raw.githubusercontent.com/Katana24/threejs-experimentation/master/models/cube/cube-1.obj',
              'https://raw.githubusercontent.com/Katana24/threejs-experimentation/master/models/cube/cube-1.mtl')
            .then(function(mesh) {
              mesh.traverse(function(child) {
                if (child instanceof THREE.Mesh) {
                  child.material = new THREE.MeshBasicMaterial({
                      map: new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/master/models/cube/imgs/cube-1-all.png'), side: THREE.DoubleSide
                    });
                }
              });
              scene.add(mesh);
            });
        }
      
        function loadObjWithMtl(modelName, modelUrl, mtlUrl, modificationFunc) {
          return new Promise(function(resolve, reject) {
            var callbackOnLoad = function(event) {
              var mesh = event.detail.loaderRootNode;
              if (modificationFunc) {
                modificationFunc(mesh);
                resolve(mesh);
              } else {
                resolve(mesh);
              }
            };
            var onLoadMtl = function(materials) {
              objLoader.setModelName(modelName);
              objLoader.setMaterials(materials);
              objLoader.getLogger().setDebug(true);
              objLoader.load(modelUrl, callbackOnLoad, null, null, null, false);
            };
            objLoader.loadMtl(mtlUrl, null, onLoadMtl);
          });
        }
      
      })();
      &#13;
      body {
        background: transparent;
        padding: 0;
        margin: 0;
        font-family: sans-serif;
      }
      
      #canvas {
        margin: 10px auto;
        width: 800px;
        height: 350px;
        margin-top: -44px;
      }
      &#13;
      <body>
        <div id="container"></div>
        <img src="https://github.com/Katana24/threejs-experimentation/blob/master/img/cube-diffuse-texture.png">
      
        <script src="https://threejs.org/build/three.js"></script>
        <script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
        <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
        <script src="https://threejs.org/examples/js/loaders/MTLLoader.js"></script>
        <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/LoaderSupport.js"></script>
        <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader2.js"></script>
      </body>
      &#13;
      &#13;
      &#13;

      1. 仅当您的导出模型在其构造中定义单个材质时,单个材质才有效。在我的第一个代码片段中,对象导出了一个材质,而在第二个代码片段中有5个材质,每个材质描述了该边的单个位置,允许每个材质都被更改。
      2. 3.对每一面应用不同的材料,包括内部,与1中描述的过程相同,但在分配材料之前,必须复制所有边并翻转法线。

        编辑2

        在我上面的最新代码段中,如果我更改了从GIMP导出的图像,该图像覆盖了所有内容,只是加载了一些随机图像,它们就不会正确显示在多维数据集上:

        enter image description here

        如何正确地将纹理映射到每一面,而不将图像的一部分移到一边或另一边?

        由于

1 个答案:

答案 0 :(得分:0)

好的,所以经过一些乱七八糟的努力后,我发现了这一切。为了回答我的上一个问题(参见编辑2),我确实需要复制所有的边并翻转内部的法线。

但是应该注意的是,当您将材质应用到立方体的每一面(包括内部)并为该材质指定图像时,它将在三个中看起来很好。

例如:

enter image description here

是一个具有UV映射的立方体,所有这些都在Blender中完成。但是当应用于其他图像时,它会产生一个与编辑2中的图像类似的立方体。

要解决此问题,我需要手动修改.obj文件中的 vt 值。我不打算在这里发布原始.obj,所以扩展下面的代码片段并在我的git上查看它。 (我将保持StackOverflow分支,以便它不会被修改)

(function onLoad() {
  var canvasElement;
  var width, height;
  var scene, camera;
  var renderer;
  var controls;

  var pivot;
  var bagMesh;
  var planeMesh;

  const objLoader = new THREE.OBJLoader2();
  const fileLoader = new THREE.FileLoader();
  const textureLoader = new THREE.TextureLoader();

  init();

  function init() {
    container = document.getElementById('container');
    initScene();
    addGridHelper();
    addCamera();
    addLighting();
    addRenderer();
    addOrbitControls();

    loadCubeObj();

    // Logic
    var update = function() {};

    // Draw scene
    var render = function() {
      renderer.render(scene, camera);
    };

    // Run game logic (update, render, repeat)
    var gameLoop = function() {
      requestAnimationFrame(gameLoop);
      update();
      render();
    };
    gameLoop();
  }

  /**** Basic Scene Setup ****/
  function initScene() {
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xd3d3d3);
    var axis = new THREE.AxesHelper();
    scene.add(axis);
  }

  function addCamera() {
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(3, 3, 3);
    scene.add(camera);
  }

  function addGridHelper() {
    var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
    planeGeometry.rotateX(-Math.PI / 2);

    var planeMaterial = new THREE.ShadowMaterial({
      opacity: 0.2
    });
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.position.y = -200;
    plane.receiveShadow = true;
    scene.add(plane);

    var helper = new THREE.GridHelper(2000, 100);
    helper.material.opacity = 0.25;
    helper.material.transparent = true;
    scene.add(helper);

    var axis = new THREE.AxesHelper();
    scene.add(axis);
  }

  // *********** Lighting settings **********************
  function addLighting() {
    var light = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
    scene.add(light);
  }

  //************** End of materials ***************

  function addRenderer() {
    renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    container.appendChild(renderer.domElement);
  }

  function addOrbitControls() {
    var controls = new THREE.OrbitControls(camera, renderer.domElement);
  }

  function addPivot() {
    var cubeGeo = new THREE.BoxBufferGeometry(5, 5, 5);
    var cubeMat = new THREE.MeshBasicMaterial();
    pivot = new THREE.Mesh(cubeGeo, cubeMat);
    bagMesh.position.x -= 15;
    bagMesh.position.z -= 55;

    pivot.add(bagMesh);
    pivot.add(handle);
    scene.add(pivot);
  }

  function loadCubeObj() {
    loadObjWithMtl('LetterBox',
        'https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/models/cube/cube-3.obj',
        'https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/models/cube/cube-3.mtl')
      .then(function(mesh) {
        mesh.traverse(function(child) {
          var textures = [
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/1.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/2.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/3.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/4.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/5.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/4.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/3.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/2.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/1.jpg'),
            new THREE.TextureLoader().load('https://raw.githubusercontent.com/Katana24/threejs-experimentation/stack-overflow/img/2.jpg')
          ];
          if( child instanceof THREE.Mesh ) {
            for(var i = 0; i < 10; i++) {
                child.material[i] = new THREE.MeshBasicMaterial({map: textures[i]});	
            }
          }
        });
        scene.add(mesh);
      });
  }
  
  function getRandomColour() {
		return "#000000".replace(/0/g,function(){return (~~(Math.random()*16)).toString(16);});
	}	

  function loadObjWithMtl(modelName, modelUrl, mtlUrl, modificationFunc) {
    return new Promise(function(resolve, reject) {
      var callbackOnLoad = function(event) {
        var mesh = event.detail.loaderRootNode;
        if (modificationFunc) {
          modificationFunc(mesh);
          resolve(mesh);
        } else {
          resolve(mesh);
        }
      };
      var onLoadMtl = function(materials) {
        objLoader.setModelName(modelName);
        objLoader.setMaterials(materials);
        objLoader.getLogger().setDebug(true);
        objLoader.load(modelUrl, callbackOnLoad, null, null, null, false);
      };
      objLoader.loadMtl(mtlUrl, null, onLoadMtl);
    });
  }

})();
body {
  background: transparent;
  padding: 0;
  margin: 0;
  font-family: sans-serif;
}

#canvas {
  margin: 10px auto;
  width: 800px;
  height: 350px;
  margin-top: -44px;
}
<body>
  <div id="container"></div>
  <img src="https://github.com/Katana24/threejs-experimentation/blob/master/img/cube-diffuse-texture.png">

  <script src="https://threejs.org/build/three.js"></script>
  <script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
  <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
  <script src="https://threejs.org/examples/js/loaders/MTLLoader.js"></script>
  <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/LoaderSupport.js"></script>
  <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader2.js"></script>
</body>