教程 8:体量建模

要访问 CityEngine 中的教程,请单击帮助 > 下载教程和示例。 在选择教程或示例后,系统会自动下载工程并将其添加到您的工作空间。

添加 L 和 U 形状

设置

在此工作流中,您将使用形状语法创建建筑物的体量模型,包括典型的建筑体积形状,例如 L 和 U 体量。

  1. Tutorial_08_Mass_Modeling 工程导入您的 CityEngine 工作空间。
  2. 打开 MassModeling_01.cej 场景。

创建规则文件

要创建规则文件,请完成以下步骤:

  1. 单击文件 > 新建 > CityEngine > CGA 规则文件
  2. 确保正确设置了容器 (Tutorial_08_Mass_Modeling/rules),将文件命名为 myMass_01.cga,然后单击完成

    系统随即创建一个新的 CGA 文件,并显示 CGA 编辑器窗口。

添加 L 形状

首先,您将使用简单的 L 形状。

attr height = rand(30, 60)
attr wingWidth = rand(10, 20)

Lot --> LShape

LShape -->
    shapeL(wingWidth, wingWidth) { shape : LFootprint }

LFootprint --> extrude(height) Mass

LotInner --> OpenSpace

shapeL 命令将创建 L 形状的覆盖区,尺寸范围在 10 到 20 之间。 然后,第二个 LFootprint 规则将 L 形状拉伸到其高度。

LotInner 将应用 OpenSpace,将地块形状保持原样。

注:

属性的注记可选(例如 @Group 或 @Range),用于控制属性在检查器窗口中的显示。 有关 CGA 注记的详细信息,请参阅 CGA 参考。

现在,您将规则应用于地块。

  1. 场景编辑器窗口中选择 Lots 图层。
  2. 单击形状 > 分配规则文件
  3. 从规则目录中选择 myMass_01.cga 规则文件,然后单击确定

生成建筑物

要生成建筑物,请完成以下步骤:

  1. 请在 3D 视窗中选择一些地块。
  2. 单击形状 > 生成或按 Ctrl+G 生成建筑物。
  3. 简单拉伸 L 形状体积
    小型城市部分上的简单 L 形状

    L 形体量模型十分有用,但外观不具有说服力。 您需要更多变化。

改变 L 形状

当前的 L 形状侧翼始终位于主体量的左侧。 使用 rotateScope,您也可以将 L 形状更改为在右侧。

使用概率运算符 % 更改 LShape 规则中的红线,以优化 L 形状,使其侧翼位于左侧或右侧。

LShape -->
    50% : shapeL(wingWidth, wingWidth) { shape : LFootprint }
    else : rotateScope(0, 90, 0) 
    			shapeL(wingWidth, wingWidth) { shape : LFootprint }

使用 convexify 命令,您可以将 L 形状分割为两翼,并更改两翼的高度。 同样,您将使用随机概率来添加变化。

LFootprint -->
    75% : extrude(height) Mass
    else : convexify comp(f) { 0 : extrude(height) Mass | 
    			all : extrude(height * 0.7) Mass }

可变 L 形状

现在,侧翼出现在左侧和右侧,并且高度有所不同。 现在,您需要其他形状。

添加 U 形状

接下来,您将添加 U 形状。 在初始 Lot 规则中,调用 UShape 而非 LShape

Lot --> UShape

同样,您将使用 shapeU 命令。

UShape -->
    shapeU(wingWidth, wingWidth * 0.7, wingWidth * 0.7) 
    			{ shape : UFootprint }

UFootprint --> extrude(height) Mass

同样添加一些变化。

UShape -->
    80% : rotateScope(0, 180, 0) shapeU(wingWidth, wingWidth * 0.7, 
    		wingWidth * 0.7) { shape : UFootprint }
    else:  shapeU(wingWidth, wingWidth * 0.7, wingWidth * 0.7) 
    		{ shape : UFootprint }
可变 U 形状

在生成的图像中,您会看到 U 形状并非在所有地块上都适用。 您将在下一部分中对此进行更正。

L 和 U 形状组合

高度分布并不令人信服。 为了更好地控制建筑物的高度,您需要在高度属性中添加一个条件。 只有大面积的地块才允许创建高层建筑物。

attr height = 
    case geometry.area < 1000: rand(20, 50)
    else: rand(50, 150)

您将添加一个新规则 LUShapes,以控制在哪些地块上创建哪个形状。

U 形状最适用于宽度大于深度的地块,或使用 CGA 语言,即 scope.sx 大于 scope.sz 的地块。 此外任何情况下,您只会触发 L 形状。

Lot --> LUShapes
LUShapes -->
    case scope.sx > scope.sz : 
        60%  : UShape
        else : LShape
    else: LShape

L 形状和 U 形状都不适用于非矩形地块。 下一个 case 语句确保 UShapeLShape 仅在近似矩形地块(公差为 15 度)上创建。 否则,您将调用新的覆盖区规则。

LUShapes -->
    case geometry.isRectangular(15):
        case scope.sx > scope.sz : 
            60%  :UShape
            else : LShape
        else: LShape
    else: BasicFootprint

与 L 形状和 U 形状相比,拉伸地块形状会太大。 因此,您需要向 BasicFootprint 添加负偏移。 这还将在各个建筑物之间留出更多空间。

BasicFootprint --> offset(-5,inside) extrude(height) Mass

L 和 U 形状组合

在下一部分中,您将学习如何在形状语法中使用递归进行体量建模。

使用递归进行质量建模

设置

在此工作流程中,您将使用递归形状语法调用对重复的建筑物元素进行建模。

如果尚未打开 MassModeling_01.cej 场景,请打开该场景。

创建规则文件

要创建规则文件,请完成以下步骤:

  1. 单击新建 > CityEngine > CGA 语法文件
  2. 确保正确设置了容器 (Tutorial_08_Mass_Modeling/rules),将文件命名为 myMass_02.cga,然后单击完成

塔形状

属性 height 为建筑物高度创建一个随机值。 起始规则 Lot 称为 Envelope,用于将覆盖区拉伸到塔形包络。 Envelope 调用递归规则。

height = 
    case geometry.area > 1000: rand(50, 200) 
    else: rand(20, 50)

Lot --> Tower

Tower --> extrude(height) Envelope
	
Envelope --> RecursiveSetbacks

对于后续的递归规则,您需要两个其他变量:lowHeightscale。 后者对于建筑物来说需是常量,因此将其定义为属性。

// switching between these two values creates visually appealing setbacks:
lowHeight 	= 50%: 0.4 else: 0.6	

// has to be constant:
attr scale 	= rand(0.75, 0.9)

只要体量高于两层楼,RecursiveSetbacks 规则就会将其分割为相对高度为 lowHeight 的较低部分体量。 其余较高部分将生成 Setback 形状。

如果 RecursiveSetbacks 形状小于两层楼,则其余部分的高度将设置为 floorheight,并生成 Mass 形状。

attr floorheight = rand(4, 5)

