Three.js入门 (参考胖达老师的B站视频) | 大帅老猿threejs特训
第一天 Three.js基础
空间坐标系
右手坐标系,threejs朝上是Y,朝右是X,朝屏幕外面是Z,Blender朝上是Z
Blender视图基本操作
A 全选
AA 取消全选(按两次A)
Shift +D 复制物体(右键或者ESC取消移动)
Shift+鼠标中键盘 移动视角
鼠标滚轮 推拉视角
鼠标中键按住 旋转视角
G grab 移动
S scale 缩放
R rotate 旋转
小键盘 . 聚焦选中物体
X 或 Delete 删除
Shift + A 添加模型
TAB 编辑模式/物体模式切换
TAB模式下 1 2 3 切换 点 线 面 几种选择模式
环选边 Alt+ 点击边(编辑模式--边模式下)
Ctrl + B 切角 (编辑模式-选中切角边,滚动鼠标中键可以增减分段数)
M 合并(焊接)顶点
/ 独立显示选中物体,恢复显示全部
编辑模式 tab
内插面 i
挤出 e
移动 g(再按 x、y、z 锁定到对应轴)
旋转 r
缩放 s
删除点线面 x 或 Del
如果是录视频,可以先安装Screencast Keys插件,这个插件从github下面去下载 https://github.com/nutti/Screencast-Keys
甜甜圈
打开Blender,导入原始没有处理过的模型 donuts_原始未处理.glb
Mac Book上面可以用 Shift + 右键 移动视角, Control + 右键 推拉视角
这时缩小的时候,远处有一部分看不到,是因为甜甜圈的尺寸太大,观察视图的远裁剪面裁剪造成的。
Shift + A 添加一个立方体(Cube),这个时候发现新加的立方体很小,是甜甜圈太大了。删除立方体,用A键选择所有,或者用Select Hierarchy选中甜甜圈
使用缩放工具Scale,可以同时选中X,Y,Z,然后输入0.001,缩小1000倍。如果要让甜甜圈回到视角中心,用小键盘的.这个键或者Shift + C
参考高两米的立方体,进一步用鼠标调整尺寸到合适的大小,调整好尺寸后,要应用一下,使用Control + A, 然后选Rotate and Scale把尺寸缩放应用到物体上。这个时候,视图缩放不会看到被裁剪了。
然后要对甜甜圈进行拆分,因为每个甜甜圈单独掉落。
用tab键进入编辑模式,用1,2,3选不同的模式
然后用左边栏的Cursor图标,从顶部选,然后点右键,选拆分
拆分完成后,可以在Blender里面直接做出下落的动画。如果已经有动画,可以先清一下,删除关键帧。
先给每个甜甜圈加上刚体Rigid Body,然后选托盘,托盘设为被动刚体。这样就可以放出动画了。
然后可以把这个动画烘焙到关键帧,选中所有甜甜圈,Layout --- Object --- Rigid Body --- Bake to Keyframes
导入threejs,创建三大件
先创建场景THREE.Scene
然后创建透视相机PerspectiveCamera,第一个参数fov是广角
接着是WebGLRenderer
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10)
const renderer = new THREE.WebGLRenderer({ antialias: true})
renderer.setSize(window.innerWidth, window.innerHeight) // 场景大小可以超过屏幕,可以是div对应的大小
document.body.appendChild(renderer.domElement)
灯光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.2) // 0.4
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6) // 1
scene.add(directionalLight)
加入物体 boxMesh 由boxGeometry和boxMaterial组成,例如
const boxGeometry = new THREE.BoxGeometry(1, 1, 1) // 宽 高 深
const boxMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00}) // 绿色 明显一点
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial)
scene.add(boxMesh)
这个时候用npm start运行出来是黑的,原因是相机的位置和角度不对
这个时候用threejs.org/editor来调试排查一下
先加一个box,然后再加一个环境光,饱和度Intensity设为0.5
然后加一个PerspectiveCamera,此时相机相当于扣到盒子里了
在三维图形里面,平面都不是双面显示。加入一个平面,把这个平面的Y坐标设为3,与box分开。然后把环境光调亮到2.2,如果从正面可以看到这个面,反面看就是透明的。这个叫背面剔除,背面就不显示了。当然代码或者unity3d里面可以特殊处理,把平面设为双面显示。
当切换到透视相机,相机在盒子里面,从中心往外看,全是透明,所以一片漆黑。
现在把透视相机的Z坐标改为2,拉出盒子,然后从透视相机看,就可以看到盒子了。
右手坐标系,threejs朝上是Y,朝右是X,朝屏幕外面是Z,Blender朝上是Z
回到VS Code把相机位置改一下 camera.position.set(0, 0, 2), 就可以看到盒子的一个面,绿色的方形了。此时要注意数据类型,比如字符串或者undefined错误的传到数值参数,整个就是黑的,看不到。可以考虑用TypeScript
此时box不能动,需要加入控制相机,可以用现成例子里面的 OrbitControls, 这样可以鼠标拖着物体缩放和旋转。
接着把box相关的代码去掉,加入甜甜圈模型
new GLTFLoader().load('../resources/models/donuts.glb', (gltf) => {
scene.add(gltf.scene);
})
现在可以在页面里面看到甜甜圈的模型了,但是颜色和光线都不对,和实物差距太大
可以用console.log(gltf)来看甜甜圈的js对象是什么结构,每个甜甜圈的名字和Blender里面是对应的,但是Blender里面名字不能超过20个字符
同时可以看到js对象里面还有一个名叫"柱体"的圆的底板,可以把visible设为false, gltf.scene.children.find(x => x.name === '柱体').visible = false
也可以看到animations数组里面有6个动画AnimationClip
还有userData可以用来存放一些自定义的数据
可以用gltf.scene.traverse()来遍历整个对象树来对每个子对象