Skip to content
nagara214Public

About

[SIGGRAPH Asia 2026] Geometry-Aware Implicit Memory for Video World Models

Resources

Stars

16 stars

Watchers

0 watching

Forks

Repository files navigation

GIM-World: Geometry-Aware Implicit Memory for Video World Models

SIGGRAPH Asia 2026

Zhengxuan Wei1,2*, Xu Guo3,2*, Xinghui Li2*†, Xunzhi Xiang1, Min Wei2, Yiran Zhu2, Qiulin Wang2, Xintao Wang2, Pengfei Wan2, Xiangwang Hou3, Qi Fan1†

1Nanjing University   2Kling Team, Kuaishou Technology   3Tsinghua University
*Equal contribution   †Corresponding author

TL;DR   GIM-World compresses an arbitrarily long observation history into a fixed-size implicit memory whose content is supervised to encode 3D scene geometry. Long-horizon autoregressive rollouts stay geometrically coherent and visually consistent with the scene, while explicit-memory (frame retrieval / packing) and geometry-agnostic implicit-memory baselines drift.

🔥 News

  • [2026-09] Code and checkpoints (first-person / third-person MIND) released.
  • [2026-06] Paper on arXiv.
  • [2026] GIM-World is accepted to SIGGRAPH Asia 2026.

📋 Table of Contents

📖 Introduction

Video world models generate the future from past observations and actions, but a long rollout depends on what the model remembers once observations leave its context window. Explicit memories keep frames or an online 3D reconstruction and inherit retrieval heuristics, redundant appearance storage or reconstruction artifacts; implicit memories compress history into a compact state, but nothing constrains that state to encode cross-view geometry.

GIM-World is a geometry-aware implicit memory for video world models built on a Wan2.1-1.3B DiT backbone:

  • Implicit Memory Encoder — two blocks of compact self-attention + FFN turn a variable-length, camera-indexed history into a fixed set of memory tokens; the tokens are concatenated with the target latents to condition the backbone. The encoder runs in < 0.3 % of the backbone's time.
  • Camera-Queryable Geometry Supervision (training only) — a ray-map query of a sampled history camera reads the memory and is matched against frozen VGGT features, forcing the memory to store view-consistent geometry rather than an appearance cache. The geometry head and teacher are discarded at inference; the head and loss are provided for reference in gim/models/geometry_head.py but are not used by generate.py.
  • Information-Guided Pruning — before encoding, the history is reduced to a budget of K latents by greedily maximizing mutual information under a pose–time Gaussian-process kernel, so encoding cost stays bounded as the rollout grows.

🛠️ Installation

conda create -n gim-world python=3.10 -y
conda activate gim-world
pip install -r requirements.txt
pip install flash-attn --no-build-isolation   # required by the Wan2.1 backbone

Tested with PyTorch >= 2.4 and CUDA 12.x on a single NVIDIA GPU (bf16 VAE / T5, fp32 DiT).

⬇️ Download Models

# Wan2.1 VAE / umT5 + GIM-World checkpoints from ModelScope,
# plus one MIND example clip for the quick start
python download_models.py --with_example

This fetches the Wan2.1-T2V-1.3B VAE / umT5 text encoder and the GIM-World checkpoints, and prints the paths to use below. Checkpoints are hosted on ModelScope: nagara214/GIM-World.

Checkpoint Trained on
GIM-World/first_person MIND first-person split
GIM-World/third_person MIND third-person split

Each checkpoint folder holds transformer/ (DiT), memory_encoder.safetensors, camera_proj.safetensors, action_embedding.safetensors and a config.json with the inference hyper-parameters (480×832, 20-latent chunks, pruning budget 200).

🎮 Quick Start

bash run.sh

run.sh rolls out the example clip in assets/examples/demo_scene for 20 seconds after its mark_time, following the recorded camera trajectory, and writes outputs/demo/demo_scene/video.mp4 (observed prefix + generated frames). Edit the variables at the top of run.sh to point at your own paths.

🔑 Inference

A single entry point handles everything end to end — VAE encoding of the prefix, text encoding, history pruning, autoregressive rollout and decoding — no offline preprocessing step.

python generate.py \
    --input  path/to/clip_dir \
    --output outputs/my_run \
    --gim_ckpt checkpoints/GIM-World/first_person \
    --wan_dir  checkpoints/Wan2.1-T2V-1.3B

Input format

A clip is a directory in the MIND layout:

clip_dir/
├── video.mp4      # at least the observed prefix: frames [0, mark_time)
└── action.json
{
  "mark_time": 1465,          // first frame to generate
  "total_time": 4352,         // frames covered by "data"
  "caption": "...",           // optional text prompt
  "data": [                   // one entry per frame, prefix AND future
    {"time": 0,
     "ws": 0, "ad": 0, "ud": 0, "lr": 0,               // actions: 0 none, 1 +, 2 −
     "actor_pos": {"x": 2398.2, "y": -4672.6, "z": 168.6},   // cm (Unreal)
     "actor_rpy": {"x": 0, "y": 0, "z": -72.5},              // roll/pitch/yaw, degrees
     "camera_pos": {...}, "camera_rpy": {...}}       // third-person only
  ]
}

Frames [0, mark_time) of video.mp4 are encoded as the initial history; entries [mark_time, total_time) of data provide the camera path and actions to follow. Positions are divided by 100 (cm → m) and expressed relative to the first history frame inside the model.

Custom camera trajectories

Author an action.json for your own footage with a pose string:

