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 details)

Uploaded Source

Built Distribution

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

Uploaded Python 3

File details

Details for the file procedural-buildings-1.0.1.tar.gz.

File metadata

  • Download URL: procedural-buildings-1.0.1.tar.gz
  • Upload date:
  • Size: 110.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/50.3.0 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.9.0

File hashes

Hashes for procedural-buildings-1.0.1.tar.gz
Algorithm Hash digest
SHA256 cd64043575ed3070b513b1df41aa31b5718bc4488941a887b19544ca7c8983b2
MD5 d715579027c3dd54b7fdab1ad08eb93f
BLAKE2b-256 62b2c73a3105a19b5b1fde14eb03855c9449761f6f975f29f6ac87fa2a8f2036

See more details on using hashes here.

File details

Details for the file procedural_buildings-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: procedural_buildings-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 115.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/50.3.0 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.9.0

File hashes

Hashes for procedural_buildings-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 40dffa1b54ba899f0cc3567c5341aa3f11ca0827e5d80f61ba33cd47ba4fd34d
MD5 225fc780ec4e20085f7cc9aff2fde632
BLAKE2b-256 54b3f25eaad3c1cb97cdc4a5b5d4189606a1fe5f4263bd17239c8be00a263647

See more details on using hashes here.

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