Harmony.codea - a procedural drawing tool

I’m having a lot of fun too. And it’s a pleasure to carry on development in parallel with some one that can give a lot of interesting suggestiona like you!

Sorry is it possible to have access to your latest changes? the links you provide some post ago are freezed to the first version, with the integration of your codea library.

I’ll try your suggestion about vec2. In the meanwhile I’ve made an optimization to my MeshCanvas class (I’ll post on github later): before I was using a single mesh for all the drawings, so after a while performances will fall down because of the large number of rects. So now after each stroke the current draw (done with a mesh) is drawn on an image using setContext and now the only way to kill the performances is to draw too many rects with a single stroke.

Btw, have you already did some tries with ellipse rendering? I’ve, and the results are poor because to have smooth circles a lot of lines are required, and a brush like Discs makes the number of rects of the canvas mesh to increase so fast (that exactly what i meant previously) to became useless at the end. I’m trying to obtain a balance betweeen smoothness and performance but it’s hard, and moreover it’s difficult to make something nice with small circles…

ops, I was writing and I’ve seen your post only after. Thanks for the updated code, I’ll check on it later!

In the meanwhile I’ve made an optimization to my MeshCanvas class (I’ll post on github later): before I was using a single mesh for all the drawings, so after a while performances will fall down because of the large number of rects.

Interesting. What’s the performance gain of this?

Newest update includes the two circular brushes.

With your mesh code, at about 400,000 vertices I was down to 17fps whilst drawing and that went up to 25fps in “idle” mode. With my code, 400,000 brought it down to nearer 11fps and then up to 20fps in “idle” mode. I’m curious to see how much using a canvas image improves on that.

Especially as 400,000 vertices just about covers the screen.

Hi, I’ve uploaded on GitHub the update version with the enhanced version of MeshCanvas (and the consequent changes in brush/brushEx). Well, the gain in performance is maximum because now the solution scales!

First consider that the cost of drawing the extra image is not high. The cost of transfering the content of the ‘current stroke’ mesh to the image used as texture for the first mesh at the end of the stroke instead is pretty high but who really care: it happens in a frame where the user is leaving is finger from the screen!

Let’s consider the benefits instead: using the same mesh for the whole drawing means to have a number of vertex that can increase to infinite… And that’s not just an hypothetic situation, if you try to make a real draw you will see that happening in a while! With my sollution instead the problem can raise only if a single stroke cumulates so many rects to make performance decrease… And that’s something I can achieve pretty easily with a long stroke of my current Discs brush implementation… :frowning:

Anyway I’ve not posted my Discs implementation at now but lookink at your code it seems pretty similar, so I’m curios to see your effective result trying your code on iPad, as soon as I can. I’m just downloading bazar now (that I have never used before…)

Btw I’ve seen you manually resize the mesh and then manually set vertices. I’ve seen that manual vertex access is pretty slow compared to the add/set Rect methods. I still think it would be great having add / set methods for generic quads…

Well, it happened again, I was writing and I haven’t seen your post. Anyway, if you want to give it a try now the code is updated. Just one thing: you said that 400000 vertices cover the screen… well, not true. Consider a real case, when you draw, than you make a mistake and you use the simple brush with white color to erase, then you make a new small correction and so on. it’s not so hard to reach that number in a session of real drawing, I can assure you!

Wow, it was easy to download your libs with bazar! I really get nervous each time I have to understand how to use a new version system…

Btw I’ve tried your Discs implementation and has a strange behaviour, it’s different from the original version but I don’t understand exactly why.

I’ve uploaded also my version on github and, at the end, is pretty similar to yours.

And at the end is sad to admit that the original version with the circles drawn by shaders is so much better that this solution feels nothing more that an exercise, that was fun but that results not so good at all :frowning:

Sadly, smooth seems to have no effect on meshes.

An alternative would be to save a few circles (at different sizes so that the blurring doesn’t get overwhelming) to sprites and render them to rectangles on the mesh.

Yes, it could be a solution but it would starts to became a little too tricky for my tastes… Having a pool of circles requires to handle different thickness and radius, having something like one atlas per thickness range, where each atlas would be composed by different circles with different radius… I fear that creating them on the fly instead would be performance killer, but maybe not. But maybe you had somthing simpler in mind.

No, I just hadn’t thought of all the possible variations.

Okay, try my latest update!

But I need to steal your save-to-canvas code as this increases the number of vertices … rather a lot.

Ahah, nice solution! Now I’m going out, but at my return If I have time I want to try it myself on my MeshCanvas class. Maybe adding smooth logic directly on the line implementation, and maybe also as a rendering option (like with the codea smooth / noSmooth api calls)

Yes, now that I’ve seen the effect on circles I want it on lines as well … but my iPad has been appropriated.

I like the smooth\ oSmooth idea. Shouldn’t be hard to implement.

Smooth and noSmooth implemented for lines with a switch in the menu. Code’s a bit of a mess, though.

Also, I need to figure out the relationship between the apparent line thickness and given line thickness when smoothing is on.

Well, I have to say that your line implementation is really a nice and clever one. I repeat again that having to manually set each vertex is not the best, it would be nice to have api to handle generic quad. The resize and vertext by vertex access is in fact pretty slow. I think that dividing the thickness by 2 is a bit too much because smoothed lines are too much thick now.

I finally had some more time to work on the project and I’ve followed your suggestion, so all the brushes and line calculation are now made directly upon vec2.
I’ve also added to my MeshCanvas a different smooth line implementation I worked on that is not so nice as yours (I mean not only as implementation but also as appeareance), but it’s faster and requires less resources. Each segment is in fact a blend of 3 rects that I can manage with addRect api call. The result is still far better than with a single rect, and not so bad in general even if the edges of the line are not so clean like in your solution.

I’ve also added your implementation to MeshCanvas (I hope that’s fine for you) and it’s possible to switch between the 2 implementation switching a parameter value.

The circle implementation still rely on line call so lot slower than could really be.

If you like to have some comparison, take care that I’ve put a modifier of 1.8 of the thickness while drawing with your algorithm: that seems to balance the thickness reduction you apply inside the alg.

I think that both the solution fail when the color of the brush is not opaque. With alpha values of ~100 in fact bad artifacts are generated at the connection of consequent segments, due to overlapping areas.

@shrike what APIs would you like to see added to mesh?

Hi @Simeon, I think that having also a more generic addQuad/setQuad accepting 4 vec2 or vec3 would be great.

In the most of the situation the addRect/setRect works fine, but there are situations (like in @Andrew_Stacey smooth line implementation) where what is needed is a generic quad.

Moreover sometimes it would be good to use similar api also for add/set a rect because the 4 vertex coords are already known, and the add/setRect require instead to calculate center and angle.

Mesh allows to handle generic quads resizing and then manually setting the vertex, but it’s more verbose, it requires 7 operations and is far slower (I mean if compared with the add/setRect). I think that add/setQuad could be also mixed whitout problem wih the add/setRect just using the id returned by the add method that, at the end, represents 6 vertex.

Path with alpha

or link: http://pic.twitter.com/GizQYraq

The above shows two paths with thick enough line width to show the effect of the newest code (will publish tomorrow). The lower path is black with an alpha of about 127. Note the distinct lack of artefacts and the continuity of the path. I have to say that I’m very pleased with the implementation.

I’m curious to see the code. iIsuppose that you have moved from an implementaton where each segment is handled by itself to one where is the whole line the pbject of the alg., adjusting ending vertex of the previous segment depending on the change of direction of the new one.