细节修正
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
class QuadBezierLine {
|
class QuadBezierLine {
|
||||||
constructor(_p0, _p1, _p2, _step, _uniformSpeed) {
|
constructor(_p0, _p1, _p2, _step, _uniformSpeedMode) {
|
||||||
this.step=_step;
|
this.step=_step;
|
||||||
this.points=[];
|
this.points=[];
|
||||||
this.uniformSpeed=_uniformSpeed;
|
this.uniformSpeedMode=_uniformSpeedMode;
|
||||||
this.updatePoints(_p0, _p1, _p2);
|
this.updatePoints(_p0, _p1, _p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,16 +25,16 @@ class QuadBezierLine {
|
|||||||
return (temp5 + temp6) / (8 * Math.pow(this.A, 1.5));
|
return (temp5 + temp6) / (8 * Math.pow(this.A, 1.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
//X(n+1) = Xn - F(Xn)/F'(Xn)
|
//u'=u-(Length(u)-len)/Speed(u)
|
||||||
invertLength(t, len) {
|
invertLength(u0, len) {
|
||||||
let t1 = t, t2;
|
let u1 = u0, u2;
|
||||||
do {
|
do {
|
||||||
t2 = t1 - (this.length(t1) - len) / this.speed(t1);
|
u2 = u1 - (this.length(u1) - len) / this.speed(u1);
|
||||||
if (Math.abs(t1 - t2) < 0.000001)
|
if (Math.abs(u1 - u2) < 0.000001)
|
||||||
break;
|
break;
|
||||||
t1 = t2;
|
u1 = u2;
|
||||||
} while (true);
|
} while (true);
|
||||||
return t2;
|
return u2;
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePoints(_p0, _p1, _p2) {
|
updatePoints(_p0, _p1, _p2) {
|
||||||
@@ -57,8 +57,7 @@ class QuadBezierLine {
|
|||||||
for (let index = 1; index < this.step; index++) {
|
for (let index = 1; index < this.step; index++) {
|
||||||
let t = index / this.step;
|
let t = index / this.step;
|
||||||
|
|
||||||
if(this.uniformSpeed) {
|
if(this.uniformSpeedMode) {
|
||||||
//根据 L 函数的反函数,求得 l 对应的 t 值
|
|
||||||
t = this.invertLength(t, totalLength*t);
|
t = this.invertLength(t, totalLength*t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ tags: 程序 算法
|
|||||||
---
|
---
|
||||||
# 匀速贝塞尔曲线运动的实现
|
# 匀速贝塞尔曲线运动的实现
|
||||||
|
|
||||||
二次贝塞尔曲线通常以如下方式构建,给定二维平面上的固定点$P_0$, $P_1$, $P_2$,用$B(t)$表示该条曲线
|
贝塞尔曲线([Bézier curve](https://en.wikipedia.org/wiki/B%C3%A9zier_curve))是一种常用的曲线,以最简单的二次贝塞尔曲线为例,通常以如下方式构建,给定二维平面上的固定点$P_0$, $P_1$, $P_2$,用$B(t)$表示该条曲线
|
||||||
$$
|
$$
|
||||||
\boldsymbol{B}(t)=(1-t)^2 \boldsymbol{P_0}+2t(1-t) \boldsymbol{P_1}+t^2 \boldsymbol{P_2}
|
\boldsymbol{B}(t)=(1-t)^2 \boldsymbol{P_0}+2t(1-t) \boldsymbol{P_1}+t^2 \boldsymbol{P_2}, t\in[0, 1]
|
||||||
$$
|
$$
|
||||||
用一个动画来演示,可以更加清楚的表明这条曲线的构建过程
|
用一个动画来演示,可以更加清楚的表明这条曲线的构建过程
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ $$
|
|||||||
<iframe width="100%" height="270" frameborder=0 src="/html/bezier.html?uniformSpeed=0"></iframe>
|
<iframe width="100%" height="270" frameborder=0 src="/html/bezier.html?uniformSpeed=0"></iframe>
|
||||||
|
|
||||||
可以看出中间的点较为密集,而两边则较为稀疏。
|
可以看出中间的点较为密集,而两边则较为稀疏。
|
||||||
如何想要得到匀速的贝塞尔曲线运动呢?比如我们在某款游戏中设计了一条贝塞尔曲线的路径,如何实现玩家匀速在这条路径上运动呢?
|
如何得到匀速的贝塞尔曲线运动呢?比如我们在某款游戏中设计了一条贝塞尔曲线的路径,如何实现NPC匀速在这条路径上运动?
|
||||||
首先需要求得$B(t)$相对于$t$的速度公式$s(t)$
|
首先需要求得$B(t)$相对于$t$的速度公式$s(t)$
|
||||||
$$
|
$$
|
||||||
s(t)=\sqrt{B_{x}^{'}(t)^2+B_{y}^{'}(t)^2}
|
s(t)=\sqrt{B_{x}^{'}(t)^2+B_{y}^{'}(t)^2}
|
||||||
@@ -44,21 +44,23 @@ L(t)&=\int_0^t\sqrt{Ax^2+Bx+C}dx\\
|
|||||||
&\quad+(B^2-4AC)\left[ln(B+2\sqrt{AC})-ln\left(B+2At+2\sqrt{A}\sqrt{At^2+Bt+C}\right)\right]\biggr)
|
&\quad+(B^2-4AC)\left[ln(B+2\sqrt{AC})-ln\left(B+2At+2\sqrt{A}\sqrt{At^2+Bt+C}\right)\right]\biggr)
|
||||||
\end{aligned}
|
\end{aligned}
|
||||||
$$
|
$$
|
||||||
特别当$t=1.0$时,$L(1.0)$就是这条曲线的总长度。
|
特别当$t=1.0$时,$L(1.0)$就是这条曲线的总长度。
|
||||||
设$t'$是能够使$L$实现匀速运动的自变量,那么此时曲线长度应该满足线性增长,也就是
|
设$u$是能够使$L(u)$实现匀速运动的自变量,那么此时曲线长度应该满足随着时间$t$线性增长,也就是
|
||||||
$$
|
$$
|
||||||
L(t')=L(1.0)t\tag{1}
|
L(u)=L(1.0)t\tag{1}
|
||||||
$$
|
$$
|
||||||
也就是$t'=L^{-1}(L(1.0)t)$,由于$L(t)$函数非常复杂,直接求其逆函数的解析解几乎不可能,还好我们知道它的导数为$s(t)$,在实际使用中,可以使用[牛顿切线法](https://en.wikipedia.org/wiki/Newton%27s_method)获得$t'$的数值解。
|
也就是$u=L^{-1}(L(1.0)t)$,由于$L(t)$函数非常复杂,直接求其逆函数的解析解几乎不可能,还好我们知道它的导数为$s(t)$,在实际使用中,可以使用[牛顿切线法](https://en.wikipedia.org/wiki/Newton%27s_method)获得$u$的数值解。
|
||||||
设$L_t=L(1.0)t$,视$t'$为未知数,根据公式1有以下方程
|
视$u$为未知数,根据公式1有以下方程
|
||||||
$$
|
$$
|
||||||
L(t')-L_t=0
|
F(u)=L(u)-L(1.0)t=0
|
||||||
$$
|
$$
|
||||||
根据牛顿切线法,求解的迭代公式为:
|
根据牛顿切线法,求解$u$的迭代公式为:
|
||||||
$$
|
$$
|
||||||
t'_{n+1}=t'_n-\frac{L(t'_n)-L_t}{s(t'_n)}
|
\begin{aligned}
|
||||||
|
u_{n+1}&=u_n-\frac{F(u_n)}{F'(u_n)}\\&=u_n-\frac{L(u_n)-L(1.0)t}{s(u_n)}
|
||||||
|
\end{aligned}
|
||||||
$$
|
$$
|
||||||
由于$t$和$t'$相差不大,可以设$t_0=t$来开始求解,以下是修正后的匀速贝塞尔曲线
|
由于$t$和$u$相差不大,可以设$u_0=t$来开始求解,以下是修正后的匀速贝塞尔曲线
|
||||||
|
|
||||||
<iframe width="100%" height="270" frameborder=0 src="/html/bezier.html?uniformSpeed=1"></iframe>
|
<iframe width="100%" height="270" frameborder=0 src="/html/bezier.html?uniformSpeed=1"></iframe>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user