CGA建模教程——形状语法(基础篇)

CGA建模教程——形状语法(基础篇)

本教程是使用CityEngine的CGA进行建筑建模的入门教程。
原文链接:http://desktop.arcgis.com/en/cityengine/latest/tutorials/tutorial-6-basic-shape-grammar.htm

资源下载:
初始数据
PDF教程

1、构建简单建筑

本教程介绍CGA形状语法的基本使用。你将分析一个完整的创建建筑过程的规则文件。
这里写图片描述
步骤:
1. 导入工程Tutorial_06_Basic_Shape_Grammar
2. 打开场景文件Tutorial_06_Basic_Shape_Grammar/scenes/01_SimpleBuilding.cej
你将创建一个具备典型立面结构的建筑,如下图所示:
这里写图片描述

在3D视图中选择该建筑,在检查视图中查看信息(如果没有该窗口,在Window > Inspector菜单中打开)
这里写图片描述
此处有2个重要的参数:
Rule File—指向规则文件rules/simpleBuilding.01.cga。当触发建筑生成时执行该规则文件。
Start Rule—定义执行规则文件时执行的第一个规则。此处的起始规则是Lot。

单击规则文件名字链接,或者双击rules/simpleBuilding.01.cga,打开CGA编辑器。

简单建筑规则集

建筑属性

建筑属性通常被定义在规则文件起始处。 (当然可以放在规则文件的任意位置)这些属性会被整个规则集合所用到,并显示在CGA属性映射区域,使得你可以在CGA编辑器外修改他们。

attr groundfloor_height = 4
attr floor_height       = 3.5
attr tile_width         = 3
attr height             = 11 
attr wallColor      = "#fefefe"
窗的资源

窗是这个简单建筑预先定义好的模型资源。该资源是从工程的assets目录中加载的。

// geometries
window_asset     = "facades/window.obj"
Lot规则

实际的建筑建造起点,即指示窗口中设定的第一个规则。
建筑模型通过如下的挤出操作而形成:

Lot -->
    extrude(height) Building
Building规则

这是个典型的步骤。一个模型可以通过组件分割的方式分成多个面。

Building --> 
    comp(f){ front : FrontFacade | side : SideFacade | top: Roof}

该规则将名为Building的形状依照3个不同的部分展开分裂。第一个部分是front(即建筑的正面),第二个部分是side(建筑的多个侧面),第三个部分是Root(即屋顶部分)。
立面可以进一步构建、典型的立面建模流程如下:首先,立面能被分解成多个楼层;然后,楼层可以进一步分解为多个元素“瓦片”。典型的瓦片包括墙面和窗户等元素。
上述分解过程用CGA语法描述如下:
这里写图片描述

FrontFacade规则

FrontFacade规则将建筑前立面分裂出高度为4的1楼,然后将上面的剩余部分分成多个高为3.5的楼层(使用重复操作符 [ *]) 注意符号~保证无论建筑高度是多少,总是尽可能保证每一层的高度尽可能等于3.5。
第一层的外观和上面各层存在很大不同,如正门,不同的高度,门窗,颜色等等。

FrontFacade -->
    split(y){ groundfloor_height : Groundfloor |
    { ~floor_height: Floor }* }
SideFacade rule
SideFacade规则

SideFacade规则将建筑的几个侧面分裂成多个楼层。分裂过程的代码和正面一样,以保证正面和侧面每一层的高度能够保持完全一致。

SideFacade -->     
    split(y){ groundfloor_height: Floor | { ~floor_height: Floor }* }

【注】此时如图所示:
这里写图片描述

Floor规则

Floor规则执行典型的分裂操作,使得分出来的每一个瓦片宽度逼近3。为了让楼层变得更加有趣你可以多分割一个宽度为1的墙面元素。

Floor -->
    split(x){ 1: Wall 
            | { ~tile_width: Tile }* 
            | 1 : Wall }
Groundfloor规则

第一层的规则和上述分裂规则一样,唯一区别在于最右边有个大门入口。

Groundfloor -->
    split(x){ 1: Wall 
        |{ ~tile_width: Tile }* 
        | ~tilewidth: EntranceTile 
        | 1: Wall }

上述分裂的结果如图所示:
这里写图片描述

Tile规则

下面开始构建瓦片内的元素。

Tile -->
    split(x){ ~1 : Wall
            |  2 : split(y){ ~1: Wall | 1.5: Window | ~1: Wall }
            | ~1 : Wall }

瓦片规则,在一个瓦片内,沿着x轴和y轴方向执行分割。(通过嵌套分割)。
设计思路如下:
左边各一个墙面元素,宽度是浮动的(1左右);
中间一个窗户元素,大小是固定的(宽度为2,高度为1.5)。
【注】此时如图所示:
这里写图片描述

