内置几何体
Three.js 提供了丰富的内置几何体(Geometry)类,用于创建各种 3D 形状。这些几何体是构建 3D 场景的基础元素。
概述
几何体定义了 3D 对象的形状,包含顶点位置、面、法线、UV 坐标等数据。Three.js 提供了多种内置几何体,可以快速创建常见的 3D 形状。
架构概览
Three.js 内置几何体继承自 BufferGeometry 基类,按照形状特征可分为以下几类:
BufferGeometry (基类)
├── 基础几何体
│ ├── BoxGeometry 立方体/长方体
│ ├── SphereGeometry 球体
│ ├── CylinderGeometry 圆柱体
│ ├── PlaneGeometry 平面
│ └── ConeGeometry 圆锥体
├── 高级几何体
│ ├── TorusGeometry 圆环
│ ├── TorusKnotGeometry 圆环结
│ └── PolyhedronGeometry 多面体基类
│ ├── TetrahedronGeometry 正四面体
│ ├── OctahedronGeometry 正八面体
│ ├── DodecahedronGeometry 正十二面体
│ └── IcosahedronGeometry 正二十面体
├── 二维形状几何体
│ ├── CircleGeometry 圆形
│ └── RingGeometry 环形
├── 特殊几何体
│ ├── TextGeometry 文字几何体
│ ├── ExtrudeGeometry 拉伸几何体
│ ├── LatheGeometry 车削几何体
│ └── TubeGeometry 管道几何体
└── 辅助几何体
├── EdgesGeometry 边缘几何体
└── WireframeGeometry 线框几何体基础几何体
立方体(BoxGeometry)
创建立方体或长方体,是最常用的几何体之一。
import * as THREE from 'three';
// 创建立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 创建长方体(宽度、高度、深度)
const boxGeometry = new THREE.BoxGeometry(2, 1, 3);
// 带分段的长方体
const segmentedBox = new THREE.BoxGeometry(2, 2, 2, 2, 2, 2);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| width | number | 1 | 宽度(X 轴方向) |
| height | number | 1 | 高度(Y 轴方向) |
| depth | number | 1 | 深度(Z 轴方向) |
| widthSegments | number | 1 | 宽度方向分段数 |
| heightSegments | number | 1 | 高度方向分段数 |
| depthSegments | number | 1 | 深度方向分段数 |
new THREE.BoxGeometry(
width: number, // 宽度(默认 1)
height: number, // 高度(默认 1)
depth: number, // 深度(默认 1)
widthSegments: number, // 宽度分段数(默认 1)
heightSegments: number, // 高度分段数(默认 1)
depthSegments: number // 深度分段数(默认 1)
);球体(SphereGeometry)
创建球体,支持创建完整球体或部分球体(如半球、扇形球)。
// 基础球体
const sphere = new THREE.SphereGeometry(1, 32, 32);
// 半球
const hemisphere = new THREE.SphereGeometry(
1, // 半径
32, // 水平分段
16, // 垂直分段
0, // 水平起始角度
Math.PI, // 水平扫描角度
0, // 垂直起始角度
Math.PI / 2 // 垂直扫描角度
);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radius | number | 1 | 球体半径 |
| widthSegments | number | 32 | 水平分段数(经度方向) |
| heightSegments | number | 16 | 垂直分段数(纬度方向) |
| phiStart | number | 0 | 水平起始角度(弧度) |
| phiLength | number | 2π | 水平扫描角度(弧度) |
| thetaStart | number | 0 | 垂直起始角度(弧度) |
| thetaLength | number | π | 垂直扫描角度(弧度) |
new THREE.SphereGeometry(
radius: number, // 半径(默认 1)
widthSegments: number, // 水平分段数(默认 32)
heightSegments: number, // 垂直分段数(默认 16)
phiStart: number, // 水平起始角度(默认 0)
phiLength: number, // 水平扫描角度(默认 2π)
thetaStart: number, // 垂直起始角度(默认 0)
thetaLength: number // 垂直扫描角度(默认 π)
);圆柱体(CylinderGeometry)
创建圆柱体,通过设置不同的顶部和底部半径,可以创建圆锥、圆台等形状。
// 基础圆柱体
const cylinder = new THREE.CylinderGeometry(1, 1, 2, 32);
// 圆锥(顶部半径为 0)
const cone = new THREE.CylinderGeometry(0, 1, 2, 32);
// 圆台
const frustum = new THREE.CylinderGeometry(0.5, 1, 2, 32);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radiusTop | number | 1 | 顶部半径 |
| radiusBottom | number | 1 | 底部半径 |
| height | number | 1 | 高度 |
| radialSegments | number | 32 | 径向分段数 |
| heightSegments | number | 1 | 高度分段数 |
| openEnded | boolean | false | 是否开口(无顶底面) |
| thetaStart | number | 0 | 起始角度(弧度) |
| thetaLength | number | 2π | 扫描角度(弧度) |
new THREE.CylinderGeometry(
radiusTop: number, // 顶部半径(默认 1)
radiusBottom: number, // 底部半径(默认 1)
height: number, // 高度(默认 1)
radialSegments: number, // 径向分段数(默认 32)
heightSegments: number, // 高度分段数(默认 1)
openEnded: boolean, // 是否开口(默认 false)
thetaStart: number, // 起始角度(默认 0)
thetaLength: number // 扫描角度(默认 2π)
);平面(PlaneGeometry)
创建平面,默认在 XY 平面上,面向 +Z 方向。
// 基础平面
const plane = new THREE.PlaneGeometry(2, 2);
// 带分段的平面
const segmentedPlane = new THREE.PlaneGeometry(4, 4, 10, 10);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| width | number | 1 | 宽度 |
| height | number | 1 | 高度 |
| widthSegments | number | 1 | 宽度分段数 |
| heightSegments | number | 1 | 高度分段数 |
new THREE.PlaneGeometry(
width: number, // 宽度(默认 1)
height: number, // 高度(默认 1)
widthSegments: number, // 宽度分段数(默认 1)
heightSegments: number // 高度分段数(默认 1)
);高级几何体
圆环(TorusGeometry)
创建圆环体(甜甜圈形状)。
// 基础圆环
const torus = new THREE.TorusGeometry(1, 0.4, 16, 100);
// 扁平圆环
const flatTorus = new THREE.TorusGeometry(2, 0.2, 8, 50);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radius | number | 1 | 圆环中心到管道中心的距离 |
| tube | number | 0.4 | 管道半径 |
| radialSegments | number | 12 | 径向分段数 |
| tubularSegments | number | 48 | 管道分段数 |
| arc | number | 2π | 圆弧角度(弧度) |
new THREE.TorusGeometry(
radius: number, // 圆环半径(默认 1)
tube: number, // 管道半径(默认 0.4)
radialSegments: number, // 径向分段数(默认 12)
tubularSegments: number, // 管道分段数(默认 48)
arc: number // 圆弧角度(默认 2π)
);圆环结(TorusKnotGeometry)
创建圆环结(三叶结),通过 p 和 q 参数控制缠绕方式。
// 基础圆环结
const torusKnot = new THREE.TorusKnotGeometry(1, 0.3, 100, 16);
// 自定义参数(p=3, q=4 的环面结)
const customKnot = new THREE.TorusKnotGeometry(1, 0.3, 100, 16, 3, 4);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radius | number | 1 | 整体半径 |
| tube | number | 0.4 | 管道半径 |
| tubularSegments | number | 64 | 管道分段数 |
| radialSegments | number | 8 | 径向分段数 |
| p | number | 2 | 缠绕次数 p(绕大圆) |
| q | number | 3 | 缠绕次数 q(绕小圆) |
new THREE.TorusKnotGeometry(
radius: number, // 半径(默认 1)
tube: number, // 管道半径(默认 0.4)
tubularSegments: number, // 管道分段数(默认 64)
radialSegments: number, // 径向分段数(默认 8)
p: number, // 缠绕次数 p(默认 2)
q: number // 缠绕次数 q(默认 3)
);多面体
多面体几何体基于正多面体,通过 detail 参数可以增加细分级别。
正四面体(TetrahedronGeometry)
const tetrahedron = new THREE.TetrahedronGeometry(1);
// 4 个面,每个面是等边三角形正八面体(OctahedronGeometry)
const octahedron = new THREE.OctahedronGeometry(1);
// 8 个面,每个面是等边三角形正十二面体(DodecahedronGeometry)
const dodecahedron = new THREE.DodecahedronGeometry(1);
// 12 个面,每个面是正五边形正二十面体(IcosahedronGeometry)
const icosahedron = new THREE.IcosahedronGeometry(1, 0);
// 20 个面,每个面是等边三角形
// 常用于创建近似球体或细分表面多面体通用参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radius | number | 1 | 外接球半径 |
| detail | number | 0 | 细分级别(0 为原始形状) |
new THREE.XGeometry(
radius: number, // 半径(默认 1)
detail: number // 细分级别(默认 0)
);圆锥体(ConeGeometry)
圆锥体是圆柱体的特殊形式,顶部半径为 0。
// 基础圆锥
const cone = new THREE.ConeGeometry(1, 2, 32);
// 开口圆锥
const openCone = new THREE.ConeGeometry(1, 2, 32, 1, true);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radius | number | 1 | 底部半径 |
| height | number | 1 | 高度 |
| radialSegments | number | 32 | 径向分段数 |
| heightSegments | number | 1 | 高度分段数 |
| openEnded | boolean | false | 是否开口 |
| thetaStart | number | 0 | 起始角度 |
| thetaLength | number | 2π | 扫描角度 |
new THREE.ConeGeometry(
radius: number, // 底部半径(默认 1)
height: number, // 高度(默认 1)
radialSegments: number, // 径向分段数(默认 32)
heightSegments: number, // 高度分段数(默认 1)
openEnded: boolean, // 是否开口(默认 false)
thetaStart: number, // 起始角度(默认 0)
thetaLength: number // 扫描角度(默认 2π)
);二维形状几何体
圆形(CircleGeometry)
创建平面圆形或扇形。
// 完整圆形
const circle = new THREE.CircleGeometry(1, 32);
// 扇形(四分之一圆)
const sector = new THREE.CircleGeometry(1, 32, 0, Math.PI / 2);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| radius | number | 1 | 半径 |
| segments | number | 32 | 边数(值越大越圆滑) |
| thetaStart | number | 0 | 起始角度 |
| thetaLength | number | 2π | 扫描角度 |
new THREE.CircleGeometry(
radius: number, // 半径(默认 1)
segments: number, // 分段数(默认 32)
thetaStart: number, // 起始角度(默认 0)
thetaLength: number // 扫描角度(默认 2π)
);环形(RingGeometry)
创建平面环形(圆环面)。
// 基础环形
const ring = new THREE.RingGeometry(0.5, 1, 32);
// 部分环形(半圆环)
const partialRing = new THREE.RingGeometry(0.5, 1, 32, 1, 0, Math.PI);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| innerRadius | number | 0.5 | 内半径 |
| outerRadius | number | 1 | 外半径 |
| thetaSegments | number | 32 | 圆周分段数 |
| phiSegments | number | 1 | 径向分段数(环形厚度分段) |
| thetaStart | number | 0 | 起始角度 |
| thetaLength | number | 2π | 扫描角度 |
new THREE.RingGeometry(
innerRadius: number, // 内半径(默认 0.5)
outerRadius: number, // 外半径(默认 1)
thetaSegments: number, // 径向分段数(默认 32)
phiSegments: number, // 环形分段数(默认 1)
thetaStart: number, // 起始角度(默认 0)
thetaLength: number // 扫描角度(默认 2π)
);特殊几何体
文字几何体(TextGeometry)
需要加载字体文件后创建 3D 文字。
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 textGeometry = new TextGeometry('Hello Three.js', {
font: font,
size: 1,
height: 0.2,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.02,
bevelOffset: 0,
bevelSegments: 5
});
const textMesh = new THREE.Mesh(textGeometry, material);
scene.add(textMesh);
});构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| font | Font | - | 字体对象(必需) |
| size | number | 100 | 文字大小 |
| height | number | 50 | 挤出厚度 |
| curveSegments | number | 12 | 曲线分段数 |
| bevelEnabled | boolean | false | 是否启用倒角 |
| bevelThickness | number | 10 | 倒角厚度 |
| bevelSize | number | 8 | 倒角大小 |
| bevelOffset | number | 0 | 倒角偏移 |
| bevelSegments | number | 3 | 倒角分段数 |
new TextGeometry(text: string, {
font: Font, // 字体对象(必需)
size: number, // 文字大小(默认 100)
height: number, // 文字厚度(默认 50)
curveSegments: number, // 曲线分段数(默认 12)
bevelEnabled: boolean, // 是否启用倒角(默认 false)
bevelThickness: number, // 倒角厚度(默认 10)
bevelSize: number, // 倒角大小(默认 8)
bevelOffset: number, // 倒角偏移(默认 0)
bevelSegments: number // 倒角分段数(默认 3)
});拉伸几何体(ExtrudeGeometry)
从 2D 形状(Shape)拉伸成 3D 几何体。
// 创建 2D 形状
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 = {
depth: 2, // 拉伸深度
bevelEnabled: true, // 启用倒角
bevelThickness: 0.2,
bevelSize: 0.1,
bevelSegments: 3
};
const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const extrudeMesh = new THREE.Mesh(extrudeGeometry, material);
scene.add(extrudeMesh);车削几何体(LatheGeometry)
通过旋转轮廓线创建旋转体(如花瓶、酒杯、碗等)。
// 定义轮廓点
const points = [];
for (let i = 0; i < 10; i++) {
points.push(
new THREE.Vector2(
Math.sin(i * 0.2) * 2 + 1, // x 坐标(半径)
i * 0.5 // y 坐标
)
);
}
// 创建车削几何体
const latheGeometry = new THREE.LatheGeometry(points, 30);
const latheMesh = new THREE.Mesh(latheGeometry, material);
scene.add(latheMesh);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| points | Vector2[] | - | 轮廓点数组 |
| segments | number | 12 | 圆周分段数 |
| phiStart | number | 0 | 起始角度 |
| phiLength | number | 2π | 旋转角度 |
new THREE.LatheGeometry(
points: Vector2[], // 轮廓点数组
segments: number, // 分段数(默认 12)
phiStart: number, // 起始角度(默认 0)
phiLength: number // 旋转角度(默认 2π)
);管道几何体(TubeGeometry)
沿曲线路径创建管道形状。
// 定义自定义曲线
class CustomCurve extends THREE.Curve {
getPoint(t) {
const x = Math.cos(t * Math.PI * 2);
const y = Math.sin(t * Math.PI * 2);
const z = t * 2;
return new THREE.Vector3(x, y, z);
}
}
const curve = new CustomCurve();
// 创建管道几何体
const tubeGeometry = new THREE.TubeGeometry(curve, 100, 0.2, 8, false);
const tubeMesh = new THREE.Mesh(tubeGeometry, material);
scene.add(tubeMesh);构造参数:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| path | Curve | - | 路径曲线 |
| tubularSegments | number | 64 | 管道分段数 |
| radius | number | 1 | 管道半径 |
| radialSegments | number | 8 | 径向分段数 |
| closed | boolean | false | 是否闭合 |
new THREE.TubeGeometry(
path: Curve, // 路径曲线
tubularSegments: number, // 管道分段数(默认 64)
radius: number, // 管道半径(默认 1)
radialSegments: number, // 径向分段数(默认 8)
closed: boolean // 是否闭合(默认 false)
);几何体属性
顶点属性
所有几何体都包含以下核心属性:
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 获取顶点位置
const position = geometry.attributes.position;
// 获取顶点数量
const vertexCount = position.count;
// 获取顶点法线
const normal = geometry.attributes.normal;
// 获取 UV 坐标
const uv = geometry.attributes.uv;
// 获取顶点颜色(可选)
const color = geometry.attributes.color;常用顶点属性说明:
| 属性名 | 数据类型 | 说明 |
|---|---|---|
| position | Float32Array | 顶点位置(x, y, z) |
| normal | Float32Array | 顶点法线方向 |
| uv | Float32Array | 纹理坐标(u, v) |
| uv2 | Float32Array | 第二组纹理坐标 |
| color | Float32Array | 顶点颜色(RGB) |
| index | Uint16Array/Uint32Array | 顶点索引 |
边界信息
边界信息用于视锥剔除、碰撞检测等。
// 计算边界球
geometry.computeBoundingSphere();
console.log('边界球半径:', geometry.boundingSphere.radius);
console.log('边界球中心:', geometry.boundingSphere.center);
// 计算边界框
geometry.computeBoundingBox();
console.log('边界框最小点:', geometry.boundingBox.min);
console.log('边界框最大点:', geometry.boundingBox.max);
// 获取几何体中心
const center = new THREE.Vector3();
geometry.computeBoundingBox();
geometry.boundingBox.getCenter(center);几何体变换
直接修改几何体顶点数据的变换方法:
// 平移
geometry.translate(x, y, z);
// 旋转
geometry.rotateX(angle);
geometry.rotateY(angle);
geometry.rotateZ(angle);
// 缩放
geometry.scale(x, y, z);
// 居中(将几何体中心移到原点)
geometry.center();几何体变换会直接修改顶点数据,与 Mesh 的 position、rotation、scale 属性不同。后者是通过变换矩阵实现的,不会修改几何体数据。
使用示例
创建多个几何体
import * as THREE from 'three';
// 创建场景、相机、渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建材质
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
// 创建多个几何体
const box = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
material
);
box.position.set(-3, 0, 0);
scene.add(box);
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(0.5, 32, 32),
material
);
sphere.position.set(0, 0, 0);
scene.add(sphere);
const cylinder = new THREE.Mesh(
new THREE.CylinderGeometry(0.5, 0.5, 1, 32),
material
);
cylinder.position.set(3, 0, 0);
scene.add(cylinder);
// 添加光源
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 5, 5);
scene.add(light);
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
camera.position.z = 5;
// 动画循环
function animate() {
requestAnimationFrame(animate);
box.rotation.x += 0.01;
box.rotation.y += 0.01;
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
cylinder.rotation.x += 0.01;
cylinder.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();使用线框模式
// 方法一:材质线框模式
const geometry = new THREE.IcosahedronGeometry(1, 0);
const wireframeMaterial = new THREE.MeshBasicMaterial({
color: 0x00ff00,
wireframe: true
});
const wireframeMesh = new THREE.Mesh(geometry, wireframeMaterial);
scene.add(wireframeMesh);
// 方法二:使用 WireframeGeometry
const wireframeGeometry = new THREE.WireframeGeometry(geometry);
const line = new THREE.LineSegments(
wireframeGeometry,
new THREE.LineBasicMaterial({ color: 0x00ff00 })
);
scene.add(line);创建边缘几何体
// 创建立方体
const box = new THREE.BoxGeometry(1, 1, 1);
// 创建边缘几何体(阈值角度 15 度)
const edges = new THREE.EdgesGeometry(box, 15);
// 创建线条
const line = new THREE.LineSegments(
edges,
new THREE.LineBasicMaterial({ color: 0xffffff })
);
scene.add(line);性能考虑
分段数优化
分段数直接影响顶点数量和渲染性能:
// 低多边形风格(性能优先)
const lowPolySphere = new THREE.SphereGeometry(1, 8, 8);
// 顶点数:约 81 个
// 标准质量
const standardSphere = new THREE.SphereGeometry(1, 32, 32);
// 顶点数:约 1,056 个
// 高质量渲染(质量优先)
const highQualitySphere = new THREE.SphereGeometry(1, 64, 64);
// 顶点数:约 4,224 个LOD(细节层次)
根据距离使用不同细节级别的几何体:
function createSphereWithLOD() {
const lod = new THREE.LOD();
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
// 近距离:高质量
const highDetail = new THREE.Mesh(
new THREE.SphereGeometry(1, 32, 32),
material
);
lod.addLevel(highDetail, 0);
// 中距离:中等质量
const mediumDetail = new THREE.Mesh(
new THREE.SphereGeometry(1, 16, 16),
material
);
lod.addLevel(mediumDetail, 10);
// 远距离:低质量
const lowDetail = new THREE.Mesh(
new THREE.SphereGeometry(1, 8, 8),
material
);
lod.addLevel(lowDetail, 20);
return lod;
}几何体复用
相同形状的对象应共享几何体实例:
// ❌ 不推荐:每个网格创建新几何体
for (let i = 0; i < 100; i++) {
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = i * 2;
scene.add(mesh);
}
// ✅ 推荐:复用几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
for (let i = 0; i < 100; i++) {
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = i * 2;
scene.add(mesh);
}内存管理
几何体使用后需要正确释放内存:
// 创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 不再需要时
scene.remove(mesh);
geometry.dispose(); // 释放几何体 GPU 内存
material.dispose(); // 释放材质内存几何体对比速查表
| 几何体 | 典型顶点数* | 适用场景 | 性能影响 |
|---|---|---|---|
| BoxGeometry | 24 | 建筑、家具、UI 元素 | 低 |
| PlaneGeometry | 4 | 地面、墙壁、广告牌 | 极低 |
| SphereGeometry | 513 | 行星、球体物体 | 中 |
| CylinderGeometry | 130 | 管道、柱子 | 低-中 |
| ConeGeometry | 65 | 屋顶、冰淇淋 | 低 |
| TorusGeometry | 806 | 甜甜圈、轮胎 | 中 |
| TorusKnotGeometry | 1,793 | 装饰、抽象图形 | 高 |
| IcosahedronGeometry | 12 | 低多边形球体、粒子 | 极低 |
*基于默认分段参数
常见问题解答
Q: 为什么我的球体看起来不圆滑?
A: 增加分段数参数。球体的圆滑度由 widthSegments 和 heightSegments 参数决定:
// 锯齿明显的球体
const roughSphere = new THREE.SphereGeometry(1, 8, 8);
// 圆滑的球体
const smoothSphere = new THREE.SphereGeometry(1, 64, 64);Q: 如何创建空心圆柱?
A: 使用 openEnded: true 参数:
const hollowCylinder = new THREE.CylinderGeometry(1, 1, 2, 32, 1, true);Q: 平面几何体默认朝向哪里?
A: PlaneGeometry 默认在 XY 平面上,面朝 +Z 方向。如需改变朝向,可以旋转:
const plane = new THREE.PlaneGeometry(2, 2);
plane.rotateX(-Math.PI / 2); // 水平放置,面朝 +YQ: 如何获取几何体的实际尺寸?
A: 使用边界框计算:
const geometry = new THREE.BoxGeometry(2, 3, 1);
geometry.computeBoundingBox();
const size = new THREE.Vector3();
geometry.boundingBox.getSize(size);
console.log('尺寸:', size); // Vector3 {x: 2, y: 3, z: 1}Q: 几何体变换和 Mesh 变换有什么区别?
A:
- 几何体变换(
geometry.translate()):直接修改顶点数据,影响所有使用该几何体的网格 - Mesh 变换(
mesh.position):通过变换矩阵实现,不修改几何体数据,可逆
// 几何体变换 - 永久修改顶点
const geo1 = new THREE.BoxGeometry(1, 1, 1);
geo1.translate(2, 0, 0);
// Mesh 变换 - 不修改几何体
const geo2 = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geo2, material);
mesh.position.set(2, 0, 0);Q: 如何选择合适的分段数?
A: 根据以下因素权衡:
- 物体距离相机的远近:远距离物体可用较少分段
- 物体大小:大型物体需要更多分段
- 性能预算:移动端或复杂场景应减少分段
- 视觉效果需求:重要展示物体可增加分段
推荐值:
- 球体:
widthSegments: 32, heightSegments: 32 - 圆柱:
radialSegments: 32 - 圆环:
radialSegments: 16, tubularSegments: 48
最佳实践
- 合理设置分段数:根据距离和重要性设置合适的分段数,平衡质量和性能
- 复用几何体:相同形状的对象共享几何体实例,减少内存和 GPU 开销
- 及时释放内存:不再使用的几何体调用
dispose()方法释放 GPU 内存 - 使用边界检测:通过边界框/球进行视锥剔除优化
- 选择合适几何体:根据需求选择最简单的几何体类型
- 预计算边界:在创建几何体后立即调用
computeBoundingBox()和computeBoundingSphere() - 使用索引缓冲区:对于复杂几何体,使用索引可以减少顶点数据量