后端 boy 因业务需求不得不学习 Three.js.将三维模型加载到 web 浏览器展示即可.
操作路线:
1 下载官方 demo,打开,运行正常,可见效果
2 网上下载.obj .mtl 文件替换官方例子,打开,可见效果 试了二个
3 建模师提供的 obj 文件,使用电脑 3d 可打开,证明模型文件没问题,用 three.js 打开,看不到效果图,f12 也没报错信息,猜测:1 加载出错?2 灯光角度大小问题导致我看不到模型?
4 贴上控制台信息
Using OBJLoader2 version: 3.2.0
verify.html?_ijt=9h2s3381ah9lvusnfe2lvi6sk7:233 Starting initialisation phase...
verify.html?_ijt=9h2s3381ah9lvusnfe2lvi6sk7:183 Progress: Loading: verificationCubes
OBJLoader2.js:342 Parsing arrayBuffer...
OBJLoader2Parser.js:324 OBJLoader.Parser configuration:
materialNames:
- attr_0
- defaultMaterial
- defaultVertexColorMaterial
- defaultLineMaterial
- defaultPointMaterial
materialPerSmoothingGroup: false
useOAsMesh: true
useIndices: false
disregardNormals: false
callbacks.onProgress: onProgress
callbacks.onAssetAvailable: defaultOnAssetAvailable
callbacks.onError: onError
OBJLoader2Parser.js:1109 Global output object count: 1
OBJLoader2Parser.js:1116 Overall counts:
Vertices: 1806
Faces: 1806
Multiple definitions: 0
OBJLoader2Parser.js:389 OBJLoader2Parser.execute: 23.46533203125 ms
OBJLoader2.js:358 OBJLoader parse: verificationCubes: 24.51318359375 ms
verify.html?_ijt=9h2s3381ah9lvusnfe2lvi6sk7:162 Loading complete: verificationCubes
verify.html?_ijt=9h2s3381ah9lvusnfe2lvi6sk7:183 Progress:
现在不知道怎么办才好.初步的想法就是可以加载成功就行.后期再去完善其他.求大佬指点
1
misdake 2020-10-18 12:47:07 +08:00 1
可以尝试一下导入到官方 editor 里看看效果: https://threejs.org/editor/
如果能看到,说明 threejs 本身应该是支持的,但是可能是你的项目中的物体位置(比如三角形不在视野内)、相机(比如 clearcolor 黑色,物体也是黑色导致看不出来)或者灯光(比如物体本应不黑但是没有光照导致是黑的)有什么问题。 如果看不到,说明导出的 obj 或 mtl 格式可能有某种不兼容(但不报错)的情况(比如材质透明了或者没设置上)。 |
2
xiaoming1992 2020-10-18 12:54:14 +08:00 via Android 1
你要注意,还有以下几种可能,会导致看不到模型:
1. 模型的实际位置离摄像机很远,在摄像机的视野外 2. 模型在 threejs 中的单位太小(例如 0.0001,只能看到一个小点,你肉眼看不到)或太大(摄像机视野内恰好只能看到模型的缝隙) 3. 模型不在原点,且摄像头看向了其他方向 以上情况我都实际碰见过的,所以要求导出模型时规范些 |
3
xiaoming1992 2020-10-18 13:00:26 +08:00 via Android 1
还有感觉 threejs 的问题可以发到官方论坛,一方面那里的人都是做这个的,另一方面官方论坛的气氛特别好,特别热心,基本很少有提问不被解答的,而 v2 接触过 threejs 的相对应该比较少吧。 以前经常逛的,现在不做这方面了才逛得少了
|
4
beginor 2020-10-18 14:22:27 +08:00 via Android 1
控制台信息应该是没有错误的, 但是仅凭这些信息很难诊断出具体的原因。
如果有可能的话可以把网页脚本和文件都放在互联网上,这样大家才能更容易帮到你。 |
5
beginor 2020-10-18 14:27:42 +08:00 via Android 1
发错了, 应该是有错,因为出现了 onError
|
6
hgjian 2020-10-18 15:33:45 +08:00 via Android 1
你可以看看 360 开源的框架哦:
https://spritejs.org |
7
lhx880619 2020-10-18 16:29:38 +08:00 via Android 1
现在建议直接 gltf 模型了 另外 BabylonJS 也是个不错的选择 对于没有 3d 基础的 感觉你还有很长的路走。。。
|
9
tangchi695 2020-10-18 16:54:44 +08:00
@lhx880619 没基础你让人用 Babylon😂
|
10
tangchi695 2020-10-18 16:59:07 +08:00
加载自己的模型看不到,先给灯光,再缩放模型,放大到 10 倍 100 倍率,或者缩小,或者加一个 axeshelper 定位看看在哪儿,加载器加载的回调里打印下结果,看看加载的结果是什么,成功和错误的回调都要打印。
|
11
alw 2020-10-19 08:39:02 +08:00
1.windows10 自带 3d 查看器,可以直接双击打开看模型。
2. 调灯光,否则有可能是黑色,黑色物体混在黑色背景,看个毛线。 用这句统一变成不受光影响的基本色试试: `scene.overrideMaterial = new THREE.MeshBasicMaterial( { color: 'green' } );` 3. 调摄像头坐标,模型太大,摄像头有可能有物体内部,或者超出了摄像头的可视范围。 建议先用 3D 模型建一个 长宽高各一米的立方体来测试,验证以上三点之后,再调试设计师的模型,主要是搞清模型大小,摄像头应该放哪个位置等问题。 |
12
LyleRockkk 2020-10-19 09:19:59 +08:00
能不能贴一下加载模型的 js 代码,obj 格式的加载都不用过多设置,模型没问题多半是相机设置的有问题,画面中看不到模型
|
13
yuxi521 OP @LyleRockkk
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - 2/OBJLoader verification</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: #F5F5F5; color: #fff; margin: 0 0 0 0; padding: 0 0 0 0; border: none; cursor: default; } #info { color: #fff; position: absolute; top: 10px; width: 100%; text-align: center; z-index: 100; display:block; } #info a { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer } #glFullscreen { width: 100%; height: 100vh; min-width: 640px; min-height: 360px; position: relative; overflow: hidden; z-index: 0; } #example { width: 100%; height: 100%; top: 0; left: 0; background-color: #555555; } #feedback { color: darkorange; } #dat { user-select: none; position: absolute; left: 0; top: 0; z-Index: 200; } </style> </head> <body> <div id="glFullscreen"> <canvas id="example"></canvas> </div> <div id="dat"> </div> <div id="info"> <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - OBJLoader2/OBJLoader verification <div id="feedback"></div> </div> <script type="module"> 'use strict'; import { AmbientLight, DirectionalLight, GridHelper, PerspectiveCamera, Scene, Vector3, WebGLRenderer } from "../../../../build/three.module.js"; import { TrackballControls } from "../../../jsm/controls/TrackballControls.js"; import { MTLLoader } from "../../../jsm/loaders/MTLLoader.js"; import { MtlObjBridge } from "../../../jsm/loaders/obj2/bridge/MtlObjBridge.js"; import { OBJLoader } from "../../../jsm/loaders/OBJLoader.js"; import { OBJLoader2 } from "../../../jsm/loaders/OBJLoader2.js"; const OBJLoaderVerify = function ( elementToBindTo ) { this.renderer = null; this.canvas = elementToBindTo; this.aspectRatio = 1; this.recalcAspectRatio(); this.scene = null; this.cameraDefaults = { posCamera: new Vector3( 0.0, 175.0, 500.0 ), posCameraTarget: new Vector3( 0, 0, 0 ), near: 0.1, far: 10000, fov: 45 }; this.camera = null; this.cameraTarget = this.cameraDefaults.posCameraTarget; this.controls = null; }; OBJLoaderVerify.prototype = { constructor: OBJLoaderVerify, initGL: function () { this.renderer = new WebGLRenderer( { canvas: this.canvas, antialias: true, autoClear: true } ); this.renderer.setClearColor( 0x050505 ); this.scene = new Scene(); this.camera = new PerspectiveCamera( this.cameraDefaults.fov, this.aspectRatio, this.cameraDefaults.near, this.cameraDefaults.far ); this.resetCamera(); this.controls = new TrackballControls( this.camera, this.renderer.domElement ); let ambientLight = new AmbientLight( 0x404040 ); let directionalLight1 = new DirectionalLight( 0xC0C090 ); let directionalLight2 = new DirectionalLight( 0xC0C090 ); directionalLight1.position.set( -100, -50, 100 ); directionalLight2.position.set( 100, 50, -100 ); this.scene.add( directionalLight1 ); this.scene.add( directionalLight2 ); this.scene.add( ambientLight ); let helper = new GridHelper( 1200, 60, 0xFF4444, 0x404040 ); this.scene.add( helper ); }, initContent: function () { let modelName = 'verificationCubes'; this._reportProgress( { detail: { text: 'Loading: ' + modelName } } ); let objLoader = new OBJLoader(); let objLoader2 = new OBJLoader2(); objLoader2.setModelName( modelName ); objLoader2.setLogging( true, false ); objLoader2.setUseOAsMesh( true ); let scope = this; let callbackOnLoad = function ( object3d ) { scope.scene.add( object3d ); console.log( 'Loading complete: ' + modelName ); scope._reportProgress( { detail: { text: '' } } ); }; let onLoadMtl = function ( mtlParseResult ) { objLoader.setMaterials( mtlParseResult ); objLoader.load( './mod1.obj', function ( object ) { object.position.y = -100; scope.scene.add( object ); } ); objLoader2.addMaterials( MtlObjBridge.addMaterialsFromMtlLoader( mtlParseResult ) ); objLoader2.load( './mod1.obj', callbackOnLoad, null, null, null ); }; let mtlLoader = new MTLLoader(); mtlLoader.load( './mod1.mtl', onLoadMtl ); }, _reportProgress: function( event ) { let output = ( event.detail !== undefined && event.detail !== null && event.detail.text !== undefined && event.detail.text !== null ) ? event.detail.text : ''; console.log( 'Progress: ' + output ); document.getElementById( 'feedback' ).innerHTML = output; }, resizeDisplayGL: function () { this.controls.handleResize(); this.recalcAspectRatio(); this.renderer.setSize( this.canvas.offsetWidth, this.canvas.offsetHeight, false ); this.updateCamera(); }, recalcAspectRatio: function () { this.aspectRatio = ( this.canvas.offsetHeight === 0 ) ? 1 : this.canvas.offsetWidth / this.canvas.offsetHeight; }, resetCamera: function () { this.camera.position.copy( this.cameraDefaults.posCamera ); this.cameraTarget.copy( this.cameraDefaults.posCameraTarget ); this.updateCamera(); }, updateCamera: function () { this.camera.aspect = this.aspectRatio; this.camera.lookAt( this.cameraTarget ); this.camera.updateProjectionMatrix(); }, render: function () { if ( ! this.renderer.autoClear ) this.renderer.clear(); this.controls.update(); this.renderer.render( this.scene, this.camera ); } }; let app = new OBJLoaderVerify( document.getElementById( 'example' ) ); let resizeWindow = function () { app.resizeDisplayGL(); }; let render = function () { requestAnimationFrame( render ); app.render(); }; window.addEventListener( 'resize', resizeWindow, false ); console.log( 'Starting initialisation phase...' ); app.initGL(); app.resizeDisplayGL(); app.initContent(); render(); </script> </body> </html> |
14
nsjs 2020-10-19 14:31:09 +08:00
微软自带的能打开并不能说明模型没有问题,每个模型解析器的实现都不一样的,微软的那个实现比较弱
各家的东西都或多或少有些不兼容的情况的 obj 在 3dmax 里导出的时候也有很多选项的,你得反复测试不同的组合 threejs 的解析不出来你可以试试别家的,babylonjs 和 cesium 都可以解析 obj 模型文件,这 2 个都是 js 库 桌面软件的话你可以下载一个 blender 试试能不能加载 |
15
nsjs 2020-10-19 14:35:08 +08:00
看了你加载的代码,你是设置了相机位置并且看向原点的
obj 格式是不含相机信息的,我觉得最有可能的就是模型没有归到原点 你可以问问建模的人 |
16
nsjs 2020-10-19 14:38:53 +08:00
然后是你的相机位置离中心 500 米开外,模型如果只有 1 米不到的大小看不见很正常
还有建模软件里单位设置得设置成米,否则有缩放的 |
17
GressJoe 2020-10-19 15:28:32 +08:00
obj 用文本编辑器打开看看坐标是多大数量级的
|