Skip to content

About

Agent-Based Model Simulation in Blender

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Blender ABMSim

A multi-agent simulation add-on that runs inside Blender, built around geometry space and object elements: agents live on a real 3D mesh space where distance, visibility, collision, and heading are first-class citizens (vs. NetLogo's 2D patches, GAMA's GIS focus, or Mesa's visualization-less Python).

ABMSim demo

Features: random walk + boundary reflection + obstacle avoidance + Boids flocking + SIR spreading + trajectory baking & export + numpy vectorization + heading display + layered 2.5D (multi-surface / elevators / goal seeking / force fields). The core is numpy (N,3) (tens of thousands of agents), rendered in bulk via Geometry Nodes instancing with per-instance heading; SIR states shade per-instance live. Trajectories bake to keyframes or export to CSV/JSON, and the core runs headless for parameter sweeps and benchmarks.

Installation

Download the release zip (built into release/, see "Building a Release") and install in Blender 4.2+:

  1. Edit → Preferences → Add-ons → Install from Disk… → select the zip;
  2. Enable "Blender ABMSim".

The zip ships with blender_manifest.toml, so it installs via the Blender 4.2+ extension mechanism — no manual directory copying.

Quick Start

  1. In the 3D Viewport press N → sidebar ABMSim tab.
  2. The top section holds scene basics and controls: Agent Count, Boundary Radius (ignored when a base surface is set), the buttons Setup / Reset / Start / Pause / Step Back / Step (timer-driven, decoupled from the timeline), and live status (agents, t, S/I/R counts, running state).
  3. Feature groups below, each in a collapsible section:
    • Scene Input — base surface, spawn zone, destination zone (goal arrival radius), elevator, force fields (multiple, each with its own parameters);
    • Behavior — speed, turn rate, substeps, dt, seed;
    • Obstacle Avoidance — probe distance, steer gain, agent radius;
    • Boids — enable, neighbor radius, separation/cohesion/alignment weights;
    • SIR Spread — contact radius, infection/recovery probability, initial infected;
    • Trajectory & Export — recording, bake, CSV/JSON export.
  4. Click Setup, then Start. To add obstacles, create a mesh named OBST_... (e.g. OBST_Wall) and re-run Setup.
  5. Boids / SIR: enable in their sections; agents recolor live (blue = S, red = I, green = R).
  6. Trajectories: with recording on, run a while, then Bake Keyframes (playback frame = bake start frame + sim time × bake FPS; re-running overwrites the keyframes) or Export CSV/JSON to Export Path.

Tip: simulation speed is substeps × dt per timer tick (heartbeat fixed at 0.05 s).

Layered 2.5D scenes

Multiple walkable heights at the same (x, y): elevated walkways, underpasses, multi-floor buildings with elevators, ramps, staircases.

  • Base Surface (base_obj): walkable-surface mesh. Multi-floor / bridges / ramps are multiple disconnected islands in ONE object (each island fits its own height). With a base set, boundary_size is ignored and no auto ground is created. Each island must be a single-valued height field — overlapping floors need separate (not vertex-connected) islands, otherwise triangle interpolation picks an arbitrary layer's z.
  • Spawn Zone (spawn_obj, optional): spawn polygon; unset = random inside the base.
  • Destination Zone (destination_obj): OD goal area; setting it auto-enables goal seeking (no separate toggle). Cross-layer goals route via elevators (nearest entrance, greedy). Arrival Radius sits in Scene Input, below the destination.
  • Elevator (lift_obj): shaft mesh — must be upright with its XY footprint reaching into each floor's walkable area, or agents can't enter the cabin. Multiple elevators = multiple islands in one object.
  • Force Fields (multiple): positive strength attracts, negative repels, 0 = obstacle only; "Also an Obstacle" merges it into the world obstacle set.
  • Legacy SURF_ / LIFT_ name prefixes still work as a fallback when no base/lift object is assigned.

Semantics: surfaces are walkable (boundary = wall, z pinned to the surface), OBST_ objects are keep-out solids. Don't model floor plates as OBST_ — the "deep penetration → nearest horizontal exit" logic treats a thin plate as a solid box and pushes agents sideways.

Architecture

Panel/operators → bpy.app.timers (per tick) → World.step() → GN instancing via sim_bridge. The core never imports bpy, so it's unit-testable and runnable headless.

  • sim_core.py — World: numpy (N,3) pos/vel, fixed dt, deterministic RNG, boundary, obstacles, Boids/SIR, 2.5D surfaces/connectors/OD/fields, trajectory record + CSV/JSON export.
  • geometry.py — obstacle triangle snapshots, ray intersection, inside test, nearest horizontal exit; SurfaceField / ConnectorField for the 2.5D layer model.
  • kdtree.py — deterministic pure-Python 2D KDTree + numpy GridNeighbors batch neighbor finder (10k+ Boids/SIR).
  • sim_bridge.py — scene building & per-frame sync: agents = one base object (human-scale 0.5×0.5×1.7 m) instanced via GN "Instance on Points"; foreach_set bulk-writes vertices, state colors, heading; bake_keyframes writes trajectories as keyframes.
  • __init__.py — registration, settings, panels, operators (incl. bake/export), timer heartbeat.
  • scripts/ — sweep.py (headless parameter sweep), bench.py (performance benchmark), build_release.py (release zip).

Roadmap

Milestone-by-milestone plan, current status, and decided technical routes: see PLAN.md.

Parameter Sweep

python scripts/sweep.py --agents 100 --steps 300 --seeds 0-4 \
    --sir-enabled --sir-beta 0.02,0.05,0.1 --out out/

Core-only (no bpy), also runnable in blender -b --python scripts/sweep.py -- .... Writes out/sweep_summary.csv — final S/I/R, infection peak and peak time per seed × β combination (--seeds accepts 0-4 ranges or 1,3,7 lists).

Performance Benchmark

<blender>/5.2/python/bin/python.exe scripts/bench.py

Measured on this machine (Blender 5.2 bundled Python / numpy 2.3.4):

Scenario Time per step
10k random walk + boundary ~0.6 ms
10k Boids (grid neighbors) ~190 ms
10k SIR (contact spread) ~50 ms
20k random walk + boundary ~0.8 ms
1k + 108-triangle obstacles + Boids (10 substeps/frame) ~1.2 s/frame (was ~24 s/frame pre-vectorization)

Tests

python tests/test_sim_core.py                # core only, no Blender (needs numpy)
blender -b --python tests/smoke_test.py      # bpy-side smoke tests

If the system Python is PEP 668-managed, run the core scripts with Blender's bundled Python — replace <blender> with your local Blender install path (same for sweep.py, bench.py, build_release.py).

Building a Release

python scripts/build_release.py

Produces release/blender_abmsim-<version>.zip (version read from blender_manifest.toml; old zips in release/ are cleaned up automatically). The zip contains only the plugin modules (__init__.py, sim_core.py, geometry.py, kdtree.py, sim_bridge.py) plus blender_manifest.toml, so it installs via Install from Disk….

Verify an installed extension — this checks that the extension loads and its operators run:

blender -b -P tests/check_extension.py

After changing code, the installed copy under user_default/blender_abmsim/ does not auto-sync — overwrite it (or reinstall the zip) and restart Blender, since modules are loaded into memory at startup.

Known Limitations

  • Undo doesn't roll back the session — click Setup again after undoing.
  • Baking inserts per-vertex keyframes; with 10k+ agents and many snapshots it gets slow (raise the record interval or cap the steps).
  • Baking then Start again overwrites the keyframes; re-bake after re-running.

About

Agent-Based Model Simulation in Blender

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages