1
\$\begingroup\$

Does anyone know how to accelerate a moving object along a Bezier curve? I found a post here that seems to solve the problem but I do not understand how to apply this code, particularly what is done to the "NewT" value in the "Finally, accelerating the ships" section of the answer.

I apologise about raising a new question about this, I was prohibited from commenting on the original question. If anyone has a solution in C# that goes through and explains each step that would be highly appreciated.

__

Further detail:

enter image description here

Scenario: The moving object moves with linear velocity until it reaches P1. When it reaches P1, I need to create the motion of the blue dashed path. Whilst the object follows the blue dashed path, it needs to uniformly accelerate from Velocity(start) to Velocity(end). Please note that the path is a rough sketch, in reality it should have smoother curvature without the abrupt changes in direction.

The following pieces of information are known:

  • Velocity (start), e.g. 5 m/s
  • Velocity (end), e.g. 10 m/s
  • The locations of the four points P1 - P4
  • The location of the centre of the circle

So far I have been able to successfully create a curve path by joining multiple bezier curves to form a spline:

enter image description here

But I do not know how to accelerate the yellow dot as it moves through the path. Any help would be really appreciated.

\$\endgroup\$
2
  • \$\begingroup\$ Can you tell us more about what kind of acceleration you want, and what degree of Bézier curve you need? Just evaluating a Bézier curve naturally comes with acceleration, and you can think of a cubic Bézier as a linearly-changing acceleration from an incoming velocity to an outgoing velocity. Try telling us a bit about what gameplay feature you're using this for in your game, and we can help you find the right curve and acceleration profile for that use case. \$\endgroup\$
    – DMGregory
    Oct 17, 2021 at 12:17
  • \$\begingroup\$ Thanks for your comments guys, I have updated the original post. Please note that the shape of the path should be changeable. It is the the ability to create the acceleration through the path that I am really struggling with. Also when I say accelerating from one velocity to another, I mean that the magnitude of the velocity changes, so it should move faster, e.g. from 5m/s to 10m/s at a uniform rate. \$\endgroup\$
    – Cato
    Oct 17, 2021 at 14:10

2 Answers 2

1
\$\begingroup\$

The behaviour you're describing is something we can get "out of the box" with a cubic Bézier spline, no new features required. You just need to set the control points accordingly.

If we want our path to begin at position p0 with velocity v0, and end at p1 with velocity v1 after a duration in seconds, then our four control points are:

c0 = p0
c1 = p0 + v0 * duration / 3.0f
c2 = p1 - v1 * duration / 3.0f
c3 = p1

You can then evaluate this at a time t seconds after leaving the start point as:

float progress = t / duration;
Vector2 position = Bezier(c0, c1, c2, c3, progress);

...where the Bézier function is the usual:

Vector2 Bezier(Vector2 c0, Vector2 c1, Vector2 c2, Vector2 c3, float p) {
    float invP = 1 - P;
    return  invP * invP * invP * c0
         + 3 * invP * invP * p * c1
            + 3 * invP * p * p * c2
                   + p * p * p * c3;
}

If you like the shape you get using those control points, you're golden. Using the p1, v1 of one segment as the p0, v0 of the next segment will give you first derivative continuity across the spline (smooth connections with no sharp corners or sudden changes in speed).

\$\endgroup\$
2
  • \$\begingroup\$ Why use a Bézier at all for the straight segment when you can just use a lerp? position = lerp(startPosition, endPosition, secondsTravelling / segmentDuration) where segmentDuration = distance(startPosition, endPosition)/speed. \$\endgroup\$
    – DMGregory
    Oct 17, 2021 at 17:24
  • \$\begingroup\$ Let us continue this discussion in chat. \$\endgroup\$
    – DMGregory
    Oct 17, 2021 at 17:24
0
\$\begingroup\$

The following code gets the point along a Bézier curve, for an arbitrary number of control points:

Adapted from https://stackoverflow.com/questions/785097/how-do-i-implement-a-bézier-curve-in-c

vector_4 getBezierPoint(vector<vector_4> points, float t)
{
    size_t i = points.size() - 1;

    while (i > 0)
    {
        for (size_t k = 0; k < i; k++)
        {
            points[k].x += t * (points[k + 1].x - points[k].x);
            points[k].y += t * (points[k + 1].y - points[k].y);
            points[k].z += t * (points[k + 1].z - points[k].z);
            points[k].w += t * (points[k + 1].w - points[k].w);
        }

        i--;
    }

    return points[0];
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .