three.js RoundedBoxGeometry 详解:带圆角立方体几何体的构造参数、源码原理与实战用法

three.js RoundedBoxGeometry 详解:带圆角立方体几何体的构造参数、源码原理与实战用法 three.js RoundedBoxGeometry 详解带圆角立方体几何体的构造参数、源码原理与实战用法【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsRoundedBoxGeometry 是 three.js 在标准 BoxGeometry 基础上扩展出的“圆角立方体”几何体插件让立方体的十二条边与八个角都呈现平滑过渡广泛用于按钮、芯片、家具、UI 元素等需要柔和外观的三维物体。本文以 RoundedBoxGeometry API 文档 为主线结合仓库内 addons 源码 与多个官方示例完整讲解它的构造参数、UV/法线处理原理、JSON 序列化流程并给出可直接复用的实战代码。一、RoundedBoxGeometry 是什么从继承链看RoundedBoxGeometry 位于内置几何体链路的末端EventDispatcher → BufferGeometry → BoxGeometry → RoundedBoxGeometry其中EventDispatcher → BufferGeometry是核心基础BoxGeometry 提供了矩形立方体的面片组织方式而 RoundedBoxGeometry 则在其基础上通过改写顶点位置把锐利的边和角替换成由多段圆弧构成的平滑曲面。三点关键特征值得先记住它不是核心库成员而是 Addon附加组件必须显式 import不会自动进入THREE命名空间面片数量显著多于同尺寸 BoxGeometry因为它需要细分网格来逼近圆弧生成的是非索引non-indexed几何体顶点数据按面展开存储。二、安装与导入方式由于 RoundedBoxGeometry 属于three/addons命名空间下的插件仓库中对应 examples/jsm/geometries/RoundedBoxGeometry.js需要在脚本中显式导入import { RoundedBoxGeometry } from three/addons/geometries/RoundedBoxGeometry.js;说明three/addons/...路径在构建/打包阶段映射到examples/jsm/...目录下的同名模块。若使用原生 ES Module 方式也可直接按仓库实际路径引用该文件。导入后即可按普通几何体使用const geometry new RoundedBoxGeometry(); const material new THREE.MeshStandardMaterial( { color: 0x00ff00 } ); const cube new THREE.Mesh( geometry, material ); scene.add( cube );三、构造参数详解构造函数签名如下源码位置examples/jsm/geometries/RoundedBoxGeometry.js#L65RoundedBoxGeometry( width : number, height : number, depth : number, segments : number, radius : number )各参数含义与默认值参数含义默认值width宽度即平行于 X 轴的边长1height高度即平行于 Y 轴的边长1depth深度即平行于 Z 轴的边长1segments构成圆角的细分段数2radius圆角边与角的半径0.13.1 三个尺寸参数 width / height / depth与 BoxGeometry 一致width、height、depth分别对应沿 X、Y、Z 三个轴的边长几何体默认居中于原点。例如 200 × 200 × 200 的圆角立方体可以写成const geometry new RoundedBoxGeometry( 200, 200, 200, 10, 10 );这一写法正是官方示例 examples/webgl_materials_texture_html.html 与 examples/webgpu_materials_texture_html.html 中用于展示 HTML 纹理映射的实际用法。3.2 segments圆角的平滑度segments决定每个圆角用多少段折线去逼近圆弧。值越大角越圆润、顶点数越多值越小角越“有棱角”。需要特别留意源码中的一个关键细节构造器内部并不直接使用segments而是先换算// 总分段数取奇数保证每个面上存在连接圆角的平面区域 const totalSegments segments * 2 1;之所以强制为奇数是为了让每个面的中央保留一块与圆角相连的平面区域——偶数段会在几何上出现圆角错位或缺乏连接面的问题。理解这一点对选值很有帮助官方示例普遍使用2~10之间的值例如物理沙盒示例 examples/physics_rapier_basic.html 用new RoundedBoxGeometry( 1, 1, 1, 2, 0.25 )生成中等平滑度的碰撞体纹理示例 examples/webgl_loader_texture_lottie.html 用new RoundedBoxGeometry( 1, 1, 1, 7, 0.1 )追求较高的表面平滑度木质质感 TSL 示例 examples/webgpu_tsl_wood.html 用new RoundedBoxGeometry( 0.125, 0.9, 0.9, 10, 0.02 )在长宽方向都较细的体块上使用较高分段。3.3 radius圆角半径及其上限约束radius是圆角在顶点处的弯曲半径。源码对它有自动夹取处理radius Math.min( width / 2, height / 2, depth / 2, radius );也就是说圆角半径不会被允许超过最短边的一半。例如构造new RoundedBoxGeometry( 1, 1, 0.2, 4, 0.5 )时实际生效的半径会被压缩为Math.min(0.5, 0.5, 0.1, 0.5) 0.1。官方示例中利用这一特性把薄板类物体做成带小圆角的“扁圆角块”例如 AO 后处理示例 examples/webgpu_postprocessing_ao.html 中const seat new THREE.Mesh( new RoundedBoxGeometry( 0.9, 0.25, 0.8, 4, 0.06 ), fabricMat ); const backrest new THREE.Mesh( new RoundedBoxGeometry( 0.9, 0.6, 0.12, 4, 0.04 ), fabricMat );如果希望获得“几乎像球体”的圆角立方体可以把 radius 设到接近边长的一半。四、源码级原理圆角网格是怎么生成的仅仅知道参数还不够理解内部流程能帮你正确预判几何体形态与性能开销。RoundedBoxGeometry 的构造过程examples/jsm/geometries/RoundedBoxGeometry.js#L65-L192大致分为四个阶段。4.1 阶段一以细分单位立方体为起点构造器先调用父类构造一个单位立方体并在三条轴方向使用刚才算出的总分段数super( 1, 1, 1, totalSegments, totalSegments, totalSegments );因此 RoundedBoxGeometry 的面片基数取决于totalSegments²级别segments每增加 1顶点规模都会明显上升。源码在细分完成后有一个快速出口如果totalSegments 1即segments 0会直接返回未做缩放的普通单位 BoxGeometry。换言之segments 至少要取 1 才会真正生成圆角缩放后的网格。4.2 阶段二转为非索引几何体并逐个改写顶点为了逐顶点精确控制圆角几何体会被转成非索引形式再交换数据const geometry2 this.toNonIndexed(); this.index null; this.attributes.position geometry2.attributes.position; this.attributes.normal geometry2.attributes.normal; this.attributes.uv geometry2.attributes.uv;随后对每个顶点执行核心变形。设const box new Vector3( width, height, depth ).divideScalar( 2 ).subScalar( radius );即“内缩一个圆角半径后的盒心半长”每个顶点的新位置由面法线方向推得positions[ i 0 ] box.x * Math.sign( position.x ) normal.x * radius; positions[ i 1 ] box.y * Math.sign( position.y ) normal.y * radius; positions[ i 2 ] box.z * Math.sign( position.z ) normal.z * radius;直观解释是六个面的中心区域仍停留在原尺寸 ±size/2 处而靠近边、角的顶点则沿归一化法线向外偏移 radius 的距离从而在边与角处自然衔接成圆弧形成平滑的圆角过渡。4.3 阶段三重写法线以保证平滑光照圆角看起来圆润很大程度上靠的是逐顶点平滑法线。源码对每个顶点先按半个网格单元向内收缩再做归一化得到新法线normal.copy( position ); normal.x - Math.sign( normal.x ) * halfSegmentSize; normal.y - Math.sign( normal.y ) * halfSegmentSize; normal.z - Math.sign( normal.z ) * halfSegmentSize; normal.normalize();归一化后的法线同时被写入normals属性因此圆角区域在标准光照下呈现平滑的明暗渐变而不是多边形感的硬棱边。4.4 阶段四按圆弧占比重新计算 UV这是 RoundedBoxGeometry 区别于“纯顶点变形”实现的关键一步。它没有沿用 BoxGeometry 的线性 UV而是调用getUv()辅助函数把每个面的 UV 区间按平面段与四分之一圆弧段的实际长度占比来分配const totArcLength 2 * Math.PI * radius / 4; // 单个角的四分之一圆弧长 const centerLength Math.max( sideLength - 2 * radius, 0 ); // 中央平面段长度代码遍历六个面right / left / top / bottom / front / back各自指定两个投影轴与面朝向向量来生成 UVexamples/jsm/geometries/RoundedBoxGeometry.js#L136-L189。这样做的收益是贴图纹理在平面与圆角交界处不会出现明显拉伸或错位这也是该几何体能直接配合棋盘格、Lottie 动画纹理、HTML 纹理等做高质量展示的原因。五、属性与静态方法5.1 .parameters : ObjectRoundedBoxGeometry 在构造时把传入参数原样记录到parameters中注意其中radius是经过最短边夹取后的实际值this.parameters { width: width, height: height, depth: depth, segments: segments, radius: radius, };这与父类 BoxGeometry 的parameters覆盖关系是父类记录width/height/depth/widthSegments/heightSegments/depthSegmentsRoundedBoxGeometry 则改记面向用户的segments与radius。需要强调的是parameters仅是构造参数的快照实例化后再修改它不会改变几何体本身。若想调整尺寸或圆角应重新new一个实例。5.2 .fromJSON( data : Object ) : RoundedBoxGeometry静态工厂方法从序列化的 JSON 对象还原出一个新的 RoundedBoxGeometry 实例static fromJSON( data ) { return new RoundedBoxGeometry( data.width, data.height, data.depth, data.segments, data.radius ); }它读取的正是width、height、depth、segments、radius五个字段。要理解data从哪来需要看基类 src/core/BufferGeometry.js#L1230 的toJSON()实现只要几何体带有parameters且未被transform过序列化时就会把 parameters 中的键直接平铺写入 JSON 顶层并提前返回。因此一个 RoundedBoxGeometry 调用geometry.toJSON()会得到类似{ metadata: { version: 4.7, type: BufferGeometry, generator: BufferGeometry.toJSON }, uuid: ..., type: RoundedBoxGeometry, name: , width: 1, height: 1, depth: 1, segments: 2, radius: 0.1 }type为RoundedBoxGeometry构造时通过this.type RoundedBoxGeometry设置配合fromJSON即可完成 JSON 存档 / 还原的往返适合在场景保存、资源管理器等场景中使用。六、实战建议与注意事项综合 API 文档与仓库源码给出几条实操建议圆角半径与尺寸联动当几何体某个维度很薄时如桌面、座椅靠背radius会被夹取到该边的一半以下盲目设置过大的radius不会报错但效果与预期不同建议按最短边推算上限。segments 与性能的权衡UI 或静态装饰用2~4即可需要近距离特写或高光滑度材质如 clearcoat、光泽金属时可提升到7~10。由于几何体最终以非索引形式存储且每轴都按segments*21细分顶点开销与segments近似平方关系动态场景中应避免过大分段。贴图映射可靠得益于按圆弧长度占比的 UV 算法该几何体可以直接放心使用纹理贴图与法线贴图不必担心圆角处的纹理拉扯。光照与着色构造器已生成逐顶点平滑法线配合MeshStandardMaterial、MeshPhysicalMaterial等 PBR 材质即可获得自然的圆角高光。七、延伸阅读API 文档原文docs/pages/RoundedBoxGeometry.html.mdAddons 模块源码examples/jsm/geometries/RoundedBoxGeometry.js父类实现src/geometries/BoxGeometry.js 与 src/core/BufferGeometry.js官方示例物理碰撞场景 examples/physics_rapier_basic.html、Lottie 纹理 examples/webgl_loader_texture_lottie.html、HTML 纹理 examples/webgl_materials_texture_html.html、AO 家具场景 examples/webgpu_postprocessing_ao.html、木质纹理 TSL 场景 examples/webgpu_tsl_wood.html【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考