- Python 90.8%
- Shell 6.4%
- TypeScript 2.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| pi-extension | ||
| .gitignore | ||
| anim.py | ||
| archviz.py | ||
| b3d_world.py | ||
| demo.py | ||
| makieta.py | ||
| map3d.sh | ||
| README.md | ||
| render.png | ||
| test_b3d_world.py | ||
b3d-world (pi-map3d)
Blender + pi plugin: give it GPS coordinates or a place name, get a 3D miniature-world grab around it — satellite terrain, facaded buildings, trees, roads with cars, railways with a train.
- clone:
git clone https://git.cyfrowynomada.com/CyfrowyNomada/pi-map3d.git - upstream (push):
ssh://git@git.cyfrowynomada.com:2222/CyfrowyNomada/pi-map3d.git
-
Terrain: AWS Terrain Tiles (terrarium PNG, no API key) → stitched elevation raster → displaced grid mesh (default 200×200 verts), UV-mapped and textured with stitched ESRI World Imagery satellite tiles (© Esri, Maxar, Earthstar Geographics; imagery zoom auto 15–17).
-
Buildings: OpenStreetMap via Overpass API → footprint polygons extruded to
height/building:levels×3.2 / 5 m default, seated on terrain (sunk 0.5 m), merged into one mesh with cube-projected UVs (roofs/bottoms planar in world XY normalized to the grab footprint — satellite image reused as roof texture; walls tile every 10 m). Per-building facade tints from OSMbuilding:colour/colourtags (named colours +#hex), else deterministic hash; procedural window textures (3 floors per 10 m tile, ground-floor aligned).roof:shapegabled/hipped/pyramidal get ridge geometry (+1.2–3 m rise); multipolygon inner rings become open courtyards (keyhole-bridged ceilings). -
Roads & traffic: OSM
highway=*ways → Chaikin-smoothed spline ribbons, width per road class (motorway 16 m … footway 2.5 m), draped on terrain, clipped to the terrain square; asphalt pads at detected intersections. Cube cars (1.8×4.2×1.5 m) on driveable roads only — lane offset, yaw-aligned to the road, 6-colour palette, 500 cap. -
Railways:
railway=rail/light_rail/subway/tram→ ballast ribbons under road level, plus one train (dark-red loco + 4 wagons) anchored where the longest track passes nearest the grab centre.
Usage
pi command (extension ~/.pi/agent/extensions/map3d.ts): /map3d Turkusowa 3 Poznan or /map3d 52.4309 16.9040 500 — geocodes, builds headless, loads the
result in Blender, publishes a QC render, and hands QC/archviz follow-up to the
agent. Append video (or video:SECONDS, min 4) to also render a tilt-shift
fly-over mp4 — e.g. /map3d Park Solacki Poznan 700 video or
/map3d Rynek Poznan video:20. Pipeline script: map3d.sh (same args),
log: .map3d-last.log.
Fly-over video manually: anim.py <grab.blend> <out.mp4> [seconds] renders
camera-keyframed frames (high sweep, treetop pass, orbit) with per-frame
tilt-shift, then encode with termux ffmpeg:
ffmpeg -y -framerate 24 -i frames/f_%04d.png -c:v libx264 \
-pix_fmt yuv420p -crf 22 -movflags +faststart fly.mp4
Blender addon (installed at ~/.config/blender/5.2/scripts/addons/b3d_world.py
in the Debian proot): enable "B3D World" in Preferences → Add-ons, then
View3D → N-panel → B3D World: latitude, longitude, radius, build.
Script (headless, builds + saves .blend + QC render):
proot-distro login debian -- /opt/blender-native/blender --background \
--factory-startup -P ~/Projects/b3d-world/demo.py -- \
50.0614 19.9366 1200 /sdcard/Documents/out.blend /sdcard/Documents/out.png
Note: render engine must be CYCLES — EEVEE/workbench crash headless in this proot (no GL). demo.py sets Cycles for you.
Tests (offline, no network):
proot-distro login debian -- /opt/blender-native/blender --background \
--factory-startup -P ~/Projects/b3d-world/test_b3d_world.py
Verified
Kraków center (50.0614, 19.9366), r=1200 m: 40k terrain verts, 4830 buildings,
131k building verts, zoom-14 tiles. /sdcard/Documents/b3d_world_krakow.blend
- wide/close QC renders pass (street grid, courtyards, terrain seating, shadows).
Roadmap
Texturesdone: satellite terrain texture + building UVs. Next: wall/ roof texture sets (the UV layout expects 10 m facade tiles).Vegetationdone: OSMnatural=treepoints +forest/woodpolygon scatter → merged low-poly trees (conifer/deciduous, seeded jitter, 12k cap), seated on terrain.
- Roads & traffic: OSM
highway=*ways → Chaikin-smoothed spline ribbons, width per road class (motorway 16 m … footway 2.5 m), draped on terrain with per-class z offsets (intersections don't z-fight), clipped to the terrain square. Cube cars (1.8×4.2×1.5 m) spawned on driveable roads only — lane offset, yaw-aligned, 6-color palette, 500 cap.
- Later: better roof geometry on complex footprints, road junction corners, per-tree variation, more rolling stock.
