ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Three.js TorusKnotGeometry 环面纽结几何体:参数体系、源码构造原理与实战用法

Three.js TorusKnotGeometry 环面纽结几何体:参数体系、源码构造原理与实战用法 Three.js TorusKnotGeometry 环面纽结几何体参数体系、源码构造原理与实战用法【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsTorusKnotGeometry 是 Three.js 内置的用于生成“环面纽结”torus knot三维网格的标准几何体类。它通过一对互质的整数参数 p 与 q 精确控制纽结绕自身对称轴与绕环内圆的缠绕次数可快速生成从经典三叶结到任意 (p, q) 拓扑形态的闭合曲线实体。本文将围绕它的构造签名、六个参数含义、底层顶点/法线/UV/索引生成算法、参数快照属性与 JSON 工厂方法展开结合仓库源码与单元测试让你既能直接调参出形也能理解它在渲染管线中究竟如何被三角化。概述什么是环面纽结在 src/geometries/TorusKnotGeometry.js 的类注释TorusKnotGeometry.js以及官方文档中对本类的定义一致Creates a torus knot, the particular shape of which is defined by a pair of coprime integers, p and q. If p and q are not coprime, the result will be a torus link.也就是说一个环面纽结的形状完全由一对互质coprime整数 p 与 q决定若 p 与 q 不互质生成的将不再是单一条纽结knot而是由多条相互交缠的闭曲线组成的“环面链环”torus link。这也是本类与 TorusGeometry标准圆环、无缠绕最本质的差异TorusKnotGeometry 的中心曲线不是平面圆而是一条在环面上缠绕的闭合空间曲线tube 截面再沿这条曲线扫掠挤出为实体。在类层级上TorusKnotGeometry 继承自 BufferGeometry进而继承自 EventDispatcher参见 EventDispatcher → BufferGeometry → TorusKnotGeometry它与所有其他内置几何体一样最终输出的是包含 index/position/normal/uv 四类缓冲数据的非索引化到索引化的标准 BufferGeometry。最小可用代码示例官方文档与本类源码注释TorusKnotGeometry.js给出了完全一致的最基本用法const geometry new THREE.TorusKnotGeometry( 10, 3, 100, 16 ); const material new THREE.MeshBasicMaterial( { color: 0xffff00 } ); const torusKnot new THREE.Mesh( geometry, material ); scene.add( torusKnot );这段代码创建了一个radius 10、tube 3、100 个环向分段、16 个径向分段的纽结并使用纯色材质放入场景。默认参数p 2, q 3对应经典的 (2, 3) 环面纽结即三叶结 trefoil knot形态。构造函数与全部参数解析构造签名如下new TorusKnotGeometry( radius : number, tube : number, tubularSegments : number, radialSegments : number, p : number, q : number )参数定义完全继承自文档其中前四个参数均可省略实际默认值由构造函数默认参数直接给出见 TorusKnotGeometry.js参数含义默认值radius环面纽结的“主轴半径”纽结中心曲线所张开的尺寸基准1tube管道截面的半径扫掠圆截面的粗细0.4tubularSegments沿纽结曲线方向的环向分段数越大曲线越光滑64radialSegments管截面圆周方向的分段数越大截面越接近正圆8p几何体绕其旋转对称轴缠绕的次数2q几何体绕环体内部圆中心曲线所在环面缠绕的次数3各参数语义详解radius控制整个纽结的宏观尺寸语义为“环面纽结的半径”。在 calculatePositionOnCurve 中曲线上的点由radius * ( 2 cs ) * 0.5一类表达式缩放可见 radius 直接决定了中心曲线在空间中的跨度。tube扫掠的圆形截面半径决定“绳体”的粗细。可推断的是由于中心曲线距对称轴的最短半径约为radius * 0.5当tube接近或超过这一尺度时管体将发生自相交实践中应让tube显著小于radius。tubularSegments沿中心曲线纽结缠绕方向的离散份数。该值过低时纽结会呈现明显折线提高该值让曲线更圆滑但同时增加顶点数量。radialSegments每个环向站位上围绕管道截面的离散份数控制截面多边形趋近圆形的程度默认8即八边形截面。p / q一对拓扑参数。p表示曲线绕旋转对称轴即环面的主轴方向缠绕的圈数q表示曲线绕环体内侧圆缠绕的圈数。只有当 p、q互质时才得到单一闭路的纽结取(2, 3)、(3, 5)、(5, 7)等斐波那契式互质对可得到不同缠绕风格的纽结。若二者存在公约数如p2, q4输出将退化为多条互相缠结的闭合链torus link。参数在编辑器中的约束参考如果你在仓库的 editor 工程中为对象选择 TorusKnotGeometrySidebar.Geometry.TorusKnotGeometry.js 会为这六个参数逐个生成输入行两个UINumberradius、tube与四个UIInteger其中 tubularSegments、radialSegments、p、q 被限制为最小 1 的整数且任何修改都会通过SetGeometryCommand重建整个几何体editor/js/Sidebar.Geometry.TorusKnotGeometry.js。而官方文档交互示例 geometry-browser.htmlL586-L619为调参提供了即时预览区间radius 1–20、tube 0.1–10、tubularSegments 3–300、radialSegments 3–20、p 与 q 各 1–20整数步进可作为快速实验的合理取值参照。结合源码看生成算法一条曲线如何变成一张网格TorusKnotGeometry 的构造并不调用 GPU而是在 CPU 上通过数学采样生成四个缓冲数组整段逻辑位于 TorusKnotGeometry.js。其步骤可从源码还原如下取整细分tubularSegments与radialSegments先经Math.floor取整L54-L55保证循环边界合法。沿曲线采样外层循环i 0 … tubularSegments每一步令u i / tubularSegments * p * Math.PI * 2即沿曲线走完p个 2π 周期L78-L82。构造切向坐标系对当前弧长u与u 0.01分别调用calculatePositionOnCurve得到曲线上的点P1、P2再用这两个点叉积构造正交基T / N / BL84-L100作为截面在三维空间中的朝向。截面扫掠内层循环j 0 … radialSegments令v j / radialSegments * Math.PI * 2把位于 xy 平面内的截面点(cx, cy) ( -tube * cos v, tube * sin v )用基向量旋转并平移到曲线上得到最终顶点坐标vertex P1 cx * N cy * BL102-L118。法线与 UV法线取“顶点相对曲线中心 P1 的方向”并归一化L120-L124UV 则分别为i / tubularSegments与j / radialSegments使纹理在环向与截面方向上各铺满一个周期L126-L129。索引化以相邻两圈剖分单元拼出两个三角形(a, b, d)、(b, c, d)通过setIndex生成索引缓冲L137-L155。组装属性最后以setAttribute挂载position、normal、uv三个Float32BufferAttributeL159-L162。中心曲线本身的参数方程是理解纽结拓扑的关键源码集中在 calculatePositionOnCurveconst cu Math.cos( u ); const su Math.sin( u ); const quOverP q / p * u; const cs Math.cos( quOverP ); position.x radius * ( 2 cs ) * 0.5 * cu; position.y radius * ( 2 cs ) * su * 0.5; position.z radius * Math.sin( quOverP ) * 0.5;可以据此推算随着u扫过2π * p的角度相位quOverP恰好扫过2π * q这正是“绕轴 p 圈、绕环内 q 圈”的数学来源当 p、q 互质时起点与终点恰好闭合为同一条闭曲线。顶点与三角形数量预估从循环结构可直接推出网格规模顶点数( tubularSegments 1 ) * ( radialSegments 1 )两层循环均取≤端点重复闭合三角形数2 * tubularSegments * radialSegments每个剖分单元拆成两个三角形。默认参数下即65 * 9 585个顶点、2 * 64 * 8 1024个三角形属于轻量几何体示例 webgl_geometries.html 中出现的new THREE.TorusKnotGeometry( 50, 10, 50, 20 )L120则对应约 1071 个顶点、2000 个三角形。Propertiesparameters 与 type.parameters : Object实例化后构造函数会把所有入参原样快照到this.parameters对象中TorusKnotGeometry.js包含radius / tube / tubularSegments / radialSegments / p / q六个字段。文档明确强调实例化之后再修改该对象不会改变几何体。原因是网格数据顶点/法线/UV/索引在构造时即一次性生成完毕parameters仅用于记录“当初用什么参数建的”供调试、序列化或编辑器回显使用。需要调整形态时应基于新参数重新new一个几何体——官方 编辑器 正是这样做的每次变更都执行一次SetGeometryCommand重建。另外源码还覆写了copy( source )方法L181-L189在继承 BufferGeometry.copy 复制全部缓冲数据后额外用Object.assign( {}, source.parameters )深拷贝一份参数快照避免新旧实例共享同一 parameters 对象。.type : String构造时会写入this.type TorusKnotGeometryL36。该字符串是 JSON 序列化/反序列化时识别几何体类别的重要依据也是 测试套件 中专门断言的值。静态方法 .fromJSON( data ) : TorusKnotGeometrystatic fromJSON( data ) { return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); }工厂方法实现位于 TorusKnotGeometry.js。它接收一个描述序列化几何体的 JSON 对象data从中取出radius、tube、tubularSegments、radialSegments、p、q六个字段返回一个全新的 TorusKnotGeometry 实例。该方法与 BufferGeometry.toJSON() 形成闭环当几何体被toJSON序列化JSON 中保留type与全部构造参数后可由fromJSON无损重建。由于parameters原样保存了入参只要入参是可 JSON 化的普通数值这一往返就是信息完整的。单元测试如何验证该类仓库在 test/unit/src/geometries/TorusKnotGeometry.tests.js 中为本类提供了成体系的 QUnit 用例可直接作为“如何使用与校验”的参照继承关系断言实例instanceof BufferGeometry为真L34-L42实例化无参构造能成功创建对象L45-L50type 标识type TorusKnotGeometryL53-L61参数渐进构造依次传入 0、1、2、4、6 个参数共创建 6 个实例验证各参数可按位省略、逐级覆盖L13-L29标准几何测试所有实例须通过通用几何校验runStdGeometryTestsL64-L68包括属性存在性、索引合法性等公共约定。测试用例使用的参数组合radius10, tube20, tubularSegments30, radialSegments10, p3, q2也提示了一个细节即便 tube 大于 radius 这类非常规取值该类也不会报错只会生成自相交的怪异形态因此“参数合理性”由使用者自行把握。完整可运行示例动画旋转的渐变纽结将文档示例扩充为一段可直接运行的完整场景渲染帧循环让纽结缓慢旋转更直观地观察缠绕拓扑与光照关系import * as THREE from three; // 1. 场景 / 相机 / 渲染器 const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); const renderer new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); // 2. 创建 (2, 3) 三叶结并提高细分以获得平滑曲线 const geometry new THREE.TorusKnotGeometry( 10, 3, 200, 32 ); // p2, q3 取默认 const material new THREE.MeshStandardMaterial( { color: 0xffff00, roughness: 0.3, metalness: 0.1 } ); const torusKnot new THREE.Mesh( geometry, material ); scene.add( torusKnot ); // 3. 添加灯光辅助观察 scene.add( new THREE.DirectionalLight( 0xffffff, 1 ) ); scene.add( new THREE.AmbientLight( 0x404040 ) ); camera.position.set( 25, 15, 25 ); camera.lookAt( 0, 0, 0 ); // 4. 动画循环 function animate() { requestAnimationFrame( animate ); torusKnot.rotation.x 0.005; torusKnot.rotation.y 0.01; // 双轴旋转更便于分辨 p/q 缠绕结构 renderer.render( scene, camera ); } animate();更换p、q即可获得不同纽结形态例如new THREE.TorusKnotGeometry( 10, 3, 200, 32, 3, 5 )对应 (3, 5) 纽结若需生成环面链环可尝试非互质组合并观察多条闭曲线共存的形态。将tubularSegments降到16、radialSegments降到4则可直观看到“折线化 棱柱截面”的低多边形风格。相关资源与延伸阅读交互调参预览官方几何体浏览器 docs/scenes/geometry-browser.html 以 dat.GUI 实时调节六参数并即时重建。几何体总览manual/pages/primitives.html 的入门手册将 TorusKnotGeometry 与其他基础几何体一并列出。编辑器中集成菜单添加入口与属性面板分别见 editor/js/Menubar.Add.js 与 editor/js/Sidebar.Geometry.TorusKnotGeometry.js。模块导出本类经 src/geometries/Geometries.js 统一导出最终汇入 Three.js 各构建产物。同类对照不缠绕的普通环面见 TorusGeometry其实现位于 src/geometries/TorusGeometry.js。源码与测试完整实现见 src/geometries/TorusKnotGeometry.js回归测试见 test/unit/src/geometries/TorusKnotGeometry.tests.js实际应用可见于 examples/webgl_geometries.html 等示例。小结TorusKnotGeometry 以“p/q 一对互质整数”定义拓扑、以 radius/tube 定义尺度、以两组 segments 定义离散精度是理解 Three.js 过程化几何体“曲线采样 → 局部坐标系 → 截面扫掠 → 索引化”这一通用范式的最佳范例之一。掌握其构造参数与 TorusKnotGeometry.js 中的曲线方程后你既可以信手生成各类纽结造型也能举一反三理解 TubeGeometry 等同类扫掠几何体的实现思路。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表