「这是我参与2022首次更文挑战的第35天,活动详情查看:2022首次更文挑战」
示例代码采用three.js-r73版本: cdnjs.cloudflare.com/ajax/libs/t…
上一节我们主要做了将obj模型加载到场景中,并且给模型添加了纹理贴图,这节我们来具体讲述下OBJLoader使用过程中需要注意的一些问题。让我们来看看吧。
使用blender查看obj模型
- 我们可以使用一些3D模型制作软件来查看obj模型,比如blender
- 选择文件->导入->导入
.obj
文件,选择我们的obj模型文件进行导入
- 导入效果
- 这也说明了我们的模型本身是没有纹理贴图的(没有穿衣服),如果想让它变得好看就需要添加纹理贴图
- 没有贴图的模型,我们也称为白模
使用OBJLoader加载模型
- 我们的OBJLoader源码的load部分和VTKLoader是差不多的,我们这里使用了自定义的loader管理器,以及监听加载进度
自定义loader管理器
- 稍后传给OBJLoader
var manager = new THREE.LoadingManager();
manager.onProgress = function (item, loaded, total) {
console.log(item, loaded, total);
}
复制代码
加载模型资源,监听模型加载进度
var objLoader = new THREE.OBJLoader(manager)
objLoader.setCrossOrigin("Anonymous"); // 解决跨域问题
objLoader.load(`${base_url}/models/obj/male02/male02.obj`, function (object) {
....
// 处理模型数据
}, onProgress, onError)
// 加载模型进度
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) {
}
复制代码
lengthComputable
我们通过获取xhr可以看到这个属性,当这个属性为true时,说明模型数据长度可以计算- 通过计算
加载的数据/总数据
可以计算当前加载的百分比
处理模型数据
- 模型加载完成以后,我们可以拿到一个object对象,这个对象就是模型对象。它是一个Object3D
objLoader.load(`${base_url}/models/obj/male02/male02.obj`, function (object) {
console.log(object);
// 遍历子模型
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = texture
}
})
object.position.y = -80
scene.add(object)
}, onProgress, onError)
复制代码
- object.traverse()方法继承自Object3D,主要用来遍历子模型
traverse: function ( callback ) {
// 回调函数传递自身
callback( this );
var children = this.children;
for ( var i = 0, l = children.length; i < l; i ++ ) {
// 遍历子模型递归调用
children[ i ].traverse( callback );
}
},
复制代码
- 这个方法首先通过回调,把自身(object)传递过去
- 然后递归遍历子object
- 达到遍历所有子模型的目的
- 如果子模型属于网格模型,那么就给他的
material.map
添加纹理贴图,这样我们的模型就有纹理贴图了(有衣服穿了)
为什么要遍历子模型
- 通过blender查看,我们的一个模型是由很多个部分组成的
- 现在我选中的部分是模型的身体,也就是左侧黄色钩边部分,如果我们删掉,会看到还有其他部分。
- 所以我们要遍历所有的子模型,给每个模型都添加纹理贴图