Skip to content

Stand Alone Mode — E-Learning Lab

Stand Alone Mode is an optional authoring workflow that replaces Vizard Inspector with Blender and targets WebXR / standalone VR headsets (e.g. Meta Quest) instead of a tethered Vizard runtime. All existing Vizard-based workflows are completely unchanged when the flag is False.


Enabling Stand Alone Mode

Open global_config/globalConfig.py and set:

STAND_ALONE_MODE = True

Set it back to False at any time to return to the standard Vizard Inspector workflow.


What Changes When Enabled

1. Blender replaces Vizard Inspector

Any action that would normally open Vizard Inspector now opens Blender instead (note: with BLENDER_EMBEDDED = True (the default) Blender will open embedded in E-Learning Lab next to the main Preview window):

Action Normal mode Stand Alone mode
Double-click environment Opens Inspector Opens in Blender
Double-click scene object Opens Inspector Opens in Blender
Double-click avatar Opens Inspector Opens in Blender
Right-click → Edit Model Opens Inspector Opens in Blender
Preview window Edit button Opens Inspector Opens in Blender

2. .glb / .gltf files are kept as primary assets

When a .glb or .gltf file is dropped into the Environments, Objects, or Avatars asset bins:

  • The .glb/.gltf is kept as the primary asset file.
  • A temporary .osgb is created only to capture the thumbnail screenshot.
  • The .osgb is automatically deleted ~4 seconds after the thumbnail is saved.

In normal mode the original non-OSGB file is deleted after conversion. In Stand Alone mode the original is always preserved.

3. _tag node convention for interactive objects

The Scene Objects panel (the checkboxes for Grabbable, Animate, Visible, etc.) normally scans all group nodes in the loaded Vizard scene. In Stand Alone mode it filters to only nodes whose name ends with _tag. This will also now carry over to non-stand alone mode, so scenes edited in Blender will work in the non-stand alone workflow as well.

When authoring a model in Blender, name any object you want to be interactive with a _tag suffix:

Chair_tag        ← will appear in the panel as "Chair_tag", can be marked Grabbable
Lever_tag        ← will appear as "Lever_tag", can be marked Animate
BackgroundWall   ← will NOT appear (no _tag suffix)

Can then check "Grabbable", "Hidden" or "Animate" in the E-Learning Lab GUI


Authoring Workflow

Step 1 — Enable the flag

# global_config/globalConfig.py
STAND_ALONE_MODE = True

Step 2 — Prepare your .glb models in Blender

  • Drag a .glb environment to the preview window
  • Click "Edit" to edit your model
  • Drag in additional objects directly to the embedded Blender window.
  • Name any interactive objects with a _tag suffix (e.g. Door_tag, Button_tag).
  • To set a starting point, drag in the START_POINT_SINGLE_start.glb object from the objects bin and then use Blender's translate and rotate tools to place where you want the user to start.

  • Export as .glb (File → Export → glTF 2.0, format = GLB).

Step 3 — Import models into the E-Learning Lab

Drag .glb files from Windows Explorer onto the Environments or Objects asset bins. The app will:
1. Copy the file to Assets/Environments/ (or Assets/Objects/).
2. Capture a thumbnail (via a temporary .osgb — deleted automatically).
3. Display the model in the gallery with its thumbnail.

Step 4 — Build your sequence

Drag environments from the Environments panel, 360 Media, Videos, or Images, slideshows onto either:
- The Scenes list (left panel) — adds as a new slide, or replaces the currently-selected blank slide.
- The Preview image (center area) — same behavior.

The scene appears in the list and loads in the Vizard preview window. You can then:
- Add Audio, Prompts, Images, Video, or 3d object files to the scene as normal.
- Right-click a scene → Edit in Blender to open the .glb for further editing.
- Use the Scene Objects panel to mark _tag nodes as Grabbable, Animate, or Visible.

Step 5 — Run in WebXR

Click "Run Session" and Choose "WebXR"

The server opens the PC browser automatically at https://localhost:8765. See Running in WebXR below for connecting headsets and other devices.


Running in WebXR

Prerequisites (on the PC running the server)

Requirement Notes
Python 3.x 3.14+ tested
websockets package pip install websockets
cryptography package pip install cryptography — needed for HTTPS/WSS
cloudflare (optional) Only for single-user internet access; not needed for LAN
Stand Alone device on the same Wi-Fi Needed for LAN / multi-user access
Blender (or a 3D editor for .glb models) Blender has the best integrated support — download Blender

First run only: When the HTTPS certificate is generated, Windows will show a UAC
security dialog asking you to allow certutil to add a trusted root certificate.
You must approve this for the PC browser to trust the connection without warnings.
This is a one-time step — the certificate is cached in %TEMP%\webxr_ssl\.

What the server prints at startup

═══════════════════════════════════════════════════
  E-Learning Lab WebXR Server
  Project : MyProjectName
  Local   : https://localhost:8765/
  LAN     : https://192.168.0.100:8765/
  WS sync : wss://192.168.0.100:8766
═══════════════════════════════════════════════════

The LAN URL is what a headset on the same Wi-Fi needs. Note it down.

Connecting devices

Where you're accessing from URL to use VR works? Multi-user sync?
Same PC https://localhost:8765 Yes Yes
Same Wi-Fi (headset, phone, tablet) LAN URL, e.g. https://192.168.x.x:8765 Yes Yes
Any network (Cloudflare tunnel) https://xxxxx.trycloudflare.com Yes No — single user

Same Wi-Fi (LAN) — supports multi-user

The headset must be on the same Wi-Fi network as the PC running the server.

  1. Put on the headset.
  2. Example for Meta Quest, open Meta Browser (the built-in browser, not a sideloaded one).
  3. Navigate to the LAN URL printed at server startup, e.g.:
https://192.168.0.100:8765
  1. Meta Browser will show a certificate warning:

    "Your connection is not private" / ERR_CERT_AUTHORITY_INVALID

This is expected — the certificate is self-signed. Tap Advanced and then
"Proceed to 192.168.0.100 (unsafe)" to bypass it. The bypass is remembered for
subsequent visits until the server IP changes.

  1. The E-Learning Lab page should load. Tap Enter VR (note: larger scenes can take a
    few minutes to load in VR mode — around 1 1/2 minutes for a 1 GB scene on the test machine).

Note: The first time you connect, the page may not load immediately after tapping
"Proceed." If you see a blank page or it times out, do a full page reload (reload icon
in Meta Browser). Subsequent connections to the same server (same cert) should be faster.

Any network — Cloudflare tunnel (single-user only)

The server binds to all network interfaces and automatically launches a Cloudflare HTTPS tunnel if cloudflared is installed. The tunnel URL appears in the console a few seconds after startup — open it in the Meta Browser and tap Enter VR.

One-time install (Windows 11 — winget is built in):

winget install cloudflare.cloudflared --accept-package-agreements --accept-source-agreements

After that, just run the server as normal. No second terminal, no account, no sign-in. If cloudflared is not installed the server still works locally — it just prints the install hint instead.

The tunnel URL changes each session (free tier limitation). The tunnel only exposes the content port (8765), not the WebSocket sync port (8766), so it supports one viewer at a time — use the LAN URL for multi-user.

Controls

In the headset

Input Action
Left controller Y button Next scene
Left controller X button Previous scene
Trigger near a _tag object Grab / release object
Left thumbstick Move forward / back / strafe (relative to head direction)
Right thumbstick left / right Snap-turn 45° left / right (turns in place)
Timer transition Auto-advances after configured duration

Desktop / phone / tablet (no headset required)

Input Action
W / A / S / D Fly camera
Mouse drag Look around
Touch drag (one finger) Look around (phones and tablets)
V or Next ▶ button Next scene
C or ◀ Prev button Previous scene

What the WebXR runner reads from your project

  • 3D environment for each scene
  • 360 video for scenes named with a 360 suffix (see below)
  • 360 image for scenes named with a 360 suffix
  • Standard videos and images (mono or stereo)
  • Powerpoint slideshows
  • Scene order and transition type (Key Press / Timer / Release Object)
  • Grabbable, animate, visible object lists per scene
  • Per-scene audio (.wav, .mp3, .ogg)
  • Whole-sequence background audio (set via right-click on an audio file in the Audio panel → Set as Whole Sequence Audio)
  • Session audio loop setting
  • Immersive-augmented reality

360 media scenes

Scenes whose names end with a recognized suffix are rendered as immersive 360 spheres instead of (or alongside) a .glb model. The media file is looked up in the Videos/ subfolder first, then the project root as a fallback.

Scene name suffix Format Description
_360_stereo Top-Bottom stereo Top half → left eye, bottom half → right eye
_180_stereo Side-by-Side stereo Left half → left eye, right half → right eye
_360 Mono equirectangular Single sphere, both eyes

Supported file formats:

Type Extensions Notes
Video .mp4, .webm Browser-native only — .avi, .mkv, .mov are not supported and will be skipped
Image .jpg, .jpeg, .png, .webp Always supported

A 360 scene does not require a .glb file — the .osgb placeholder that Vizard creates is ignored by the WebXR runner. Scenes with no .glb and no recognised 360 media are skipped with a SKIP message in the console.

On desktop, stereo scenes show the left-eye view. In the headset, each eye receives the correct half of the image automatically via WebXR layer masking.

Augmented Reality/Passthrough mode

