Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

SpatialBench Logo

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

PaperarXivProject PageSpatialBenchDA-Next-5MDA-Next


SpatialBench Overview

🔍 Overview

SpatialBench is a deterministic, density-aware benchmark for evaluating spatial foundation models across multiple paradigms and various domains. It spans 19 source datasets, 540+ scenes, 40+ model variants, and six reconstruction paradigms covering depth, camera pose, trajectory, point-cloud reconstruction, long-sequence streaming, and prior-enhanced tasks.

Every scene is normalized into RGB / metric depth / camera-to-world pose / intrinsics, and the test frames for each scene are precomputed and pinned, so all users evaluate on exactly the same frames. A unified YAML-config + model-adapter interface lets you drop in a new model with a single predict() method.

Overview

The leaderboard is reported in leaderboard.md.

🔧 Installation

Setup Environment

conda create -n spatialbench python=3.11
conda activate spatialbench
# 1) PyTorch — pick the CUDA build that matches your driver (must be installed first)
pip install torch==2.7.0 torchvision==0.22.0 torchaudio==2.7.0 --index-url https://download.pytorch.org/whl/cu128
# 2) Core benchmark harness (no per-model deps yet)
pip install -e .
Per-model extras — click to expand

Model-specific dependencies are managed via pip extras. Install only the ones you need — every extra below pulls in exactly what is required to run the corresponding config under benchmark/configs/:

# VGGT and most VGGT-family adapters — vggt, vggt_omega, fastvggt, omnivggt, pi3, pi3x,# worldmirror, stream3r_{stream,window}, page4d, vggt_long, pi_long, loger, loger_star
pip install -e ".[vggt]"# Optimization-based DUSt3R / MASt3R adapters (depends on [vggt] + roma + scikit-learn)
pip install -e ".[optimization]"# MAPAnything (depends on [vggt] + hydra-core + uniception)
pip install -e ".[mapanything]"# LingbotMap window/stream adapters (depends on [vggt] + flashinfer-python)
pip install -e ".[lingbot-map]"# Depth Anything 3 family — da3_{small,base,large,giant}, da3nested, da3_streaming
pip install -e ".[da3]"# Scal3R TTT adapter (depends on [vggt] + numba + pykitti + pypose + rich)
pip install -e ".[scal3r]"# ZipMap TTT adapter (depends on [vggt]; source is vendored under benchmark/models/zipmap)
pip install -e ".[zipmap]"# VGG-TTT adapter (depends on [vggt] + hydra-core; source is vendored under benchmark/models/vgg_ttt)
pip install -e ".[vgg_ttt]"# StreamVGGT / InfiniteVGGT (depends on [vggt] + transformers)
pip install -e ".[streaming]"# R3 online adapter (vendored under benchmark/models/r3; depends on DA3 + xformers)
pip install -e ".[r3]"# AMB3R benchmark adapter for the README environment above:# Python 3.11 + torch==2.7.0+cu128 / torchvision==0.22.0+cu128.# Install the CUDA extension wheels first, then install the Python extra.
pip install torch-scatter==2.1.2 -f https://data.pyg.org/whl/torch-2.7.0+cu128.html
pip install xformers==0.0.30 --index-url https://download.pytorch.org/whl/cu128
pip install spconv-cu126==2.3.8
pip install "git+https://github.com/facebookresearch/pytorch3d.git@V0.7.8" --no-build-isolation
pip install flash-attn==2.7.3 --no-build-isolation
pip install -e ".[amb3r]"# Combine multiple at once, for example
pip install -e ".[vggt,optimization,mapanything,lingbot-map,da3,scal3r,zipmap,vgg_ttt,r3]"# Install all currently supported model deps
pip install -e ".[all]"

LingbotMap defaults to FlashInfer attention (use_sdpa: false). If your package index cannot resolve a compatible flashinfer-python wheel, install FlashInfer from the wheel index matching your CUDA/PyTorch build, or set use_sdpa: true in the LingbotMap config to use PyTorch SDPA instead.

