abenci
abenci

Reputation: 8681

Moving an object along a path with constant speed

I have an object path composed by a polyline (3D point array) with points VERY unevenly distributed. I need to move an object at constant speed using a timer with interval set at 10 ms.

Unevenly distributed points produce variable speed to the human eye. So now I need to decide how to treat this long array of 3D points.

The first idea I got was to subdivide long segments in smaller parts. It works better but where points are jam-packed the problem persists.

What's the best approach in these cases? Another idea, could be to simplify the original path using Ramer–Douglas–Peucker algorithm, then to subdivide it evenly again but I'm not sure if it will fully resolve my problem.

This should be a fairly common problem in many areas of the 3D graphics, so does a proven approach exist?

Upvotes: 0

Views: 1602

Answers (1)

damix911
damix911

Reputation: 4443

I made a JavaScript pen for you https://codepen.io/dawken/pen/eYpxRmN?editors=0010 but it should be very similar in any other language. Click on the rect to add points.

You have to maintain a time dependent distance with constant speed, something like this:

const t = currentTime - startTime;
const distance = (t * speed) % totalLength;

Then you have to find the two points in the path such that the current distance is intermediate between the "distance" on the path; you store the "distance from start of the path" on each point {x, y, distanceFromStart}. The first point points[i] such that distance < points[i].distanceFromStart is your destination; the point before that points[i - 1] is your source. You need to interpolate linearly between them.

Assuming that you have no duplicate points (otherwise you get a division by zero) you could do something like this.

for (let i = 0; i < points.length; i++) {
  if (distance < points[i].distanceFromStart) {

    const pFrom = points[i - 1];
    const pTo = points[i];
    const f = (distance - pFrom.distanceFromStart) / (pTo.distanceFromStart- pFrom.distanceFromStart);
    const x = pFrom.x + (pTo.x - pFrom.x) * f;
    const y = pFrom.y + (pTo.y - pFrom.y) * f;
    ctx.fillRect(x - 1, y - 1, 3, 3);
    break;
  }
}

See this pen. Click on the rectangle to add points: https://codepen.io/dawken/pen/eYpxRmN?editors=0010

Upvotes: 2

Related Questions