地图不适用于加载的 Obj [英] Map not applying to loaded Obj

查看:39
本文介绍了地图不适用于加载的 Obj的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是继我之前的问题这里.我只是想在这个 obj 的每一面应用不同的纹理,但什么也没出现.没有控制台错误,我相信我正在按正确的顺序应用.

This follows on from my previous question here. I'm just trying to apply a different texture to each side of this obj but nothing appears. There are no console errors and I believe I'm applying things in the right order.

这应该很简单,但过去一个小时我一直在努力.下面是一个代码示例:

This should be quite simple to do but I've been struggling with it for the past hour. Here's a code sample below:

(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();

    loadPlaneObj();
    
    // 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);
  }

  // ************** Material settings **************
  function setMaterial(materialName) {
    // get the object from the scene
    var bagMesh = scene.getObjectByName('bag');
    var material;

    if (!materialName) {
      materialName = materials.material;
    }

    if (bagMesh) {
      var colour = parseInt(materials.colour);
      switch (materialName) {
        case 'MeshBasicMaterial':
          material = new THREE.MeshBasicMaterial({
            color: colour
          });
          break;
        case 'MeshDepthMaterial':
          material = new THREE.MeshDepthMaterial();
          break;
        case 'MeshLambertMaterial':
          material = new THREE.MeshLambertMaterial({
            color: colour
          });
          break;
        case 'MeshNormalMaterial':
          material = new THREE.MeshNormalMaterial();
          break;
        case 'MeshPhongMaterial':
          material = new THREE.MeshPhongMaterial({
            color: colour
          });
          break;
        case 'MeshPhysicalMaterial':
          material = new THREE.MeshPhysicalMaterial({
            color: colour
          });
          break;
        case 'MeshStandardMaterial':
          material = new THREE.MeshStandardMaterial({
            color: colour
          });
          break;
        case 'MeshToonMaterial':
          material = new THREE.MeshToonMaterial({
            color: colour
          });
          break;
      }
      bagMesh.children.forEach(function(c) {
        c.material = material;
      });
    }
  }

  function setMaterialColour(colour) {
    materials.colour = colour;
    setMaterial(null);
  }
  // ************** 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 loadPlaneObj() {
		loadObjWithMtl('PlaneWithMaterial', 
      'https://rawgit.com/Katana24/threejs-experimentation/material-test/models/PlaneWithMaterial.obj', 
      'https://rawgit.com/Katana24/threejs-experimentation/material-test/models/PlaneWithMaterial.mtl')
			.then(function(mesh) {
        loadTexture(
          'https://rawgit.com/Katana24/threejs-experimentation/material-test/img/1.jpg', scene, 0xff0000, THREE.FrontSide, mesh);
			});
	}
  
  function loadObjWithMtl(modelName, modelUrl, mtlUrl) {
		return new Promise(function(resolve, reject) {
			var callbackOnLoad = function ( event ) { resolve(event.detail.loaderRootNode); };
			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 );
		});
	}

	function loadTexture(imgPath, scene, color, side, mesh) {
		var loadedMesh = mesh;
	  textureLoader.load(imgPath,
			function (texture) {	
        var geometry = new THREE.Geometry().fromBufferGeometry( loadedMesh.children[0].geometry );
				mesh.children[0].material.map = texture;
				mesh.children[0].material.needsUpdate = true;
				scene.add(mesh);
			},
			undefined,
			function ( err ) {
				console.error( 'An error occurred...' );
			}
		);
	}
  
  function addPlaneToSceneSOAnswer(mesh) {
		var frontMaterial = new THREE.MeshBasicMaterial( { color : 0xff0000, side: THREE.FrontSide } );
		var backMaterial 	= new THREE.MeshBasicMaterial( { color : 0x00ff00, side: THREE.BackSide } );
		
		var geometry = new THREE.Geometry().fromBufferGeometry( mesh.children[0].geometry );
		var length = geometry.faces.length;
		geometry.faces.splice(14, 1);

		for (var i = 0; i < geometry.faces.length; i ++ ) {
			var face = geometry.faces[i];
			face.color.setHex(Math.random() * 0xffffff);
		}
		mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, side: THREE.DoubleSide }) );
		mesh.material.side = THREE.FrontSide; 
		
		var mesh2 = new THREE.Mesh( geometry, mesh.material.clone() ); 
		mesh2.material.side = THREE.BackSide; 
		// mesh2.material.vertexColors = THREE.NoColors; 
		mesh2.material.vertexColors = [new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff)];

		mesh.add( mesh2 );
		scene.add(mesh);
	}
})();

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>
  <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>

