要访问 ArcGIS CityEngine 中的教程工程,请打开 CityEngine,然后在主菜单中单击帮助 > 下载教程和示例。 在选择教程或示例后,系统会自动下载工程并将其添加到 CityEngine 工作空间。
在本教程中,您将学习如何分析建筑物立面图像,并将立面组件转换为 CGA。 您将探索如何创建一组 CGA 规则,以根据以下真实图像重新创建建筑物:
您将注意到本示例中切片和窗口布局的复杂模式,并且您将使用一些高级 CGA 机制(例如嵌套重复分割和参数传递)来创建建筑物。
有关 CGA 形状语法的详细信息,请参阅基于规则的建模教程以及基于规则的建模和 CGA 建模帮助主题。
探索建筑物
首先,通过执行以下操作,使用以上立面图像的 CGA 版本打开该场景:
- 在 Navigator 窗口中展开 Tutorial_09_Advnced_Shape_Grammar 教程文件夹。
- 打开 scenes 文件夹中的 Complex Patterns.cej 场景。
当系统询问您“是否要重新生成这些模型?”时,请单击是以显示建筑物:
定义立面布局
规划新的 CGA 规则时,在开始编写规则之前,勾勒出粗略的布局并定义一些形状名称十分有帮助。
执行立面分析
首先,在分析立面时,您将看到立面主要由三种楼层类型组成:顶层、地面和上层。 较低的楼层由包含窗口的切片构成,而顶层仅包含窗口元素。 其他所有较低的楼层都是相同的,因此您将传递带有 Floor 形状的索引 (floorIndex) 参数,以便为特定楼层创建正确的外观(切片和窗口对齐)。
由于切片的模式,您将定义一个中间的 DoubleTile 形状,其中包含两个 Tile 形状,对楼层模式进行编码后,这将非常有用。
定义子形状
接下来,您将在切片中定义详细的子形状。 它由两个主要部分组成:MilkGlass 和 Window 形状。 Window 形状包含顶部的 Blind 和一个嵌入的 Subwindow 形状。 这些元素的位置取决于切片在楼层上的水平位置,因此您需要将此位置索引 (tileIndex ) 存储为 Tile 形状的参数,以便能够正确放置子形状结构。
在 CGA 中创建建筑物体积
定义立面布局后,即可开始在 CGA 中创建建筑物。
添加属性、变量和资产
第一步是创建一个新规则,然后在规则文件的开头定义属性。 将在整个规则集中使用这些属性,并且可以在场景中对其进行修改,方法是使用检查器窗口调整属性和参数。 要开始创建规则,请执行以下操作:
- 单击新建 > CityEngine > CGA 规则文件。
- 单击下一步。
- 将该规则命名为 myComplexPatterns.cga。
- 单击完成。
系统随即创建一个新的 CGA 文件,并显示 CGA 编辑器窗口。 除了版本号之外,此为空文件。
- 在底部添加以下用户属性和一个注记为 @StartRule 的空规则:
// User Attribute @Group("Building", 1) @Range(min=5, max=40, restricted=false) @Distance attr buildingH = 27 // building height @Group("Facade", 2) @Range(min=3, max=6, restricted=false) @Distance attr floorH = 3.5 // floor height @Range(min=3, max=6, restricted=false) @Distance attr groundfloorH = floorH+1 // groundfloor height @Range(min=1, max=4, stepsize=1, restricted=false) attr nSymmetries = 2 @Range(min=0.1, max=1, restricted=false) @Distance attr borderwallW = 0.3 // width of border wall stripe @Range(min=0.1, max=0.8, restricted=false) @Distance attr ledgeH = 0.3 // ledge height @Group("Window",3) @Range(min=1, max=5, restricted=false) @Distance attr windowW = 2.5 // window width @Range(min=1, max=5, restricted=false) @Distance attr milkGlassW = windowW/2 // milkglass blend width @Range(min=0.1, max=2.5, restricted=false) @Distance attr blindH = 0.8 // blind height @Range(min=0.01, max=0.5, restricted=false) @Distance attr frameW = 0.07 // frame width @Group("Balcony",4) @Range(min=3, max=6, restricted=false) @Distance attr balconyDepth = 2 @Group("Colors",5) @Color attr brightblue = "#86b1c7" @Color attr darkblue = "#33556c" @Color attr red = "#5c3f40" @Color attr grey ="#6b7785" @Color attr white = "#ffffff" @StartRule Lot --> BuildingVolume
- 按 Ctrl+S 以保存规则文件。
- 选择模型并为其分配 myComplexPatterns.cga 规则。
- 在 @StartRule 上方添加附加变量和资产:
tileW = windowW + milkGlassW // total tile width const barDiameter = 0.04 // assets const cyl_v = "primitives/cylinder.vert.8.notop.tex.obj" const cyl_h = "primitives/cylinder.hor.8.notop.tex.obj" const window_tex = "facade/windows/1_glass_2_blue.tif" const milkGlass_tex = "facade/windows/blend_tex.png"
拉伸建筑物
该建筑物的实际创建从现在开始。 要拉伸建筑物,请执行以下操作:
- 可以使用 extrude 操作创建体量模型。 将顶层与主体分割,然后再次分割以创建退缩阳台:
BuildingVolume --> extrude(buildingH) split(y) { ~1 : MainPart | floorH : UpperPart } UpperPart --> split(z) { ~1 : TopFloor | balconyDepth : Balcony }
- 添加组件分割以将其应用于不同的体积部分,以便区分正面、侧面和顶面。 由此将触发 Facade、Wall 和 Roof 规则:
MainPart --> comp(f) { front : Facade | side : Wall | top : Roof. } TopFloor --> comp(f) { front : Floor(-1) | side : Wall | top : Roof. }
- 使用组件分割以调用 Railing 规则,将扶手放置在正面、左侧和右侧:
Balcony --> s(scope.sx-2*borderwallW, 1.1, scope.sz-borderwallW) center(x) comp(f) { front : Railing | left : Railing | right : Railing }
已设置阳台的尺寸。 接下来,您将向建筑物添加扶手。
- 保存规则。
确保已在视窗中选择建筑物。
- 单击生成 (Ctrl+G) 以生成建筑物:
添加楼层
要进一步细分正立面,请执行以下操作:
- 将立面分割为底层和重复的上层:
Facade --> split(y) { ~groundfloorH : Floor( split.index ) | { ~floorH : Floor( split.index ) }* }
首次分割借助重复分割 {...}* 将立面细分为底层部分和一组较高的楼层。 分割大小高度的波形符号 (~)(例如 ~groundfloorH)支持使用灵活高度,并确保匹配的楼层在立面上没有孔洞。 通过传递 split.index(代表楼层索引)作为参数,您之后可以触发特定楼层要素。
- 对于每个楼层,通过在 x 方向进行简单的分割,可以在两侧创建狭窄的墙壁区域:
Floor(floorIndex) --> split(x) { borderwallW : Wall | ~1 : FloorSub(floorIndex) | borderwallW : Wall }
- 根据以下要求,可以使用水平分割命令为每个楼层添加特殊水平元素:
- 较高的楼层仅有顶部窗台。
- 顶层没有其他元素,可以直接触发 TileRow 形状。
- 再次分配楼层索引作为 TileRow 形状的参数,因为您将在稍后的规则中再次使用该楼层索引。
FloorSub(floorIndex) --> case floorIndex == 0: split(y) { 1 : Wall | ~1 : TileRow(floorIndex) | ledgeH : Wall } case floorIndex > 0: split(y) { ~1 : TileRow(floorIndex) | ledgeH : Ledge } else: TileRow(floorIndex)
- 保存规则并生成建筑物:
添加切片
现在您要将楼层分割为切片。 对于顶层而言,没有特殊的模式,仅包含重复的窗口元素。 要稍后处理这些切片,请使用 -1 参数对其进行标记。
- 要为主要楼层创建特殊的重复模式,请创建 DoubleTile 中间形状:
TileRow(floorIndex) --> case floorIndex == -1: split(x) { ~windowW : Tile(-1) }* else: split(x) { ~tileW*nSymmetries : DoubleTile(floorIndex, split.index) }*
要在后面的步骤中正确地对齐窗口元素,您将需要楼层和切片索引 (split.index),其将作为参数传递。
- 添加两个具有重复分割的规则以获得 MilkGlass 和 Tile 形状的不同位置:
DoubleTile(floorIndex, tileIndex) --> case tileIndex%2 + floorIndex%2 == 1: split(x) { ~milkGlassW : MilkGlass | ~windowW : Tile(tileIndex) }* else: split(x) { ~windowW : Tile(tileIndex) | ~milkGlassW : MilkGlass }*
楼层和切片索引的组合确定了双切片内窗户的对齐方式。
- 为将来的窗口纹理设置纹理坐标:
Tile(tileIndex) --> setupProjection(0, scope.xy, scope.sx, scope.sy) split(x) { frameW : Frame Bracing | ~1 : split(y) { frameW : Frame | ~1 : Window(tileIndex) | frameW : Frame | blindH : Blind | frameW : Frame } | frameW : Frame Bracing }
然后将整个 Tile 形状水平分割为窗框和中间部分。 再次分割中心部分,这次是垂直分割为框架、窗口、框架、百叶窗和框架元素。
- 保存并生成:
添加窗口
要向建筑物添加窗口,请执行以下操作:
- 对于 Window 形状,DoubleTile 的切片索引用于确定子窗口的位置。
Window(tileIndex) -->
- 在窗口的左半部分放置右对齐子窗口:
case tileIndex%nSymmetries >= 1: split(x) { ~1 : Subwindow("right") | frameW : Frame | ~1 : Glass }
- 在窗口的右半部分放置左对齐子窗口:
case tileIndex%nSymmetries >= 0: split(x) { ~1 : Glass | frameW : Frame | ~1 : Subwindow("left") }
- 使用代表顶层窗口的 -1 切片索引以创建不含子窗口的窗口。
else: split(x) { ~1 : Glass | frameW : Frame | ~1 : Glass }
- 使用左参数和右参数,将 RedWindow 放置在正确的位置:
Subwindow(align) --> case align == "left": split(x) { ~3 : RedWindow | ~2 : Glass } else: split(x) { ~2 : Glass | ~3 : RedWindow }
- 添加规则,为 RedWindow 形状创建框架和玻璃元素:
RedWindow --> split(x) { frameW : RedFrame | ~1 : split(y) { frameW : RedFrame | ~1 : RedGlass | frameW : RedFrame } | frameW : RedFrame } RedGlass --> split(y) { ~1 : Glass | frameW/2 : t(0,0,-frameW) Frame | ~1 : t(0,0,-frameW) Glass }
- 保存并生成:
添加材料
要将颜色和纹理应用于建筑物,请执行以下操作:
- 定义立面元素的颜色、拉伸和平移:
Wall --> color(darkblue) Blind --> color(grey) Frame --> extrude(frameW) color(white) RedFrame --> t(0, 0, -frameW) extrude(frameW*4) color(red)
- 对当前形状几何应用纹理坐标,并分配纹理和颜色:
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 --> s('1, '1, frameW*1.2) primitiveCube color(brightblue) setupProjection(0, scope.xy, scope.sx, scope.sy, 0, 0, 0) 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)
- 保存并生成:
添加详细信息
最后,要向元素添加细节,请执行以下操作:
- 通过添加后墙元素、具有深度的立方体和第二个作为盖板的薄立方体来优化楼层窗台:
Ledge --> Wall [ s('1, '0.9, 0.2) primitiveCube Wall ] t(0, -0.1, 0.2) s('1, scope.sy+0.1, 0.03) primitiveCube Wall
- 通过使用浮动分割宽度进行重复分割,垂直条块可均匀分布:
Railing --> [ t(0,scope.sy-barDiameter/2,0) HBar ] set(trim.vertical, false) split(x) { ~tileW/3 : VBar }*
插入了水平条块以创建扶手的水平部分。 通过禁用垂直修剪,可以防止垂直角条块被切割。
- 插入圆柱资产以创建垂直条块和水平条块:
VBar --> s(barDiameter, '1, barDiameter) t(0, 0, -barDiameter) i(cyl_v) color(white) HBar --> s('1, barDiameter, barDiameter) t(0, 0, -barDiameter) i(cyl_h) color(white)
- 窗口的支撑由顶部和底部固定装置以及中间的垂直条块组成。 对于固定装置,插入一个立方体,并且 VBar 将触发圆柱资产:
Bracing --> s(barDiameter, '1, 0.15) center(x) primitiveCube split(y) { 0.01 : Wall | ~1 : t(0, 0, 0.15) VBar | 0.01 : Wall }
- 保存并生成:
添加了细节元素(包括窗台、窗撑和扶手)的最终模型:
现在您已经有了最终模型,请将规则应用于不同的地块形状,或者尝试使用检查器窗口中的用户属性来修改立面设计。
添加样式
您可以使用样式关键字来定义用于重新定义某些属性的新样式。
- 在规则文件底部,通过重新定义颜色属性向模型添加样式:
@Description("A Variation in Red") style Red_Color_Theme attr brightblue = "#FF8080" attr darkblue = "#D20000" attr grey = "#ECCACA" attr red = "#361B1B"
- 保存规则文件。
- 在检查器窗口中,单击样式管理器下拉菜单中的 Red_Color_Theme:
已应用 Red_Color_Theme 样式:
要查看最终的规则文件,请打开 complexpatterns_01.cga 规则。
坎德勒大楼
坎德勒大楼是 CGA 如何通过程序创建逼真的建筑物的一个很好的示例。 要探索 CGA,请执行以下操作:
- 打开 Candler Building.cej 场景。
- 双击导航窗口中的 Candler Building.cga 文件,然后探索用于创建坎德勒大楼的 CGA 规则。
巴台农神庙
最后,要探索巴台农神庙,请执行以下操作:
- 打开 Parthenon.cej 场景。
- 再次双击 parthenon.cga 文件以查看巴台农神庙背后的规则:
在本教程中,您学习了如何执行以下操作:
- 获取并分析图像,并将其拆分为 CGA 组件。
- 添加元素,如窗户、瓷砖和材料。
- 探索更复杂的高级形状语法示例。
要继续学习 CityEngine,请参阅完整的 CityEngine 教程目录。