Skip to content

QuestRoomScan 1.0.0 — first stable release

Choose a tag to compare

@arghyasur1991 arghyasur1991 released this 09 Sep 18:27
· 10 commits to main since this release
ca3b69b

Real-time 3D room reconstruction for Meta Quest 3 / 3S in Unity 6 (URP, OpenXR + Meta XR SDK 205). Point the headset around a room and get a textured, persistent, relocatable mesh of it — GPU-only during the scan, with a high-level RoomScanSession facade for games and a full VR debug menu for development.

This is the first stable release. RoomScanSession is API-stable from here; breaking changes bump the major version. The v0.1.0 tag from March predates almost everything below.

Install, pinned:

"com.genesis.roomscan": "https://github.com/arghyasur1991/QuestRoomScan.git#v1.0.0"

Then RoomScan → Setup Scene → Apply Game-Ready Setup. Full docs: README · ALGORITHM · CHANGELOG.

What the package does

Live scan (all on the GPU, zero CPU readback)

  • TSDF volume integration from the Quest depth sensor (256³, RG8 SNorm + RGBA8 colour), with bilateral depth filtering, dilation, normals, adaptive weighting and pruning.
  • GPU Surface Nets mesh extraction via compute shaders, rendered with a single Graphics.RenderPrimitivesIndirect draw. Adaptive per-vertex temporal damping, HC Laplacian smoothing, plane-snap regularization.
  • Two-layer real-time texturing: a triplanar world-space colour cache (~8 mm/texel) from the passthrough RGB camera, with vertex colour as fallback. Triplanar can be disabled to save ~240 MB.
  • Presentation-only live-mesh birth fade and hold-and-morph between extractions, so the mesh grows in rather than popping.
  • FreezeInView / UnfreezeInView to paint regions done; ScanCoverage / ScanProgress metrics for guided UX; exclusion zones around tracked heads; render modes Wireframe / Vertex / Triplanar / Refined / Occlusion / Splat / None.

Scan priors from the Scene API (optional RoomUnderstanding)

  • ConfineScanToContainingRoom: TSDF clipped to the MRUK room the headset is in (outer walls / floor / ceiling expanded 50 cm, then hard-confined). Default off.
  • StampScreenPlanes: MRUK SCREEN (TV) planes written as analytic TSDF slabs so glass depth does not become noise. Default on.

Refinement and persistence

  • Texture refinement: xatlas UV unwrap (native plugin builds on macOS / Windows / Linux hosts), multi-view atlas bake from motion-gated keyframes, Sobel normal maps, UV-preserving post-bake simplification via meshoptimizer.
  • Package-based persistence: each scan is a self-contained pkg_YYYYMMDD_HHMMSS/ (TSDF, triplanar, keyframes, refined mesh + atlas, splat) with a manifest. LoadRefinedOnlyAsync loads mesh + atlas in under a second, no TSDF.
  • OVRSpatialAnchor relocation per package with per-artifact creation matrices, so artifacts made in different sessions line up. Each package also stores the Scene API UUID of the room it was scanned in.
  • RoomSpaceRoot: parent your content under it and saved local coordinates reload into the same physical spot across sessions.

Game integration (RoomScanSession)

  • StartScanAsync → FreezeInView → FinalizeScanAsync → ScanResult (mesh + atlas + package id). LoadAsync(id) / LoadLatestAsync / LoadRefinedOnlyAsync; ListSavedScans / DeleteScanAsync / UnloadActiveScanAsync / ClearAllScansAsync.
  • One serialised permission queue. StartScanAsync requests whatever is missing before bring-up — USE_SCENE (required), then HEADSET_CAMERA / USE_ANCHOR_API (degrade gracefully) — so a bare call always gets its dialogs and no two can race. Request{Scene,Camera,Anchor}PermissionAsync let a host front-load them for UX.
  • Scene-room occupancy that does not trust GetCurrentRoom(): IsHeadsetInsideASceneRoom, IsHeadsetInsideBoundSceneRoom, HeadsetSceneRoomUuid, BoundSceneRoomUuid, TryRebindBoundSceneRoomIfHeadsetMatches, CopyHeadsetRoomWallFaces (visible walls and TVs for pinning world-space UI).
  • Discovery control without surprise Space Setup: WaitUntilRoomReadyAsync, HasSceneRooms, ReloadSceneFromDeviceAsync, RequestSpaceSetupAndReloadAsync.
  • Depth sensor and RGB camera run only during a scan; nothing opens at boot.
  • Scene discovery always completes (RoomReady / IsRoomLoaded signal on zero rooms, denied permission, or a missing SceneLoadedEvent), so a host is never left waiting.

Beyond the mesh

  • Gaussian Splat pipeline: keyframes + PLY point cloud → server training → on-device rendering (gated behind HAS_GAUSSIAN_SPLATTING).
  • Optional YOLO object detection through Unity Inference Engine with GPU NMS (HAS_AI_INFERENCE), projected into 3D and merged with MRUK anchors in a SceneObjectRegistry, with a debug visualizer.
  • Server-side atlas and mesh enhancement clients.

Tooling

  • Game-ready setup wizard: Meta Building Blocks, URP pipeline, build profile, VR UI input pipeline, AndroidManifest checks, shader wiring, xatlas build, and game-proven defaults (extract 8 Hz, keyframes 0.4 m / 20° / 1 s, post-bake simplify 0.5).
  • Two-panel world-space VR debug menu: scan, saved-scan browser with load/delete, refine, Gaussian Splat, tools.

Requirements

Unity 6000.0+, URP 17, AR Foundation 6.1, Meta XR Core SDK + MRUK 205, Quest 3 / 3S. Android permissions USE_SCENE, USE_ANCHOR_API, horizonos.permission.HEADSET_CAMERA.

Used in production by CoasterMania on the Meta Store. MIT licensed.