Right click on a scene to set in AR Mode

This will then use the passthrough camera on any stand alone headset, or a phone or tablet to use augmented reality


Biopac

The E-Learning Lab can connect to a Biopac AcqKnowledge system to record physiological data (heart rate, GSR, EEG, etc.) in sync with WebXR sessions.

Check "Biopac" under the "Advanced Settings"

When a WebXR session is started with Biopac enabled, a companion script launches automatically in a separate window. See Session Synchronization below for how the companion controls session timing.

Note: Biopac recording works alongside Data Saving (see below). Both can be active at the same time.


Saving Data

The E-Learning Lab can save a timestamped CSV log for every WebXR session without requiring Biopac hardware.

Check "Data Saving" under the "Advanced Settings"

When a WebXR session starts with Data Saving, a companion script launches automatically. It creates a CSV file with the session date, start time, trial label, and any flag events recorded during the session. The CSV is saved to the project's data folder and can be opened in Excel or any data analysis tool.

There is also the option to set a label that will go into the data in the biopac_webxr_companion.py script on line 59
yield sightlab.startTrial(trialLabel="A")

See Session Synchronization below for how the companion controls session timing.


Session Synchronization

When Data Saving or Biopac is enabled, a companion script launches in a separate window on the instructor machine. It controls when the session starts and ends so that all participants and the data recording are synchronized.

Flow

  1. Waiting screen — As soon as the companion launches, all connected browser clients (Quest headsets, phones, tablets) show a black "Loading session…" screen. Users should click Enter VR from this screen so the headset enters VR mode while scenes download in the background.
  2. Ready — Once scenes have finished downloading, the screen updates to "✓ All scenes ready — Waiting for instructor to start". The instructor can now press Space.
  3. Start — The instructor presses Spacebar in the companion window (that window must be in focus). All clients simultaneously clear the waiting screen, the recording trial begins, and AcqKnowledge starts capturing (if Biopac is enabled).
  4. End — The instructor presses Spacebar again. All clients fade to a black "Session ended" screen, the trial ends, and the data file is saved.

Important: The companion window must be in focus (clicked/active) on the instructor machine for spacebar keypresses to register. If the E-Learning Lab or another window is in front, the keypress will be ignored.

T key — Sync flag / custom event

While a session is running, pressing T in the companion window inserts a synchronization marker:

  • Writes a "T key pressed" event to the CSV data file
  • If Biopac is active, sends a Sync Event marker to AcqKnowledge at that exact moment

This is useful as a secondary synchronization method. For example, if a participant takes noticeably longer than others to load into a scene (VR scenes can take 1–2 minutes to become fully interactive after the session starts), the instructor can press T at the moment that participant is visibly ready — giving a precise timestamp to align against in post-processing.

Scene load times in VR

Even after the session starts and the waiting screen clears, VR users may experience a short delay (typically 1–2 minutes on large sessions) before scenes are fully interactive. This is normal — the 3D assets are large files and continue streaming in the background. The T key flag can be used to mark the exact moment a participant is ready if precise per-user alignment is needed.


Converting Projects to WebXR

An existing Vizard-based project can be converted for WebXR in one step. Right-click the project in the Projects panel and choose Convert to WebXR.

This will:

  1. Duplicate the project as <name>_WebXR — the original is left completely untouched
  2. Convert every .osgb scene file to .glb in the copy
  3. Convert any browser-incompatible videos (.avi, .mkv, .mov) to .mp4 if FFmpeg is available
  4. Remove the original .osgb and old video files from the copy to save space

A progress bar shows each file as it converts. When done, the _WebXR project appears in the Projects panel and is ready to run with WebXR.

Note: Scenes that contain 3D text labels (osgText::Text3D) cannot be converted automatically — remove the text labels in Vizard first, then re-export.


Converting Models and Videos

Convert to glb (individual assets)

Right-click any environment or object in the asset gallery and choose Convert to glb. This converts the asset to .glb using the built-in converter and saves it alongside the original as <name>_glb. The thumbnail is copied automatically. Supported source formats: .osgb, .fbx, .obj, .dae (and .glb/.gltf are simply copied).

This is useful when you want to make a single asset available in Stand Alone / WebXR mode without converting the whole project.

Video conversion

Browser playback requires .mp4 or .webm. If FFmpeg is installed (or placed in the utils/ folder), the Convert to WebXR project action converts incompatible videos automatically. For manual conversion:

ffmpeg -i input.avi -c:v libx264 -crf 23 -preset fast -movflags +faststart output.mp4

Filtering Assets

The Objects and Avatars galleries have a Type filter dropdown in the top bar. It automatically populates with the file extensions present in the gallery (e.g. .glb, .osgb, .fbx) and lets you show only one type at a time.

