赞
踩
近期在做三维重建项目,需要把最终生成的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。。
虽然最后解决问题的方式看起来简单,但是博主花了好大力气才知道这个解决办法,从一头雾水一点点排查也着实不容易,以此记录希望可以帮助到以后的同学,也非常感谢大家可以看到这里。
最后放上加载出来的模型截图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。