Splinerider

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. :slight_smile:

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 :smiley:

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 :slight_smile:

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 :slight_smile:

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 :slight_smile: ty