bezier curves

Started by
9 comments, last by szecs 14 years, 1 month ago
Hi, I am currently using cubic bezier curves (4 control points) to direct paths my camera moves on. Using similar code as described in this wiki: http://www.gamedev.net/reference/articles/article1808.asp However, I need to expand this to be a 6 point bezier curve, however it was hard for me to find information on how to do this. The code im using for a cubic curve is like so:

// where alpha is incremented elsewhere
double a = 1.0 - m_alpha;
double b = m_alpha;

position.x = m_curvePoints[0].x * a * a * a + m_curvePoints[1].x * 3 * a * a * b + m_curvePoints[2].x * 3 * a * b * b + m_curvePoints[3].x * b * b * b;

position.y = m_curvePoints[0].y * a * a * a + m_curvePoints[1].y * 3 * a * a * b + m_curvePoints[2].y * 3 * a * b * b + m_curvePoints[3].y * b * b * b;

position.z = m_curvePoints[0].z * a * a * a + m_curvePoints[1].z * 3 * a * a * b + m_curvePoints[2].z * 3 * a * b * b + m_curvePoints[3].z * b * b * b;
Any help would be great. Thanks.
Advertisement
Check out the Wikipedia article; the general form is given in the section titled 'Generalization'.

It looks like the example given there (for n = 5) is exactly what you're looking for.

[Edit: Direct link (see after 'For example, for n = 5:').]
Thanks for your reply jyk!

I must have missed that when i skimmed over it before. I have modified the code for a 6 point curve (using that wiki) that seems to be working okay, but I did have another question of its use.

At the moment my camera is rotating around a planet sized sphere. I am trying to get the camera to do a 6 point curve to get to / look at a specific surface point.

I can do the rotation easy enough, this is just for positioning
I hope this doesn't sound like a mess...

// 'totalLength' is the length of a vector between the starting point and the ending point

// 'upDirection' is a directional vector from the sphere centre to the midpoint of a vector between the starting point and end point

My points are:

1) The starting position of the camera

2) The starting position plus a point that is backwards along the camera's forward vector by totalLength

3) The starting position plus a point that is along upDirection by totalLength

4) The ending position plus a point that is along upDirection by totalLength

5) The ending position plus a point that is backwards along the camera's forward vector by totalLength

6) The ending position of the camera

I thought that this would give me a nice curve that moves backwards out of the starting position, moves around the sphere and then goes into the ending position. But it seems to act strangely when far away from the target point (around the other side of the sphere for example).

Am I going about this type of problem all wrong? xD

Thanks.
Quote:1) The starting position of the camera

2) The starting position plus a point that is backwards along the camera's forward vector by totalLength

3) The starting position plus a point that is along upDirection by totalLength

4) The ending position plus a point that is along upDirection by totalLength

5) The ending position plus a point that is backwards along the camera's forward vector by totalLength

6) The ending position of the camera

I thought that this would give me a nice curve that moves backwards out of the starting position, moves around the sphere and then goes into the ending position. But it seems to act strangely when far away from the target point (around the other side of the sphere for example).
Keep in mind that with a Bezier curve, the curve itself is only guaranteed to pass through the first and last control points. I can't quite visualize what you described above, but it seems like you could pretty easily end up with a curve that passes through the sphere or otherwise behaves incorrectly.

In any case, if the camera is just dollying in and out and moving around a sphere, I'm not sure that Bezier curves are the best choice here. Why not just have the camera follow the shortest arc from the start point to the end point, while moving away from the sphere at the beginning and then back towards the sphere at the end?
Have you looked into Catmull–Rom splines?
Thanks for the replies again!

jyk, your answer seems quite logical and I would like to try that, I suppose the only hurdle for me was how to vary the alpha variable over the course of the transition to make it zoom right out and then back in again (which is why I started looking at curves with control points in the first place).

Before I was just doing a standard slerp for the rotation (and then position), and using the alpha variable (starts from 0.0 and goes to 1.0 at completion) to gradually get to the height needed at the end point. But this did not have a zooming in and out pattern, just a gradual increase or decline in height depending on what the final desired height was.

