Get Current Point In Cubic Bezier Curve

lxXTaCoXxl 0 Tallied Votes 447 Views Share

I realized that I haven't released any snippets in a while so I figured while I was working on some interesting projects of my own that I would release one that I recently decided to write because I don't see the algorithm out there in C# very often. This snippet is useful for plotting preset paths in game development and can be used in many different styles. A race track, an enemy path in a 2D shooter, a plane's flight path, graph editing, so on and so forth. The implementation is simple as well. If you don't want to use the BezierPoint class that is provided then just replace it with the Point class from .NET framework when working with forms applications, or Vector2 from XNA Framework. I use my own class because I thought it would be fun. Anyways, hope you all enjoy and hope it helps some one out there.

Formula for a cubic Bezier curve:

^ = Exponent
_ = Subset

[x, y] = (1 - t)^3P_0 + 3(1 - t)^2tP_1 + 3(1 - t)t^2P_2 + t^3P_3

Algorithm Variables:
A = 3 * (P_1 - P_0)
B = 3 * (P_2 - P_1)
C = P_3 - P_0 - A - B

Algorithm (Current Point):
(C * t^3) + (B * t^2) + (A * t) + P_0

Have a great year,
Jamie

// Class to hold the X and Y variable for each point.
public class BezierPoint
{
public float X { get; private set; }
public float Y { get; private set; }

public BezierPoint(float x, float y) { this.X = x; this.Y = y; }
}

// Method used to get the current point in the curve based on t.
public BezierPoint CurrentPoint(float t, BezierPoint p0, BezierPoint p1, BezierPoint p2, BezierPoint p3)
{
float cube = t * t * t;
float square = t * t;

BezierPoint a = 3 * (p1 - p0);
BezierPoint b = 3 * (p2 - p0);
BezierPoint c = p3 - p0 - a - b;
BezierPoint r = (c * cube) + (b * square) + (a * t) + p0;

return r;
}

// Implementation (used with timer in most cases):
BezierCurve ObjectPoint;
BezierCurve EndPoint1 = new BezierCurve(200, 80);
BezierCurve ControlPoint1 = new BezierCurve(180, 160);
BezierCurve ControlPoint2 = new BezierCurve(90, 300);
BezierCurve EndPoint2 = new BezierCurve(312, 115);

for (float t = 0.0f; t < 1.0f; t += 0.01f)
ObjectPoint = CurrentPoint(t, EndPoint1, ControlPoint1, ControlPoint2, EndPoint2);
lxXTaCoXxl 26 Posting Whiz in Training

Just found out that I can't use my custom class the way I have it set up here (that's what I get for typing it up in notepad), so instead here's a new snippet:

public Point CurrentPoint(float t, Point p0, Point p1, Point p2, Point p3)
{
float cube = t * t * t;
float square = t * t;

float ax = 3 * (p1.X - p0.X);
float ay = 3 * (p1.Y - p0.Y);

float bx = 3 * (p2.X - p1.X) - ax;
float by = 3 * (p2.Y - p1.Y) - ay;

float cx = p3.X - p0.X - ax - bx;
float cy = p3.Y - p0.Y - ay - by;

float x = (cx * cube) + (bx * square) + (ax * t) + p0.X;
float y = (cy * cube) + (by * square) + (ay * t) + p0.Y;

return new Point(x, y);
}

The implementation is pretty much the same:

Point ObjectPoint;
Point Endpoint1 = new Point(200, 80);
Point ControlPoint1 = new Point(180, 160);
Point ControlPoint2 = new Point(90, 300);
Point EndPoint2 = new Point(312, 115);

// Forms Apps:
float t = 0.0f;
private void timer1_Tick(object sender, EventArgs e)
{
t += 0.01f

if (t > 1.0f)
t = 0.0f;

ObjectPoint = CurrentPoint(t, Endpoint1, ControlPoint1, ControlPoint2, EndPoint2);
}

// XNA:
TimeSpan MoveTime = TimeSpan.FromMilliseconds(50);
TimeSpan LastMove;

float t = 0.0f;
protected override void Update(GameTime gameTime)
{
if (gameTime.TotalGameTime - LastMove > MoveTime)
{
LastMove = gameTime.TotalGameTime;

t += 0.01f;

if (t > 1.0f)
t = 0.0f;

ObjectPoint = CurrentPoint(t, EndPoint1, ControlPoint1, ControlPoint2, EndPoint2);
}
}

When using XNA just change all the Point variable types to Vector2 variable types. The method I used in the original snippet will work with Vector2 types (not sure about Point types). Once again, enjoy!

Jamie

Keith_2 0 Newbie Poster

Can I ask, what does t refer to? the x axis or something else?
Would you be able to expand on the methods to include

public static float GetForX(float x)

and

public static float GetForY(float y)

? Thanks.

lxXTaCoXxl 26 Posting Whiz in Training

Sorry for the extremely late response, however t refers to the point in time you are looking for during the travel of the curve. To get x and y individually you would simply do the following:

float x = CurrentPoint(t, e1,c1,c2,e2).X;
float y = CurrentPoint(t, e1,c1,c2,e2).Y;

-Jamie

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.