曲线上一点的法线表示垂直于该点曲线的方向。要计算法线,需要找到曲线的导数,然后找到垂直于导数的单位向量。
在三次曲线的情况下,曲线由一组四个控制点 P0、T0、P1 和 T1 以及参数“A”定义。计算法线首先需要求曲线对“A”的导数,然后将结果归一化得到单位向量。
以下是如何计算曲线上某个点的法线的示例:
求曲线关于“A”的导数。为此,您需要对 CubicInterp 的等式中的每一项求导关于“A”,然后简化结果。
将结果归一化以获得单位向量。您可以通过将导数除以其大小来完成此操作,您可以将其计算为导数与其自身的点积的平方根。
template< class T, class U >
static FORCEINLINE_DEBUGGABLE T CubicSplineNormal( const T& P0, const T& T0, const T& P1, const T& T1, const U& A )
{
const float A2 = A * A;
T tangent = (T)((3*A2-2*A+1) * P0) + ((3*A-2*A2) * T0) + ((A3-A2) * T1) + ((-3*A2+A) * P1);
tangent = normalize(tangent);
T normal = cross(tangent, T(0, 0, 1));
return normal;
}
vector<T> CalculateNormals(const vector<T>& controlPoints, int numSegments)
{
vector<T> normals;
for (int i = 0; i < controlPoints.size() - 3; i += 3)
{
T P0 = controlPoints[i];
T T0 = controlPoints[i + 1];
T P1 = controlPoints[i + 2];
T T1 = controlPoints[i + 3];
float step = 1.0f / numSegments;
for (int j = 0; j < numSegments; ++j)
{
float A = j * step;
normals.push_back(CubicSplineNormal(P0, T0, P1, T1, A));
}
}
return normals;
}
在这段代码中,'控制点'是包含样条曲线控制点的向量,并且'numSegments'是将样条划分成的段数。这'计算法线'函数将样条拆分为'numSegments'段,并使用以下方法计算沿每个段的每个点的法线'CubicSplineNormal'功能。结果存储在'法线'向量并由函数返回。