
Three.js CylinderGeometry 圆柱几何体完整解析从构造参数到底层顶点生成原理【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js本文基于 three.js 官方文档中CylinderGeometry类页面展开系统讲解圆柱几何体的 8 个构造参数、默认值及其底层含义含锥台、扇形截面、多材质分组等进阶用法并结合 CylinderGeometry.js 源码逐段剖析顶点、法线、UV 与索引的实际生成过程。读完本文你不仅能正确使用CylinderGeometry创建圆柱、锥台、开口管体等几何体还能理解heightSegments为何影响变形与 UV、openEnded与半径为零时底层做了什么取舍以及.parameters与fromJSON在几何体序列化中的作用。继承关系与基本用法CylinderGeometry是用于表示圆柱体的几何类A geometry class for representing a cylinder其继承链为EventDispatcher → BufferGeometry → CylinderGeometry在 CylinderGeometry.js 中可以看到类声明为class CylinderGeometry extends BufferGeometry构造函数中立即执行this.type CylinderGeometry该字符串用于序列化时标识几何体类型与fromJSON配合使用。它通过 Geometries.js 统一导出属于 Three.Core 的基础几何模块因此可以按模块按需引入。文档给出的最小可用示例如下const geometry new THREE.CylinderGeometry( 5, 5, 20, 32 ); const material new THREE.MeshBasicMaterial( { color: 0xffff00 } ); const cylinder new THREE.Mesh( geometry, material ); scene.add( cylinder );这里半径上下同为5即为正圆柱若上下半径不同则得到锥台圆台。仓库示例 webgl_geometries.html 中就展示了非正圆柱的用法new THREE.CylinderGeometry( 25, 75, 100, 40, 5 )即下底半径 75、上底半径 25 的锥台。此外仓库还附带了可视化调试页面 geometry-browser.html可以在线调整圆柱各参数实时观察网格变化比静态文档更直观。构造函数8 个参数逐一解读构造签名为new CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength )参数含义默认值radiusTop圆柱顶部半径1radiusBottom圆柱底部半径1height圆柱高度1radialSegments沿圆周方向水平一圈的分割面数量32heightSegments沿高度方向的行数竖直切分1openEnded底面顶/底盖是开放还是封闭falsethetaStart第一个分段起始角弧度0thetaLength圆心角theta弧度默认值生成完整圆柱Math.PI * 2从源码构造函数CylinderGeometry.js可以补充两点文档未展开的细节分段数会被取整radialSegments与heightSegments传入浮点数时会执行Math.floor()即只取整数部分参与网格生成。参数被完整记录8 个参数原样存入this.parameters对象实例化后修改它不会重建几何体这一点与文档中.parameters的说明完全一致。参数之间的隐性联动radiusTop与radiusBottom决定形态二者相等是正圆柱radiusTop radiusBottom是锥台任一为0时该端面退化为尖点/线且源码会跳过该端盖片的生成见下文generateCap条件。正因如此ConeGeometry.js 中的锥体实现极简——ConeGeometry直接继承CylinderGeometry并在构造函数里调用super( 0, radius, height, ... )把顶部半径固定为 0。也就是说圆锥在 three.js 中本质上就是上底半径为 0 的圆柱。radialSegments决定侧面精度一圈被切成多少个竖直面片。侧面顶点按x radius * sin(theta)、z radius * cos(theta)排布CylinderGeometry.js段数越大圆柱越接近光滑。heightSegments决定竖直方向行数侧面被切成heightSegments行四边形。它直接影响能否做皮肤化/顶点位移类变形行数越多越能沿高度弯曲并影响 UV 在竖直方向的分布密度。thetaStart/thetaLength决定角度范围默认0与2π构成完整圆柱例如thetaLength: Math.PI得到半圆柱thetaLength: Math.PI / 2得到四分之一圆柱。测试用例 CylinderGeometry.tests.js 中使用了thetaStart: 0.1, thetaLength: 2.0这类非完整扇形参数验证了部分圆柱的构造路径。底层实现几何数据是如何生成的阅读 CylinderGeometry.js 构造函数主体可以把它拆成三个生成阶段。1. 侧面generateTorso核心循环按行y与列x遍历顶点对每一行计算当前行半径radius v * (radiusBottom - radiusTop) radiusTopv 从 0 到 1即从上到下线性插值上下半径再按角度计算x radius * sinTheta、y -v * height halfHeight、z radius * cosTheta。注意 y 坐标以几何中心为原点圆柱竖直居中于 Y 轴。法线slope (radiusBottom - radiusTop) / height法线方向为normalize(sinTheta, slope, cosTheta)CylinderGeometry.js。正圆柱 slope 为 0法线纯水平锥台法线会向外倾斜。同一列上的所有顶点共享同一法线方向这也是侧面能呈现平滑着色的原因。UV推入(u, 1 - v)即 u 对应圆周方向 0→1v 对应从底到顶 0→1。索引相邻四角 a、b、c、d 组成两个三角形(a, b, d)与(b, c, d)。这里有一个细节当radiusTop 0时会跳过首行上方三角形radiusBottom 0时跳过末行下方三角形避免在锥尖处生成退化三角面。2. 端盖片generateCap仅当openEnded false时才生成且分别判断radiusTop 0生成顶盖、radiusBottom 0生成底盖CylinderGeometry.js。端盖的实现有两个值得注意的点每个扇形面都有独立的中心顶点。注释写明 the geometry needs one set of uvs per face, we must generate a center vertex per face/segment即为了让每个盖片三角形拥有独立的 UV 采样点中心 UV 固定为0.5, 0.5每个分段都要生成一个位于盖面中心的重复顶点。盖片 UV 映射到单位圆盘外圈顶点 UV 按0.5 cos/sin * 0.5计算使顶/底面纹理呈圆形分布与侧面的展开矩形UV 布局不同。3. 构建 BufferGeometry 与多材质分组生成结束后通过setIndex与setAttribute挂载position3 分量、normal3 分量、uv2 分量四类数据。更关键的是分组逻辑侧面调用addGroup( groupStart, groupCount, 0 )顶盖为材料索引1底盖为材料索引2CylinderGeometry.js。源码注释说明 this will ensure multi material support——这意味着你可以给一个圆柱 Mesh 传一个材质数组让侧面与顶/底面使用不同材质例如侧面包金属纹理、底面用黑色无需拆分多个 Mesh。属性与静态方法.parameters : Object保存用于生成该几何体的构造参数对象8 个字段与构造函数一一对应见 CylinderGeometry.js。它是构造记录而非几何体配置实例化后修改parameters不改变任何顶点数据。其实际用途是序列化——导出几何体如 GLTF时可以把 parameters 写入 JSON加载端据此重建几何体。.copy( source )文档页面未单列但源码中定义了copy方法CylinderGeometry.js先调用父类BufferGeometry.copy复制缓冲数据再用Object.assign( {}, source.parameters )深拷贝一层参数对象。当你用geometry.copy( other )克隆圆柱时参数会一并迁移。.fromJSON( data ) : CylinderGeometry静态工厂方法从序列化的 JSON 对象创建实例CylinderGeometry.jsstatic fromJSON( data ) { return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); }入参data是几何体序列化 JSON字段名与.parameters完全对应返回一个新实例。data.type CylinderGeometry正是前面提到的type字符串加载器通常据此分派到对应的fromJSON。与之对照ConeGeometry.js 的fromJSON则接收data.radius单半径字段而非radiusTop/radiusBottom两者字段格式不同序列化时需区分。测试用例给出的参数组合验证单测文件 CylinderGeometry.tests.js 覆盖了文档中所有参数及其组合可作为合法调用方式的参考清单const parameters { radiusTop: 10, radiusBottom: 20, height: 30, radialSegments: 20, heightSegments: 30, openEnded: true, thetaStart: 0.1, thetaLength: 2.0, }; geometries [ new CylinderGeometry(), // 全默认 new CylinderGeometry( parameters.radiusTop ), new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom ), // ... 依次递增到 8 参全量构造 ];测试还断言了两点object instanceof BufferGeometry为真继承链验证以及object.type CylinderGeometry。所有构造产物再经过runStdGeometryTests做通用几何体一致性校验索引范围、属性长度等。这说明 8 个参数按顺序任意截断均合法且非默认角度范围如thetaLength: 2.0弧度是被官方测试认可的用法。常见进阶用法速查结合文档参数语义与源码行为整理几种典型场景需求构造方式说明正圆柱new CylinderGeometry( r, r, h, 32 )上下半径相同圆锥new THREE.ConeGeometry( r, h, 32 )等价于CylinderGeometry( 0, r, h, ... )圆台/锥台new CylinderGeometry( rTop, rBottom, h )侧面法线自动按 slope 倾斜开口管new CylinderGeometry( r, r, h, 32, 1, true )openEndedtrue不生成顶底盖半圆柱new CylinderGeometry( r, r, h, 32, 1, false, 0, Math.PI )thetaLength控制扇形角度侧面/底面不同材质Mesh 传材质数组[sideMat, topMat, bottomMat]依赖 group 的材料索引 0/1/2沿高度变形增大heightSegments更多顶点行才能支撑位移/弯曲需要留意的前提与限制本文所述行为基于当前仓库版本的源码radialSegments、heightSegments传入小于 1 的值会产生空网格生产代码建议做下限保护。端盖顶点是按分段重复生成的每段一个中心顶点因此radialSegments同时影响侧面与盖片顶点数若用低分段数配合openEndedfalse盖片纹理精度会随分段数下降。.parameters仅记录构造时的原始值几何体后续若被其他工具如修改器二次处理parameters 不会随之更新。参考路径汇总类文档页docs/pages/CylinderGeometry.html.md核心实现src/geometries/CylinderGeometry.js锥体继承实现src/geometries/ConeGeometry.js模块导出src/geometries/Geometries.js单元测试test/unit/src/geometries/CylinderGeometry.tests.js官方示例examples/webgl_geometries.html、examples/misc_uv_tests.html参数可视化调试页docs/scenes/geometry-browser.html【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考