4.2 城市与建筑生成


4.2 城市与建筑生成

本节摘要:程序化城市生成 = 地块划分 + 规则填充 + 变体控制。核心方法论与地形一脉相承:掩码定"哪里"、规则定"什么"、散布定"怎么摆"。本节从最小实验(一块地切分并填充建筑)走到街网生长策略,并讨论风格控制与真实城市数据两条路线的取舍。

最小实验:一块地长出楼

  1. 画一块矩形地块(或从高度场的平缓掩码导出边界——城市天然长在地貌约束上);
  2. Enumerate/ 或 Wrangle 打标签:这里用最直接的递归切分思路——Houdini 有现成的 Lots 类思路,也可用 Transform Pie/ For-Each 循环手工二分地块(每轮按随机比例切一刀,直到地块小于阈值)。用 For-Each with Feedback + 一个判断即可实现:
// 在循环体内对地块做一次随机二分(示意逻辑) // 面积小于阈值则跳过,否则切一刀并把两半回填循环 float area = primintrinsic(0, 'measuredarea', @primnum); if (area > chf('min_lot')) { int dir = rand(@primnum + detail(-1, 'iteration')) > 0.5; // ...按方向调用 clip 面或返回切线(实现细节随版本而异) }
  1. 每个小地块上收缩边界(向内偏移出红线距离),中心即建筑足迹;
  2. 足迹 Extrude 拉高——高度不是常数,而是属性:
// 离市中心越近越高 + 随机起伏:城市天际线的最小模型 float d = length(v@P - chv('center')); @height = fit(d, 20, 400, 80, 8) * (0.6 + 0.8 * rand(@primnum));

十几栋楼出来后你会立刻看到"市中心高、周边矮"的天际线雏形——天际线不是逐栋设计的,是距离场的输出

图 4.2-1 城市生成的分层规则栈

街网生长:两种策略

地块切分之前得先有街。常见两派:

策略 做法 视觉结果 适用
网格法 规则格网+扰动、斜穿主干道 曼哈顿式秩序 新大陆城市
生长法 从种子点沿吸引子延伸、遇障碍绕行 有机蔓延 老欧洲城市、村落

生长法与 3.4 的 L-System 一脉相承——道路网就是一棵改写规则驱动的树:每步延伸时按方向偏好(沿等高线、朝水源、避陡坡)分叉或转向。4.1 的 flow、slope 掩码在这里直接当成本函数用:地貌数据第二次上岗。

风格与真实数据

变体控制的三档投入:

  • 纯规则:样式表(建筑高度带、材质调色板、屋顶类型)+ 种子。零数据成本,风格统一但"哪都像";
  • 规则+参考图:密度图、天际线轮廓图作为约束场喂给规则——保持艺术方向的控制权;
  • 真实数据接入:路网与建筑轮廓从开放地理数据导入(用 2.3 的 Python 读入),程序化只负责"补全细节"(立面、楼层、损毁)。电影与 AAA 项目里这是常态——真实布局给可信度,程序化给规模

⚠️ 常见坑:追求"每栋楼都程序化生成"的全自动执念。城市可信度来自宏观秩序(街区、天际线、路网逻辑),微观多样性可以靠有限的建筑变体+散布解决。规则层级越高的部分越值得程序化。

💡 关键直觉:城市不是"很多建筑",是"被交通与经济规律切分过的空间"。先模拟切分,再填充建筑——顺序反了就是楼堆。

本节要点回顾

  • 方法四步:掩码选址 → 街网 → 地块切分 → 足迹填充;
  • 天际线=距离场的输出,不要逐栋调高度;
  • 街网两派:网格法(秩序)与生长法(有机,本质是 L-System 思想);
  • 变体三档投入:纯规则、规则+参考、真实数据;
  • 程序化做宏观秩序,变体库给微观多样性

环境长好了。第 5 章让这座山谷"动起来":约束与解算器。

延伸:地块划分的三步流水线

程序化城市的骨架是地块(Parcel)划分,标准流水线三步走:主干道(样条+噪声扰动)切出街区,偏移(Shrink)得到建筑红线,OBB/递归切分填满地块:

[地块流水线] 1. 道网: 曲线网络(自由绘制 or L-system 街区母版) ->Curvenet 2. 街区: Curvenet 提取面 -> Fuse -> Facet -> 面积过滤(去碎片) 3. 地块: Sort by area -> For-Each: 递归对半切(Orientation 沿长轴) 直到 fit(面积, lot_min, lot_max) 命中目标区间 4. 退线: PolyExpand2D(负值) 得建筑足迹, 留出人行道

这套流水线的价值在参数化城市形态:lot_min/lot_max 调大立即从曼哈顿变郊区独栋,路网密度参数一扫,城市的"性格"连续可调。

廕伸:建筑立面的语法装配

// 楼板生成后: 立面按朝向+楼层双循环装配(VEX 顶层逻辑示意) int floor = i@floor_idx; float w = f@tile_width; int modules = max(1, int(w / ch("unit_w"))); i@style = i@floor_idx % 2; // 奇偶层交替 // For-Each module 内按 style 分派: 窗/阳台/广告位 HDA 实例 s@module_tag = choose(["window","balcony","blank"], int(rand(floor*31 + @elemnum)*3));

城市生成的黄金分层是"路网→地块→体量→立面→细节"五层各自参数化、逐层冻结缓存,任何一层的需求变更都不会点燃整条管线——这个分层法将在第六章 PDG 里升级为正式的工作单元划分。

关于城市生成还有一个容易被低估的维度:地标与记忆点。纯参数化城市最大的风险是"处处都真实、处处都无聊",因为真实城市的魅力来自历史的偶然——斜插的旧教堂、突然弯掉的主街。工程做法是"程序化打八成,手工占两成":在参数系统里预留手工地标位(指定地块直接引用美术制作的 hero 资产,跳过装配管线),并把主街路径留给构图师的曲线输入。程序化提供广度,手工提供焦点,两成的手工通过引用接口进入八成的系统而非相反——这是所有大规模生成内容管线的黄金配比。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U