2016-10-10 15 views
1

У меня проблема с вычислением нормали сплайна для выдавливания сетки.Сплайн Нормальный расчет

Проверьте изображение: enter image description here Как вы можете видеть, нормали в определенной области aplop перевернулись, и я понятия не имею, почему.

Соответствующий код:

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)); 
     } 

Я понятия не имею, почему, и как это исправить. Я попытался использовать ссылочный вектор, вроде как безрезультатно, я даже попытался отрицать нормаль на определенных условиях (Dot prouct of accel и tangent < -1).

+0

Я предполагаю, что нормаль вычисляется путем взятия поперечного произведения внеплоскостного вектора с производной вдоль кривой Безье. Вы перевернете направление сплайнов, которые не определены в одном направлении. Первый и третий сплайны используют точки, которые продвигаются слева направо; второй работает в противоположном направлении. Сделайте все точки согласованными, а нормали будут в одном направлении. – duffymo

ответ

3

Бинормаль может переворачиваться в зависимости от кривизны кривой. Мы вычисляем B = T X dT Рассмотрим S-образную кривую в плоскости. В начале кривой они будут в одной ориентации, что дает двунаправленную направленную направленность. В конце они находятся в противоположной ориентации, указав нормальное положение внутрь.

Этот перевернутый бинормаль приведет к нормальному отражению. Простое исправление состоит в том, чтобы использовать только

normalOr = accel.normalise 

Более совершенный метод заключается в наложении непрерывности между последовательными векторами. Итак, мы вычисляем T1, N1, B1 в первой точке и T2, N1, B1. Теперь вычислим T1. T2, N1. N2, B1. БИ 2. Для непрерывных векторных полей каждый из этих точечных произведений должен быть положительным, если какие-либо отрицательные, просто переверните соответствующий вектор.

У вас всегда возникают проблемы вокруг точек с нулевой кривизной и кручением.

+0

с использованием метода ускорения. Похоже, что проблема не устраняется, когда выдается форма из этого сплайна, я получаю эти [артефакты] (https://i1.someimage.com/mhMdJye.png). Есть ли другое решение? Как добавить направление по умолчанию для нормального? Или добавление Up-вектора мира и использование этого? – Morphex

+0

ОК, поэтому сонный идиот меня просто понял, что вы подразумеваете под «более сложной техникой», и это именно то, что я хочу;) Спасибо! – Morphex

 Смежные вопросы

  • Нет связанных вопросов^_^