DUSt3R / MASt3R vendor CroCo under benchmark/models/{dust3r_root,mast3r_root}/. CroCo's CUDA RoPE extension is optional; if it is not compiled, the adapters fall back to the slower PyTorch RoPE implementation.

Optional: DA-Next submodule

The DA-Next variant lives in a separate git submodule. If you only run the benchmark, you can skip this:

git submodule update --init --recursive DA-Next

Download Datasets

The benchmark is released on Hugging Face as tar archives — one per sampling regime, plus an optional ground-truth point-cloud archive. Pick the regime(s) you need; you do not have to download all archives.

ArchiveFileSizeRecommend
Singlesingle.tar1.0 GiB
Sparsesparse.tar5.1 GiB
Mediummedium.tar19.4 GiB
Densedense.tar73.9 GiB
Point-cloud GTpointcloud.tar1.8 GiB

The pointcloud.tar archive is required only if you enable point-cloud evaluation metrics. It unpacks into SpatialBenchmark/pointcloud/.

# Download the archive(s) you need (here: all four single/sparse/medium/dense)
mkdir -p SpatialBenchmark &&cd SpatialBenchmark
forsplitin single sparse medium dense;do
hf download ropedia-ai/SpatialBenchmark "${split}.tar" \
--repo-type dataset --local-dir .done# Optional: download GT point clouds only when running point-cloud evaluation
hf download ropedia-ai/SpatialBenchmark pointcloud.tar \
--repo-type dataset --local-dir .# Extract — each tar unpacks into its own top-level directory (single/, sparse/, ...)forsplitin single sparse medium dense;do
tar -xf "${split}.tar"&& rm "${split}.tar"# drop the rm if you want to keep the archivedone# Optional: extract GT point clouds for point-cloud evaluation
tar -xf pointcloud.tar && rm pointcloud.tar
After downloading, the directory tree should look like this (click to expand)
SpatialBenchmark
├── _split_log.jsonl
├── dense
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── kitti_odometry
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── medium
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
├── pointcloud # optional, required only for point-cloud evaluation
│ ├── 7scenes
│ ├── dtu
│ ├── hiroom
│ ├── nrgbd
│ └── scannetpp
├── single
│ ├── 7scenes
│ ├── adt
│ ├── droid
│ ├── dtu
│ ├── eth3d
│ ├── hiroom
│ ├── lingbot
│ ├── nrgbd
│ ├── omniworld
│ ├── rlbench
│ ├── robolab
│ ├── robotwin
│ ├── ropedia
│ ├── scannetpp
│ ├── tanks_and_temples
│ ├── tum
│ ├── vkitti
│ └── waymo
└── sparse
├── 7scenes
├── adt
├── droid
├── dtu
├── eth3d
├── hiroom
├── nrgbd
├── omniworld
├── rlbench
├── robolab
├── robotwin
├── ropedia
├── scannetpp
├── tanks_and_temples
├── tum
├── vkitti
└── waymo

Download Model Checkpoints

Most adapters auto-download from the Hugging Face Hub the first time they run (e.g. facebook/VGGT-1B, depth-anything/DA3-GIANT-1.1, nvidia/vgg-ttt). If you prefer to pre-stage them, set checkpoint in each model yaml to your cache directory before running an evaluation.

Visualize Benchmark Scenes

Use the web viewer to inspect GT RGB, depth, camera poses, point clouds, and exported GLB files. The viewer uses the same benchmark/datasets readers as the evaluation harness, so it expects the current SpatialBenchmark layout:

SpatialBenchmark/{single,sparse,medium,dense}/{dataset}/{scene_path}/...

Start the viewer from the repository root:

python visualize_benchmark_web.py \
--benchmark-root SpatialBenchmark \
--scene-index benchmark/scene_indices/all_scenes.json \
--port 8082

