zoukankan      html  css  js  c++  java
  • 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_ Tile }* | 1 : Wall }

    如下图:

     

    8.     最后对正面的地面一楼进行细化:

    //同样先在x轴方向的两端画出宽度为1的墙面(Wall),按照tile_width划分为多个Tile,并按照tile_width划分出一个入口EntranceTile。
    Groundfloor -->split(x){ 1: Wall                
    |{ ~tile_ Tile }*
    | ~ tile_ 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替换为其他模型。如下图:

     

  • 相关阅读:
    DataTable 只保留想要的几列
    如何用多个字符串来切分字符串
    用.net 发送邮件
    sqlserver 行列转换
    sql面试题一 学生成绩
    将DataReader转换为DataTable
    C# 如何用多个字符串来切分字符串并去除空格
    SqlServer按时间自动生成生成单据编号
    实验一 Java开发环境的熟悉
    Java学习笔记心得——初识Java
  • 原文地址:https://www.cnblogs.com/esrichina/p/2639623.html
Copyright © 2011-2022 走看看