You can get Voxel Farm now. For more information click here.

Wednesday, April 4, 2012

A room with an angle

This is a continuation of the previous post. Like the one before, it is mostly about occlusion tests and snap planes in architecture generation systems.

It is possible to create richer architectural volumes by combining several simple volumes like boxes. The resulting volumes can be quite complex, which is in part what we wanted but it also brings some complications.

In the following image you can see the result of three boxes intersecting each other:

If you concentrate on the walls going out you will see they would make an interesting building. At the same time there is a lot of nastiness in the inside. There are several triangular spaces and at least one non-convex polygonal space. Those would not translate well into rooms. Ideally we would like to keep the outer walls and remove all the nonsense spaces. This can be done with occlusion tests and snap planes.

To show this I will use the same grammar language as in the earlier post. If you feel lost in the code there are some comments in that post that may help.

This is the code that produced these three boxes. It will be our starting point:

The module "angletest" is the one that produces the three rotated box volumes. Each box has its sides covered by wall panels.

The first half of the trick is to hide those panels that appear inside a volume. The occlusion query can do that. It would take only a few lines to add it:

The "volume" module now occludes. Also there is a new definition for the "panel" module that should be picked when the panel is occluded. Just to visualize which ones should be hidden I chose to render them as lines on the floor. You can see the results here:

This is already better, but there are still some holes in the corners. This is because an entire panel is hidden even if only one part of it is occluded.

Snap planes can help with this. If each volume defines a set of planes, the intersecting panels will match their size to the near volume. This is how you would write it:

Now each wall introduces a snap plane, then the panel repetition is snapped to those planes. Panels are aligned to wall intersections. They can be entirely removed and no holes will appear:

It wasn't so bad. Again, this alone won't be enough to create interesting buildings, but it is a technique you may want to remember.

Here is how it would look if you replaced the panels by windows. I also added some random rotation to the three boxes.


  1. Can't wait to see more examples with more complex and unusual architecture.

    I'm having trouble understanding how your modules communicate between each-other. I first thought they were some sort of functions like in any programming language and that one could call another but then got confused when you introduced the variable wall in the "repeat x [3] panel" line in the wallpanel module. Is that a sort of way to do recursive function calls ?

    So far, i'm amazed by the quality of your project. I never saw something like this before... Awesome.

    1. Thanks.

      The "wall" identifier in the repeat clause is the name for the family of snap planes. It is not a variable, nor it is used for recursion. It means the repetition will occur in fragments of three meters length, but if there is a snap plane nearby that is named "wall", the fragment's length should grow or shrink to match the intersection with the snap plane.

      These planes are like invisible guidelines that can be shared by different modules. In this example they are declared a few lines before by doing "snap wall z 0.1".

  2. This is really cool work mate. Such a simple way to make an environment seemingly more complex. I suppose you could make things even more interesting by including some other basic primitives like a hexagon + 2 rectangles.

    What I think makes this whole method fall down though is the lack of intelligence in the design. I think procedural methods like this, whilst passable, aren't believable when the shapes don't equate to any form or function of the area. This is a problem if you expect to live in or navigate the the structure.
    You need a way of, before you even generate the physical structure, of creating the 'room' layout. Like you should be able to tell the algorithm that you want a 'house', and it knows a house is made up of 2 bedrooms, a lounge room, a kitchen, tv room, a deck, etc. So it then goes and makes a loose and discounted layout of these rooms, maybe based off of some basic rules or guidelines on what each room type should be able to look like. Then does another pass on top of that similar to your above article of randomly placing, occluding, and connecting shapes to make it all fit.


    1. I think you are missing the point. This method does not fall down due its lack of intelligence because of two things:

      a. It is not a method
      b. It is not meant to be intelligent

      You are not looking at the whole method here. Not sure of what problems you talk because I have not posted any building interiors yet. This is just a technique you will be using. The generation of complex architecture requires several different layers of logic working together, at different levels of abstraction. The fact that one layer is not smart does not reflect on the intelligence of the whole system.

      Grammars can be used to express all that, from very specific and spatially defined tasks like layering bricks, to very generic constructs, like how all Japanese castles are laid out.

      There are a few papers that teach the approach you described for generating a believable interior for a house. I will link to them later. This is not a different method, they actually use the very same technique described in this post to blend different sections of a house, for instance attaching the garage to the rest of the house.

    2. Partially following on from the above point; I've been looking at a few different papers on simple l-system based trees and then some extensions/varations on that base concept - Guided generation with key points and adaptation to surronding physical geometry.

      The result being a tree that grows in a simple way, but towards a guided goal. It also takes into account surrounding volumes through a simple boolean operation can can clip the tree's own volume and cause a redistribution of its guide points. This leads to trees growing towards light and up over objects but all within a given space.

      After all that, my question! I was wondering if you had experimented at all with providing a final/global volume for your generation to occur in? It would be pretty interesting to see your system generate a base building, but scale with surrounding geometry to collapse or expand itself.

      An example house might flatten to a single floor bungalow of 4-5 rooms, or if placed in a busy area stack up to a 3-floor town house with the same contents also adding stair access. I don't see any reason it wouldn't be possible, more just looking to see any results you've already produced! :)

      Ps. This is an amazing blog, keep up the good work!!

    3. It looks interesting, but I have not tried anything like this. My approach is top/down, which the the opposite of what you describe. I start with the final volume (or a list of volumes) and then they are broken down using grammar rules and some other rules similar to an expert system.

  3. I enjoy reading your blog and the articles are very nicely illustrated. Just wondering, did you consider using CSG to solve this particular problem? ( Although the technique you have chosen seems to work very well.

    1. CSG is a double-edged sword. It would make combining boxes quite easy, but there is a price. These grammars rely on transformations to a simple geometric object called the "scope", which is either a box or a triangular prism (these two combined can give you any shape you want). With CSG the scope could end up being a really complex object after a few operations. It would be difficult to write rules for it.

      I do use CSG for some end level objects like roofs, but they are specialized towards one meaning. Generic ones in my experience create more issues than what they solve.