Spaces:
Running
Running
Industrial Harbor card on the same live three.js viewer as the other cases
Browse files- .gitattributes +0 -1
- README.md +4 -3
- assets/buildingbench.css +4 -0
- assets/scene-cards.js +2 -1
- data/progressive-scenes.json +8 -0
- index.html +5 -8
- models/300f1aa5a401127f000d.bin +3 -0
- models/progressive-v1/geo-d66d7f03eb1980602bf2a55f.bin +3 -0
- media/t2s/industrial-harbor/astra.jpg → models/progressive-v1/tex-35d7d0d091290d3bc7cb5a20.bin +2 -2
- models/progressive-v1/tex-4f945f2c0f421ebc6bf65033.bin +3 -0
- models/progressive-v1/tex-585c276ed8bedc6aee678c49.bin +3 -0
- models/progressive-v1/tex-8176ff1aee3ce76879b8ebc1.bin +3 -0
- models/progressive-v1/tex-8e1054705c359552f9c71bb8.bin +3 -0
- models/progressive-v1/tex-8f98ae220f6a95d53a345f23.bin +3 -0
- models/progressive-v1/tex-a56428f1b9776256b96bcd76.bin +3 -0
- models/progressive-v1/tex-a94ed8cf35b5d1ff634abb66.bin +3 -0
- models/progressive-v1/tex-b977ed36fd1da5120e579e41.bin +3 -0
- models/progressive-v1/tex-bb0df2ff7f490aee4a2820ea.bin +3 -0
- models/progressive-v1/tex-cfd3e66a519826aca10eb07d.bin +3 -0
- models/progressive-v1/tex-f5f5d0ca36782e9e5d8ff1d5.bin +3 -0
- scripts/build_harbor_glb.mjs +98 -0
- scripts/harbor_live.py +96 -0
- scripts/progressive-card-urls.json +1 -1
.gitattributes
CHANGED
|
@@ -108,4 +108,3 @@ media/i2s/comp-51-suburban-driveway-mailbox-recovery-v2/qwen-on_full.jpg filter=
|
|
| 108 |
media/i2s/comp-72-suburban-umbrella-pair-repair-v2/gemini_full.jpg filter=lfs diff=lfs merge=lfs -text
|
| 109 |
media/i2s/comp-72-suburban-umbrella-pair-repair-v2/gemma-off_full.jpg filter=lfs diff=lfs merge=lfs -text
|
| 110 |
media/i2s/comp-72-suburban-umbrella-pair-repair-v2/ref-1.jpg filter=lfs diff=lfs merge=lfs -text
|
| 111 |
-
media/t2s/industrial-harbor/astra.jpg filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 108 |
media/i2s/comp-72-suburban-umbrella-pair-repair-v2/gemini_full.jpg filter=lfs diff=lfs merge=lfs -text
|
| 109 |
media/i2s/comp-72-suburban-umbrella-pair-repair-v2/gemma-off_full.jpg filter=lfs diff=lfs merge=lfs -text
|
| 110 |
media/i2s/comp-72-suburban-umbrella-pair-repair-v2/ref-1.jpg filter=lfs diff=lfs merge=lfs -text
|
|
|
README.md
CHANGED
|
@@ -15,8 +15,9 @@ Project page for Code4Scene: the leaderboard, the paper's takeaways, and selecte
|
|
| 15 |
be viewed in 3D. Each section has a Text-to-Scene tab (construction; selected by default, the 20-scene Research Track) and an
|
| 16 |
Image-to-Scene tab (editing; the 75-case public evaluation). `scripts/t2s_only.py` removed Image-to-Scene on 2026-10-01;
|
| 17 |
`scripts/i2s_tabs.py` brought it back as the second tab on 2026-10-04; `scripts/i2s_more_cases.py` adds four more
|
| 18 |
-
Image-to-Scene cases (six in all) and `scripts/harbor_card.py` features GPT-6 Astra's Industrial Harbor,
|
| 19 |
-
|
|
|
|
| 20 |
|
| 21 |
Paper: [arXiv:2609.36777](https://arxiv.org/abs/2609.36777) · Code: [SimWorld-AI/Code4Scene](https://github.com/SimWorld-AI/Code4Scene)
|
| 22 |
|
|
@@ -44,7 +45,7 @@ Queue tests: `node --test tests/scene-assets.test.mjs`. Browser QA includes publ
|
|
| 44 |
|
| 45 |
## Geometry-first scene cards
|
| 46 |
|
| 47 |
-
The homepage uses `data/progressive-scenes.json` to choose immutable packed derivatives for
|
| 48 |
|
| 49 |
Three.js r160, GLTFLoader, MeshoptDecoder, Sky and OrbitControls are served from `assets/vendor/three-r160/`, retaining the official MIT license. Both page import maps use this pinned same-origin version. Original sources: https://github.com/mrdoob/three.js/tree/r160 .
|
| 50 |
|
|
|
|
| 15 |
be viewed in 3D. Each section has a Text-to-Scene tab (construction; selected by default, the 20-scene Research Track) and an
|
| 16 |
Image-to-Scene tab (editing; the 75-case public evaluation). `scripts/t2s_only.py` removed Image-to-Scene on 2026-10-01;
|
| 17 |
`scripts/i2s_tabs.py` brought it back as the second tab on 2026-10-04; `scripts/i2s_more_cases.py` adds four more
|
| 18 |
+
Image-to-Scene cases (six in all) and `scripts/harbor_card.py` features GPT-6 Astra's Industrial Harbor, shown in the same live viewer as the other cards
|
| 19 |
+
(`scripts/build_harbor_glb.mjs` builds its GLB from the viewer Space's library; `scripts/harbor_live.py` packs it) and linked
|
| 20 |
+
to its full-resolution viewer Space.
|
| 21 |
|
| 22 |
Paper: [arXiv:2609.36777](https://arxiv.org/abs/2609.36777) · Code: [SimWorld-AI/Code4Scene](https://github.com/SimWorld-AI/Code4Scene)
|
| 23 |
|
|
|
|
| 45 |
|
| 46 |
## Geometry-first scene cards
|
| 47 |
|
| 48 |
+
The homepage uses `data/progressive-scenes.json` to choose immutable packed derivatives for 18 of its public scene/state variants (the suburban Image-to-Scene scenes are almost all geometry, so their cards load the packed model directly). Geometry and meshopt bytes are unchanged; embedded images are moved into small packed batches. The original packed models remain available to the full case explorer. `assets/progressive-gltf.js` returns the geometry with neutral texture placeholders, then the visible card starts material work after its first rendered frame. Image updates preserve glTF samplers, color spaces, transforms and material parameters. At most two texture jobs run across the page; offscreen cards pause them, and a texture failure keeps the geometry visible with a separate retry control.
|
| 49 |
|
| 50 |
Three.js r160, GLTFLoader, MeshoptDecoder, Sky and OrbitControls are served from `assets/vendor/three-r160/`, retaining the official MIT license. Both page import maps use this pinned same-origin version. Original sources: https://github.com/mrdoob/three.js/tree/r160 .
|
| 51 |
|
assets/buildingbench.css
CHANGED
|
@@ -74,3 +74,7 @@ svg.kit-ch{display:block;width:100%;height:auto;overflow:visible}
|
|
| 74 |
.case-feature .feature-prompt{margin:12px 0 14px;padding:10px 14px;border-left:3px solid var(--border);color:var(--text-muted);font-size:13px;line-height:1.6;font-style:italic}
|
| 75 |
.case-feature .feature-note{margin-top:6px;font-size:11px;color:var(--text-muted)}
|
| 76 |
@media(max-width:900px){.case-grid .case-feature{grid-template-columns:minmax(0,1fr)}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
.case-feature .feature-prompt{margin:12px 0 14px;padding:10px 14px;border-left:3px solid var(--border);color:var(--text-muted);font-size:13px;line-height:1.6;font-style:italic}
|
| 75 |
.case-feature .feature-note{margin-top:6px;font-size:11px;color:var(--text-muted)}
|
| 76 |
@media(max-width:900px){.case-grid .case-feature{grid-template-columns:minmax(0,1fr)}}
|
| 77 |
+
|
| 78 |
+
/* the featured card's live scene (scripts/harbor_live.py) */
|
| 79 |
+
.case-feature .live-scene{height:auto;min-height:400px;border-radius:16px 0 0 16px}
|
| 80 |
+
@media(max-width:900px){.case-feature .live-scene{min-height:0;height:270px;border-radius:16px 16px 0 0}}
|
assets/scene-cards.js
CHANGED
|
@@ -281,7 +281,8 @@ import {Sky} from "three/addons/objects/Sky.js";
|
|
| 281 |
const viewers=new Map();
|
| 282 |
function syncMotion(viewer,button){button.textContent=viewer.paused?'▶':'Ⅱ';button.setAttribute('aria-label',viewer.paused?'Resume scene rotation':'Pause scene rotation');}
|
| 283 |
function mount(el){
|
| 284 |
-
|
|
|
|
| 285 |
const url=state=>state==='input'?c.input_glb:state==='gt'?c.gt_glb:a.glb;
|
| 286 |
const viewer=new window.GLBViewer(el.querySelector('canvas'),{assetKey:url(el.dataset.state||'repair'),refCam:c.ref_cam,rotationX:.55,rotationY:-.62,speed:.1});viewers.set(el,viewer);
|
| 287 |
const pause=el.querySelector('.scene-motion');syncMotion(viewer,pause);pause.addEventListener('click',()=>{viewer.paused=!viewer.paused;viewer.dirty=true;syncMotion(viewer,pause);});
|
|
|
|
| 281 |
const viewers=new Map();
|
| 282 |
function syncMotion(viewer,button){button.textContent=viewer.paused?'▶':'Ⅱ';button.setAttribute('aria-label',viewer.paused?'Resume scene rotation':'Pause scene rotation');}
|
| 283 |
function mount(el){
|
| 284 |
+
// a showcase card names its model itself (data-glb): it has no case, score or case-explorer entry in data/site.js
|
| 285 |
+
const c=el.dataset.glb?{agents:[{key:el.dataset.agent,glb:el.dataset.glb}]}:window.SITE.cases.find(c=>c.id===el.dataset.case),a=c.agents.find(a=>a.key===el.dataset.agent);
|
| 286 |
const url=state=>state==='input'?c.input_glb:state==='gt'?c.gt_glb:a.glb;
|
| 287 |
const viewer=new window.GLBViewer(el.querySelector('canvas'),{assetKey:url(el.dataset.state||'repair'),refCam:c.ref_cam,rotationX:.55,rotationY:-.62,speed:.1});viewers.set(el,viewer);
|
| 288 |
const pause=el.querySelector('.scene-motion');syncMotion(viewer,pause);pause.addEventListener('click',()=>{viewer.paused=!viewer.paused;viewer.dirty=true;syncMotion(viewer,pause);});
|
data/progressive-scenes.json
CHANGED
|
@@ -134,5 +134,13 @@
|
|
| 134 |
"textureBytes": 1248976,
|
| 135 |
"images": 209,
|
| 136 |
"bundles": 7
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
}
|
| 138 |
}
|
|
|
|
| 134 |
"textureBytes": 1248976,
|
| 135 |
"images": 209,
|
| 136 |
"bundles": 7
|
| 137 |
+
},
|
| 138 |
+
"300f1aa5a401127f000d.bin": {
|
| 139 |
+
"geometry": "models/progressive-v1/geo-d66d7f03eb1980602bf2a55f.bin",
|
| 140 |
+
"originalBytes": 23372960,
|
| 141 |
+
"geometryBytes": 15103296,
|
| 142 |
+
"textureBytes": 8315388,
|
| 143 |
+
"images": 380,
|
| 144 |
+
"bundles": 12
|
| 145 |
}
|
| 146 |
}
|
index.html
CHANGED
|
@@ -19,7 +19,7 @@ svg.ch .dim{opacity:.42}svg.ch g.row:hover{opacity:1}svg.ch .hot{fill:var(--c4s-
|
|
| 19 |
.chip.ok{color:var(--c4s-ok);border-color:currentColor}.chip.no{color:var(--c4s-hot);border-color:currentColor}.chip small{font-weight:500;color:var(--text-muted);margin-left:4px}
|
| 20 |
.bigstats{display:flex;flex-wrap:wrap;gap:12px 34px;margin:0 0 12px}.bigstats b{display:block;font-size:30px;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
|
| 21 |
.bigstats span{font-size:13px;color:var(--text-secondary)}
|
| 22 |
-
</style><link href="assets/buildingbench.css?v=
|
| 23 |
<header class="site-header"><div class="brand"><a aria-label="Code4Scene home" class="brand-home" href="index.html#top"><svg aria-hidden="true" fill="none" viewbox="0 0 30 32"><path d="M15 2 27 9v14l-12 7L3 23V9L15 2Z M3 9l12 7 12-7 M15 16v14 M9 5.5l12 7v14 M21 5.5l-12 7v14" stroke="currentColor" stroke-linejoin="round" stroke-width="1.6"></path></svg><span>Code4Scene</span></a><a class="brand-by" href="https://simworld.org/">by SimWorld</a></div><nav aria-label="Main navigation"><a class="nav-active" href="index.html#top">Benchmark</a><a href="index.html#leaderboard">Leaderboard</a><a href="index.html#cases">Visualization</a><a href="https://arxiv.org/abs/2609.36777" rel="noopener" target="_blank">Paper ↗</a><a href="https://github.com/SimWorld-AI/Code4Scene" rel="noopener" target="_blank">Github ↗</a></nav></header><main class="page-main"><section class="intro" id="top"><div class="intro-copy"><h1>Constructing<br/><em>3D Scenes with Code</em></h1><p class="intro-text">Benchmarking coding agents that turn open-ended scene descriptions into engine-native 3D scenes in Unreal Engine. Measuring spatial reasoning, task fulfillment and physical validity.</p><div class="intro-links"><a href="https://arxiv.org/abs/2609.36777">Read the paper ↗</a><a href="https://github.com/SimWorld-AI/Code4Scene">Code & Data ↗</a><a href="#hero-video">Watch the teaser ↘</a></div></div><div class="featured featured-video" id="hero-video"><video aria-label="Code4Scene overview video" controls="" playsinline="" poster="media/teaser-poster.jpg" preload="metadata"><source src="media/teaser-v31.mp4" type="video/mp4"/>Your browser does not support embedded video. <a href="media/teaser-v31.mp4">Watch the Code4Scene video</a>.</video><div class="featured-video-caption"><strong>Code4Scene in 90 seconds</strong><span>Construction and evaluation</span></div></div></section><section class="task-section" id="task-format"><div class="container"><h2 class="section-title">Task Format</h2><div class="task-shell"><div aria-label="Task format" class="task-tabs" role="tablist"><button aria-controls="task-t2s" aria-selected="true" data-task="t2s" id="task-tab-t2s" role="tab">Text-to-Scene</button><button aria-controls="task-i2s" aria-selected="false" data-task="i2s" id="task-tab-i2s" role="tab" tabindex="-1">Image-to-Scene</button></div><div aria-labelledby="task-tab-t2s" class="task-content" data-task="t2s" id="task-t2s" role="tabpanel"><h3>Nordic Harbour <span>· Text-to-Scene</span></h3><p class="task-subtitle">An open-ended scene description, an asset catalog and the Unreal Engine editor.</p><div class="task-columns"><article class="task-panel"><div class="panel-heading"><strong>Agent input</strong><span>Text + assets</span></div><div class="prompt-preview"><span class="eyebrow">Task instruction</span><p>Build me a compact, sunlit Copenhagen-style canal district with narrow cobblestone streets and rectangular waterways enclosing dense urban blocks.</p><p class="prompt-detail">Townhouses, canals, bridges and a waterfront promenade — with detailed requirements for materials, layout and street furniture.</p></div><p class="task-foot"><strong>Given:</strong> an empty level and the content pack’s asset catalog.</p></article><article class="task-panel output-panel"><div class="panel-heading"><strong>Agent output</strong><span>GPT-6 Astra</span></div><div class="live-scene" data-agent="astra" data-case="nordic-harbour"><canvas aria-label="Interactive 3D scene: Nordic Harbour. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><a class="task-foot text-button" href="cases.html#nordic-harbour">Compare agents and evaluator views ↗</a></article><article class="task-panel evaluation-panel"><div class="panel-heading"><strong>Evaluation</strong><span>Engine-native scene</span></div><div class="score-block"><span>CASE SCORE</span><strong>0.877</strong><dl><div><dt>Detailed Alignment</dt><dd>0.757</dd></div><div><dt>Overview Alignment</dt><dd>0.909</dd></div><div><dt>Physical Safety</dt><dd>0.900</dd></div></dl></div><p class="task-foot">Task fulfillment, artifact integrity and static physical validity.</p><p class="task-formula">0.2 × Detailed + 0.6 × Overview + 0.2 × Physical</p></article></div><details class="task-full"><summary><span>+ Full task instruction</span><span>TEXT-TO-SCENE</span></summary><p>Build me a compact, sunlit Copenhagen-style canal district with narrow cobblestone streets and rectangular waterways enclosing dense urban blocks. Arrange roughly thirty attached four- to six-storey townhouses in continuous street and canal-front rows, using slender façades, repetitive white-framed windows, arched doors and carriage entrances, modest cornices, and steep tiled roofs packed with dormers and brick chimneys. Include occasional exposed party walls between staggered building rows. Finish the façades in weathered muted red, mustard yellow, dusty blue, warm grey, beige, and exposed brick, with red, orange, and charcoal roof tiles. Run a principal waterfront street along a stone quay, crossed by smaller streets and linked across the canals by short, gently arched stone-and-metal bridges, including one opening onto a broad paved promenade with rounded landings. Form the canal edges from stepped pale stone, dark timber retaining walls, and iron railings around reflective rippling water. Add regularly spaced leafy trees, ornate black lamps, stone bollards, benches, European road signs, zebra crossings, puddles, grime, and sparse weeds.</p></details><div class="availability"><span><b>20</b> scenes in the <strong>Research Track</strong>: affordable, reproducible evaluation for academic and model-development use</span><span><b>160</b> scenes in the <strong>Full Benchmark</strong>: comprehensive evaluation for leaderboard and final reporting</span></div></div><div aria-labelledby="task-tab-i2s" class="task-content" data-task="i2s" hidden="" id="task-i2s" role="tabpanel"><h3>Old Industrial Pallet Bay <span>· Image-to-Scene</span></h3><p class="task-subtitle">Repair the corrupted scene using its reference image; preserve all unrelated actors.</p><div class="task-columns"><article class="task-panel input-panel"><div class="panel-heading"><strong>Agent input</strong><span>Scene + reference image</span></div><div class="live-scene" data-agent="astra" data-case="comp-31-old-industrial-pallet-bay-repair-v2" data-state="input"><canvas aria-label="Interactive 3D: Old Industrial Pallet Bay, input. Drag to orbit; scroll to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Resume scene rotation" class="scene-motion">▶</button></div><a class="task-reference" href="media/i2s/comp-31-old-industrial-pallet-bay-repair-v2/ref-1.jpg?v=1790549706" rel="noopener" target="_blank"><img alt="Provided reference image for Old Industrial Pallet Bay" loading="lazy" src="media/i2s/comp-31-old-industrial-pallet-bay-repair-v2/ref-1.jpg?v=1790549706"/><span>Provided reference image ↗</span></a><p class="task-foot">A translated and rotated pallet stack, plus an unintended duplicate.</p></article><article class="task-panel output-panel"><div class="panel-heading"><strong>Agent output</strong><span>GPT-6 Astra</span></div><div class="live-scene" data-agent="astra" data-case="comp-31-old-industrial-pallet-bay-repair-v2" data-state="repair"><canvas aria-label="Interactive 3D: Old Industrial Pallet Bay, repair. Drag to orbit; scroll to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Resume scene rotation" class="scene-motion">▶</button></div><div aria-label="Output scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><p class="task-foot">Inspect the saved repair from the same reference camera.</p><a class="text-button task-foot" href="cases.html#comp-31-old-industrial-pallet-bay-repair-v2">Compare agents and evaluator views ↗</a></article><article class="task-panel evaluation-panel"><div class="panel-heading"><strong>Evaluation</strong><span>Actor-level repair</span></div><div class="score-block"><span>CASE SCORE</span><strong>1.000</strong><dl><div><dt>Repair F1</dt><dd>1.000</dd></div><div><dt>Physical Safety</dt><dd>1.000</dd></div><div><dt>TP / FP / FN</dt><dd>2 / 0 / 0</dd></div></dl></div><p class="task-foot">Restore each target within 5 cm, 5° and 5%, without unintended edits.</p><p class="task-formula">0.8 × Repair F1 + 0.2 × Physical</p></article></div><details class="task-full"><summary><span>+ Full task instruction</span><span>IMAGE-TO-SCENE</span></summary><p>Repair the current outdoor scene so it matches the provided reference image. Make only the minimum changes needed, and preserve all unrelated actors and properties.</p></details><div class="availability"><span><b>160</b> editing cases in the full benchmark target, including private cases</span><span><b>72</b> public editing cases (22 indoor, 50 outdoor)</span></div></div></div></div></section><section id="leaderboard"><div class="container">
|
| 24 |
<div class="section-header centered"><span class="section-label">Leaderboard</span><h2 class="section-title">Leaderboard</h2>
|
| 25 |
<p class="section-desc" data-view="t2s">Research Track · 20 representative scenes · 14 coding-agent configurations.</p><p class="section-desc" data-view="i2s" style="display:none">Image-to-Scene · 75 public cases (25 indoor, 50 outdoor) · 14 coding-agent configurations.</p><p class="tracks-why" data-view="t2s">Text-to-scene generation with frontier models is a long-horizon agentic task with substantial inference cost and runtime, which makes repeated full-scale evaluation difficult for many research groups. The Research Track supports affordable, reproducible experimentation; the Full Benchmark provides the more comprehensive evaluation for final model comparison and leaderboard reporting.</p></div>
|
|
@@ -33,16 +33,13 @@ svg.ch .dim{opacity:.42}svg.ch g.row:hover{opacity:1}svg.ch .hot{fill:var(--c4s-
|
|
| 33 |
<div class="section-header centered"><span class="section-label">Cases</span><h2 class="section-title">Visualizing agent outputs</h2>
|
| 34 |
<p class="section-desc" data-view="t2s">Drag any scene to inspect the saved 3D output, or open a case to explore every agent.</p><p class="section-desc" data-view="i2s" style="display:none">Drag any scene to inspect the saved 3D output. Switch each repair between the saved scene, its corrupted input and the ground truth, or open a case to explore every agent.</p></div>
|
| 35 |
<div class="lb-tabs"><div class="seg seg-lg" data-for="cases"><button class="on" data-view="t2s">Text-to-Scene</button><button data-view="i2s">Image-to-Scene</button></div></div><div class="case-grid" data-view="t2s"><article class="case-card case-feature">
|
| 36 |
-
<
|
| 37 |
-
<img alt="GPT-6 Astra's Industrial Harbor: quay cranes over a container ship, container stacks, a hangar, storage tanks and a rail siding" height="900" loading="lazy" src="media/t2s/industrial-harbor/astra.jpg?v=20261004harbor" width="1600"/>
|
| 38 |
-
<span class="feature-badge">3,949 actors</span>
|
| 39 |
-
</a>
|
| 40 |
<div class="meta">
|
| 41 |
<span class="eyebrow">Text-to-Scene · Showcase</span>
|
| 42 |
<h4>Industrial Harbor</h4>
|
| 43 |
-
<p>GPT-6 Astra (max) ·
|
| 44 |
<blockquote class="feature-prompt">An industrial harbor loading dock with shipping containers, barrels, cranes, warehouse props, pallets, and warning signs.</blockquote>
|
| 45 |
-
<a class="text-button" href="https://simworld-ai-industrial-harbor-viewer.static.hf.space/" rel="noopener" target="_blank">
|
| 46 |
<p class="feature-note">Streams about 1.2 GB of textures on first load.</p>
|
| 47 |
</div>
|
| 48 |
</article><article class="case-card"><div class="live-scene" data-agent="astra" data-case="nordic-harbour"><canvas aria-label="Interactive 3D scene: Nordic Harbour. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Nordic Harbour</h4><p>GPT-6 Astra (max) · score 0.877</p><a class="text-button" href="cases.html#nordic-harbour">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="medieval-big-farm-town"><canvas aria-label="Interactive 3D scene: Medieval Big Farm Town. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Medieval Big Farm Town</h4><p>Claude Fable 5.1 (max) · score 0.830</p><a class="text-button" href="cases.html#medieval-big-farm-town">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="opus" data-case="egyptian-temple"><canvas aria-label="Interactive 3D scene: Egyptian Temple. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Egyptian Temple</h4><p>Claude Opus 5 (max) · score 0.777</p><a class="text-button" href="cases.html#egyptian-temple">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="bazaar"><canvas aria-label="Interactive 3D scene: Bazaar. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Bazaar</h4><p>Claude Fable 5.1 (max) · score 0.930</p><a class="text-button" href="cases.html#bazaar">Compare all 14 agents ↗</a></div></article></div><div class="case-grid" data-view="i2s" style="display:none"><article class="case-card"><div class="live-scene" data-agent="astra" data-case="comp-31-old-industrial-pallet-bay-repair-v2"><canvas aria-label="Interactive 3D scene: Old Industrial Pallet Bay. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Old Industrial Pallet Bay</h4><p>GPT-6 Astra (max) · score 1.000</p><a class="text-button" href="cases.html#comp-31-old-industrial-pallet-bay-repair-v2">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="comp-61-new-york-mailbox-pair-repair-v2"><canvas aria-label="Interactive 3D scene: New York Mailbox Pair. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>New York Mailbox Pair</h4><p>Claude Fable 5.1 (max) · score 1.000</p><a class="text-button" href="cases.html#comp-61-new-york-mailbox-pair-repair-v2">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="opus" data-case="comp-72-suburban-umbrella-pair-repair-v2"><canvas aria-label="Interactive 3D scene: Suburban Umbrella Pair. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Suburban Umbrella Pair</h4><p>Claude Opus 5 (max) · score 1.000</p><a class="text-button" href="cases.html#comp-72-suburban-umbrella-pair-repair-v2">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="astra" data-case="comp-17-rosies-service-bin-reset-v3"><canvas aria-label="Interactive 3D scene: Rosie's Service Bin. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Rosie's Service Bin</h4><p>GPT-6 Astra (max) · score 1.000</p><a class="text-button" href="cases.html#comp-17-rosies-service-bin-reset-v3">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="astra" data-case="comp-18-rosies-roadside-billboard-reset-v3"><canvas aria-label="Interactive 3D scene: Rosie's Roadside Billboard. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Rosie's Roadside Billboard</h4><p>GPT-6 Astra (max) · score 1.000</p><a class="text-button" href="cases.html#comp-18-rosies-roadside-billboard-reset-v3">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="comp-51-suburban-driveway-mailbox-recovery-v2"><canvas aria-label="Interactive 3D scene: Suburban Driveway Mailbox. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Suburban Driveway Mailbox</h4><p>Claude Fable 5.1 (max) · score 1.000</p><a class="text-button" href="cases.html#comp-51-suburban-driveway-mailbox-recovery-v2">Compare all 14 agents ↗</a></div></article></div>
|
|
@@ -70,4 +67,4 @@ svg.ch .dim{opacity:.42}svg.ch g.row:hover{opacity:1}svg.ch .hot{fill:var(--c4s-
|
|
| 70 |
<a href="https://simworld.org/" rel="noopener" target="_blank">SimWorld Home</a></p>
|
| 71 |
<p style="margin-top:.5rem;font-size:.75rem;color:rgba(255,255,255,.25)">Part of the SimWorld project.</p></footer>
|
| 72 |
<script src="assets/paper.js?v=5427505a"></script>
|
| 73 |
-
<script defer="" src="assets/leaderboard-bars.js?v=20261004i2s"></script><script src="data/site.js?v=20261004i2smore"></script><script src="assets/pareto.js?v=20261004i2s" type="module"></script><script src="assets/scene-cards.js?v=
|
|
|
|
| 19 |
.chip.ok{color:var(--c4s-ok);border-color:currentColor}.chip.no{color:var(--c4s-hot);border-color:currentColor}.chip small{font-weight:500;color:var(--text-muted);margin-left:4px}
|
| 20 |
.bigstats{display:flex;flex-wrap:wrap;gap:12px 34px;margin:0 0 12px}.bigstats b{display:block;font-size:30px;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
|
| 21 |
.bigstats span{font-size:13px;color:var(--text-secondary)}
|
| 22 |
+
</style><link href="assets/buildingbench.css?v=20261004harborlive" rel="stylesheet"/><script type="importmap">{"imports":{"three":"./assets/vendor/three-r160/build/three.module.js","three/addons/":"./assets/vendor/three-r160/addons/"}}</script></head><body><a class="skip-link" href="#leaderboard">Skip to benchmark explorer</a>
|
| 23 |
<header class="site-header"><div class="brand"><a aria-label="Code4Scene home" class="brand-home" href="index.html#top"><svg aria-hidden="true" fill="none" viewbox="0 0 30 32"><path d="M15 2 27 9v14l-12 7L3 23V9L15 2Z M3 9l12 7 12-7 M15 16v14 M9 5.5l12 7v14 M21 5.5l-12 7v14" stroke="currentColor" stroke-linejoin="round" stroke-width="1.6"></path></svg><span>Code4Scene</span></a><a class="brand-by" href="https://simworld.org/">by SimWorld</a></div><nav aria-label="Main navigation"><a class="nav-active" href="index.html#top">Benchmark</a><a href="index.html#leaderboard">Leaderboard</a><a href="index.html#cases">Visualization</a><a href="https://arxiv.org/abs/2609.36777" rel="noopener" target="_blank">Paper ↗</a><a href="https://github.com/SimWorld-AI/Code4Scene" rel="noopener" target="_blank">Github ↗</a></nav></header><main class="page-main"><section class="intro" id="top"><div class="intro-copy"><h1>Constructing<br/><em>3D Scenes with Code</em></h1><p class="intro-text">Benchmarking coding agents that turn open-ended scene descriptions into engine-native 3D scenes in Unreal Engine. Measuring spatial reasoning, task fulfillment and physical validity.</p><div class="intro-links"><a href="https://arxiv.org/abs/2609.36777">Read the paper ↗</a><a href="https://github.com/SimWorld-AI/Code4Scene">Code & Data ↗</a><a href="#hero-video">Watch the teaser ↘</a></div></div><div class="featured featured-video" id="hero-video"><video aria-label="Code4Scene overview video" controls="" playsinline="" poster="media/teaser-poster.jpg" preload="metadata"><source src="media/teaser-v31.mp4" type="video/mp4"/>Your browser does not support embedded video. <a href="media/teaser-v31.mp4">Watch the Code4Scene video</a>.</video><div class="featured-video-caption"><strong>Code4Scene in 90 seconds</strong><span>Construction and evaluation</span></div></div></section><section class="task-section" id="task-format"><div class="container"><h2 class="section-title">Task Format</h2><div class="task-shell"><div aria-label="Task format" class="task-tabs" role="tablist"><button aria-controls="task-t2s" aria-selected="true" data-task="t2s" id="task-tab-t2s" role="tab">Text-to-Scene</button><button aria-controls="task-i2s" aria-selected="false" data-task="i2s" id="task-tab-i2s" role="tab" tabindex="-1">Image-to-Scene</button></div><div aria-labelledby="task-tab-t2s" class="task-content" data-task="t2s" id="task-t2s" role="tabpanel"><h3>Nordic Harbour <span>· Text-to-Scene</span></h3><p class="task-subtitle">An open-ended scene description, an asset catalog and the Unreal Engine editor.</p><div class="task-columns"><article class="task-panel"><div class="panel-heading"><strong>Agent input</strong><span>Text + assets</span></div><div class="prompt-preview"><span class="eyebrow">Task instruction</span><p>Build me a compact, sunlit Copenhagen-style canal district with narrow cobblestone streets and rectangular waterways enclosing dense urban blocks.</p><p class="prompt-detail">Townhouses, canals, bridges and a waterfront promenade — with detailed requirements for materials, layout and street furniture.</p></div><p class="task-foot"><strong>Given:</strong> an empty level and the content pack’s asset catalog.</p></article><article class="task-panel output-panel"><div class="panel-heading"><strong>Agent output</strong><span>GPT-6 Astra</span></div><div class="live-scene" data-agent="astra" data-case="nordic-harbour"><canvas aria-label="Interactive 3D scene: Nordic Harbour. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><a class="task-foot text-button" href="cases.html#nordic-harbour">Compare agents and evaluator views ↗</a></article><article class="task-panel evaluation-panel"><div class="panel-heading"><strong>Evaluation</strong><span>Engine-native scene</span></div><div class="score-block"><span>CASE SCORE</span><strong>0.877</strong><dl><div><dt>Detailed Alignment</dt><dd>0.757</dd></div><div><dt>Overview Alignment</dt><dd>0.909</dd></div><div><dt>Physical Safety</dt><dd>0.900</dd></div></dl></div><p class="task-foot">Task fulfillment, artifact integrity and static physical validity.</p><p class="task-formula">0.2 × Detailed + 0.6 × Overview + 0.2 × Physical</p></article></div><details class="task-full"><summary><span>+ Full task instruction</span><span>TEXT-TO-SCENE</span></summary><p>Build me a compact, sunlit Copenhagen-style canal district with narrow cobblestone streets and rectangular waterways enclosing dense urban blocks. Arrange roughly thirty attached four- to six-storey townhouses in continuous street and canal-front rows, using slender façades, repetitive white-framed windows, arched doors and carriage entrances, modest cornices, and steep tiled roofs packed with dormers and brick chimneys. Include occasional exposed party walls between staggered building rows. Finish the façades in weathered muted red, mustard yellow, dusty blue, warm grey, beige, and exposed brick, with red, orange, and charcoal roof tiles. Run a principal waterfront street along a stone quay, crossed by smaller streets and linked across the canals by short, gently arched stone-and-metal bridges, including one opening onto a broad paved promenade with rounded landings. Form the canal edges from stepped pale stone, dark timber retaining walls, and iron railings around reflective rippling water. Add regularly spaced leafy trees, ornate black lamps, stone bollards, benches, European road signs, zebra crossings, puddles, grime, and sparse weeds.</p></details><div class="availability"><span><b>20</b> scenes in the <strong>Research Track</strong>: affordable, reproducible evaluation for academic and model-development use</span><span><b>160</b> scenes in the <strong>Full Benchmark</strong>: comprehensive evaluation for leaderboard and final reporting</span></div></div><div aria-labelledby="task-tab-i2s" class="task-content" data-task="i2s" hidden="" id="task-i2s" role="tabpanel"><h3>Old Industrial Pallet Bay <span>· Image-to-Scene</span></h3><p class="task-subtitle">Repair the corrupted scene using its reference image; preserve all unrelated actors.</p><div class="task-columns"><article class="task-panel input-panel"><div class="panel-heading"><strong>Agent input</strong><span>Scene + reference image</span></div><div class="live-scene" data-agent="astra" data-case="comp-31-old-industrial-pallet-bay-repair-v2" data-state="input"><canvas aria-label="Interactive 3D: Old Industrial Pallet Bay, input. Drag to orbit; scroll to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Resume scene rotation" class="scene-motion">▶</button></div><a class="task-reference" href="media/i2s/comp-31-old-industrial-pallet-bay-repair-v2/ref-1.jpg?v=1790549706" rel="noopener" target="_blank"><img alt="Provided reference image for Old Industrial Pallet Bay" loading="lazy" src="media/i2s/comp-31-old-industrial-pallet-bay-repair-v2/ref-1.jpg?v=1790549706"/><span>Provided reference image ↗</span></a><p class="task-foot">A translated and rotated pallet stack, plus an unintended duplicate.</p></article><article class="task-panel output-panel"><div class="panel-heading"><strong>Agent output</strong><span>GPT-6 Astra</span></div><div class="live-scene" data-agent="astra" data-case="comp-31-old-industrial-pallet-bay-repair-v2" data-state="repair"><canvas aria-label="Interactive 3D: Old Industrial Pallet Bay, repair. Drag to orbit; scroll to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Resume scene rotation" class="scene-motion">▶</button></div><div aria-label="Output scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><p class="task-foot">Inspect the saved repair from the same reference camera.</p><a class="text-button task-foot" href="cases.html#comp-31-old-industrial-pallet-bay-repair-v2">Compare agents and evaluator views ↗</a></article><article class="task-panel evaluation-panel"><div class="panel-heading"><strong>Evaluation</strong><span>Actor-level repair</span></div><div class="score-block"><span>CASE SCORE</span><strong>1.000</strong><dl><div><dt>Repair F1</dt><dd>1.000</dd></div><div><dt>Physical Safety</dt><dd>1.000</dd></div><div><dt>TP / FP / FN</dt><dd>2 / 0 / 0</dd></div></dl></div><p class="task-foot">Restore each target within 5 cm, 5° and 5%, without unintended edits.</p><p class="task-formula">0.8 × Repair F1 + 0.2 × Physical</p></article></div><details class="task-full"><summary><span>+ Full task instruction</span><span>IMAGE-TO-SCENE</span></summary><p>Repair the current outdoor scene so it matches the provided reference image. Make only the minimum changes needed, and preserve all unrelated actors and properties.</p></details><div class="availability"><span><b>160</b> editing cases in the full benchmark target, including private cases</span><span><b>72</b> public editing cases (22 indoor, 50 outdoor)</span></div></div></div></div></section><section id="leaderboard"><div class="container">
|
| 24 |
<div class="section-header centered"><span class="section-label">Leaderboard</span><h2 class="section-title">Leaderboard</h2>
|
| 25 |
<p class="section-desc" data-view="t2s">Research Track · 20 representative scenes · 14 coding-agent configurations.</p><p class="section-desc" data-view="i2s" style="display:none">Image-to-Scene · 75 public cases (25 indoor, 50 outdoor) · 14 coding-agent configurations.</p><p class="tracks-why" data-view="t2s">Text-to-scene generation with frontier models is a long-horizon agentic task with substantial inference cost and runtime, which makes repeated full-scale evaluation difficult for many research groups. The Research Track supports affordable, reproducible experimentation; the Full Benchmark provides the more comprehensive evaluation for final model comparison and leaderboard reporting.</p></div>
|
|
|
|
| 33 |
<div class="section-header centered"><span class="section-label">Cases</span><h2 class="section-title">Visualizing agent outputs</h2>
|
| 34 |
<p class="section-desc" data-view="t2s">Drag any scene to inspect the saved 3D output, or open a case to explore every agent.</p><p class="section-desc" data-view="i2s" style="display:none">Drag any scene to inspect the saved 3D output. Switch each repair between the saved scene, its corrupted input and the ground truth, or open a case to explore every agent.</p></div>
|
| 35 |
<div class="lb-tabs"><div class="seg seg-lg" data-for="cases"><button class="on" data-view="t2s">Text-to-Scene</button><button data-view="i2s">Image-to-Scene</button></div></div><div class="case-grid" data-view="t2s"><article class="case-card case-feature">
|
| 36 |
+
<div class="live-scene" data-agent="astra" data-case="industrial-harbor" data-glb="models/300f1aa5a401127f000d.bin?v=1791183752"><canvas aria-label="Interactive 3D scene: Industrial Harbor. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div>
|
|
|
|
|
|
|
|
|
|
| 37 |
<div class="meta">
|
| 38 |
<span class="eyebrow">Text-to-Scene · Showcase</span>
|
| 39 |
<h4>Industrial Harbor</h4>
|
| 40 |
+
<p>GPT-6 Astra (max) · 3,949 actors, built in one agent session from an empty 130 m stage</p>
|
| 41 |
<blockquote class="feature-prompt">An industrial harbor loading dock with shipping containers, barrels, cranes, warehouse props, pallets, and warning signs.</blockquote>
|
| 42 |
+
<a class="text-button" href="https://simworld-ai-industrial-harbor-viewer.static.hf.space/" rel="noopener" target="_blank">Open at full texture resolution ↗</a>
|
| 43 |
<p class="feature-note">Streams about 1.2 GB of textures on first load.</p>
|
| 44 |
</div>
|
| 45 |
</article><article class="case-card"><div class="live-scene" data-agent="astra" data-case="nordic-harbour"><canvas aria-label="Interactive 3D scene: Nordic Harbour. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Nordic Harbour</h4><p>GPT-6 Astra (max) · score 0.877</p><a class="text-button" href="cases.html#nordic-harbour">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="medieval-big-farm-town"><canvas aria-label="Interactive 3D scene: Medieval Big Farm Town. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Medieval Big Farm Town</h4><p>Claude Fable 5.1 (max) · score 0.830</p><a class="text-button" href="cases.html#medieval-big-farm-town">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="opus" data-case="egyptian-temple"><canvas aria-label="Interactive 3D scene: Egyptian Temple. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Egyptian Temple</h4><p>Claude Opus 5 (max) · score 0.777</p><a class="text-button" href="cases.html#egyptian-temple">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="bazaar"><canvas aria-label="Interactive 3D scene: Bazaar. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div class="meta"><span class="eyebrow">Text-to-Scene</span><h4>Bazaar</h4><p>Claude Fable 5.1 (max) · score 0.930</p><a class="text-button" href="cases.html#bazaar">Compare all 14 agents ↗</a></div></article></div><div class="case-grid" data-view="i2s" style="display:none"><article class="case-card"><div class="live-scene" data-agent="astra" data-case="comp-31-old-industrial-pallet-bay-repair-v2"><canvas aria-label="Interactive 3D scene: Old Industrial Pallet Bay. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Old Industrial Pallet Bay</h4><p>GPT-6 Astra (max) · score 1.000</p><a class="text-button" href="cases.html#comp-31-old-industrial-pallet-bay-repair-v2">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="comp-61-new-york-mailbox-pair-repair-v2"><canvas aria-label="Interactive 3D scene: New York Mailbox Pair. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>New York Mailbox Pair</h4><p>Claude Fable 5.1 (max) · score 1.000</p><a class="text-button" href="cases.html#comp-61-new-york-mailbox-pair-repair-v2">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="opus" data-case="comp-72-suburban-umbrella-pair-repair-v2"><canvas aria-label="Interactive 3D scene: Suburban Umbrella Pair. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Suburban Umbrella Pair</h4><p>Claude Opus 5 (max) · score 1.000</p><a class="text-button" href="cases.html#comp-72-suburban-umbrella-pair-repair-v2">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="astra" data-case="comp-17-rosies-service-bin-reset-v3"><canvas aria-label="Interactive 3D scene: Rosie's Service Bin. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Rosie's Service Bin</h4><p>GPT-6 Astra (max) · score 1.000</p><a class="text-button" href="cases.html#comp-17-rosies-service-bin-reset-v3">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="astra" data-case="comp-18-rosies-roadside-billboard-reset-v3"><canvas aria-label="Interactive 3D scene: Rosie's Roadside Billboard. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Rosie's Roadside Billboard</h4><p>GPT-6 Astra (max) · score 1.000</p><a class="text-button" href="cases.html#comp-18-rosies-roadside-billboard-reset-v3">Compare all 14 agents ↗</a></div></article><article class="case-card"><div class="live-scene" data-agent="fable" data-case="comp-51-suburban-driveway-mailbox-recovery-v2"><canvas aria-label="Interactive 3D scene: Suburban Driveway Mailbox. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" class="scene-motion">Ⅱ</button></div><div aria-label="Scene state" class="scene-versions"><button class="on" data-state="repair">Repair</button><button data-state="input">Corrupted input</button><button data-state="gt">Ground truth</button></div><div class="meta"><span class="eyebrow">Image-to-Scene</span><h4>Suburban Driveway Mailbox</h4><p>Claude Fable 5.1 (max) · score 1.000</p><a class="text-button" href="cases.html#comp-51-suburban-driveway-mailbox-recovery-v2">Compare all 14 agents ↗</a></div></article></div>
|
|
|
|
| 67 |
<a href="https://simworld.org/" rel="noopener" target="_blank">SimWorld Home</a></p>
|
| 68 |
<p style="margin-top:.5rem;font-size:.75rem;color:rgba(255,255,255,.25)">Part of the SimWorld project.</p></footer>
|
| 69 |
<script src="assets/paper.js?v=5427505a"></script>
|
| 70 |
+
<script defer="" src="assets/leaderboard-bars.js?v=20261004i2s"></script><script src="data/site.js?v=20261004i2smore"></script><script src="assets/pareto.js?v=20261004i2s" type="module"></script><script src="assets/scene-cards.js?v=20261004harborlive" type="module"></script><script src="assets/task-tabs.js?v=20261001c" type="module"></script><script src="assets/leaderboard-controls.js?v=20261001c" type="module"></script><script src="assets/takeaway-bars.js?v=20261004kit" type="module"></script></body></html>
|
models/300f1aa5a401127f000d.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:96c0be6c94185300ed7593ca49de862cbd46da61fca03d2999f3f37f638f42fd
|
| 3 |
+
size 23372960
|
models/progressive-v1/geo-d66d7f03eb1980602bf2a55f.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:de20c6708173d6a4a951deb9275412d715095e47ad8293933cb0a4aa8c2ed3fa
|
| 3 |
+
size 15103296
|
media/t2s/industrial-harbor/astra.jpg → models/progressive-v1/tex-35d7d0d091290d3bc7cb5a20.bin
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:53022e695baf3ce848dbc4252e5e4e475dccfbc1397649de0c025a9e2ec1c877
|
| 3 |
+
size 571308
|
models/progressive-v1/tex-4f945f2c0f421ebc6bf65033.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:19b1d6b3bccebee0711469fa00c4915bad6efa8dbd054d66211c27ae1d716731
|
| 3 |
+
size 845428
|
models/progressive-v1/tex-585c276ed8bedc6aee678c49.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ba00252716c531b79cea41584db4399834fedb3d6e205eb7c4b882a5bd0f60f8
|
| 3 |
+
size 646250
|
models/progressive-v1/tex-8176ff1aee3ce76879b8ebc1.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:48c1af67822ef6cc91983fe81890328900c5608490fe61fbaf026bde45bebfe4
|
| 3 |
+
size 741122
|
models/progressive-v1/tex-8e1054705c359552f9c71bb8.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:57c78f81dd3ad8f6a698cf2e5aceb4b5459c9bde4dd66b05afe5a24ffc086299
|
| 3 |
+
size 706126
|
models/progressive-v1/tex-8f98ae220f6a95d53a345f23.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d83b82690b09f2c3a43b3b39b90e91eee1f6daf500aebc0ab167dd8cd4c65ead
|
| 3 |
+
size 755988
|
models/progressive-v1/tex-a56428f1b9776256b96bcd76.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:16e4b4fa4c88501af011efa2745703a96a0fb9dff512f9cf39d27de865b04a44
|
| 3 |
+
size 856396
|
models/progressive-v1/tex-a94ed8cf35b5d1ff634abb66.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b1ed43c5ea39eb489fb496f9fda0804e01f68b1ad616341c665ae753407c4dea
|
| 3 |
+
size 538180
|
models/progressive-v1/tex-b977ed36fd1da5120e579e41.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0444d92b0f3d1da10fb9651bfbc1778e952ea271e61022d0709882a961ae25ca
|
| 3 |
+
size 668110
|
models/progressive-v1/tex-bb0df2ff7f490aee4a2820ea.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c461701c3aa61e41c9b1629d24b39afcb6c2b0577005763bb739457dee71aa96
|
| 3 |
+
size 658042
|
models/progressive-v1/tex-cfd3e66a519826aca10eb07d.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8180bca8d65ff324aa587459a80441d15719f58cecb638f31303362f1701f2a8
|
| 3 |
+
size 651952
|
models/progressive-v1/tex-f5f5d0ca36782e9e5d8ff1d5.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c6d126a192cfe21b247a9f2888c3164b311a6fe6844c45f1cf32ef9d44f36e86
|
| 3 |
+
size 676486
|
scripts/build_harbor_glb.mjs
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// One GLB of GPT-6 Astra's Industrial Harbor for the homepage card, assembled the way SimWorld-AI/industrial-harbor-viewer's
|
| 2 |
+
// web/viewer.js draws it: scenes/industrial-harbor-astra-max.json places 3,806 instances of 222 library meshes; a mesh GLB
|
| 3 |
+
// has one primitive per material slot (traversal order = slot index), an instance's slots[p] indexes data.materials, the
|
| 4 |
+
// instance matrix is compose(pos, quat, scale) applied to the primitive's geometry alone, and water/ocean sits 2 cm lower.
|
| 5 |
+
// Materials are the full library's; their textures are KTX2 (Basis), which the site's loader cannot read, so each is
|
| 6 |
+
// transcoded here with three r160's Basis transcoder (from the smallest mip level at least 512 px) and stored as PNG.
|
| 7 |
+
// The harbor's UE export could not be used: baking its 3,949 actors ran serv6's shared GPUs out of memory (2026-10-04).
|
| 8 |
+
//
|
| 9 |
+
// node scripts/build_harbor_glb.mjs <scene.json> <library/web dir> <out.glb>
|
| 10 |
+
// then compress as website/compress_glb.sh does for Text-to-Scene scenes (meshopt, 512 px WebP, instancing) and pack with
|
| 11 |
+
// scripts/harbor_live.py. Needs @gltf-transform/{core,extensions,functions}, draco3dgltf, sharp and three@0.160.0.
|
| 12 |
+
import { readFileSync } from 'node:fs';
|
| 13 |
+
import { createRequire } from 'node:module';
|
| 14 |
+
import { join } from 'node:path';
|
| 15 |
+
import { NodeIO, Document } from '@gltf-transform/core';
|
| 16 |
+
import { ALL_EXTENSIONS } from '@gltf-transform/extensions';
|
| 17 |
+
import { mergeDocuments, prune, unpartition } from '@gltf-transform/functions';
|
| 18 |
+
import draco3d from 'draco3dgltf';
|
| 19 |
+
import sharp from 'sharp';
|
| 20 |
+
|
| 21 |
+
const [scenePath, lib, out] = process.argv.slice(2);
|
| 22 |
+
const data = JSON.parse(readFileSync(scenePath, 'utf8'));
|
| 23 |
+
const meshManifest = JSON.parse(readFileSync(join(lib, 'meshes/manifest.json'), 'utf8')).assets;
|
| 24 |
+
const matManifest = JSON.parse(readFileSync(join(lib, 'materials/manifest.json'), 'utf8')).assets;
|
| 25 |
+
const NOT_GROUND = /water|ocean/i; // viewer.js: these sit 2 cm lower so the ground does not z-fight them
|
| 26 |
+
|
| 27 |
+
const io = new NodeIO().registerExtensions(ALL_EXTENSIONS)
|
| 28 |
+
.registerDependencies({ 'draco3d.decoder': await draco3d.createDecoderModule() });
|
| 29 |
+
const doc = new Document();
|
| 30 |
+
doc.createBuffer();
|
| 31 |
+
const scene = doc.createScene('Industrial Harbor');
|
| 32 |
+
|
| 33 |
+
// the first material of each library material GLB, by data.materials index
|
| 34 |
+
const materials = [];
|
| 35 |
+
for (const path of data.materials) {
|
| 36 |
+
const src = await io.read(join(lib, 'materials', matManifest[path].file));
|
| 37 |
+
const map = mergeDocuments(doc, src);
|
| 38 |
+
const m = src.getRoot().listMaterials()[0];
|
| 39 |
+
materials.push(m ? map.get(m) : null);
|
| 40 |
+
}
|
| 41 |
+
const fallback = doc.createMaterial('Fallback').setBaseColorFactor([0.604, 0.627, 0.678, 1]).setRoughnessFactor(0.85).setMetallicFactor(0);
|
| 42 |
+
|
| 43 |
+
let placed = 0;
|
| 44 |
+
for (const group of data.instances) {
|
| 45 |
+
const path = data.meshes[group.mesh];
|
| 46 |
+
const src = await io.read(join(lib, 'meshes', meshManifest[path].file));
|
| 47 |
+
const map = mergeDocuments(doc, src);
|
| 48 |
+
const prims = []; // primitives in traversal order, as viewer.js's primitivesOf()
|
| 49 |
+
for (const s of src.getRoot().listScenes()) s.traverse((n) => { const m = n.getMesh(); if (m) prims.push(...m.listPrimitives().map((p) => map.get(p))); });
|
| 50 |
+
if (!prims.length) continue;
|
| 51 |
+
const meshes = new Map(); // one mesh per distinct slot assignment in this group
|
| 52 |
+
group.labels.forEach((label, i) => {
|
| 53 |
+
const slots = prims.map((_, p) => { const s = (group.slots[i] || [])[p]; return s != null && s >= 0 ? s : -1; });
|
| 54 |
+
const key = slots.join(',');
|
| 55 |
+
if (!meshes.has(key)) {
|
| 56 |
+
const mesh = doc.createMesh(path.split('.').pop());
|
| 57 |
+
prims.forEach((p, k) => mesh.addPrimitive(p.clone().setMaterial(slots[k] >= 0 && materials[slots[k]] ? materials[slots[k]] : fallback)));
|
| 58 |
+
meshes.set(key, mesh);
|
| 59 |
+
}
|
| 60 |
+
const pos = group.pos.slice(i * 3, i * 3 + 3);
|
| 61 |
+
if (NOT_GROUND.test(label || '')) pos[1] -= 0.02;
|
| 62 |
+
scene.addChild(doc.createNode(label).setMesh(meshes.get(key)).setTranslation(pos)
|
| 63 |
+
.setRotation(group.quat.slice(i * 4, i * 4 + 4)).setScale(group.scale.slice(i * 3, i * 3 + 3)));
|
| 64 |
+
placed++;
|
| 65 |
+
});
|
| 66 |
+
}
|
| 67 |
+
// the merged sources' own scenes are not used; prune() then drops their nodes and the source meshes
|
| 68 |
+
for (const s of doc.getRoot().listScenes()) if (s !== scene) s.dispose();
|
| 69 |
+
await doc.transform(prune(), unpartition());
|
| 70 |
+
|
| 71 |
+
// KTX2 -> PNG (RGBA32 = Basis transcoder format 13)
|
| 72 |
+
const require = createRequire(import.meta.url);
|
| 73 |
+
// three's package is "type": "module", so its UMD transcoder is evaluated as a script rather than required
|
| 74 |
+
const basisJs = require.resolve('three/examples/jsm/libs/basis/basis_transcoder.js');
|
| 75 |
+
const BASIS = new Function('require', '__dirname', `${readFileSync(basisJs, 'utf8')}\nreturn BASIS;`)(require, join(basisJs, '..'));
|
| 76 |
+
const basis = await BASIS({ wasmBinary: readFileSync(require.resolve('three/examples/jsm/libs/basis/basis_transcoder.wasm')) });
|
| 77 |
+
basis.initializeBasis();
|
| 78 |
+
let transcoded = 0;
|
| 79 |
+
for (const tex of doc.getRoot().listTextures()) {
|
| 80 |
+
if (tex.getMimeType() !== 'image/ktx2') continue;
|
| 81 |
+
const k = new basis.KTX2File(tex.getImage());
|
| 82 |
+
if (!k.isValid() || !k.startTranscoding()) throw new Error(`bad KTX2: ${tex.getName()}`);
|
| 83 |
+
let level = 0;
|
| 84 |
+
const dim = (l) => { const i = k.getImageLevelInfo(l, 0, 0); return Math.max(i.origWidth, i.origHeight); };
|
| 85 |
+
while (level + 1 < k.getLevels() && dim(level + 1) >= 512) level++;
|
| 86 |
+
const info = k.getImageLevelInfo(level, 0, 0);
|
| 87 |
+
const dst = new Uint8Array(k.getImageTranscodedSizeInBytes(level, 0, 0, 13));
|
| 88 |
+
if (!k.transcodeImage(dst, level, 0, 0, 13, 0, -1, -1)) throw new Error(`transcode failed: ${tex.getName()}`);
|
| 89 |
+
k.close(); k.delete();
|
| 90 |
+
tex.setImage(await sharp(Buffer.from(dst), { raw: { width: info.origWidth, height: info.origHeight, channels: 4 } }).png().toBuffer()).setMimeType('image/png');
|
| 91 |
+
transcoded++;
|
| 92 |
+
}
|
| 93 |
+
for (const e of doc.getRoot().listExtensionsUsed()) if (e.extensionName === 'KHR_texture_basisu') e.dispose();
|
| 94 |
+
console.log(`transcoded ${transcoded} KTX2 textures to PNG`);
|
| 95 |
+
doc.getRoot().setDefaultScene(scene);
|
| 96 |
+
for (const e of doc.getRoot().listExtensionsUsed()) if (e.extensionName === 'KHR_draco_mesh_compression') e.dispose();
|
| 97 |
+
await io.write(out, doc);
|
| 98 |
+
console.log(`placed ${placed} instances of ${data.instances.length} meshes, ${data.materials.length} materials -> ${out}`);
|
scripts/harbor_live.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""The Industrial Harbor card in the same live three.js viewer as the other cards (user, 2026-10-04: "你把IndustrialHarbor的threejs弄的和其他人一样啊").
|
| 2 |
+
|
| 3 |
+
GPT-6 Astra's scored harbor (EVAL gpt-6-astra-max, map scenebench_industrial_harbor__20260907_214132, the scene the viewer
|
| 4 |
+
Space shows) was staged and exported to GLB on serv6 (code4scene-video/scripts/export_glb_harbor.sh, with the ContainerYard,
|
| 5 |
+
Hangar and FactoryEnvironment packs linked from scenebench-content), then compressed as website/compress_glb.sh does for
|
| 6 |
+
Text-to-Scene scenes (meshopt geometry, 512 px WebP). The harbor has no case in data/site.js (no score), so its card names
|
| 7 |
+
its packed model itself (data-glb) and scene-cards.js reads that before looking up a case. The live scene replaces the still
|
| 8 |
+
(media/t2s/industrial-harbor/astra.jpg, removed); the card's link still opens the full-resolution viewer Space.
|
| 9 |
+
|
| 10 |
+
Each step asserts it found what it edits.
|
| 11 |
+
GLB=<compressed industrial-harbor__astra.glb> python3 scripts/harbor_live.py
|
| 12 |
+
"""
|
| 13 |
+
from __future__ import annotations
|
| 14 |
+
import hashlib, json, os, re, shutil, sys
|
| 15 |
+
from pathlib import Path
|
| 16 |
+
import numpy as np
|
| 17 |
+
from bs4 import BeautifulSoup
|
| 18 |
+
|
| 19 |
+
ROOT = Path(__file__).resolve().parent.parent
|
| 20 |
+
GLB = Path(os.environ["GLB"])
|
| 21 |
+
V = "20261004harborlive"
|
| 22 |
+
KEY = bytes.fromhex("5c2f9e71d3a84b06e1f7c29a38d05b64a7193ce8f2046db95e81c73a2df6904b") # website/pack_models.py
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def one(found, what):
|
| 26 |
+
assert found, f"not found: {what}"
|
| 27 |
+
return found
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def pack():
|
| 31 |
+
assert GLB.name == "industrial-harbor__astra.glb", GLB.name
|
| 32 |
+
a = np.frombuffer(GLB.read_bytes(), np.uint8); idx = np.arange(a.size, dtype=np.int64)
|
| 33 |
+
ks = np.frombuffer(KEY, np.uint8)[idx % 32] ^ ((idx // 32) * 131 & 255).astype(np.uint8)
|
| 34 |
+
dst = ROOT / "models" / f"{hashlib.sha256(b'c4s-model:' + GLB.name.encode()).hexdigest()[:20]}.bin"
|
| 35 |
+
dst.write_bytes((a ^ ks).tobytes())
|
| 36 |
+
url = f"models/{dst.name}?v={int(dst.stat().st_mtime)}"
|
| 37 |
+
print("packed", url, round(dst.stat().st_size / 1e6, 1), "MB")
|
| 38 |
+
return url
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def progressive(url):
|
| 42 |
+
"""build_progressive.py's geometry-first derivative, when textures are a real share of the file (as i2s_more_cases.py)"""
|
| 43 |
+
sys.path.insert(0, str(ROOT / "scripts"))
|
| 44 |
+
import build_progressive as bp
|
| 45 |
+
from i2s_more_cases import texture_share
|
| 46 |
+
share = texture_share(ROOT / url.split("?")[0])
|
| 47 |
+
print("texture share", round(share, 3))
|
| 48 |
+
if share < 0.1:
|
| 49 |
+
return
|
| 50 |
+
shutil.copyfile(ROOT / url.split("?")[0], bp.CACHE / url.split("/")[-1].split("?")[0])
|
| 51 |
+
m = ROOT / "data/progressive-scenes.json"; d = json.loads(m.read_text())
|
| 52 |
+
d.update([bp.convert(url)]); m.write_text(json.dumps(d, indent=2) + "\n")
|
| 53 |
+
cu = ROOT / "scripts/progressive-card-urls.json"; cu.write_text(json.dumps(json.loads(cu.read_text()) + [url]) + "\n")
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def scene_cards():
|
| 57 |
+
p = ROOT / "assets/scene-cards.js"; s = p.read_text()
|
| 58 |
+
a = " const c=window.SITE.cases.find(c=>c.id===el.dataset.case),a=c.agents.find(a=>a.key===el.dataset.agent);\n"
|
| 59 |
+
assert s.count(a) == 1, "mount() case lookup"
|
| 60 |
+
s = s.replace(a, " // a showcase card names its model itself (data-glb): it has no case, score or case-explorer entry in data/site.js\n"
|
| 61 |
+
" const c=el.dataset.glb?{agents:[{key:el.dataset.agent,glb:el.dataset.glb}]}:window.SITE.cases.find(c=>c.id===el.dataset.case),a=c.agents.find(a=>a.key===el.dataset.agent);\n")
|
| 62 |
+
p.write_text(s); print("scene-cards.js: data-glb")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
CSS = """
|
| 66 |
+
/* the featured card's live scene (scripts/harbor_live.py) */
|
| 67 |
+
.case-feature .live-scene{height:auto;min-height:400px;border-radius:16px 0 0 16px}
|
| 68 |
+
@media(max-width:900px){.case-feature .live-scene{min-height:0;height:270px;border-radius:16px 16px 0 0}}
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def index(url):
|
| 73 |
+
p = ROOT / "index.html"
|
| 74 |
+
soup = BeautifulSoup(p.read_text(), "html.parser")
|
| 75 |
+
card = one(soup.find(class_="case-feature"), "harbor card")
|
| 76 |
+
shot = one(card.find(class_="feature-shot"), "harbor still")
|
| 77 |
+
shot.replace_with(BeautifulSoup(
|
| 78 |
+
f'<div class="live-scene" data-agent="astra" data-case="industrial-harbor" data-glb="{url}"><canvas aria-label="Interactive 3D scene: '
|
| 79 |
+
'Industrial Harbor. Drag to orbit, scroll or use plus and minus to zoom." tabindex="0"></canvas><span class="scene-loading" role="status">'
|
| 80 |
+
'Loading 3D scene…</span><span class="scene-hint">Drag to orbit · Scroll to zoom</span><button aria-label="Pause scene rotation" '
|
| 81 |
+
'class="scene-motion">Ⅱ</button></div>', "html.parser"))
|
| 82 |
+
one(card.find("p"), "harbor line").string = "GPT-6 Astra (max) · 3,949 actors, built in one agent session from an empty 130 m stage"
|
| 83 |
+
one(card.find(class_="text-button"), "harbor link").string = "Open at full texture resolution ↗"
|
| 84 |
+
for t in soup.find_all(["script", "link"]):
|
| 85 |
+
a = "src" if t.name == "script" else "href"
|
| 86 |
+
u = t.get(a) or ""
|
| 87 |
+
if re.match(r"assets/(buildingbench\.css|scene-cards\.js)", u):
|
| 88 |
+
t[a] = re.sub(r"\?v=.*$", "", u) + f"?v={V}"
|
| 89 |
+
p.write_text(str(soup)); print("index.html: harbor card on the live viewer")
|
| 90 |
+
css = ROOT / "assets/buildingbench.css"; s = css.read_text()
|
| 91 |
+
assert "scripts/harbor_live.py" not in s
|
| 92 |
+
css.write_text(s.rstrip("\n") + "\n" + CSS)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
if __name__ == "__main__":
|
| 96 |
+
url = pack(); progressive(url); scene_cards(); index(url)
|
scripts/progressive-card-urls.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
["models/38071c69a86d174dc55f.bin?v=1790737099", "models/46734878f740aae816d8.bin?v=1790737099", "models/66da6868d20ebb100197.bin?v=1790737099", "models/6afbbaec6b7a4271b21f.bin?v=1790737099", "models/a32fa4ebc640e2278635.bin?v=1790737099", "models/cb082e689f15e654daab.bin?v=1790737099", "models/cc1bdce0533a50e81385.bin?v=1790737099", "models/db5c0c5d2b78f9e47bb7.bin?v=1790737099", "models/e6a6333939ccfe57d584.bin?v=1790737099", "models/fa367ea5d33ed24f577a.bin?v=1790737099", "models/feb923d4f4f257315904.bin?v=1790737098", "models/fef6016b97b176af9fef.bin?v=1791181855", "models/6ed621e057a53331469a.bin?v=1791181855", "models/843768ef1999c6f33178.bin?v=1791181855", "models/d3e551d366b82c38cfe2.bin?v=1791181856", "models/ca03f1482ef5f2decbcb.bin?v=1791181856", "models/73ceabf2d178a47c7d70.bin?v=1791181856"]
|
|
|
|
| 1 |
+
["models/38071c69a86d174dc55f.bin?v=1790737099", "models/46734878f740aae816d8.bin?v=1790737099", "models/66da6868d20ebb100197.bin?v=1790737099", "models/6afbbaec6b7a4271b21f.bin?v=1790737099", "models/a32fa4ebc640e2278635.bin?v=1790737099", "models/cb082e689f15e654daab.bin?v=1790737099", "models/cc1bdce0533a50e81385.bin?v=1790737099", "models/db5c0c5d2b78f9e47bb7.bin?v=1790737099", "models/e6a6333939ccfe57d584.bin?v=1790737099", "models/fa367ea5d33ed24f577a.bin?v=1790737099", "models/feb923d4f4f257315904.bin?v=1790737098", "models/fef6016b97b176af9fef.bin?v=1791181855", "models/6ed621e057a53331469a.bin?v=1791181855", "models/843768ef1999c6f33178.bin?v=1791181855", "models/d3e551d366b82c38cfe2.bin?v=1791181856", "models/ca03f1482ef5f2decbcb.bin?v=1791181856", "models/73ceabf2d178a47c7d70.bin?v=1791181856", "models/300f1aa5a401127f000d.bin?v=1791183752"]
|