Skip to content

v2.53.0

Choose a tag to compare

@doranteseduardo doranteseduardo released this 11 Mar 00:34
· 5 commits to main since this release

@reactvision/react-viro v2.53.0 — Release Notes

⚠️ Breaking Changes

ViroARSceneNavigatorprovider replaces cloudAnchorProvider and geospatialAnchorProvider

The two separate props are merged into a single provider prop that controls both backends simultaneously. provider defaults to "reactvision" so the prop can be omitted entirely in most cases.

Before:

<ViroARSceneNavigator
  cloudAnchorProvider="reactvision"
  geospatialAnchorProvider="reactvision"
  initialScene={{ scene: MyARScene }}
/>

After:

// defaults to "reactvision" — prop can be omitted
<ViroARSceneNavigator initialScene={{ scene: MyARScene }} />

// Or to override:
<ViroARSceneNavigator provider="arcore" initialScene={{ scene: MyARScene }} />

ViroCloudAnchorProvider and ViroGeospatialAnchorProvider are now deprecated aliases for the new ViroProvider type. They still compile with a deprecation warning.

Expo plugin (withViro) — provider replaces cloudAnchorProvider and geospatialAnchorProvider

Before:

["@reactvision/react-viro", {
  "cloudAnchorProvider": "reactvision",
  "geospatialAnchorProvider": "reactvision",
  "rvApiKey": "...",
  "rvProjectId": "..."
}]

After:

["@reactvision/react-viro", {
  "provider": "reactvision",
  "rvApiKey": "...",
  "rvProjectId": "..."
}]

ViroARPlaneSelector requires manual anchor wiring

The component no longer self-discovers planes. You must now forward ViroARScene anchor events to it via a ref:

const selectorRef = useRef<ViroARPlaneSelector>(null);

<ViroARScene
  anchorDetectionTypes={["PlanesHorizontal", "PlanesVertical"]}
  onAnchorFound={(a)   => selectorRef.current?.handleAnchorFound(a)}
  onAnchorUpdated={(a) => selectorRef.current?.handleAnchorUpdated(a)}
  onAnchorRemoved={(a) => a && selectorRef.current?.handleAnchorRemoved(a)}
>
  <ViroARPlaneSelector ref={selectorRef} alignment="Both" onPlaneSelected={...}>
    <MyContent />
  </ViroARPlaneSelector>
</ViroARScene>

What's new

ReactVision Cloud Anchors (RVCA)

Place persistent AR content that other users can find — no Google Cloud account required. RVCA is a proprietary closed-source SDK; its implementation is not part of the open-source ViroCore or react-viro distribution.

The "reactvision" provider routes hostCloudAnchor / resolveCloudAnchor through the ReactVision platform. The existing hostCloudAnchor, resolveCloudAnchor, and onCloudAnchorStateChange API is unchanged.

  • Hosting: scan your environment briefly, then call hostCloudAnchor. Returns an error immediately if the environment has not been sufficiently observed — no silent fallback.
  • Resolving: the SDK matches the live camera feed against stored anchor data and returns a pose once a confident localisation is established. Cross-platform (iOS host → Android resolve and vice versa) is fully supported.
  • TTL: hostCloudAnchor accepts a ttlDays parameter (1–365) to control anchor expiry on the backend.
  • GPS tagging: set the device location before hosting to embed GPS coordinates as anchor metadata. Enables proximity search via rvFindNearbyCloudAnchors.

8 new methods on arSceneNavigator for full CRUD and analytics on cloud anchors:

Method Description
rvGetCloudAnchor(anchorId) Fetch a single anchor record
rvListCloudAnchors(limit, offset) Paginated list of all project anchors
rvUpdateCloudAnchor(id, name, desc, isPublic) Rename / re-describe an anchor
rvDeleteCloudAnchor(anchorId) Permanently delete an anchor and its assets
rvFindNearbyCloudAnchors(lat, lng, radius, limit) GPS proximity search
rvAttachAssetToCloudAnchor(id, url, size, name, type, userId) Attach a hosted file
rvRemoveAssetFromCloudAnchor(anchorId, assetId) Remove an attached asset
rvTrackCloudAnchorResolution(...) Record resolve analytics manually

ReactVision Geospatial Anchor Management

5 new management methods for GPS-tagged anchors (backed by the proprietary RVCA SDK):

Method Description
rvListGeospatialAnchors(limit, offset) Paginated list
rvGetGeospatialAnchor(anchorId) Fetch a single geospatial anchor
rvFindNearbyGeospatialAnchors(lat, lng, radius, limit) GPS proximity search
rvUpdateGeospatialAnchor(id, sceneAssetId, sceneId, name) Update metadata
rvDeleteGeospatialAnchor(anchorId) Permanently delete

