three.js学习之平面图形圆环和平面

特意看了一眼,从2022年8月19号开始写第一篇教程到今天,已经一个月零三天了。平均下来连三天一篇都做不到。进度缓慢的原因很多,自己面对的众多琐碎小事,工作的压力,在某些细节处被卡住等等。总之就是没有预想的顺利。本来我的计划是一个月将文字版教程写完,然后开始录制视频。按照目前的进度看来,显然是不可能的了。首先就是要写明白的东西比较多,限制篇幅可能会导致每一篇都很长,不利于阅读,然后就是我自己的时间精力也被自己高估了。不管怎么样,我都想坚持把three.js教程系列做完。这里我要手动@我的大学辅导员,他曾对我说,不管做什么,在大学坚持做完一件事都是很好的。可惜了,我大学做的事多,但是没有坚持下去的。

不接着说废话了,开始今天的学习内容。在开始之前,还是和之前一样,将three.js学习之常见几何体圆柱和球中的代码复制过来,然后删除掉圆柱和球相关的代码。

three.js基本图形之PlaneGeometry(平面)

three.js学习之常见几何体平面圆形和圆锥中,我们已经学习过一个平面图形平面圆形(CircleGeometry),现在我们来学习PlaneGeometry(平面)。PlaneGeometry(平面)是一个矩形平面,构建时传入参数如下:

  • width 平面沿着x轴的宽度,默认是1
  • height 平面沿着y轴的高度,默认是1
  • widthSegments 平面宽度分界线,默认是1
  • heightSegments 平面高度分界线,默认是1

看到这里,不知道有没人想起three.js学习之盒子中盒子来,如果我们将盒子中的参数depth放的足够小,是不是就是一个平面图形。感兴趣的可以自己去对比一下,当把depth设置为很小的时候,和PlaneGeometry(平面)有什么区别。

对于已经学过多个图元的我们来说,是不是感觉PlaneGeometry(平面)足够简单了。不管怎么样,咱们demo环节还是要有,不过PlaneGeometry(平面)只做一个demo,上代码:

1
2
3
4
5
6
7
8
9
const planeGeometry = new THREE.PlaneGeometry(3,3, 4, 4);
const planeMaterial = new THREE.MeshBasicMaterial({color: 0x00f5ff})
const plane1 = new THREE.Mesh(planeGeometry, planeMaterial)

const lineMaterial1 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const lineGeometry1 = new THREE.WireframeGeometry(planeGeometry)
const line1 = new THREE.Line(lineGeometry1, lineMaterial1)
group.add(plane1, line1)
scene.add(group)

PlaneGeometry(平面)的学习就到这里,接下来我们学习与平面圆形(CircleGeometry)类似的一个图形圆环RingGeometry。

three.js基本图形之RingGeometry(圆环)

创建圆环所需的参数及顺序如下:

  • innerRadius 内部空心圆的半径,默认值为0.5。
  • outerRadius 整个圆环的半径,默认为1.
    这里需要注意,内部圆的半径是0.5,外部是1,那么做出来的圆环半径,就等于圆的半径减去内环半径。
  • thetaSegments 圆的分段数,数值越大圆越圆。相应的,越小圆就🈷️不像圆。最小值为3,最大值为8.
  • phiSegments 圆环上的分段线,可以理解它将圆环分成了多个圆环,文档上说最小值是1,默认是8.但是实际上我在实际写代码的过程中发现,默认就是1.
  • thetaStart — 起始角度,默认值为0。
  • thetaLength — 角度大小,默认值为Math.PI * 2。

  • three.js基本图形之RingGeometry(圆环)基本用法

1
2
3
4
5
6
7
8
const ring1Geometry = new THREE.RingGeometry(1, 2); 
const ring1Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring1 = new THREE.Mesh(ring1Geometry, ring1Material)
const ringLineMaterial1 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry1 = new THREE.WireframeGeometry(ring1Geometry)
const ringLine1 = new THREE.Line(ringLineGeometry1, ringLineMaterial1)
group.add(ring1, ringLine1)
scene.add(group)

在基本用法中,我们只传入了圆环的内环和外环半径,内环半径为1,外环为2,因此内部空白圆心处为1,环为2。除了内外环半径外,我们其余参数都是默认的。可以发现thetaSegments确实是有8,但是phiSegments却是1。

接下来咱们看看设置了thetaSegments和phiSegments的情况

  • three.js基本图形之RingGeometry(圆环)设置thetaSegments和phiSegments

    • 设置thetaSegments

      1
      2
      3
      4
      5
      6
      7
      8
      9
      const ring2Geometry = new THREE.RingGeometry(1, 2, 3);
      const ring2Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
      const ring2 = new THREE.Mesh(ring2Geometry, ring2Material)
      const ringLineMaterial2 = new THREE.LineBasicMaterial( { color: 0xffffff} );
      const ringLineGeometry2 = new THREE.WireframeGeometry(ring2Geometry)
      const ringLine2 = new THREE.Line(ringLineGeometry2, ringLineMaterial2)
      ringLine2.position.y = 2
      ringLine2.position.x = 4
      group.add(ring2, ringLine2)

      为了直观的显示,将thetaSegments设置为了3。可以看到,原本的环变成了一个三角形。

    • 设置phiSegments

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

      const ring5Geometry = new THREE.RingGeometry(2, 4, 6, 10);

      const ring5Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
      const ring5 = new THREE.Mesh(ring5Geometry, ring5Material)
      const ringLineMaterial5 = new THREE.LineBasicMaterial( { color: 0xffffff} );
      const ringLineGeometry5 = new THREE.WireframeGeometry(ring5Geometry)
      const ringLine5 = new THREE.Line(ringLineGeometry5, ringLineMaterial5)
      group.add(ring5, ringLine5)
      scene.add(group)

      可以看到,环被一圈圈的分割了。到了这里,只能说是只可意会,不可言传了。

  • three.js基本图形之RingGeometry(圆环)设置thetaStart和thetaLength

    最后,再看一个,再看一下thetaStart和thetaLength的demo,这个写的太多了,直接上demo,代码不写了。

    最后,想看所有本次demo和源码集合点击这里

