
three.js PolyhedronGeometry 深入解析顶点投影与球面细分算法实战指南【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js本篇指南围绕 three.js 的核心几何类PolyhedronGeometry展开介绍如何通过扁平顶点数组 索引数组描述任意多面体并利用球面投影与细分算法将其平滑化为球状网格。读完你将掌握PolyhedronGeometry的构造参数语义、底层三角剖分流程、法线与 UV 生成策略以及派生多面体类Tetrahedron/Octahedron/Icosahedron/Dodecahedron的实现方式与适用场景。PolyhedronGeometry 是什么PolyhedronGeometry是 three.js 中用于生成正/任意多面体的几何基类。多面体Polyhedron是三维空间中由平面面片围成的立体其几何数据源自 src/geometries/PolyhedronGeometry.js。该类的核心思想并不复杂接收一组描述基础形状的顶点与面索引先把它们全部投影到球面上再按需求细分为指定细节级别的网格。这也是它区别于BoxGeometry、SphereGeometry等确定性几何的关键——输入数据完全由调用方定义因此既可以构造正四面体、正十二面体等柏拉图立体也可以构造任意自定义的多面体形状。在继承体系上类注释标明augments BufferGeometry即直接继承自BufferGeometry其顶层父类为EventDispatcher。构造完成后它最终会输出position、normal、uv三个 buffer attribute供Mesh直接渲染使用。构造函数与参数说明new PolyhedronGeometry( vertices : Array.number, indices : Array.number, radius : number, detail : number )源码中构造函数的四个参数均有默认值见 src/geometries/PolyhedronGeometry.js参数类型默认值说明verticesArray.number[]描述基础形状的扁平顶点数组按[x0,y0,z0, x1,y1,z1, …]排布每组 3 个数构成一个三维坐标indicesArray.number[]描述基础形状的扁平索引数组每 3 个数构成一个三角形面片的三个顶点下标radiusnumber1形状的半径所有顶点最终会被投影到以原点为球心、半径为radius的球面上detailnumber0细分层级整数数值越大细分产生的面与顶点越多形状越平滑vertices 与 indices 的组织约定vertices必须以三个一组连续存放顶点坐标。例如下方这份来自单元测试 test/unit/src/geometries/PolyhedronGeometry.tests.js 的数据描述了一个四面体const vertices [ 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 ]; const indices [ 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 ];注意索引是三角形面片级的每 3 个下标构成一个三角面上例 12 个索引即代表 4 个三角面恰好拼出一个四面体的闭合表面。索引引用的下标以vertices中顶点序号 × 3作为数据偏移对应源码中按index * 3读取坐标的getVertexByIndex逻辑见 src/geometries/PolyhedronGeometry.js。源码注释与 JSDoc 均强调detail表示对该几何细分多少个层级细分越多形状越平滑。此外从源码看detail在细分流程中实际按整数使用生成detail 1列网格工程实践中请传入非负整数。构造流程与底层算法剖析构造器内部并非简单地把输入顶点拷成 buffer而是走了一条细分 → 球面投影 → 生成 UV的完整流水线见 src/geometries/PolyhedronGeometry.jssubdivide( detail )—— 将输入的多边形面按 detail 逐面细分展开为小三角面片并写入顶点缓冲区applyRadius( radius )—— 对所有新生成顶点做归一化并乘上半径将其贴到目标球面上generateUVs()—— 依据球面方位角/倾角计算 UV 坐标并修复接缝设置position、normal、uv三个 attribute依据detail取值决定法线策略。细分把每个三角面插值成网格subdivide遍历indices中每个三角面逐面调用subdivideFace见 src/geometries/PolyhedronGeometry.js。其插值算法为取cols detail 1对三角形两条边a→c、b→c分别做参数i/cols的线性插值得到aj、bj再用j/rows在aj→bj之间二次插值构造出三角网格的顶点阵行列循环中按上三角行数递减的方式切分出两套小三角形j为偶数/奇数时三角形朝向不同从而把原始大三角替换为更细密的面片。当detail 0时该流程不新增中间顶点输出即为原始多边形表面。球面投影normalize 后再缩放applyRadius见 src/geometries/PolyhedronGeometry.js逐顶点执行vertex.normalize().multiplyScalar( radius );normalize()使每个方向向量落在单位球上再乘以radius放大到目标尺寸。这是把立方体棱角磨圆成球的关键一步——所有细分出的顶点最终都精确地位于半径radius的球面上这也是为什么该几何常被当作各类球状网格的低多边形变体。法线策略flat 还是 smooth源码末尾见 src/geometries/PolyhedronGeometry.js按detail分流detail 0调用computeVertexNormals()按面片计算平面法线flat shading保留多面体棱角分明的硬边外观detail 0调用normalizeNormals()使用细分后的顶点方向向量直接作为法线本质是球面径向方向得到**平滑smooth**的球形明暗过渡。这也解释了一个常见直觉detail越大不仅几何更平滑光照过渡也随之变平滑。UV 生成与接缝修复细分与投影完成后generateUVs见 src/geometries/PolyhedronGeometry.js根据每个顶点的球面坐标计算 UVu azimuth(vertex) / 2π 0.5其中方位角azimuth atan2(z, -x)是绕 Y 轴、从上方俯视逆时针的角度v inclination(vertex) / π 0.5其中倾角inclination表示相对 XZ 平面的仰角UV 纵轴最终存为1 - v。随后依次执行两个校正函数correctUVs()对每个三角面先求面片质心的方位角再逐顶点判断是否需要把u环绕回[0,1]避免跨2π边界时 UV 大幅跳变correctSeam()修复跨越 UV 接缝seam的面——当某面三个u值的最大值超过 0.9 而最小值低于 0.1 时把小于 0.2 的u值整体加 1使纹理不会在背面缝合线处被错误拉伸。源码注释标明该修复针对的是 #3269 号历史问题见 src/geometries/PolyhedronGeometry.js。Properties 与 Methods.parameters : Object构造完成后实例会保存一份构造参数字面量this.parameters { vertices: vertices, indices: indices, radius: radius, detail: detail };如文档所述该对象保存生成几何所用的构造参数实例化之后的任何修改都不会改变已生成的几何。需要改变形状时必须重新构造实例。源码中该方法相关片段见 src/geometries/PolyhedronGeometry.js。该几何同时覆写了copy( source )会把源实例的parameters一并浅拷贝src/geometries/PolyhedronGeometry.js。.fromJSON( data : Object ) : PolyhedronGeometry静态工厂方法从序列化 JSON 重建几何见 src/geometries/PolyhedronGeometry.jsstatic fromJSON( data ) { return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.detail ); }反序列化时机、四个字段与构造参数一一对应。派生类如 IcosahedronGeometry各自覆写了fromJSON以仅传递自己暴露的参数radius/detail因此反序列化时会保持子类实例类型。派生多面体类无需自备数据的开箱方案手动书写vertices与indices较繁琐因此 three.js 基于PolyhedronGeometry预置了四类正多面体全部通过extends PolyhedronGeometry并在构造函数里传入各自预计算的顶点/索引表实现src/geometries/TetrahedronGeometry.js —— 正四面体src/geometries/OctahedronGeometry.js —— 正八面体src/geometries/IcosahedronGeometry.js —— 正二十面体src/geometries/DodecahedronGeometry.js —— 正十二面体以 IcosahedronGeometry 为例src/geometries/IcosahedronGeometry.js构造器先用黄金比例t (1 √5) / 2预定义 12 个顶点坐标与 20 个三角面的索引表再调用super( vertices, indices, radius, detail )。它只对外暴露radius与detail两个参数构造后会将this.type覆写为IcosahedronGeometry、parameters收敛为仅含这两个字段这与基类在几何形状上保持一致而接口更友好。该文件开头的 JSDoc 示例展示了典型用法const geometry new THREE.IcosahedronGeometry(); const material new THREE.MeshBasicMaterial( { color: 0xffff00 } ); const icosahedron new THREE.Mesh( geometry, material ); scene.add( icosahedron );对派生类设置detail 0时细分会使其不再是严格的正二十面体而趋向平滑球体——这一点在派生类的 JSDoc 中被特别注明。实战用 PolyhedronGeometry 生成球化立方体官方手册示例 manual/examples/primitives.html 演示了把立方体八顶点通过PolyhedronGeometry球化的用法// 以立方体的 8 个顶点为输入 addSolidGeometry( -1, 0, new THREE.PolyhedronGeometry( verticesOfCube, indicesOfFaces, radius, detail ) );这类自定义多面体的完整落地流程是用常规BoxGeometry或手工数组准备基础多面体的顶点坐标并对每个四边形面拆分为两个三角形索引传入new PolyhedronGeometry( vertices, indices, radius, detail )配合MeshStandardMaterial、MeshPhongMaterial等创建Mesh加入场景。当radius固定时从结构上可以推断detail 0得到棱角分明的多面体硬边效果detail 1、2、3…则逐步逼近光滑球面。由于构造过程一次性完成顶点投影与 UV 计算这类几何适合作为静态网格使用动态逐帧修改顶点位置并不在PolyhedronGeometry的设计目标内。单元测试印证PolyhedronGeometry的公开契约由单元测试覆盖见 test/unit/src/geometries/PolyhedronGeometry.tests.js入口在 test/unit/three.source.unit.js继承关系断言PolyhedronGeometry instanceof BufferGeometry true实例化无参构造也可创建对象得益于默认参数type 标记断言object.type PolyhedronGeometry标准几何测试基于前面给出的四面体顶点/索引对运行runStdGeometryTests覆盖 position/normal/uv attribute、包围盒等常规几何正确性。同样地test/unit/src/geometries/IcosahedronGeometry.tests.js、Tetrahedron、Octahedron、Dodecahedron 的测试均以instanceof PolyhedronGeometry断言继承自基类。运行相关测试可执行仓库单元测试套件中的对应文件例如通过 QUnit 加载three.source.unit.js后筛选 Geometries 模块。小结PolyhedronGeometry是 three.js 中输入任意多面体描述、输出球面化细分网格的通用基类其四参数vertices、indices、radius、detail约定清晰内部则依次完成三角细分、球面归一化投影、UV 方位角映射与接缝修复三条流水线并在detail为 0 与大于 0 时切换平面/平滑法线。若不希望手工准备顶点索引数据可直接使用继承它的 Tetrahedron、Octahedron、Icosahedron、Dodecahedron 四个预置类。作为网格生成的最底层拼图理解其机制也有助于理解其他三类几何库中基于顶点投影/细分的实现思路。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考