Skip to main content

Tools for the procedural modelling of buildings

Project description

Procedural Generation of Buildings

Welcome to my third year university project on the procedural generation of buildings!

There are two main goals for this project:

  • Design a grammar language that can be used to describe buildings with sets of procedural rules, which can then be transformed into a 3D models
  • Given an example set of 3D buildings, attempt to reverse engineer a grammar from the given buildings, which could then be used to create more buidings similar to the examples

To discover how I achieved the above, I encourage you to read (or perhaps just flick through!) my project report. The report also teaches you how to write your own grammars and demonstrates some of my own architectural creations.

If you want to have a go at writing your own grammars and generating your own buildings, read on!

Installation (using Pip)

This project is packaged and available on PyPi and can be installed (or updated) with the following:

python -m pip install --upgrade procedural-buildings

Basic usage

Writing your first grammar

If you want to learn the ins and outs of writing a grammar, read my report. Here we'll learn by example and leave the rest to intuition! A grammar is run on an initial scope (a 3D bounding box) and consists of a set of rules, one of which is a start rule. By default, the start rule is plot but you can specify a different name if you'd prefer. The following grammar takes the initial scope and splits it in half along the x-axis into two cuboids:

plot --> split(x){~1 : I(rect) | ~1 : I(rect)}

Save the above to a new file called split_grammar (make sure to include a newline at the end as above). We can then generate a .obj file from the grammar using the following on the command line:

python -m procedural_buildings -i split_grammar -o split.obj

This will create a 3D model in split.obj. Open this in your favourite 3D model viewer (I recommend Blender), noting that the positive z-axis corresponds to upward and the positive y-axis corresponds to foward. Blender lets you specify these axis directions when you import an object. You should see a 10x10x10 cube which is cut in half along the x-axis. To change the initial scope (which defaults to the 10x10x10 cube you see), use the -s (or --start-scope) option. To see a full list of options, use -h:

python -m procedural_buildings -i split_grammar -o split.obj -s 2,2,0,10,5,20

Play around with different start scopes and check out the results.

Creating a house

Now lets look at a slightly more interesting example - a house with a garage. Copy the following grammar into a new file called house_grammar. Once again, don't forget the newline (I really ought to change that "feature"!):

plot --> split(x){~2 : house | ~1 : garage}
house --> split(z){~2 : I(rect) | ~1 : I(triangle)}
garage --> split(z){~1 : I(rect) | ~2 : nil}

Now generate the buildings with:

python -m procedural_buildings -i house_grammar -o house.obj

Take a look at house.obj and try and understand how it's been generated by the grammar we wrote. Play around with some numbers in the grammar to see how it affects the result.

As a final example, let's adapt house_grammar so it has some randomness. Copy the below into a new file called house2_grammar:

plot --> split(x){~2 : house | ~1 : garage} : 0.5
plot --> split(x){~1 : garage | ~2 : house} : 0.5
house --> split(z){~2 : I(rect) | ~1 : I(triangle)}
garage --> split(z){~(rand(0.75,1.25)) : I(rect) | ~2 : nil}

See if you can figure out what the result will look like then generate a building:

python -m procedural_buildings -i house2_grammar -o house2.obj

Notice that if you run the above command a few times, the result will be different each time.

To generate many buildings from our grammar, we can use the following options:

  • -n (or --num_buildings) (default 1) specifies the number of buildings to generate from the grammar
  • -d (or --separation) (default 10) specifies the distance between buldings.
  • -f (of --file_per_obj) specifies whether to use a separate file for each building. In this case the -d option will be ignored and the given output file name will be used as the file prefix to use for the output files.

Let's create 10 buildings each 2 units apart. We'll stick to one output file for now:

python -m procedural_buildings -i house2_grammar -o house2.obj -n 10 -d 2

How about backwards?

To create a grammar from a given buildings, we can use the -r (or --reverse) flag. Now, our input file is the .obj file and the output is a grammar file. Let's try and reverse engineer the grammar we used to create the first house:

python -m procedural_buildings -i house.obj -o house_engineered_grammar -r

Take a look at house_engineered_grammar and you should see its equivalence to the original house_grammar.

Now lets try and engineer a grammar from mutliple example buildings. First create 10 example buildings using house2_grammar. We'll put them in separate files this time by using the -f flag. The output file name example will be used as the prefix for the 10 output files so we'll get example0.obj, example1.obj, ... , example9:

python -m procedural_buildings -i house2_grammar -o example -n 10 -f

Now we can create a grammar from the example buildings. Create a new file called examples and enter the file names of the example buildings:

example0.obj
example1.obj
example2.obj
example3.obj
example4.obj
example5.obj
example6.obj
example7.obj
example8.obj
example9.obj

Now, create a grammar from the buildings. The input file will be the file containing the file names (it knows it's a list of file names rather than a single object input by checking for a .obj extension):

python -m procedural_buildings -i examples -o house2_engineered_grammar -r

Take a look at the engineered grammar. You should be able to see the similarity to the original house2_grammar. We can now use our engineered grammar to create more buildings. Note that we'll have to specify that the start rule for this grammar is rule0:

python -m procedural_buildings -i house2_engineered_grammar -o more_houses.obj -n 10 -R rule0

You've now generated 10 buildings similar to the 10 examples.

To see some more complex examples, check out my report or create your own buildings!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

procedural-buildings-1.0.1.tar.gz (110.6 kB view hashes)

Uploaded Source

Built Distribution

procedural_buildings-1.0.1-py3-none-any.whl (115.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page