# VoxelForge local web viewer
This folder contains a Python standard-library server, a `.vfmesh` to GLB converter, and a Three.js page for viewing exported VoxelForge worlds. The converter accepts `VFMSH001` and `VFMSH002` files, preserves vertex normals and tile/triangle counts, and writes metre-scale GLB geometry. It rotates VoxelForge's Z-up coordinates to glTF's Y-up coordinates.
Three.js and its GLTF loader are loaded from jsDelivr at the pinned version **0.160.0**, so the browser needs internet access the first time it loads the page. Python and the viewer server need no package installs.
## Convert existing meshes
From this directory, convert one or more existing exports:
```sh
python3 convert.py \
../../../Saved/Linux/l32/capture-sw-far-v20-settled-surface.vfmesh \
../../../Saved/Linux/l32/fi-floor-v20-lod4-focus.vfmesh \
../../../Saved/Linux/linux23/capture-fi-mouth.vfmesh
```
The GLBs go into `meshes/` by default. To use another output folder, add `--out-dir /path/to/glbs`. The converter reads the source mesh directly and does not regenerate a world.
## Refresh the owner world previews
From the repository root, run:
```sh
python3 Standalone/Tools/webviewer/export_world.py
```
This uses the existing `Saved/Linux/l101/bin/VoxelForgeCoreHeadless-l101-clang` exporter to regenerate LOD0–2 arrival views for SW, FI, TN, and VS, plus a FI passage view. It applies the CPU affinity and memory limits used by the capture runners, writes the GLBs into `Standalone/Tools/webviewer/meshes/`, and keeps per-view logs and a size/count summary in `Saved/Linux/w2/`. To use another compatible headless binary, pass `--headless-binary /path/to/VoxelForgeCoreHeadless-*`.
## Start and view
```sh
cd Standalone/Tools/webviewer
python3 server.py
```
Open in a WebGL-capable browser on the **same machine**. The server binds to `127.0.0.1` by default. To serve GLBs from a different local folder:
```sh
python3 server.py --mesh-dir /path/to/glbs --port 8000
```
For a phone connected over Tailscale, bind to the viewer machine's Tailscale address with `--host ` and open `http://:8000/` on the phone. Keep the browser online so it can load the pinned Three.js modules from jsDelivr.
On Windows with Python 3, run `py -3 server.py --mesh-dir .\meshes` from this folder and open `http://127.0.0.1:8000/` on that Windows machine.
## Controls
- Click the world to capture the mouse, then use **W/A/S/D** and mouse movement to fly and look. **Space** rises; **C** or **Ctrl** descends. **Esc** releases the mouse.
- On touch screens, drag the left pad to move and the right pad to look. **Touch pads** can show or hide the pads; this also makes them available in headset browsers that do not report a coarse pointer.
- Adjust flight speed with the slider. Toggle wireframe or normal-colour shading in the panel.
- Choose mesh A and an optional mesh B. Click **Show B** or press **B** to switch between them. **Fit view** frames the active mesh.
- The overlay shows the active mesh's triangles and tiles and the camera position in metres.
The viewer uses normal-based lighting and distance fog. It applies a simple viewer material; VFMSH002 resource material IDs are read and skipped by the converter.