那么我在这里做错了什么简单的事情?我认为问题出在这个函数上:

So what simple thing am I doing wrong here? I think the problem is in this function:

  function loadTexture(imgPath, scene, color, side, mesh) {
    var loadedMesh = mesh;
    textureLoader.load(imgPath,
      function (texture) {  
        var geometry = new THREE.Geometry().fromBufferGeometry( loadedMesh.children[0].geometry );
        mesh.children[0].material.map = texture;
        mesh.children[0].material.needsUpdate = true;
        scene.add(mesh);
      },
      undefined,
      function ( err ) {
        console.error( 'An error occurred...' );
      }
    );
  }

此函数获取网格,然后加载所需的纹理并将其应用于网格中的材质.然后它告诉材质更新.这是正确的方法吗?

This function gets the mesh then loads the required texture and applies it to the material in the mesh. It then tells the material to update. Is this the correct approach?

这个答案 here 实际上只在设置完所有内容后才调用 render 但我想要能够在运行时更改纹理、材料等.

This answer here actually only calls render once everything is set it but I want to be-able to change textures, materials etc at run time.

我认为 mesh.children[0].material.needsUpdate = true 会通知着色器程序更新...

I thought that mesh.children[0].material.needsUpdate = true would signal the shader program to update...

谢谢

推荐答案

纹理加载正确,但是没有正确显示,因为blender对象没有提供任何纹理坐标:

The texture is loaded correctly, but it is not shown correctly, because the blender object does not provide any texture coordinates:

# Blender v2.77 (sub 0) OBJ File: 'Plane.blend'
# www.blender.org
mtllib PlaneWithMaterial.mtl
o Plane
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v -1.000000 0.000000 -1.000000
v 1.000000 0.000000 -1.000000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 1//1 2//1 4//1 3//1

改用以下对象:

# Blender v2.77 (sub 0) OBJ File: 'Plane.blend'
# www.blender.org
mtllib PlaneWithMaterial.mtl
o Plane

v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
v -1.000000 0.000000 -1.000000
v 1.000000 0.000000 -1.000000

vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000

vn 0.0000 1.0000 0.0000

usemtl Material
s off
f 1/1/1 2/2/1 4/4/1 3/3/1

查看代码片段:

