4、几何体基础:BoxGeometry、SphereGeometry、CylinderGeometry、PlaneGeometry的创建与参数
好,咱们今天来聊聊 Three.js 里最基础的四个几何体。说白了,它们就是 3D 世界的「乐高积木」。你想想看,不管多复杂的模型,拆开来看,基本都能找到这些基础形状的影子。
我个人习惯,每次新建项目,都会先拿这四个几何体练手。为什么?因为它们的参数最直观,能帮你快速验证光照、材质、相机这些核心概念是否配置正确。我记得刚学 Three.js 那会儿,就靠来回调这几个几何体的参数,把整个渲染管线摸了个透。
4.1 BoxGeometry:最常用的「方盒子」
BoxGeometry,就是长方体。你看到的很多建筑、箱子、甚至 UI 面板,底层都是它。
它的构造函数长这样:
const geometry = new THREE.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments);
前三个参数好理解:宽、高、深。后三个参数是分段数,默认都是 1。
核心要点:分段数决定了几何体的顶点密度。分段越多,顶点越多,你就能做更精细的形变操作(比如弯曲、扭曲)。但如果只是做个静态的方块,分段保持 1 就行,别浪费性能。
我的小技巧:调试阶段,我习惯把分段数设成 2 或 3。这样在浏览器里能清楚看到网格线的走向,方便我理解 UV 贴图的映射关系。
举个例子,创建一个 2x1x0.5 的扁平盒子:
const boxGeo = new THREE.BoxGeometry(2, 1, 0.5);
const boxMat = new THREE.MeshStandardMaterial({ color: 0x44aa88 });
const boxMesh = new THREE.Mesh(boxGeo, boxMat);
scene.add(boxMesh);
4.2 SphereGeometry:圆滑的「球体」
球体在游戏里太常见了——星球、弹珠、甚至角色的头部。它的参数比盒子多一些,但核心逻辑就一个:用经纬线来逼近一个完美的圆。
const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength);
这里我重点说几个关键参数:
- radius:半径,默认 1。
- widthSegments:水平分段数(经线),默认 32。数值越大,球越圆,但顶点也越多。
- heightSegments:垂直分段数(纬线),默认 16。
- phiStart / phiLength:水平方向的起始角度和跨度。可以用来切出「西瓜瓣」效果。
- thetaStart / thetaLength:垂直方向的起始角度和跨度。可以用来切出「碗状」效果。
我曾经踩过的坑:做移动端项目时,我把球体的分段数设成了 64x64,结果在低端手机上直接卡成 PPT。后来我学乖了,移动端用 24x16 就够,PC 端用 48x32 也绰绰有余。别盲目追求圆滑,性能才是王道。
创建一个标准球体:
const sphereGeo = new THREE.SphereGeometry(1, 32, 16);
const sphereMat = new THREE.MeshStandardMaterial({ color: 0xff6633, roughness: 0.3 });
const sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
sphereMesh.position.x = 3;
scene.add(sphereMesh);
4.3 CylinderGeometry:不只是「圆柱」
CylinderGeometry 的名字叫圆柱,但它的能力远不止于此。你可以用它做柱子、做锥体、甚至做六角螺母。
const geometry = new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength);
注意看前两个参数:radiusTop 和 radiusBottom。如果它们相等,就是标准圆柱。如果顶部半径设为 0,底部半径保持 1,你就得到了一个圆锥。
| 参数 | 说明 | 我的常用值 |
|---|---|---|
| radiusTop | 顶部半径 | 1(圆柱)或 0(圆锥) |
| radiusBottom | 底部半径 | 1 |
| height | 高度 | 2 |
| radialSegments | 圆周分段数 | 8(做六边形)或 32(做圆滑柱) |
| openEnded | 是否去掉顶底盖 | false(默认有盖) |
实用场景:把 radialSegments 设为 6,你就得到了一个六棱柱。我在做塔防游戏时,就用这个参数快速生成了各种炮塔底座,省去了建模的麻烦。
创建一个圆锥:
const coneGeo = new THREE.CylinderGeometry(0, 1, 2, 32);
const coneMat = new THREE.MeshStandardMaterial({ color: 0x33aaff });
const coneMesh = new THREE.Mesh(coneGeo, coneMat);
coneMesh.position.x = -3;
scene.add(coneMesh);
4.4 PlaneGeometry:被忽视的「平面」
PlaneGeometry 看起来最简单,就一个矩形面。但它的用途其实很广——地面、墙面、公告板、甚至粒子系统的发射面。
const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
参数和 BoxGeometry 的前四个参数类似。但有个关键点:PlaneGeometry 默认是单面渲染的。你从背面看,它是透明的。
注意:如果你把 PlaneGeometry 当作地面,记得旋转它。默认它是在 XY 平面上的,而地面通常需要放在 XZ 平面上。我刚开始就忘了这茬,结果地面「竖」在了场景里,找了半天 bug。
正确的做法:
const planeGeo = new THREE.PlaneGeometry(10, 10);
const planeMat = new THREE.MeshStandardMaterial({ color: 0xcccccc, side: THREE.DoubleSide });
const planeMesh = new THREE.Mesh(planeGeo, planeMat);
planeMesh.rotation.x = -Math.PI / 2; // 旋转到水平
planeMesh.position.y = -1;
scene.add(planeMesh);
我的经验:做地面时,我习惯把 side 设为 THREE.DoubleSide。虽然多渲染一面,但能避免相机穿模时看到「空洞」的尴尬。另外,分段数设高一点(比如 10x10),方便后续做地形起伏。
4.5 四个几何体的对比总结
好了,四个几何体都过了一遍。我最后用一张表帮你理清思路:
| 几何体 | 核心参数 | 典型用途 | 避坑点 |
|---|---|---|---|
| BoxGeometry | 宽、高、深、分段 | 建筑、箱子、UI面板 | 静态物体分段保持 1 |
| SphereGeometry | 半径、经纬分段 | 星球、弹珠、角色头部 | 移动端分段别超过 24x16 |
| CylinderGeometry | 顶底半径、高度、圆周分段 | 柱子、锥体、螺母 | 调整顶底半径可做圆锥 |
| PlaneGeometry | 宽、高、分段 | 地面、墙面、公告板 | 默认单面,记得旋转到 XZ 平面 |
嗯,到这里,四个基础几何体就讲完了。你可能会问:「就这?也太简单了吧?」没错,就是简单。但简单的东西往往最实用。我做了这么多年项目,90% 的场景都离不开这四个形状。关键是你要理解它们的参数含义,知道什么时候该调什么值。
下一章,咱们会把这些几何体组合起来,做一些更有趣的东西。到时候你就知道,今天打下的基础有多重要了。