赞
踩
本段内容会写在0篇以外所有的,本人所编写的Threejs教程中
对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久
如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS
本篇中将主要介绍如何加载模型,会使用到模型界中最通用的模型格式OBJ格式,但是OBJ格式并非我们实际开发中使用的理想格式,在下一篇中,我们会着重讲解GL格式的加载与获取方式,本篇的重点在于加载模型以及加载模型后的接下来一系列操作
案例代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas{ display: block; } body { margin: 0; overscroll-behavior: none; } #btns{ position: absolute; top:10%; width: 500px; height: 100px; left: 50%; transform:translateX(-50%); } </style> </head> <body> <div id="btns"></div> <!-- Import maps polyfill --> <!-- Remove this when import maps will be widely supported --> <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "three": "../../three.js-master/build/three.module.js" } } </script> <script type="module"> import * as THREE from '../../three.js-master/build/three.module.js'; import {OrbitControls} from "../../three.js-master/examples/jsm/controls/OrbitControls.js"; import {OBJLoader} from "../../three.js-master/examples/jsm/loaders/OBJLoader.js"; let scene,renderer,camera,orbitControls; function init(){ scene = new THREE.Scene(); renderer = new THREE.WebGLRenderer({ antialias:true }); renderer.setSize(window.innerWidth,window.innerHeight); document.body.appendChild(renderer.domElement); camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000); camera.position.set(10,10,10); orbitControls = new OrbitControls(camera,renderer.domElement); let helper = new THREE.AxesHelper(5); scene.add(helper); let light = new THREE.PointLight(); camera.add(light); scene.add(camera); } function addMesh(){ let loader = new OBJLoader(); loader.load("./tree.obj",(obj)=>{ console.log(obj); scene.add(obj); },null,(error)=>{ console.log("加载模型时出错,错误原因:"+error); }); } function render(){ renderer.render(scene,camera); requestAnimationFrame(render); } init(); addMesh(); render(); </script> </body> </html>
案例效果
这里我们使用的文件在threejs开发包中:three.js-master\examples\models\obj\tree.obj
引入我们的加载器,加载器一般都需要外部引入,如果是使用< script>引入,需要从以下地址引入
three.js-master/examples/js/loaders/OBJLoader.js
2023年1月6日追加:ThreeJS148版本不再支持< script src> 方式引入组件了,如有jquery开发者在学习本篇教程,请选用148以前的版本
import {OBJLoader} from "../../three.js-master/examples/jsm/loaders/OBJLoader.js";
接下来是声明我们的Loader
let loader = new OBJLoader();
如果你使用< script >引入则需要加上THREE前缀
//threejs148版本之后不再支持使用<script src="">方式引入组件
let loader = new THREE.OBJLoader();
构造器:new OBJLoader( manager );
manager:加载管理器,这个在后面的教程中会着重讲解,这里我们不需要填充它
接下来进入我们的加载过程,加载过程为异步,一定要搞清楚,这里是异步加载
loader.load("./tree.obj",(obj)=>{
//这里的代码在模型加载完成后才执行
console.log(obj);
scene.add(obj);
},null,(error)=>{
console.log("加载模型时出错,错误原因:"+error);
});
//这里的代码可能在模型加载完之前就执行,所以如果这里的代码涉及到模型处理
如果你对异步函数使用比较熟悉的话,你还可以使用异步函数来让代码更具有逻辑性,本段代码仅供初期学习时参考使用
//注意,Loader这个对象仅建议在全局上创建一个 let loader = new OBJLoader(); function loadModel(path){ return new Promise((resolve)=>{ loader.load(path,(obj)=>{ resolve(obj) }) }) } async function addMesh(){ let model = await loadModel("./tree.obj"); console.log(model); scene.add(model); }
还有一件事,养成好习惯,加载模型后console.log()一下你的模型
这里我们拿到的模型,是一个THREE.Group()对象,从文档得知,THREE.Group()是继承了Object3D的子类,所以我们可以直接将它添加到scene中
注意:不同的Loader加载完成后,交给我们的返回值,不一定都是一个THREE.Group对象,常见的obj格式一般是一个Group对象,STL是一个 Geometry,gl格式通常是一组数据等
这类错误一般可以在load()的第四个参数,onError这个函数中输出,根据函数的输出内容去判断问题在哪即可
加载模型一般是使用字符串来表示路径,最常见的错误就是路径写错,相对路径和绝对路径错误等等
3.1 首先是上面的养成好习惯,拿obj格式举例,obj格式加载出来是一个Group,那么我们可以展开它的Children属性,以及其下的children,先确认这里是否有Mesh存在,空的Group无论你怎么加载都不会加载任何东西的
前面讲到了OrbitControls【ThreeJS基础教程】1.1. 使用Helper让我们的开发变的更流畅,我们使用这个的视角旋转,缩放功能,来尽可能的扩大或者缩小范围去寻找我们的模型
在进行上述操作时,应尽可能大的增加相机的远端面和尽可能小的缩小近端面
camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,50000);
笔者这里使用的近端面为0.1,远端面为5万,如果还是找不到还能再扩大
还有一种方式,就是查看Mesh下的Attribute
展开模型下的任意Mesh,然后依次展开Geometry,attributes,position,array,查看里面的具体数字,如果里面的数字在小数点后好几位,那么我们需要对模型进行缩放操作后,更容易找到模型
上图为官方的模型的数据,这里的数据就属于偏小,此时,我们修改相机与模型的距离也可以,对模型进行缩放也可以,两种方式都可以增加你渲染出来的模型大小
//把相机放到距离模型足够近的位置
//这里需要多次调试才能找到比较完美的位置
camera.position.set(1,1,1);
//scale是一个Vector3对象,每一个Object3D对象均有一个scale属性
//将模型的x,y,z三个轴向均扩大10倍
model.scale.set(10,10,10);
如果你想整体等比缩放
model.setScalar(10);
根据你的实际情况去修改大小与相机位置即可
笔者这里不建议过多修改缩放,缩放值也受相对坐标影响,处理不好很容易造成某个模型过大或者过小的情况,模型大小应由建模师统一处理好后,交给程序,程序后续不应对scale做过多处理
函数:Vector3.set(x,y,z) 设置这个三维向量的值
函数Vector3.setScalar(scalar) 设置这个三维向量为同一个值
确认一下你的代码中是否添加了环境光源,如果没有环境光源,且你的背景是黑色的,那么模型实际上已经显示了,只是因为融入了背景所以你看不到
使用threejsEditor来查看模型是否可以被成功加载,如果在editor中都无法加载出来的话,那么该模型本身就是一个问题模型 threejs官方编辑器,在【ThreeJS基础教程】0.在学习使用ThreeJS之前中我们已经介绍了如何把editor在本地运行,如果直接打开官网速度太慢,我们可以使用本地版
还有一件事
官方亲切的提供了中文翻译版,也不用太担心这个editor难上手什么的
一定要有一个参照物,在【ThreeJS基础教程】1.1. 使用Helper让我们的开发变的更流畅中已经对常用的参照物做了介绍,参照物能帮助你更快的找到你的模型
很多新人在刚开始入坑threejs时,只知道怎么去加载模型,但是从来没有关注过模型标准这个东西,当没有模型标准时,我们的建模师又不是专业级的游戏建模师的话,我们就很容易遇到上面提到的那些错误,所以我们在使用模型前,最好是能和甲方,建模师他们确立一套模型标准,以最大程度的把这些繁冗的问题在建模软件中就处理好再使用会比较好
笔者在工作中合作的建模师,有很多都是那种出图的建模师,他们不会管你模型大了之后对程序有多少影响,他们会无脑的添加更多的素材进去,增加更多的点线面,然后让电脑花几个小时渲染一张牛逼的渲染成品图,这些建模师一般最终的成品都是一张图片,而非模型,这种模型用到程序中,出的问题多到能把一个新手完全劝退
关于建模师合作问题,笔者在后面模型的最优选的文章中会更多着墨
该标准为笔者3年来的经验之谈,仅供参考,详细的标准可以参考游戏建模标准
在threejs中,官方提供了一条能检索模型的方法
object.getObjectByName( name:String )
这个就是通过名称来检索模型内物体的,所以我们开发时怎么用,那么在跟建模师交流时,也应该严格要求对方把命名标准化
//假设我要求建模师把红绿灯都丢在了组里,并且进行了标准化命名
// TrafficLight
// - RoadATrafficLight
// - RoadBTrafficLight
let group = scene.getObjectByName('TrafficLight');
let roadATrafficLight = group.getObjectByName('RoadATrafficLight');
//这样就可以在众多的模型零件中,快速检索到我们需要控制的红绿灯
下一篇主要讲解loadingManager
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。