The API has the handy BezierCurve classes, however, the structures are all Vector2's. Is there a way to make 3-dimensional Bezier curves? That seems like it would be more generally useful than the 2-dimensional curves.

Posted Wednesday, 1 August, 2012 - 01:22 by Robmaister

I wrote a basic 3d implementation of both Quadratic and Cubic Bezier curves in about half an hour without looking at the OpenTK ones (didn't know they existed at the time). Once you understand how they work, they're trivial to implement. You could probably take the OpenTK ones and search-and-replace Vector2 with Vector3 and it'll work (or be very close to working).

Posted Tuesday, 21 August, 2012 - 22:03 by chronosifter

If your still curious about this subject, some tricks I've used to develop bezier curve and surface functions in several languages (including GLSL and HLSL).

I choose to use the Bernstein basis approach to calculating the intervals since it yielded the best performance out of all the methods I've tried in shaders, as well as lowest instruction counts.

The two functions which are required for this approach are the following:

Key:
- n = number of controls points.
- i = index of the control point.
- t = linear distance between the first and last control points to the point you want to extract the coordinate for.
- Num! = factorial of Num
- Num^Power = raise Num to Power
Binomial Coefficient: b(n, i) = n! / (i! * (n - i)!)
Bernstein Basis: B(n, i, t) = b(n, i) * t^i * (1 - t)^(n - i)

From there it's simple to calculate points on the curve or surface.

Higher dimension repeat that pattern, but tangents get a bit hairy as you tack on more dimensions, I've only really solved out 2D surface tangents since it's all I ever needed:

To extract the tangent, bitangent, and normal from that:
TangentX = (C1 - C2) * n
TangentY = (C1 - C2) * n
Normal = -cross(TangentX, TangentY)
Bitangent = cross(TangentY, Normal)

For the Tangent use TangentY if Y-axis is up in your world, TangentX if Z is up.

## Comments

## Re: Is it possible to make 3d Bezier curves using the API?

I wrote a basic 3d implementation of both Quadratic and Cubic Bezier curves in about half an hour without looking at the OpenTK ones (didn't know they existed at the time). Once you understand how they work, they're trivial to implement. You could probably take the OpenTK ones and search-and-replace Vector2 with Vector3 and it'll work (or be very close to working).

The Wikipedia article for Bezier curves has an excellent animated gif explaining how they work: http://en.wikipedia.org/wiki/B%C3%A9zier_curve

## Re: Is it possible to make 3d Bezier curves using the API?

If your still curious about this subject, some tricks I've used to develop bezier curve and surface functions in several languages (including GLSL and HLSL).

I choose to use the Bernstein basis approach to calculating the intervals since it yielded the best performance out of all the methods I've tried in shaders, as well as lowest instruction counts.

The two functions which are required for this approach are the following:

Key:

- n = number of controls points.

- i = index of the control point.

- t = linear distance between the first and last control points to the point you want to extract the coordinate for.

- Num! = factorial of Num

- Num^Power = raise Num to Power

Binomial Coefficient: b(n, i) = n! / (i! * (n - i)!)

Bernstein Basis: B(n, i, t) = b(n, i) * t^i * (1 - t)^(n - i)

From there it's simple to calculate points on the curve or surface.

1D: bez(p, t, n) = sum(i = 0->n) B(n, i, t) * p[i]

2D: bez(p, t, n) = sum(i = 0->n)sum(j = 0->n) B(n, i, t.x) * B(n, j, t.y) * p[i][j]

Higher dimension repeat that pattern, but tangents get a bit hairy as you tack on more dimensions, I've only really solved out 2D surface tangents since it's all I ever needed:

X-axis Tangent

- C1(p, t, n) = sum(i = 0->n)sum(j = 0->n - 1) B(n - 2, j, t.x) * p[i][j + 1]

- C2(p, t, n) = sum(i = 0->n)sum(j = 0->n - 1) B(n - 2, j, t.x) * p[i][j]

Y-axis Tangent

- C1(p, t, n) = sum(i = 0->n)sum(j = 0->n - 1) B(n - 2, j, t.y) * p[j + 1][i]

- C2(p, t, n) = sum(i = 0->n)sum(j = 0->n - 1) B(n - 2, j, t.y) * p[j][i]

To extract the tangent, bitangent, and normal from that:

TangentX = (C1 - C2) * n

TangentY = (C1 - C2) * n

Normal = -cross(TangentX, TangentY)

Bitangent = cross(TangentY, Normal)

For the Tangent use TangentY if Y-axis is up in your world, TangentX if Z is up.