Math 样条法线计算

Math 样条法线计算,math,spline,splines,cubic-spline,Math,Spline,Splines,Cubic Spline,我在计算样条线的法线以从中挤出网格时遇到问题 检查图像: 正如你所看到的,某个区域的法线发生了翻转,我不知道为什么 相关代码: public Vector3 GetNormal(float t) { var tangent = GetTangent(t); var point = GetPoint(t); var accel = GetAcceleration(t); // we need to lerp up base d

我在计算样条线的法线以从中挤出网格时遇到问题

检查图像: 正如你所看到的,某个区域的法线发生了翻转,我不知道为什么

相关代码:

public Vector3 GetNormal(float t)
    {
        var tangent = GetTangent(t);
        var point = GetPoint(t);
        var accel = GetAcceleration(t);
        // we need to lerp up base don the control points
        int i;
        if (t >= 1f)
        {
            t = 1f;
            i = _points.Length - 4;
        }
        else
        {
            t = Mathf.Clamp01(t) * CurveCount;
            i = (int)t;
            t -= i;
            i *= 3;
        }
        //var rotaSource = GetControlPointRotation(i);
        //var rotaDest = GetControlPointRotation(i + 2);
        //var lerp = Mathf.Lerp(rotaSource, rotaDest,t);      
        //var normalRotation = Quaternion.AngleAxis(lerp,tangent);

        var binormal = Vector3.Cross(tangent, accel).normalized;

        var normalOr = Vector3.Cross(tangent, binormal).normalized;


        Debug.DrawLine(point, point + accel * 5, Color.blue);
        Debug.DrawLine(point, point + binormal * 5,Color.black);
        Debug.DrawLine(point, point + normalOr * 5, Color.yellow);
        Debug.DrawLine(point, point + tangent * 5, Color.magenta);

        if (Vector3.Dot(tangent, accel) > 0)
            return Vector3.up;

        return normalOr;
        //return (normalRotation*up).normalized;

    }


 public Vector3 GetAcceleration(float t)
        {
            int i;
            if (t >= 1f)
            {
                t = 1f;
                i = _points.Length - 4;
            }
            else
            {
                t = Mathf.Clamp01(t) * CurveCount;
                i = (int)t;
                t -= i;
                i *= 3;
            }

            return Bezier.GetSecondDerivative(_points[i], _points[i + 1], _points[i + 2],
                _points[i + 3], t).normalized;

        }



public Vector3 GetTangent(float t)
        {
            int i;
            if (t >= 1f)
            {
                t = 1f;
                i = _points.Length - 4;
            }
            else
            {
                t = Mathf.Clamp01(t) * CurveCount;
                i = (int)t;
                t -= i;
                i *= 3;
            }
            return
                Bezier.GetFirstDerivative(_points[i], _points[i + 1], _points[i + 2],
                    _points[i + 3], t).normalized;
        }
贝塞尔曲线方法如下:

     public static Vector3 GetPoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
            {
                t = Mathf.Clamp01(t);
                float OneMinusT = 1f - t;
                return OneMinusT*OneMinusT*OneMinusT*p0 + 3f*OneMinusT*OneMinusT*t*p1 + 3f*OneMinusT*t*t*p2 + t*t*t*p3;
            }

 public static Vector3 GetFirstDerivative(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
        {
            t = Mathf.Clamp01(t);
            float oneMinusT = 1f - t;
            float it = oneMinusT;
            float it2 = oneMinusT*oneMinusT;
            float t2 = t*t;


            return (p0 * -it2 +
            p1 * (t * (3 * t - 4) + 1) +
            p2 * (-3 * t2 + t * 2) +
            p3* t2).normalized;

            return 3f*oneMinusT*oneMinusT*(p1 - p0) + 6f*oneMinusT*t*(p2 - p1) + 3f*t*t*(p3 - p2);
        }


        public static Vector3 GetSecondDerivative(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
        {


            return (6*t*(p1 + 3*(p2 - p3) - p0) + 6*(p0 - 2*p2 + p3));
        }

我不知道为什么,也不知道如何修复它。我曾经尝试过使用参考向量,例如,在某些条件下(加速度和切线的点积<-1),我甚至尝试否定法线

根据曲线的曲率,副法线可以翻转。我们正在计算 B=T×dT 考虑平面中的S形曲线。在曲线的开始处,这些将在一个方向上,提供一个向外指向的双法线。在末端,它们处于相反的方向,提供向内指向的法线

此翻转的副法线将导致翻转法线。一个简单的修复方法就是使用

normalOr = accel.normalise
更先进的技术是在连续向量之间施加连续性。我们在第一点计算T1,N1,B1,和T2,N1,B1。现在计算T1。T2,N1。N2,B1。B2。对于连续向量场,这些点积中的每一个都应该是正的,如果有负的,只需翻转相应的向量即可


在曲率和扭转为零的点周围总是会出现问题

我的猜测是,法线是通过取平面外向量与沿贝塞尔曲线的导数的叉积来计算的。将翻转样条线的方向,但样条线的定义方向不同。第一条和第三条样条线使用从左向右移动的点;第二个方向相反。使所有点一致,法线将位于同一方向。使用accel.normalise似乎无法解决问题,从该样条线挤出a形状时,我得到了这些。还有其他解决办法吗?是否为法线添加默认方向?或者加上一个世界矢量并使用它?好吧,那个昏昏欲睡的白痴我刚刚明白了你所说的“更先进的技术”是什么意思,这正是我想要的;)非常感谢。