赞
踩
一条贝塞尔曲线是由一组定义的控制点P0到 Pn,n=1为线性,n=2为二次......第一个和最后一个控制点称为起点和终点,中间的控制点一般不会位于曲线上
获取两个点之间的点就是通过线性插值( Mathf.Lerp),0 <= t <= 1
——线性公式:给定点P0、P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出
——二阶贝塞尔曲线:二次方贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)公式推导:由(P0,P1),(P1,P2)分别求线性公式所得的结果P0‘ 和 P1‘再带入线性公式,整理所得即为二次公式
P0,P1所求:
P1,P2所求:
P0,P1,P2二次方公式:
简化所得
——三阶贝塞尔曲线:P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝兹曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;这两个点只是在那里提供方向。P0和P1之间的间距,决定了曲线在转而趋进P3之前,走向P2方向的“长度有多长”。
其公式为
- using UnityEngine;
- using System.Collections.Generic;
-
- /// <summary>
- /// 贝塞尔工具类
- /// </summary>
- public static class BezierUtils
- {
- /// <summary>
- /// 线性贝塞尔曲线
- /// </summary>
- public static Vector3 BezierCurve(Vector3 p0, Vector3 p1, float t)
- {
- Vector3 B = Vector3.zero;
- B = (1 - t) * p0 + t * p1;
- return B;
- }
-
- /// <summary>
- /// 二阶贝塞尔曲线
- /// </summary>
- public static Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, float t)
- {
- Vector3 B = Vector3.zero;
- float t1 = (1 - t) * (1 - t);
- float t2 = 2 * t * (1 - t);
- float t3 = t * t;
- B = t1 * p0 + t2 * p1 + t3 * p2;
- return B;
- }
-
- /// <summary>
- /// 三阶贝塞尔曲线
- /// </summary>
- public static Vector3 BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
- {
- Vector3 B = Vector3.zero;
- float t1 = (1 - t) * (1 - t) * (1 - t);
- float t2 = 3 * t * (1 - t) * (1 - t);
- float t3 = 3 * t * t * (1 - t);
- float t4 = t * t * t;
- B = t1 * p0 + t2 * p1 + t3 * p2 + t4 * p3;
- return B;
- }
-
- /// <summary>
- /// n阶贝塞尔曲线
- /// </summary>
- public static Vector3 BezierCurve(List<Vector3> pointList, float t)
- {
- Vector3 B = Vector3.zero;
- if (pointList == null)
- {
- return B;
- }
- if (pointList.Count < 2)
- {
- return pointList[0];
- }
-
- List<Vector3> tempPointList = new List<Vector3>();
- for (int i = 0; i < pointList.Count - 1; i++)
- {
- Vector3 tempPoint = BezierCurve(pointList[i], pointList[i + 1], t);
- tempPointList.Add(tempPoint);
- }
- return BezierCurve(tempPointList, t);
- }
- }
- using System.Collections.Generic;
- using UnityEngine;
-
- public class BezierTest : MonoBehaviour
- {
- public int m_CurveDensity;//曲线密度
- public bool m_IsSecondOrderBezier;//是否为二阶贝塞尔曲线,否则为三阶贝塞尔曲线
-
- private List<Transform> m_ControlPointList = new List<Transform>();//所有的控制点(控制点作为挂载此脚本的游戏物体的子物体)
-
- public void OnDrawGizmos()
- {
- //添加控制点
- m_ControlPointList.Clear();
- foreach (Transform trans in transform)
- {
- m_ControlPointList.Add(trans);
- }
-
- List<Vector3> pointList = new List<Vector3>();//曲线上的所有点
- if (m_IsSecondOrderBezier)
- {
- if (m_ControlPointList.Count < 3)
- {
- return;
- }
- //获取曲线上的所有点
- for (int i = 0; i < m_ControlPointList.Count - 2; i += 2)
- {
- Vector3 p0 = m_ControlPointList[i].position;
- Vector3 p1 = m_ControlPointList[i + 1].position;
- Vector3 p2 = m_ControlPointList[i + 2].position;
- for (int j = 0; j <= m_CurveDensity; j++)
- {
- float t = j * 1f / m_CurveDensity;
- Vector3 point = BezierUtils.BezierCurve(p0, p1, p2, t);
- pointList.Add(point);
- }
- }
- }
- else
- {
- if (m_ControlPointList.Count < 4)
- {
- return;
- }
- //获取曲线上的所有点
- for (int i = 0; i < m_ControlPointList.Count - 3; i += 3)
- {
- Vector3 p0 = m_ControlPointList[i].position;
- Vector3 p1 = m_ControlPointList[i + 1].position;
- Vector3 p2 = m_ControlPointList[i + 2].position;
- Vector3 p3 = m_ControlPointList[i + 3].position;
- for (int j = 0; j <= m_CurveDensity; j++)
- {
- float t = j * 1f / m_CurveDensity;
- Vector3 point = BezierUtils.BezierCurve(p0, p1, p2, p3, t);
- pointList.Add(point);
- }
- }
- }
-
- //绘制所有点
- foreach (var point in pointList)
- {
- Gizmos.DrawSphere(point, 0.1f);
- }
- //绘制控制点连线
- Gizmos.color = Color.red;
- for (int i = 0; i < m_ControlPointList.Count - 1; i++)
- {
- Gizmos.DrawLine(m_ControlPointList[i].position, m_ControlPointList[i + 1].position);
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。