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);

注意看前两个参数:radiusTopradiusBottom。如果它们相等,就是标准圆柱。如果顶部半径设为 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% 的场景都离不开这四个形状。关键是你要理解它们的参数含义,知道什么时候该调什么值。

下一章,咱们会把这些几何体组合起来,做一些更有趣的东西。到时候你就知道,今天打下的基础有多重要了。