Cinema Environments

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.

How it works

In Blender, +Y is the center of the image, where the screen usually goes. +X is the viewer's right and Z is up.

What the image can and can't do

The image is flat: one picture, with no depth of its own. That decides what looks right.

Boards

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.

Building a place

There are two ways in:

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:

  1. Add 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.
  2. Add a case to 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.
  3. List every asset's source in scripts/cinema/README.md.

The build fails if the scene has no screen, or if its HDRI isn't in cache/.

The sky and the light: HDRIs

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.

Rules for assets

Trying it

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.