kikita & Maps

GIS,spatial and artificial intellegence learning and share

​ CityEngine的同义词几乎就是“规则建模”,规则指的是CGA脚本。说到脚本,很多用户又会联想到 Python, 衍生出来的问题就是,“CityEngine中是用python脚本建模吗?” 答案是No。

​ CityEngine中确实也引入了python,只不过使用python的姿势不是建模,而是自动化。通过python脚本,可以增强CityEngine的建模功能,自动化驱动脚本建模工作流,提高建模效率。我们既可以在控制台交互式执行python命令,也可以在python editor 中书写python执行文件,甚至可以将一些自定义功能扩展到CityEngine中。如下是CityEngine官方教程中的几个示例代码:

Example 1 选择部分对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'''
Created on 2018-4-9
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

def selectByAttribute(attr, value):
objects = ce.getObjectsFrom(ce.scene)
selection = []
for o in objects:
attrvalue = ce.getAttribute(o, attr)
if attrvalue == value:
selection.append(o)
ce.setSelection(selection)

if __name__ == '__main__':
selectByAttribute("connectionStart","JUNCTION")

Example 2 修改对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'''
Created on 2018-4-9
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

''' increment the street width parameter of all selected street segments'''
# @noUIupdate
def incrementStreetWidths(increment):
selectedSegments = ce.getObjectsFrom(ce.selection, ce.isGraphSegment)
for segment in selectedSegments:
oldWidth = ce.getAttribute(segment, "/ce/street/streetWidth")
newWidth = oldWidth+increment
ce.setAttribute(segment, "/ce/street/streetWidth", newWidth)

if __name__ == '__main__':
incrementStreetWidths(10)

