Ellipses vs Meshes Part 2

Hello all.

I’m sorry to come back with this question, but there is something I don’t catch with the supposed speed performance of Meshes vs “natives” shapes of codea. I asked the question yesterday and it has been kindly answered by JMV38, to sum up, that Meshes were much faster to draw than natives Ellipses. Ok, then I decided it check it with an old little file using some Ellipses. The code below, which has been done very quickly, just serves to calculate and show the smaller distance between a point and a segment line. The first version was Ellipses alone, and with a framerate class I pick up from here (thanks to Mpilgrem the owner of the code by the way…) I was able to estimate FPS. With Ellipses → 60 FPS. OK. Then I replace all Ellipses with Meshes using an Arc method that does the job and that is mesh based. You can check, but with this new version FPS just drop to about 15 FPS or less… So you see what I mean ? How it is that the meshes version is far slower that the “native” Ellipses one. Of course, I know there is something wrong I did not catch. I m sure that meshes are much more efficient, but please help me to understand what happens with this try. To change between Ellipses or Meshes versions in the code, you just have to comment the non-desired part and to release the other part as indicated. Thanks.
(sorry, I don’t know how to add code… I just copy and paste it)

--distance cercle segment
--Use this function to perform your initial setup

function setup()

    myFPSReporter = FPSReporter(4)
    parameter.integer("x 1er point", 0, WIDTH, 100)
    parameter.integer("y 1er point", 0, HEIGHT, 100)
    parameter.integer("x point", 0, WIDTH,WIDTH/2)
    parameter.integer("y point", 0, HEIGHT,HEIGHT/2)
    parameter.integer("position", 1, 4, 1)

end

--This function gets called once every frame
function draw()
    
    if CurrentTouch.x == 0 and CurrentTouch.y == 0 then 
        x_2eme_point, y_2eme_point = 250, 320
    else
        x_2eme_point, y_2eme_point = CurrentTouch.x,
        CurrentTouch.y
    end
    
    local p1 = vec2(x_1er_point, y_1er_point)
    local p2 = vec2(x_2eme_point, y_2eme_point)
    local pA = vec2(x_point, y_point)

    --This sets a dark background color 
    strokeWidth(5)
    background(40, 40, 50)
    fill(255)
    
    pushStyle()
    stroke(170, 186, 110, 255)
    line(x_1er_point, y_1er_point, x_2eme_point, y_2eme_point)
    noFill()
    stroke(255, 0, 29, 255)

    --ellipse (x_point, y_point, 15) --here you can change between Ellipses and Meshes 
    arc (x_point, y_point, 7) --here you can change between Ellipses and Meshes 
    if p2:dist(pA) <= 100 then stroke(255, 255, 255, 255) else stroke(255, 144, 0, 255) end
    --ellipse (x_point, y_point, 200) --here you can change between Ellipses and Meshes 
    arc (x_point, y_point, 100) --here you can change between Ellipses and Meshes
    popStyle()
    
    --ellipse (x_1er_point, y_1er_point, 10) --here you can change between Ellipses and Meshes 
    arc (x_1er_point, y_1er_point, 5) --here you can change between Ellipses and Meshes 
    --ellipse (x_2eme_point, y_2eme_point, 10) --here you can change between Ellipses and Meshes 
    arc (x_2eme_point, y_2eme_point, 5) --here you can change between Ellipses and Meshes 
    
    minimum_distance(p1,p2,pA)
    
    myFPSReporter:draw(position)

end

function minimum_distance (v, w, p)

    local l2 = v:distSqr(w)
    if l2 == 0 then 
    return v:dist(w) 
    end
    local t = (p - v):dot(w - v) / l2
    if t < 0 then 
        if p:dist(v) <= 100 then
            line (p.x,p.y,v.x,v.y)
        end
        return p:dist(v) 
    elseif t >1 then 
        if p:dist(w) <= 100 then
            line (p.x,p.y,w.x,w.y)
        end
        return p:dist(w)
    else
        local projection = v + t * (w - v)
        if projection:dist(p) <= 100 then
            line (p.x,p.y,projection.x,projection.y)
        end
        return p:dist(projection)
    end

end

function arc(x, y, radius, a1, a2) --the famous arc function...

    local m = mesh()
    m:addRect(x, y, radius * 2, radius * 2)
    m.shader = shader("Patterns:Arc")
    m.shader.size = (1 - strokeWidth()/radius) * 0.5
    m.shader.color = color(stroke())
    --m.shader.a1 = math.rad(a1)
    --m.shader.a2 = math.rad(a2)
    m:draw()

end

FPSReporter = class() --class for FPS

function FPSReporter:init(rate)

    self.spacing = 1/rate
    self.last = ElapsedTime
    self.count = 0
    self.rate = 60

end

function FPSReporter:draw(pos)

    self.count = self.count + 1
    local now = ElapsedTime
    local delta = now - self.last
    if delta >= self.spacing then
        self.rate = self.count/delta
        self.count = 0
        self.last = now
    end
    pushStyle()
    local s = string.format("%d", self.rate)
    local w, h = textSize(s)
    textMode(CENTER)
    fontSize(18)
    font("Inconsolata")
    fill(255)
    pos = pos - 1
    local x = math.floor(pos/2) % 2 * (WIDTH - w) + w/2
    local y = pos % 2 * (HEIGHT - h) + h/2
    text(s, x, y)  
    popStyle()

end

Please use proper code formatting… Three ~ at only the very top and the very bottom of your code, not at the top and bottom of functions.

Sorry, the three ~ (~ ~ ~) does not seem to repare anything… What should I exactly do ? I did not add anything to my code. It’s just exactly like in codea.

No, it’s… Remove all of the ~ from your code. Once you’ve done that, place the three ~ at the top and bottom of your code again, but without spaces in between. Like… ~~~

Ok. Done. Thanks for the tips. Now if somebody can help with the code itself, it would be nice :slight_smile:

@Lostania your issue is that you are creating a mesh on every frame in the draw function using the arc function. Use this from the setup function and it should be alot faster :slight_smile:

function setup()
myarc = arc()
end

function draw()
myarc:draw()
end

edit: Also don’t call mesh:draw() in the arc function :slight_smile:

Ok, thanks, I ll try this. On the contrary, I suppose it’s normal to put the Ellipse code inside the Draw() function, is not it ?
By the way, after some try, I do have a question : if I have to set the mesh (arc) in the setup, how can I interact with ? (Change, size, radius and so on…)

The arc shader is not one of the speediest shaders in town. There are faster ways to draw an arc or an ellipse using a mesh and I suspect that these are what the respondents in the other thread meant. One way is to make a one-time image of an ellipse and use that as the texture of a rectangular mesh. This is probably the fastest, but the line width of the ellipse will vary depending on its size. Another way is to build an actual elliptical mesh - this is what I would choose as the “hole” in the middle is then a genuine hole and you don’t get any funny transparency effects (this matters more in 3D than in 2D).

It is normal to use the ellipse function in the draw function, in fact this is the only place you can use it (or any function called by draw). Meshes should be setup else where and just drawn and potentially passed some values in the draw function.

Edit: Almost forgot you can also use the ellipse function when you are drawing too an image (with setcontext), and in this case it’s an exception and it doesn’t need be called by draw :slight_smile: