SpatialDise is a Blender-based dataset generator for 3D spatial reasoning tasks. It creates rendered images plus JSON metadata for:
3d_rotation3d_projection3d_combination3d_folding3d_shape_finding
- Python
>= 3.10 - Blender (recommended
3.6+) available asblenderin your shell uv(recommended for dependency management)
generator/core/: shared camera/scene/render/geometry utilitiesgenerator/tasks/3d/: task implementationsgenerator/cli/: command-line entrypointsgenerator/scripts/: helper scripts (for example icon caching)generator/tests/test_regression.py: Blender regression smoke testtests/: pure Python unit testsconfigs/spatialdise_3d.yaml: sample multi-task configassets/lucide/: cached icon assets used by folding/shape-finding tasks
From repository root:
uv venv .venv
source .venv/bin/activate
uv sync --group devThis installs runtime dependencies and pytest for local tests.
If this fails, install Blender and add it to your PATH.
- Download Blender from the official site: https://www.blender.org/download/
- Install Blender.
- Make sure
blenderis callable from your terminal:
blender --versionIf your shell cannot find blender, add Blender to PATH:
- Linux/macOS: add the Blender executable directory to your shell profile.
- Windows: add Blender install directory to Environment Variables
Path.
Run one generator directly inside Blender:
blender --background --python generator/cli/generate.py -- \
--task 3d_rotation \
--num-questions 5 \
--difficulty-level easy \
--resolution 640x480 \
--output-dir blender_dataset/3D_rotation_demoNotes:
- Arguments after
--are passed to the Python script. --difficulty-levelis the discrete level (easy|medium|hard).--difficultyin this CLI is a numeric distractor scale.
Use the sample config:
blender --background --python generator/cli/config_generate.py -- \
--config configs/spatialdise_3d.yamlDry run (show planned jobs only):
blender --background --python generator/cli/config_generate.py -- \
--config configs/spatialdise_3d.yaml \
--dry-runRun only selected tasks from config:
blender --background --python generator/cli/config_generate.py -- \
--config configs/spatialdise_3d.yaml \
--task 3d_folding \
--task 3d_shape_findingSpatialDise supports two config styles:
- Multi-task config (recommended):
defaults+tasks - Single-task config: one task object at root
Example (multi-task):
defaults:
output_root: blender_dataset
image_resolution: [640, 480]
num_questions: 20
difficulty: medium
use_gpu: true
tasks:
- task: 3d_rotation
difficulty: hard
num_questions: 30
- task: 3d_folding
difficulty: medium
lucide_download: falseConfig behavior:
- Each task config is merged as:
task_itemoverridesdefaults. taskis required per job (orname/generatoras fallback).presetis ignored inconfig_generate.py; use explicit fields likedifficulty,num_cells_min,num_cells_max,distractor_difficulty.image_resolutioncan be[W, H]; it is normalized to(W, H)internally.
Output directory behavior:
- If
output_diris set in a task, it is used directly. - Else if
output_rootis set, output is:output_root/<TaskDefaultName>/<difficulty>(difficulty suffix only when set). - Else default output is used (
blender_dataset/3D_*, with optional difficulty suffix).
Available example configs:
- Basic example:
configs/spatialdise_3d.yaml - Full-parameter example:
configs/spatialdise_3d_full_example.yaml
Supported task names:
3d_rotation3d_projection3d_combination3d_folding3d_shape_finding
By default, output folders are under blender_dataset/:
3d_rotation->blender_dataset/3D_rotation3d_projection->blender_dataset/3D_projection3d_combination->blender_dataset/3D_combination3d_folding->blender_dataset/3D_folding3d_shape_finding->blender_dataset/3D_shape_finding
Each task writes:
- rendered images (
*_Q.png,*_A*.png, etc.) - per-question metadata JSON
- a summary file
3d_folding and 3d_shape_finding can use:
- Lucide icons under
assets/lucide/ - Custom icons under
assets/customize/
Recommended format: PNG.
- Put custom icons in
assets/customize/*.pngwhenever possible. 3d_shape_findingusesallow_svg_fallback=false, so SVG-only icons may be skipped.
When lucide_icons is not set:
- If
assets/customize/has icons, use all available custom icons. - Otherwise, use the default Lucide icon list.
When lucide_icons is set:
Each icon name is resolved in this order:
assets/customize/{name}.png|.svgassets/lucide/{name}.png|.svg- download from Lucide (when
lucide_download: true)
You can pre-cache Lucide icons:
uv run generator/scripts/cache_lucide_icons.py -- --icons circle square triangleCache all available icons:
uv run generator/scripts/cache_lucide_icons.py -- --allIf PNG conversion fails, install cairosvg or allow SVG fallback with:
uv run generator/scripts/cache_lucide_icons.py -- --allow-svg-fallback- Source: https://lucide.dev
- License: ISC
- Copyright: Lucide Contributors
- Local license note:
assets/lucide/LICENSE_LUCIDE.txt
When redistributing generated assets that include Lucide icons, keep the license attribution above.
Option 1: pass icons directly:
uv run generator/scripts/cache_lucide_icons.py -- --icons circle square triangle heartOption 2: use a file:
uv run generator/scripts/cache_lucide_icons.py -- --icons-file ./my_icons.txtmy_icons.txt example:
circle
square
triangle
heart
If you want to replace the existing icon cache completely:
rm -f assets/lucide/*.png assets/lucide/*.svg
uv run generator/scripts/cache_lucide_icons.py -- --icons-file ./my_icons.txtNotes:
lucide_download: falsemeans use local cache only.lucide_download: trueallows downloading missing icons at runtime.- If an icon with the same name exists in
assets/customize/, it overrides Lucide. - For best compatibility, store custom icons as PNG files.
Pure Python tests:
pytest -qBlender regression smoke test (all tasks, all difficulties):
blender --background --python generator/tests/test_regression.py -- \
--output-root ./tmp/regression_fullSmaller run:
blender --background --python generator/tests/test_regression.py -- \
--task 3d_projection \
--difficulty easy \
--num-questions 2 \
--output-root ./tmp/regression_projection-
bpy not foundRun scripts with Blender (blender --background --python ...), not plainpython. -
YAML config fails to load (
PyYAMLmissing) Install dependencies into your environment (uv sync) and ensure Blender can access them. -
Folding/shape-finding has missing icon textures Run the icon cache script first, and verify files exist under
assets/lucide/. -
Blender command not found Install Blender and add it to your shell
PATH.
from generator.tasks import get_generator_class
Generator = get_generator_class("3d_rotation")
gen = Generator(
output_dir="blender_dataset/3D_rotation_api_demo",
config={
"num_questions": 3,
"image_resolution": (640, 480),
"difficulty": "easy",
"use_gpu": False,
},
)
files, summary = gen.generate_dataset()
print(len(files), summary)If you find Spatial-DISE helpful, please cite:
@inproceedings{huang2025spatialdise,
title = {Spatial-{{DISE}}: {{A Unified Benchmark}} for {{Evaluating Spatial Reasoning}} in {{Vision-Language Models}}},
booktitle = {The {{Fourteenth International Conference}} on {{Learning Representations}}},
author = {Huang, Xinmiao and He, Qisong and Huang, Zhenglin and Wang, Boxuan and Li, Zhuoyun and Cheng, Guangliang and Dong, Yi and Huang, Xiaowei},
year = 2025
}