logo头像
Snippet 博客主题

threejs几何体

前面在场景那节只是简单介绍了threejs中可用的几何体,本节和下一节将深入讨论threejs提供的所有几何体(不包括上一节探讨过的THREE.Line)。

二维几何体

THREE.PlaneGeometry

它可以用来创建一个非常简单的二维矩形。

属性 描述
width(宽度) 指定矩形宽度
height(高度) 指定矩形高度
widthSegments(宽度段数) 指定矩形宽度应该划分为几段,默认为1
heightSegments(高度段数) 指定矩形高度应该划分为几段,默认为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
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
<!-- chapter-05-01.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 2D geometries - Plane</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建平面网格
var plane = createMesh(new THREE.PlaneGeometry(10, 14, 4, 4));
scene.add(plane);

camera.position.x = -20;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(new THREE.Vector3(10, 0, 0));

var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);

document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
// 因为plane是使用组合材质创建,所以这里取children的第一个
this.width = plane.children[0].geometry.parameters.width;
this.height = plane.children[0].geometry.parameters.height;
this.widthSegments = plane.children[0].geometry.parameters.widthSegments;
this.heightSegments = plane.children[0].geometry.parameters.heightSegments;

// 重新绘制
this.redraw = function () {
scene.remove(plane);
plane = createMesh(new THREE.PlaneGeometry(controls.width, controls.height, Math.round(controls.widthSegments), Math.round(controls.heightSegments)));
scene.add(plane);
};
};

var gui = new dat.GUI();
gui.add(controls, 'width', 0, 40).onChange(controls.redraw);
gui.add(controls, 'height', 0, 40).onChange(controls.redraw);
gui.add(controls, 'widthSegments', 0, 10).onChange(controls.redraw);
gui.add(controls, 'heightSegments', 0, 10).onChange(controls.redraw);
render();

// 创建平面网格
function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide; // 背面/前面两面可见
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var plane = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return plane;
}

function render() {
stats.update();
plane.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.CircleGeometry

它可以创建一个非常简单的二维圆(或部分圆)。

属性 描述
radius 设置圆的半径,默认为50
segments 设置创建圆所用面的数量,最小值是3,默认是8。值越大,圆越光滑
thetaStart 设置从哪里开始画圆,取值范围是0到2*PI, 默认为0
thetaLength 设置圆画的弧度,默认是2*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
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
<!-- chapter-05-02.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 2D geometries - Circle</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建圆形网格
var circle = createMesh(new THREE.CircleGeometry(4, 10, 0.3 * Math.PI * 2, 0.3 * Math.PI * 2));
scene.add(circle);

camera.position.x = -20;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(new THREE.Vector3(10, 0, 0));

var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);

document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.radius = 4;
this.thetaStart = 0.3 * Math.PI * 2;
this.thetaLength = 0.3 * Math.PI * 2;
this.segments = 10;
this.redraw = function () {
scene.remove(circle);
circle = createMesh(new THREE.CircleGeometry(controls.radius, controls.segments, controls.thetaStart, controls.thetaLength));
scene.add(circle);
};
};

var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
gui.add(controls, 'segments', 0, 40).onChange(controls.redraw);
gui.add(controls, 'thetaStart', 0, 2 * Math.PI).onChange(controls.redraw);
gui.add(controls, 'thetaLength', 0, 2 * Math.PI).onChange(controls.redraw);
render();

// 创建圆形网格
function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

function render() {
stats.update();
circle.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.RingGeometry

它和上面圆类似,但它可以在中心定义一个孔。

属性 描述
innerRadius 圆环的内半径,它定义中心圆孔的尺寸。如果设置为0,则不会显示圆孔。默认值为0
outerRadius 圆环的外半径,它定义圆环的尺寸。默认值为50
thetaSegments 指定圆环的对角线段数量,越大则圆环更平滑。默认为8
phiSegments 指定沿着圆环的长度所需要使用的线段数量。默认为8。它不会影响圆的平滑度,只会增加面的数量
thetaStart 指定从哪里开始画圆
thetaLength 指定画圆的弧度大小
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
<!-- chapter-05-03.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 2D geometries - Ring</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建圆环网格
var torus = createMesh(new THREE.RingGeometry());
scene.add(torus);

camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(10, 0, 0));
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.innerRadius = 0;
this.outerRadius = 50;
this.thetaSegments = 8;
this.phiSegments = 8;
this.thetaStart = 0;
this.thetaLength = Math.PI * 2;
this.redraw = function () {
scene.remove(torus);
torus = createMesh(new THREE.RingGeometry(controls.innerRadius, controls.outerRadius, controls.thetaSegments, controls.phiSegments, controls.thetaStart, controls.thetaLength));
scene.add(torus);
};
};

