Currently trying to instantiate some objects along a bezier curve. It's working, except for the fact that the meshes are not evenly distributed along the curve. So I need to do some arc-parameterization.
My information has come from this document WarpingTextToSplines so the code below is my interpretation of the pseudo-code.
First off, finding the (approx) length of the curve, and dividing it into sections:
private void buildCurveTables()
{
int curveSegments = 100;
lengthTable = new float[curveSegments + 1];
Vector3 previousPoint = GetBezierPoint(0, curvePoints[0], curvePoints[1], curvePoints[2]);
float sum = 0;
lengthTable[0] = 0;
for (int i = 1; i < lengthTable.Length; i++)
{
Vector3 currentPoint = GetBezierPoint(i / (float) lengthTable.Length, curvePoints[0], curvePoints[1], curvePoints[2]);
sum += Vector3.Distance(previousPoint, currentPoint);
lengthTable[i] = sum;
previousPoint = currentPoint;
}
totalCurveLength = sum;
}
This stores 100 values of the lengths along the curve. These are used later to determine the correct position on the curve to put the mesh. The value is found in the table using this:
private float findPositionOnCurve(float u)
{
float t; //Find t for the given u
float targetArcLength = u * lengthTable[lengthTable.Length-1];
//Debug.Log("u is: " + u);
int index = Array.BinarySearch(lengthTable, targetArcLength);
if (u >=1)
{
return 1;
}
if (index < 0)
{
index = ~index - 1;
//No exact match found
float lengthBefore = lengthTable[index];
return (index + (targetArcLength - lengthBefore) / (lengthTable[index + 1] - lengthBefore)) / lengthTable.Length;
}
else
{
//Exact match found
t = index / (float)lengthTable.Length - 1;
//Debug.Log("Exact match, returning " + t);
return t;
}
}
I've tried a number of different quadratic bezier curve algorithms, but these are the ones that seem to be producing the correct results.
private Vector3 GetBezierPoint(float t, Vector3 start, Vector3 control, Vector3 end)
{
//float x = (((1 - t) * (1 - t)) * start.x) + (2 * t * (1 - t) * control.x) + ((t * t) * end.x);
//float y = (((1 - t) * (1 - t)) * start.y) + (2 * t * (1 - t) * control.y) + ((t * t) * end.y);
//float z = (((1 - t) * (1 - t)) * start.z) + (2 * t * (1 - t) * control.z) + ((t * t) * end.z);
//return new Vector3(x, y, z);
//http://answers.unity3d.com/questions/990171/curve-between-lerps.html
float rt = 1 - t;
return rt * rt * start + 2 * rt * t * control + t * t * end;
}
UPDATE
I'll also put up the code I've written to Instantiating the objects on the curve, in case I'm doing something dumb there..
//Only try to curve the objects once the control point has been put down.
if (curvedMode && createdCurveControlHandle)
{
Vector3 startOfCurve = getCurveStartPoint().transform.position;
curvePoints = new Vector3[3] { startOfCurve, currentCurveControlHandle.transform.position, currentMousePosition };
buildCurveTables();
//Lerp value is generated through a loop that generates 'n' number of
objects based on the distance between the start and current mouse position
float mappedLerp = findPositionOnCurve(lerpValue);
Vector3 pointTest = GetBezierPoint(mappedLerp, curvePoints[0], curvePoints[1], curvePoints[2]);
nextPlacementLocationTarget = pointTest;
nextPosition = Vector3.Lerp(startOfCurve, nextPlacementLocationTarget,mappedLerp);}
Here are a few of the lerp lookups:
Lerp: 0.32 mappedLerp: 0.1659664
Lerp: 0.36 mappedLerp: 0.1896916
Lerp: 0.3999999 mappedLerp: 0.2143274
Lerp: 0.4399999 mappedLerp: 0.2399609
Lerp: 0.4799999 mappedLerp: 0.2667291
Lerp: 0.5199999 mappedLerp: 0.2948231
Lerp: 0.5599999 mappedLerp: 0.3244205
ADDITIONAL UPDATE
After some tweaking and help from SO user 'MBo' I've now got a fairly even distribution using a fixed length of ten objects. However they are still distributing more towards the start of the curve.
I've updated my code to use the table creation and binary search mentioned in the second answer on this SO question How-to-achieve-uniform-speed-of-movement-on-a-bezier-curve
I've been through and checked it so many times, I'm starting to go cross eyed. I'm not sure if my maths is off, so I'm misunderstanding something.
The majority of the meshes on the curve are all grouped at the start, then after a while they start to even out.
If anyone has any ideas or suggestions, I'd greatly appreciate it.
Thanks