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