Skip to content

v2.56.0

Latest

Choose a tag to compare

@doranteseduardo doranteseduardo released this 05 Jun 01:13
· 1 commit to main since this release
770e808

Release Notes — v2.56.0

What's new

Dynamic mesh node

VRODynamicMeshNode lets you update geometry every frame without recreating the node or triggering GPU reallocation. This unlocks a class of apps that wasn't practical before: procedural terrain, marching cubes in AR, CPU skinning of custom formats, and output from external simulation engines. The vertex buffers (positions, normals, UVs, colors) are updated in place using an orphan + sub-data path on OpenGL, keeping frame time flat even at 60 fps.


Virtual game controller

Two new native components — ViroVirtualJoystick and ViroVirtualButton — bring on-screen game controls to AR apps with sub-2 ms input latency. Touch events are handled entirely at the native layer and written to a shared state registry that your C++ game loop reads every frame, with no JS bridge round-trips in the hot path. Both components also fire JS callbacks (onStickChange, onPressIn, onPressOut) so you can drive UI reactions from the same input.

<ViroVirtualJoystick
  controllerId="p1"
  stickSide="left"
  radius={60}
  onStickChange={(e) => move(e.nativeEvent.x, e.nativeEvent.y)}
/>
<ViroVirtualButton controllerId="p1" button="A" size={52} />

PCM audio streaming

StreamingAudioManager opens a real-time audio path where you push raw PCM samples as they are produced, rather than loading a complete file. The API is the same on iOS and Android:

StreamingAudioManager.create('voice');
StreamingAudioManager.beginStreaming('voice', 24000, 1);
StreamingAudioManager.play('voice');

// from your audio producer loop:
StreamingAudioManager.pushSamples('voice', base64Float32PCM);

Useful for TTS output, procedural sound synthesis, physics-driven audio, and any embedded engine that generates audio samples at runtime.


AR World Mesh — public subscriber API

The AR world mesh is now a general-purpose multi-consumer provider. Any part of your app can subscribe to receive the full mesh geometry (vertices, indices, confidence) along with a source tag that tells you whether the data came from LiDAR, the monocular depth model, or ARKit plane anchors.

This release also adds:

  • Plane fallback — devices without LiDAR or the Depth API now get a mesh built from detected AR planes, so the feature degrades gracefully instead of producing nothing.
  • Per-consumer decimation — each subscriber can cap its triangle budget independently, so a physics engine and a nav-mesh consumer can coexist without fighting over resolution.
  • Async physics — Bullet BVH construction runs on a background thread, preventing the ARKit frame drops that appeared when processing large meshes on the render thread.
  • Full Android support — ARCore depth mode is now activated automatically when world mesh is enabled, and plane mesh generation is implemented end-to-end on Android.

Game loop

ViroGameLoop and the useGameLoop / useFixedUpdate hooks give you a proper per-frame callback with both variable-dt and deterministic fixed-step modes. Fixed-step mode is useful for physics engines and networked simulations that require ticks at an exact frequency.

<ViroGameLoop
  onUpdate={({ dt, elapsed }) => { /* variable, every frame */ }}
  fixedHz={30}
  onFixedUpdate={({ dt }) => { /* deterministic, 30 times/s */ }}
/>

ViroGameLoopUtils provides setPosition, setRotation, and setScale that write directly to the native node, bypassing React's reconciler for zero-overhead transforms from inside the loop.


Improvements

Monocular depth — new metric model, better occlusion

The monocular depth estimator has been upgraded to Depth Anything V2 (metric, indoor), a model trained on indoor scenes that outputs depth in meters. Compared to the previous model, occlusion triggers more reliably and at the correct distances for typical indoor AR use.

The pipeline also received several quality improvements: temporal confidence synthesis to avoid upgrading hit-tests on unstable depth pixels, in-place GPU texture updates that eliminate a per-frame allocation, correct handling of all four device orientations, and adaptive thermal throttling to prevent overheating during extended sessions.

Two new props on ViroARSceneNavigator let you tune the estimator at runtime:

Prop Default Description
monocularDepthScale 1.0 Multiplies all depth values before occlusion. Lower values make occlusion trigger sooner.
monocularDepthTargetFPS 5 Inference rate. Raise for smoother occlusion; lower to reduce thermal load.

Bug fixes

  • SIGABRT on Android 14+ (API 34) — a hard crash in the ARCore anchor handling path has been resolved. The crash occurred when NewStringUTF received a non-Modified-UTF-8 anchor ID, which became common on Android 14.

  • Quest Store submission rejected due to forced landscape orientation — the Viro Android plugin was unconditionally setting landscape orientation on MainActivity, which caused Quest Store validation failures for non-Quest apps and overrode the orientation set in app.json. The override now applies only to Quest apps.


Upgrade notes

No breaking changes. All new components and hooks are additive. StreamingAudioManager, ViroVirtualJoystick, ViroVirtualButton, ViroGameLoop, and the useGameLoop family are available as named exports from @reactvision/react-viro.

The setUpdateCallback on VROARWorldMesh is retained but deprecated in favor of the new subscribe / unsubscribe API.