ARCHITECTURAL COMPUTATION / CASE 01GPT‑6 Astra 3D 建模能力测试 · 卢浮雅邸
GPT‑6 Astra · 3D 建模测试

从设计图,
到可编辑的
几何体。

这里展开的不只是最终效果。你可以看到尺寸如何被选定,窗框如何计算位置,几万个构件怎样写入 Blender,以及哪些问题是在真实渲染之后才被发现。

开始拆解模型
最终 Blender 建筑与庭院渲染
01 / 最终工程实际渲染程序化建模 · Cycles
854,463场景中实际网格顶点
721,561多边形面 · 非三角面计数
287合批后的网格对象
8最终渲染视角 / 1440 × 960
先明确方法:这次是根据图像进行人工解释,再用 Python / bpy 生成模型。没有使用摄影测量、自动三维重建或逐像素尺寸标定。二维图中看不见的尺寸与构造,是建模假设。
绿色标记 / 原始文件与实际记录金色标记 / 为解释新增的复现或示意红色标记 / 失败与未解决边界
01
READING → ASSUMPTIONS → RULES

先确定规则,再堆积细节。

以下规划根据实际脚本、当时的进度说明和 trace 重建为可读的决策摘要。它解释做了什么、采用了什么依据,以及哪些地方属于推定。

建模前的外观概念设计板
输入 A:外观概念图原设计文件
建模前的四个室内设计空间
输入 B:四个室内空间原设计文件
可观察的关系选定的建模规则代码如何实现证据与局限
中央突出、左右对称1 + 3 + 3 + 3 + 1,共 11 开间轴线数组 + 分段坐标变换从图中解释;没有像素标定
拱窗细长、上下窗对齐底层 1.60 × 3.65 m;上层 1.55 × 3.25 mwindow(x,z,w,h,arched)数值为选定参数,不是实测
深色折线屋顶与老虎窗陡坡下段 + 缓坡上段多圈四边形连接;坡面插值排瓦瓦片和窗为几何;未做完整防水构造
门厅通高、楼梯弯曲楼板留空;30 级弧形踏步半径、角度和高度同步递增空间关系推定,未作结构校核
装饰丰富、重复较多建立少量可复用的几何函数旋转体、管线、叶饰、曲面雕刻为抽象近似,非数字雕塑复原
图像特征尺寸假设构件函数批量网格渲染检查修正与保存

为什么先做构件库?

同一层窗户只有少量参数不同。如果每扇窗都单独摆放,很容易出现高低不齐、窗套厚度变化。把重复规律写成函数后,位置来自统一轴线,尺寸来自同一组参数。

工程使用米作为单位。墙体、地面、屋顶与室内先建立关系,再添加石材分缝、栏杆、家具和庭院。四个重点室内空间放在建筑内部,其他空间保留为框架。

02
ASSEMBLY SEQUENCE

逐层看,模型是怎样长出来的。

点击阶段查看从楼板、立面到屋顶与庭院的组合。画面来自最终工程的集合开关复现,不是历史时刻截图;“室内剖开”是解释视图,不是实际施工剖面。

按构建阶段显示模型
复现画面 / 同一最终模型的集合显隐

本阶段增加或隔离的内容

对象不等于构件。一排瓦片可能处在同一个网格对象里,但仍由许多独立的顶点与面组成。最终只保留 287 个网格对象,是因为重复细节按“集合 × 材质 × 构件名称”合并,减少场景管理开销。
03
THE GEOMETRY KERNEL

底层没有“墙”的概念,只有点和面。

“创建一块石材”最终会变成一组顶点坐标和面索引。下面用脚本中的同一种长方体拓扑,演示从 8 个点到 6 个四边形面,再到世界坐标的过程。

示意使用相同的 8 顶点 / 6 四边形拓扑;数值可视化不修改 .blend。