createGeospatialAnchor, createTerrainAnchor, and createRooftopAnchor are now supported with provider="reactvision". No VPS, no ARCore Geospatial API, and no ARCore pods are required.

Asset upload:

rvUploadAsset(assetType, filename, data, appUserId) — uploads a file to ReactVision storage and returns a URL and asset ID. Supported assetType values: "3d-model", "image", "video", "audio". The returned asset ID can be linked to a geospatial anchor via rvUpdateGeospatialAnchor or to a cloud anchor via rvAttachAssetToCloudAnchor.

New geospatial utilities

  • gpsToArWorld(devicePose, lat, lng, alt) — converts a GPS coordinate to an AR world-space [x, y, z] offset from the device's current geospatial pose.
  • latLngToMercator(lat, lng) — converts a GPS coordinate to a metric 2D position. Building block for gpsToArWorld and custom geo math.

Both are exported from @reactvision/react-viro.

New ViroProvider type

Canonical union type "none" | "arcore" | "reactvision" exported from the package. Replaces the deprecated ViroCloudAnchorProvider and ViroGeospatialAnchorProvider types.

Shader modifier system — major expansion

Shader modifiers now support the full range of custom GPU effects:

  • Custom textures — declare uniform sampler2D in modifier code and pass textures via materialUniforms. Swap them at runtime with updateShaderUniform.
  • Vertex → fragment data — use the new varyings field to pass typed values from a Geometry modifier to a Surface or Fragment modifier (e.g. displacement amount driving roughness).
  • Scene depth access — set requiresSceneDepth: true on a fragment modifier to receive scene_depth_texture automatically. Enables soft particles, contact glow, and intersection effects.
  • Live camera feed on geometry — set requiresCameraTexture: true to sample the AR camera on any surface. Platform differences (samplerExternalOES vs sampler2D) handled invisibly. Enables magnifying glass, portal, refraction, and warp effects.
  • Deterministic ordering — modifiers now have a priority field so engine internals never override your effects regardless of attachment order.

AR plane detection improvements

  • Plane detection now defaults to both horizontal and vertical — no need to set anchorDetectionTypes explicitly.
  • Objects placed via ViroARPlaneSelector now appear at the exact tap point, not the plane centre.
  • onPlaneSelected receives the tap position as a third argument: (plane, tapPosition?) => void.
  • New props: onPlaneRemoved, hideOverlayOnSelection, material.
  • useActualShape now defaults to true — polygon boundary used instead of bounding rect.
  • New public method handleAnchorRemoved on ViroARPlaneSelector for use in the onAnchorRemoved callback.

Depth sensor access

ViroARSceneNavigator has three new props for apps that need depth data without full occlusion:

  • depthEnabled — activates LiDAR / monocular depth / ARCore Depth for DepthPoint hit tests.
  • depthDebugEnabled — overlays the depth map on the camera feed.
  • preferMonocularDepth (iOS only) — forces monocular depth even on LiDAR devices.

Bug fixes

  • Models with washed-out / overexposed colours — GLB and other 3D assets appeared too bright due to an emissive colour value being incorrectly added to all materials. Fixed.
  • iOS video recording silent failurestartVideoRecording / stopVideoRecording were broken on iOS 17+ with the New Architecture. Multiple AVAssetWriter and AVAudioSession issues fixed; recording now falls back to video-only if audio fails.
  • Android crash when closing a scene with physics — null pointer dereference on scene close for physics-enabled nodes. Fixed.
  • Android New Architecture dev menu error — "You should not use ReactNativeHost directly" error on startup. Fixed.
  • Ghost planes in ViroARPlaneSelector — pre-allocated slot index mapping was non-deterministic causing planes to appear in wrong positions or persist after removal. Fully rewritten.
  • Selected plane disappeared immediately on tap — opacity logic inversion fixed.
  • Children rendered on every plane slot — children now rendered once, only on the selected plane.
  • onPlaneDetected return value ignored — returning false from onPlaneDetected previously had no effect. Now correctly prevents the plane from being added to the visible set.
  • Removed planes not cleaned up — disappeared planes were never removed from internal state, accumulating over time. handleAnchorRemoved now deletes the entry and resets selection if needed.
  • Plane updates silently dropped for large surfaces — ARKit update threshold logic was AND instead of OR; large planes (floors, walls) rarely updated. Fixed.
  • Rapid plane updates dropped on initial detection — fixed 100 ms throttle replaced with adaptive rate (33 ms for first 20 updates, 66 ms thereafter).