恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

three.js CubicBezierCurve 深度解析:2D 三次贝塞尔曲线的 API、采样实现与弧长参数化

  • 首页
  • 资讯中心
  • /
  • three.js CubicBezierCurve 深度解析:2D 三次贝塞尔曲线的 API、采样实现与弧长参数化

相关资讯

CMSIS-DSP源码深度拆解:从FFT优化到工业固件落地实践 2026/9/7 18:40:10
superpowers 压力测试实战:用「权威 + 社会压力」场景验证 Agent 是否坚守系统化调试流程 2026/9/7 18:35:10
清单来了:盘点2026年最受欢迎的的AI论文平台 2026/9/7 18:35:10

最新资讯

Claude Code技能包全解析:7大必备工具提升AI编程效率
从QQ空间数据导出看开源项目:模拟请求实现个人数据备份
单片机与CPU的区别:从内存、外设到开发流程的全面解析
AI浪潮来袭!小白程序员如何抓住大模型红利,收藏这篇必看攻略!
SpringBoot充电桩管理系统毕设实战:新基建下的架构设计与答辩要点
无畏契约海洋旅者套装介绍 无畏契约海洋旅者什么时候上线

今日推荐

基于YOLOv8和PyQt5的麦穗稻穗检测识别系统设计与实现
UL 1642锂电池安全标准全解析:测试项目、认证流程与避坑指南
BS EN 13814-1-2019游乐设施安全标准:设计与制造核心要点解析

本周热门

超人会飞不算本事:系统稳定依赖清晰规则与边界设计
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
基于CNN的调制信号识别:MATLAB实现时频图分类实战

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

three.js CubicBezierCurve 深度解析:2D 三次贝塞尔曲线的 API、采样实现与弧长参数化

