第三篇:几何体入门:内置几何体全解析
引言
几何体是Three.js世界的基石,它们定义了3D物体的形状和结构。Three.js提供20+种内置几何体,从基础立方体到复杂多面体,覆盖90%的3D建模需求。本文将深入解析12种核心几何体,并通过Vue3实现交互式参数调节面板,助你掌握几何造型的核心技术。
1. 几何体核心概念
1.1 顶点(Vertex)与面(Face)
几何体由两大基本元素构成:
- 顶点(Vertex):3D空间中的点,包含(x,y,z)坐标
- 面(Face):由三个顶点组成的三角形(Three.js仅支持三角面)
- 示例:立方体有8个顶点和12个面(6个面×2个三角形)
1.2 几何体类型对比
几何体名称 | 顶点数 | 面数 | 主要参数 | 应用场景 |
---|---|---|---|---|
BoxGeometry | 8 | 12 | 宽/高/深 | 建筑/家具 |
SphereGeometry | 482 | 960 | 半径/分段数 | 星球/粒子 |
CylinderGeometry | 136 | 240 | 顶径/底径/高度 | 柱体/管道 |
TorusGeometry | 800 | 1600 | 半径/管道径/分段数 | 圆环/轮胎 |
IcosahedronGeometry | 12 | 20 | 半径/细节层级 | 低模球体 |
2. 12大核心几何体详解
2.1 立方体(BoxGeometry)
<script setup>
import { ref } from 'vue';
const boxParams = ref({
width: 1,
height: 1,
depth: 1,
widthSegments: 1,
heightSegments: 1,
depthSegments: 1
});
// 创建立方体
const createBox = () => {
return new THREE.BoxGeometry(
boxParams.value.width,
boxParams.value.height,
boxParams.value.depth,
boxParams.value.widthSegments,
boxParams.value.heightSegments,
boxParams.value.depthSegments
);
};
</script>
参数解析:
widthSegments
:宽度分段数(影响表面细分)- 当分段数>1时,可用于变形动画或曲面效果
2.2 球体(SphereGeometry)
const sphere = new THREE.SphereGeometry(
1, // 半径
32, // 经度分段数(水平细分数)
16, // 纬度分段数(垂直细分数)
0, // 水平起始角度(0-Math.PI*2)
Math.PI * 2, // 水平覆盖角度
0, // 垂直起始角度(0-Math.PI)
Math.PI // 垂直覆盖角度
);
分段数影响:
2.3 圆柱体(CylinderGeometry)
const cylinder = new THREE.CylinderGeometry(
0.5, // 顶部半径
1, // 底部半径
2, // 高度
16, // 径向分段数
4, // 高度分段数
false // 是否开启顶盖/底盖
);
特殊形态:
- 圆锥:顶部半径=0
- 棱柱:分段数=4/6/8
- 圆台:顶部半径≠底部半径
2.4 圆环(TorusGeometry)
const torus = new THREE.TorusGeometry(
1, // 圆环半径
0.3, // 管道半径
16, // 径向分段数
100, // 管道分段数
Math.PI * 2 // 圆弧角度(缺省为整圆)
);
应用场景:行星环、戒指、管道弯曲
3. 其他实用几何体
3.1 平面(PlaneGeometry)
const plane = new THREE.PlaneGeometry(
10, // 宽度
10, // 高度
10, // 宽度分段
10 // 高度分段
);
用途:地面、水面、公告板
3.2 圆环缓冲(TorusKnotGeometry)
const knot = new THREE.TorusKnotGeometry(
1, // 半径
0.3, // 管道半径
100, // 管道分段
16, // 交叉分段
2, // P值(控制缠绕次数)
3 // Q值(控制围绕轴旋转次数)
);
数学原理:通过参数方程生成复杂拓扑结构
3.3 二十面体(IcosahedronGeometry)
const ico = new THREE.IcosahedronGeometry(
1, // 半径
2 // 细节层级(0=基础,每+1细分4倍面数)
);
特点:最接近球体的多面体,常用于低模风格
4. Vue3实战:几何体参数调节器
4.1 项目结构
src/
├── components/
│ ├── GeometryController.vue // 参数控制面板
│ ├── GeometryViewer.vue // 3D显示组件
│ └── ParamSlider.vue // 通用滑动条
└── App.vue
4.2 核心代码实现
<!-- GeometryController.vue -->
<script setup>
import { ref, watch } from 'vue';
// 支持的几何体类型
const GEOMETRY_TYPES = {
BOX: 'Box',
SPHERE: 'Sphere',
CYLINDER: 'Cylinder',
TORUS: 'Torus'
};
const currentType = ref(GEOMETRY_TYPES.BOX);
// 几何体参数响应式对象
const params = ref({
// 立方体参数
[GEOMETRY_TYPES.BOX]: {
width: 2, height: 1, depth: 1,
widthSegments: 1, heightSegments: 1, depthSegments: 1
},
// 球体参数
[GEOMETRY_TYPES.SPHERE]: {
radius: 1, widthSegments: 32, heightSegments: 16,
phiStart: 0, phiLength: Math.PI * 2,
thetaStart: 0, thetaLength: Math.PI
},
// 圆柱体参数
[GEOMETRY_TYPES.CYLINDER]: {
radiusTop: 0.5, radiusBottom: 1, height: 2,
radialSegments: 32, heightSegments: 8
},
// 圆环参数
[GEOMETRY_TYPES.TORUS]: {
radius: 1, tube: 0.3, radialSegments: 100, tubularSegments: 16
}
});
// 生成当前几何体的配置项
const currentParams = computed(() => ({
type: currentType.value,
...params.value[currentType.value]
}));
// 发射更新事件
const emit = defineEmits(['update']);
watch(currentParams, (val) => {
emit('update', val);
}, { deep: true });
</script>
<template>
<div class="controller">
<select v-model="currentType">
<option v-for="(type, key) in GEOMETRY_TYPES" :value="type" :key="key">
{{ type }}
</option>
</select>
<template v-if="currentType === GEOMETRY_TYPES.BOX">
<ParamSlider label="宽度" v-model="params.BOX.width" :min="0.1" :max="5" :step="0.1"/>
<ParamSlider label="高度" v-model="params.BOX.height" :min="0.1" :max="5" :step="0.1"/>
<ParamSlider label="深度" v-model="params.BOX.depth" :min="0.1" :max="5" :step="0.1"/>
<!-- 其他参数 -->
</template>
<!-- 其他几何体参数控制 -->
</div>
</template>
4.3 几何体动态更新
<!-- GeometryViewer.vue -->
<script setup>
import { ref, watch } from 'vue';
import * as THREE from 'three';
const props = defineProps(['geometryParams']);
let geometry = ref(null);
let mesh = ref(null);
// 根据参数创建几何体
const createGeometry = (params) => {
switch(params.type) {
case 'Box':
return new THREE.BoxGeometry(...Object.values(params));
case 'Sphere':
return new THREE.SphereGeometry(...Object.values(params));
// 其他几何体...
}
};
// 监听参数变化
watch(() => props.geometryParams, (newParams) => {
// 释放旧几何体内存
if (geometry.value) geometry.value.dispose();
// 创建新几何体
geometry.value = createGeometry(newParams);
// 更新网格
if (mesh.value) {
mesh.value.geometry = geometry.value;
} else {
const material = new THREE.MeshNormalMaterial();
mesh.value = new THREE.Mesh(geometry.value, material);
scene.add(mesh.value);
}
}, { immediate: true });
</script>
4.4 性能优化:几何体复用
// 使用BufferGeometryUtils合并几何体
import { mergeBufferGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils';
const geometries = [];
for (let i = 0; i < 100; i++) {
const box = new THREE.BoxGeometry(0.2, 0.2, 0.2);
box.translate(Math.random()*10-5, Math.random()*10-5, Math.random()*10-5);
geometries.push(box);
}
// 合并为单个几何体(减少Draw Call)
const mergedGeometry = mergeBufferGeometries(geometries);
const mesh = new THREE.Mesh(mergedGeometry, material);
scene.add(mesh);
5. 几何体操作进阶技巧
5.1 顶点修改:创建波浪平面
const plane = new THREE.PlaneGeometry(10, 10, 50, 50);
const positions = plane.attributes.position.array;
// 遍历顶点添加波浪效果
for (let i = 0; i < positions.length; i += 3) {
const x = positions[i];
const z = positions[i+2];
// 使用正弦函数生成高度
positions[i+1] = Math.sin(x * 0.5) * Math.cos(z * 0.5) * 1.5;
}
// 通知Three.js更新
plane.attributes.position.needsUpdate = true;
5.2 UV坐标操作:纹理映射
const geometry = new THREE.BoxGeometry(2, 2, 2);
const uvs = geometry.attributes.uv.array;
// 修改UV坐标实现特殊纹理映射
for (let i = 0; i < uvs.length; i += 2) {
uvs[i] *= 2; // U坐标拉伸
uvs[i+1] *= 2; // V坐标拉伸
}
geometry.attributes.uv.needsUpdate = true;
// 应用纹理
const texture = new THREE.TextureLoader().load('brick.jpg');
const material = new THREE.MeshBasicMaterial({ map: texture });
5.3 法线重计算
geometry.computeVertexNormals(); // 自动计算法线
// 手动修改法线
const normals = geometry.attributes.normal.array;
for (let i = 0; i < normals.length; i += 3) {
normals[i] = 0; // X分量
normals[i+1] = 1; // Y分量(指向正上方)
normals[i+2] = 0; // Z分量
}
geometry.attributes.normal.needsUpdate = true;
6. 性能优化指南
6.1 几何体选择策略
graph TD
A[选择几何体] --> B{需要变形?}
B -->|是| C[高分段几何体]
B -->|否| D{静态物体?}
D -->|是| E[使用BufferGeometry]
D -->|否| F[使用基础几何体]
6.2 内存管理最佳实践
几何体复用:相同物体共享几何体
const boxGeometry = new THREE.BoxGeometry(); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const mesh1 = new THREE.Mesh(boxGeometry, material); const mesh2 = new THREE.Mesh(boxGeometry, material.clone());
及时释放内存:
// 组件卸载时 onUnmounted(() => { geometry.dispose(); material.dispose(); });
避免每帧创建:在动画循环外创建几何体
6.3 实例化渲染(InstancedMesh)
const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const material = new THREE.MeshBasicMaterial();
const instances = new THREE.InstancedMesh(geometry, material, 1000);
// 设置每个实例的位置和旋转
const matrix = new THREE.Matrix4();
for (let i = 0; i < 1000; i++) {
matrix.setPosition(
Math.random() * 100 - 50,
Math.random() * 100 - 50,
Math.random() * 100 - 50
);
instances.setMatrixAt(i, matrix);
}
scene.add(instances);
性能提升:1000个立方体,Draw Call从1000次降为1次
7. 常见问题解答
Q1:如何创建自定义形状?
- 简单形状:组合基础几何体(Group)
- 复杂形状:使用
BufferGeometry
手动设置顶点 - 专业建模:Blender创建后导出GLTF
Q2:几何体分段数设置多少合适?
- 静态物体:低分段(如Box用1x1x1)
- 曲面物体:32-64分段(球体/圆柱)
- 变形物体:≥64分段(波浪平面)
- 性能临界点:单物体面数<10000
Q3:几何体显示为黑色怎么办?
- 检查材质是否需要光照(
MeshBasicMaterial
不受光) - 确认场景中有灯光
- 验证法线方向是否正确(使用
MeshNormalMaterial
调试)
8. 总结
通过本文,你已掌握:
- 12种核心几何体的创建与参数配置
- 顶点(Vertex)与面(Face)的底层原理
- Vue3实现几何体参数实时调节器
- 几何体内存管理与性能优化技巧
- 高级操作:顶点修改、UV映射、法线计算
关键点:Three.js中所有几何体最终都转换为
BufferGeometry
,它使用TypedArray
直接操作二进制数据,比传统Geometry
性能提升3-5倍。
下一篇预告
第四篇:材质与纹理:让物体"真实"起来
你将学习:
- 6种核心材质特性对比(Basic/Standard/Physical)
- 纹理贴图技术:漫反射/法线/环境遮挡贴图
- UV映射原理与自定义UV展开
- PBR(物理渲染)材质工作流
- Vue3实现材质实时编辑器
准备好为几何体注入灵魂了吗?让我们进入Three.js的视觉魔法世界!