(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();
  textureLoader.setCrossOrigin("");
 
  init();

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

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

		// Draw scene
		var render = function() {
			renderer.render(scene, camera);
		};
    
    function resize() {
      var aspect = window.innerWidth / window.innerHeight;
      renderer.setSize(window.innerWidth, window.innerHeight);
      camera.aspect = aspect;
      camera.updateProjectionMatrix();
    }
    window.onresize = resize;

		// 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(1,1,1);
    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);
  }

  // ************** Material settings **************
  function setMaterial(materialName) {
    // get the object from the scene
    var bagMesh = scene.getObjectByName('bag');
    var material;

    if (!materialName) {
      materialName = materials.material;
    }

    if (bagMesh) {
      var colour = parseInt(materials.colour);
      switch (materialName) {
        case 'MeshBasicMaterial':
          material = new THREE.MeshBasicMaterial({
            color: colour
          });
          break;
        case 'MeshDepthMaterial':
          material = new THREE.MeshDepthMaterial();
          break;
        case 'MeshLambertMaterial':
          material = new THREE.MeshLambertMaterial({
            color: colour
          });
          break;
        case 'MeshNormalMaterial':
          material = new THREE.MeshNormalMaterial();
          break;
        case 'MeshPhongMaterial':
          material = new THREE.MeshPhongMaterial({
            color: colour
          });
          break;
        case 'MeshPhysicalMaterial':
          material = new THREE.MeshPhysicalMaterial({
            color: colour
          });
          break;
        case 'MeshStandardMaterial':
          material = new THREE.MeshStandardMaterial({
            color: colour
          });
          break;
        case 'MeshToonMaterial':
          material = new THREE.MeshToonMaterial({
            color: colour
          });
          break;
      }
      bagMesh.children.forEach(function(c) {
        c.material = material;
      });
    }
  }

  function setMaterialColour(colour) {
    materials.colour = colour;
    setMaterial(null);
  }
  // ************** 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 loadPlaneObj() {
    makeTextFile = function (text) {
      var data = new Blob([text], {type: 'text/plain'});
      var textFile = window.URL.createObjectURL(data);
      return textFile;   
    }
    var textbox_obj = document.getElementById('plane_obj');
    var obj_url = makeTextFile(textbox_obj.value);
    var textbox_mtl = document.getElementById('plane_mtl');
    var mtl_url = makeTextFile(textbox_mtl.value);

    loadObjWithMtl('plane1', 
      obj_url, mtl_url)
			.then(function(mesh) {
        loadTexture(
         'https://rawgit.com/Katana24/threejs-experimentation/material-test/img/1.jpg',
         scene, 0xff0000, THREE.FrontSide, mesh);
			});
	}
  
  function loadObjWithMtl(modelName, modelUrl, mtlUrl) {
		return new Promise(function(resolve, reject) {
			var callbackOnLoad = function ( event ) { resolve(event.detail.loaderRootNode); };
			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 );
		});
	}

	function loadTexture(imgPath, scene, color, side, mesh) {
		var loadedMesh = mesh;
	  textureLoader.load(imgPath,
			function (texture) {	
        var geometry = new THREE.Geometry().fromBufferGeometry( loadedMesh.children[0].geometry );
				mesh.children[0].material.map = texture;
				mesh.children[0].material.needsUpdate = true;
				scene.add(mesh);
			},
			undefined,
			function ( err ) {
				console.error( 'An error occurred...' );
			}
		);
	}
  
  function addPlaneToSceneSOAnswer(mesh) {
		var frontMaterial = new THREE.MeshBasicMaterial( { color : 0xff0000, side: THREE.FrontSide } );
		var backMaterial 	= new THREE.MeshBasicMaterial( { color : 0x00ff00, side: THREE.BackSide } );
		
		var geometry = new THREE.Geometry().fromBufferGeometry( mesh.children[0].geometry );
		var length = geometry.faces.length;
		geometry.faces.splice(14, 1);

		for (var i = 0; i < geometry.faces.length; i ++ ) {
			var face = geometry.faces[i];
			face.color.setHex(Math.random() * 0xffffff);
		}
		mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, side: THREE.DoubleSide }) );
		mesh.material.side = THREE.FrontSide; 
		
		var mesh2 = new THREE.Mesh( geometry, mesh.material.clone() ); 
		mesh2.material.side = THREE.BackSide; 
		// mesh2.material.vertexColors = THREE.NoColors; 
		mesh2.material.vertexColors = [new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff)];

		mesh.add( mesh2 );
		scene.add(mesh);
	}
})();

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>
  <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>

  <textarea id="plane_obj" style="display:none;">
    # Blender v2.77 (sub 0) OBJ File: 'Plane.blend'
    # www.blender.org
    mtllib Plane.mtl
    o Plane
    
    v -1.000000 0.000000 1.000000
    v 1.000000 0.000000 1.000000
    v -1.000000 0.000000 -1.000000
    v 1.000000 0.000000 -1.000000
    
    vt 0.000000 0.000000
    vt 1.000000 0.000000
    vt 0.000000 1.000000
    vt 1.000000 1.000000
    
    vn 0.0000 1.0000 0.0000
    
    usemtl None
    s off
    f 1/1/1 2/2/1 4/4/1 3/3/1
  </textarea>

  <textarea id="plane_mtl" style="display:none;">
    # Blender MTL File: 'Plane.blend'
    # Material Count: 1
    
    newmtl None
    Ns 0
    Ka 0.000000 0.000000 0.000000
    Kd 0.8 0.8 0.8
    Ks 0.8 0.8 0.8
    d 1
    illum 2
  </textarea>

</body>

这篇关于地图不适用于加载的 Obj的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