When I was playing with the FeatherEditor last week, I felt a hint of some new way of creating when I would move one item, and the rest would move closer into place. I was working with the holistic result in mind, trying to move the fewest number of critical points so the blending could work its magic and smooth things out in between.
I got excited when I realized the concept of blending many features between feathers could be applied to other sequences of things, either over space or time. But ah, it’s easier to show than to try to explain why it’s cool, so I did a second application where instead of blending between feathers, the blending happens within a single feather, to the strands branching off the central shaft (i.e., the barbs branch off the rachis).
The gist of blending is I use the MurreletGen macro that can map a data type (like “the feather” or “the curve of a barb”) to a vector and back. So I can train a linear model to predict that vector from a restricted set of features. For example, an important feature for blending is how far the barb is up the feather, or the percentage relative to the first and last barb.
(There are tricks to make the micro model work in the way you want, like having each point be defined relative to the previous one instead of globally. Since each barb has its own offset and rotation based on the position on the rachis, I also don’t make the model learn that. A tradeoff is that it makes the editor code more complicated, since you need to map from global back to local.)
I started generalizing the bit of code that fits the model, and realized I wanted to handle features differently. With the feathers, I would compute all 18 feathers and store them. With 100s of barbs, that was less feasible. I also wanted to be able to change the number of barbs. So now I’m only storing the barbs that have been modified, and I key them by their percentage through the feather: the barb 25% of the way up the feather is treated the same, whether it’s barb 100 of 400 or 25 of 100. If the particular “X% barb” is not displayed (e.g., if you defined the barb one third of the way, and then switched to quarters, then the 1/3 barb is no longer rendered), it’s still stored to compute.
Phew. I got that working, and it looked pretty cool.
I’m noticing places where the blending doesn’t work as well and I end up having to define a lot of the location points. I might have too few or too many features e.g., I used to mark the first and last feather as special, but that means when I fit those, sometimes the rest don’t update. Presumably, the model is getting hung up on those feathers being the first and the last. Part of the reason it’s not working is that I’m still learning the tool and the domain: I’m slowly picking up on better ways to position the points on the feathers.
This is basically my first project where you can click on a drawing in the JavaScript editor, and it updates the Rust data structure so that when Rust creates a new SVG, the change corresponds to where you clicked. I’m really tempted to create another procedural macro to generate that code for me (maybe with attributes like “this point is relative to that point, so draw them with a line connecting, add them when you are calculating the output, and subtract them when you’re updating them”).
But, basically, Monday through Friday, I was refactoring code every day: to generalize the blending module, to update the ui to work with many feathers or one feather, to work with multiple layers of color.. So I didn’t want to spend another full day doing that instead of making things with the tools. It’s also a bit too early. I’m telling myself I need to use this in a very different project with different parameters and see how I want to edit things.
I brought over the little sparklines and evaluated parameters for the dovekie ui.
I also realized that even though the FeatherEditor takes a very different approach than the Dovekie interface, Dovekie could work great for parameters like the number of barbs or the colors of feather details.
Meanwhile, off of the computer, I finally picked up a used bike! My last one had its lock broken in my Portland apartment’s bike room, but I’ve been making great use of the Blue Bikes in Boston this last year. To try a longer but safe ride for its maiden voyage, I biked to Castle Island to check out shorebirds and spotted my first ruddy turnstone. Looking for shorebirds is cool: like first getting there and intently looking, but seeing nothing but rocks and water. And then noticing a small brown bird on the rocks, a semipalmated plover. Spend a while photographing it, then notice a second one less than three feet away that had been there the whole time. A (human) kitesurfer cuts through the water nearby and flushes a dozen plovers I also hadn’t noticed, and they land back on the shore. And then by then, I feel like my eyes and head are downshifted from city biking to birding, and I start spotting the other shorebirds on the rocks.
I watched the recording of the Hundred Rabbits Permacomputing 101 talk. I think it’s the first time I got a good definition of permacomputing.
I do still have a dream of making things that don’t need computers but still can compute, like, ah, nomograms or astrolabes or making live visuals with computational shadow puppets.
Something interesting was that browsers appear to be cool, but some of the new features mean that only a few huge tech companies can actually implement them, so it’s exceedingly difficult for new browsers to be developed. I’ve started to use browsers for more work and have been pleasantly surprised at all of the available APIs, but it was good to hear more about the cost of those.
(I actually tried to draw a feather before, but using a grammar system with attributes, where each barb would know how much further it should grow. It was a fun idea and maybe a bit closer to how the cells actually grow [caveat: I haven’t done biology in a long time], but it ran extremely slow, and it was pretty tricky to find the right formula. Here’s a an image that I really like that came out of the same system.)