以一块长方体为例

  1. 输入中心 c=(x,y,z) 与尺寸 s=(宽,深,高)
  2. 尺寸除以 2,组合正负号,得到八个角点。
  3. 如果需要,绕局部 Z 轴旋转。
  4. 面用顶点编号表示,例如 (4,5,6,7) 是顶面。
  5. 应用全局原点 O 与旋转 A
  6. 把顶点和面追加到批次缓存。
世界 X = Oₓ + x·cos(A) − y·sin(A) 世界 Y = Oᵧ + x·sin(A) + y·cos(A) 世界 Z = O𝓏 + z
同样的局部窗户可以先在“墙面 Y=0”附近生成,再通过旋转放到侧面。尺寸规则不用重写。

真正写入 Blender,发生在 flush()。

前面的函数大多只往 Python 列表里追加几何数据。flush() 遍历每个批次,调用 from_pydata(vs, [], fs) 建立网格,再创建对象、绑定材质、放入集合、添加部分倒角和平滑着色。第一轮实现约 53 万面,细化后约 72 万面。

曲线为什么也能变成网格?

tube() 先估计路径切线,再构造两个与切线垂直的方向。在每个路径点周围放一圈顶点,相邻圆环连成四边形。扶手、卷草、吊灯枝臂和水线都复用这套方法。

花瓶、柱础怎样生成?

lathe() 接收一串“半径、高度”。每个截面绕竖直轴转一圈,相邻截面连接,便成为旋转体。改变截面曲线,就能得到不同器形。

04
A WINDOW, GENERATED

窗框不是逐根猜位置,
而是从宽、高和圆弧推出来。

调节参数,观察底层拱窗的组成。原模型底层参数是 w=1.60 m、h=3.65 m、窗底 z=0.90 m。图中示意对应脚本的计算规则,石材线脚进行了简化绘制。

零件本次选定尺寸
左右边框 / 中央框55 mm
内部细竖棂22 mm
水平横框45 mm
半圆内部放射棂7 根
玻璃位置局部 Y=0.21 m

立面图表达外形与分格,未指定窗型厂商。这些厚度都是视觉参数,不是经过计算的型材规格。

调整这里的参数只改变教学示意,不会改写保存的 Blender 工程。

横向分格

边框:x ± w/2 中央框:x 细竖棂:x ± w/4 直段横框:z + (spring − z) × i/5

底层直段被横框分成五个高度区间。拱顶部分另外生成半圆框和放射棂;上层矩形高窗不使用圆弧。

前后层次

外墙为局部 Y=0,正 Y 指向室内。窗框中心约 0.12–0.13 m,玻璃约 0.21 m,墙体内侧约 0.64 m。玻璃是表面网格,没有多层中空玻璃构造。

05
ONE RULE, ELEVEN BAYS

同一扇窗,如何成为整栋立面。

先确定窗轴线,再围绕窗洞填充墙体。下面的轴线来自脚本中的实际分组坐标,不是均匀撒点;点击任意窗位可查看该窗的中心和所属分段。

点击窗位,查看轴线数据。上、下层复用同一组 X 坐标,以保持竖向对齐。

真实窗洞是留出来的。

脚本将每个窗洞的左右边界加入 cuts。相邻窗洞之间建立窗间墙;窗底以下补窗下墙,窗顶以上补过梁区。拱顶上方根据圆的关系计算墙体下边界:

z(x) = spring + √(r² − (x − centerX)²)

因此没有一整面实墙挡在玻璃后面。前后与侧面通过变换重复生成,中央和端部使用不同的 Y 值制造凸出。

立面分段前立面外表面 Y
中央三开间−8.55 m
左右中段−8.00 m
端部楼亭−8.85 m
左右侧立面X=±17.70 m,旋转 ±90°

示意中的开间划分准确对应轴线。屋顶老虎窗的轴线来自另一组手动参数,并未全部与下层严格协调。

06
ROOF / ORDER / ORNAMENT

屋顶靠插值,装饰靠复用。

复杂外观由几种基础算法叠加而成:截面连接、沿坡面排布、曲线管线与叶片曲面。

增加屋顶之后的模型集合复现
主体 + 立面 + 装饰 + 屋顶集合复现
  1. ① 用三圈点描述屋顶轮廓屋檐、陡坡顶部、上部屋脊。相邻四边形环连接成连续屋面。
  2. ② 在四个陡坡面上逐排取点在坡面上下边界之间插值,每排再分割成许多片瓦。
  3. ③ 赋予细小层次与颜色变化瓦片略高于底层,不同蓝灰材质随机分配;固定随机种子以便复现。
  4. ④ 添加老虎窗、收边和烟囱独立构件按位置放入,再通过渲染检查遮挡。

柱式与山花

柱础和柱身采用旋转体;竖向附加几何表现柱身细部;柱头用叶片和卷涡组合。三角山花是实体三角形场,边缘有多层斜向线脚,中央放置盾饰,两侧重复卷草。

这不是古典柱式的严格比例推导,也不是把图中人物雕塑逐一重建。重复叶饰可传达风格,但细节还原有限。

一片叶饰如何出现

叶片沿高度分段,宽度由正弦函数收放,局部起伏形成锯齿,Y 方向的弯曲让表面翘起。卷涡则是半径逐渐缩小的螺旋路径。

07
SPACE → STAIR → FURNITURE

先有空间关系,再放楼梯与家具。

底层门厅居中、餐厅与会客厅分居两翼,主卧放在二层一侧。下图用于解释布局,未表达所有隔墙、门洞及施工尺寸。

上方为花园侧,下方为到达庭院。尺寸方向与模型坐标一致;该图为代码布局的简化示意。

去除外墙屋顶与天花后的室内几何复现
去除外壳与部分楼板后的室内几何解释视图

视图通过集合显隐制作,因此会出现悬浮部件。它展示室内对象在建筑中的位置,不代表真实的建造先后或可施工剖面。

弧形楼梯:角度和高度同步递增

几何规则演示
内半径 ri = 2.22 m 外半径 ro = 3.48 m 角度跨度 = −0.90π(约 162°) 30 级,总上升 = 4.81 m 第 i 级高度 = 0.70 + (i+1)·4.81/30

每级踏步用内外半径和两端角度得到四个角点,再加入上下高度形成实体。扶手沿同一弧线连续上升。初版把踏步一直延伸到地面,后改为每级厚约 0.23 m 的薄体。

几何连续不等于楼梯设计已通过验证。这里没有检查净高、扶手安全间距、平台衔接或结构承载。

软包:把椭球改得更像靠垫

初版使用椭球,软垫呈圆鼓形。细化后采用超椭球:对三角函数的绝对值取小于 1 的幂,让截面接近圆角矩形。床品另用起伏网格表达褶皱;没有运行布料物理模拟。

窗帘与地板

窗帘沿横向使用余弦起伏,再沿高度下垂,形成褶皱。木地板由分块底板、边框和对角条组成;视觉检查后把条带压薄,避免出现格栅效果。

其他家具也复用底层函数:chair()sofa()table()fireplace()vase()。在末尾完整代码中可直接搜索它们,不需要依赖外部模型资源。
08
MATERIALS / LANDSCAPE / LIGHT

几何决定形,材质与光让它可读。

40 个自定义材质使用 Blender 节点生成。基础色、粗糙度、金属度和透射控制表面;噪声参与颜色与凹凸。没有调用扫描材质库。

浅色石灰岩

Base RGB .69 / .61 / .47
Roughness .70 · Noise .18

建筑玻璃

Transmission 1.00
Roughness .025 · Metallic 0

旧金色金属

Metallic .78
Roughness .27

象牙色织物

Roughness .86
Noise scale 150

色块是材质参数的概念示意,显示器颜色与渲染结果会受色彩管理和照明影响。

