procedural-buildings 1.0.1
Tools for the procedural modelling of buildings
Requires Python: >=3.6

# 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](https://github.com/JUST0M/procedural-buildings/blob/master/doc/project_report.pdf). 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](https://pypi.org/project/procedural-buildings) 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](https://github.com/JUST0M/procedural-buildings/blob/master/doc/project_report.pdf). 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](https://www.blender.org/)), 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](https://github.com/JUST0M/procedural-buildings/blob/master/doc/project_report.pdf) or create your own buildings!