Jump to content
  • Advertisement
Sign in to follow this  
CarlML

Getting y on a curve given x?

This topic is 3497 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, a little math problem; I need a way to create a falloff using a bezier curve. Here is the setup: There are axis of x and y and both go from 0.0 to 1.0. As x goes from 0 to 1 I need to find the y value on the bezier curve. The curve can have any number of points but always starts at x = 0.0 and ends at x = 1.0. No values along the curve are below 0 or above 1. Any ideas on how to calculate the curve's y value given a value on the x axis?

Share this post


Link to post
Share on other sites
Advertisement
This sounds like home work - in which case I can only suggest you read your text book and/or handouts :)

Otherwise I suggest Googling bezier, interpolation, and wolfram

Share this post


Link to post
Share on other sites
No home work, although I'm at home, and working. Just want to pick your minds.:)

I know how to calculate a point along a bezier curve, like say 0.5 along the curve, but I can't get my head around the algorithm well enough to figure out how to plug in a x value and get an y value out.

As an example I calculate a position along the curve like this(Point2 is a class containing two floats for x and y):

Point2 curv1(0.0f,1.0f);
Point2 curv2(1.0f,0.0f);
Point2 curvTang1(1.0f,1.0f);
Point2 curvTang2(1.0f,1.0f);
Point2 c = 3 * (curvTang1 - curv1);
Point2 b = (3 * (curvTang2 - curvTang1)) - c;
Point2 a = curv2 - curv1 - c - b;

float r = 0.5f; // value along curve
float r2 = r * r;
float r3 = r2 * r;

Point2 curvepos = (a * r3) + (b * r2) + (c * r) + curv1;



The value 0.5 along the curve is not the same as when x is 0.5 though...

[Edited by - CarlML on January 23, 2009 2:27:00 PM]

Share this post


Link to post
Share on other sites
Just do the calculation in the x dimension only and set the result of the equation to 0.5 then you need to solve for t, plug that t back into the equation for the y dimension and get y. Unless I misunderstand what you need?

Share this post


Link to post
Share on other sites
The approach proposed by asp_ is the way to go. However, there can be more than one solution if you use bezier curves of a higher order than cubic. This makes things complicated. I would consider limiting the number of control points. If this is not an option you need to look at algorithms for approximating the solution of higher order polynomials.

Share this post


Link to post
Share on other sites
Thanks, yes I should be able to limit the control points, at most I think I will need 5.

I will try out the asp_ suggestion and see where it takes me.

Share this post


Link to post
Share on other sites
Well it didn't take me anywhere.:P ...but I decided to do a more brute force method and build a lookup table with 1001 entries. I then step through in steps of 0.001 and get that x value along the curve. The value that generates an x closest to the current step is choosen. A lookup table would be something I would want anyway for fast lookup so this is good and the table takes only about a millisecond to create. This is the new code: (only for a curve with two points currently, start and end)

Point2 curv1(0.0f,1.0f);
Point2 curv2(1.0f,0.0f);
Point2 curvTang1(0.0f,0.25f);
Point2 curvTang2(0.25f,0.0f);
Point2 c = 3 * (curvTang1 - curv1);
Point2 b = (3 * (curvTang2 - curvTang1)) - c;
Point2 a = curv2 - curv1 - c - b;

curveLookup.resize(1001); //std::vector<float>

for (int i=0;i<1001;i++)
{
float xval = 0.001f * i;
float theval = 0.0f;
for (int d=0;d<1001;d++)
{
float val = 0.001f * d;
float r2 = val * val;
float r3 = r2 * val;
float test = (a.x * r3) + (b.x * r2) + (c.x * val) + curv1.x;
if (test > xval) break;
theval = val;
}
float r2 = theval * theval;
float r3 = r2 * theval;
curveLookup = (a.y * r3) + (b.y * r2) + (c.y * theval) + curv1.y;
}


Then I can access by doing:

xval = 0.5f;
yval = curveLookup[(int)(xval * 1000)];


[Edited by - CarlML on January 24, 2009 2:54:07 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!