CityEngine建模示例教程6:BasicShapeGrammar之Part1:简单建筑物
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CityEngine建模⽰例教程6:BasicShapeGrammar之Part1:简单建筑物
本着从⽰例中学习使⽤规则建模的⽬的,学习⼀下CityEngine中的教程。
前⼏个教程是熟悉软件以及如何使⽤规则的,第六个教程是开始使⽤规则建模,并给建筑物贴纹理的。
因此⼀边学习教程6中的步骤,⼀边查看其中创建规则的CGA具体语法,希望我们都能从教程中有很多收获。
前提要了解如何创建规则和应⽤规则。
本次学习的教程为Tutorial_06_Basic_Shape_Grammar__2011_1,其中包含四部分,分别为:1.构建简单建筑物;2.为简单建筑物贴纹理;3.添加LOD;4.建筑物属性随机变化。
本节学习该教程中的第⼀部分。
本节学习最终要构建⼀个如下图的建筑物,该建筑物有地⾯⼀楼和其他楼层,⼀楼的正⾯有⼀个⼊⼝的门,其他窗⼝都使⽤的是⼀个提前做好的OBJ模型。
下⾯开始创建规则进⾏建模:
为了更好的理解规则,我们⾃⼰创建⼀个新的规则,按照教程中的语句进⾏规则的书写。
1. 在规则⽂件的最开始处定义建筑的属性(也可以放在规则⽂件的其他位置)。
在CGA⽂件中,这些属性将对整个规则⽂件产⽣作⽤。
这些属性将显⽰在属性查看器(Inspector)中,可通过属性查看器修改这些属性。
attr groundfloor_height = 4 //地⾯⼀楼的⾼度
attr floor_height = 3.5 //其他楼层的⾼度
attr tile_width = 3 //将楼⾯按块划分的宽度
attr height = 11 //楼⾼
attr wallColor = "#fefefe" //墙⾯颜⾊
2. 教程中构建的窗户是使⽤的⼀个已经建好的窗户模型window.obj,这个⽂件存放在assets⽂件夹中,使⽤之前也要先定义出来。
window_asset = "facades/window.obj" //指定obj⽂件
3. 下⾯我们定义第⼀条规则为Lot. 在属性检查器中,该规则被指定为开始规则。
⼤量的模型是使⽤拉伸操作创建⽽来的:
//对shape使⽤height中定义的⾼度进⾏拉伸,并命名为Building
Lot -->
extrude(height) Building
拉伸之后如下图:
4. 可以通过应⽤comp()将Building分解为多个⾯, ⽣成了正⾯(FrontFacade)、多个侧⾯(SideFacade)和⼀个顶⾯(Roof)
Building-->
comp(f){ front : FrontFacade | side : SideFacade | top: Roof}
5. 分解完成之后,就开始开始对这些⾯进⾏外观造型。
典型的外观造型流程如下:1,将⾯分解为楼层(Floors)。
2,将楼层分解为块(Tile),每⼀块通常由墙⾯和窗⼝构成。
这样的细分过程在CGA要素语法的实现过程如下图:
//下⾯的FrontFacade规则将正⾯沿y轴⽅向,分割为两⼤部分,第⼀部分⾼度为groundfloor_height的地⾯⼀层Groundfloor,剩余的以floor_height⾼度进⾏重复分割(以*符号标记),分割为多个Floor。
FrontFacade -->
split(y){ groundfloor_height : Groundfloor | { ~floor_height: Floor }* }
正⾯分割之后如下图:
6. 细分侧⾯:
SideFacade -->
split(y){ groundfloor_height: Floor | { ~floor_height: Floor }* }
SideFacade规则将侧⾯沿y轴⽅向分割也分为两⼤部分,这两部分使⽤的都是是相同的Floor对象,因此侧⾯这两⼤部分看起来都应该是⼀样的。
只有⾼度不⼀样,⾼度不⼀样主要是为了与正前⾯的楼层⾼度保持⼀致。
侧⾯分割之后如下图,三个侧⾯都是⼀致的:
7. 继续对Floor对象进⾏细化:
//先给每层楼在x轴⽅向的两端画出宽度为1的墙⾯(Wall),剩余的部分以tile_width为宽度重复分割(Tile)Floor -->
split(x){ 1: Wall
| { ~tile_width: Tile }*
| 1 : Wall }
如下图:
8. 最后对正⾯的地⾯⼀楼进⾏细化:
//同样先在x轴⽅向的两端画出宽度为1的墙⾯(Wall),按照tile_width划分为多个Tile,并按照tile_width划分出⼀个⼊⼝EntranceTile。
Groundfloor -->split(x){ 1: Wall
|{ ~tile_width: Tile }*
| ~ tile_width: EntranceTile
| 1: Wall }
结果如下图:
9. 下⾯对Tile进⾏定义:
//先对Tile在x轴⽅向中间划分出宽度为2的⼀部分(对这部分再按y轴⽅向先划分⼀个⾼度为分别为1和1.5的wall和window,剩余的⾼度也定为wall),然后两边分别划分为宽度⼤概为1的wall Tile -->
split(x){ ~1 : Wall
| 2 : split(y){ 1: Wall | 1.5: Window | ~1: Wall }
| ~1 : Wall }
结果如下:
10. 对EntranceTile进⾏定义:
EntranceTile -->
split(x){ ~1 : SolidWall
| 2 : split(y){ 2.5: Door | ~2: SolidWall }
| ~1 : SolidWall }
先对⼊⼝在x轴⽅向划分宽度为2的⼀部分(这部分在y轴⽅向先划分2.5⾼度的Door,剩余的⼤约⾼度2定为SolidWall.),然后两边各为⼤约1⽶的Solidwall。
11. 最后对前⾯定义的Window,Door,Wall和SolidWall写具体的规则。
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")
这⾥解释⼀下上⾯出现的⼏个命令:
① s('1,'1,0.4):
命令:s(float xSize, float ySize, float zSize)
作⽤设置形状的尺⼨。
eg1: s(5,5,5) 表⽰将三个⽅向的值设为绝对值5
eg2: s('0.5,'1,'1.5) 等同于 s(0.5*scope.sx,scope.sy,1.5*scope.sz),如果加上'符号,括号内的值在0-1之间,表⽰设置xyz的值为原先的多少倍。
②t(0,0,-0.25)
平移:t(tx, ty, tz)
③i(window_asset)或者i("builtin:cube:notex")
对象替换:i(geometryPath)
CityEngine有内置的素材可以直接使⽤,分为Geometry Assets和Textures。
Geometry Assets:
builtin:cube—有节点的单位⽴⽅体,带有纹理图层的纹理坐标系
builtin:cube:notex—单位⽴⽅体,不带有纹理坐标系
Textures:
builtin:default—表⽰16×16⿊⽩⽅格相间的纹理
builtin:uvtest.png—使⽤CE标准的测试纹理
最终效果:
到此我们完成了简单建筑物的构建,学习了构建流程,如何拉伸、分解⾯、分割Tile等。
规则可以⼀步步尝试,也可以替换成其他颜⾊或将obj替换为其他模型。
如下图:。