发布时间:2026/9/7 18:40:10
three.js CubicBezierCurve 深度解析:2D 三次贝塞尔曲线的 API、采样实现与弧长参数化 three.js CubicBezierCurve 深度解析2D 三次贝塞尔曲线的 API、采样实现与弧长参数化【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js本篇技术指南围绕 three.js 官方 API 文档 CubicBezierCurve 展开系统讲解这个 2D 三次贝塞尔曲线类的构造方式、核心属性与getPoint插值原理并结合 src/extras/curves/CubicBezierCurve.js 源码与 QUnit 测试用例 验证其采样行为。读完后你将掌握如何用四个向量定义一条三次贝塞尔曲线、如何用getPoints将其渲染为THREE.Line以及如何利用父类Curve的弧长机制做等距采样getPointAt/getSpacedPoints。类定位Curve 体系中的 2D 三次贝塞尔曲线CubicBezierCurve是 three.jsextras模块下曲线路径curves家族的一员官方文档将其定义为 A curve representing a 2D Cubic Bezier curve即一条由四个点确定的2D三次贝塞尔曲线。它直接继承自抽象基类 CurveCurve (src/extras/core/Curve.js) └── CubicBezierCurve (src/extras/curves/CubicBezierCurve.js)同一个 src/extras/curves 目录下还有一组相关实现理解它们的分工有助于选对类类维度控制点数量说明QuadraticBezierCurve2D3二次贝塞尔曲线CubicBezierCurve2D4本文主角三次贝塞尔曲线QuadraticBezierCurve33D3二次的 3D 变体CubicBezierCurve33D4三次贝塞尔曲线的 3D 版本LineCurve/LineCurve32D / 3D2直线段SplineCurve/CatmullRomCurve3/EllipseCurve/ArcCurve——其他解析曲线三次贝塞尔曲线由起点v0、终点v3以及两个控制点v1、v2完全确定。控制点决定了曲线的走向曲线始终被包裹在由四个控制点构成的凸包内并在t 0与t 1处分别与v0、v3相切。构造函数与属性new CubicBezierCurve( v0, v1, v2, v3 )构造函数接收四个Vector2参数v0起点start pointv1第一个控制点first control pointv2第二个控制点second control pointv3终点end point。对照 CubicBezierCurve.js#L37-L80 的源码构造函数有一个值得注意的细节四个参数都有默认值new Vector2()。也就是说new CubicBezierCurve()不传任何参数也是合法的会得到一条从原点到原点、退化为一点的曲线这在单元测试中直接体现了type与isCubicBezierCurve属性可在空构造下断言class CubicBezierCurve extends Curve { constructor( v0 new Vector2(), v1 new Vector2(), v2 new Vector2(), v3 new Vector2() ) { super(); this.isCubicBezierCurve true; this.type CubicBezierCurve; this.v0 v0; this.v1 v1; this.v2 v2; this.v3 v3; } // ... }构造完成后实例上会有以下属性.isCubicBezierCurve : boolean (readonly)类型测试标志默认true。three.js 大量使用isXxx标志做鸭子类型判断方便在不依赖instanceof的场景下识别对象类型。.v0 / .v1 / .v2 / .v3 : Vector2分别对应起点、第一控制点、第二控制点与终点。注意源码中这四个属性直接引用传入的向量对象而非拷贝因此持有这些向量的其他代码如果后续修改它们会直接影响曲线形状若需要独立副本请传入前自行clone()。此外源码还定义了this.type CubicBezierCurve该字段与父类Curve的序列化机制配合用于 JSON 反序列化时识别具体曲线类型下文toJSON一节会说明。getPointBernstein 多项式插值的核心.getPoint( t : number, optionalTarget : Vector2 ) : Vector2这是CubicBezierCurve唯一覆写自基类的抽象方法Overrides:Curve#getPoint返回参数t对应的曲线位置。t插值因子表示曲线上的位置必须位于[0, 1]区间optionalTarget可选的目标向量结果会写入该向量并返回便于在循环中复用临时向量、避免 GC 压力。源码实现CubicBezierCurve.js#L89-L102非常精炼getPoint( t, optionalTarget new Vector2() ) { const point optionalTarget; const v0 this.v0, v1 this.v1, v2 this.v2, v3 this.v3; point.set( CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) ); return point; }可以看到它对 x、y 两个分量分别调用 Interpolations.js 中导出的标量函数CubicBezier再把结果写回一个Vector2。而CubicBezier的实现就是标准的三次 Bernstein 多项式// src/extras/core/Interpolations.js function CubicBezierP0( t, p ) { const k 1 - t; return k * k * k * p; } function CubicBezierP1( t, p ) { const k 1 - t; return 3 * k * k * t * p; } function CubicBezierP2( t, p ) { return 3 * ( 1 - t ) * t * t * p; } function CubicBezierP3( t, p ) { return t * t * t * p; } function CubicBezier( t, p0, p1, p2, p3 ) { return CubicBezierP0( t, p0 ) CubicBezierP1( t, p1 ) CubicBezierP2( t, p2 ) CubicBezierP3( t, p3 ); }合并起来即经典公式P(t) (1-t)³·v0 3(1-t)²t·v1 3(1-t)t²·v2 t³·v3四个基函数在t 0和t 1处分别只有一项为 1因此曲线必然精确地通过v0与v3中间项的权重则平滑地把曲线拉向两个控制点。用官方示例把曲线渲染成一条线官方文档给出的最小可用示例如下完整保留了从曲线到可渲染对象的链路const curve new THREE.CubicBezierCurve( new THREE.Vector2( - 0, 0 ), new THREE.Vector2( - 5, 15 ), new THREE.Vector2( 20, 15 ), new THREE.Vector2( 10, 0 ) ); const points curve.getPoints( 50 ); const geometry new THREE.BufferGeometry().setFromPoints( points ); const material new THREE.LineBasicMaterial( { color: 0xff0000 } ); // Create the final object to add to the scene const curveObject new THREE.Line( geometry, material );逐行说明getPoints( 50 )是继承自Curve的方法它以d / divisionsd 0 … divisions为参数循环调用getPoint因此返回divisions 1个点51 个。注意getPoints按参数 t 均匀采样由于贝塞尔曲线参数化并非匀速生成的线段在曲线上疏密并不均匀BufferGeometry.setFromPoints直接以Vector2/Vector3数组填充position属性LineBasicMaterialTHREE.Line是最轻量的曲线呈现方式。如果想要等弧长的采样例如沿线匀速运动的粒子、等间距的装饰点应改用getSpacedPoints( divisions )它内部通过getPointAt( u )实现机制见下一节。弧长参数化getPointAt 与 getUtoTmappingCurve基类解决的核心问题是参数 t 均匀 ≠ 弧长均匀。以官方测试中的曲线v0(-10,0) v1(-5,15) v2(20,15) v3(10,0)为例getPoint( 0.5 )给出的中点并不是几何意义上的曲线中点。three.js 的应对策略是采样 累加 二分查找三件套getLengths( divisions )Curve.js#L153-L184把曲线按divisions段切分累加相邻采样点的欧氏距离生成累积弧长数组cacheArcLengths受arcLengthDivisions默认200与needsUpdate标志控制缓存复用——修改了控制点之后必须调用updateArcLengths()或把needsUpdate置为true否则拿到的仍是旧缓存getUtoTmapping( u, distance? )Curve.js#L208-L281给定弧长因子u或绝对距离distance在累积弧长数组上做二分查找定位所在区间再用线性内插折算回参数t供getPoint使用getPointAt( u ) / getSpacedPoints( divisions ) / getTangentAt( u )都是先经getUtoTmapping折算再委托给对应的getPoint/getTangent版本。单元测试CubicBezierCurve.tests.js给出了这组 API 的精确预期值可直接作为数值回归基准// 曲线总长getLength() ≈ 36.64630888504102 // 弧长中点getPointAt( 0.5 ) ≈ ( 3.4718554735926617, 11.07899406116314 ) // 与参数中点 getPoint( 0.5 ) ( 5.625, 11.25 ) 明显不同 —— 这正是弧长重映射的意义 // getUtoTmapping( 0.5, 1 ) ≈ 0.02130029182257093 // 表示沿曲线走 1 个单位弧长对应的参数位置getSpacedPoints()默认 5 段在该测试曲线上的六个点为(-10, 0)→(-6.168, 6.170)→(-0.059, 10.124)→(7.124, 11.155)→(12.302, 6.809)→(10, 0)相邻点间弧长近似相等可作为等距撒点实现的验收标准。参数校验之外的实用方法copy、toJSON、fromJSON官方 API 页面的 Methods 一节只列出了getPoint但源码中CubicBezierCurve还实现了三个序列化与复制相关的方法在实际工程尤其是与 three.js 的ObjectLoader/场景 JSON 生态配合时会用到// 复制逐个拷贝四个向量 copy( source ) { super.copy( source ); this.v0.copy( source.v0 ); this.v1.copy( source.v1 ); this.v2.copy( source.v2 ); this.v3.copy( source.v3 ); return this; } // 序列化在 Curve 的 metadata 基础上追加四个向量数组 toJSON() { const data super.toJSON(); data.v0 this.v0.toArray(); data.v1 this.v1.toArray(); data.v2 this.v2.toArray(); data.v3 this.v3.toArray(); return data; } // 反序列化按数组恢复四个向量 fromJSON( json ) { super.fromJSON( json ); this.v0.fromArray( json.v0 ); this.v1.fromArray( json.v1 ); this.v2.fromArray( json.v2 ); this.v3.fromArray( json.v3 ); return this; }父类Curve.prototype.toJSON会输出metadata含type: Curve与生成器信息、arcLengthDivisions与子类覆写的type CubicBezierCurve反序列化时type字段正是用来找回具体子类的依据clone()继承自Curve实现为new this.constructor().copy( this )因此curve.clone()会得到一条独立的新曲线。单元测试中的完整数值行为test/unit/src/extras/curves/CubicBezierCurve.tests.js 以v0(-10,0) v1(-5,15) v2(20,15) v3(10,0)这条曲线为基准覆盖了以下断言可作为你本地验证实现的标准答案参数采样getPoints(4)[ (-10, 0), (-3.359375, 8.4375), (5.625, 11.25), (11.796875, 8.4375), (10, 0) ]该测试还验证了对称性把四个控制点逆序构造new CubicBezierCurve( v3, v2, v1, v0 )采样结果恰好是原曲线采样结果的逆序——这是三次贝塞尔曲线的基本几何性质也是快速手写反向曲线的技巧。切线getTangent / getTangentAtgetTangent使用 ±0.0001 的差分近似见 Curve.js#L293-L313测试给出的getTangent(0.5)恰为(1, 0)与曲线在参数中点处切向水平的直觉一致getTangentAt则是先做弧长重映射再差分因此中间采样值与getTangent不同如u 0.25处分别为(0.839, 0.544)与(0.779, 0.626)。继承性断言object instanceof Curve trueobject.type CubicBezierCurveobject.isCubicBezierCurve true与文档Properties一节的描述完全对应。使用建议与注意事项区分getPoint与getPointAt动画中若希望对象匀速沿曲线运动请基于getPointAt或getUtoTmappinggetPoint驱动而不是直接用线性递增的t修改控制点后刷新弧长缓存v0~v3是引用属性改动后记得curve.needsUpdate true或调用curve.updateArcLengths()否则getPointAt系列仍基于旧弧长表2D 还是 3DCubicBezierCurve的点全部是Vector2若曲线要作为TubeGeometry的 spine 等需要 3D Frenet 标架的场景computeFrenetFrames要求 3D 曲线定义应改用同目录的CubicBezierCurve3复用目标向量在每帧循环中调用getPoint( t, tmpVec2 )传入常驻的Vector2可以避免每次调用都新建对象带来的分配开销——这也是optionalTarget参数存在的意义。小结CubicBezierCurve是 three.js 曲线体系中控制点显式指定的 2D 三次贝塞尔曲线实现构造时给定v0/v1/v2/v3四个Vector2getPoint(t)通过 Interpolations.js 中的 Bernstein 基函数对 x、y 分量分别插值父类 Curve 则在其上提供getPoints参数采样、getPointAt/getSpacedPoints弧长采样、getTangent切线与toJSON/fromJSON序列化等通用能力。配合 单元测试 中给出的精确数值你可以完整验证从定义曲线到渲染成 Line再到等弧长驱动动画的整条链路。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号