目前正在尝试沿贝塞尔曲线实例化一些对象。它正在工作,除了网格不是沿曲线均匀分布的事实。所以我需要做一些弧参数化。
我的信息来自这个文档WarpingTextToSplines所以下面的代码是我对伪代码的解释。
首先,找到曲线的(大约)长度,并将其分成几部分:
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;
}
这将存储 100 个沿曲线的长度值。这些稍后用于确定曲线上放置网格的正确位置。使用以下方法在表中找到该值:
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;
}
}
我尝试了许多不同的二次贝塞尔曲线算法,但这些算法似乎产生了正确的结果。
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;
}
更新
我还将把我写的代码放在实例化曲线上的对象上,以防我在那里做一些愚蠢的事情。
//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);}
以下是一些 lerp 查询:
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
附加更新
经过 SO 用户“MBo”的一些调整和帮助后,我现在使用固定长度的十个对象得到了相当均匀的分布。然而,它们仍在向曲线的起点分配更多。
我已经更新了我的代码以使用这个 SO 问题How-to-achieve-uniform-speed-of-movement-on-a-bezier-curve的第二个答案中提到的表创建和二进制搜索
我已经通过并检查了很多次,我开始对眼了。我不确定我的数学是否关闭,所以我误解了一些东西。
曲线上的大多数网格在开始时都是分组的,然后一段时间后它们开始变得均匀。
如果有人有任何想法或建议,我将不胜感激。
谢谢