EntranceTile规则

EntranceTile规则通过类似的方式定义大门。显然的区别在于,大门下方不需要墙面元素。

EntranceTile -->
    split(x){ ~1 : SolidWall
            |  2 : split(y){ 2.5: Door | ~2: SolidWall }
            | ~1 : SolidWall }
Window, Door, and Wall规则

最后的规则,用相应的模型资源来替换窗户、门、墙的形状对象,并给其赋予贴图。

Window -->
    s('1,'1,0.4)
    t(0,0,-0.25)
    i(window_asset)  

Door -->
    s('1,'1,0.1)
    t(0,0,-0.5)
    i("builtin:cube")     

Wall -->
    color(wallColor)

SolidWall -->
    color(wallColor)
    s('1,'1,0.4) 
    t(0,0,-0.4) 
    i("builtin:cube:notex")

首先注意,代码中使用平移操作:t(x,y,z),使得窗户向z方向移动了-0.25,制造出窗户嵌入立面0.25米的效果。
其次,插入操作:i(objectname) 将相应的对象插入到当前形状所在的区域。如果不指定大小,模型会自动适应目标大小,否则将使用指定的大小。
大小操作:s(x,y,z)用于在x,y,z轴3个方向放缩目标。 以窗户为例,x,y轴使用(‘1) 使其不受变化影响,z轴设置为0.4,使其向外放大0.4米)

此时如图所示:
这里写图片描述
下一节你将学习如何贴纹理。

给建筑贴纹理

本小节你将学习如何给门窗等元素贴纹理。

教程步骤
  1. 打开Tutorial_06_Basic_Shape_Grammar/scenes/01_SimpleBuilding.cej 场景。
  2. 打开Tutorial_06_Basic_Shape_Grammar/rules/simpleBuilding.01.cga规则文件。
纹理定义

在规则文件的最开始定义纹理对应的资源文件。
1 增加如下纹理定义:

// textures
frontdoor_tex   = "facades/textures/shopdoor.tif"
wall_tex        = "facades/textures/brickwall.jpg"
dirt_tex        = "facades/textures/dirtmap.15.tif"
roof_tex        = "roofs/roof.tif"

assets/facade文件夹下有9张不同的窗户纹理。无需定义9个纹理,步骤2一次性返回这9个纹理中的一个。
2 增加如下代码:

randomWindowTexture = fileRandom("*facades/textures/window.*.tif")

3 增加setupProjection()命令给Frontfacade和Sidefacade规则:

FrontFacade --> // 原文此处拼写有误
    setupProjection(0, scope.xy, 1.5, 1, 1) 
    setupProjection(2, scope.xy, scope.sx, scope.sy)
    split(y){ groundfloor_height : Groundfloor | { ~floor_height: Floor }* }

SideFacade -->// 原文此处拼写有误
    setupProjection(0, scope.xy, 1.5, 1, 1) 
    setupProjection(2, scope.xy, scope.sx, scope.sy)  
    split(y){ groundfloor_height: Floor | { ~floor_height: Floor }* }

setupProjection() 命令对设置纹理的UV坐标。
参数1:纹理通道编号。如颜色贴图通道为0, 污垢贴图通道为2。
参数2:映射坐标。scope.xy表示映射到xy平面。如砖块贴图(通道0)在 x方向上每隔1.5米重复一次,y方向1米重复一次。污垢纹理(通道2)扩展到整个立面,因此可使用参数scope.sx和scope.sy。

4 添加屋顶规则。

Roof --> 
    setupProjection(0, scope.xy, scope.sx, scope.sy)    
    texture(roof_tex)
    projectUV(0)

屋顶规则将UV坐标覆盖整个面。

5 将texture()命令添加到如下代码中:

Window -->
    s('1,'1,0.4)
    t(0,0,-0.25)
    texture(randomWindowTexture)
    i(window_asset)  

Door -->
    s('1,'1,0.1)
    t(0,0,-0.5)
    texture(frontdoor_tex)  
    i("builtin:cube")

对于门窗元素,只需指定颜色通道的贴图即可。特别的,对于窗户,使用 randomWindowTexture() 函数来获取9张纹理中随机的纹理。

6 Wall和SolidWall使用UV坐标指定来贴图。为了对颜色通道和污垢通道进行贴图,还必须用projectUV函数将UV坐标映射到这2个通道上。

Wall -->
    color(wallColor)
    texture(wall_tex)  
    set(material.dirtmap, dirt_tex)
    projectUV(0) projectUV(2)

SolidWall -->
    color(wallColor)
    s('1,'1,0.4) 
    t(0,0,-0.4) 
    texture(wall_tex)  
    set(material.dirtmap, dirt_tex)
    i("builtin:cube:notex") 
    projectUV(0) projectUV(2)
