n阶bezier曲线 通用公式说明和应用

今天,孤陋寡闻数学不好的我,才知道n阶bezier 曲线是有一个通用公式的。

我先把这个公式截图放在这里,留作备忘

 

感觉就这么一个公式,说的就比较明确了,用代码实现起来也比较简单。

稍微解释一下:

上面的公式,说的是 2d 场景下, 每个点的插值坐标,是怎么算的。

首先得有一个所有点集合的数组。数组里包括 起点、控制点x N,终点。

比如有 3个控制点, 加上 起点终点,这个 数组长度就是5, 这个bezier 曲线就叫做  4阶贝塞尔曲线。

上面公司描述的是,在 整条曲线区间里 [0,1] ,的 其中某一个时刻, 曲线上的点的位置,是怎么计算得来的。

 

网上找的那些实现的博客,写的烂七八糟,就是不把公式帖明白。代码写的可读性差的可以。找来找去还是就这么2张图片说的最明白。

放在这里备忘

 

补充

 

每次自己想写 的时候 ,看到自己的博客  也晕头转向,都得 重新梳理一遍 .中间用 C++ , C# 甚至是 bolo  各种语言都实现过一次. 这次用 Lua 重新实现的,把代码贴在这里 ,方便自己将来做参考 

 


local Bezier2D = {}
Bezier2D.__index = Bezier2D


local function factorial(n)
    local result = 1
    for i = 1,n do
        result = result * i
    end
    return result
end

local function pow(num,powerNum)
    local r = 1
    for i = 1,powerNum do
        r = r * num
    end
    return r
end

--[[
    ctrlPoints:[{x = ?,y = ?},...]
    [1] is start point
    [n] is end point
]]
function Bezier2D.New(ctrlPoints)
    local o = setmetatable({},Bezier2D)
    assert(#ctrlPoints >= 2)
    o:Init(ctrlPoints)
    return o
end

function Bezier2D:Init(ctrlPoints)
    self.ctrlPoints = ctrlPoints
    self.from = self.ctrlPoints[1]
    self.to = self.ctrlPoints[#self.ctrlPoints]
    self.n = #self.ctrlPoints - 1
end

--[[
    t: [0,1]
]]
function Bezier2D:GetPoint(t)
    local x = self:GetX(t)
    local y = self:GetY(t)
    return {x = x,y = y}
end

function Bezier2D:GetX(t)
    local r = 0
    for i = 0,self.n do
        local kbd = self:GetKBD(i,self.n)
        local pow1minusT = pow(1 - t,self.n - i)
        local powT = pow(t,i)
        local tempPoint = self.ctrlPoints[i + 1]
        local value = kbd * pow1minusT * powT * tempPoint.x   
        r = r + value
    end
    return r
end

function Bezier2D:GetY(t)
    local r = 0
    for i = 0,self.n do
        local kbd = self:GetKBD(i,self.n)
        local pow1minusT = pow(1 - t,self.n - i)
        local powT = pow(t,i)

        local tempPoint = self.ctrlPoints[i + 1]
        local value = kbd * pow1minusT * powT * tempPoint.y
        r = r + value
    end
    return r
end

function Bezier2D:GetKBD(i,n)
    return factorial(n) / (factorial(i) * factorial(n - i))
end

_G.Bezier2D = Bezier2D
_G.factorial = factorial
_G.pow = pow

测试用例:


local points = {
    {x = 0,y = 0},
    {x = 0.5,y = 1},
    {x = 1,y = 0},
}

local bezier = Bezier2D.New(points)

local duration = 1
local function GetObj()
    local charId = 2
    local char = _G.CharacterManagerIns.characters[charId]
    return char.HeroModel.Prefab
end

VeAsync(function() 
    px.warning("done.")
end,function()
    local elapsed = 0
    while elapsed < duration do
        local point = bezier:GetPoint(elapsed / duration)
        local go = GetObj()
        GameObjectSetPosition(go,point.x , point.y, 0)
        
        
        VeSleep(0.02)
        elapsed = elapsed + 0.02
    end
end)

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值