近期在做三维重建项目,需要把最终生成的obj文件导入到web端浏览,这里使用的是three.js(另一个是babylon.js),但博主发现导入meshlab生成的obj时无法显示模型,但使用3dmax制作好的obj模型就可以正常加载。
模型可以加载但不显示,将mtl文件中的Tr值置为0或者将此行删除,Tr值是透明度的意思。
查看使用3dmax导出的obj模型和meshlab导出的obj模型的内容差异:
3dmax:
mtllib .\hezi.mtl
#
# object Box001
#
v -376.1360 0.0000 -195.4246
v -376.1360 0.0000 -2416.9438
v 383.2684 0.0000 -2416.9438
v 383.2684 0.0000 -195.4246
v -376.1360 281.1217 -195.4246
v 383.2684 281.1217 -195.4246
v 383.2684 281.1217 -2416.9438
v -376.1360 281.1217 -2416.9438
# 8 vertices
vn -0.5774 -0.5774 0.5774
vn -0.5774 -0.5774 -0.5774
vn 0.5774 -0.5774 -0.5774
vn 0.5774 -0.5774 0.5774
vn -0.5774 0.5774 0.5774
vn 0.5774 0.5774 0.5774
vn 0.5774 0.5774 -0.5774
vn -0.5774 0.5774 -0.5774
# 8 vertex normals
vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords
o Box001
g Box001
usemtl Material__20
s 2
f 1/1/1 2/2/2 3/3/3 4/4/4
s 4
f 5/4/5 6/1/6 7/2/7 8/3/8
s 8
f 1/4/1 4/1/4 6/2/6 5/3/5
s 16
f 4/4/4 3/1/3 7/2/7 6/3/6
s 32
f 3/4/3 2/1/2 8/2/8 7/3/7
s 64
f 2/4/2 1/1/1 5/2/5 8/3/8
# 6 polygons
meshlab:
####
#
# OBJ File Generated by Meshlab
#
####
# Object scene_dense_mesh_refine_texture.obj
#
# Vertices: 36032
# Faces: 70060
#
####
mtllib ./oursIron.mtl
vn -0.076525 -6.217203 -0.898077
v -0.537006 2.274760 -0.542009
vn -0.113609 -6.222937 -0.851465
v -0.480373 2.269041 -0.512856
vn 3.533463 -1.284490 -3.854646
v 0.272679 2.189417 -0.064509
vn -3.800684 -2.640818 -4.247900
v -1.191661 0.672984 0.196901
vn -3.108446 -1.922066 4.855567
v -0.489023 -0.371425 0.833074
vn 3.783675 -1.464100 4.783770
v -0.290044 -0.228601 0.900917
vn 1.204478 -2.802450 5.142253
v -0.240296 -0.132796 0.911664
vn -1.789222 -3.291406 5.007094
v -0.998870 0.413465 1.330705
vn -3.730475 5.029276 0.472679
v -1.170823 0.951970 0.805072
比较后发现除了排列方式不同其他的内容元素都是一样的,比如v,vn等,这里的具体含义参考博客:
obj文件、mtl文件结构说明
并且博主使用可以加载显示的obj模型在meshlab中重新导出仍然可以显示,这基本上可以排除是meshalb导出的原因。
先给出加载mtl和obj的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - OBJLoader + MTLLoader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: rgba(101, 132,226, 0.1);
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>
<!--引入three.js三维引擎-->
<!-- <script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>-->
<!-- <script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>-->
<!-- <script src="js/three.js"></script>-->
<!--引入轨道控件OrbitControls.js-->
<!--<script src="js/OrbitControls.js"></script>-->
<!--<script src="http://www.yanhuangxueyuan.com/3D/example/OrbitControls.js"></script>-->
</head>
<body>
<!--<script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>-->
<script src="js/three.js"></script>
<!--<script src="../build/three.js"></script>-->
<script src="js/DDSLoader.js"></script>
<script src="js/MTLLoader.js"></script>
<script src="js/OBJLoader.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/OrbitControls.js"></script>
<!--<script src="js/Vector3Node.js"></script>-->
<script>
// 容器
var container,
stats,
// 控制器
controls,
orbitControls;
// 镜头
var camera,
// 场景
scene,
// 渲染
renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
// animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
//正投影相机
//创建正投影相机
// var camera = new THREE.OrthographicCamera(window.innerWidth / -16, window.innerWidth / 16, window.innerHeight / 16, window.innerHeight / -16, -200, 500);
// camera.position.set(120, 60, 180); //设置相机位置
// camera.lookAt(scene.position); //设置相机方向
//创建一个一个视角
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
//设置视角离原点的位置(眼睛距离模型的距离)
// camera.position.z = 700;
camera.position.set(15,25,20);//设置相机位置
camera.lookAt(new THREE.Vector3(0, 0, 0)); // 让相机指向原点
//控制器
controls = new THREE.TrackballControls( camera );
//设置旋转速度
controls.rotateSpeed = 3;
// 使动画循环使用时阻尼或自转 意思是否有惯性
controls.enableDamping = true;
//是否可以缩放
controls.enableZoom = true;
//是否自动旋转
controls.autoRotate = true;
//设置相机距离原点的最近距离
controls.minDistance = 500;
//设置相机距离原点的最远距离
controls.maxDistance = 2000;
//是否开启右键拖拽
controls.enablePan = true;
// scene
scene = new THREE.Scene();
// const axesHelper = new THREE.AxesHelper();
// scene.add(axesHelper);
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
scene.add( ambientLight );
var axesHelper = new THREE.AxesHelper(15);
scene.add(axesHelper);
var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( pointLight );
// pointLight.position.set(0,0,20100);
// camera.position.set(10,10,10);
// camera.lookAt(10,10,10);
scene.add( camera );
// var mesh=new THREE.Object3D (mtlLoader);//网格模型对象
// scene.add(mesh);//网格模型添加到场景中
renderer = new THREE.WebGLRenderer({antialias: false,
alpha: true}); // 设置透明);
// 设置分辨率
renderer.setPixelRatio( window.devicePixelRatio );
// 设置渲染尺寸
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
orbitControls = new THREE.OrbitControls(camera,renderer.domElement);
orbitControls.enableDamping = true;
orbitControls.enableZoom = true;
orbitControls.autoRotate = false;
orbitControls.autoRotateSpeed = 3;
orbitControls.enablePan = true;
orbitControls.enableKeys = true;
orbitControls.keyPanSpeed = 7;
orbitControls.keys = {
LEFT:37,
UP:38,
RIGHT:39,
BOTTOM:40
}
controls =orbitControls;
// model 开始创建模型
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round( percentComplete, 2 ) + '% downloaded' );
}
};
//报错通知
var onError = function ( xhr ) {
console.log("error!");
};
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
// 加载mtl
var mtlLoader=new THREE.MTLLoader()
.setPath( './objmtl/' )
.load( 'iron.mtl', function ( materials ) {
materials.preload();
// 加载obj
new THREE.OBJLoader()
.setMaterials( materials )
.setPath( './objmtl/' )
.load( 'iron.obj', function ( object ) {
object.position.y = - 95;
console.log("print obj:" , object);
// object.children[0].geometry.center();
// 设置旋转中心点
object.children[0].geometry.computeBoundingBox();
// console.log("23123123", object.children[0].geometry.computeBoundingBox());
object.children[0].geometry.center();
// object.children[0].scale.set(200,200,200);
object.position.y = 0;
console.log("111",object.children[0].geometry.boundingBox.max.x,"ininn",object.children[0].geometry.boundingBox.min.x);
console.log("222",object.children[0].geometry.boundingBox.max.y,"ininn",object.children[0].geometry.boundingBox.min.y);
console.log("333",object.children[0].geometry.boundingBox.max.z,"ininn",object.children[0].geometry.boundingBox.min.z);
console.log("444",object.children[0].geometry.center());
// object.position.y = 0;
console.log("position()",object.position);
// object.scale.set(200,200,200);
object.position.set(0,0,0);
scene.add( object );
function animate() {
controls.update();
requestAnimationFrame( animate );
object.rotateY(0.1);//每次绕y轴旋转0.01弧度
renderer.render( scene, camera );
}
animate();
}, onProgress, onError );
} );
// 自适应监听
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX ) / 2;
mouseY = ( event.clientY - windowHalfY ) / 2;
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
render();
</script>
</body>
</html>
下面是打印的log
可以看到模型已经加载完毕,且包围框的最大最小值都是有值的,且可以加载的obj模型打印出的log也差不多,但是我注意到一点,可以正常显示的obj模型的包围框的最大最小值是远大于上面那张显示不出的,见下图:
看111 222 333那几行的log可以看出要比第一张大很多,所以怀疑是不是由于模型太小了在Three.js的坐标系中无法找到(在obj文件中的v参数也可以看出这一点),于是向调整相机位置、放大模型,寻找模型中心点等操作,参考以下文章:
Three.js加载.obj和.mtl文件(无法加载材质、路径错误问题
vue+three.js导入obj模型不显示问题
使用three.js加载obj+mtl模型完整案例
尝试以上方法后仍然不能解决问题。ε=(´ο`*)))
看log认为实际上已经加载进three.js了,博主偶然发现贴图指定错误后原来可以显示的模型也无法显示了,所以会不会贴图的问题?
于是博主修改代码,只加载obj不加载mtl文件,代码如下:
new THREE.OBJLoader()
.setPath( './objmtl/' )
.load( 'oursIron_original.obj', function ( object ) {
object.position.y = - 95;
object.children[0].geometry.computeBoundingBox();
object.children[0].geometry.center();
// object.children[0].scale.set(200,200,200);
object.position.y = 0;
object.scale.set(4,4,4);
object.position.set(0,0,0);
scene.add( object );
发现竟然显示出来了,是一个没有贴图的白色模型,那也就是说是贴图问题导致obj在three.js中无法加载。
这里首先要了解mtl文件中各个参数的含义,这里参考博客:
obj文件、mtl文件结构说明
mtl文件详解
three.js 为obj模型设置mtl后模型不显示问题
重点是最后一篇博客,评论区有一条是:
打开mtl文件,删除TR 那一行的值即可(我的问题是这样解决的)
https://stackoverflow.com/questions/46916134/mesh-disappears-after-setting-material-obj-mtl-using-three-js
博主打开自己的mtl文件发现果然Tr值为1,Tr是透明度的意思。。。改为0后终于显示出来了!查看了其他加载不出来的模型的mtl文件发现Tr值都为1。。
虽然最后解决问题的方式看起来简单,但是博主花了好大力气才知道这个解决办法,从一头雾水一点点排查也着实不容易,以此记录希望可以帮助到以后的同学,也非常感谢大家可以看到这里。
最后放上加载出来的模型截图: