Archive 17/01/2023.

Possible SplinePath Speed Bug

George1

It looks like speed changes between control point path segment. See gif below.
I set the speed of each node to be the same. But it changes between control points.
On short segment node move slower.

Spline Bug

George1

What you mean?
If I have a linear line to travel. With a constant speed ( same for each characters), Shouldn’t I get a constant gap between the characters.

I’m not sure if the interpolate position GetPoint return the correct position. The following calculation is done similar to a single node Move method.

Modanung

I do think this is intended behaviour for a spline path.

George1

This is the calculation.

float newDistance = lstPed_[i]->relativePosInQueue_ + dt * lstPed_[i]->speed_;
float traveled_ = newDistance / queuePath_->GetLength();
lstPed_[i]->GetNode()->SetWorldPosition(queuePath_->GetPoint(traveled_));

Modanung

If you divide the speed by the length of the current segment it should be constant.

George1

I don’t believe this is correct.

If it is a linear. It is easy to get the correct position.

The behaviour is wrong. Theoretically.

Modanung

For your use case, yes.
The interpolation logic is consistent along different interpolation modes.

George1

The current logic return incorrect position as you can see in the gif.

Modanung

What if you were to move the knots during runtime? Which behaviour would you expect?

George1

I recalculate the length using the built in SplinePath function when I move the knots.

George1

Anyway maybe leave it here.
I’m only trying to report a possible bug/behaviour.

I will fix the interpolation.

The math should be easy.

Best regards

Modanung

“There are a few ways to move along at a constant speed along a path whose “segments” are not a constant length - and it’s not trivial to make them that way.” - ClickerMonkey

This supports my not-a-bug theory. :wink:

George1

Thanks I have done this a number of years ago in Irrlicht.

Best regards

Eugene

Are you talking about linear interpolation between control points or more complex cases too?

George1

Yes! Navigate through multi control points.

For linear polyline.
It is easier to fix the behaviour. E.g.
I speed up my simulation clock to reduce the file size of the gif.

Linear Spline fixed

For catmul-rom I can use this multi linear line segment method or the calculus method via simson’s rule.

George1

A simple piecewise linear over existing interpolation.

Linear Spline fixed

I first linearized the spline.

void LinearisedPath()
{

	if (queuePath_->GetControlPoints().Size() > 2)
	{
		Spline spline = queuePath_->GetSpline();
		int size = queuePath_->GetControlPoints().Size();
		double rate = 0.001f;
		splinePath_.Clear();
		for (float f = 0.f; f <= 1.0f; f += rate)
		{
			Vector3 b = spline.GetPoint(f).GetVector3();
			splinePath_.AddKnot(b);
		}
	}
	else if (queuePath_->GetControlPoints().Size() == 2)
	{
		splinePath_ = queuePath_->GetSpline();
	}

}

Then loop through like below.

    Vector<Variant> knots_ = splinePath_.GetKnots();
int size = knots_.Size();
int segment = 1;
float sumLength = 0.0f;

for (; segment < size; segment++)
{

	float segmentLength = (knots_[segment].GetVector3() - knots_[segment - 1].GetVector3()).Length();
	sumLength += segmentLength;
	if (sumLength >= relativeDistance)
		break;
}

if (segment == size)
{
	segment--;
}

Vector3 dir = knots_[segment].GetVector3() - knots_[segment - 1].GetVector3();
dir.y_ = 0;
dir.Normalize();
Vector3 pos = knots_[segment].GetVector3() - dir * (sumLength - character->relativePosInQueue_);
Quaternion Q;
Q.FromLookRotation(dir);
Q.Normalize();
character->GetNode()->SetRotation(Quaternion());
character->GetNode()->SetWorldRotation(Q);
character->GetNode()->SetWorldPosition(pos);

I recommend we have dynamic number of interpolate segment increases with number of control points. This will remove the debug line drawn bug.