var gui = new dat.GUI();
gui.add(controls, 'innerRadius', 0, 40).onChange(controls.redraw);
gui.add(controls, 'outerRadius', 0, 100).onChange(controls.redraw);
gui.add(controls, 'thetaSegments', 1, 40).step(1).onChange(controls.redraw);
gui.add(controls, 'phiSegments', 1, 20).step(1).onChange(controls.redraw);
gui.add(controls, 'thetaStart', 0, Math.PI * 2).onChange(controls.redraw);
gui.add(controls, 'thetaLength', 0, Math.PI * 2).onChange(controls.redraw);
// 创建圆环网格
function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

render();
function render() {
stats.update();
torus.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.ShapeGeometry

它可以自定义二维图形。

先来看看THREE.ShapeGeometry方法的参数:

上面传入参数最重要的就是shapes,THREE.Shape对象的创建。它可以用来创建图形,所以下面介绍它的绘图函数。

THREE.Shape对象的一些辅助函数:

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<!-- chapter-05-04.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 2D geometries - Shape</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建自定义网格
var shape = createMesh(new THREE.ShapeGeometry(drawShape()));
scene.add(shape);

camera.position.x = -30;
camera.position.y = 70;
camera.position.z = 70;
camera.lookAt(new THREE.Vector3(10, 0, 0));

var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
// 重绘自定义网格
this.asGeom = function () {
scene.remove(shape);
shape = createMesh(new THREE.ShapeGeometry(drawShape()));
scene.add(shape);
};
// 重绘自定义几何体线框
this.asPoints = function () {
scene.remove(shape);
shape = createLine(drawShape(), false);
scene.add(shape);
};
// 同上,使用另一种方式创建
this.asSpacedPoints = function () {
scene.remove(shape);
shape = createLine(drawShape(), true);
scene.add(shape);
};
};

var gui = new dat.GUI();
gui.add(controls, 'asGeom');
gui.add(controls, 'asPoints');
gui.add(controls, 'asSpacedPoints');

// 创建自定义的Shape对象
function drawShape() {
// create a basic shape
var shape = new THREE.Shape();

// startpoint
shape.moveTo(10, 10);

// straight line upwards
shape.lineTo(10, 40);

// the top of the figure, curve to the right
shape.bezierCurveTo(15, 25, 25, 25, 30, 40);

// spline back down
shape.splineThru(
[new THREE.Vector2(32, 30),
new THREE.Vector2(28, 20),
new THREE.Vector2(30, 10),
]);

// curve at the bottom
shape.quadraticCurveTo(20, 15, 10, 10);

// add 'eye' hole one
var hole1 = new THREE.Path();
hole1.absellipse(16, 24, 2, 3, 0, Math.PI * 2, true);
shape.holes.push(hole1);

// add 'eye hole 2'
var hole2 = new THREE.Path();
hole2.absellipse(23, 24, 2, 3, 0, Math.PI * 2, true);
shape.holes.push(hole2);

// add 'mouth'
var hole3 = new THREE.Path();
hole3.absarc(20, 16, 2, 0, Math.PI, true);
shape.holes.push(hole3);

// return the shape
return shape;
}

// 创建自定义网格
function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

// 使用THREE.Shape的两个辅助函数创建自定义网格的线框
function createLine(shape, spaced) {
if (!spaced) {
var mesh = new THREE.Line(shape.createPointsGeometry(10), new THREE.LineBasicMaterial({
color: 0xff3333,
linewidth: 2
}));
return mesh;
} else {
// TODO: 目前测试这个方式会报错?
var mesh = new THREE.Line(shape.createSpacedPointsGeometry(3), new THREE.LineBasicMaterial({
color: 0xff3333,
linewidth: 2
}));
return mesh;
}

}

render();
function render() {
stats.update();
shape.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>


三维几何体

THREE.BoxGeometry

这是一个非常简单的三维几何体,只需要指定宽、高和深度就可以创建一个长方体。

属性 描述
width 指定长方体的宽度
height 指定长方体的高度
depth 指定长方体的深度
widthSegments 指定宽分成多少份,默认值为1
heightSegments 指定高分成多少份,默认值为1
depthSegments 指定深度分成多少份,默认值为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
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
<!-- chapter-05-05.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 2D geometries - Cube</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建长方体网格
var cube = createMesh(new THREE.BoxGeometry(10, 10, 10, 1, 1, 1));
scene.add(cube);

camera.position.x = -20;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(new THREE.Vector3(10, 0, 0));

var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.width = cube.children[0].geometry.parameters.width;
this.height = cube.children[0].geometry.parameters.height;
this.depth = cube.children[0].geometry.parameters.depth;
this.widthSegments = cube.children[0].geometry.parameters.widthSegments;
this.heightSegments = cube.children[0].geometry.parameters.heightSegments;
this.depthSegments = cube.children[0].geometry.parameters.depthSegments;

this.redraw = function () {
scene.remove(cube);
cube = createMesh(new THREE.BoxGeometry(controls.width, controls.height, controls.depth, Math.round(controls.widthSegments), Math.round(controls.heightSegments), Math.round(controls.depthSegments)));
scene.add(cube);
};
};

var gui = new dat.GUI();
gui.add(controls, 'width', 0, 40).onChange(controls.redraw);
gui.add(controls, 'height', 0, 40).onChange(controls.redraw);
gui.add(controls, 'depth', 0, 40).onChange(controls.redraw);
gui.add(controls, 'widthSegments', 0, 10).onChange(controls.redraw);
gui.add(controls, 'heightSegments', 0, 10).onChange(controls.redraw);
gui.add(controls, 'depthSegments', 0, 10).onChange(controls.redraw);

// 创建网格
function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

function render() {
stats.update();
cube.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
render();

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.SphereGeometry

它可以创建一个三维的球体。这个几何体非常灵活,可以用来创建所有跟球体相关的几何体。通过下面这些属性调节球体相关几何体网格的外观:

属性 描述
radius 设置球体的半径,默认值为50
widthSegments 球体竖直方向分段数,值越大,球体表面越光滑。默认值为8,最小值为3
heightSegments 水平方向分段数,同上
phiStart 指定从x轴的什么地方开始绘制球体
phiLength 指定从phiStart开始画多少弧度
thetaStart 指定从y轴的什么地方开始绘制球体
thetaLength 指定从phetaStart开始画多少弧度
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
<!-- chapter-05-06.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 3D geometries - Sphere</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建球体网格
var sphere = createMesh(new THREE.SphereGeometry(4, 10, 10));
scene.add(sphere);

camera.position.x = -20;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(new THREE.Vector3(10, 0, 0));
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.radius = sphere.children[0].geometry.parameters.radius;
this.widthSegments = sphere.children[0].geometry.parameters.widthSegments;
this.heightSegments = sphere.children[0].geometry.parameters.heightSegments;
this.phiStart = 0;
this.phiLength = Math.PI * 2;
this.thetaStart = 0;
this.thetaLength = Math.PI;

this.redraw = function () {
scene.remove(sphere);
sphere = createMesh(new THREE.SphereGeometry(controls.radius, controls.widthSegments, controls.heightSegments, controls.phiStart, controls.phiLength, controls.thetaStart, controls.thetaLength));
scene.add(sphere);
};
};