Example 3 动态模拟建筑物生长

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
'''
Created on 2018-4-12
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

def growBuilding():
for i in range(1,14):
height = 20+i
doStep(i,height,1)
for i in range(15,35):
height = 34
width = i-14
doStep(i,height,width)

def doStep(i,height,width):
object = ce.getObjectsFrom(ce.scene, ce.withName("'Lot1'"))
ce.setAttributeSource(object, "height", "OBJECT")
ce.setAttributeSource(object, "width", "OBJECT")
ce.setAttribute(object, "height", height)
ce.setAttribute(object, "width", width)
Generate(object)

def Generate(object):
ce.generateModels(object)

if __name__ == '__main__':
growBuilding()

Example 4 陈列资源库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
'''
Created on 2018-4-12
@author: kikita
'''
from scripting import *

# get a CityEngine instance
ce = CE()

def writeCGAlib():
# open the cga file to be written
cga = "/*Asset Library Loader : Generated by asset_lib.py*/\n version \"2014.0\"\n\n"
# write start rule
cga += "Lot --> Geometries Textures"
# write rule showing geometries
cga += "\n\nGeometries --> "
# get all .obj files from asset directory, and call their loader
for obj in ce.getObjectsFrom("/", ce.isFile, ce.withName("/Tutorial_10*/assets/*.obj")):
# and write
cga += "\n\t t(2,0,0) Geometry(\""+obj+"\")"
print obj
# write rule showing jpg textures
cga += "\n\nTextures --> \n\ts(1,0,0) set(scope.tz,0) set(scope.ty,3) i(\"facades/xy-plane.obj\")"
# get all .jpg files from asset directory, and call their loader
for jpg in ce.getObjectsFrom("/", ce.isFile, ce.withName("/Tutorial_10*/assets/*.jpg")):
cga += "\n\tt(2,0,0) Texture(\""+jpg+"\")"
#write geometry loader rule
cga += "\n\n Geometry(asset) --> s(1,0,0) i(asset) set(scope.ty,0) set(scope.tz,0)"
#write texture loader rule
cga += "\n\n Texture(asset) --> set(material.colormap, asset)"
cgafile = ce.toFSPath("rules/asset_lib2.cga")
CGA = open(cgafile, "w")
CGA.write(cga)
CGA.close()
print "written file "+cgafile

def assignAndGenerateLib():
object = ce.getObjectsFrom(ce.scene, ce.withName("'Lot2'"))
ce.refreshWorkspace()
ce.setRuleFile(object, "asset_lib2.cga")
ce.setStartRule(object, "Lot")
ce.generateModels(object)

if __name__ == '__main__':
writeCGAlib()
assignAndGenerateLib()
Read more »

摄于 2014-5-9, Acropolis, Athens, Greece

CityEngine的教程中刚好有个Parthenon Temple 的 Demo

不禁会想起在雅典卫城里它的断壁残垣,晒晒我们的合影

不知道几年过去,修复工作又向前推进了多少

那些带有编号的石头是不是已经归位了呢

整个卫城中我最喜欢的是上图中最后一张的“厄瑞克忒翁神庙”,据说用于供奉雅典娜、波塞冬和英雄厄瑞克忒翁。

神庙一侧的女神柱像精致优美,即使经过了这么多的时光,都可以感受到雕刻师的精湛技艺。

厄瑞克忒翁神庙

Read more »

​ 接着上一篇

​ 为了让脚本看起来更连贯,无需跳转上一篇,我们从头开始。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* File: MyTestforBaseTexure.cga
* Created: 30 Mar 2018 08:16:37 GMT
* Author: Xiaoyan Mu
*/

version "2017.1"
attr height = 10
attr groundfloor_height = 4
attr floor_height = 3.5
attr tile_width = 3.5

wall_tex = "facades/textures/brickwall.jpg"
dirt_tex = "facades/textures/dirtmap.15.tif"
graffiti_tex = "facades/textures/Graffiti.jpg"
window_tex = "facades/textures/window.5.tif"

Lot --> extrude(height) Building

Building --> comp(f) {front : Sidefacade}

​ 假设我希望在这面墙上“凿”出窗户,就需要将Sidefacade进行细化切割。贴纹理时也要注意一下新的技巧,也就是在细分表面之前先定义纹理UV,细分之后再用上一篇中提到的贴纹理的方法应用到Wall,这样就可以得到连续的墙体贴图。这样的做的原因在于,CE中的shape都是被不断迭代替换的,如果不在细分之前定义UV,Sidefacade对象在细分之后已经消亡了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Sidefacade is modified

Sidefacade -->
# Setup texturing
setupProjection(1, scope.xy, 1.5, 1)
setupProjection(2, scope.xy, scope.sx, scope.sy)
# Divide Sidefacade
split(y){ groundfloor_height: Wall | {~floor_height : Floor}* }

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

Wall -->
# Apply the texture
set(material.bumpmap,wall_tex)
set(material.dirtmap, dirt_tex)
projectUV(1)
projectUV(2)

Window -->
offset(0.05)
comp(f) { inside: WondowInner | border: WondowFrame }
WondowInner -->
setupProjection(0, scope.xy, scope.sx, scope.sy)
texture(window_tex)
projectUV(0)
WondowFrame -->
extrude(0.1)

material.opacitymap

material.opacitymap 通道可以用于控制纹理的透明度。

继续上面的例子,如果希望做出透明的窗户效果,可以将Window的代码替换为如下的样子。

Read more »

​ 经常看到官微、公众号的各种推送,了解到很多轰动一时的大片和电游的视觉制作都有CityEngine 助力过。CityEngine 在影娱视觉行业早已硕果累累,而对于GIS大众,CityEngine 算是刚从幕后走到了台前,从神秘娱乐圈走近了烟火人间。这几年来,这个不姓“Arc”的非主流产品在不断地推陈出新,吸引着慕名围观的用户去了解。3D模型的纹理贴图问题通常是建模中的高频问题,作为前排围观群众之一,我今天就用CityEngine做一面“墙”娱乐一下吧。

环境: Esri City Engine 2017.1

​ 在 CityEngine中的 shape 对象具有material 属性,这一属性可以控制模型的纹理贴图、阴影效果、外观等。CityEngine 支持的纹理图片的格式有:**.bmp、.gif、.jpg/.jpeg、.png、.tif/.tiff**。 CityEngine贴图支持6个纹理通道,它们通过特定的关键字来表达,如下:

uv-set Texture Layer
0 colormap
1 bumpmap
2 dirtmap
3 specularmap
4 opacitymap
5 normalmap

下面我通过几个实例来说明下它们的用途:

​ 基于共同的基础脚本向下进行,这里不再解释,相信你一看即懂。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* File: MyTestforBaseTexure.cga
* Created: 21 Mar 2018 08:26:37 GMT
* Author: Xiaoyan Mu
*/

version "2017.1"
attr height = 6
wall_tex = "facades/textures/brickwall.jpg"
dirt_tex = "facades/textures/dirtmap.15.tif"
graffiti_tex = "facades/kiktia/Graffiti.jpg"
Lot --> extrude(height) Building
Building --> comp(f) {side : Sidefacade}

material.colormap

Read more »

我们可以将2D矢量数据、3D模型格式导入到CityEngine 中使用,前者一般作为CityEngine shape 来使用,后者作为模型来使用。

OBJ,DAE,FBX这几种模型格式导入时可以作为两种角色来使用,shape 或 static model。这是由导入窗口中的 Import as static model 设置控制的。

Import as static model

When checked, the file will be imported ‘as is’ and will not be modifiable by cga rules.

  • Shapes—Serve as a base for CGA generation. A typical example is footprint data.
  • Static models—Can be scaled, rotated, and translated after import but cannot be processed further with CGA.

通过如上说明,我们可以清晰的了解到把模型转为shape或Static Model的差异。 一般实际应用中,我们会把当作“素材”使用的模型小件作为static model用;而把表示基础结构的模型作为shape来使用。

static model导入之后,仍然可以再转换为shape,操作:菜单栏 Shapes->Convert Models to Shapes。成为shapes 之后,就可以通过cga对这个模型的继续进行改造了。

在如下示例图中了解:

0%