当前位置:   article > 正文

Unity中的数学基础——贝塞尔曲线_unity 贝塞尔曲线

unity 贝塞尔曲线

一:前言 

一条贝塞尔曲线是由一组定义的控制点P0到 Pn,n=1为线性,n=2为二次......第一个和最后一个控制点称为起点和终点,中间的控制点一般不会位于曲线上 
获取两个点之间的点就是通过线性插值( Mathf.Lerp),0 <= t <= 1


二:贝塞尔曲线公式

——线性公式:给定点P0、P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出

1


——二阶贝塞尔曲线:二次方贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)公式推导:由(P0,P1),(P1,P2)分别求线性公式所得的结果P0‘ 和 P1‘再带入线性公式,整理所得即为二次公式
P0,P1所求:
1.1.1
P1,P2所求:
1.2.2
P0,P1,P2二次方公式:
1.2.3
简化所得
1.2.4


——三阶贝塞尔曲线:P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝兹曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;这两个点只是在那里提供方向。P0和P1之间的间距,决定了曲线在转而趋进P3之前,走向P2方向的“长度有多长”。
其公式为
1.3.1 


三:公式转换为代码

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. /// <summary>
  4. /// 贝塞尔工具类
  5. /// </summary>
  6. public static class BezierUtils
  7. {
  8. /// <summary>
  9. /// 线性贝塞尔曲线
  10. /// </summary>
  11. public static Vector3 BezierCurve(Vector3 p0, Vector3 p1, float t)
  12. {
  13. Vector3 B = Vector3.zero;
  14. B = (1 - t) * p0 + t * p1;
  15. return B;
  16. }
  17. /// <summary>
  18. /// 二阶贝塞尔曲线
  19. /// </summary>
  20. public static Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, float t)
  21. {
  22. Vector3 B = Vector3.zero;
  23. float t1 = (1 - t) * (1 - t);
  24. float t2 = 2 * t * (1 - t);
  25. float t3 = t * t;
  26. B = t1 * p0 + t2 * p1 + t3 * p2;
  27. return B;
  28. }
  29. /// <summary>
  30. /// 三阶贝塞尔曲线
  31. /// </summary>
  32. public static Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
  33. {
  34. Vector3 B = Vector3.zero;
  35. float t1 = (1 - t) * (1 - t) * (1 - t);
  36. float t2 = 3 * t * (1 - t) * (1 - t);
  37. float t3 = 3 * t * t * (1 - t);
  38. float t4 = t * t * t;
  39. B = t1 * p0 + t2 * p1 + t3 * p2 + t4 * p3;
  40. return B;
  41. }
  42. /// <summary>
  43. /// n阶贝塞尔曲线
  44. /// </summary>
  45. public static Vector3 BezierCurve(List<Vector3> pointList, float t)
  46. {
  47. Vector3 B = Vector3.zero;
  48. if (pointList == null)
  49. {
  50. return B;
  51. }
  52. if (pointList.Count < 2)
  53. {
  54. return pointList[0];
  55. }
  56. List<Vector3> tempPointList = new List<Vector3>();
  57. for (int i = 0; i < pointList.Count - 1; i++)
  58. {
  59. Vector3 tempPoint = BezierCurve(pointList[i], pointList[i + 1], t);
  60. tempPointList.Add(tempPoint);
  61. }
  62. return BezierCurve(tempPointList, t);
  63. }
  64. }

 四:绘制出曲线

  

  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. public class BezierTest : MonoBehaviour
  4. {
  5. public int m_CurveDensity;//曲线密度
  6. public bool m_IsSecondOrderBezier;//是否为二阶贝塞尔曲线,否则为三阶贝塞尔曲线
  7. private List<Transform> m_ControlPointList = new List<Transform>();//所有的控制点(控制点作为挂载此脚本的游戏物体的子物体)
  8. public void OnDrawGizmos()
  9. {
  10. //添加控制点
  11. m_ControlPointList.Clear();
  12. foreach (Transform trans in transform)
  13. {
  14. m_ControlPointList.Add(trans);
  15. }
  16. List<Vector3> pointList = new List<Vector3>();//曲线上的所有点
  17. if (m_IsSecondOrderBezier)
  18. {
  19. if (m_ControlPointList.Count < 3)
  20. {
  21. return;
  22. }
  23. //获取曲线上的所有点
  24. for (int i = 0; i < m_ControlPointList.Count - 2; i += 2)
  25. {
  26. Vector3 p0 = m_ControlPointList[i].position;
  27. Vector3 p1 = m_ControlPointList[i + 1].position;
  28. Vector3 p2 = m_ControlPointList[i + 2].position;
  29. for (int j = 0; j <= m_CurveDensity; j++)
  30. {
  31. float t = j * 1f / m_CurveDensity;
  32. Vector3 point = BezierUtils.BezierCurve(p0, p1, p2, t);
  33. pointList.Add(point);
  34. }
  35. }
  36. }
  37. else
  38. {
  39. if (m_ControlPointList.Count < 4)
  40. {
  41. return;
  42. }
  43. //获取曲线上的所有点
  44. for (int i = 0; i < m_ControlPointList.Count - 3; i += 3)
  45. {
  46. Vector3 p0 = m_ControlPointList[i].position;
  47. Vector3 p1 = m_ControlPointList[i + 1].position;
  48. Vector3 p2 = m_ControlPointList[i + 2].position;
  49. Vector3 p3 = m_ControlPointList[i + 3].position;
  50. for (int j = 0; j <= m_CurveDensity; j++)
  51. {
  52. float t = j * 1f / m_CurveDensity;
  53. Vector3 point = BezierUtils.BezierCurve(p0, p1, p2, p3, t);
  54. pointList.Add(point);
  55. }
  56. }
  57. }
  58. //绘制所有点
  59. foreach (var point in pointList)
  60. {
  61. Gizmos.DrawSphere(point, 0.1f);
  62. }
  63. //绘制控制点连线
  64. Gizmos.color = Color.red;
  65. for (int i = 0; i < m_ControlPointList.Count - 1; i++)
  66. {
  67. Gizmos.DrawLine(m_ControlPointList[i].position, m_ControlPointList[i + 1].position);
  68. }
  69. }
  70. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/580282
推荐阅读
相关标签
  

闽ICP备14008679号