CityEngine建模示例教程6:Basic Shape Grammar之Part 1:简单建筑物

    本着从示例中学习使用规则建模的目的,学习一下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.  最后对前面定义的WindowDoorWallSolidWall写具体的规则。

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替换为其他模型。如下图:

 

 

posted @ 2012-08-15 10:45  esrixa  阅读(6070)  评论(0编辑  收藏  举报