It’s explained in [this article][1].
Here is some code for cubic Beziers:
void Subdivide(
Vector3 a0, Vector3 a1, Vector3 a2, Vector3 a3, float t,
out Vector3[] firstPart, out Vector3[] secondPart
) {
var b0 = Vector3.Lerp(a0, a1, t); // Same as evaluating a Bezier
var b1 = Vector3.Lerp(a1, a2, t);
var b2 = Vector3.Lerp(a2, a3, t);
var c0 = Vector3.Lerp(b0, b1, t);
var c1 = Vector3.Lerp(b1, b2, t);
var d0 = Vector3.Lerp(c0, c1, t); // This would be the interpolated point
firstPart = new Vector3[] { a0, b0, c0, d0 }; // first point of each step
secondPart = new Vector3[] { a3, b2, c1, d0 }; // last point of each step
}
EDIT:
Ah, now I understand what you meant (I’ll leave the previous answer because it might be helpful for someone else). Unfortunately I think this might be quite a difficult problem. It’s surely possible but it probably involves some nasty integrals. Depending on your requirements, an approximate solution might be enough. Here is one, it’s a bit ugly but it kinda works. It takes any curve (could be Bezier), the number of subdivisions you want to perform and a value that determines how accurate the approximation will be. It returns an array of values such that evaluating the curve with those values yields evenly spaced points.
float[] Subdivide(System.Func<float, Vector3> curve, int divisionCount, int approximationSteps) {
// Estimate distances along the curve in regular intervals of t
// by approximating the curve with a polyline
float stepSize = 1f / approximationSteps;
float[] distances = new float[approximationSteps + 1];
Vector3 last = curve(0);
Vector3 current;
for (int i = 1; i < distances.Length; i++) {
current = curve(i * stepSize);
distances *= distances[i - 1] + Vector3.Distance(last, current);*
last = current;
}
// Walk through distance array to find the t for each subdivision
float sectionLength = distances[distances.Length - 1] / (divisionCount + 1);
float[] divisions = new float[divisionCount];
int tInt = 0;
float tFrac;
for (int i = 0; i < divisionCount; i++) {
float target = (i + 1) * sectionLength; // Where the next subdivision should be
while (distances[tInt] < target) tInt++; // Skip until target is exceeded
tFrac = Mathf.InverseLerp(distances[tInt - 1], distances[tInt], target);
divisions = (tInt - 1 + tFrac) / approximationSteps;
}
return divisions;
}
Here is how it could be used:
var divisions = Subdivide(t => Bezier(a, b, c, d, t), 10, 100);
foreach (var t in divisions) {
var p = Bezier(a, b, c, d, t);
Gizmos.DrawLine(p + Vector3.down * 0.1f, p + Vector3.up * 0.1f);
}
If you just need it to look right, this should be accurate enough:
[132784-beziersubdivide.png|132784]_
_[1]: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-sub.html*_
_*