Three.js 几何体 #
几何体(Geometry)定义了 3D 物体的形状。Three.js 提供了丰富的内置几何体,也支持自定义几何体的创建。
几何体概述 #
text
┌─────────────────────────────────────────────────────────────┐
│ Three.js 几何体分类 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 基础形状 │ │ 参数形状 │ │ 复杂形状 │ │
│ ├─────────────┤ ├─────────────┤ ├─────────────┤ │
│ │ BoxGeometry │ │ LatheGeometry│ │ TextGeometry│ │
│ │SphereGeometry│ │TubeGeometry │ │ExtrudeGeometry│ │
│ │PlaneGeometry│ │ShapeGeometry│ │ParametricGeo│ │
│ │CylinderGeo │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
基础几何体 #
立方体(BoxGeometry) #
javascript
const geometry = new THREE.BoxGeometry(
1, // width:宽度
1, // height:高度
1, // depth:深度
1, // widthSegments:宽度分段数
1, // heightSegments:高度分段数
1 // depthSegments:深度分段数
);
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
参数详解 #
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| width | Number | 1 | X 轴方向的长度 |
| height | Number | 1 | Y 轴方向的长度 |
| depth | Number | 1 | Z 轴方向的长度 |
| widthSegments | Integer | 1 | X 轴方向的分段数 |
| heightSegments | Integer | 1 | Y 轴方向的分段数 |
| depthSegments | Integer | 1 | Z 轴方向的分段数 |
球体(SphereGeometry) #
javascript
const geometry = new THREE.SphereGeometry(
1, // radius:半径
32, // widthSegments:水平分段数
16, // heightSegments:垂直分段数
0, // phiStart:水平起始角度
Math.PI * 2, // phiLength:水平扫描角度
0, // thetaStart:垂直起始角度
Math.PI // thetaLength:垂直扫描角度
);
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
创建半球 #
javascript
const hemisphere = new THREE.SphereGeometry(
1, 32, 16,
0, Math.PI * 2,
0, Math.PI / 2
);
圆柱体(CylinderGeometry) #
javascript
const geometry = new THREE.CylinderGeometry(
1, // radiusTop:顶部半径
1, // radiusBottom:底部半径
2, // height:高度
32, // radialSegments:径向分段数
1, // heightSegments:高度分段数
false, // openEnded:是否开口
0, // thetaStart:起始角度
Math.PI * 2 // thetaLength:扫描角度
);
const cylinder = new THREE.Mesh(geometry, material);
scene.add(cylinder);
创建圆锥体 #
javascript
const cone = new THREE.CylinderGeometry(
0, 1, 2, 32
);
平面(PlaneGeometry) #
javascript
const geometry = new THREE.PlaneGeometry(
2, // width:宽度
2, // height:高度
1, // widthSegments:宽度分段数
1 // heightSegments:高度分段数
);
const plane = new THREE.Mesh(geometry, material);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
圆形(CircleGeometry) #
javascript
const geometry = new THREE.CircleGeometry(
1, // radius:半径
32, // segments:分段数
0, // thetaStart:起始角度
Math.PI * 2 // thetaLength:扫描角度
);
const circle = new THREE.Mesh(geometry, material);
scene.add(circle);
圆环(TorusGeometry) #
javascript
const geometry = new THREE.TorusGeometry(
1, // radius:圆环半径
0.4, // tube:管道半径
16, // radialSegments:径向分段数
100, // tubularSegments:管道分段数
Math.PI * 2 // arc:弧度
);
const torus = new THREE.Mesh(geometry, material);
scene.add(torus);
圆环结(TorusKnotGeometry) #
javascript
const geometry = new THREE.TorusKnotGeometry(
1, // radius:半径
0.3, // tube:管道半径
100, // tubularSegments:管道分段数
16, // radialSegments:径向分段数
2, // p:绕圈数
3 // q:缠绕数
);
const torusKnot = new THREE.Mesh(geometry, material);
scene.add(torusKnot);
二十面体(IcosahedronGeometry) #
javascript
const geometry = new THREE.IcosahedronGeometry(
1, // radius:半径
0 // detail:细分级别
);
const icosahedron = new THREE.Mesh(geometry, material);
scene.add(icosahedron);
十二面体(DodecahedronGeometry) #
javascript
const geometry = new THREE.DodecahedronGeometry(
1, // radius:半径
0 // detail:细分级别
);
const dodecahedron = new THREE.Mesh(geometry, material);
scene.add(dodecahedron);
八面体(OctahedronGeometry) #
javascript
const geometry = new THREE.OctahedronGeometry(
1, // radius:半径
0 // detail:细分级别
);
const octahedron = new THREE.Mesh(geometry, material);
scene.add(octahedron);
四面体(TetrahedronGeometry) #
javascript
const geometry = new THREE.TetrahedronGeometry(
1, // radius:半径
0 // detail:细分级别
);
const tetrahedron = new THREE.Mesh(geometry, material);
scene.add(tetrahedron);
参数化几何体 #
车削几何体(LatheGeometry) #
通过旋转轮廓线创建几何体,适合制作花瓶、杯子等旋转体。
javascript
const points = [];
for (let i = 0; i < 10; i++) {
points.push(new THREE.Vector2(
Math.sin(i * 0.2) * 0.5 + 0.5,
i * 0.2
));
}
const geometry = new THREE.LatheGeometry(
points, // 轮廓点数组
12, // segments:分段数
0, // phiStart:起始角度
Math.PI * 2 // phiLength:旋转角度
);
const lathe = new THREE.Mesh(geometry, material);
scene.add(lathe);
管道几何体(TubeGeometry) #
沿路径创建管道形状。
javascript
class CustomCurve extends THREE.Curve {
getPoint(t) {
const x = Math.cos(t * Math.PI * 2) * 2;
const y = Math.sin(t * Math.PI * 4) * 0.5;
const z = Math.sin(t * Math.PI * 2) * 2;
return new THREE.Vector3(x, y, z);
}
}
const path = new CustomCurve();
const geometry = new THREE.TubeGeometry(
path, // 路径
64, // tubularSegments:管道分段数
0.2, // radius:半径
8, // radialSegments:径向分段数
false // closed:是否闭合
);
const tube = new THREE.Mesh(geometry, material);
scene.add(tube);
挤压几何体(ExtrudeGeometry) #
从 2D 形状挤压出 3D 几何体。
javascript
const shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(1, 0);
shape.lineTo(1, 1);
shape.lineTo(0, 1);
shape.lineTo(0, 0);
const extrudeSettings = {
steps: 2,
depth: 1,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.1,
bevelOffset: 0,
bevelSegments: 3
};
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const extruded = new THREE.Mesh(geometry, material);
scene.add(extruded);
形状几何体(ShapeGeometry) #
从 2D 形状创建平面几何体。
javascript
const shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.bezierCurveTo(0.5, 0.5, 1, 0, 1, 0);
shape.lineTo(1, 1);
shape.lineTo(0, 1);
const geometry = new THREE.ShapeGeometry(shape);
const shapeMesh = new THREE.Mesh(geometry, material);
scene.add(shapeMesh);
文字几何体 #
TextGeometry #
javascript
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
const loader = new FontLoader();
loader.load('fonts/helvetiker_regular.typeface.json', (font) => {
const geometry = new TextGeometry('Hello Three.js!', {
font: font,
size: 0.5,
height: 0.2,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.02,
bevelOffset: 0,
bevelSegments: 5
});
geometry.computeBoundingBox();
geometry.center();
const text = new THREE.Mesh(geometry, material);
scene.add(text);
});
自定义几何体 #
使用 BufferGeometry #
javascript
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0
]);
const indices = [
0, 1, 2, 0, 2, 3,
1, 5, 6, 1, 6, 2,
5, 4, 7, 5, 7, 6,
4, 0, 3, 4, 3, 7,
3, 2, 6, 3, 6, 7,
4, 5, 1, 4, 1, 0
];
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.setIndex(indices);
geometry.computeVertexNormals();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
创建三角形 #
javascript
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.computeVertexNormals();
const triangle = new THREE.Mesh(geometry, material);
scene.add(triangle);
添加顶点颜色 #
javascript
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
]);
const colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
]);
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.MeshBasicMaterial({ vertexColors: true });
const triangle = new THREE.Mesh(geometry, material);
scene.add(triangle);
几何体属性 #
包围盒(BoundingBox) #
javascript
geometry.computeBoundingBox();
const box = geometry.boundingBox;
console.log('Min:', box.min);
console.log('Max:', box.max);
const center = new THREE.Vector3();
box.getCenter(center);
const size = new THREE.Vector3();
box.getSize(size);
包围球(BoundingSphere) #
javascript
geometry.computeBoundingSphere();
const sphere = geometry.boundingSphere;
console.log('Center:', sphere.center);
console.log('Radius:', sphere.radius);
居中几何体 #
javascript
geometry.center();
缩放几何体 #
javascript
geometry.scale(2, 1, 1);
旋转几何体 #
javascript
geometry.rotateX(Math.PI / 4);
geometry.rotateY(Math.PI / 2);
geometry.rotateZ(Math.PI);
平移几何体 #
javascript
geometry.translate(1, 0, 0);
几何体合并 #
合并多个几何体 #
javascript
import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';
const box1 = new THREE.BoxGeometry(1, 1, 1);
const box2 = new THREE.BoxGeometry(1, 1, 1);
box2.translate(2, 0, 0);
const mergedGeometry = mergeGeometries([box1, box2]);
const mesh = new THREE.Mesh(mergedGeometry, material);
scene.add(mesh);
几何体工具 #
边缘几何体(EdgesGeometry) #
javascript
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const edgesGeometry = new THREE.EdgesGeometry(boxGeometry);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xffffff });
const wireframe = new THREE.LineSegments(edgesGeometry, lineMaterial);
scene.add(wireframe);
线框几何体(WireframeGeometry) #
javascript
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const wireframeGeometry = new THREE.WireframeGeometry(boxGeometry);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xffffff });
const wireframe = new THREE.LineSegments(wireframeGeometry, lineMaterial);
scene.add(wireframe);
几何体对比表 #
| 几何体 | 顶点数 | 适用场景 | 性能 |
|---|---|---|---|
| BoxGeometry | 低 | 建筑物、方块 | 高 |
| SphereGeometry | 中 | 行星、球体 | 中 |
| CylinderGeometry | 中 | 管道、柱子 | 中 |
| PlaneGeometry | 低 | 地面、墙面 | 高 |
| TorusGeometry | 中 | 圆环、轮胎 | 中 |
| TorusKnotGeometry | 高 | 复杂装饰 | 低 |
| IcosahedronGeometry | 低 | 低多边形风格 | 高 |
最佳实践 #
分段数选择 #
javascript
const lowPoly = new THREE.SphereGeometry(1, 8, 6);
const smooth = new THREE.SphereGeometry(1, 64, 32);
const balanced = new THREE.SphereGeometry(1, 32, 16);
复用几何体 #
javascript
const geometry = new THREE.BoxGeometry(1, 1, 1);
for (let i = 0; i < 100; i++) {
const material = new THREE.MeshStandardMaterial({
color: Math.random() * 0xffffff
});
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(
Math.random() * 10 - 5,
Math.random() * 10 - 5,
Math.random() * 10 - 5
);
scene.add(mesh);
}
释放内存 #
javascript
geometry.dispose();
完整示例 #
javascript
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(5, 5, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);
const geometries = [
new THREE.BoxGeometry(1, 1, 1),
new THREE.SphereGeometry(0.5, 32, 16),
new THREE.CylinderGeometry(0.5, 0.5, 1, 32),
new THREE.TorusGeometry(0.4, 0.15, 16, 32),
new THREE.IcosahedronGeometry(0.5, 0),
new THREE.OctahedronGeometry(0.5, 0)
];
const materials = [
new THREE.MeshStandardMaterial({ color: 0xff6b6b }),
new THREE.MeshStandardMaterial({ color: 0x4ecdc4 }),
new THREE.MeshStandardMaterial({ color: 0x45b7d1 }),
new THREE.MeshStandardMaterial({ color: 0x96ceb4 }),
new THREE.MeshStandardMaterial({ color: 0xffeaa7 }),
new THREE.MeshStandardMaterial({ color: 0xdfe6e9 })
];
geometries.forEach((geometry, index) => {
const mesh = new THREE.Mesh(geometry, materials[index]);
const row = Math.floor(index / 3);
const col = index % 3;
mesh.position.set(col * 2 - 2, 0, row * 2 - 2);
scene.add(mesh);
});
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
下一步 #
现在你已经掌握了各种几何体的创建,接下来学习 材质,为几何体添加外观!
最后更新:2026-03-28