地图不适用于加载的 Obj
Posted
技术标签:
【中文标题】地图不适用于加载的 Obj【英文标题】:Map not applying to loaded Obj 【发布时间】:2018-06-21 02:41:53 【问题描述】:这是我上一个问题here 的后续。我只是想在这个 obj 的每一侧应用不同的纹理,但什么都没有出现。没有控制台错误,我相信我正在以正确的顺序应用。
这应该很简单,但过去一个小时我一直在努力解决这个问题。下面是一个代码示例:
(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>
那么我在这里做错了什么简单的事情?我认为问题出在这个函数上:
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...' );
);
此函数获取网格,然后加载所需的纹理并将其应用于网格中的材质。然后它告诉材料更新。这是正确的方法吗?
这个答案here 实际上只有在设置完所有内容后才调用渲染,但我希望能够在运行时更改纹理、材质等。
我以为mesh.children[0].material.needsUpdate = true
会通知着色器程序更新...
谢谢
【问题讨论】:
【参考方案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
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
见代码sn-p:
(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 数据,但是当它遇到 loadTexture 函数并在传入的网格上查找几何时它会抱怨 - 结果网格没有任何子对象。 实际上这很奇怪 - 我将我的 jsfiddle 更新为你所拥有的并且它可以工作,但同样的动作在我的本地不起作用 - 仍然返回给孩子们..以上是关于地图不适用于加载的 Obj的主要内容,如果未能解决你的问题,请参考以下文章