Lua版
local Bezier = {}
--【无限阶贝塞尔曲线】
--@params t 整条线上对应的百分比位置{0-1}
--@params node 起点,控制点1,控制点2,控制点3......,结束点
--@return ret 返回对应的点/值
function Bezier.BezierCurve(t, node)
local vecs = node
local count = #vecs
local rank = count - 1
local ret = Vector3.zero
local pts = Bezier.GetPascalTriangle(count)
local fs = {}
for i = 1,count do
local f = Bezier.GetFormula(vecs[i],rank,i,pts[i],t)
table.insert(fs,f)
end
for i = 1,#fs do
ret = ret + fs[i].Caclu()
end
return ret
end
-------------------------Private---------------------------------
function Bezier.Exponentiation(num,power)
local n = 1
if power == 0 then return n end
for i = 1,power do
n = n * num
end
return n
end
function Bezier.GetFormula(point,rank,index,ptValue,t)
local ret = {}
ret.point = point
ret.rank = rank
ret.index = index - 1
ret.ptValue = ptValue
ret.t = t
ret.Caclu = function()
local t1 = Bezier.Exponentiation((1 - ret.t),(ret.rank - ret.index))
local t2 = Bezier.Exponentiation(ret.t,ret.index)
return ret.point * t1 * t2 * ret.ptValue
end
return ret
end
function Bezier.GetPascalTriangle(n)
local ret = {}
local t = {}
for i = 1,n do
t[i] = {}
for j = 1,i do
if j == 1 or j == i then
t[i][j] = 1
else
t[i][j] = t[i - 1][j - 1] + t[i - 1][j]
end
end
end
for i = 1,n do
table.insert(ret,t[n][i])
end
t = nil
return ret
end
------------------------测试函数------------------------
function Bezier.TEST()
local go = GameObject()
go.name = "测试点"
go.transform.position = Vector3.zero
local go1 = GameObject()
go1.name = "测试点1"
go1.transform.position = Vector3(-17.4,0,0)
go1.transform:SetParent(go.transform)
local go2 = GameObject()
go2.name = "测试点2"
go2.transform.position = Vector3(-9.52,0,-3.84)
go2.transform:SetParent(go.transform)
local go3 = GameObject()
go3.name = "测试点3"
go3.transform.position = Vector3(-2.88,0,5.94)
go3.transform:SetParent(go.transform)
local go4 = GameObject()
go4.name = "测试点4"
go4.transform.position = Vector3(1.7,0,0)
go4.transform:SetParent(go.transform)
local go5 = GameObject()
go5.name = "测试点5"
go5.transform.position = Vector3(9.95,0,-4.91)
go5.transform:SetParent(go.transform)
local go6 = GameObject()
go6.name = "测试点6"
go6.transform.position = Vector3(15.38,0,5.46)
go6.transform:SetParent(go.transform)
local lineCount = 20
go:AddComponent(typeof(UnityEngine.LineRenderer))
local lr = go:GetComponent("LineRenderer")
lr.positionCount = lineCount + 1
for i = 0,lineCount do
lr:SetPosition(i,Bezier.BezierCurve(i / lineCount,go1.transform.position,
go2.transform.position,
go3.transform.position,
go4.transform.position,
go5.transform.position,
go6.transform.position))
end
end
return Bezier
C#版
//N阶贝塞尔
public class Bezier
{
public static Vector3 BezierCurve(float t, List<Vector3> vecs)
{
int count = vecs.Count;
int rank = count - 1;
Vector3 ret = Vector3.zero;
List<int> pts = CacluPascalTriangle(count);
List<Formula> fs = new List<Formula>();
for (int i = 0; i < count; i++)
{
Formula f = new Formula(vecs[i], rank, i, pts[i], t);
fs.Add(f);
}
for (int i = 0; i < fs.Count; i++)
{
ret += fs[i].Caclu();
}
return ret;
}
public static Vector3 BezierCurve(float t, params Vector3[] vecs)
{
int count = vecs.Length;
int rank = count - 1;
Vector3 ret = Vector3.zero;
List<int> pts = CacluPascalTriangle(count);
List<Formula> fs = new List<Formula>();
for (int i = 0; i < count; i++)
{
Formula f = new Formula(vecs[i], rank, i, pts[i], t);
fs.Add(f);
}
for (int i = 0; i < fs.Count; i++)
{
ret += fs[i].Caclu();
}
return ret;
}
public static List<int> CacluPascalTriangle(int n)
{
List<int> ret = new List<int>();
int[,] array = new int[n, n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j <= i; j++)
{
if (j == 0 || i == j)
{
array[i, j] = 1;
}
else
{
array[i, j] = array[i - 1, j - 1] + array[i - 1, j];
}
}
}
for (int i = 0; i < n; i++)
{
ret.Add(array[n - 1, i]);
}
return ret;
}
public class Formula
{
//点
public Vector3 point;
//阶层
public int rank;
//索引
public int index;
//杨辉三角
public int PTValue;
public float t;
public Formula(Vector3 point, int rank, int index, int pTValue, float t)
{
this.point = point;
this.rank = rank;
this.index = index;
this.PTValue = pTValue;
this.t = t;
}
public float Exponentiation(float num, int power)
{
float n = 1;
if (power == 0)
{
return n;
}
for (int i = 0; i < power; i++)
{
n *= num;
}
return n;
}
public Vector3 Caclu()
{
Vector3 P = Vector3.zero;
float t1 = Exponentiation((1 - t), (rank - index));
float t2 = Exponentiation(t, index);
P = PTValue * point * t1 * t2;
return P;
}
}
}