# treat all frames of my_clip/video.mp4 as the prefix, then move forward 60 frames,
# turn right 20 frames, move forward 40 frames
python make_trajectory.py --clip_dir my_clip \
    --pose "w-60, right-20, w-40" \
    --caption "A quiet stone courtyard at dusk."
python generate.py --input my_clip --output outputs/my_clip --gim_ckpt ... --wan_dir ...
Token Meaning Token Meaning
w / s move forward / backward up / down look up / down
a / d move left / right left / right look left / right
stay hold pose

Each item is <action>-<frames>; speeds default to 5 cm/frame and 1°/frame (--move_speed, --turn_speed). If your prefix camera is not static, pass per-frame poses with --prefix_pose_json. For arbitrary paths, write action.json directly or use gim.utils.trajectory.frames_from_keyframes.

Options

Flag Default Description
--max_seconds 20 Stop this many seconds after mark_time (≤ 0: run to total_time)
--num_steps 50 Denoising steps per chunk (DPM-Solver++)
--guide_scale 1.0 Text CFG scale (1.0 = off)
--pruning from config information_guided (paper) or uniform
--pruning_budget 200 Max history latents kept before memory encoding
--perspective from config 1st or 3rd: which pose in action.json is the camera
--caption from json Override the text prompt
--include_prefix off Prepend the observed frames to the saved video
--dry_run off Encode, align and prune only (no diffusion) — quick sanity check

Every 20-latent chunk corresponds to 77 frames (≈ 3.2 s at 24 fps).

Reproducing MIND mem_test

Point --input_root at a MIND split; every sub-directory with video.mp4 + action.json is a clip, and clips are sharded across the GPUs launched by torchrun:

torchrun --nproc_per_node=8 generate.py \
    --input_root MIND-Data/1st_data/test/mem_test \
    --output     outputs/gim_world/1st_data/mem_test \
    --gim_ckpt   checkpoints/GIM-World/first_person \
    --wan_dir    checkpoints/Wan2.1-T2V-1.3B

torchrun --nproc_per_node=8 generate.py \
    --input_root MIND-Data/3rd_data/test/mem_test \
    --output     outputs/gim_world/3rd_data/mem_test \
    --gim_ckpt   checkpoints/GIM-World/third_person \
    --wan_dir    checkpoints/Wan2.1-T2V-1.3B --perspective 3rd

The output tree outputs/gim_world/{1st_data,3rd_data}/mem_test/{clip}/video.mp4 is exactly what the official MIND evaluator expects:

python src/process.py --gt_root MIND-Data --test_root outputs/gim_world --num_gpus 8

📊 Results

Quantitative comparison on the MIND memory test (from the paper, Table 1). Memory: per-frame reconstruction vs. ground truth; Action: relative pose error of the rendered trajectory; Geometry: normalized dense reprojection score.

MethodFirst-personThird-person
MSE↓PSNR↑SSIM↑LPIPS↓Trans↓Rot↓Reproj↑ MSE↓PSNR↑SSIM↑LPIPS↓Trans↓Rot↓Reproj↑
Matrix-Game 2.00.1188–––0.02650.6914–0.1404–––0.06220.9031–
MIND-World0.1035–––0.03840.5534–0.1042–––0.03210.3328–
FramePack0.076412.040.37630.70620.02690.653673.970.073512.230.39570.67700.01450.285270.82
Context-as-Memory0.070612.500.39170.69530.02350.569766.140.067112.810.40510.64800.02410.438569.17
SSM memory0.079611.960.39530.74390.03790.670253.950.092811.760.40370.68300.02010.297161.26
GIM-World0.061413.400.41350.63040.02470.412681.700.060513.580.43030.59740.01060.158887.10

🗂️ Code layout

generate.py                 # single inference entry point
make_trajectory.py          # author action.json from a pose string
download_models.py          # fetch Wan2.1 VAE/T5 + GIM-World checkpoints (+ example clip)
gim/
  pipeline.py               # GIMWorldPipeline: encode -> prune -> rollout -> decode
  models/
    memory_encoder.py       # Implicit Memory Encoder (Sec. 3.2)
    dit.py                  # memory-conditioned Wan2.1 DiT, camera injection, chunk sampler
    action_embedding.py     # action embeddings
    geometry_head.py        # camera-queryable geometry head + L_geo (Sec. 3.3, training only)
  utils/
    pruning.py              # information-guided pruning (Sec. 3.4)
    camera.py               # poses, relative frames, latent <-> frame alignment
    video.py                # streaming Wan VAE encode / decode, mp4 I/O
    trajectory.py           # pose-string / keyframe -> action.json
wan/                        # trimmed Wan2.1 (DiT, VAE, umT5, flow-matching solver)

📚 Citation

@article{wei2026gim,
  title   = {Geometry-Aware Implicit Memory for Video World Models},
  author  = {Wei, Zhengxuan and Guo, Xu and Li, Xinghui and Xiang, Xunzhi and Wei, Min and Zhu, Yiran and Wang, Qiulin and Wang, Xintao and Wan, Pengfei and Hou, Xiangwang and Fan, Qi},
  journal = {arXiv preprint arXiv:2606.02436},
  year    = {2026}
}

📧 Contact

Questions and issues: open a GitHub issue or email [email protected].

🙏 Acknowledgements

GIM-World builds on Wan2.1 (backbone, VAE, text encoder), is trained and evaluated on MIND, and distills geometry from VGGT during training. We thank the authors for releasing their work.

License

Code derived from Wan2.1 is released under the Apache 2.0 License; the GIM-World additions follow the same license.

About

[SIGGRAPH Asia 2026] Geometry-Aware Implicit Memory for Video World Models

Resources

Stars

16 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages