前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Bezier曲线移动

使用Bezier曲线移动

作者头像
keyle
发布2024-11-01 12:13:39
700
发布2024-11-01 12:13:39
举报
文章被收录于专栏:礼拜八不工作

Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。

以下公式中:B(t)为t时间下 点的坐标;

P0为起点,Pn为终点,Pi为控制点

一阶贝塞尔曲线(线段):

意义:由 P0 至 P1 的连续点, 描述的一条线段

二阶贝塞尔曲线(抛物线):

原理:由 P0 至 P1 的连续点 Q0,描述一条线段。

由 P1 至 P2 的连续点 Q1,描述一条线段。

由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

经验:P1-P0为曲线在P0处的切线。

三阶贝塞尔曲线:

通用公式:

高阶贝塞尔曲线:

4阶曲线:

5阶曲线:

附:文末是C#中使用贝塞尔曲线的脚本

代码语言:javascript
复制
using UnityEngine;
using System.Collections;
using Pathfinding;

public class BezierMover : MonoBehaviour {

public Transform[] points;

public float tangentLengths = 5;
public float speed = 1;

  float time = 0;

  void Update (  ) {
Move ( true );
  }

Vector3 Plot (float t) {
Vector3 inTang, outTang;


    int c = points.Length;
    int pt = Mathf.FloorToInt(t);
    inTang = (  (points[(pt+1)%c].position - points[(pt+0)%c].position).normalized - (points[(pt-1+c)%c].position - points[(pt+0)%c].position).normalized ).normalized;

    outTang = (  (points[(pt+2)%c].position - points[(pt+1)%c].position).normalized - (points[(pt-0+c)%c].position - points[(pt+1)%c].position).normalized ).normalized;

Debug.DrawLine ( points[pt%c].position, points[pt%c].position + inTang*tangentLengths, Color.red);
Debug.DrawLine ( points[(pt+1)%c].position - outTang*tangentLengths, points[(pt+1)%c].position, Color.green);

return AstarMath.CubicBezier ( points[pt%c].position, points[pt%c].position + inTang*tangentLengths, points[(pt+1)%c].position - outTang*tangentLengths, points[(pt+1)%c].position, t - pt);
  }

// Update is called once per frame
  void Move ( bool progress ) {

/*if ( time > pt+1 ) {
      Move ( false );
      return;
    }*/

    float mn = time;
    float mx = time+1;
while ( mx - mn > 0.0001f ) {
      float mid = (mn+mx)/2;

Vector3 p = Plot ( mid );
if ( (p-transform.position).sqrMagnitude > (speed*Time.deltaTime)*(speed*Time.deltaTime) ) {
        mx = mid;
      } else {
        mn = mid;
      }
    }

    time = (mn+mx)/2;


/*Vector3 p1 = AstarMath.CubicBezier ( points[pt%c].position, points[pt%c].position + inTang*tangentLengths, points[(pt+1)%c].position - outTang*tangentLengths, points[(pt+1)%c].position, time - pt);
    Vector3 p2 = AstarMath.CubicBezier ( points[pt%c].position, points[pt%c].position + inTang*tangentLengths, points[(pt+1)%c].position - outTang*tangentLengths, points[(pt+1)%c].position, time - pt + 0.001f);*/
Vector3 p1 = Plot(time);
Vector3 p2 = Plot(time+0.001f);
    transform.position = p1;
    transform.rotation = Quaternion.LookRotation ( p2 - p1 );

  }

public void OnDrawGizmos () {
if ( points.Length >= 3 ) {

for ( int i = 0; i < points.Length; i++ ) if ( points[i] == null ) return;

for ( int pt = 0; pt < points.Length; pt++ ) {

        int c = points.Length;
Vector3 inTang = (  (points[(pt+1)%c].position - points[pt+0].position).normalized - (points[(pt-1+c)%c].position - points[pt+0].position).normalized ).normalized;

Vector3 outTang = (  (points[(pt+2)%c].position - points[(pt+1)%c].position).normalized - (points[(pt-0+c)%c].position - points[(pt+1)%c].position).normalized ).normalized;

Vector3 pp = points[pt].position;

for ( int i=1;i<=100;i++) {
Vector3 p = AstarMath.CubicBezier ( points[pt].position, points[pt].position + inTang*tangentLengths, points[(pt+1)%c].position - outTang*tangentLengths, points[(pt+1)%c].position, i / 100.0f );
Gizmos.DrawLine ( pp, p );
          pp = p;
        }
      }

    }
  }

}

参考链接:http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 礼拜八不工作 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档