我试图在我的Unity游戏中实现一个简单的bezier曲线,但似乎没有用。 这是如何绘制的截图:
4个绿色球体是Bezier的枢轴,白色球体是计算出来的实际贝塞尔曲线。如你所见,它有点不正确。
这是我的bezier代码(我从Unity的论坛中获取):
using UnityEngine;
[System.Serializable]
public class Bezier : System.Object
{
public Vector3 p0;
public Vector3 p1;
public Vector3 p2;
public Vector3 p3;
public float ti = 0f;
private Vector3 b0 = Vector3.zero;
private Vector3 b1 = Vector3.zero;
private Vector3 b2 = Vector3.zero;
private Vector3 b3 = Vector3.zero;
private float Ax;
private float Ay;
private float Az;
private float Bx;
private float By;
private float Bz;
private float Cx;
private float Cy;
private float Cz;
// Init function v0 = 1st point, v1 = handle of the 1st point , v2 = handle of the 2nd point, v3 = 2nd point
// handle1 = v0 + v1
// handle2 = v3 + v2
public Bezier( Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3 )
{
this.p0 = v0;
this.p1 = v1;
this.p2 = v2;
this.p3 = v3;
}
// 0.0 >= t <= 1.0
public Vector3 GetPointAtTime( float t )
{
this.CheckConstant();
float t2 = t * t;
float t3 = t * t * t;
float x = this.Ax * t3 + this.Bx * t2 + this.Cx * t + p0.x;
float y = this.Ay * t3 + this.By * t2 + this.Cy * t + p0.y;
float z = this.Az * t3 + this.Bz * t2 + this.Cz * t + p0.z;
return new Vector3( x, y, z );
}
private void SetConstant()
{
this.Cx = 3f * ( ( this.p0.x + this.p1.x ) - this.p0.x );
this.Bx = 3f * ( ( this.p3.x + this.p2.x ) - ( this.p0.x + this.p1.x ) ) - this.Cx;
this.Ax = this.p3.x - this.p0.x - this.Cx - this.Bx;
this.Cy = 3f * ( ( this.p0.y + this.p1.y ) - this.p0.y );
this.By = 3f * ( ( this.p3.y + this.p2.y ) - ( this.p0.y + this.p1.y ) ) - this.Cy;
this.Ay = this.p3.y - this.p0.y - this.Cy - this.By;
this.Cz = 3f * ( ( this.p0.z + this.p1.z ) - this.p0.z );
this.Bz = 3f * ( ( this.p3.z + this.p2.z ) - ( this.p0.z + this.p1.z ) ) - this.Cz;
this.Az = this.p3.z - this.p0.z - this.Cz - this.Bz;
}
// Check if p0, p1, p2 or p3 have changed
private void CheckConstant()
{
if( this.p0 != this.b0 || this.p1 != this.b1 || this.p2 != this.b2 || this.p3 != this.b3 )
{
this.SetConstant();
this.b0 = this.p0;
this.b1 = this.p1;
this.b2 = this.p2;
this.b3 = this.p3;
}
}
}
这是我的实现脚本(它在场景中的空游戏对象上):
public class arrowPath : MonoBehaviour {
public Transform[] pontos=new Transform[4];
public Bezier bezier;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
bezier=new Bezier(pontos[0].position, pontos[1].position, pontos[2].position, pontos[3].position);
for(float u= 0.0f; u<=1.0f; u+=0.05f)
{
Graphics.DrawMesh(pontos[0].GetComponent<MeshFilter>().sharedMesh, bezier.GetPointAtTime(u), Quaternion.Euler(Vector3.zero), pontos[0].renderer.sharedMaterial, 0);
}
}
}
&#34; pontos&#34; array是Transform数组以保存球体。我通过Unity的检查员填写。
我感谢任何帮助。
感谢。
答案 0 :(得分:2)
看起来非常像GetPointAtTime
旨在生成贝塞尔点。如果是这样的话,你根本就没有评估正确的函数:对于一个三次贝塞尔曲线,函数是:
a ‧ t³ + 3 ‧ b ‧ t² ‧ (1-t) + 3 ‧ c ‧ t ‧ (1-t)² + d ‧ (1-t)³
因此,您的代码不使用二项式,它只是使用t
的直接多项式,它会产生非常错误的东西=)
所以,改变你的功能:
public float ComputeBezierValue( float t, float a, float b, float c, float d )
{
float t2 = t * t,
t3 = t2 * t,
mt = 1 - t,
mt2 = mt * mt,
mt3 = mt2 * mt;
return a * t3 + 3 * b * t2 * mt + 3 * c * t * mt2 + d * mt3;
}
public Vector3 GetPointAtTime( float t )
{
this.CheckConstant();
float x = ComputeBezierValue(t, this.Ax, this.Bx, this.Cx, this.Dx);
float y = ComputeBezierValue(t, this.Ay, this.By, this.Cy, this.Dy);
float z = ComputeBezierValue(t, this.Az, this.Bz, this.Cz, this.Dz);
return new Vector3( x, y, z );
}
另请注意,我已经写过这个以明确使用四个坐标。 Cubic Bezier曲线需要全部四个,Quadratic只使用三个(但通常很差,表示均匀弯曲的段,如圆形/椭圆形段,以及sinoids)