教程 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. 在场景编辑器中选择地块图层。
  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 }

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

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

可变 L 形状

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

U 形状

您将添加 U 形状。 在起始地块规则中,调用 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 语句请确保 UShape 和 LShape 仅在近似矩形地块(公差为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,然后单击完成

塔形状

属性高度为建筑物高度创建一个随机值。 起始规则地块称为 Envelope,将覆盖区拉伸到塔信封。 Envelope 调用递归规则。

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

Lot --> Tower

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

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

// 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

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

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

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

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

生成建筑物

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

Round 形状

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

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,然后单击完成

街道退缩尺度

宗地规则适用于地块所有街道两侧的退缩尺度,并将该区域转至 OpenSpace 规则。 远离街道两侧的内部部分将转发到覆盖区,然后将其拉伸到随机高度。

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 生成建筑物。

建筑物距离

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

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

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

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

子宗地将再次应用退缩尺度,但这次将应用于非街道边缘。

  1. 保存 .cga 文件。
  2. 请在 3D 视窗中选择一些地块。
  3. 单击形状 > 生成或按 Ctrl+G 生成建筑物。
  4. 选择一个生成的模型,然后使用 distanceBuildings 和 distanceStreet 规则参数进行实验。 您可以在单个选定模型上设置值,也可以同时选择多个模型。
  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. 修改覆盖区规则,如下所示:
  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. }

指示导入的规则使用此质量规则。

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 生成建筑物。
    生成的建筑物的视图
    生成的显示纹理立面的建筑物的视图
    生成的建筑物
    生成的显示纹理立面的建筑物的视图