Tutorial 9_ Advanced shape grammar—ArcGIS CityEngine Resources _ Documentation
Tutorial 9_ Advanced shape grammar—ArcGIS CityEngine Resources _ Documentation
2024.12024.02023.12023.02022.12022.02021.1
To access the tutorial projects in ArcGIS CityEngine, open CityEngine and click Help > Download Tutorials and Examples in the main menu. After
choosing a tutorial or example, the project is automatically downloaded and added to your CityEngine workspace.
In this tutorial, you'll learn how analyze a building facade image and translate the facade components into CGA. You'll explore how to create a set of CGA
rules to re-create a building from the real-world image below:
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 1/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
You'll notice the complex patterns of the tile and window layout in this example, and you'll use some advanced CGA mechanisms, such as nested repeat
splits and parameter passing to create the building.
To learn more about CGA shape grammar, see the Rule-based modeling tutorial, and the Rule-based modeling and CGA modeling help topics.
Click Yes when asked "Would you like to regenerate these models?" to display the building:
First, when you analyze the facade, you'll see the facade consists mainly of three floor types: top, ground, and upper. The lower floors are made of tiles
containing windows, whereas the top floor contains only window elements. Every other lower floor is identical, so you'll pass the index (floorIndex)
parameter with the Floor shape to create the correct look (tile and window alignment) for a specific floor.
Due to the pattern of the tiles, you'll define an intermediate DoubleTile shape, which contains two Tile shapes, and is helpful once you encode the floor
patterns.
Define subshapes
Next, you'll define the detailed subshapes in a tile. It consists of two main parts: the MilkGlass and Window shapes. The Window shape contains a Blind
on the top and an embedded Subwindow shape. The position of these elements depends on the horizontal position of the tile on the floor, so you'll
need to store this position index ( tileIndex) as a parameter of the Tile shape to be able to place the subshape structure correctly.
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 3/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
The first step is to create a new rule and then define attributes at the beginning of the rule file. These attributes are used through the entire rule set, and
they can be modified in the scene, by adjusting the attributes and parameters using the Inspector window. To start creating the rule, do the following:
A new CGA file is created, and the CGA Editor window appears. It's empty except for the version number.
5. Add the following user attributes and an empty rule annotated as @StartRule at the bottom:
// User Attribute
attr nSymmetries = 2
attr balconyDepth = 2
@Group("Colors",5)
@Color
@Color
@Color
@Color
@Color
@StartRule
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 4/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
6. Press Ctrl+S to save the rule file.
7. Select the model and assign the myComplexPatterns.cga rule to it.
Notice that annotations such as @Group or @Range were added to the attributes to control their appearance in the Inspector window:
// assets
The actual creation of the building starts now. To extrude the building, do the following:
1. Create the mass model with the extrude operation. The top floor is split from the main part and split again to create the set-back balcony:
BuildingVolume -->
extrude(buildingH)
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 5/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
split(y) { ~1 : MainPart
| floorH : UpperPart }
UpperPart -->
split(z) { ~1 : TopFloor
| balconyDepth : Balcony }
2. Add component splits to apply them to the different volume parts to distinguish the front, side, and top faces. This triggers the Facade, Wall, and
Roof rules:
MainPart -->
| side : Wall
| top : Roof. }
TopFloor -->
| side : Wall
| top : Roof. }
3. Use a component split to call the Railing rule to place the railing on the front, left, and right faces:
Balcony -->
center(x)
| left : Railing
| right : Railing }
The dimensions of the balcony are set. Next, you'll add the railing to the building.
Add floors
To subdivide the front facade further, do the following:
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 6/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
Facade -->
The first split subdivides the facade into a ground floor part and a set of upper floors with the help of a repeating split {...}*. The tilde sign (~)
before the split size height, such as ~groundfloorH, allows a flexible height and ensures matching floors without holes in the facade. By passing
the split.index, (which represents the floor index) as a parameter, you can later trigger specific floor features.
2. Create the narrow wall area on both sides with a simple split in the x-direction for every floor:
Floor(floorIndex) -->
| ~1 : FloorSub(floorIndex)
| borderwallW : Wall }
3. Add special horizontal elements for every floor with the horizontal split commands using the following requirements:
FloorSub(floorIndex) -->
case floorIndex == 0:
split(y) { 1 : Wall
| ~1 : TileRow(floorIndex)
| ledgeH : Wall }
split(y) { ~1 : TileRow(floorIndex)
| ledgeH : Ledge }
else:
TileRow(floorIndex)
Add tiles
You'll now split the floors into tiles. For the top floor, there is no special pattern, only repeating window elements. To address these tiles later, you mark
them with the -1 parameter.
1. To create the special repeating pattern for the main floors, create the intermediate DoubleTile shape:
TileRow(floorIndex) -->
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 7/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
else:
To align the window elements correctly in a later step, you'll need the floor and the tile indexes (split.index), which you'll pass as parameters.
2. Add two rules with repeating splits to obtain different placements of the MilkGlass and Tile shapes:
| ~windowW : Tile(tileIndex) }*
else:
| ~milkGlassW : MilkGlass }*
The combination of the floor and tile indexes determines the alignment of the windows within the double tile.
Tile(tileIndex) -->
| ~1 : Window(tileIndex)
| frameW : Frame
| blindH : Blind
| frameW : Frame }
The entire Tile shape is then split horizontally into window frames and the center part. The center part is again split, this time vertically, into the
frame, window, frame, blind, and frame components.
Add windows
To add windows to the building, do the following:
1. For the Window shape, the tile index of the DoubleTile is used to determine the position of the sub-windows:
Window(tileIndex) -->
split(x) { ~1 : Subwindow("right")
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 8/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
| frameW : Frame
| ~1 : Glass }
split(x) { ~1 : Glass
| frameW : Frame
| ~1 : Subwindow("left") }
4. Use the -1 tile index, representing the top floor windows, to create windows without sub-windows:
else:
split(x) { ~1 : Glass
| frameW : Frame
| ~1 : Glass }
5. Using the left and right parameters, the RedWindow is placed in the correct location:
Subwindow(align) -->
split(x) { ~3 : RedWindow
| ~2 : Glass }
else:
split(x) { ~2 : Glass
| ~3 : RedWindow }
6. Add the rule to create the frame and glass elements for the RedWindow shape:
RedWindow -->
| ~1 : RedGlass
| frameW : RedFrame }
| frameW : RedFrame }
RedGlass -->
split(y) { ~1 : Glass
| ~1 : t(0,0,-frameW) Glass }
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 9/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
Add materials
To apply color and texture to the building, do the following:
Wall -->
color(darkblue)
Blind -->
color(grey)
Frame -->
extrude(frameW)
color(white)
RedFrame -->
t(0, 0, -frameW)
extrude(frameW*4)
color(red)
2. Apply texture coordinates to the current shape geometry and assign texture and color:
Glass -->
projectUV(0)
texture(window_tex)
color(white)
set(material.specular.r, 0.4)
set(material.specular.g, 0.4)
set(material.specular.b, 0.4)
set(material.shininess, 4)
set(material.reflectivity, 0.3)
MilkGlass -->
primitiveCube
color(brightblue)
texture(milkGlass_tex)
projectUV(0)
set(material.specular.r, 0.7)
set(material.specular.g, 0.7)
set(material.specular.b, 0.7)
set(material.shininess, 20)
set(material.reflectivity, 0.05)
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 10/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
Add details
Finally, to add details to the elements, do the following:
1. Refine the floor ledges by adding a back wall element, a cube to give it some depth, and a second thin cube that serves as a cover plate:
Ledge -->
Wall
primitiveCube
Wall
2. The vertical bars are evenly distributed with the help of a repeat split with a floating split width:
Railing -->
[ t(0,scope.sy-barDiameter/2,0) HBar ]
set(trim.vertical, false)
A horizontal bar is inserted to create the horizontal part of the railing. By disabling vertical trimming, the vertical corner bars are prevented from
being cut.
VBar -->
t(0, 0, -barDiameter)
i(cyl_v)
color(white)
HBar -->
t(0, 0, -barDiameter)
i(cyl_h)
color(white)
4. The bracing of the windows consists of top and bottom mountings and a vertical bar in the middle. For the mountings, insert a cube and have the
VBar trigger the cylinder asset:
Bracing -->
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 11/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
center(x)
primitiveCube
| 0.01 : Wall }
The final model appears with detail elements including ledges, window bracings, and railings added:
Now that you have the final model, apply the rule on different lot shapes, or experiment with the user attributes in the Inspector window to modify your
facade design.
Add styles
You can use the style keyword to define a new style that redefines some attributes.
1. At the bottom of the rule file, add a style to the model by redefining the color attributes:
style Red_Color_Theme
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 12/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
Candler Building
The Candler building is a great example of how CGA can create realistic buildings procedurally. To explore the CGA, do the following:
Parthenon temple
Finally, to explore the Parthenon temple, do the following:
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 13/14
15/05/2025 11:00 Tutorial 9: Advanced shape grammar—ArcGIS CityEngine Resources | Documentation
2. Again, double-click the parthenon.cga file to see the rules behind the Parthenon Temple:
To continue your learning with CityEngine, see the complete CityEngine tutorial catalog.
https://doc.arcgis.com/en/cityengine/2023.1/tutorials/tutorial-9-advanced-shape-grammar.htm 14/14