Now that you have Rust and Nannou installed , lets look at a basic Nannou sketch. A sketch in Nannou is a fast way to get a drawing displayed. Here is a simple one which just draws a rectangle and an ellipse on a colored background.
use nannou::prelude::*; fn main() { nannou::sketch(view).run(); } fn view(app: &App, frame: Frame) { let draw = app.draw(); draw.background() .color(LIGHTBLUE); draw.rect() .color(ORANGE) .w(100.0) .h(200.0) .x_y(200.0, -100.0); draw.ellipse() .color(DARKGREEN) .w(200.0) .h(230.0) .x_y(100.0, -50.0); draw.to_frame(app, &frame).unwrap(); } So what is going on here? At the top level, the three important parts of this sketch are the use statement, which imports all the Nannou components we need, the main() function, and the view() function. This is, in itself, a complete Rust program as well as a Nannou sketch. In Rust, the main() function is where the program starts – it’s the code that is executed when the program is run. In this case, that is just one line: nannou::sketch(view).run();, but there’s a lot going on on that line!
In my last post , I mentioned Nannou , a generative art framework for the Rust programming language. While I am focusing mainly on drawing here, Nannou goes much further dealing with user interface, audio and video, and even lasers ! Its goal is to provide tools for artists building any kind of art installation.
For drawing, it is similar to Processing in how it is used, and therefore similar to all the other frameworks I’ve discussed here, which are all based on, or at least inspired by, Processing.
This is my first real new post since 2020. All the ones posted at the end of 2023 were written back in 2020, and have been backlogged while we dealt with personal issues. New year, new posts!
In my previous posts, I’ve explored some basic generative art in a variety computer languages and art frameworks. We tried Javascript with p5.js , Clojure with Quil , and Java and Processing . I don’t have any post to document it, but in the past few years, I also experimented with Kotlin and Go for artwork.
“Everybody should learn to program a computer, because it teaches you how to think.”
— Steve Jobs
I’ve shown many attractor images I have generated over the past few weeks, but how have I been drawing them? I have been writing code to do so, but stopped including it in the posts because it was getting long and complex. I promised that, someday, I would share the code. Today is that day!
Ash nazg durbatulûk, ash nazg gimbatul, ash nazg thrakatulûk agh burzum-ishi krimpatul.
One ring to rule them all, one ring to find them, one ring to bring them all and in the darkness bind them.
— J. R. R. Tolkien’s The Lord of the Rings (1954–55)
I’ve been going on and on about de Jong attractors lately , but that is only one kind of attractor. There are many others! This image is a Svensson attractor. It uses a set of equations very similar to what the de Jong attractor uses, and also requires four constants which define the shape of the result. Because of the way it handles sine and cosine, circular results are far more common than with the de Jong equations.
In my last post , I talked about coloring a de Jong attractor based on the number of times each point in the image was generated by the de Jong equations. Of course, there are other ways to do it! Since we have more than one way, we’d better name them so we don’t get confused. We’ll call the first method Frequency Coloring since it’s based on how frequently each point appears. Now let’s talk about Velocity Coloring!
In my last post , I took a first stab at coloring a de Jong attractor. Here was my image:
The main problem was that I had wanted an image in which the points with the fewest hits were blue, transforming to red for points hit the highest number of times, but as you can see, the image was stubbornly mostly blue, whereas I would have expected a lot of shades of purple as the blue transformed to red.
Hello! By now you have seen Tandika's article explaining why it’s been so long since we have posted anything. It’s been a wild three years! Things are finally getting back to normal (although as she mentioned, a new normal.)
This post, as well as the next several “The Artist’s Husband” posts, were written three years ago, when I thought they’d be published. I’ll post these about once a week until I work through the backlog. After that, I plan to continue posting periodically, as often as I can.
Last week , I showed a program I was working on to generate deJong attractor images. I mentioned I’d be working on adding some color. I am not there yet! This is a mere stop to take a breather, and to talk about an intermediate step: smoothing the image. Here is one of my images from last week:
While interesting, there are some problems here. I am just calculating points, and as each one is calculated, I draw it on the canvas, even if it has already been drawn. For any given set of input constants, there are going to be the same points showing up a lot, some more than others. The final image, however, is very sensitive to the number of unique points I actually draw. Too few, and there is not much to see. Too many, and the image devolves into an amorphous blob:
In my last post , we played The Chaos Game and ended up with a Sierpinski Triangle. It’s quite nice as far as it goes, but there is not a lot of variation and visual interest beyond the initial surpise of finding it buried in the chaos at all. This time around, lets look at the de Jong attractor.
First, some terminology! An Attractor is a dynamic system with a set of numeric values to which the system tends to evolve over time, no matter what state it starts in. An attractor is called a Strange Attractor if it contains a fractal element. The Sierpinski Triangle we came up with last week is an example of a strange attractor. It doesn’t matter what your starting point is (it could be miles away from the triangle), you will eventually get pretty much the same result for any given triangle. The de Jong attractor is another example of a strange attractor.
Today, we’ll play The Chaos Game! It’s easy to play, and it goes like this:
First, put three points on your paper. These will be the vertices of a triangle (so don’t put them in a straight line!) Any triangle will work, but be sure to leave lots of area inside where the triangle will be to make it easier to see what it going on.
Next, you need a way to randomly choose one of those vertices over and over. You can roll a die, and if you get a 1 or a 2, that could reference the first vertex, a 3 or a 4 could reference the second vertex, and a 5 or a 6 could reference that last vertex. If you are a Dungeons and Dragons player and happen to have a 3-sided die, feel free to use that!
Let’s draw some squares!
Last week I introduced Clojure as a possible replacement for Javascript for my generative art pursuits. Clojure has the Quil library that provides many of the same capabilities that p5.js provides to Javascript. Let’s look at a simple example. This Javascript/p5.js program generates an image like the one at the top of this post.
function setup() { createCanvas(800, 800); background(240); stroke(0); let size = 500; let offset = 50; let centerX = width/2; let centerY = height/2; let topLeftX = centerX - size/2; let topLeftY = centerY - size/2; fill(200, 150, 250, 150); rect(topLeftX, topLeftY, size, size); rect(topLeftX-offset, topLeftY-offset, size, size); rect(topLeftX+offset, topLeftY+offset, size, size); } The program is fairly simple: create the canvas, fill in the background with grey, set the stroke (line) color to black, set the fill color, and draw three rectangles slightly offset from each other. If you’ve been following along with my previous posts, this looks pretty basic. The only remotely tricky thing going on here is that the fill() function has a fourth parameter. The first three set the red, green and blue components of the fill color, while the fourth sets the transparency. This is what allows us to see the through the squares, and is what causes the gradations of color where the squares overlap.
If you’ve been reading my posts each week, you’re probably aware that I have been working mostly in Javascript, using the p5.js drawing library. There are many things to like about Javascript, but also many ways for it to slowly drive you bonkers. I won’t go into all those reasons here, but I will say it’s time to try something new. I’d like to try to do some generative art using the Clojure language. This is way out of my comfort zone, since I don’t actually know Clojure, and it is not a simple language, but I thought I’d share my experiences with it here.
The Entanglement library has a few grid-based tangles now: Huggins, W-2 , Ambler and Emingle. But we have limited control over the grid: we can affect the spacing in the x and y directions, and we can add some random fluctuations to where each intersection on the grid ends up. Wouldn’t it be nice if we could warp the grid in some more dramatic ways? Yes, I thought so too! So I spent some time adding some more grid options. This turned out to be harder to do than I thought it would be – I ended up having to rewrite big chunks of the Tangle class, then I ended up subclassing Tangle and creating a special class just for grid-based tangles: GridTangle.
This week I wanted to talk about something a little different, something only peripherally related to art: Behavioral Animation. Behavioral Animation is a kind of computer animation in which an autonomous object determines its own actions by interacting with its environment according to certain rules. Behavioral Animation is a fairly vague term, which covers quite a bit of ground.
The Game of Life A simple example is The Game of Life, developed by John Conway , a British mathematician, in the early 1970s. The game starts with an infinite grid (well, potentially infinite – please don’t try to draw an infinite grid…) with some of the squares filled in. It’s important to notice that each square is surrounded by eight additional squares. Nothing surprising there, it’s just how grids work! Then the squares are modified according to two simple rules: 1) if square that is filled in has either two or three of its eight neighboring squares filled in, then it remains filled in, otherwise it is emptied. 2) if an unoccupied square has exactly three filled in neighbors, then it is filled in. This continues through successive generations. The interesting thing about this is that is mimics population growth. Consider each square to be a living cell if it is filled in. If the cell doesn’t have enough neighbors, it dies (perhaps of loneliness.) If it has too many neighbors, it dies (perhaps for lack of resources.) If conditions are just right, they can reproduce, and new cells appear (we’ll just gloss over the fact that that takes three neighbors, not two!) It turns out this models things like bacterial growth fairly well.
Huggins and W-2 have appeared in the Entanglement library! Huggins and W-2 both look like they have been woven but are really just shapes on a grid connected by lines according to a few simple rules. The difference between them is that Huggins connects circles with curved lines, while W-2 connects squares with straight lines.
In this post, I’ll talk about how I built Huggins (once you build Huggins, W-2 is pretty easy to add) and show some examples of how both are used.
The Entanglement library has a very few (so far) tangle patterns built in which can be used to create Zentangles. New ones get added to the library as I get to them, but you (yes, YOU) as a user can create them too. Warning! This post is mostly Javascript code! If that’s not your thing, avert your eyes now! You need version 0.0.5 of Entanglement to follow along:
<script src="https://cdn.jsdelivr.net/gh/tektsu/entanglement@0.0.5/dist/entanglement.js"></script> In this post, we’ll create a simple grid-based tangle pattern, then use it in a Zentangle. The tangle we’ll create is not particularly interesting, and is not a “real” Zentangle (as far as I know.) It’s just an example to show the process. The Entanglement library only supports two general kinds of tangles so far: a pattern of tangle elements placed randomly on the canvas, such as Aah or BoxSpirals, or a grid with some kind of pattern, such as Ambler or Emingle. We’ll create a grid tangle in this case. We want it to look something like this:
On two occasions I have been asked, ‘Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?’ […] I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
— Charles Babbage, Passages from the Life of a Philosopher (1864)
In my first post about generative art, I dumped a lot of Javascript on you with only a basic explanation of how it works, and more recently I have given up trying to explain it at all under the theory that most of the people reading these posts are more interested in the art rather than the programming behind it. Also, including a Javascript course here would make for some very, very long articles!
Up until now, the Entanglement library has provided a few tangle elements and a few tangles, which you could draw onto your canvas. But real Zentangles have a border, and might be round or triangular instead of square. To make this easier to do, Entanglement now has the Zentangle class. This is the top-level class you should use to define what your Zentangle should look like.
Here is an example using it. This program drew the image at the top of this page:
Recently I did a post about the Ambler tangle in the Entanglement library. Ambler uses an element called a box spiral. It turns out, box spirals appear in several tangles, most notably the Box Spirals tangle. In this post, we’ll talk about the Entanglement BoxSpiral class, which implements the Box Spirals tangle.
The box spiral used in Ambler as it is implemented in Entanglement is very specific. It consists of nine lines, and always rotates counter-clockwise. Therefore it can only be drawn in four orientations, with the spiral starting from one of the four corners of its enclosing box.