In Stand Alone mode this is particularly handy if you have both .osgb and .glb versions of assets in the gallery — select .glb from the filter to see only the WebXR-ready files.


Presentation Generator

The Presentation Generator Wizard builds a complete multi-scene lesson from a topic and a set of options — no manual scene creation needed.

When stand alone mode is active it will save the slides as .glb files instead of .osgb


Multi-User

One or more VR headsets (or browsers) can view the same E-Learning presentation simultaneously. All connected clients share the same scene index in real time — navigating on any client advances all others.

All devices must be on the same Wi-Fi network as the PC and use the LAN URL — see Connecting devices above. The Cloudflare tunnel is single-user only (see Limitations below).

What syncs

  • Scene index — every client jumps to the same scene in real time
  • Release Object transitions — server-authoritative; whichever client releases the
    object, all clients advance together (no double-advancing)
  • Session state — waiting / started / stopped overlay shown on all clients
  • Video play/pause
  • Audio state

Connection flow

  1. Client opens the page → WebSocket connects to port 8766
  2. Server immediately sends a state_snapshot — client jumps to the current scene
  3. From then on, any scene change from any client broadcasts to all others in ~50–100 ms
  4. If the WS drops, the client auto-reconnects within 3 seconds and re-syncs
  5. If running with INSTRUCTOR_LED then only the Instructor can initiate scene changes

Session control modes

Set in globalConfig.py:

  • INSTRUCTOR_LED — only the instructor tab can navigate; student headsets follow
  • ALL_CLIENT_CONTROL — any headset can navigate (current behavior)

Add ?role=instructor to the network address to make a client the instructor.

Troubleshooting

Symptom Likely cause Fix
PC browser shows ERR_CONNECTION_RESET Server not running or still starting Wait a moment (or a few minutes), refresh
PC browser shows cert warning certutil step failed or was denied Run certutil -addstore -user Root <cert.pem> manually
Quest 3 shows ERR_CERT_AUTHORITY_INVALID Expected on first connect Tap Advanced → Proceed, then reload the page
Quest 3 shows "WebXR Unavailable" HTTP (not HTTPS) URL used Use the https:// LAN URL — plain HTTP can't use WebXR
Quest 3 controller changes slides locally but PC doesn't follow WS connection dropped Check WS port 8766 is open in Windows Firewall; wait for auto-reconnect
ImportError: No module named 'websockets' Package not installed pip install websockets
ImportError: No module named 'cryptography' Package not installed pip install cryptography
Firewall prompt appeared but rules weren't added netsh needs admin rights Approve the UAC dialog for firewall rule creation

Limitations & Planned Next Steps

Current limitations

  • Cloudflare tunnel — single-user only — The tunnel only exposes port 8765 (HTTP/WebXR content); port 8766 (WebSocket sync) is not reachable through it, so remote participants get a single-user view. For multi-user, all devices must be on the same LAN as the PC.
  • Self-signed certificate on the headset — Meta Browser requires a manual bypass each time the server IP changes (different network or new DHCP address). Once bypassed, it is remembered for subsequent visits to the same address. The PC trusts the certificate automatically (via certutil).
  • 360 video formats — Only .mp4 and .webm play in browsers. Existing .avi and .mkv files (e.g. from older Vizard projects) must be converted to .mp4 (e.g. with ffmpeg) for WebXR playback. The Vizard runtime is unaffected and continues to use the original formats.
  • .osgb scenes — Standard (non-Stand Alone) scenes in .osgb format are not loadable by Three.js and will be skipped by the WebXR runner. Only .glb/.gltf scenes and recognised 360 media are served.
  • Quiz UI — Not yet implemented in the WebXR runner.
  • AI Agents — Not yet implemented
  • Screencasting — Not yet implemented
  • Data Saving — Limited and currently can synchronize with biopac, add labels, time stamp and flags (no eye tracking or position data)

Planned next steps

  • Route WS through port 8765 (HTTP Upgrade) — Currently the WS sync server runs on a separate port 8766 that Cloudflare can't proxy. Sharing port 8765 via the HTTP Upgrade: websocket handshake would enable multi-user sync through the Cloudflare tunnel for remote participants, and would also fix Cloudflare's 100 s idle timeout on the separate WS path.
  • Auto-install missing packages — If websockets or cryptography aren't installed, the server currently crashes with an ImportError. A pip bootstrap on first run would self-install them.
  • User presence — Show how many users are connected in the HUD; optionally render a simple avatar per remote user at their approximate head position.
  • AR mode multi-user — Passthrough works for single-user; multi-user AR hasn't been tested and may need additional anchor sync.
  • mDNS/Bonjour discovery — Auto-discover the server on the LAN so users never have to type an IP address (removes the "note down the LAN URL" step).