RecursiveSetbacks -->
    case scope.sy > 2 * floorheight  :
        split(y){ 'lowHeight : Mass | ~1: Setback }
    else: 
        s('1, floorheight, '1) Mass

Setback 规则将形状缩放并居中,然后递归调用 RecursiveSetbacks 规则。

Setback -->
    s('scale, '1, 'scale) center(xz) RecursiveSetbacks

现在,请将规则应用于地块。

  1. 场景编辑器窗口中选择 Lots 地块图层。
  2. 单击形状 > 分配规则文件
  3. 从规则目录中选择 myMass_02.cga 规则文件,然后单击确定

生成建筑物

要生成建筑物,请完成以下步骤:

  1. 请在 3D 视窗中选择一些地块。
  2. 单击形状 > 生成或按 Ctrl+G 生成建筑物。
  3. 使用递归形状语法调用生成的模型

Round 形状

您可以使用外部圆柱资产创建递归塔的圆形版本。 修改 Tower 规则,如下所示:

Tower --> extrude(height) Envelope

Envelope -->
    case geometry.isRectangular(20):
        20% : i("cyl.obj") RecursiveSetbacks	
        else: RecursiveSetbacks
    else: RecursiveSetbacks

在全部 20% 的塔中,您将插入圆柱资产,而非使用隐式立方体作为基础形状。

圆柱资产与隐式立方体的比较

矩形和圆形混合递归塔

在下一部分中,您将使用退缩尺度来修改地块。

使宗地适应退缩尺度

教程设置

在本部分中,您将对地块形状应用退缩尺度。

如果尚未打开 MassModeling_01.cej 场景,请打开该场景。

创建规则文件

要创建规则文件,请完成以下步骤:

  1. 单击新建 > CityEngine > CGA 语法文件
  2. 确保正确设置了容器 (Tutorial_08_Mass_Modeling/rules),将文件命名为 myMass_03.cga,然后单击完成

街道退缩尺度

Parcel 规则会对地块的所有街道两侧应用退缩,并将该区域转至 OpenSpace 规则。 远离街道两侧的内部部分将转至 Footprint,并将拉伸到随机高度。

attr height = 
    case geometry.area > 1000: rand(50, 200) 
    else: rand(20, 50)

attr distanceStreet = 
    20%: 0
    else: rand(3, 6)


Lot --> Parcel
LotInner --> OpenSpace

Parcel --> 
    setback(distanceStreet)
        { street.front: OpenSpace 
        | remainder: Footprint }

Footprint --> extrude(height)

OpenSpace --> color("#77ff77")

注:

street.front 选择器将评估形状 streetWidth 对象属性,该属性会针对从街区创建的地块自动设置,但可能不会出现在手动创建的形状上。

  1. 场景编辑器窗口中选择 Lots 地块图层。
  2. 单击形状 > 分配规则文件
  3. 从规则目录中选择 myMass_03.cga 规则文件,然后单击确定
  4. 在 3D 视窗中选择地块。
  5. 具有 street.front 退缩尺度的宗地
  6. 单击形状 > 生成或按 Ctrl+G 生成建筑物。

建筑物距离

现在,您将添加类似的退缩尺度来控制建筑物之间的距离。 添加 distanceBuildings 属性,修改 Parcel 规则,然后添加新的 SubParcel 规则,如下所示:

attr distanceBuildings =
    30%: 0
    else: rand(4, 8)

Parcel --> 
    setback(distanceStreet)
        { streetSide: OpenSpace 
        | remainder: SubParcel }

SubParcel -->
    setback(distanceBuildings / 2)
        { noStreetSide: OpenSpace 
        | remainder: Footprint }

SubParcel 将再次应用退缩,但这次将应用于非街道边缘。

  1. 保存 .cga 文件。
  2. 请在 3D 视窗中选择一些地块。
  3. 单击形状 > 生成或按 Ctrl+G 生成建筑物。
  4. 选择一个生成的模型,然后使用 distanceBuildingsdistanceStreet 规则参数进行实验。 您可以在单个选定模型上设置值,也可以同时选择多个模型。
  5. 要将用户定义的值重置为规则文件中的随机值,请将源从用户更改回规则
  6. 在“检查器”窗口中手动设置的 distanceBuildings 和 distanceStreet 规则参数
    产生的退缩宗地

在下一部分中,您将合并前一部分中的体量模型和退缩宗地,并添加纹理立面。

合并体量和退缩宗地

设置

如果尚未打开 MassModeling_01.cej 场景,请打开该场景。

创建规则文件

打开 massmodeling_03.cej 规则文件,并将其另存为 myMass_04.cga

导入 LU 形状和塔的体量规则

  1. 添加以下两个导入命令:
  2. import lushapes : "massmodeling_01.cga"
    import towers : "massmodeling_02.cga"
  3. 修改 Footprint 规则,如下所示:
  4. Footprint -->
        case geometry.isRectangular(15):
            25% : towers.Tower
            else : lushapes.LUShape
        else:
            25%: towers.Tower
            else: offset(-5, inside) lushapes.BasicFootprint
  5. 保存规则文件。
  6. 场景编辑器窗口中选择 Lots 地块图层。
  7. 单击形状 > 分配规则文件
  8. 从规则目录中选择 myMass_04.cga 规则文件,然后单击确定

生成建筑物

  1. 请在 3D 视窗中选择一些地块。
  2. 单击形状 > 生成或按 Ctrl+G 生成建筑物。
    生成的建筑物
    城市混合了 LU 形状、塔形状和退缩宗地

在下一部分中,您将为体量模型添加纹理立面。

添加纹理立面

设置

如果尚未打开 MassModeling_01.cej 场景,请打开该场景。

创建规则文件

打开 massmodeling_04.cej 规则文件,并将其另存为 myMass_05.cej

要将简单的纹理立面添加到体量模型中,您需要一个函数,该函数会随机选择 12 个立面纹理切片其中之一。

const randomFacadeTexture = fileRandom("*facade_textures/f*.tif")

为了正确地将纹理切片映射到您的立面上,您将定义两个函数来计算实际的楼层高度和切片宽度。 借助这些函数,您可以确保在立面的边缘没有切掉任何纹理切片。

attr floorheight = rand(4,5)

actualFloorHeight =  
	case scope.sy >= floorheight : scope.sy/rint(scope.sy/floorheight)
	else : scope.sy
	
actualTileWidth = 
	case scope.sx >= 2 : scope.sx/rint(scope.sx/4)
	else : scope.sx

分割组件后,您将从体量模型中获取立面组件。

Mass --> 
	comp(f){ side: Facade | top: Roof. }

指示导入的规则使用此 Mass 规则。

towers.Mass --> Mass
lushapes.Mass --> Mass

最后,在立面上设置 UV 坐标,使用 randomFacadeTexture 函数定义纹理文件,并投影 UV。

Facade -->
	setupProjection(0, scope.xy, 8*actualTileWidth, 8*actualFloorHeight)
	texture(randomFacadeTexture)
 projectUV(0)

  1. 保存规则文件。
  2. 场景编辑器窗口中选择 Lots 地块图层。
  3. 单击形状 > 分配规则文件
  4. 从规则目录中选择 myMass_05.cga 规则文件,然后单击确定

生成建筑物

  1. 请在 3D 视窗中选择一些地块。
  2. 单击形状 > 生成或按 Ctrl+G 生成建筑物。
    生成的建筑物的视图
    显示纹理立面的所生成建筑物的视图
    生成的建筑物
    从侧面显示纹理立面的所生成建筑物的视图