Archived

This topic is now archived and is closed to further replies.

Erkki

"parallel" bezier curves

Recommended Posts

In my game prototype, I am defining roads in the game world with bezier curves & lines. But when I want to draw these roads, I need to draw a few "parallel" (probably the wrong term) curves, depending on how many lanes there are on the road etc. The minimum would be 2 for one road (the sides of the road). But I don''t know how to calculate a "parallel" curve. The other curves would be a bit different and so the control points must change too. Is it even possible to calculate it? It would probably be easier if I used catmull-roms? Here''s a little picture to illustrate: http://lap.ttu.ee/erkki/bezier.jpg It isn''t exactly what I need, that just has the copy of the same curve placed next to the other. And in reality, the end points should not be apart like that, but one should be on the others normal.

Share this post


Link to post
Share on other sites
You can find the normal component to the curve at each point. By adding or substracting the normal vector to the position vector of that point, you''ll get another point. Now, do this for each point, and you should get a parallel curve... Even better, from the inital curve, create two parallel curves (so the inital shape serves as an axis).

How to do this? Well a Bézier curve is a R² Bernstein polynomial, of the form

{ X(t) = an t^n + .... a1 t + a0
{ Y(t) = bn t^n + .... b1 t + b0

So the tangent vector is obtained by derivating

{ Xtan(t) = n an t^(n-1) + ..... 2 a2 t + a1
{ Ytan(t) = n bn t^(n-1) + ..... 2 b2 t + b1

So Xnor = -Ytan, Ynor = Xran is a normal vector. Normalize it to have a magnitude vector, and multiply it by half the width of the path you want to create.

Basically, one side of your path will be

{ X(t) + (Width / 2) * (normalized)Xnor(t)
{ Y(t) + (Width / 2) * (normalized)Ynor(t)

And the other will be

{ X(t) - (Width / 2) * (normalized)Xnor(t)
{ Y(t) - (Width / 2) * (normalized)Ynor(t)

So for each (t) you can compute a point on each side of your road.


ToohrVyk

Share this post


Link to post
Share on other sites
yeah, you need to derive the curve to get the direction at the point of interest on the curve, and the second derivative will give you the ''acceleration'', which would be a direction pointing towards the ''inside'' of the curve. You cross product the two, and it will give you the vector towards the side of the curvature, basically, where to draw the parallel curve. The catmul-romms are not continuous in the second derivative, so they won;t be very useful for what you need. However, since you are doing roads, you can expect the road to be generally pointing up towards the sky. In that case, you can use just the first derivative, and deduce the direction of the width of the road.


// normal spline calculation, to get the point on a spline and the direction at that point.

void CalculatePointOnPath(float u, Vector& P, Vector& Dir)
{
.....
.....
.....
}

Vector CalculateSideVector(Vector Dir, Vector Up=Vector(0, 1, 0))
{
Vector Side = Up.Cross(Dir);

Side.Normalise();

Up = Dir.Cross(Side);

return Side;
}


so for a given point on the spline, the point on the other lane would be



float u; // Position on the spline of the control point

Vector P; // point on the reference spline (control point)

Vector Dir; // the direction of the spline at point P

Vector Up; // the reference direction of the road

Vector Side; // where the parallel spline should be relative to the reference spline


// calculate the point on path and the direction of the path at that point

CalculatePointOnPath(u, P, Dir);

Dir.Normalise();

Up = Vector(0, 1, 0);

// calculate the side direction at the point on path to generate a point on a parallel spline

Side = CalculateSideVector(Dir, Up);

// calculate the point on the parallel spline

Pother = P + Side * widthOfLane;




if the spline is C2 continous, you can do



float u; // Position on the spline of the control point

Vector P; // point on the reference spline (control point)

Vector Dir; // the direction of the spline at point P

Vector Up; // the reference direction of the road

Vector Side; // where the parallel spline should be relative to the reference spline


// calculate the point on path and the direction of the path at that point

CalculatePointOnPath(u, P, Dir, Up);

Dir.Normalise();
Up.Normalise();

// calculate the side direction at the point on path to generate a point on a parallel spline

Side = Up.Cross(Up, Dir);
Side.Normalise();

// calculate the point on the parallel spline

Pother = P + Side * widthOfLane;

Share this post


Link to post
Share on other sites
Uuh... thanx for your help. I haven''t done much math for several years so It''ll take me some time to figure this out

Share this post


Link to post
Share on other sites
I don''t know if this is more of a math or programming question, but:

If I want to have a bit more bends following each other, should I use a bezier curve with more control points (I haven''t looked into how that works exactly, but the code I''ve been using to draw a bezier - from SDL_gfx - let''s you use any number of points >= 3)? Or should I just put several 4-point beziers together?

I think the first option would make everything a bit more difficult so I''m leaning towards using several 4-point beziers in a row.

Share this post


Link to post
Share on other sites
Id'' advise you to use several 4-point curves (even 3-point ones) because that solution is less computationnally expensive/

ToohrVyk

Share this post


Link to post
Share on other sites