```l
此时如图所示:
![这里写图片描述](http://desktop.arcgis.com/en/cityengine/latest/tutorials/GUID-5D082634-56C1-48A6-8ECA-60EF65894E41-web.png)
近距离特写如下:
![这里写图片描述](http://desktop.arcgis.com/en/cityengine/latest/tutorials/GUID-140D68F1-C2DF-40A4-AA07-E40AA6F93918-web.png)
下列图片展示了将该规则用于任意大小的建筑模型上的效果:
![这里写图片描述](http://desktop.arcgis.com/en/cityengine/latest/tutorials/GUID-BEABFDA8-A67A-40BA-80B5-660AF0A7326B-web.png)


----------






<div class="se-preview-section-delimiter"></div>

##增加多层次细节(LOD, level of detail)
本节你将学会添加简单的LOD机制。你将降低模型的复杂度(多边形数量),这对于构建大规模的简单建筑体尤其有用。





<div class="se-preview-section-delimiter"></div>

###步骤
1 打开**Tutorial_06_Basic_Shape_Grammar/scenes/02_SimpleBuilding.cej** 场景。
2 打开**Tutorial_06_Basic_Shape_Grammar/rules/simpleBuilding.02.cga** 规则文件。




<div class="se-preview-section-delimiter"></div>

###添加LOD属性
在规则文件中添加LOD属性。




<div class="se-preview-section-delimiter"></div>

```c
attr LOD = 1

本例我们使用2级LOD:

  • LOD 0—低级别LOD,低复杂度。
  • LOD 1—高级别LOD,高复杂度。

之前构建的模型可以作为高级别LOD模型。现在只需要简单几步即可完成低级别LOD模型构建。
检查当前模型,可以发现,简化窗户模型可以降低模型复杂度。可以使用戴文丽的平面来代替窗户模型。

  1. 在Window规则中添加LOD > 0的情况,并在其中使用texture(randomWindowTexture) 来完成窗户构建。如下所示:
Window -->
    case LOD > 0 : 
      s('1,'1,0.4)
      t(0,0,-0.25)
      texture(randomWindowTexture)
      i(window_asset)  
    else :      
      setupProjection(0,scope.xy,scope.sx,scope.sy) 
      texture(randomWindowTexture)  
      projectUV(0)

如果LOD值大于0(即高LOD),则使用之前的代码;否则,不在加载window模型资源,而是在当前的面上直接贴图。
2. Door规则一样。直接使用平面而不加载立方体模型:

Door -->
    case LOD > 0 :
    s('1,'1,0.1)
    t(0,0,-0.5)
    texture(frontdoor_tex)
    i("builtin:cube")
  else :
    setupProjection(0,scope.xy,scope.sx,scope.sy)   
    texture(frontdoor_tex) 
    projectUV(0)
  1. 下面是SolidWall。因为你移除了门的内部,因此不在需要他了。
SolidWall -->
    case LOD > 0 :
        color(wallColor)
        s('1,'1,0.4) 
        t(0,0,-0.4) 
        texture(wall_tex)  
        set(material.dirtmap, dirt_tex)
        i("builtin:cube:notex") 
        projectUV(0) projectUV(2)
    else :
        Wall
  1. 选中建筑,查看指示窗中新增的LOD属性,将其修改为0。
    下次执行生成的时候,规则文件会用0来执行生成。
    这里写图片描述
  2. 生成低LOD级别的建筑。
    这里写图片描述
  3. 使用网格模式显示建筑(快捷键:6),并且去除显示纹理(快捷键:5),两者的差异非常明显。按2下d键,在视图的最上方查看模型的多边形数量。可以发现多边形数量从3699降低到了475。
    这里写图片描述
    下一节你将学会如何给模型添加随机属性。

建筑随机属性

下一节你将学会如何给模型添加随机属性以生成多样化的建筑。

步骤

1 打开Tutorial_06_Basic_Shape_Grammar/scenes/03_SimpleBuilding.cej
2 打开Tutorial_06_Basic_Shape_Grammar/rules/simpleBuilding.03.cga 规则文件。,

添加随机属性

1 你将给3个建筑属性添加多样化:建筑高度(8-35之间),瓦片宽度(2.5 ~6),三种随机的颜色。

attr tile_width = rand(2.5, 6)
attr height     = rand(8, 35) 
attr wallColor  = 33%  :  "#ffffff"
                      33%  :  "#999999"
                      else :  "#444444"

2 因为要生成大量建筑,将默认LOD设置为0。

 attr LOD = 0

3 左边的场景管理列表中,选择Block层。
4 单击Generate生成建筑。
这里写图片描述
http://desktop.arcgis.com/en/cityengine/latest/tutorials/GUID-71581E6D-635E-40ED-BCD6-A2E63310BA97-web.png

  • 4
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值