On Apple Vision Pro, the Cinema puts the app on a big screen inside a place: so far, a search and rescue tent. Each place is a 360° image rendered in Blender from a Python script in scripts/cinema/, plus an anchors file that says where the app's screen and boards go. This page is for anyone who wants to add a place of their own: a ham shack, a fire lookout, a hilltop.
Open an issue describing the place first, and wait for a maintainer to add the approved label before building it.
<name>_anchors.json: each board's center, size and facing, relative to the camera. The app places its live panels from it, so moving a board in the scene and rendering again moves the panel with it.In Blender, +Y is the center of the image, where the screen usually goes. +X is the viewer's right and Z is up.
The image is flat: one picture, with no depth of its own. That decides what looks right.
| Board | Id | Required | What the app draws |
|---|---|---|---|
| Screen | screen |
Yes | The app's sections, with tabs above. Use screen_anchor(); it's 2.6 m wide by default, in the screen's shape. Nothing is drawn in the image there. |
| Team Favorites | teamStatus |
No | Favorite nodes and the connected radio. The tent uses a 1.35 × 0.9 m whiteboard. |
| Trace route | traceRoute |
No | The latest trace route's card. The tent uses a 1.1 × 0.9 m framed print. |
| Status | nodeStatus |
No | The nodes' status messages, the connected radio's first. CinemaEnvironment titles it for the place and says whether it stands portrait (2:3) or lies landscape (3:2). The tent uses a 0.8 × 1.2 m portrait whiteboard beside the screen. |
A board is a plane passed to anchor("<id>", plane, width, height). The plane's +X is the board's right and its +Z faces the viewer. Paint the board blank in the image (the app covers it), and light it about as bright as the panel will be, so the frame around it matches. The app skips any optional board an environment leaves out.
There are two ways in:
scripts/cinema/sar_tent.py, change its furnish(layout), and call tent_base.render(furnish). The tent shell, lights, windows, branding, dusk forest and the screen on the front wall come with it.build() that makes the room, its furniture, lights and boards, and calls screen_anchor(center, rotation). Then call room_base.render_room(build, "<hdri file>"). room_base.py gives you the camera, the render settings, the anchors file and small helpers (box, plane, cylinder, material, …). For a screen on a side wall, rotation is (math.pi / 2, 0, -side * math.pi / 2), with side 1 for the right wall and -1 for the left.A room of your own starts like this. Blender runs the script directly, so it has to add its own folder to the import path before it can import room_base:
import math
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from room_base import EYE_HEIGHT, box, material, render_room, screen_anchor # noqa: E402
def build():
wall = material("Wall", (0.55, 0.5, 0.42), 0.8)
box("Front", (6, 0.1, 2.6), (0, 3, 1.3), wall)
# ... the other walls, the floor, furniture, lights and boards ...
screen_anchor((0, 2.9, EYE_HEIGHT + 0.2), (math.pi / 2, 0, 0))
render_room(build, "sunset_forest_4k.hdr")
Then:
environment <name> at the end of scripts/cinema/build.sh. Use build.sh --preview for a quick 2048-wide render in scripts/cinema/out/, and build.sh for the full size. The full build writes <name>.heic and <name>_anchors.json into Packages/CinemaContent.CinemaEnvironment in Meshtastic/Helpers/Cinema/CinemaEnvironment.swift with a localized title, imageName set to <name>, and placeholder colors for the backdrop shown if the image can't be loaded.scripts/cinema/README.md.The build fails if the scene has no screen, or if its HDRI isn't in cache/.
What's outside the room, and much of its light, comes from an HDRI: a 360° photo that keeps how bright each part of the scene really is. Poly Haven's are CC0. Add one with an hdri <name> <resolution> line in build.sh, which downloads it to cache/<name>_<resolution>.hdr, and pass that file name to render_room. hdri_rotation turns it (in degrees) to put the sun where you want it, and hdri_strength sets how much light it gives.
4K is enough when the HDRI is only seen through a door or windows, as in the tent. When it's most of the view, as on a hilltop or in a fire lookout's glass cab, use 8K or more, or it will look soft.
An environment whose outside the app may replace, as it replaces the fire lookout's with real terrain, renders with render_room(..., cutout=True): the HDRI still lights the room, but the image is left transparent wherever the camera saw past the room's geometry, glass included. The app then shows a sky sphere behind it, rendered from an HDRI alone by sky.py (a sky <name> <hdri file> <rotation> <strength> line in build.sh), and CinemaEnvironment says which sky images the environment has and where their sun is.
scripts/cinema/README.md. No manufacturer logos or other marks..blend files or rendered PNGs; only the HEIC and its anchors ship.Build for the visionOS 26.5 simulator and launch with --meshtastic-open-cinema. The app opens the Cinema a few seconds after launch. Pick your place under Environment on the control panel, then check that:
Then try it on a headset if you have one.