var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
gui.add(controls, 'widthSegments', 0, 20).onChange(controls.redraw);
gui.add(controls, 'heightSegments', 0, 20).onChange(controls.redraw);
gui.add(controls, 'phiStart', 0, 2 * Math.PI).onChange(controls.redraw);
gui.add(controls, 'phiLength', 0, 2 * Math.PI).onChange(controls.redraw);
gui.add(controls, 'thetaStart', 0, 2 * Math.PI).onChange(controls.redraw);
gui.add(controls, 'thetaLength', 0, 2 * Math.PI).onChange(controls.redraw);

// 创建网格
function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

function render() {
stats.update();
sphere.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
render();

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.CylinderGeometry

它可以创建圆柱和类似圆柱的物体。

属性 描述
radiusTop 设置圆柱顶部的尺寸,默认值为20
radiusBottom 设置圆柱底部的尺寸,默认值为20
height 设置圆柱的高度,默认值为100
radialSegments 设置沿半径分为多少段。默认值为8,值越大越光滑
heightSegments 设置沿高度分成多少段。默认值为1,值越大面越多
openEnded 设置网格顶部和底部是否封闭。默认为false
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
<!-- chapter-05-07.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 3D geometries - Cylinder</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建圆柱体
var cylinder = createMesh(new THREE.CylinderGeometry(20, 20, 20));
scene.add(cylinder);

camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(10, 0, 0));
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.radiusTop = 20;
this.radiusBottom = 20;
this.height = 20;
this.radialSegments = 8;
this.heightSegments = 8;
this.openEnded = false;
this.redraw = function () {
scene.remove(cylinder);
cylinder = createMesh(new THREE.CylinderGeometry(controls.radiusTop, controls.radiusBottom, controls.height, controls.radialSegments, controls.heightSegments, controls.openEnded));
scene.add(cylinder);
};
};

var gui = new dat.GUI();
gui.add(controls, 'radiusTop', -40, 40).onChange(controls.redraw);
gui.add(controls, 'radiusBottom', -40, 40).onChange(controls.redraw);
gui.add(controls, 'height', 0, 40).onChange(controls.redraw);
gui.add(controls, 'radialSegments', 1, 20).step(1).onChange(controls.redraw);
gui.add(controls, 'heightSegments', 1, 20).step(1).onChange(controls.redraw);
gui.add(controls, 'openEnded').onChange(controls.redraw);

function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

function render() {
stats.update();
cylinder.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
render();

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

​ 把顶部或底部设置为负数的半径,可以创建一个类似沙漏的图形。

THREE.TorusGeometry

它可以创建圆环。

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
<!-- chapter-05-08.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 3D geometries - Torus</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建圆环网格
var torus = createMesh(new THREE.TorusGeometry(10, 10, 8, 6, Math.PI * 2));
scene.add(torus);

camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(10, 0, 0));
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.radius = torus.children[0].geometry.parameters.radius;
this.tube = torus.children[0].geometry.parameters.tube;
this.radialSegments = torus.children[0].geometry.parameters.radialSegments;
this.tubularSegments = torus.children[0].geometry.parameters.tubularSegments;
this.arc = torus.children[0].geometry.parameters.arc;
this.redraw = function () {
scene.remove(torus);
torus = createMesh(new THREE.TorusGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), controls.arc));
scene.add(torus);
};
};

var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
gui.add(controls, 'tube', 0, 40).onChange(controls.redraw);
gui.add(controls, 'radialSegments', 0, 40).onChange(controls.redraw);
gui.add(controls, 'tubularSegments', 1, 20).onChange(controls.redraw);
gui.add(controls, 'arc', 0, Math.PI * 2).onChange(controls.redraw);

function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

function render() {
stats.update();
torus.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
render();

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.TorusKnotGeometry

它可以创建一个环状扭结,看起来像一根管子绕自己转了几圈。

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
<!-- chapter-05-09.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 3D geometries - Torusknot</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建环状扭结
var knot = createMesh(new THREE.TorusKnotGeometry(10, 1, 64, 8, 2, 3, 1));
scene.add(knot);

camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(10, 0, 0));
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.radius = knot.children[0].geometry.parameters.radius;
this.tube = 0.3;
this.radialSegments = knot.children[0].geometry.parameters.radialSegments;
this.tubularSegments = knot.children[0].geometry.parameters.tubularSegments;
this.p = knot.children[0].geometry.parameters.p;
this.q = knot.children[0].geometry.parameters.q;
this.heightScale = knot.children[0].geometry.parameters.heightScale;