Then open http://localhost:8082. If your dataset is stored elsewhere, point --benchmark-root to that directory. --scene-index defaults to benchmark/scene_indices/all_scenes.json, so it only needs to be set when using a custom scene index.

🚀 Quick Start

Run the VGGT baseline on the full benchmark in a single command:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml

Override config fields from the CLI for quick experiments:

python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/vggt_eval.yaml \
--tags "droid+sparse" --max-scenes 5 --visualize

For the complete usage, tag-filter syntax, model list, and per-metric details, see benchmark/README.md.

Tag Filter Syntax

SyntaxMeaningExample
datasetAll scenes from a single datasetdroid, dtu, tanks_and_temples
tag1+tag2AND: matches bothdtu+dense, droid+sparse+indoor
tag1|tag2OR: matches eithersparse|dense
nullNo filter, all scenes

Available tag axes (values verified against benchmark/scene_indices/all_scenes.json):

Tag axisPossible values
source_dataset7scenes, adt, droid, dtu, eth3d, hiroom, kitti_odometry, lingbot, nrgbd, omniworld, rlbench, robolab, robotwin, ropedia, scannetpp, tanks_and_temples, tum, vkitti, waymo
view_densitysparse / medium / dense / single (1 frame)
environmentindoor / outdoor
dynamicsstatic / dynamic
view_typewrist / egoview / normal
data_typereal / simulation

Scenes tagged single contain only one frame, so pose / trajectory / point-cloud metrics are undefined — the evaluation harness auto-restricts eval_metrics to ["depth"] when the tag expression includes single.

📊 Dataset Coverage

SpatialBench unifies 19 source datasets that span indoor / outdoor, real / simulation, static / dynamic, and a range of embodied view types.

DatasetEnvironmentTypeNotes
DROIDindoorreal / dynamicRobot manipulation (wrist view)
DTUindoorreal / staticMulti-view stereo (normal view)
ETH3Dindoor / outdoorreal / staticHigh-precision MVS (COLMAP format)
7-Scenesindoorreal / staticIndoor localization
RLBenchindoorsyntheticRobot simulation tasks
Ropediaindoorreal / dynamicRobot egocentric view
NRGBDindoorreal / staticNeural RGB-D
RoboTwinindoorsyntheticBimanual robot simulation
Tanks & Templesoutdoorreal / staticOutdoor large scenes (RobustMVD)
TUMindoorreal / dynamicRGB-D SLAM
ADTindoorreal / dynamicAria Digital Twin
OmniWorldoutdoorsimulation / dynamicGame-engine virtual outdoor scenes
Lingbotindoor / outdoorreal / dynamicLingbot robot single-frame scenes
VKITTIoutdoorsimulation / dynamicVirtual KITTI 2 driving simulation
Waymooutdoorreal / dynamicWaymo Open Dataset autonomous driving (LiDAR depth)
RoboLabindoorsimulation / dynamicIsaac Sim synthetic (wrist view)
HiRoomindoorsimulation / staticSynthetic indoor (aliasing_mask filtered)
ScanNet++indoorreal / staticiPhone subset (COLMAP + rendered depth)

Full per-dataset reader specs live in benchmark/datasets/data_readers.py.

📖 Models

SpatialBench ships adapters for 40+ spatial foundation model variants. Each lives under benchmark/evaluation/model_adapters/. Following the taxonomy used in our main leaderboard, models are grouped into six categories:

  • Optimization-based: DUSt3R, MASt3R
  • End-to-End Feed-Forward: VGGT, VGGT-Omega, Fast3R, FastVGGT, MUSt3R, MAPAnything, OmniVGGT, π³, π³-X, AMB3R, DA3 (Small / Base / Large / Giant), DA3-Nested, WorldMirror
  • Online: Spann3R, CUT3R, MonST3R, Point3R, Stream3R (Stream / Window), StreamVGGT, PAGE4D, InfiniteVGGT, WinT3R, LongStream (Batch / Streaming), LingbotMap (Stream / Window)
  • Chunk-wise: VGGT-Long, π³-Long, DA3-Streaming
  • SLAM-based: MASt3R-SLAM, VGGT-SLAM
  • Test-Time Training: TTT3R, Scal3R, LoGeR, LoGeR*, ZipMap, VGG-TTT

