Skip to content

Instantly share code, notes, and snippets.

@alex-golovanov
Last active April 23, 2023 20:13
Show Gist options
  • Save alex-golovanov/1383576 to your computer and use it in GitHub Desktop.
Save alex-golovanov/1383576 to your computer and use it in GitHub Desktop.
Curve Fitting - Catmull-Rom spline
function smooth( points, steps )
if #points < 3 then
return points
end
local steps = steps or 5
local spline = {}
local count = #points - 1
local p0, p1, p2, p3, x, y
for i = 1, count do
if i == 1 then
p0, p1, p2, p3 = points[i], points[i], points[i + 1], points[i + 2]
elseif i == count then
p0, p1, p2, p3 = points[#points - 2], points[#points - 1], points[#points], points[#points]
else
p0, p1, p2, p3 = points[i - 1], points[i], points[i + 1], points[i + 2]
end
for t = 0, 1, 1 / steps do
x = 0.5 * ( ( 2 * p1.x ) + ( p2.x - p0.x ) * t + ( 2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x ) * t * t + ( 3 * p1.x - p0.x - 3 * p2.x + p3.x ) * t * t * t )
y = 0.5 * ( ( 2 * p1.y ) + ( p2.y - p0.y ) * t + ( 2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y ) * t * t + ( 3 * p1.y - p0.y - 3 * p2.y + p3.y ) * t * t * t )
--prevent duplicate entries
if not(#spline > 0 and spline[#spline].x == x and spline[#spline].y == y) then
table.insert( spline , { x = x , y = y } )
end
end
end
return spline
end
function draw( points )
for i = 1, #points do
local point = points[i]
display.newCircle(point.x, point.y, 2)
end
end
local points = { {x = 100, y = 100}, {x = 100, y = 200}, {x = 200, y = 200}, {x = 200, y = 300} }
--draw(points)
local spline = smooth( points )
draw(spline)
@piller187
Copy link

So could this be used for an arc of throwing a grenade in a video game for example? If the known points are the start, end, and mid? If so, do you think you'd be able to translate this to 3D with x,y,z instead of just x & y?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment