Three.js使用贝塞尔曲线绘制心形

本文介绍了贝塞尔曲线的基本概念和公式,从一阶到高阶曲线的递进,并讲解了如何利用德卡斯特里奥算法进行计算。在Three.js中,通过调整贝塞尔曲线的控制点,详细展示了如何绘制圆形以及心形的过程,提供了具体的代码示例。
摘要由CSDN通过智能技术生成

贝塞尔曲线是图形学中非常重要的知识,是绘制曲线以及曲面的基础,在很多地方都有着非常广泛的应用,比如Photoshop里的钢笔工具,字体设计,各种过渡动画等等。本文将记录贝塞尔曲线的原理公式,以及使用Three.js中的贝塞尔曲线API进行简单的心形绘制。

贝塞尔曲线详解

贝塞尔曲线就是在起始点和终止点之间,设置控制点,通过控制点的移动来控制曲线的形状。根据控制点数量的不同,可以将贝塞尔曲线分为一阶曲线、二阶曲线、三阶曲线……等等。

一阶曲线

一阶曲线非常简单,因为没有控制点,所以就是一条从起始点到终止点的线段。

二阶曲线

image-20220210111040096

二阶曲线由起始点、终止点和一个控制点组成。贝塞尔曲线由以下规则形成:对于[0, 1]内任何t,在 b 0 b 1 b_0b_1 b0b1上取一个点 b 0 1 b_0^1 b01,满足 b 0 b 0 1 b_0b_0^1 b0b01 b 0 1 b 1 b_0^1b_1 b01b1的关系为 t : 1 − t t : 1-t t:1t,同样的,在在 b 1 b 2 b_1b_2 b1b2上取一个点 b 1 1 b_1^1 b11,满足 b 1 b 1 1 b_1b_1^1 b1b11 b 1 1 b 2 b_1^1b_2 b11b2的关系为 t : 1 − t t : 1-t t:1t。最后将 b 0 1 b 1 1 b_0^1b_1^1 b01b11相连,在 b 0 1 b 1 1 b_0^1b_1^1 b01b11上继续取一点满足 b 0 1 b 0 2 : b 0 2 b 1 1 = t : 1 − t b_0^1b_0^2:b_0^2b_1^1=t:1-t b01b02:b02b11=t:1t。所有的t所形成的 b 0 2 b_0^2 b02形成一道曲线,这道曲线就是贝塞尔曲线。对应的点的坐标在向量表示下很容易表示出来:
b 0 1 ⃗ ( t ) = ( 1 − t ) b 0 ⃗ + t b ⃗ 1 b 1 1 ⃗ ( t ) = ( 1 − t ) b 1 ⃗ + t b ⃗ 2 b 0 2 ⃗ ( t ) = ( 1 − t ) b 0 1 ⃗ + t b ⃗ 1 1 ⇒ b 0 2 ⃗ ( t ) = ( 1 − t ) 2 b ⃗ 0 + 2 t ( 1 − t ) b 1 ⃗ + t 2 b ⃗ 2 \vec{b^1_0}(t)=(1-t)\vec{b_0}+t\vec b_1 \\ \vec{b^1_1}(t)=(1-t)\vec{b_1}+t\vec b_2 \\ \vec{b^2_0}(t)=(1-t)\vec{b_0^1}+t\vec b_1^1 \\ \Rightarrow \vec{b_0^2}(t)=(1-t)^2\vec b_0 + 2t(1-t)\vec{b_1}+t^2\vec b_2 b01 (t)=(1t)b0 +tb 1b11 (t)=(1t)b1 +tb 2b02 (t)=(1t)b01 +tb 11b02 (t)=(1t)2b 0+2t(1t)b1 +t2b 2

三阶以及多阶曲线

类似于二阶曲线,三阶以及多阶贝塞尔曲线也是采用同样的方法,不断进行迭代,每一个t确定一个点,最后形成一条曲线。

image-20220210112920807

计算贝塞尔曲线有一个对于任意阶通用的公式:德卡斯特里奥算法 (De Casteljau’s algorithm),是一种递归的计算贝塞尔曲线的方法:
b ⃗ n ( t ) = b ⃗ 0 n ( t ) = ∑ j = 0 n b ⃗ j B j n ( t ) , where  b ⃗ j  is the Bernstein polynomial Bernstein polynomial:  B t n ( t ) = ( n t ) t i ( 1 − t ) n − i \vec b^n(t)=\vec b_0^n(t)=\sum_{j=0}^n\vec b_jB_j^n(t)\text{, where }\vec b_j \text{ is the Bernstein polynomial} \\ \text{Bernstein polynomial: }B^n_t(t)=\tbinom{n}{t}t^i(1-t)^{n-i} b n(t)=b 0n(t)=j=0nb jBjn(t), where b j is the Bernstein polynomialBernstein polynomial: Btn(t)=(tn)ti(1t)ni

使用Three.js中的贝塞尔曲线绘制心形

绘制圆形

我们首先可以通过贝塞尔曲线绘制出一个圆形,心形可以在圆形的基础上进行一定的控制点的调整就可以绘制而成。

aEsuA

从上图中可以看出,一个圆形可以被分成四个弧线,每条弧线可以通过一个三阶贝塞尔曲线绘制而成(两个控制点),控制点的位置在geometry - How to create circle with Bézier curves? - Stack Overflow已经有人计算好了,我们可以直接使用(这里的计算也并不是特别复杂,简单的数学知识就可以计算出来)。由此,我们可以通过贝塞尔曲线创建出一个圆的形状:

const x = 0, y = 0;
const radius = 30;
const c = 0.551915024494 * radius;

const heartShape = new THREE.Shape()
    .moveTo(x, y+radius)
    .bezierCurveTo(x+c,y+radius, x+radius, y+c, x+radius, y)
    .bezierCurveTo(x+radius,y-c, x+c, y-radius, x, y-radius)
    .bezierCurveTo(x-c,y-radius, x-radius, y-c, x-radius, y)
    .bezierCurveTo(x-radius,y+c, x-c, y+radius, x, y+radius)

bezierCurveTo()是Three.js中的贝塞尔曲线的API,它接受六个参数,前四个分别是两个控制点的x,y坐标,最后两个是终止点的x,y坐标。这里只需要设定好参数,使用四段贝塞尔曲线一一绘制出来就可以了。

绘制心形

心形其实就是在圆形的基础上移动了三个控制点的位置,将y轴上上方的起始点稍向下移动,以及下方左右两个控制点向上移动,就可以绘制出一个心形,代码以及效果图如下所示。

const x = 0, y = 0;
const radius = 30;
const c = 0.551915024494 * radius;

const heartShape = new THREE.Shape()
    .moveTo(x, y+radius/3)
    .bezierCurveTo(x+c,y+radius, x+radius, y+c, x+radius, y)
    .bezierCurveTo(x+radius,y-c, x+c, y-radius/2, x, y-radius)
    .bezierCurveTo(x-c,y-radius/2, x-radius, y-c, x-radius, y)
    .bezierCurveTo(x-radius,y+c, x-c, y+radius, x, y+radius/3)

heart

参考资料

GAMES101-现代计算机图形学入门-闫令琪_哔哩哔哩_bilibili

德卡斯特里奥算法 - 维基百科,自由的百科全书 (wikipedia.org)

Path#bezierCurveTo – three.js docs (threejs.org)

AndroidNote_Path_BezierGcsSloop/AndroidNote (github.com)

geometry - How to create circle with Bézier curves? - Stack Overflow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值