Arrays of books! (Geometry nodes)

Hello !

I needed a little break from my procedural buildings , so after seeing an amazing talk by Anastasia Opara I tried to reproduce her book generator in blender (toward 26mn in the talk) :


I didn’t think it would be that much complicated, but eventually I figured out a way of doing it…
Mainly because there is no loop in geometry nodes yet, I find that it was hard to replicate exactly how she did it. So I find my own way in the end.

For those interested here is a short description of the method :

I start by generating some points and some random values for scale and rotation.
At this stage what I get is something like that :

The cubes are instanced on points and scaled / rotated according to the random values.
Then comes the tricky part, it’s basically a lot of vector operations based on these random values.
The basic idea is to do all the calculations beforehand , to know the exact position of the book according to their rotation and scale, and when I get these value I can instance object or do some modeling based on that.

The first step was to get these vectors :


It’s not taken from the geometry, but by taking the random values and do some math operation . Like taking the Z random scale and use rotate vector on that according to the random rotate value (that will give the purple lines).
At some point I had to make a group that help me visualize these values, forming these colored arrows.

Then comes the most difficult part, using previous vectors I look for these ones :


That’s basically the contact points between two books.
I used the Field at Index node to inspect the next “book” .
You can see that the red arrow change direction depending if one book is next to a bigger book.
The direction isn’t relevant, but I needed to find the upmost corner of the smallest book between two books and point toward the biggest.
To give these arrows the right length I needed a way to get the intersection point between two lines , because at this stage there isn’t any geometry to do some raycast .
I looked up for finding the interesection point of two segments in 3D.
And I ended up translating this code into geometry nodes.
Then I find the intersection point of the red arrows with the purple or blue lines in the previous capture.

Once that was done, the last step is to take the shortest line between the red and the green , and substract that from the original positions :


And all the books will stack between each-other \o/ !

There is still some way to make that fail, there are some intersection in the black circle because it only take into account the closest books, but if there isn’t too much variations in size it will work !

At this stage I could then build the books.

The good thing in having only fields and do all the calculation beforehand, is that I can model the books straight , witch is much simpler, and rotate them in a last step :


because rotation and center points are stored in the geometry as attributes, I can always access them down the line and use them when I want…

I think it’s the most involved thing I’ve done in GN yet, despite the visual simplicity of the result.
I’ve learned a lot in the process !
I hope at some point doing things like that could be less involved, on a production I would have probably gave up and used a more manual approach which would have been faster, unless there are really a huge amount of books and client would be phobic of repetition patterns.

I’ll see if I can build a bit more on that now that the difficult part is figured out…

If someone look into it I would be really glad to know of other ways of doing it (hopefully simpler) that would allow these kinds of rotation / distribution !
Thanks !

27 Likes

Clearly black magic! :slight_smile:

On second thought, would it be possible to use a accumulate node, instance the books, randomly rotated as in your way, but using their bounding boxes for calculating the distance between books, then rotate the whole stack?

1 Like

Something like:

  • if the “previous book of the stack” angle is > than “this book”, then transform this book location by “that book” bounding box length (moving it closer to that one on z axis of the accumulated “tower”; )
  • if the “previous book of the stack” angle is < than “this book”, then transform this book location by “this book” bounding box length instead; (as above)

[edit] it wouldn’t work probably if the previous book was taller than the next, damn.

1 Like

It’s not that easy, especially because there isn’t rotation on the bounding boxes and you can’t get them from instances, so seems likes a dead end, but it could have helped to simplify getting the initial distances.
I also used accumulate fields in some places, especially to get the accumulated rotations, so it gives the feeling that the books slipped toward the end of the array.

1 Like

A small updates, now with UVs and curve deform inside geometry nodes.
The only modifier used so far is an temporary edge split to get a better shading.


I’ll probably look into generating some shelves and put the books inside… At least it should work nicely with that.

The funny thing (at least to me) is that generating the books is quite fast, like ~500 ms for the image above with 920 individual books, no instancing, 455 000 Tris. And adding a bevel or edge split modifier after that seems like at least 2/3 times longer…
Even if that’s understandable I wouldn’t have though that in the first place… Geometry nodes never cease to impress me !

10 Likes

Very cool work!
While it uses recursion, so it won’t work well in Geometry Nodes, you are welcome to use my bookshelf generating code to make bookshelves. Crazy Procgen Bookshelf Script
Or you may draw inspiration, just as you have given inspiration!

Hey ! Thanks !
I already started looking into something a bit simpler / boring , I’ll try to push the details on the model and try to make huge rows of shelves.

But I’ll take a look at your script, that’s something definitively useful to do and as a lot of applications.
This post just came out, that’s along the same lines :

It uses recursion too, but, as long as it’s not too slow to compute :slight_smile:

I’m really looking forward to look into these kind of base pattern and test different applications, so I’ll
take look as much approach as I can for inspirations !

Thanks for sharing !

5 Likes

Your work is really inspiring. You’re a blender ROCK STAR dude!!!

2 Likes