从零构建CityEngine规则:用CGA语法实现带属性SLPK的完整工作流
你是否曾在CityEngine中面对空白的地块数据手足无措?或是看着复杂的CGA语法手册却不知从何入手?本文将带你体验从基础几何体到完整三维场景的蜕变过程。不同于传统教程的功能点罗列,我们将以真实项目需求为导向——假设你手头有一份包含建筑高度、用途等属性的地块数据(如.shp文件),需要最终生成可直接发布到WebGIS平台的SLPK场景图层包。这个完整流程将串联起CGA规则编写、模型优化、属性保留等关键技术环节。
1. 环境准备与数据导入
在开始编写规则前,合理的工程目录结构是高效工作的基础。CityEngine默认会创建以下文件夹结构:
/ProjectName ├── Assets # 存放贴图、3D组件等资源 ├── Data # 存放.shp等原始数据 ├── Rules # CGA规则文件存放位置 ├── Scenes # 场景文件(.cej) └── Models # 导出模型(如SLPK)的存放位置数据导入关键步骤:
- 将地块.shp文件拖入Data文件夹
- 在视图中右键点击导入的数据,选择"Create Initial Shapes"
- 确认坐标系正确(CityEngine仅支持投影坐标系)
注意:如果原始数据包含高度字段,建议在导入时勾选"Extract heights from attributes",这样初始形状就会具有Z值信息。
2. CGA规则编写基础:从方块到参数化建筑
让我们从最简单的规则开始——将二维地块拉伸为三维体块。新建.cga文件并输入以下基础规则:
// 定义可调节的参数 @Range(10, 100) attr buildingHeight = 30 // 初始规则 Lot --> extrude(buildingHeight) Building此时将规则文件拖拽到地块上,就能看到基础的三维体块。在Inspector面板中,你可以动态调整buildingHeight参数观察变化。
进阶技巧:要实现不同建筑高度,可以利用随机函数:
attr baseHeight = 20 attr heightVariation = 10 Lot --> extrude(baseHeight + rand(0, heightVariation)) Building3. 建筑细分化与纹理映射
简单的方块显然不够真实,我们需要对建筑进行细分和贴图处理。以下是典型的分层贴图实现:
Building --> comp(f) { top : Roof | side : Facade } Roof --> setupProjection(0, scope.xy, 10, 10) projectUV(0) texture("Assets/Textures/roof.jpg") Facade --> setupProjection(0, scope.yz, 5, 5) projectUV(0) texture("Assets/Textures/facade.jpg")关键参数解析:
setupProjection中的数字10表示贴图在模型上重复的次数scope.xy指定贴图投影平面- 使用
projectUV(0)应用UV坐标
4. 保留原始地块属性到SLPK
这是许多用户容易忽视的关键步骤。假设原始.shp包含"height"、"type"等字段,需要通过特殊方法保留到最终模型:
version "2023.0" // 声明与原始数据对应的属性 attr sourceHeight = 0 attr buildingType = "" // 主规则 Lot --> report("height", sourceHeight) report("type", buildingType) extrude(sourceHeight) Building导出SLPK的正确流程:
- 全选所有模型
- 在Inspector中应用编写好的规则
- 右键选择"Export Models"
- 格式选择"Scene Layer Package (SLPK)"
- 勾选"Preserve Attributes"
5. 高级技巧:条件分支与组件复用
真正的项目往往需要处理多样化的建筑类型。下面展示如何根据属性值应用不同规则:
Building --> case buildingType == "residential": ResidentialBuilding case buildingType == "commercial": CommercialBuilding else: DefaultBuilding ResidentialBuilding --> split(y){ ~3: Floor }* ...对于常见建筑元素,可以创建可复用的组件规则:
// 窗户组件规则 module Window(width, height) --> s('1, '1, 0.1) t(0, 0, -0.05) color("#6ab4e8")然后在主规则中调用:
Facade --> split(x){ ~5: Window(1, 1.5) | ~1: Wall }*6. 性能优化与调试技巧
随着规则复杂度增加,性能问题可能显现。以下优化策略值得关注:
性能对比表:
| 优化方法 | 实现方式 | 效果提升 |
|---|---|---|
| 纹理合并 | 使用纹理集替代单个贴图 | 减少30-50%绘制调用 |
| LOD控制 | 为不同距离设置不同细节级别 | 提升远距离渲染性能 |
| 实例化 | 对重复元素使用i()函数引用 | 降低内存占用 |
调试工具推荐:
- Model Hierarchy窗口(Window > Show Model Hierarchy)
- CGA Debugger(规则编辑器中的调试按钮)
- 临时使用color()函数标记不同部件
当规则出现问题时,可以逐步注释代码块定位问题区域。例如:
Building --> // extrude(height) // 先注释这行测试 color(1,0,0) // 用颜色可视化当前形状7. 完整项目工作流示例
让我们整合所有知识点,看一个从数据到发布的完整案例:
数据准备阶段:
- 在GIS软件中准备带属性的地块数据
- 确保包含高度、类型等关键字段
- 导出为.shp格式
CityEngine处理:
version "2023.0" // 属性声明 attr plotHeight = 0 attr plotType = "" attr plotID = 0 // 主规则 Lot --> report("height", plotHeight) report("type", plotType) report("id", plotID) extrude(plotHeight) comp(f) { top: Roof | side: Facade } Facade --> case plotType == "office": split(y){ ~3: OfficeFloor }* else: split(x){ ~5: Window | ~1: Wall }*导出与发布:
- 导出时选择SLPK格式
- 设置合理的LOD级别
- 上传到ArcGIS Online/Portal
- 在Web场景中配置样式
经过这样的系统化学习路径,你会发现CGA语法不再是需要死记硬背的咒语,而是可以灵活运用的设计工具。当遇到特殊需求时,不妨先分解问题——确定需要修改形状、纹理还是结构,然后查找对应的CGA函数实现。