求助帖.Three.js

2020-10-18 12:33:48 +08:00
 yuxi521

后端 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: 

现在不知道怎么办才好.初步的想法就是可以加载成功就行.后期再去完善其他.求大佬指点

2950 次点击
所在节点    程序员
17 条回复
misdake
2020-10-18 12:47:07 +08:00
可以尝试一下导入到官方 editor 里看看效果: https://threejs.org/editor/
如果能看到,说明 threejs 本身应该是支持的,但是可能是你的项目中的物体位置(比如三角形不在视野内)、相机(比如 clearcolor 黑色,物体也是黑色导致看不出来)或者灯光(比如物体本应不黑但是没有光照导致是黑的)有什么问题。
如果看不到,说明导出的 obj 或 mtl 格式可能有某种不兼容(但不报错)的情况(比如材质透明了或者没设置上)。
xiaoming1992
2020-10-18 12:54:14 +08:00
你要注意,还有以下几种可能,会导致看不到模型:

1. 模型的实际位置离摄像机很远,在摄像机的视野外
2. 模型在 threejs 中的单位太小(例如 0.0001,只能看到一个小点,你肉眼看不到)或太大(摄像机视野内恰好只能看到模型的缝隙)
3. 模型不在原点,且摄像头看向了其他方向

以上情况我都实际碰见过的,所以要求导出模型时规范些
xiaoming1992
2020-10-18 13:00:26 +08:00
还有感觉 threejs 的问题可以发到官方论坛,一方面那里的人都是做这个的,另一方面官方论坛的气氛特别好,特别热心,基本很少有提问不被解答的,而 v2 接触过 threejs 的相对应该比较少吧。 以前经常逛的,现在不做这方面了才逛得少了
beginor
2020-10-18 14:22:27 +08:00
控制台信息应该是没有错误的, 但是仅凭这些信息很难诊断出具体的原因。

如果有可能的话可以把网页脚本和文件都放在互联网上,这样大家才能更容易帮到你。
beginor
2020-10-18 14:27:42 +08:00
发错了, 应该是有错,因为出现了 onError
hgjian
2020-10-18 15:33:45 +08:00
你可以看看 360 开源的框架哦:
https://spritejs.org
lhx880619
2020-10-18 16:29:38 +08:00
现在建议直接 gltf 模型了 另外 BabylonJS 也是个不错的选择 对于没有 3d 基础的 感觉你还有很长的路走。。。
yuxi521
2020-10-18 16:47:30 +08:00
@lhx880619 仅仅是加载下模型展示出来 也不知道难度,公司没这方面技术的同事,领导就派我上了,哎
tangchi695
2020-10-18 16:54:44 +08:00
@lhx880619 没基础你让人用 Babylon😂
tangchi695
2020-10-18 16:59:07 +08:00
加载自己的模型看不到,先给灯光,再缩放模型,放大到 10 倍 100 倍率,或者缩小,或者加一个 axeshelper 定位看看在哪儿,加载器加载的回调里打印下结果,看看加载的结果是什么,成功和错误的回调都要打印。
alw
2020-10-19 08:39:02 +08:00
1.windows10 自带 3d 查看器,可以直接双击打开看模型。
2. 调灯光,否则有可能是黑色,黑色物体混在黑色背景,看个毛线。
用这句统一变成不受光影响的基本色试试:
`scene.overrideMaterial = new THREE.MeshBasicMaterial( { color: 'green' } );`

3. 调摄像头坐标,模型太大,摄像头有可能有物体内部,或者超出了摄像头的可视范围。
建议先用 3D 模型建一个 长宽高各一米的立方体来测试,验证以上三点之后,再调试设计师的模型,主要是搞清模型大小,摄像头应该放哪个位置等问题。
LyleRockkk
2020-10-19 09:19:59 +08:00
能不能贴一下加载模型的 js 代码,obj 格式的加载都不用过多设置,模型没问题多半是相机设置的有问题,画面中看不到模型
yuxi521
2020-10-19 10:18:29 +08:00
@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>
nsjs
2020-10-19 14:31:09 +08:00
微软自带的能打开并不能说明模型没有问题,每个模型解析器的实现都不一样的,微软的那个实现比较弱
各家的东西都或多或少有些不兼容的情况的
obj 在 3dmax 里导出的时候也有很多选项的,你得反复测试不同的组合

threejs 的解析不出来你可以试试别家的,babylonjs 和 cesium 都可以解析 obj 模型文件,这 2 个都是 js 库
桌面软件的话你可以下载一个 blender 试试能不能加载
nsjs
2020-10-19 14:35:08 +08:00
看了你加载的代码,你是设置了相机位置并且看向原点的
obj 格式是不含相机信息的,我觉得最有可能的就是模型没有归到原点
你可以问问建模的人
nsjs
2020-10-19 14:38:53 +08:00
然后是你的相机位置离中心 500 米开外,模型如果只有 1 米不到的大小看不见很正常
还有建模软件里单位设置得设置成米,否则有缩放的
GressJoe
2020-10-19 15:28:32 +08:00
obj 用文本编辑器打开看看坐标是多大数量级的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/716084

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX