Code-as-Room: Generating 3D Rooms from Top-Down View Images via Agentic Code Synthesis

Paper: arXiv:2605.18451 Code: YxuanAr/Code-as-Room Code reference: main @ ffd266c6 (2026-05-22)

1. Motivation (研究动机)

这篇论文要解决的是一个非常具体的 3D 场景生成问题:给定一张 top-down room image(俯视图、草图、layout-like image 或平面布局参考),自动生成一个完整、可渲染、可编辑的 Blender 3D room 程序。作者把目标设为“从图像到 Blender code”,而不是只生成一张室内效果图,因为 code 表示可以继续编辑、换视角渲染、检查几何关系,也更适合 VR、游戏、室内设计和 Embodied AI 的下游使用。

当前方法的瓶颈主要有三类。第一,传统 procedural / rule-based / optimization-based indoor scene synthesis 依赖手工规则、固定类别和设计约束,难以覆盖真实室内空间里复杂的物体组合、墙面元素、支撑关系和用户偏好。第二,text-to-scene 或 text-conditioned MLLM 方法虽然可以输出 JSON / scene graph / object attributes,但文本很难精确描述物体数量、位置、朝向、支撑面和区域功能,因此生成的 3D room 往往与用户心中的空间布局不一致。第三,已有 image-conditioned agent(论文重点对比 VIGA)在 perspective image reconstruction 上可行,但直接迁移到 top-down holistic room generation 时会丢失细粒度空间细节,并且 generator–critic loop 容易陷入无限循环,导致生成不稳定、Blender code 不可靠。

作者的关键观察是:真实设计流程里,top-down layout / sketch / floor-plan-like image 本身就是很强的空间先验。它比文字更直接地编码了房间边界、功能区域、家具相对位置、朝向、墙面/门窗位置和整体比例。如果能把这个空间先验拆解成可执行的阶段化 code synthesis 流程,就可以同时利用 MLLM 的视觉理解、空间推理和代码生成能力,又避免“单次生成整屋代码”带来的上下文遗忘和循环失控。

Figure 1 解读:这张 teaser 展示了任务形式:输入可以是多种 top-down room images,输出是 Blender 中可交互的 3D scenes。它强调 Code-as-Room 的核心不是做 2D image translation,而是让 MLLM 通过结构化执行 harness 生成可执行、可编辑的 Blender scene code。

2. Idea (核心思想)

核心思想是把 3D room generation 重新表述为 top-down image-guided agentic code synthesis:图像提供全局空间先验,MLLM 负责分阶段理解、生成和修复 Blender code,cross-stage memory 负责把前面阶段的结构化输出保留下来,避免长链路 agent workflow 中的 context forgetting。

这与 VIGA 这类 analysis-by-synthesis agent 的根本区别在于:Code-as-Room 不让一个 agent 在同一个 loop 里“看图—写整屋代码—critic—再写整屋代码”,而是把问题拆成五个语义阶段:image-based scene structuring、layout code generation、layout-grounded object profiling、object-level code generation、interior decoration code generation。每个阶段只处理一个相对清晰的中间表示,并把结果写入 typed memory entry,下游阶段按需读取 memory view。

这种设计的直觉是:俯视图到完整 3D room 的难点不在某一个模型能不能写 Blender API,而在“空间一致性”和“细节可控性”必须逐层锁定。先固定房间边界、主要家具和支撑关系,再补局部几何、材质、纹理和光照,可以减少后续阶段推翻前面布局的概率;render-and-compare visual feedback 只修正 layout-level 错误,也比让 agent 在最终渲染阶段大幅重写场景更稳定。

3. Method (方法)

3.1 Overall framework:从俯视图到 Blender scene code

给定房间级 top-down image ,目标是生成可执行 Blender code ,其中 code 同时定义房间结构、物体位置、物体几何、材质和光照。论文把整个系统写成: 其中 是 Code-as-Room 的 VLM-agent harness。直接从 一次性生成完整 很困难,所以作者采用 coarse-to-fine decomposition。粗阶段先构建 scene understanding 和 layout program: 细阶段再基于 layout 进行 object profiling 和最终 code generation: 这里 是所有阶段共享的 cross-stage memory。这个分解把全局空间对齐和局部细节合成分开:粗阶段锁定 room structure、major object placement 和 layout relations;细阶段只在既定 pose/scale 上增加 editable geometry、appearance 和 rendering code。

Figure 2 解读:pipeline 图把系统分成五个 phase。左侧输入图像先经过 scene classifier / spatial semantic analysis / scene graph construction,形成 coarse understanding;中间 layout code generation 使用 visual feedback loop 逐轮渲染、比较和修正;后续 object-level stages 把 bounding-box proxy 替换成由 primitive parts 组成的对象,并为小物体、材质、纹理和光照生成代码。图中的 memory arrows 是关键:每个阶段将 typed artifact 写入 memory,下游只读取需要的 memory view,而不是依赖一个不断膨胀的 prompt。

3.2 Cross-stage memory:让长链路 agent 不遗忘

每个阶段 产生 typed artifact: 其中 是阶段编号, 是 artifact 类型, 是阶段输出, 是 metadata。memory 更新为: 下游阶段不是无差别读取全部历史,而是读取预定义 memory view。这样做有两个作用:一是保留早期视觉解析出的 object ids、parent relations、wall anchors、minor-object sidecar,避免后面生成 geometry / material 时忘记;二是减少 prompt noise,降低 agent 为了“补全上下文”而 hallucinate 新对象或新关系的概率。

released code 中,agent_utils/memory.py 定义 MemoryEntryMemoryMemoryAwareAgent,实际把 memory 写成每个 run directory 下的 agent_memory.jsonl。这对应论文中的 ,但实现层面还提供 get_latestget_by_stageget_context_for_stagequery_by_semantic_tags 等检索函数。

3.3 Image-based scene structuring:先把图像变成可约束的 scene state

前两个 stage 负责把输入图像 转成结构化 scene state。

Stage 1: spatial semantic analysis

Stage 1 输出 schema-constrained description 包括 functional zones、object hierarchies、architectural elements。每个 object 被赋予 identifier、category、placement type 和 parent;walls、doors、windows、openings、built-in structures 被保留为固定空间参考。论文特别提到 perimeter-aware prompt:它扫描墙、角、开口和 coarse grid,以恢复 peripheral / wall-mounted objects。这一步如果缺失,后续 layout stage 很容易只放出中心家具,漏掉贴墙柜、门窗、墙面装饰等约束物。

Stage 2: object-centric scene graph construction

Stage 2 读取 ,先构造 deterministic skeleton: 其中 是建筑元素, 是 layout-defining objects, 是 hierarchy-derived relations, 是稍后处理的小物体 sidecar。VLM 只补全 attributes、geometry hints 和 forward relations,不允许随意改写 skeleton。最后过滤非法边、添加 inverse relations 和 wall/corner anchor relations: released code 中,agent_utils/stage2/run_stage2.py_build_node_skeleton_derive_wall_edges_derive_corner_edges_make_inverse_edge_merge_skeleton_with_llm 体现了“先 deterministic skeleton、再让 LLM 补属性/关系”的策略。这是论文方法中比单纯 prompting 更稳定的部分。

3.4 Layout code generation:用可渲染 proxy 锁定空间关系

Layout stage 生成粗布局程序 。对象先以 Blender 中的 named bounding-box proxies 实例化,包含 approximate position、scale 和 orientation;详细几何、材质、光照和 tiny objects 推迟到后续 stage。因为每个 placement 都是 primitive-constructor call, 可以被渲染成 top-down image,也可以被后续 stage 解析。

Stage 3: major layout with visual feedback

Stage 3 通过 render–critique–revise loop 修正 major object layout。初始化: 轮先渲染当前 code,再让 VLM critic 比较输入图和渲染图: critic 输出 textual feedback 和 layout quality score ,分数覆盖 object coverage、overlap、boundary consistency 和 spatial relation correctness。由于 critic 可能建议不受支持的建筑改动,系统先做 sanitize: 停止条件是 或达到最大迭代 ;论文实验和 released config 都使用 。released code 的 example/pipeline_config.example.jsonmax_iter=5target=0.85run_pipeline.pyUnifiedPipeline.run_stage3 调用 Stage3 runner,并在每个 run directory 保存 stage 输出。

Stage 4: wall objects and selected minor placeholders

Stage 4 冻结 major layout,再追加 wall-mounted objects 和 coarse-scale visible minor objects。wall-mounted objects 会根据 scene graph 中的 semantic anchors 对齐到推断的 wall planes;minor sidecar 中只保留在 coarse layout 尺度可见且不是 surface-bound 的对象: 这包括 rugs、floor lamps、plants 和 large decorations;books、cups、small tabletop items 等 tiny surface-bound objects 被推迟到 fine-grained placement。设计上,Stage 4 的作用是补足会影响空间占用和布局理解的对象,而不让早期布局阶段被小物体细节淹没。

3.5 Object-level code generation:从 proxy 到可编辑局部几何

Stage 5: layout-grounded object description

Stage 5 解析 中已经放置的对象,保留每个 object 的 identifier、category、pose 和 size,再结合输入图与 memory 生成 fine-grained object descriptions 。描述包括 color、material、function、structure、style,以及全局 room-style JSON。它不应改变物体放置,只补足“这个椅子/桌子/柜子长什么样、由哪些语义部件构成、材质风格是什么”。

Stage 6: object geometry replacement

Stage 6 对每个 placed object 预测 semantic 3D primitive decomposition: 每个 part 指定 primitive type、semantic part name、local size、offset 和 rotation。因为 parts 定义在原 proxy 的 local frame 中,生成对象继承 coarse layout pose,从而避免 geometry 细化时破坏整体布局。代码替换写作: 同一映射还会保存为 geometry dictionary,供后续 surface discovery 和 material assignment 使用。

Tiny objects: procedural placeholder + retrieval

对几何细节复杂的小物体,论文采用 hybrid procedural-and-retrieval。先创建简单几何 placeholder 来保留位置和占用区域,再从 asset library 中检索匹配资产: matching score 同时考虑语义相关性和尺寸兼容性;选中的 asset 被 scale / align 到 placeholder,保持支撑面和 footprint。released repo 目前的 README 标注:3D assets retrieval checkpoint 尚未发布;codebase 中 Stage 7–9 已有 small-object placement / description / geometry 的 optional extension,但 example/pipeline_config.example.json 默认 detail_small_objects=false,只有打开 --detail-small-objects 才运行 Stage 8 和 Stage 9。

3.6 Interior decoration code generation:材质、纹理、光照和 post-hoc correction

布局和对象几何固定后,系统通过 geometry-preserving rewriting 完成外观与渲染: Stage 8/10(论文编号/代码编号存在差异,见下文)进行 part-level PBR material assignment:输入 part dictionary、fine-grained descriptions 和 global room style,输出 material type、linear-RGB base color、roughness、metallic、specular strength,并注入 Blender script。Glass / mirror-like surfaces 通过 material type 或 part-name keywords 触发 shader overrides;floors / walls 使用 procedural shader nodes。

Texture stage 为 floors、walls、rugs、paintings、posters、decorative panels 合成 texture maps,并把 image-texture nodes 注入 material graph。Render stage 根据输入图和当前 scene 推断 overall lighting style,包括 dominant illumination direction、window-driven natural light、artificial light sources 和 ambient intensity,再生成 Blender light objects 和 Cycles render settings。

最终 post-hoc correction 修复 missing material assignments、invalid texture paths、unreasonable light intensities、incomplete camera coverage 和 geometric artifacts。对边界或碰撞违规的可移动对象,论文写作局部投影搜索: subject to 这里 是生成位置, 是局部网格邻域, 是房间边界,碰撞约束只对 nearby non-parent objects 应用。实践中用 deterministic local search、boundary clamping 和 stacking offsets 实现。

论文公式与 released code 实现差异

论文把五个 phase 展开成 Stage 1–10,并在文字中称 material / texture / lighting 分别是 Stage 8、Stage 9、Stage 10;released code 的 README 和 run_pipeline.py 则是 Stage 0–12:Stage 0 scene classification,Stage 7 surface-based small-object placement,Stage 8/9 是 optional detailed small-object extension,Stage 10 per-part PBR material,Stage 11 real texture generation,Stage 12 lighting/render settings。因此本文笔记中的方法编号以论文叙述为主,但代码映射以 main@ffd266c6 的实际 stage 编号为准。

另一个差异是 retrieval assets:论文描述了 asset library 和 retrieval-based replacement,但 README 的 Release Plan 显示 “3D assets retrieval checkpoint release” 尚未完成;当前 release 更偏向 code-only geometry、optional small-object geometry 和 texture/render generation。最后,论文 benchmark 是内部/人工修正的 41-scene benchmark;README 标注 benchmark release 仍在计划中,因此 released repo 不能直接复现论文完整 benchmark 数字。

3.7 Pseudocode(基于 released code 的实现抽象)

from pathlib import Path
 
class AgentMemory:
    def __init__(self, run_dir: Path):
        self.path = run_dir / "agent_memory.jsonl"
        self.entries = []
 
    def add(self, stage: str, entry_type: str, content: dict, metadata: dict | None = None):
        self.entries.append({"stage": stage, "type": entry_type, "content": content, "metadata": metadata or {}})
        self.path.write_text("\n".join(serialize(e) for e in self.entries), encoding="utf-8")
 
    def latest(self, stage: str, entry_type: str = "result") -> dict:
        for entry in reversed(self.entries):
            if entry["stage"] == stage and entry["type"] == entry_type:
                return entry["content"]
        raise KeyError((stage, entry_type))
def run_code_as_room(image_path, config):
    run_dir = make_run_dir(config.output_dir, image_path)
    memory = AgentMemory(run_dir)
 
    scene_type = classify_scene(image_path, config.scene_classify_model)
    memory.add("meta", "scene_type", scene_type)
 
    d1 = stage1_spatial_semantic_analysis(image_path, scene_type)
    memory.add("stage1", "result", d1)
 
    graph, minor_sidecar = stage2_object_graph(image_path, d1)
    memory.add("stage2", "result", {"graph": graph, "minor": minor_sidecar})
 
    layout_code = stage3_major_layout_feedback(
        image_path=image_path,
        scene_description=d1,
        scene_graph=graph,
        max_iter=config.max_iter,
        target_score=config.target,
    )
    memory.add("stage3", "result", {"code": layout_code})
 
    layout_code = stage4_append_wall_and_visible_minors(layout_code, graph, minor_sidecar)
    memory.add("stage4", "result", {"code": layout_code})
 
    descriptions = stage5_describe_objects(image_path, layout_code, memory)
    memory.add("stage5_describe", "result", descriptions)
 
    geometry_code, geometry_dict = stage6_replace_proxy_with_parts(layout_code, descriptions)
    memory.add("stage6_geometry", "result", {"code": geometry_code, "geometry_dict": geometry_dict})
 
    small_code = stage7_place_surface_small_objects(geometry_code, geometry_dict, minor_sidecar)
    if config.detail_small_objects:
        small_desc = stage8_describe_small_objects(image_path, small_code, memory)
        small_code = stage9_generate_small_object_geometry(small_code, small_desc)
 
    material_code = stage10_assign_pbr_materials(small_code, descriptions, geometry_dict)
    texture_code = stage11_inject_real_textures(material_code, image_path, config.stage11_texture_model)
    final_code = stage12_setup_lighting_and_render(texture_code, image_path)
    return posthoc_correct(final_code)
def stage3_major_layout_feedback(image_path, scene_description, scene_graph, max_iter=5, target_score=0.85):
    code = generate_initial_blender_layout(image_path, scene_description, scene_graph)
    for t in range(1, max_iter + 1):
        render_path = render_topdown_with_blender(code, name=f"layout_iter_{t}.png")
        critique = vlm_critique_layout(
            reference_image=image_path,
            rendered_image=render_path,
            graph=scene_graph,
            checks=["object_coverage", "overlap", "room_boundary", "spatial_relation", "rotation"],
        )
        if critique.score >= target_score:
            break
        safe_actions = sanitize_actions(critique.actions, scene_description, scene_graph)
        code = revise_blender_code(code, safe_actions)
        code = validate_and_patch_python_blender_code(code)
    return code
def stage6_replace_proxy_with_parts(layout_code, object_descriptions):
    placed = parse_create_box_calls(layout_code)
    geometry_dict = {}
    for obj in placed:
        desc = object_descriptions[obj.name]
        parts = vlm_predict_parts(
            category=obj.category,
            pose=obj.pose,
            size=obj.size,
            description=desc,
            output_schema=["primitive", "semantic_part", "local_size", "offset", "rotation"],
        )
        parts = clamp_parts_to_proxy(parts, proxy_size=obj.size)
        geometry_dict[obj.name] = parts
    return rewrite_proxy_constructors(layout_code, geometry_dict), geometry_dict
def stage10_to_12_appearance_and_render(code, geometry_dict, object_descriptions, image_path, config):
    material_specs = vlm_assign_part_materials(geometry_dict, object_descriptions)
    code = inject_pbr_material_functions(code, material_specs)
 
    texture_manifest = generate_texture_maps(
        code=code,
        image_path=image_path,
        texture_model=config.stage11_texture_model,
        image_size=config.stage11_texture_image_size,
        max_wall_arts=config.stage11_texture_max_wall_arts,
    )
    code = rewrite_material_nodes_with_images(code, texture_manifest)
 
    lighting = vlm_analyze_lighting(image_path, code)
    code = inject_lighting_and_cycles_settings(code, lighting)
    return fix_missing_materials_invalid_paths_camera_and_collisions(code)

3.8 Code-to-paper mapping

Code reference: main @ ffd266c6 (2026-05-22) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
CLI / full 12-stage orchestrationrun_pipeline.pyPipelineConfig, UnifiedPipeline, run_full_pipeline, main
Cross-stage memory agent_utils/memory.pyMemoryEntry, Memory.add, Memory.get_latest, Memory.get_context_for_stage, MemoryAwareAgent
Scene type routing before Stage 1agent_utils/scene_classifier.pyclassify_scene, read_scene_type, is_lab
Stage 1 spatial semantic analysisagent_utils/stage1/run_stage1.pyStage1Runner
Stage 2 object-centric scene graphagent_utils/stage2/run_stage2.py_build_node_skeleton, _derive_wall_edges, _derive_corner_edges, _merge_skeleton_with_llm, Stage2Runner
Stage 3 layout code and visual feedbackagent_utils/stage3/run_stage3.py, agent_utils/stage3/pipeline.py, agent_utils/stage3_rotation.pyStage3Runner, Stage3Pipeline, Stage3RotationRunner
Blender primitive layout harnessIncrementalLayoutEngine.pycreate_box, create_cylinder, IncrementalLayoutEngine.add_furniture, find_valid_position
Stage 4 wall objects / selected minorsagent_utils/stage4/run_stage4.pyStage4Runner
Stage 5 object descriptionagent_utils/stage5_describe.pyStageDescribeRunner
Stage 6 major-object geometryagent_utils/stage6_geometry.pyStageGeometryRunner
Stage 7–9 small-object extensionagent_utils/stage7_small_objects.py, agent_utils/stage8_small_describe.py, agent_utils/stage9_small_geometry.pyStageSmallObjectsRunner, StageSmallDescribeRunner, StageSmallGeometryRunner
Stage 10 material assignmentagent_utils/stage10_material.pyStageMaterialRunner
Stage 11 texture generation / injectionagent_utils/stage11_texture.pyStageTextureRunner, texture manifest / material-node rewrite helpers
Stage 12 lighting and render settingsagent_utils/stage12_render.pyStageRenderRunner, _analyze_lighting, _inject_lighting_function, _save_results
Validation and extraction helpersagent_utils/validators.py, agent_utils/stage3/core.pyvalidate_stage1_schema, validate_stage2_object_centric_schema, validate_stage3_code, extract_python_from_response
Reproducible run config exampleexample/pipeline_config.example.jsonmax_iter=5, target=0.85, start=1, end=12, detail_small_objects=false

4. Experimental Setup (实验设置)

4.1 Benchmark and data scale

论文构建了一个专门用于 code-based 3D room synthesis 的 benchmark,而不是使用已有室内场景数据集。测试集包含 41 scenes,覆盖不同 room types、scene complexities 和 image styles。普通 residential spaces 包括 bedrooms、kitchens、living rooms,并按 spatial scale 和 object density 分为 Simple、Middle、Hard;此外还包含 laboratories、barber shops、cafes 等 specialized scenes,用于测试模型在非标准家居环境下的泛化。

输入图像类型包括 photorealistic photos、synthetic renderings 和 abstract line drawings。由于这些多源输入没有统一 ground truth,作者采用 human-in-the-loop annotation:先用 Gemini 3.1 在 agent workflow 中生成 coarse labels,再由人工 annotators 通过 reverse code refinement tool 修正,保证视觉编辑和底层 scene code 同步。

4.2 Compared models and baselines

评估分两组。第一组是不同 VLM backbone 在 CaR harness 下的 benchmark:Gemini-3 Flash、Gemini-3.1 Pro、GPT-5.5。第二组是 direct generation / agent baseline:Gemini3.1-Pro single-pass、GPT-5.5 single-pass 和 VIGA。论文说明 Qwen-3.6 与 Claude Opus-4.6 在 preliminary runs 中常常不可用,因此没有纳入主 benchmark。

4.3 Metrics

评估指标分为四类:

  • Visual Understanding:Object Recall 衡量 code 是否恢复 annotated objects;Functional Accuracy 衡量 major functional regions 是否重建正确。
  • Spatial Reasoning:Self Overlap 越低越好;Layout IoU 衡量布局区域对齐;Spatial Relation Consistency、Rotation Accuracy、Support Accuracy 分别检查关系、朝向和支撑关系。
  • Code Generation:Agent Completion 衡量完整 multi-stage pipeline 是否完成;Execution Rate 衡量最终 Blender code 是否可运行。
  • Scene Quality:Image Similarity、Scene Usability、Aesthetic Quality 是 VLM-based score;human evaluation 另由 20 experts 对 similarity、usability、lighting alignment 和 acceptability 打分。Acceptability 表示生成场景能否只需少量人工修正就可使用。

4.4 Running / inference config from released code

论文没有报告训练过程、GPU 数量、learning rate 或 batch size;Code-as-Room 主要是 inference-time agentic harness,依赖 VLM/API、Blender 渲染和代码修复。released code 的可复现配置来自 example/pipeline_config.example.json,不是 base default:start=1end=12max_iter=5target=0.85、默认 backbone gemini-3.1-pro-preview-thinking、Stage 11 texture model gemini-3-pro-image-previewstage11_texture_image_size="1K"stage11_texture_parallel=8stage11_texture_max_wall_arts=20、Blender executable path /Applications/Blender.app/Contents/MacOS/Blenderparallel=16geometry_max_attempts=3geometry_retry_delay=2.0material_batch_size=6material_parallel=4material_max_attempts=3detail_small_objects=false

这说明论文的“training config”栏在本任务中应理解为运行/推理配置:没有 model training,主要超参数是 feedback iteration、score threshold、stage range、并行度、texture generation 设置和 Blender renderer path。

5. Experimental Results (实验结果)

5.1 Main benchmark numbers

Table 1 的核心结论是:直接 single-pass 生成在空间一致性和执行成功率上不稳定,而 CaR harness 可以显著提升不同 VLM backbone 的 object recall、layout IoU、agent completion、execution rate 和 scene quality。

Visual Understanding

MethodObj. Recall ↑Func. Acc. ↑
Gemini3.1-Pro / Single-pass17.8%15.3%
GPT-5.5 / Single-pass42.2%71.7%
Gemini3-Flash w/ CaR58.9%88.42%
Gemini3.1-Pro w/ CaR55.5%84.3%
GPT-5.5 w/ CaR67.5%72.54%

Spatial Reasoning

MethodSelf Overlap ↓Layout IoU ↑Spatial Relation ↑Rotation Acc. ↑Support Acc. ↑
Gemini3.1-Pro / Single-pass8.4%16.8%54.7%78.0%41.7%
GPT-5.5 / Single-pass14.5%46.2%50.8%65.3%52.6%
Gemini3-Flash w/ CaR2.57%72.0%76.9%93.5%93.5%
Gemini3.1-Pro w/ CaR3.3%73.2%79.8%93.6%94.0%
GPT-5.5 w/ CaR10.5%66.7%71.4%92.2%80.1%

Code Generation and Scene Quality

MethodAgent Completion ↑Exec. Rate ↑Image Similarity ↑Scene Usability ↑Aesthetic Quality ↑
Gemini3.1-Pro / Single-pass57.8%2.493.242.51
GPT-5.5 / Single-pass42.2%5.85.427.24
Gemini3-Flash w/ CaR100%100%8.326.077.17
Gemini3.1-Pro w/ CaR100%95.5%8.087.058.20
GPT-5.5 w/ CaR71.1%73.3%7.286.007.52

Figure 3 解读:这张 qualitative comparison 对应 Table 1。直接 VLM 生成常出现房间结构不完整、物体位置漂移、功能区缺失等问题;CaR 版本能更稳定地保留 top-down input 中的空间比例和家具安排。它直观说明 Table 1 中 Layout IoU、Spatial Relation、Execution Rate 的提升不是孤立指标,而是来自分阶段 layout scaffold 和 feedback loop。

Figure 4 解读:这张图展示了不同 VLM backbone 接入 CaR 后的代表性结果。Gemini-based variants 更容易恢复 shelves、cabinets、decorations、tabletop objects 等局部结构;GPT-5.5 更能保留 coarse layouts,但小细节会简化。论文因此强调,最终质量既依赖 base VLM 能力,也依赖 agentic workflow 如何组织视觉理解、空间推理和代码生成。

Figure 5 解读:Figure 5 进一步放大局部区域,展示细节层面的差异。CaR 的优势不只是“房间大致像”,还包括小型装饰、柜体层级、桌面/墙面物件和局部功能区域的恢复。这支持作者在 Method 中把 object profiling、small-object handling、part-level geometry 和 material stages 单独拆出来的设计。

5.2 Human evaluation

20 位 experts 从 similarity、usability、lighting alignment、acceptability 四个维度评价整体 scene quality。CaR variants 在 similarity / usability / acceptability 上明显优于 direct generation 和 VIGA。

MethodSim. ↑Use. ↑Light ↑Accept. ↑
Gemini3.1-Pro / Single-pass2.00.04.01.0
GPT-5.5 / Single-pass7.06.06.55.0
VIGA5.54.58.04.0
CaR w/ GPT-5.57.57.08.06.5
CaR w/ Gemini3-Flash8.58.08.07.5
CaR w/ Gemini3.1-Pro9.08.08.07.5

Figure 6 解读:这张图直接对比 CaR with Gemini3.1-Pro 和 VIGA。VIGA 更容易生成 template-like scenes,细节缺失、物体位置和局部关系不准确;CaR 保留了 room proportions、furniture arrangements 和 local semantics。它解释了为什么 VIGA 的 Light score 可以达到 8.0,但 Sim. / Use. / Accept. 仍低于 CaR:视觉光照不等于空间布局可用。

5.3 Re-rendering as visual enhancement

作者还用 GPT-5.5 做 image-level re-rendering,以展示 generated Blender scenes 作为 3D structural priors 的潜力。基础 Blender scenes 可编辑且几何一致,但许多对象仍由 primitive shapes 构成,视觉真实感有限;re-rendering 可以在保持 room structure、object layout、spatial relations 和 camera-consistent geometry 的基础上改善材质、光照和对象细节。

Figure 7 解读:左侧是基础 3D scene / rendering,右侧是 GPT-5.5 re-rendering 后的视觉增强结果。关键点是 re-rendering 没有取代 Code-as-Room 的 3D code representation;它依赖 CaR 先提供稳定的几何和语义结构,再把视觉质感提升到更真实的水平。

5.4 Ablation: memory and visual feedback matter

Table 3 分析 cross-stage memory 和 visual feedback iterations。去掉 memory 会让 Object Recall 从 55.5% 降到 48.2%,Layout IoU 从 73.2% 降到 58.0%,Rotation Acc. 从 93.6% 降到 88.4%。这说明后续 stages 如果不能可靠复用早期视觉信息,就会漏物体、弱化空间一致性。

ConfigurationObj. Recall ↑Layout IoU ↑Rotation Acc. ↑
w/o Memory48.2%58.0%88.4%
Full Model (Ours)55.5%73.2%93.6%
w/o Visual Feedback (0 iter.)33.8%64.0%71.9%
Feedback ×335.6%65.7%73.2%
Feedback ×5 (Ours)38.4%66.2%75.4%
Feedback ×1039.1%64.2%72.6%

Figure 8 解读:上半部分展示 memory system 的影响:有 memory 时,后续 stages 能继承前面解析出的对象和空间关系;无 memory 时,迭代过程中更容易丢失对象或改变布局。下半部分展示 visual feedback iterations:0 到 5 轮通常能逐步修正缺失物体、位置和朝向;但 10 轮反而可能引入 layout drift 或 over-correction,这与 Table 3 中 Feedback ×10 的 Layout IoU 和 Rotation Acc. 下降一致。

5.5 Limitations and conclusions

作者承认的限制包括:第一,当前方法主要针对从 top-down view image 进行 global 3D scene synthesis,尚未优化 arbitrary-view inputs。第二,很多真实对象很难仅靠 procedural code 精确生成,因为 code-generation models 与 3D asset 的对齐能力有限;更高几何保真度可能仍需要 retrieval-based asset insertion。第三,image re-rendering 可以提升视觉真实感,但当前 video models 对超过五秒轨迹的高质量、时间一致 re-rendering 仍不稳定。

总体结论是:Code-as-Room 的贡献不只是“让 VLM 写 Blender code”,而是提出了一个适配 top-down room image 的 structured execution harness。通过 scene graph skeleton、layout proxy、render-and-compare feedback、typed memory、object-level geometry、material/texture/render stages,系统把一个容易失控的 holistic generation 问题拆成可检查、可修复、可执行的 code synthesis 流程。实验上,CaR 让 Gemini3-Flash 达到 100% agent completion 和 100% execution rate,让 Gemini3.1-Pro w/ CaR 达到 73.2% Layout IoU、94.0% Support Acc.、8.20 Aesthetic Quality,并在 human evaluation 中取得最高 Sim. 9.0、Use. 8.0、Accept. 7.5。