shared my project on Codea Community

I posted my little bezier curve project on CC in hopes that someone could check it out and help me figure out ways to better implement what’s happening in it now.

some things that I am having trouble finding solutions for are:

1) when you drag a controlPoint around, it gets really slow if the line gets long.  
2) when you click on a point and drag it around, if you drag too fast, it stops tracking your finger.
3) the touch detection algorithm for everything on the screen.   take a look in BezierLine:touched() for starters
4) the state machine 'order of interaction' for how best to set up the user interaction.  i.e. how can you interact with the line to edit it, given the choices offered in the TouchEvent tab

the interactions available are:

it’s a work in progress, but it kinda works for starters. I’m not sure what my end goal is for this project, but right now I’m just trying to learn to problem solve better, and i’ve created the problem of “create bezier curves by tapping/long-pressing an existing curve to edit/add/remove control points”

@matkatmusic I loaded your code. There’s a lot of it, and while I continue to look at it, here’s a brezier program that I have. Maybe you can look it over and see if anything here can help you in the mean time.


displayMode(FULLSCREEN)

function setup()
    x={200,600,200,600}
    y={200,300,600,400}
    tp=0
    bezier(.001)
end

function draw()
    background(40,40,50)
    fill(255)
    strokeWidth(4)
    for z=2,#tab do
        line(tab[z-1].x,tab[z-1].y,tab[z].x,tab[z].y)
    end
    for z=1,#x do
        ellipse(x[z],y[z],10)
    end
end 

function touched(t)
    if t.state==BEGAN then
        v1=vec2(t.x,t.y)
        for z=1,4 do
            if v1:dist(vec2(x[z],y[z]))<40 then
                tp=z
            end
        end
    end
    if t.state==MOVING and tp>0 then
        x[tp]=t.x
        y[tp]=t.y
        bezier(.001)
    end
    if t.state==ENDED then
        tp=0
    end 
end

function bezier(val) 
    tab={}
    for t=0,1,val do
        px=(1-t)^3*x[1]+3*t*(1-t)^2*x[2]+3*t^2*(1-t)*x[3]+t^3*x[4]
        py=(1-t)^3*y[1]+3*t*(1-t)^2*y[2]+3*t^2*(1-t)*y[3]+t^3*y[4]            
        table.insert(tab,vec2(px,py))
    end
end

thanks, @dave1707. I see your code has the same slowdown issues that mine has when dragging the points around.

I checked out @loopspace’s project that’s up on Codea Community as well, just to see what someone else did for bezier curves. It seems like he used Shaders to render the curve.

in my project, I used a recursion method to render curves like this:

http://en.m.wikipedia.org/wiki/File:Bézier_4_big.gif

I’d like to develop a method for drawing and interacting with curves similar to the ones in this video: http://youtu.be/GYTCQeggyzo

@matkatmusic I like the animation on the page you sent me to. On my iPad Air, there doesn’t seem to be any slowdown at all no matter how fast I move the points.

I’m on an ipad 3, i believe you have a faster chip than my device.

@meerkatmusic - your frames per second are about 5, on my iPad3. No wonder it lags.

Just using @dave1707’s code, I found it could make it run much faster (40FPS+) by changing the bezier step from 0.001 to 0.01, with no noticeable change in the display.

PS There are other speedups you could try, like precalculating all the coefficients (because they don’t change as you drag the points around) and getting rid of all the power functions, which are slow, but I did try all that and it didn’t make much difference in this case.

@ignatz how did you determine those FPS? also, did you check out my project on CC?

@meerkatmusic - DeltaTime gives you the time interval since the last draw, but it is erratic, so you need to average it somehow.

I use a simple FPS measure (developed by Jmv38)

--in setup
FPS=60
--in draw
FPS = 0.9*FPS + 0.1 / DeltaTime

Some people prefer to use a running average of the last 10 intervals, but I’m happy with the one above.

@ignatz it’s “matkatmusic” not “meerkatmusic” lol

that’s good to know about determining FPS. I’ll look for ways to speed up the FPS in my project.

Please do not use that measure of FPS! It is not a good one. I’d like to expunge it from these discussions.

Back to Beziers, yes mine uses a shader. I’ve never noticed it producing a slow-down when I use it in a program so I think it’s pretty fast.

@LoopSpace could you give a little explanation of how your shader works to draw/calc the Bézier curve?

@Loopspace it is a good one indeed. ‘Good’ here means easy and accurate enough to do what one wants (ie putting a figure on a visual impression). To my understanding, you dont like it because it is not perfectly accurate in the sense of some purely mathematical definition of FPS, but i dont think this is what we are looking for here. It is good in the sense that we all try to measure FPS for. Unless you can prove me wrong?

