现在我们对three.js的基本元素与如何用three.js搭建场景有了一定的了解后,本篇我们开始搭建村落中山坡,房屋等对象。
ps:如果没看过第一篇的请移步这里
山坡与草皮
思路
从图中可以看出山坡mesh的geometry在three.js中并未直接提供,demo的思路是由基本几何体BoxGeometry变形而来。
这里说明一下,three.js构建的图形都有点(vertex),线(edge),面(face)三个属性:
如图所示移动box中对应点,可将box变形成最终所需的geometry:
代码
var geom = new THREE.BoxGeometry(basicWidth, groundDeep, basicHeight, 4, 1, 1)
// 改变矩形形状
geom.vertices[0].y += hillHeight
geom.vertices[1].y += hillHeight
geom.vertices[10].y += hillHeight
geom.vertices[13].y += hillHeight
geom.vertices[4].x += groundDeep
geom.vertices[5].x += groundDeep
var mat = new THREE.MeshStandardMaterial({
color: color.ground,
shading: THREE.FlatShading,
roughness: 1,
metalness: 0
})
this.mesh = new THREE.Mesh(geom, mat)
this.add(this.mesh)
使用相同的逻辑我们可以创建草皮元素
房屋
思路
房屋可以拆分成屋顶,窗户,门,墙,烟囱等部件
其中屋顶,和墙也是对基本几何体的变形,可以参考上一节的方法,这里就不再赘述。
下面我们说一说Group与ThreeBSP
Group与Merge
THREE.Group.apply(this, arguments)
查看源码可以发现一个经常被使用到的对象THREE.Group。
Group是一个组,其中可以容纳多个Mesh对象,并且如果我们对该group进行旋转,平移,缩放操作时,Group会相当于一个整体进行旋转,平移,缩放。
与之相似,Geometry对象提供了一个Merge方法,可以合并geometry。
它们之间的差异在于:
Group添加的是Mesh,而Merge作用的对象是Geometry;
即便添加到Group中,Group内的各个Mesh还可以被单独操作,使用Merge相当与合成了一个大的geometry对象,你无法在单独操作其中的geometry,对于创建后不需要再单独操作的对象使用Merge可以提升性能
ThreeBSP
ThreeBSP是一个用来创建geometry的Three.js的扩展库
用图来表示一下:
union方式用来得到geometry的合体(类似并集)
intersect方式用来得到交集
substract用来从Mesh中挖去另一个Mesh
用将大Box中挖去小box的思路,我们就可以穿件一个窗户的外框
镂空函数
// 镂空
function substractMesh(basic, substract, mat) {
var material = new THREE.MeshBasicMaterial()
var mesh1 = new THREE.Mesh(basic, material)
var mesh2 = new THREE.Mesh(substract, material)
var basicBSP = new ThreeBSP(mesh1)
var substractBSP = new ThreeBSP(mesh2)
var res = basicBSP.subtract(substractBSP)
res = res.toMesh()
res.geometry.computeFaceNormals()
res.geometry.computeVertexNormals()
res.material = mat
return res
}
如上,可以抽象出一个镂空函数来帮我们处理mesh
substractMesh函数将接收三个参数(被挖的Mesh,从中挖去的Mesh,最终Mesh的材质)
返回一个镂空后的Mesh
后记
这篇并没有像前篇一样全程代码,因为静态元素的构建过程真的大同小异全写出来不免枯燥,二来这也仅仅是个人的思路,而且条条大路通罗马,不应该束缚自己的想象力。
以上就是构建村庄中静态部件的思路,在下一章节我们会介绍复杂部件如云,森林是如何构建的
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。