this.redraw = function () {
scene.remove(knot);
knot = createMesh(new THREE.TorusKnotGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), Math.round(controls.p), Math.round(controls.q), controls.heightScale));
scene.add(knot);
};
};

var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
gui.add(controls, 'tube', 0, 40).onChange(controls.redraw);
gui.add(controls, 'radialSegments', 0, 400).step(1).onChange(controls.redraw);
gui.add(controls, 'tubularSegments', 1, 20).step(1).onChange(controls.redraw);
gui.add(controls, 'p', 1, 10).step(1).onChange(controls.redraw);
gui.add(controls, 'q', 1, 15).step(1).onChange(controls.redraw);
gui.add(controls, 'heightScale', 0, 5).onChange(controls.redraw);

function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial({});
meshMaterial.side = THREE.DoubleSide;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial]);
return mesh;
}

function render() {
stats.update();
knot.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
render();

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>

THREE.PolyhedronGeometry

它可以很容易的创建多面体,它是只有平面和直边的几何体。大多数情况下,你不需要直接使用这种几何体,Threejs提供了几种特定的多面体可以直接使用,而不必自己去指定THREE.PolyhedronGeometry的顶点和面。

THREE.PolyhedronGeometry属性:

属性 描述
vertices 设置构成多面体的顶点
indices 设置由vertices创建出的面
radius 设置多面体的大小,默认值为1
detail 如果设置为1,这个多面体每个三角形都会分成4个小三角形,如果设置为2,那4个小三角形中每一个将会继续分成4个小三角形,以此类推

下面是Threejs提供的几个开箱即用的多面体:

  • THREE.lcosahedronGeometry 20面体
  • THREE.TetrahedronGeometry 4面体
  • THREE.OctahedronGeometry 8面体
  • THREE.DodecahedronGeometry 12面体
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
<!-- chapter-05-10.html -->
<!DOCTYPE html>
<html>
<head>
<title>Basic 3D geometries - Polyhedron</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<script type="text/javascript">
function init() {
var stats = initStats();

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

var webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;

// 创建20面体网格
var polyhedron = createMesh(new THREE.IcosahedronGeometry(10, 0));
scene.add(polyhedron);

camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(10, 0, 0));
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

var controls = new function () {
this.radius = 10;
this.detail = 0;
this.type = 'Icosahedron';

this.redraw = function () {
scene.remove(polyhedron);
switch (controls.type) {
case 'Icosahedron':
polyhedron = createMesh(new THREE.IcosahedronGeometry(controls.radius, controls.detail));
break;
case 'Tetrahedron':
polyhedron = createMesh(new THREE.TetrahedronGeometry(controls.radius, controls.detail));
break;
case 'Octahedron':
polyhedron = createMesh(new THREE.OctahedronGeometry(controls.radius, controls.detail));
break;
case 'Dodecahedron':
polyhedron = createMesh(new THREE.DodecahedronGeometry(controls.radius, controls.detail));
break;
case 'Custom':
var vertices = [
1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1
];

var indices = [
2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
];

polyhedron = createMesh(new THREE.PolyhedronGeometry(vertices, indices, controls.radius, controls.detail));
break;
}

scene.add(polyhedron);
};
};

var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).step(1).onChange(controls.redraw);
gui.add(controls, 'detail', 0, 3).step(1).onChange(controls.redraw);
gui.add(controls, 'type', ['Icosahedron', 'Tetrahedron', 'Octahedron', 'Dodecahedron', 'Custom']).onChange(controls.redraw);

function createMesh(geom) {
var meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
var wireFrameMat = new THREE.MeshBasicMaterial();
wireFrameMat.wireframe = true;
var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);
return mesh;
}

function render() {
stats.update();
polyhedron.rotation.y += 0.01;
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
render();

function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>