@Jmv38, @LoopSpace - I think that measure of FPS is good enough for what we do, and simpler than a moving average. (Unless someone can prove otherwise using a real example, of course).

It’s been explained elsewhere why it’s not a good measure and I’m not going to rehash that here.

Rather, the onus is on you to explain what, exactly, does it measure? I strongly suspect that you can’t answer that precisely and that is why it should not be used. It may be correlated with FPS, but correlation does not mean it is good.

Back to the subject, @matmakmusic, the shader works by defining a mesh built from lots of rectangles. These are then deformed to lie along the bézier curve using a vertex shader to move the vertices of the mesh. All the rest of the code is about styling.

Here’s a graph of the average frames per second. The actual average is in green and the calculated in red. Change the number of sprites drawn in the “for” loop to vary the frames per second. As for “what does it measure”, it gives a person an idea of how fast the draw routine is drawing what’s on it. Since a person can’t look at the screen an see how fast the draw routine is running, a calculation gives a reasonable value that allows a person to alter their code to change how fast the draw function is executing.


--# Main

displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    tot=0
    count=0
    FPS=60
    backingMode(RETAINED)
end

function draw()
    tot=tot+1/DeltaTime
    count=count+1
    
    for z=1,400 do
        sprite("Planet Cute:Character Boy",z/5,100)
    end

    fill(255)
    rect(200,140,200,100)
    
    fill(0,255,0)
    text(tot/count,300,200)  
    ellipse(count,300+(tot/count)*5,4)
    
    fill(255,0,0)  
    FPS = 0.9*FPS + 0.1 / DeltaTime
    text(FPS,300,160)
    ellipse(count,300+FPS*5,4)
end

@Jmv38, @LoopSpace - here is an FPS simulation comparing Jmv’s “geometric” method, and the “averaging” method.

https://www.youtube.com/watch?v=BPT9Ek2BPtY

Video link is here if you can’t see it above.

and the code: https://gist.github.com/dermotbalson/d9b4e35c7d6167b4980c

It simulates two types of variations in FPS - big changes every now and then, or continual variation. It shows that there is very little difference between the two methods, especially if you alter the geometric weighting to 0.2 (ie FPS = 0.8FPS + 0.2latestFPS) - see second half of the video for this.

This doesn’t mean the weighting of 0.1 we have been using is wrong, it simply means that 0.2 matches up better to an average of 10 points. And there is nothing to say 10 points should be used rather than 5 or 20.

So I think Jmv’s method gives equivalent results, and it is simpler and more compact. That’s why I use it.

@Loopspace actually i precisely understand what it measures, this is why i know it is good enough for what we want. We want something that :

  • gives a good idea of the current instantaneous fps when not constant
  • but with some smoothing behavior otherwise we cannot read it easily,
  • and that gives the same value as an average when fps is constant.
    This averaging method uses wheight decreasing exponentially from the current frame ( 0.1 ) to frame -n ( 0.1 x 0.9^n ). So recent frames have weights close to 0.1 and the weights of older frames are rapidely (exponentially) decreasing to zero.
    As Ignatz has found it is roughtly equivalent to an average of 2/k in terms of desnoising factor when k tends to 0 (here k=0.1) if you compute the resulting standard deviation on a gaussian variable.
    But we dont need people to know all these maths, and Dave1707 and Ignatz made an very nice job at showing the point in a pragmatic way.
    So please dont try to ‘expunge it from these discussions’, you would deprive people from a good and simple tool.

What’s wrong with:

in setup:

afps = {}
totalTime=0
for k=1,10 do
    table.insert(afps,1/60)
    totalTime = totalTime + 1/60
end

in draw:

totalTime = totalTime - table.remove(afps,1) + DeltaTime
table.insert(afps,DeltaTime)
fps = 10/totalTime

At least with this it’s really obvious what it is measuring, and how to change it to extend or narrow the averaging window.

I’m all for rough-and-ready when doing it “properly” is far, far more complicated. But doing it properly with fps is not complicated, so why not do it? Otherwise it’s a mysterious formula that is actually more complicated (in terms of comprehensibility) than the accurate formula.

No one says what you are doing is wrong (except it takes slightly more cpu) nor wants to ‘expunge’ you or anyone from doing it. From your side, maybe you could consider our alternative method as an interesting (and elegant) way to get the desired result, and try to understand it first, before putting it down because you don’t.

It’s six lines where two will do fine :wink: