Three.js教程(6):几何体

之前的章节中我们使用了平地、方块、球体等几何体(Geometry),今天我们探讨更多的几何体
先说一个事实,在WebGL中只能绘制3种东西,分别是点、线和三角形。什么?我们之前做的方块和球体,明明就不是三角形呢?其实他们确实是由三角形组成的。多个小的三角形就是可以组成包括球体以内的几乎任何几何体。我们先从简单的例子开始今天的课程吧。


PlaneGeometry

PlaneGeometry就是一个平地,我们直接看例子吧:

1
2
3
4
5
6
7
8
var geometry = new THREE.PlaneGeometry(30, 30, 10, 10);
var material = new THREE.MeshBasicMaterial({ color:'#ff0000'});
material.wireframe = true;
mesh = new THREE.Mesh(geometry, material);
// 由于平地添加后默认是在正前方 所以需要旋转一下
mesh.rotation.x = -0.5 * Math.PI;
mesh.position.y = -10;
scene.add(mesh);

PlaneGeometry的构造函数有四个参数,分别是长、宽、长的段数和宽的段数;这里长分成了10段,宽也分成了10段。另外我们这里使用了材质MeshBasicMaterial,其中wireframefalse表示只显示空的框架。MeshBasicMaterial的更多细节将在下章讨论。此时的效果如下,我们可以很清楚的看到平地是由三角形构成的。

PlaneGeometry_1

由于平地添加后默认和电脑屏幕是一个平面,我们这里需要在下方,所以需要走旋转:mesh.rotation.x = -0.5 * Math.PI;

我们上面的代码添加了一块平地,但是不利于调试,现在我们调整代码,使用gui来管理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
var step = 0;

function createMesh(geometry) {
var material = new THREE.MeshBasicMaterial({
color:'#ff0000'
});
material.wireframe = true;
var mesh = new THREE.Mesh(geometry, material);
return mesh;
}

var obj = {
width: 30,
height: 30,
widthSegments: 10,
heightSegments: 10,
getGeometry (){
return new THREE.PlaneGeometry(this.width, this.height, this.widthSegments, this.heightSegments);
},
update () {
if (mesh) {
// 先删除
scene.remove(mesh);
// 后创建一个新的
mesh = createMesh(this.getGeometry());
// 再添加到场景中
scene.add(mesh);
}
},
};

// 添加一片平地
mesh = createMesh(obj.getGeometry());
scene.add(mesh);

gui.add(obj, 'width', 0, 40).onChange(function () {
obj.update();
});
gui.add(obj, 'height', 0, 40).onChange(function () {
obj.update();
});
gui.add(obj, 'widthSegments', 0, 20).onChange(function () {
obj.update();
});
gui.add(obj, 'heightSegments', 0, 20).onChange(function () {
obj.update();
});

function animate() {
stats.update();

// 添加了一行控制旋转的代码
mesh.rotation.y = step += 0.01;

requestAnimationFrame( animate );

renderer.render( scene, camera );
}

上述createMesh用来创建一个mesh;obj对象是gui的控制器对象,其中getGeometry方法是用来获取Geometry对象,update函数用来更新几何体;最后在animate添加代码,用来控制mesh旋转。此时的效果如下,你可以修改参数来更新mesh:

PlaneGeometry_2

CircleGeometry

CircleGeometry是一种圆形的平面几何体。CircleGeometry构造方法的参数有四个,分别是radius,表示圆形的半径;segments,表示分为几段,默认是8段;thetaStart表示起始的弧度,默认是0;thetaLength表示总共的弧度,默认是2 * Math.PI也就是一个圆,我们先来看个例子,这个例子就是在上一个例子中修改obj对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 var obj = {
radius: 10,
segments: 8,
thetaStart: 0,
thetaLength: 2 * Math.PI * 3 / 4,
getGeometry (){
return new THREE.CircleGeometry(this.radius, this.segments, this.thetaStart, this.thetaLength);
},
update () {
if (mesh) {
// 先删除
scene.remove(mesh);
// 后创建一个新的
mesh = createMesh(this.getGeometry());
// 再添加到场景中
scene.add(mesh);
}
},
};

这里我们画了一个3/4圆,你可以设置segments,你会发现当小于3的时候也会按照3个来绘制的,如果是小数,Three.js也会转化为整数(向下取整)来处理,但是最好还是传入的就是整数,因为有的几何体传入小数的段数会报错。效果如下:

CircleGeometry

RingGeometry

RingGeometry是一种环状的平面几何体。RingGeometry的构造方法有6个参数,分别是innerRadius,表示内圆半径;outerRadius,表示外圆半径;thetaSegments,表示分成几个三角形,默认是8个,最小3个,与上面是一样的;phiSegments表示半径方向分为多少个三角形,最小是1个,默认也是8个;后两个是thetaStartthetaLength、跟上面是一样的。我们再修改一下obj对象,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var obj = {
innerRadius: 5,
outerRadius: 10,
thetaSegments: 8,
phiSegments: 8,
thetaStart: 0,
thetaLength: 2 * Math.PI * 3 / 4,
getGeometry (){
return new THREE.RingGeometry(
this.innerRadius,
this.outerRadius,
Math.round(this.thetaSegments),
Math.round(this.phiSegments),
this.thetaStart,
this.thetaLength
);
},
update () {
if (mesh) {
// 先删除
scene.remove(mesh);
// 后创建一个新的
mesh = createMesh(this.getGeometry());
// 再添加到场景中
scene.add(mesh);
}
},
};

RingGeometry

BoxGeometry

上面我们说的都是平面几何体,现在看看三维几何体,首先来看的是BoxGeometry,这个几何体我们前面见得挺多的,就是一个长方体。他的构造方法有6个参数,分别是长宽高,和长宽高的段数,默认值都是1。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var obj = {
width: 10,
height: 10,
depth: 10,
widthSegments: 1,
heightSegments: 1,
depthSegments: 1,
getGeometry (){
return new THREE.BoxGeometry(
this.width,
this.height,
this.depth,
Math.round(this.widthSegments),
Math.round(this.heightSegments),
Math.round(this.depthSegments),
);
},
update () {
if (mesh) {
// 先删除
scene.remove(mesh);
// 后创建一个新的
mesh = createMesh(this.getGeometry());
// 再添加到场景中
scene.add(mesh);
}
},
};

运行结果如下:

BoxGeometry

SphereGeometry

SphereGeometry是一个球体几何体。构造方法参数分别是:radius表示半径;widthSegments表示水平方向段数;heightSegments表示垂直方向的段数;phiStart表示水平方向的起始弧度,默认0phiLength表示水平方向的总弧度,默认Math.PI * 2thetaStart表示垂直方向的起始弧度,默认0thetaLength表示垂直方向的总弧度,默认Math.PI。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var obj = {
radius: 10,
widthSegments:8,
heightSegments: 8,
phiStart: 0,
phiLength: 2 * Math.PI,
thetaStart: 0,
thetaLength: Math.PI,
getGeometry (){
return new THREE.SphereGeometry(
this.radius,
Math.round(this.widthSegments),
Math.round(this.heightSegments),
this.phiStart,
this.phiLength,
this.thetaStart,
this.thetaLength,
);
},
update () {
if (mesh) {
// 先删除
scene.remove(mesh);
// 后创建一个新的
mesh = createMesh(this.getGeometry());
// 再添加到场景中
scene.add(mesh);
}
},
};

运行结果如下:

SphereGeometry

更多几何体

我们上面讲了5种几何体,估计你也知道了创建几何体的套路了,其他几何体的创建方式和上面的基本一致,这里就不做更多的叙述了。Three.js还提供的几何体有:ConeGeometryCylinderGeometryDodecahedronGeometryExtrudeGeometryIcosahedronGeometryLatheGeometryOctahedronGeometryParametricGeometryPolyhedronGeometryShapeGeometryTextGeometryTetrahedronGeometryTorusGeometryTorusKnotGeometryTubeGeometry等。由于篇幅有限就不一一展开说了。当然Three.js不仅仅可以使用给出的几何体,甚至还可以自定义几何体,最重要的是还可以导入其他建模软件做出来的模型,这一点是非常厉害的。

-------------本文结束 感谢您的阅读-------------
0%