See benchmark/README.md for the full table and per-model configs under benchmark/configs/.

🌟 DA-Next (Ours)

DA-Next is our metric-scale extension of Depth Anything 3 — it adds a scale head, a camera encoder, and ray-based pose decoding. Source and training/inference instructions live in the DA-Next/ submodule.

# Fetch the DA-Next submodule (one-time)
git submodule update --init --recursive DA-Next
# Evaluate DA-Next via the unified harness
python benchmark/evaluation/run_benchmark.py \
--config benchmark/configs/end2end/danext_eval.yaml

Integrating a New Model

frombenchmark.evaluation.model_adaptersimportregister_adapterfrombenchmark.evaluation.model_adapters.base_adapterimportModelAdapter@register_adapter("your_model")classYourModelAdapter(ModelAdapter):
defname(self):
return"YourModel"defload_model(self, checkpoint=None, device="cuda"):
...
defpredict(self, scene):
# scene contains images / intrinsic / depth(GT) / extrinsic(GT)# Return any subset of pred_depth / pred_pose / pred_pointcloud / pred_confidencereturn {"pred_depth": ..., "pred_pose": ...}
defsupports_metric_depth(self):
returnFalse

Full adapter contract: benchmark/README.md#integrating-a-new-model.

📈 Evaluation Metrics

CategoryMetrics
Depthabs_rel, sq_rel, rmse, log_rmse, delta_1.03, delta_1.05, delta_1.10
Camera pose (pairwise)racc_3 / racc_5, tacc_3 / tacc_5, auc_3 / 5 / 15 / 30
Trajectory (Sim(3) aligned)ATE, RPE
Point cloudchamfer_distance, f_score (τ=0.05)

Predicted poses are aligned to GT via Procrustes, and depth metrics are reported with and without scale alignment (median / lstsq) depending on whether the model is metric. See benchmark/README.md#metric-definitions for definitions.

📝 To-Do List

  • ✅ Release technical report on arXiv
  • ✅ Release benchmark dataset on Hugging Face
  • ✅ Release DA-Next training scripts
  • Release DA-Next Checkpoint
  • Release DA-Next-5M dataset
  • Update more model adapter

🤝 Citation

If SpatialBench is useful for your research, please cite:

@misc{peng2026spatialbench,
title={SpatialBench: Is Your Spatial Foundation Model an All-Round Player?}, author={Haosong Peng and Hao Li and Jiaqi Chen and Yuhao Pan and Runmao Yao and Yalun Dai and Fushuo Huo and Fangzhou Hong and Zhaoxi Chen and Haozhao Wang and Dingwen Zhang and Ziwei Liu and Wenchao Xu},
year={2026},
eprint={2605.27367},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2605.27367}, 

📄 License

  • Benchmark code (this repository): released under the CC-BY 4.0.
  • Dataset assets (released via Hugging Face ropedia-ai/DA-Next-5M): released under the CC-BY-NC 4.0.

Third-party model checkpoints and source datasets remain subject to their original upstream licenses.

🙏 Acknowledgments

SpatialBench builds on a large body of prior work. We thank the authors of the following projects whose code or data are reused in this benchmark, as well as the maintainers of the 19 source datasets listed above.

Optimization-based — click to expand
End-to-End Feed-Forward — click to expand
Online — click to expand
Chunk-wise — click to expand
SLAM-based — click to expand
Test-Time Training — click to expand
Prior-enhanced variants — click to expand

Configurations that condition the same backbone on additional priors (intrinsics / depth / etc.).

About

SpatialBench: Is Your Spatial Foundation Model an All-Round Player?

Topics

Resources

Stars

127 stars

Watchers

2 watching

Forks

Contributors

Languages