庭院不是背景图片

花坛是平面和低矮长方体,卷草绿篱沿螺旋线生成。喷泉池壁是旋转截面,水面是圆盘,喷射水线沿抛物线形成细管。树木由枝干、冠层和大量叶片组成,仍带有明显的程序化外观。

相机和渲染设置

使用太阳光、天空环境、室内面光和吊灯补光。先低采样检查,再以 64 采样输出 8 张最终图,并使用降噪。保存工程的默认采样是 32;最终输出脚本覆盖为 64。

09
RENDER → INSPECT → CORRECT

不是一次生成就结束。

拖动对照滑杆查看检查前后。不同轮次还同时改变了灯光、玻璃和采样,不能把整张图的变化都归因于某一个修正。每个案例标明图像来源。

A / 老虎窗被自身遮住

原始首轮外观图 → 最终外观图
看到什么

老虎窗看起来像白色实体装饰,部分下缘被屋面埋住,玻璃不清晰。

定位到哪里

初版老虎窗使用整块墙体;窗户前后位置与陡坡屋面发生遮挡。

具体改动

把整块墙改成两侧窗壁与上部过梁,并向室外移动老虎窗。最终画面可见窗框与玻璃。

普通老虎窗:|Y| 7.65 → 8.26 m 端部老虎窗:|Y| 8.42 → 9.04 m 整块实体 → 左右窗壁 + 上部过梁

初始外观 PNG 保留完好。初始版本脚本未完整归档;旧值来自当时的修改记录与初版工程,最终代码可在第 06 节核对。

B / 楼梯厚重、墙面细节藏在墙内

初版工程重新渲染 → 最终原图
看到什么

楼梯下方成为厚重实体,上层墙面装饰不明显,通高空间显得空白。

定位到哪里

每级踏步都从地面向上拉伸;部分护墙板朝向墙内,上层两侧缺少同样的饰面。

具体改动

踏步下表面从固定地面改为随踏步上升;调整墙面朝向并补上上层护墙板。

旧:for zz in [.67, z] 新:for zz in [z-.23, z] 后墙护墙板方向:π → 0 补充上层两侧的 panel_wall()

旧室内 PNG 已被覆盖。左图来自保留的 initial-untraced/Louvre_Residence.blend 的复现渲染,不是历史截图。

C / 地板像格栅,窗帘消失了

初版工程重新渲染 → 最终原图
看到什么

木地板对角条带明显凸起;窗帘埋在墙内;玻璃偏浑浊,软垫过于圆鼓。

定位到哪里

条带厚度与偏移过大;窗帘的位置超过墙体内侧;玻璃粗糙度较高,软垫采用普通椭球。

具体改动

压薄条带、移动窗帘、提高玻璃透射并降低粗糙度;部分靠垫改为超椭球。

条带厚度:.022 → .001 m;偏移 .040/.043 → .016/.017 m 后侧窗帘:Y=7.60 → 7.11 m 玻璃:Transmission .68 → 1;Roughness .12 → .025 部分软垫:ell() → softbox()

D / 主卧镜头撞上新窗帘

旧相机位置复现 → 修正后的原图
看到什么

最后一次检查发现画面左侧被窗帘与挂杆挡住;模型本身不需要重做。

定位到哪里

新增窗帘后,原主卧相机位于其附近。应调整取景,而非删去窗帘。

具体改动

相机从 (6.10,7.10,7.05) 移到 (7.05,6.30,7.05),保持目标点,保存后重新渲染。

E / 天空节点接口失败

实际异常记录
失败是什么

Blender 5.2 不再接受脚本中的旧枚举 NISHITA,构建在保存前中断。

怎么确认

读取错误提示,并在本机查询 ShaderNodeTexSky 可用字段,单独测试新的枚举与属性。

怎样修复

使用本机支持的 MULTIPLE_SCATTERING。重跑带 trace 的构建,随后重新打开文件验证。

10
THE AUDIT TRAIL

代码说明方法,trace 说明实际发生了什么。

这里展示真实日志的时间线与代表性调用。为保持 HTML 可离线打开,没有把约 999 MB 的全部原始 trace 塞进页面;内嵌的是原始事件摘录,完整文件保留在原项目中。

当天的实际运行

时间显示为北京时间(UTC+8)。原始记录使用 UTC。同一时间可有构建、验证或渲染进程重叠,列表按运行开始时间排列。

纠正统计口径:138,451 是被记录的函数调用次数,其中包含 58,800 次 sp() 数学辅助调用,以及嵌套构件函数。它不等于 138,451 个独立对象或手动操作。“纯数学计算全部排除”的早先表述过于宽泛:坐标变换 tr() 被排除了,但 sp() 没被排除。
记录函数调用138,451
扣除 sp() 后的函数调用79,651,仍包含嵌套调用
Blender 相关源码行事件634,491,不等于不同 API 数量
最终主体运行run_complete,无未完成函数调用
StopIteration 记录106 次,迭代控制信号,不是建模失败

记录器使用 sys.settrace:函数进入记录参数,退出记录结果,异常记录类型;命中筛选条件的源码行记录为 blender_statement。它不是 Blender 内部每个 C/C++ 操作的录像,也不记录所有鼠标或操作系统动作。

operation_start #父子构件调用blender_statementoperation_complete / exception
用户提出 trace 要求前的第一次生成,仅保留普通运行日志和初版工程,没有逐操作 trace。后来重新生成模型以建立记录。本 HTML 新增的集合隔离与复现渲染,也有独立的 trace;原模型没有因此被改写。
11
VERIFIED OUTPUT / KNOWN LIMITS

验证的是文件与几何,
不是建筑可施工性。

最后用独立后台进程重新打开保存的工程,再检查场景、依赖与渲染文件。下面数据来自 verification.json 和 delivery_verification.json。

已经核验

    尚未覆盖

    • 严格比例复原没有相机标定、逐像素拟合或完整平立剖控制图。
    • 完整居住功能四个重点室内空间已布置;其他区域不是完整住宅施工方案。
    • 建筑工程要求未校核承重、楼梯规范、门窗性能、防水和机电。
    • 高精度资产雕塑、叶饰、织物和植物仍是程序化近似。
    • 几何质量全检重新打开与有限值检查不等于无穿插、流形或拓扑全面审查。
    统计差异也保留说明:构建时数据块列表显示 854,471 顶点、721,567 面;重新打开后按场景对象统计为 854,463 / 721,561。差值是一个未使用的 8 顶点、6 面数据块;本文使用实际场景统计。
    12
    SOURCE DESK

    继续往下,直到每一行代码。

    主建模代码采用最终成功主体运行时的快照。快照中主卧仍是旧相机位置;最后的相机修正由 refine_camera.py 单独记录。可选择文件、搜索关键字、复制或下载内嵌源代码。

    关联文件

    以下链接依赖原项目目录;正文图片、代码和样本无需联网
    Louvre_Residence.blend ↗ 可编辑模型 · 材质和设计图已打包(原项目附件,未随博客发布)Louvre_Residence_Delivery.zip ↗ 原建模交付包 · 约 91 MB(原项目附件,未随博客发布)trace.jsonl.gz ↗ 原建模、修正与验证的完整压缩记录(原项目附件,未随博客发布)trace_summary.json ↗ 最终主体统计与各次运行索引(原项目附件,未随博客发布)复现渲染的逐操作 trace ↗ 本 HTML 新增分层图与检查复现图的真实记录(原项目附件,未随博客发布)provenance.json ↗ 本页面新增复现图的来源说明(原项目附件,未随博客发布)verification.json ↗ 重新打开工程后的验证结果(原项目附件,未随博客发布)
    放大的过程图