Discuss and collaborate on GML scripts

You are not logged in.

- Topics: Active | Unanswered

Pages: **1**

**xot****Administrator**- Registered: 2007-08-18
- Posts: 1,201

Computes a cubic Bézier curve given a parameter, t, and four control points, {p0,p1,p2,p3}.

[tex]\mathbf{B}(t)=(1-t)^3\mathbf{P}_0+3(1-t)^2t\mathbf{P}_1+3(1-t)t^2\mathbf{P}_2+t^3\mathbf{P}_3 \mbox{ , } t \in [0,1].[/tex]

```
// bezier4(t,p0,p1,p2,p3)
{
argument5 = 1 - argument0;
return
power(argument5,3) * argument1 +
power(argument5,2) * 3 * argument0 * argument2 +
power(argument0,2) * 3 * argument5 * argument3 +
power(argument0,3) * argument4;
}
```

Can this be optimized?

*Abusing forum power since 1986.*

Offline

**RaiSoleil****Member**- Registered: 2009-08-02
- Posts: 16

Depends. If you're calculating a series of points on one curve, you can precalculate some important stuff and use a different equation to save time.

Pseudocode, off the top of my head:

a = P3 - 3(P2 - P1) - P0

b = 3(P2 - 2P1 + P0)

c = 3(P1 - P0)

And then for any *t* on the the cubic curve B:

B(*t*) = ((a**t* + b)**t* + c)**t* + P0

You should be able to confirm a, b, and c by multiplying out the equation you have above and then regrouping by powers of *t* instead of by point #.

But I've got something even better. This script will work for an arbitrary number of points (just specify the right degree) and works on pure add/sub/mult/div. A cubic call takes 0.02 milliseconds.

```
/*
scr_bezier_point();
0 degree
1 t
n point
*/
var a, i, n, t, t1;
a = argument2;
i = 1;
n = 1;
t = 1;
t1 = 1-argument1;
repeat argument0 {
n *= (argument0-i+1) / i;
t *= argument1;
a *= t1;
a += argument[i+2] * n * t;
i += 1;
}
return a;
```

Bezier curves are crazy stuff. I came up with some equations for bezier-to-circle collision detection in April, and then this semester I wrote a paper on them to get credit for a calculus class. Booyah.

Offline

**xot****Administrator**- Registered: 2007-08-18
- Posts: 1,201

I guess if GM was compiled and had static variables, the first optimization could be included for a little boost. It's certainly useful information for special cases. Maybe a function that returns a list of values might be in order since it could take advantage of the precomputation. And it would be just plain handy in many cases.

Your nth degree Bézier function is awesome. I had a vague notion that something like that would be possible after reading a bit about how the equation is structured. That's totally going on the site.

I've always found splines a bit mysterious because it's difficult for me to visualize the mathematics involved. Then I saw these animations on Wikipedia that made everything so much clearer.

It sort of amused me as well. Some of my earliest graphics coding (circa 1982) used this same approach to drawing curves. All these years later and I had no idea it was related to how a Bézier curve actually works.

*Abusing forum power since 1986.*

Offline

**icuurd12b42****Member**- Registered: 2008-12-11
- Posts: 303

These animations are new. They were not there a while back. Only a bunch of equations. I'm glad someone finally realise the usefulness of pictures.

Offline

**xDanielx****Member**- Registered: 2009-01-02
- Posts: 38

Offline

**brac37****Member**- Registered: 2010-02-12
- Posts: 18

xot wrote:

Computes a cubic Bézier curve given a parameter, t, and four control points, {p0,p1,p2,p3}.

[tex]\mathbf{B}(t)=(1-t)^3\mathbf{P}_0+3(1-t)^2t\mathbf{P}_1+3(1-t)t^2\mathbf{P}_2+t^3\mathbf{P}_3 \mbox{ , } t \in [0,1].[/tex]

`// bezier4(t,p0,p1,p2,p3) { argument5 = 1 - argument0; return power(argument5,3) * argument1 + power(argument5,2) * 3 * argument0 * argument2 + power(argument0,2) * 3 * argument5 * argument3 + power(argument0,3) * argument4; }`

Can this be optimized?

Well, one/two times multiplication is faster than second/third power, I would think. Further, the terms in the middle can be factorized.

```
// bezier4(t,p0,p1,p2,p3)
{
argument5 = 1 - argument0;
return
sqr(argument5) * argument5 * argument1 +
3 * argument0 * argument5 * (argument5 *
argument2 + argument0 * argument3) +
sqr(argument0 * argument0 * argument4;
}
```

Offline

Pages: **1**