Repository navigation
Releases: ReactVision/virocore
Release list
v3.0.3
v3.0.3
A patch release for Meta Quest, iOS and the physics and recording paths. The native build ships inside @reactvision/react-viro 3.0.3. It links Spatial 1.3.1, which pins platform requests to the database's region.
Meta Quest
- A scene opened after another AR scene gets the room's planes. The session published each plane only to the scene attached when it was first found, so a plane scene opened from an AR scene never fired
onAnchorFound. A new scene now receives every plane found so far. - The boundary is hidden while passthrough is on, through
XR_META_boundary_visibility, and comes back for a fully virtual scene. The app has to declarecom.oculus.permission.BOUNDARY_VISIBILITY; the viro Expo plugin does.
iOS
- A session-only app no longer asks for location when it opens an AR scene. Core Location starts only when
RVApiKeyandRVProjectIdare set, as before 3.0.2. An anchor hosted on a session records no GPS fix. - Camera texture recordings carry audio. The microphone is live only while recording.
Android
startRecordingwithoutRECORD_AUDIOfails through its callback instead of leaving the caller waiting forever, and camera-open and device errors reach it too.
Everywhere
onCollisionfires against the AR world mesh, with the mesh'scollisionTag. Ray and hit tests skip the mesh as before.- A session can carry a function region (
setSession(..., functionRegion)on Android,+setStudioSessionBaseUrl:accessToken:clientTag:functionRegion:on iOS), which the cloud-anchor providers send asx-region. The three-argument forms still work. VROGeospatial.his one header again: both copies call the earth-tracking stateEnabled. Nothing changes at runtime.
What's Changed
Other Changes
- Correct the docs the MCP servers index by @doranteseduardo in #402
- iOS: start the Core Location feed on a key only by @PetkoKuzmanov in #403
- Carry a session's function region to the cloud-anchor providers by @PetkoKuzmanov in #404
- Fix/quest plane replay by @PetkoKuzmanov in #405
- Settle every startRecording path, and record audio on iOS by @benmotanoti in #406
- Report collisions against the world mesh by @benmotanoti in #407
- Make the two VROGeospatial.h copies identical by @benmotanoti in #408
- Release 3.0.3 by @doranteseduardo in #409
Full Changelog: v3.0.2...v3.0.3
v3.0.2
ViroCore 3.0.2
Web renderer fixes, Quest input and capture, and cloud anchors and co-location that work with a signed-in user instead of an API key. The web build ships inside @reactvision/viro-web-renderer 1.0.1, and the native build inside @reactvision/react-viro 3.0.2. It links Spatial 1.3.0 on every platform, visionOS included.
Web
- The heap grows. It was fixed at 256 MB, and a single generated or photogrammetry GLB of 30 to 40 MB crossed it once decoded.
abort("OOM")is permanent in Emscripten, so the whole renderer died rather than the one model. The heap now grows to 2 GB. A failure past that still aborts, andviro-web-rendererreports it throughonAbort. - Taps are no longer mirrored vertically. Y was flipped twice on the way to
unproject. - AR holds the last pose through a tracking dropout instead of snapping the scene to identity rotation. Limited applies the new rotation and holds the position.
- Source textures (
viroCreateSourceTexture,viroUpdateTextureFromSource) are filled by the GPU straight from a<video>,<canvas>,ImageBitmaporVideoFrame. The AR camera feed uses them instead of a per-frame readback and upload.
Meta Quest
- Gaze works on every Quest. Where there is no eye tracker it falls back to the head pose. The head-pose hit drives hover and the reticle only, so it never takes fuse, pinch, rotate or drag away from the controller in use.
- Screen capture.
ViroViewOpenXRnow creates aViroMediaRecorder, sized to one eye's swapchain. A passthrough capture holds the virtual content on transparency, since the OS composites the room underneath. - AR hit test against the planes the session tracks, reachable through
ViroViewOpenXR.performARHitTestWithRayfrom the camera along a ray or from an origin to a destination. - Two drags at once, one per hand. Each hand drags its own node and releases it independently. A hand can't grab a node the other one holds, and its own
onMoveand fuse stay on what it points at. Single-pointer platforms behave as before. - Controllers vibrate on click, on the hand that pressed.
- The left-palm menu pinch with hand tracking reaches the app as the Menu button does. A pinch made during a system gesture no longer also counts as a select.
Cloud anchors and co-location
- A signed-in session authenticates cloud anchors and the co-location channel (
VROReactVisionAuth,com.viro.core.ReactVisionAuth). Each request reads its credential when it is sent, and a session wins over a key. On iOS a session that arrives after the AR scene mounted is picked up. With neither a session nor a key, a request fails right away with "Not signed in". - Cancelling works.
rvCancelOperations()(ARScene.rvCancelOperations()on Android) cancels pending ReactVision hosts and resolves, which reportErrorCancelledonce, and closes an open scan. An upload already in flight can still leave an anchor, which expires with its TTL. - Scan status reports its points.
triangulatedPointsandminTriangulatedPointsshow how far a scan is from the host floor. - A scan now needs 300 triangulated points to host, up from 40. This applies to key-only apps too. Maps of 96 and 211 points used to host, and then no other device could resolve against them.
All platforms
- Loading a glTF no longer copies the model. It moves into a shared pointer and images decode in place, which lowers peak memory on large files.
VROPlatformLoadImageWithBufferedDatatakes its buffer byconst &. - Remounting a navigator with physics no longer crashes (
btDbvtBroadphase::destroyProxyon teardown). - iOS: text no longer comes back garbled after a navigator remounts. The old view's GL cleanup ran in the new view's context.
- Android: remounting a navigator no longer crashes (
AAssetManager_openon a null manager in the new renderer's first frame). - Quest: hit tests, screenshots and recordings work. A hit test from JS crashed on the OpenXR thread, a screenshot aborted on an assertion, and every recording after the first came out black.
- Quest: the laser follows a dragged object, and a drag whose node leaves the scene (a scene change mid-drag) ends instead of crashing.
- iOS: a gesture in flight during AR teardown no longer crashes (
EXC_BAD_ACCESSinhandleLongPress:).
What's Changed
Other Changes
- Release 3.0.2 — web player fixes by @doranteseduardo in #390
- iOS: stop gesture actions reaching a torn-down VROViewAR by @stephen-gobin in #387
- Quest: mirada, captura de pantalla, hit test AR y háptica by @benmotanoti in #388
- Quest: route left-palm menu pinch to BackButton with hand tracking by @oliedis in #389
- Authenticate cloud anchors and co-location with a user session by @PetkoKuzmanov in #394
- 3.0.2: fold unreleased work into the release by @doranteseduardo in #395
- Input: one drag per hand on Quest (two simultaneous drags) by @oliedis in #393
- Move the two-hand drag entry into 3.0.2 by @doranteseduardo in #396
- Physics and GL teardown fixes on navigator remount by @doranteseduardo in #397
- Android: reference-count the platform env per renderer by @doranteseduardo in #398
- Quest fixes from device testing by @doranteseduardo in #399
- Release 3.0.2 by @doranteseduardo in #400
- Merge main into develop after 3.0.2 by @doranteseduardo in #401
New Contributors
- @stephen-gobin made their first contribution in #387
- @oliedis made their first contribution in #389
Full Changelog: v3.0.1...v3.0.2
v3.0.1
Release Notes
v3.0.1
Four fixes to shared coordinate frames on Meta Quest, all of them in the same call path, each one hidden behind the last. The renderer ships inside @reactvision/react-viro as prebuilt binaries; upgrade that package to 3.0.1 to get these.
Fixed
-
Four OpenXR extensions are now requested at instance creation.
XR_FB_spatial_entity_storage,XR_FB_spatial_entity_sharing,XR_META_spatial_entity_sharingandXR_META_spatial_entity_group_sharing.xrGetInstanceProcAddrrefuses a function whose extension was not enabled, soxrShareSpacesMETAnever loaded, the capability flag stayed false, and every shared-frame call reported the feature unavailable on hardware that supports it.The last two are different extensions and the distinction is easy to miss:
xrShareSpacesMETAis declared byXR_META_spatial_entity_sharing, whileXR_META_spatial_entity_group_sharingonly adds the group-uuid recipient and filter. Enabling the group one alone loads no function and reports "XR_META_spatial_entity_group_sharing not present" — naming the extension that is present rather than the one that is not.static_asserts now fail the build if any of the four leaves the list. -
The event loop forwards
XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FBandXR_TYPE_EVENT_DATA_SHARE_SPACES_COMPLETE_META.onSpatialEventhad handlers for both;xrPollEvent's switch forwarded three of the five types it handles and dropped these two intodefault. Every spatial-entity call is asynchronous and answers through an event, so an event that is not forwarded is a call that never completes — no error, no timeout, just a callback that is never invoked. On device the anchor was created successfully and nothing was ever told about it. -
The group filter chains on
XrSpaceQueryInfoFB::next, not::filter.filtertakes the FB filter types — uuid, component — and the runtime rejects an unrecognised one withXR_ERROR_VALIDATION_FAILURE. The group filter is an extension struct and chains like every other META addition to an FB call.
Verified on a Quest 3: xrCreateSpatialAnchorFB → STORABLE and SHARABLE → xrShareSpacesMETA round-trips, and a group query recovers the frame.
Requires horizonos.permission.IMPORT_EXPORT_IOT_MAP_DATA in the app manifest, which @reactvision/react-viro 3.0.1's config plugin adds. Without it the Meta runtime hides the group-sharing extension from enumeration rather than failing the call, so the headset appears not to support shared anchors.
What's Changed
Other Changes
- Release 3.0.1 — renderer by @doranteseduardo in #385
Full Changelog: v3.0.0...v3.0.1
What's Changed
Other Changes
- Release 3.0.1 — renderer by @doranteseduardo in #385
- Release notes carry the current version, the changelog the history by @doranteseduardo in #386
Full Changelog: v3.0.0...v3.0.1
v3.0.0
Release Notes
v3.0.0
One renderer now covers five targets: OpenGL ES on Android, Metal on iOS, Metal into a CompositorServices immersive space on Apple Vision Pro, OpenXR on Meta Quest, and WebGL2 through WebAssembly on the web.
Behind ViroReact 3.0.0's headline capabilities, the engine work is the world mesh and scan pipeline that VPS is built on, the shared coordinate frames co-location needs, and mixed reality on Quest.
Added
- World mesh and room-scale scanning. The depth-derived mesh that VPS snapshots and reattaches — accumulated from ARKit's LiDAR and ARCore's Depth API, serialised into a scan's own location frame, and restored against a resolved one for occlusion and physics.
VROARSceneowns the mesh, its configuration and its lifetime. - The web target. The WebAssembly build under
wasm/: the C API that@reactvision/viro-web-rendererdrives, the scene bindings, and the renderer work behind them. - Co-location.
VROColocationSessionas the platform-neutral holder,Colocation_JNIon Android,VROColocationBridgefor iOS and visionOS, and shared spatial anchors on Quest throughxrShareSpacesMETA. - Quest. Plane detection through
XR_EXT_plane_detection, passthrough compositing, per-ray drag ownership and the input controller work behind mixed reality. - Scan and world-mesh state are readable from the bridge.
rvGetScanStatusJson()andrvGetScanDiagnosticsJson()onVROARSessionreport how a scan in progress is doing and why the last one ended as it did;nativeRvGetWorldMeshStatsdoes the same for the world mesh over JNI. The JSON shape is defined once onVROARSessionrather than restated in each bridge, so the two platforms cannot drift. All three are read-only snapshots taken on the render thread and are cheap enough to poll.
Changed
- Web text renders in Roboto. The preloaded typeface is now Apache 2.0 licensed and matches the face already used on Android and Quest, so the three platforms agree. The preloaded data drops from 2.3 MB to 389 KB.
- Android shader assets are generated at build time.
android/shaders.gradleregeneratessharedCode/src/main/assets/*.glslfromViroRenderer/duringpreBuild, keeping the shipped copies in step with the sources automatically. The generated files stay committed, so a build after a shader change will modify the working tree. - iOS pods build at deployment target 15.0. A
post_installhook rewrites every pod target, as Xcode 26 and later reject anything lower.
Fixed
- Compound physics shapes distribute mass by child volume, and a compound built from given parts no longer drifts on every physics update.
- Alpha cutoff binds only for
Masktransparency mode; every other mode fades continuously instead of vanishing at half alpha. - Vertex colours and glTF
doubleSidedare honoured. - A
FixedToPlanedrag no longer snaps to the aim point on float noise, and aiming square at the plane no longer produces a NaN world transform. - Calls made before the AR session exists are queued and flushed in order rather than dropped without a callback.
- On visionOS the renderer archive now carries the ReactVisionCCA slices it references, so an application no longer fails to link on symbols it never used.
What's Changed
Other Changes
- Release 3.0.0 — renderer by @doranteseduardo in #384
Full Changelog: v2.58.1...v3.0.0
v2.58.1
v2.58.0
v2.58.0
Highlights
AR Session Recording
VROARSessiongains an optional local recording surface (startRecording/stopRecording/getRecordingStatus) —video.mp4+session.jsonl(raw IMU + ground-truth pose), for offline analysis/replay viatinyvio. iOS (AVAssetWriter) and Android (MediaCodec/MediaMuxer) implementations, both with sorted, race-free sidecar/video finalization.
Fixes
- glTF: sparse accessors and non-indexed (draw-arrays) primitives no longer fail to load (VIRO-3664).
Notes
- Pairs with
@reactvision/react-viro2.58.0.
See CHANGELOG.md for full detail.
What's Changed
Other Changes
- v2.58.0 by @doranteseduardo in #361
Full Changelog: v2.57.5...v2.58.0
v2.57.5
What's Changed
Other Changes
- v2.57.5 by @doranteseduardo in #353
Full Changelog: v2.57.3...v2.57.5
What's Changed
Other Changes
- Release/2.57.5 by @doranteseduardo in #352
- v2.57.5 by @doranteseduardo in #353
Full Changelog: v2.57.3...v2.57.5
v2.57.3
v2.57.3
Highlights
- Front-camera AR no longer references the ARKit TrueDepth API in core (iOS) — fixes App Store review 2.5.1.
VROARSessioniOSnow uses a registered config provider instead of instantiatingARFaceTrackingConfiguration; the ObjC hostVROFrontCameraProvideris supplied at runtime by the optional@reactvision/react-viro-face-trackingpackage (the only place that references the TrueDepth API). Core ViroKit ships free of it. TheViroCameraTextureselfie feed is unaffected (AVFoundation). - Android 15+ 16 KB launch crash fixed (viro#491). Removed the non-16 KB-aligned prebuilt
libvrapi.so, force-loaded vialibviro_renderer.so'sNEEDEDentry on every launch. - Removed the Oculus Mobile SDK (VrApi) renderer path.
VROSceneRendererOVR/VROInputControllerOVRare no longer compiled; superseded byVROSceneRendererOpenXR. - LiDAR depth confidence fixed (iOS). AR hit-test
depthConfidencenow reads ARKit'ssceneDepth.confidenceMap(normalised to 0–1) instead of returning the raw depth value, so the> 0.3confidence gate discards low-quality hits as intended. Monocular depth unaffected. - ViroVideo lifecycle crash & ANR fixed (Android, viro#478). (1)
AVPlayerguards its ExoPlayer listener callbacks with amDestroyedflag, so callbacks after the native player is deleted no longer reach freed memory (fixes the background/foreground crash). (2) removed two GL-thread↔main-thread deadlocks that froze/ANR'd the app when leaving a ViroVideo screen (GL thread blocked calling ExoPlayer on the main thread while the main thread was inGLSurfaceView.surfaceDestroyed()waiting for the GL thread):getCurrentTimeInSeconds()/getVideoDurationInSeconds()(called every frame from the render thread) now read avolatilecache refreshed on the main thread instead of a blocking hop (also removes per-frame playback jank), andnativeDeleteVideoTextureno longer callspause()on the GL thread before deleting (redundant — deletion already stops/releases the player).AVPlayer.destroy()additionally defersExoPlayer.release()off the teardown call.
Notes
- Rebuild the prebuilt AARs before publishing; confirm no shipped
.solistslibvrapi.soasNEEDED. - iOS:
VROFrontCameraProvider.{h,mm}must be in the ViroKit target; verifyARFaceTrackingis absent from the built ViroKit. - Pairs with
@reactvision/react-viro2.57.3; front-camera face tracking needs the optional package.
See CHANGELOG.md for full detail.
What's Changed
Other Changes
- v2.57.3 by @doranteseduardo in #344
Full Changelog: v2.57.2...v2.57.3
v2.57.2
v2.57.2 — 16 KB page-size alignment (completion)
This release completes the 16 KB memory-page alignment work started in previous releases,
unblocking Google Play / Meta Quest Store submission for Android 15+ devices.
Highlights
- All bundled native libraries are now 16 KB-page aligned. v2.57.0 aligned
libopenxr_loader.so, butlibc++_shared.sowas still 4 KB-aligned (2**12)
and kept failing the requirement. Because it's a prebuilt copied verbatim from
the NDK sysroot, the-Wl,-z,max-page-size=16384linker flag (which already
aligns everything Viro compiles) can't touch it — and NDK r21–r26 ship it at
4 KB. The Android NDK was bumped from r25 (25.2.9519653) → r27
(27.1.12297006), whoselibc++_shared.sois 16 KB-aligned, across all
native modules (sharedCode,viroreact,viroar,virocore,
reactvisioncca).
Notes
- Every 64-bit (
arm64-v8a) library now reports ≥ 16 KB segment alignment —
most at 16 KB (2**14), withlibvrapi.so/libgvr*.soat 64 KB (2**16).
Verified with Google'scheck_elf_alignment.sh(0 unaligned). - ELF segment alignment is one half of the requirement; ensure the consuming
app also packages each.souncompressed and 16 KB-aligned in the APK/AAB
(AGP 8.2+ handles this automatically). - Pairs with
@reactvision/react-viro2.57.2.
See CHANGELOG.md for full detail.
Full Changelog: v2.57.1...v2.57.2
v2.57.1
v2.57.1 — Mixed Reality on Meta Quest
This release adds a mixed-reality AR backend to the OpenXR renderer, so the
engine's AR component API (VROARScene / VROARPlaneAnchor / the anchor delegate)
works on Meta Quest 3 / 3S with passthrough.
Highlights
-
VROARSessionOpenXR— a newVROARSessionsubclass that mirrors
VROARSessionARCore, reusing the existing anchor → delegate → JNI → JS chain
unchanged. Plane detection is sourced from the Quest room model via
XR_FB_scene/XR_FB_spatial_entity/XR_FB_spatial_entity_query;
XR_EXT_plane_detectionis wired as a fallback.VROSceneRendererOpenXRowns
and drives the session per frame and wires it to the scene's AR delegate. -
Passthrough layer styling —
setPassthroughStyle(opacity, edgeRGBA)via
xrPassthroughLayerSetStyleFB. -
Passthrough black-background fix —
VRODisplayOpenGLOpenXR::bind()now
clears with a configurable alpha (0 for passthrough), and the projection layer
is composited over the passthrough underlay with source-alpha blending, so empty
regions reveal the room. -
Deferred-renderer state fix — passthrough / hand-tracking / style values set
before the lazily-created renderer exists are now cached and re-applied in
initRenderer().
Notes
- Quest room planes require the
horizonos.permission.USE_ANCHOR_APISpatial Data
permission and a completed Space Setup on the headset. - Bring-up-era OpenXR renderer diagnostics (alpha probe, blend-mode enumeration,
passthrough-only flag, redundant clear) have been removed now that the
passthrough composite path is validated.
See CHANGELOG.md for full detail.
Full Changelog: v2.57.0...v2.57.1