Would you have any advice on how to go about achieving that dolly in/out effect? I guess it would need to dolly out more if the camera was further around the other side of the sphere, but I have no idea how to get it to do this.

My code that currently does the rotation and positioning (works fine):

WorldQuaternion transitionSlerp = WorldQuaternion::Slerp(m_alpha, m_transitionStart, m_transitionEnd);transitionSlerp.Normalize();transitionSlerp.ToRotation(rotation);WorldMatrix3D orgRotation;m_transitionStart.ToRotation(orgRotation);WorldMatrix3D rotationDiff = rotation * orgRotation.Inverse();position = rotationDiff * m_transitionStartPos;


My code that currently alters the position again to dolly in/out (this works but is not the effect that I want):

float centreToStartRadius = m_transitionStartPos.Length();float centreToEndRadius = m_transitionEndPos.Length();float offsetDistance = centreToStartRadius - centreToEndRadius;float radiusChange = centreToStartRadius - (centreToStartRadius - (offsetDistance * m_alpha));WorldPoint3D PosToCentre = -position;PosToCentre.Unitize();position += (PosToCentre * radiusChange);


I have a function that currently calculates alpha depending on the time, and the selected duration that the transition is suppose to take.

// where fTime is the current timem_alpha = ((fTime - m_transitionStartTime) / m_transitionDuration);// clamp alpha to maximum to stop transitionif (m_alpha >= 1.0f){	m_alpha = 1.0f;	ClearMovement();	return false;}return true;


Again, any help would be great. Thanks for the responses so far.
I'm not 100% clear on the behavior you're after, so I can probably only offer general suggestions at this point.

One possibility would be to use a different type of spline, as suggested by Wan. If you want to handle the orbiting and dollying separately though, it seems there'd be any number of functions you could come up with to control the camera distance. For example, you could interpolate from the initial distance to a max 'orbital' distance over the first half of the rotation, and then from the 'orbital' distance to the goal distance over the second half, using an 'ease in, ease out' function to smooth the effect.
About the Catmull–Rom splines. I'm having trouble finding a site that can explain it so that I can expand it into code for 6 control points. Every example I see seems to deal with only 4 control points. But it seems like a good option if I can get something working with it.

At the moment im just trying to alter the dolly in / out for a maximum height at the half way point as you suggested.

[Edited by - McFury on March 10, 2010 11:52:41 PM]
Hi again,

Okay so I am just testing using a 4 point Catmull-rom curve at the moment. I noticed that the curve seems to only move between the middle two control points (not the starting and ending points). Is this because its not a closed curve and I need to do something else to the equation?

The code im using (found on web):

void PointOnCurve(WorldPoint3D &out, float t, TrackPoint p0, TrackPoint p1, TrackPoint p2, TrackPoint p3){float t2 = t * t;float t3 = t2 * t;out.x = 0.5f * ( ( 2.0f * p1.x ) +( -p0.x + p2.x ) * t +( 2.0f * p0.x - 5.0f * p1.x + 4 * p2.x - p3.x ) * t2 +( -p0.x + 3.0f * p1.x - 3.0f * p2.x + p3.x ) * t3 );out.y = 0.5f * ( ( 2.0f * p1.y ) +( -p0.y + p2.y ) * t +( 2.0f * p0.y - 5.0f * p1.y + 4 * p2.y - p3.y ) * t2 +( -p0.y + 3.0f * p1.y - 3.0f * p2.y + p3.y ) * t3 );out.z = 0.5f * ( ( 2.0f * p1.z ) +( -p0.z + p2.z ) * t +( 2.0f * p0.z - 5.0f * p1.z + 4 * p2.z - p3.z ) * t2 +( -p0.z + 3.0f * p1.z - 3.0f * p2.z + p3.z ) * t3 );}


I also realize now that I need to have multiple segements (each with 4 control points, but each only describing the p1 -> p2 parts of the curve. So I need a way to connect the curve segments. Does anyone know any good way to do this with what im doing?

Thanks

[Edited by - McFury on March 11, 2010 1:01:24 AM]
Sorry to bump this, but does anyone know about joining catmull-rom segements? i cannot seem to find any pages on this.

Thanks.

This topic is closed to new replies.

Advertisement