[006] Understanding the Basic Concepts of Procedural Modeling in CityEngine
Explore Model Hierarchy in CityEngine to Design Dynamic and Flexible Rule-Based Structures
In this tutorial, you will explore the fundamental differences between traditional 3D modeling and CityEngine's Procedural Modeling. By understanding the concept of Model Hierarchy, you will learn how to design flexible, rule-based structures that automatically adapt to changes in geometry and parameters.
Suppose you are modeling the building below using a traditional 3D program.
Traditional 3D programs (like 3ds Max or Blender) do not enforce a strict workflow order. You can create walls, windows, and floors separately and place them wherever indicated on the blueprint without any issues. There is no predetermined rule about what must be built first.
Using the building photo above as an example, traditional modeling would result in a structure like the diagram below.
In this scenario, each object has no relational connection with the others. They are simply fixed in their designated spatial coordinates.
What if you want to add another window to the 3rd floor? You would simply copy an existing window and place it, making sure it doesn't float outside the building. What if you want to add another floor? You stretch the wall polygons upward, copy a row of windows, and manually position them again.
A wall is just a wall, a door is just a door, and a window is just a window. Changes to one object do not affect the others. If the building's overall width changes, the windows won't automatically recalculate their spacing or count. If you reduce the number of floors, the windows floating in the removed space won't delete themselves.
Simply put, every object is completely independent.
The Concept of Procedural Modeling
So, what exactly is Procedural Modeling in CGA (Computer Generated Architecture)?
If we represent that same building using a procedural modeling workflow, the diagram looks entirely different, as shown below.
The objects aren't floating independently; they maintain a strict, nested hierarchy. Unlike independent objects, each element contained within the main structure (the wall/facade) can dynamically influence its lower-level components and reflect structural changes automatically.
Verifying the Hierarchy in CityEngine
Let's verify this by examining the hierarchy of a model generated entirely by CGA code.
Open CityEngine, create a new project, a new scene, and a new rule file. Set up your 3D View as shown below. Today, you can draw the building footprint slightly larger.
Please draw a rectangle footprint roughly 20m wide and 10m deep.
Now, apply the following CGA code. You do not need to type the comments (the text after `#`).
attr floor_Height = 3 # Initial floor height
attr floor_Count = 3 # Initial number of floors
Lot -->
extrude(y, floor_Count * floor_Height)
# Extrude the footprint upwards by total height
Facade
Facade -->
split(y){ ~floor_Height: Floor(split.index) }*
# Split the facade vertically by floor height
# and pass the index to the Floor rule
Floor(idx) -->
case idx == 0:
# Ground Floor: 3m wide windows repeating
split(x){ ~1: Wall | 3: Window | ~1: Wall }*
case idx < split.total - 1:
# Middle Floors: 1m wide windows repeating
split(x){ ~1: Wall | 1: Window | ~1: Wall }*
else:
# Top Floor: A large panoramic window taking 60% of the width
split(x){ ~1: Wall | ~0.6: Window | ~1: Wall }
Wall -->
color(0.5, 0.5, 0.5) # Gray walls
Window -->
color(0, 0, 1) # Blue windows
Don't obsess over the specific syntax of this code just yet; it's a rough draft designed strictly to demonstrate the concept of hierarchy.
If you apply this rule file to your drawn shape and it looks like the image below, you have succeeded.
In the Inspector panel, try changing the floor height and floor count to see if the building updates correctly.
Testing the Hierarchical Response
If the attributes apply correctly, let's observe what happens when the building's physical width changes.
Click the Scale button on the top toolbar (or press 'S') and select your object. You will see three axes inside the model. Grab the red cube (X-axis) and drag it left and right to stretch the building.
Notice what happens? As the width changes, the number of windows automatically increases or decreases on the lower floors, and the proportional width of the top-floor panoramic window adjusts dynamically.
This is the absolute advantage of procedural modeling: dependency allows higher-level spatial changes to automatically cascade down and re-evaluate lower-level components.
Exploring the Model Hierarchy Panel
Now, let's look beneath the hood and examine the exact hierarchical relationship of the object we just created.
From the top menu bar, select Window -> Model Hierarchy.
You will see the Model Hierarchy panel appear, usually next to the Inspector. Click the 'Inspect model' button at the top of this panel and click on your building model in the viewport.
Right-click anywhere inside the blank space of the Model Hierarchy panel and select 'Expand All'.
The entire tree structure will unfold, displaying the DNA of your procedural building.
Notice how perfectly this matches the theoretical diagram I showed you earlier? (If there are too many branches to see clearly, simply scale your building width down and check again). Each named Rule from our CGA code (Lot, Facade, Floor, Wall, Window) becomes a structural node in this tree.
Here is the brilliant part: if you click a specific rule in this tree structure, the corresponding geometry in the 3D View and the specific line in the CGA code editor will be highlighted simultaneously.
Conversely, if you select a specific window or wall directly on the 3D model, CityEngine traces it back, showing you exactly where that part exists within the hierarchy tree and which line of code generated it. This is how professionals debug, understand, and refine complex code.
Limitations and Python Integration
This requirement for hierarchical thinking is exactly why I advise against jumping straight into writing code. If you want to model something, find a reference photo first. Practice sketching out the tree structure on paper—subdividing the asset step-by-step—before typing a single line. This planning makes coding exponentially easier.
Of course, CGA's procedural modeling has its limitations. Because it relies on top-down subdivision logic, a shape generally cannot access the information of a model generated from a different neighboring shape. Furthermore, you cannot natively pass information from a lower leaf node back up to a parent node.
A frequent question on the Esri Community forums is: "I want to determine the window shape of my current building by referencing the window shape of the adjacent model. How can I do this?"
The answer is always the same: "CGA cannot reference the attributes of other independent shapes natively. You must use a Python script."
CityEngine provides a powerful Python interface to globally access and manipulate shapes, models, and attributes across the entire scene.
Once you hit the boundaries of pure CGA, you will naturally find yourself needing to learn Python. For a glimpse into this, you can look forward to future lessons like [120] How to Apply Rules to Shapes Using Python Scripts in CityEngine.
Next Steps
Let's take a break from these heavy, headache-inducing theoretical concepts. Next, we will look at one of the most highly requested, practical out-of-the-box features in CityEngine.
In Lecture [007], we will cover Viewshed Creation (Visibility Analysis).
If you have any questions, please leave a comment. Let's solve them together!
- Learn previous workflow in [005] Create Adjustable 3D Building Models
- Continue learning with [007] Viewshed Analysis (Viewshed Creation)
Comments
Post a Comment
Feel free to leave a comment if you have any questions about Global Mapper or CityEngine. I will get back to you with a sincere response as soon as possible. (Please note that all comments are moderated and manually approved to maintain a high-quality community. Promotional or spam content will not be published.)