实现本次RingGeometry(圆环)的代码如下:

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
{
// 添加圆环

// 基础
const ring1Geometry = new THREE.RingGeometry(1, 2);
const ring1Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring1 = new THREE.Mesh(ring1Geometry, ring1Material)
ring1.position.y = 2
const ringLineMaterial1 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry1 = new THREE.WireframeGeometry(ring1Geometry)
const ringLine1 = new THREE.Line(ringLineGeometry1, ringLineMaterial1)
ringLine1.position.y = 2
if (search.includes('ring1') || !search) {
group.add(ring1, ringLine1)
}

// 修改分段数3
const ring2Geometry = new THREE.RingGeometry(1, 2, 3);
const ring2Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring2 = new THREE.Mesh(ring2Geometry, ring2Material)
ring2.position.y = 2
ring2.position.x = 4
const ringLineMaterial2 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry2 = new THREE.WireframeGeometry(ring2Geometry)
const ringLine2 = new THREE.Line(ringLineGeometry2, ringLineMaterial2)
ringLine2.position.y = 2
ringLine2.position.x = 4
if (search.includes('ring2') || !search) {
group.add(ring2, ringLine2)
}
if (search.includes('ring2')) {
ringLine2.position.y = 0
ringLine2.position.x = 0
ring2.position.y = 0
ring2.position.x = 0
}

// 修改分段数4
const ring3Geometry = new THREE.RingGeometry(1, 2, 4);
const ring3Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring3 = new THREE.Mesh(ring3Geometry, ring3Material)
ring3.position.y = 2
ring3.position.x = -4.2
const ringLineMaterial3 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry3 = new THREE.WireframeGeometry(ring3Geometry)
const ringLine3 = new THREE.Line(ringLineGeometry3, ringLineMaterial3)
ringLine3.position.y = 2
ringLine3.position.x = -4.2
if (search.includes('ring3') || !search) {
group.add(ring3, ringLine3)
}

if (search.includes('ring3')) {
ring3.position.y = 0
ring3.position.x = 0
ringLine3.position.y = 0
ringLine3.position.x = 0
}

// 修改分段数5
const ring4Geometry = new THREE.RingGeometry(1, 2, 5);
const ring4Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring4 = new THREE.Mesh(ring4Geometry, ring4Material)
ring4.position.y = 2
ring4.position.x = 8.2
const ringLineMaterial4 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry4 = new THREE.WireframeGeometry(ring4Geometry)
const ringLine4 = new THREE.Line(ringLineGeometry4, ringLineMaterial4)
ringLine4.position.y = 2
ringLine4.position.x = 8.2
if (search.includes('ring4') || !search) {
group.add(ring4, ringLine4)
}


// 修改环内分段数6
let ring5Geometry = ''
if (search.includes('ring5')) {
ring5Geometry = new THREE.RingGeometry(2, 4, 6, 10);
} else {
ring5Geometry = new THREE.RingGeometry(1, 2, 20, 10);
}
const ring5Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring5 = new THREE.Mesh(ring5Geometry, ring5Material)
ring5.position.y = 2
ring5.position.x = -8.2
const ringLineMaterial5 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry5 = new THREE.WireframeGeometry(ring5Geometry)
const ringLine5 = new THREE.Line(ringLineGeometry5, ringLineMaterial5)
ringLine5.position.y = 2
ringLine5.position.x = -8.2
if (search.includes('ring5') || !search) {
group.add(ring5, ringLine5)
}

if (search.includes('ring5')) {
ring5.position.y = 0
ring5.position.x = 0
ringLine5.position.y = 0
ringLine5.position.x = 0
}

// 修改开始结束角度
let ring6Geometry = ''
if (search.includes('ring6')) {
ring6Geometry = new THREE.RingGeometry(1, 4, 20, 10, 0, 1 * Math.PI);
} else {
ring6Geometry = new THREE.RingGeometry(1, 2, 20, 10, 0, 1 * Math.PI);
}
const ring6Material = new THREE.MeshBasicMaterial({color: 0x0000CD})
const ring6 = new THREE.Mesh(ring6Geometry, ring6Material)
ring6.position.y = -4
const ringLineMaterial6 = new THREE.LineBasicMaterial( { color: 0xffffff} );
const ringLineGeometry6 = new THREE.WireframeGeometry(ring6Geometry)
const ringLine6 = new THREE.Line(ringLineGeometry6, ringLineMaterial6)
ringLine6.position.y = -4
if (search.includes('ring6') || !search) {
group.add(ring6, ringLine6)
}
if (search.includes('ring6')) {
ring6.position.y = 0
ringLine6.position.y = 0
}

}