Customizing Rule Files, and Why Coding Ability is Important

 “The ultimate goal for the Redlands Example is to provide a set of rules that require little to no coding ability for use within other CityEngine projects.”  

An important point. What does it mean? That you can use the .cga rule files from the Redlands Example to point and click your way to happiness and productivity on your own work, using the controls in the Shape Inspector.  But as we codeheads know, it’s not always that easy. As good as some products are off-the-rack, the ability to customize is critical to make things work the way we want them to.

In this installment, I’m using rule files from ESRI’s CityEngine Example, Redlands Redevelopment 2016.0. Download the example by going to Help > Download Tutorials and Examples.

Open the Redlands Redevelopment 64bit.cej scene, select one of the green parcels and experiment with the Scene Inspector controls. Under Model Options, work with the “Green_Space_Type” control and explore the differences between “Formal” and “Natural”.

Here’s my issue: I’m working on a model that needs large green grass areas without trees, but as you can see in the transect diagram above, “Formal” and “Natural” don’t fit the bill.

  • “Formal” would work, except it won’t let me get rid of the paved pathways (T1).
  • “Natural” has a mottled texture that won’t work when I take away the trees (T2, T3).
  • The Shape Inspector controls aren’t configured to work for “Natural”, so I can’t change the grass type.

So, I will have to go under the hood and modify code to get what I want.

Let’s do some code analysis. Green spaces are created using the Greenspace Construction.cga rule file. In the rules/3D_City_Design_Rules folder, open the Greenspace Construction.cga and Support/Greenspace Rules.cga code files.  Put them side by side on your screen, because we’ll be bouncing back and forth between the two.

  • In Greenspace Construction.cga, the rule file Greenspace Rules.cga is imported at the top of the page using the alias Greenspace_Rules (with an underscore between words). This is where we’ll begin.

In Greenspace Rules.cga, look for the Start Rule named GreenSpace. We go through several permutations of this rule and are led to GreenSpaceStep2. From here, read your way through the rule path:

GreenspaceType > NaturalSpace > Park > ParkTexture > ParkTextureStep2

ParkTextureStep2 -->
setupProjection(0, scope.xz, scope.sx, scope.sz)
projectUV(0)
offsetUV(0,rand(1), rand(1))
# Here is where our texture image file is named
texture(materialDirectory + "Grass/Park.jpg")

# Let's change the texture file:
texture(materialDirectory + "Grass/Grass Thick.jpg")
# Note: there is a space between Grass and Thick.jpg, which does not thrill me.
# Using no space or an underscore _ character in between is preferable.

The problem now is that our grass looks like a forest, as seen in the center section. What we want is scale down the texture image to get the look on the right. The Grass_Scale control in the Shape Inspector won’t work because the texture dimensions in the setupProjection operation are the same size as the shape (the scope.sx and scope.xz dimensions).

Time to modify the code.

Neither “Formal” and “Natural” will work, so I’m going to create another option called “Lawnscape”.  The Shape Inspector controls are configured in the Greenspace Construction.cga file. The control we are looking for is first in the Greenspace Attributes section:

################################################################
## GREENSPACE ATTRIBUTES
##

@Group("MODEL OPTIONS",0) @Order(1)
@Range("Formal","Natural")
attr Green_Space_Type = "Formal"

# I'll add my new Green_Space_Type option:
@Range("Formal","Natural","Lawnscape")

Now we’ll go back to Greenspace Rules.cga. and to the point where we start making decisions based on Greenspace type,

GreenspaceType -->
case Green_Space_Type == "Formal" : OpenSpace
else : NaturalSpace

Here, we are calling out an exception for the “Formal” type.  Our new type fits the “else” condition, so I won’t change the code here. Instead, let’s follow the rule path to NaturalSpace > Park > ParkTexture. At the end of this rule, the shape is passed along to ParkTextureStep2, which is where the texture is applied. So let’s intervene here and create a new path option using some conditional logic:

# Here is the original rule
ParkTexture -->
scatter(surface,People_Percentage * 0.0025 * geometry.area,uniform) { Human(rand(360)) }
ParkTextureStep2

#Here is the modified rule
ParkTexture -->
scatter(surface,People_Percentage * 0.0025 * geometry.area,uniform) { Human(rand(360)) }
ParkTextureStep

#This new rule is needed to execute the case/else statement
ParkTextureStep -->
case Green_Space_Type == "Natural" : ParkTextureStep2
else : ParkTextureLawnscape


# NOW note the difference between the existing ParkTextureStep2 rule
# and our new ParkTextureLawnscape rule

ParkTextureStep2 -->
case texturingOn:
setupProjection(0, scope.xz, scope.sx, scope.sz)
projectUV(0)
offsetUV(0,rand(1), rand(1))
texture(materialDirectory + "Grass/Grass Thick.jpg")
ParkRainfall 
else:
ParkRainfall

ParkTextureLawnscape -->
case texturingOn:
setupProjection(0, scope.xz, 15*Grass_Scale, 15*Grass_Scale) projectUV(0)
projectUV(0)
offsetUV(0,rand(1), rand(1))
texture(materialDirectory + "Grass/Grass Thick.jpg")
ParkRainfall 
else:
ParkRainfall

To enable use of the Grass_Scale control, we took the setupProjection operation from the Lawn Rule that is used for Formal green spaces and copied it into the new ParkTextureLawnscape rule. I’ve modified the cga files to get the look I want, and if I want to, I can still use the controls to add trees and people.

Leave a Reply

Your email address will not be published. Required fields are marked *