Sounds like it could be pretty good, and probably more unique than the Bézier classes going about at the moment as the speed is just not comparable with others, aswell as the colours and such. This is a reason I should start shaders
Yes indeed - yet to touch shaders as yet and would be really interested in a shader oriented Bezier class/library as well - really interested in the general performance speedup!
I’ll continue with my non-shader version for my game, as its less to do with raw display performance - more a convenient/simple/fast method of specifying paths for sprites and other useful functions (e.g. closest point to curve etc…).
I use the same approach as @Andrew_Stacey and pretty much pre-process all the calculations prior to drawing unless something gets changed. I guess the beauty of a piece-wise approximating (i.e. multiple Quadratic curves with C0/C1 continuity joining them together) is that you dont necessarily have to recompute all the curves just the current ‘span’ local to where the points have changed. Im sure there are lots of other speed ups like this to help pre-processing the curve prior to draw should interactive performance be an issue.
Quick question: Would either of you (@Luatee and @andymac3d) have a use for a function that computed a sequences of béziers through a given set of points, so that the resulting curve looked smooth? That is, you specify a set of points and there’s an algorithm that computes a set of Béziers, one between each successive pair of points, which match up well.
Absolutely @Andrew_Stacey . This sort of ‘inverse’ computation of control-points that fit a set of ‘knots’ that lie on a curve is really useful and far more intuitive than specifying a bunch of CP’s that influence the curve directly. Happy days
This would definitely be of use I could see a overhaul of controls in this game with the use of that
Uhm, I would like to use it in a game
I stopped working on it but here’s the code, shouldn’t be too hard to integrate its in classes for the most part.
--# Spline
Spline = class()
function Spline:init(v)
-- you can accept and set parameters here
self.v = v
self.p = vec2()
self.msh = mesh()
self.msh.texture = txture2
self.rct = self.msh:addRect(0,0,35,35)
self.msh:setColors(180,0,0,150)
self.holding = {}
self.moving = nil
self.verts = {}
self.newv = {}
self.n = 30
local n = self.n
local t = 0
for i = 1,n do
self.verts[i] = (1-t)^3 * v[1] + 3*(1-t)^2 *t * v[2] + 3*(1-t)* t^2 *v[3] + t^3*v[4]
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v)
self.points = Points(self.v,200)
self.p = vec2()
for i = 1,#self.v do
self.p = self.p + self.v[i]
end
self.p = self.p/4
self.msh:setRect(self.rct,self.p.x,self.p.y,30,30)
end
function Spline:draw()
self.lines:draw()
if ball == nil then
self.vlines:draw()
self.points:draw()
self.msh:draw()
end
end
function Spline:closestPoint()
return self.cp
end
function Spline:drawPoints()
end
function Spline:pos()
return self.p
end
function Spline:createFloor()
local verts = {}
local t = 0
local n = 60
local v = self.v
for i = 1,n do
verts[i] = (1-t)^3 * v[1] + 3*(1-t)^2 *t * v[2] + 3*(1-t)* t^2 *v[3] + t^3*v[4]
t=t+1/(n-1)
end
self.spline = physics.body(CHAIN,false,unpack(verts))
self.spline.type = STATIC
self.spline.friction = 0.2
end
function Spline:destroy()
if self.spline ~= nil then
self.spline:destroy()
self.spline = nil
end
end
function Spline:touched(t)
self.p = vec2()
for i = 1,#self.v do
self.p = self.p + self.v[i]
end
self.p = self.p/4
self.msh:setRect(self.rct,self.p.x,self.p.y,30,30)
if t.state == BEGAN then
for i=1,#self.v do
local pos = self.v[i]+scr
if vec2(t.x,t.y):dist(pos) < 25 then
self.holding[i] = true
end
end
if vec2(t.x,t.y):dist(self.p+scr) < 25 then
self.moving = 1
for i=1,#self.v do
self.newv[i] = (self.v[i]-self.p)
end
end
for i=1,#self.v do
if self.v[i]:dist(self.p) < 20 then
self.v[i] = self.v[i] + (self.v[i]-self.p):normalize()*20
self.v[i].x = math.ceil(self.v[i].x)
self.v[i].y = math.ceil(self.v[i].y)
local t = 0
local n = self.n
local v = self.v
for i = 1,n do
self.verts[i] = (1-t)^3 * v[1] + 3*(1-t)^2 *t * v[2] + 3*(1-t)* t^2 *v[3] + t^3*v[4]
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v,200)
self.points:setpoints(i,self.v)
end
end
elseif t.state == MOVING and self.moving == 1 then
tp = vec2(t.x,t.y)
for i=1,#self.v do
self.v[i] = tp + self.newv[i]-scr
self.v[i].x = math.ceil(self.v[i].x)
self.v[i].y = math.ceil(self.v[i].y)
end
local t = 0
local n = self.n
local v = self.v
for i = 1,n do
self.verts[i] = (1-t)^3 * v[1] + 3*(1-t)^2 *t * v[2] + 3*(1-t)* t^2 *v[3] + t^3*v[4]
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v,200)
self.points:setpoint(self.v)
self.p = (self.v[1]+self.v[2]+self.v[3]+self.v[4])/4
self.msh:setRect(self.rct,self.p.x,self.p.y,30,30)
elseif t.state == ENDED and self.moving == 1 then
self.moving = nil
end
for i=1,#self.v do
local pos = self.v[i]
if t.state == MOVING and self.holding[i] then
touches[2] = t
tp = vec2(t.x,t.y)
self.v[i] = tp-scr
self.v[i].x = math.ceil(self.v[i].x)
self.v[i].y = math.ceil(self.v[i].y)
local t = 0
local n = self.n
local v = self.v
for d = 1,n do
self.verts[d] = (1-t)^3 * (v[1]) + 3*(1-t)^2 *t * (v[2]) + 3*(1-t)* t^2 *(v[3])+ t^3*(v[4])
t=t+1/(n-1)
end
self.lines = Lines(self.verts,50)
self.vlines = Lines(self.v,200)
self.points:setpoints(i,self.v)
elseif t.state == ENDED and self.holding[i] then
self.v[i].x = math.ceil(self.v[i].x)
self.v[i].y = math.ceil(self.v[i].y)
self.holding[i] = nil
end
end
end
--# Lines
Lines = class()
function Lines:init(v,col)
self.m = mesh()
self.r = {}
local c = col or 255
for i=2,#v do
self.p = (v[i]+v[i-1])
self.p2 = (v[i]-v[i-1])
self.dir = self.p2:normalize()
self.len = self.p2:len()
self.p = self.p/2
self.r[i] = self.m:addRect(self.p.x,self.p.y,self.len,3,angleOfPoint(self.dir)/57.3)
self.m:setColors(c,c,c,255)
end
end
function Lines:draw()
self.m:draw()
end
function Lines:touched(touch)
-- Codea does not automatically call this method
end
--# Points
Points = class()
function Points:init(v,col)
self.m = mesh()
self.r = {}
local c = col or 255
for i=1,#v do
self.p = v[i]
self.r[i] = self.m:addRect(self.p.x,self.p.y,13,13,0)
self.m.texture = txture
self.m:setColors(c,c,c,150)
end
end
function Points:setpoint(v)
for i=1,#v do
self.m:setRect(self.r[i],v[i].x,v[i].y,13,13,0)
end
end
function Points:setpoints(i,v)
self.m:setRect(self.r[i],v[i].x,v[i].y,13,13,0)
end
function Points:draw()
self.m:draw()
end
function Points:touched(touch)
-- Codea does not automatically call this method
end
There are a few missing textures which won’t be hard to make, it’s simple graphics. If you need help to use the class then send me a message
Hey, i have noticed that you have changed the Point:init function with different initializator params type, those were numeric and now tables…? I would like to see the Main , you can submit to gist
It’s to set points individually and as a whole, I don’t have a GitHub account, ill put it on paste bin in the morning
Ok ty