Bite-size updates

Heyo. I'll be posting some quick updates here. Not everything deserves a blog post.

Currently I'm working on vector rendering and tools.

I went through making a buggy triangulation renderer, then made a scanline rasterizer (which was way too slow), then the trapezoidal rasterizer which looked reazonable


Problem with the trapezoidal r. is that it generates way too many triangles. I'm experimenting with subdividing comlex polys into simple polys, and then rendering them with triangles. (This is way more complex algorithmically than trapezoids, but will in theory produce so much less triangles, that will justify the complexity)

Also, I did some work on offset curves.
Here's i think about 60-80 offset curves



see video (2MB mp4)

Right now I took a break from vectors, and decided to tackle object tree (like the layers in photoshop).
Also, I'm working on undo/redo stuff - which requires a robust serializer. Just yesterday I made a thing that does the serialization of shapes lik this:

1
2
u32 Size;
u8 *Serialized = lsmeta_serialize(tree_node, Nodes, &Size);


I just pass the type, pointer to the root node and get back the data+size. It's pretty cool.
It uses internal buffers, so no pre-allocation of space is needed by the caller.
I still have to make the reverse process. Going to work on that in the next couple days.

I'll be posting more of these shorter updates here.

Follow me on twitter for more pictures twitter.com/stas_lisetsky.
And feel free to leave comments. Thanks!



Edited by Stas Lisetsky on
July was a bit boring for Cascade. I dont even have screenshots.
But, I have 2 big 'gains', so to speak.


First, the serializer. It's really getting there. It's a very small 2k loc library that a)generates metadata for specified files and b) does serialization and deserializanion.

In mice. Ehm, I mean on a very small subset of C++.
But it's more than enough. It supports linked lists, static arrays, dynamic arrays (including specifying member variables that store the counts or the 'Next' pointers). Very convenient. And just in time for me to finally start working on history. Most of history stuff, I believe, won't require complex serialization - it's going to be just a memcopy of a single struct. But in case of tree hierarchy changes (eg for storing removed branches of objects) the serializer is very very useful.

Another use I found for the metadata I now have - is to use the actual types as tagged union tags. No extra info or enums are needed for each union, because I just have all the type info.


Second big thing is the object storage.

It's not unreasonable to assume that large projects could have thousands, maybe tens of thousands of objects.
Let's say 100K to be sure. That's at least 300K of control points - if all objects are triangles.
The storage for all that has to be fast, growable and so on...
For several reasons the point storage had to be separate from shape storage. So for points - I made a list of gap-buffer arrays. Exactly like text editors. (Point edits are mostly localized, and gap buffer works really well for that).
Shapes are stored in a linked list of arenas in depth-first order always.

There were obviously some synchronization issues, because I move memory around. For that I came up with a mix of a lookup table, indexing and pointers. it makes sense, I promise =) but it would take pages and pages to describe all the reasoning.

Anyways, I think I solved it. Not 100%, obviously, but it's a good solution to actually start building the editor.
And I did not want - in this case - to solve the problem by typing in some dumb system and fix it later.
This is kind of a core thing and without it editing and history could not really work properly. And an editor is really just a thing that does, well, editing and undo/redo of the editing. So I wanted to really think this stuff through and implement something that worked really well and scaled to huge data sizes.

Ohm and I did couple refactorings here and there. Simplified the renderer quite a bit and did some improvements to the string library (of course, I have my own string library).

So that's that. Anyways, this post is too long already, thanks for reading and I will see you next month.







Wow it's been a long time since the last update.

Ok basically, I've finalized the storage system for points and shapes.
Wchich allowed me to implement history undo-redo very easily.

eg. creating, undoing and redoing points in a shape:



Now I'm just making sure that basically all of the editor is working. All the tools, all the history operations for them etc.

At the same time, we're trying to put together a UI for all this.
I've teased my UI system a bunch here. Hopefully next month I'll be able to do a demonstration video on it.

But here's a quick picker window I made recently:



And the code for it looks like this. (NaN value is a joke, dont worry)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#components
text-input role:text-input; dim:100% h:27; bg:#eee; padding-left:10; padding-right:10; radius:2;
    rect text:<text, "default">; align:4; font-size:12;
picker-input role:num-input; w:fill; bg:#dfe6eb; padding:3 3; radius:3;
    rect text:<value,"NaN">; font-size:10; font-color:#7d8184; align:8;
    rect text:<label, "NaN">; origin:center-top; anchor: center-bottom; font-size:10; font-color:#848688;
picker-radio-btn w:33%; h:20;
    rect text:<label, "NaN">; align:8; font-color:#7d8184; font-size:10;

window-fill w:300; h:430; bg:#f4f8fb; align:8; y:100; padding:10; stack:v; gap:8; radius:3;
    "Fill"
    rect w:100%; stack:h; bg:#dfe6eb; radius:3;
        picker-radio-btn v.label:"Solid";
        picker-radio-btn v.label:"Gradient";
        picker-radio-btn v.label:"Image";
    sat-val-picker w:280; h:280; bg:#a00;
    hue-picker w:280; h:14; bg:#a00; radius:2;
    rect w:100%; stack:h; gap:10;
        picker-input#shape-hue v.label:"H";
        picker-input#shape-sat v.label:"S";
        picker-input#shape-val v.label:"B";
        picker-input#shape-alpha v.label:"a";
#ui


All in all, nothing fun is going on. I hope next time I'll have more to show.

Thanks and bye.

Edited by Stas Lisetsky on Reason: added code for the UI
I suppose it's not part of the project, but I was wondering if your renderer could be shipped as a library to render (in software) vector shapes to bitmaps ?
At some point I'm going to write a thing that does that - right now I'm just drawing everything real-time without any kind of caching, even the small svg icons, but that's not coming any time soon. Right now perf is not a priority, and we're more focused on core features of the editor.

The closest thing to a tool like that is this guy's github.com/memononen nanosvg lib.
Or there is the famous antigrain engine antigrain.com/. But ripping their renderer out to make a tool could take a while.

Edited by Stas Lisetsky on
Thanks