City Generator Include File: Design Guide
for Persistence of Vision 3.1
Created by Chris Colefax, 1 February 1999
The documentation for the City Generator Include File explains the basic structure and usage of the include file package. This document details the guidelines to follow when you create your own custom city macro and object files.
The type of file you create (macro or object) depends on the sort of city/town/village scene you want to produce. City object files can contain definitions of vehicles, pavement objects (such as street lamps), and building components (single storeys, roofs, etc.), that are copied and placed by City.mcr to assemble the city. Although some randomness can be added to textures for the buildings and building windows, all the objects remain basically static.
City macro files, on the other hand, allow you to completely redefine not only the objects that the city is constructed from but also the way in which the objects are assembled. For example, you could design city macros that construct buildings directly (rather than simply copying a predefined object), ensuring that no two buildings (or vehicles, or streets, etc.) in the city are alike. Or, you could design macros that animate some or all of the city in various ways.
Designing City Object Files
City object files can be designed in two basic ways: they can contain all the objects required to build a city, or they can contain a selection of objects (say, a set of vehicles, or a single building). The second type of file can then be used in conjunction with other similar object files, so you (or people you distribute your object files to) can build a library of object files and combine them in different ways.
Each of the components that make up a full set of city objects will be explained separately, so you can concentrate on one section at a time. For example's sake, simple textures and objects will be used where necessary - of course, you can make your object files as complex and detailed as you like. If you are designing objects in an external modeller or importing meshes from another program, you should keep in mind that the City Generator uses a left-handed coordinate system with the +y axis pointing skywards (and the object bases sitting at y=0).
Also, while the scaling of objects and textures is up to you (depending on the options you use with City.inc and City.mcr such as building_width, pavement_height, etc.) you may find it best to use the default scale of approximately 1 unit = 1 metre. This will ensure that you can easily share your object files with others.
Basic City Object Files
The minimum requirements for a stand-alone object file are very simple: all you need to declare are a texture to be used for the streets and a texture for the pavements, plus a value telling City.mcr not to use the default objects, eg:
If you save these three lines to a file (eg. MyCity.obj), you will have a working city object file ready to be used with City.inc, eg:
Rendering the above scene will show the default city layout, with dark grey streets and lighter grey pavements. Of course, you can declare the textures in any way you want, including image, bump, and material maps, layered textures, etc.
The third, optional city texture is that used to place markings on the streets. This texture should generally be semi-transparent, so the underlying street texture can still be seen. One unit of the texture will correspond to one traffic lane, travelling along the x-axis, eg: to create lined streets:
The next (optional) step is to place objects on the city pavements, which might include things like street lamps, traffic lights, bus stops, fire hydrants, and pedestrians. To define the objects, you need to declare arrays containing the object definitions themselves, the offsets of the objects from the edge of the pavement, the spacing between adjacent objects, and the randomness of this spacing. These arrays will be used to place objects on all four sides of each pavement, with the objects rotated accordingly.
To declare the objects themselves you should imagine a street running along the z-axis, with the edge of the pavement at the origin. Moving the object along the -x axis will move it further away from the street, while extending the object over the +x axis will cause it to extend out over the streets. Let's say you want to create street lamps, pedestrians, and phone boxes (represented here by simple primitives of appropriate sizes):
In this case, the street lamps are 3 metres high, and the bases of the lamps are one-quarter of a unit from the street. The first street lamp along each side of the pavement will be 3 metres from the street corner, with lamps exactly every 15 metres after that (no turbulence is added to the spacing).
The pedestrian, on the other hand, is 1.7 units tall, and 1.5 units from the pavement's edge. The first pedestrian is half a metre from the street corner, with a minimum distance between pedestrians of 2 metres. The turbulence value of 3, however, means that these values may be increased by up to 3 metres, eg. the first pedestrian may be between 0.5 and 3.5 metres from the street corner, and the spacing between pedestrians may be between 2 and 5 metres.
The phone box measures 1.5 x 2.5 metres, and is 1 metre from the street. The spacing value of zero means that only one phone box will be created along each side of the pavement. Also, the turbulence value of 100 means that the box may be between 5 and 105 metres from the street corner. If the offset distance calculated for a particular box is greater than the length of the pavement, no box will be placed along that side of the pavement (a useful feature when you don't necessarily want a particular object on every pavement).
City vehicle objects are created similar to the pavement objects, with arrays defining the objects and the minimum space required for each vehicle. To create the vehicles you should again imagine a street running along the z-axis. The vehicles should be centred on the origin, with the necessary parts of the object touching the ground at y = 0. If the front of the vehicles point in the +z direction, the vehicles will be placed on the left-hand side of the streets; vehicles pointing in the -z direction will be placed on the right-hand side of the streets. To make your object file support both arrangements, you can include an option similar to that used in the default VEHICLES.OBJ file, eg:
Setting the city_vehicle_spacing values to the length of each vehicle along the z-axis ensures that vehicles don't overlap incorrectly, even when spaced closely together using the traffic_spacing option.
The building objects are the most complicated of the city objects, with up to ten arrays of objects, textures, and values possible for a single building. In addition, a stand-alone object file must also declare a set of values that tell City.mcr which arrays to use for which buildings. The good news is that the DEFAULT.OBJ file can be used to initialise the arrays and the values for a custom building objects file, by placing this line at the beginning of the file:
Having done that, the file must now declare values for some or all of the arrays defining the building. To make your file work in conjunction with other building files, you should use the building_types value to specify the current index of the arrays (ie. use
In between these two lines you can define the building with the options you want. Like the vehicle objects, you need to define the building objects centred on the origin, with their bases at y = 0. Also, the building objects should be orientated so the front of the building points in the -z direction and the back to the +z direction. The building will be rotated so the front always faces out onto the streets surrounding the city blocks. For buildings on the corners of blocks (with two sides exposed), the side of the building facing in the -x direction will also be visible from the streets. The other side (facing in the +x direction) and the back of the building will usually not be visible, except where one building is taller than the building next to it.
Building Window Options
Although the above options are enough to design highly complex buildings, you are likely to be faced with problems if you want to create night scenes containing buildings with lit and unlit windows. Making the windows part of the building_details object would mean that every storey would have exactly the same arrangement of windows, while including the windows in the texture would probably require large image maps for a decent result, and every copy of the same building would have the same window arrangement.
You can solve this problem by using the building_windows object, along with the window texturing macros that are included in DEFAULT.OBJ. These macros will create a three-dimensional texture consisting of regular, rectangular blocks of a specified size. The macros accept two textures: one for lit windows, eg. with a high ambient value, and one for unlit windows. Each block of the texture will then contain one or either of these base textures, with the proportions of each controlled by the windows_lit and windows_blend options. The syntax for the first of these is:
This is usually the easiest method, but in some cases you will want to set the building_window_size option manually, or use the block window texture as part of a texture map (in which case you can use the first macro).
There are various ways of creating the windows for a building: the first is to declare the building_windows object as a union of the actual window panes you want to create on each storey of the building. In this case, you should add the build_window_levels value to the building options, and declare a building_window_texture that maps one block to each pane, eg:
Here we have created two windows (note how the window objects themselves extend from the front wall of the building to the back). Using <25, 0, 0> for the window size option indicates that each block of the window texture should be 25 units wide, but no blocks should be created in the y or z directions. To understand why this value is used, we need to understand what the building_window_size option actually does. Apart from setting the block size of the texture created by the macro, each time a copy of the building_window object is created the texture is shifted by a whole-number multiple of this vector, eg: one copy might have the texture shifted by <50, 0, 0>, another by <-225, 0, 0> . In this way we avoid any two stories from having the same arrangement of lit and unlit windows.
One problem with the above method is that creating more windows requires more objects, and many-storey buildings will require more and more memory. You can avoid this by using a building_windows object that wraps around the entire building, and then using the window_texture () macro as part of a suitable texture map (eg. brick or gradient). You can see an example of this method in the red-brick apartment building defined in FLATS.OBJ.
However, both of the above methods create windows on the outside of the building. To create windows that are inset from the building walls you can add the build_window_profile value to the building options instead, and then define the building_windows object in the same way as the building_profile object (ie. it will be scaled to full height). In this case the building_window_size should also contain a y-component equal to the height of a single building level, so that each storey has a different window arrangement. You can then wrap the outside of the building around the window profile object, either by using a building_details object containing the necessary "cutouts" to view the window profile inside, or a fitted building_texture that contains transparent areas. You can see examples of both methods in the various default building object files that come with the City Generator Include File package.
City Object File Hints and Tips
Hopefully the information above, along with the default city object files, should be enough to have you well on your way to creating entirely new cities of your own. Here a few things to bear in mind:
Designing City Macro Files
Redefining the macros that City.inc uses to construct the city allows you to extend the City Generator Include File in all sorts of ways. This documentation will only attempt to outline the required macro definitions and parameters.
As mentioned earlier, the City Generator Include File uses a left-hand coordinate system. All the coordinates passed to the following macros lie in the x-z plane, and no height data is determined by the include file or passed to the macros. Note that you only have to declare those macros which you want for a particular city construction.
Also, because the macros are called from City.inc any variables local to that file can be used in the macros (eg. street_width, building_width, city_corner1 & city_corner2, BlockSize, etc). You may also declare and use your own global variables (such as random-number seeds and height data) to allow the macros to support other parameters.
Note that the TEMPLATE.MCR file included with the City Generator includes all of the following macro definitions, along with simple object creation examples.
The copyright statements covering the City Generator Include File package can be found in the user documentation.
Further to those statements, any object or macro files created for use with the City Generator Include File remain entirely the property of the user or users who have created them. Responsibility for such files also remains with the authors of the files.
POV-RayTM and Persistence of VisionTM are registered trademarks of the POV-Ray TeamTM