@reactvision/react-viro 2.56.0 → 2.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/android/react_viro/react_viro-release.aar +0 -0
- package/android/viro_renderer/viro_renderer-release.aar +0 -0
- package/components/AR/ViroARScene.tsx +17 -0
- package/components/Utilities/ViroVersion.ts +1 -1
- package/components/ViroObjectDetector.tsx +222 -0
- package/dist/components/AR/ViroARScene.d.ts +12 -0
- package/dist/components/AR/ViroARScene.js +8 -1
- package/dist/components/Utilities/ViroVersion.d.ts +1 -1
- package/dist/components/Utilities/ViroVersion.js +1 -1
- package/dist/components/ViroObjectDetector.d.ts +138 -0
- package/dist/components/ViroObjectDetector.js +85 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -2
- package/dist/plugins/withViro.js +2 -15
- package/dist/plugins/withViroAndroid.js +0 -5
- package/dist/plugins/withViroIos.js +0 -6
- package/index.ts +3 -0
- package/ios/ViroReact.podspec +25 -6
- package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreCoreMLSemanticsResources.bundle/Info.plist +0 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreResources.bundle/Info.plist +0 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARFrameiOS.h +9 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARScene.h +14 -1
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROARSceneDelegateiOS.h +8 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROGLTFLoader.h +5 -1
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROMonocularDepthEstimator.h +10 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Headers/VROObjectDetector.h +134 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Info.plist +0 -0
- package/ios/dist/ViroRenderer/ViroKit.framework/Shaders.dat +1 -1
- package/ios/dist/ViroRenderer/ViroKit.framework/ViroKit +0 -0
- package/ios/dist/ViroRendererVisionOS/ViroKit.podspec +27 -0
- package/ios/dist/include/VRTARScene.h +1 -0
- package/ios/dist/lib/libViroReact.a +0 -0
- package/package.json +17 -20
package/README.md
CHANGED
|
@@ -45,6 +45,14 @@ For Expo projects, the easiest way to start is to clone the official starter kit
|
|
|
45
45
|
|
|
46
46
|
For step-by-step setup instructions, including platform-specific permissions and build configuration, see the full installation guide in the docs: <https://viro-community.readme.io/docs/installation-instructions>
|
|
47
47
|
|
|
48
|
+
## MCP Server
|
|
49
|
+
|
|
50
|
+
If you're building AR, VR or XR apps with ViroReact, our MCP server is the fastest way to get moving. Think of it as a living guide to ViroReact, always current, that plugs straight into the tools you already use.
|
|
51
|
+
|
|
52
|
+
Connect it to Claude, Codex, Cursor or any other coding agent, and your agent instantly understands how to work with ViroReact's cross-platform rendering. No hunting through docs, no guesswork. (Our documentation is still a great companion, but the MCP is the most up to date source there is.)
|
|
53
|
+
|
|
54
|
+
[MCP Setup Instructions](https://viro-community.readme.io/docs/viroreact-mcp-server)
|
|
55
|
+
|
|
48
56
|
## Features
|
|
49
57
|
|
|
50
58
|
ViroReact ships with a complete spatial computing toolkit out of the box — no third-party plugins, no paid add-ons.
|
|
Binary file
|
|
Binary file
|
|
@@ -72,6 +72,14 @@ type Props = ViroCommonProps & {
|
|
|
72
72
|
) => void;
|
|
73
73
|
onPlatformUpdate?: (platformInfoViro: ViroPlatformInfo) => void;
|
|
74
74
|
onAmbientLightUpdate?: (update: ViroAmbientLightInfo) => void;
|
|
75
|
+
/**
|
|
76
|
+
* Fired once when depth data (LiDAR or monocular depth estimation) first becomes
|
|
77
|
+
* available for the session — i.e. hit tests can now return DepthPoints. Useful for
|
|
78
|
+
* hiding an "initializing depth…" state instead of acting on early, inaccurate
|
|
79
|
+
* feature points. On devices using monocular depth estimation, this can take a few
|
|
80
|
+
* seconds after the AR screen appears while the model warms up.
|
|
81
|
+
*/
|
|
82
|
+
onDepthReady?: () => void;
|
|
75
83
|
/**
|
|
76
84
|
* Describes the acoustic properties of the room around the user
|
|
77
85
|
*/
|
|
@@ -237,6 +245,13 @@ export class ViroARScene extends ViroBase<Props> {
|
|
|
237
245
|
this.props.onAmbientLightUpdate(event.nativeEvent.ambientLightInfo);
|
|
238
246
|
};
|
|
239
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Fired once when depth data first becomes available for hit testing.
|
|
250
|
+
*/
|
|
251
|
+
_onDepthReady = (_event: NativeSyntheticEvent<{}>) => {
|
|
252
|
+
this.props.onDepthReady && this.props.onDepthReady();
|
|
253
|
+
};
|
|
254
|
+
|
|
240
255
|
_onAnchorFound = (event: NativeSyntheticEvent<ViroARAnchorFoundEvent>) => {
|
|
241
256
|
// TODO: this is in a different format than the other onAnchorFound methods
|
|
242
257
|
this.props.onAnchorFound &&
|
|
@@ -527,6 +542,7 @@ export class ViroARScene extends ViroBase<Props> {
|
|
|
527
542
|
onPlatformUpdateViro={this._onPlatformUpdate}
|
|
528
543
|
onTrackingUpdatedViro={this._onTrackingUpdated}
|
|
529
544
|
onAmbientLightUpdateViro={this._onAmbientLightUpdate}
|
|
545
|
+
onDepthReadyViro={this._onDepthReady}
|
|
530
546
|
onAnchorFoundViro={this._onAnchorFound}
|
|
531
547
|
onAnchorUpdatedViro={this._onAnchorUpdated}
|
|
532
548
|
onAnchorRemovedViro={this._onAnchorRemoved}
|
|
@@ -573,6 +589,7 @@ var VRTARScene = requireNativeComponent<any>(
|
|
|
573
589
|
onTrackingInitializedViro: true,
|
|
574
590
|
onTrackingUpdatedViro: true,
|
|
575
591
|
onAmbientLightUpdateViro: true,
|
|
592
|
+
onDepthReadyViro: true,
|
|
576
593
|
onAnchorFoundViro: true,
|
|
577
594
|
onAnchorUpdatedViro: true,
|
|
578
595
|
onAnchorRemovedViro: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VIRO_VERSION = "2.
|
|
1
|
+
export const VIRO_VERSION = "2.57.0";
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-present, ReactVision, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import {
|
|
11
|
+
NativeSyntheticEvent,
|
|
12
|
+
requireNativeComponent,
|
|
13
|
+
ViewProps,
|
|
14
|
+
} from "react-native";
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Types
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
export type ViroDetectorMode = "prompt-free" | "text" | "visual";
|
|
21
|
+
|
|
22
|
+
export type ViroDetectionBoundingBox = {
|
|
23
|
+
/** Left edge, normalized [0, 1] */
|
|
24
|
+
x: number;
|
|
25
|
+
/** Top edge, normalized [0, 1] */
|
|
26
|
+
y: number;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type ViroDetectedObject = {
|
|
32
|
+
label: string;
|
|
33
|
+
confidence: number;
|
|
34
|
+
boundingBox: ViroDetectionBoundingBox;
|
|
35
|
+
/** 3D world position (metres), from raycasting the bbox centre. Present when `projectToWorld` is true (iOS only). */
|
|
36
|
+
worldPosition?: { x: number; y: number; z: number };
|
|
37
|
+
/**
|
|
38
|
+
* Bounding box in density-independent points (dp), aligned to the on-screen AR
|
|
39
|
+
* camera preview. Use directly as { left, top, width, height } in an
|
|
40
|
+
* absolute-positioned View. Present on iOS and Android.
|
|
41
|
+
*/
|
|
42
|
+
screenBoundingBox?: { x: number; y: number; width: number; height: number };
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type ViroDetectionEvent = {
|
|
46
|
+
detections: ViroDetectedObject[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type ViroDetectorReadyEvent = Record<string, never>;
|
|
50
|
+
|
|
51
|
+
export type ViroDetectorErrorEvent = {
|
|
52
|
+
error: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type Props = ViewProps & {
|
|
56
|
+
/**
|
|
57
|
+
* The YOLOE model to run. Either a bundled model **name** (resolved natively as
|
|
58
|
+
* `<name>.onnx` in the app bundle / Android assets), or an absolute `/`-path or
|
|
59
|
+
* `file://` URL to an `.onnx` file. Defaults to "yoloe-26s".
|
|
60
|
+
*/
|
|
61
|
+
model?: string;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Inference mode:
|
|
65
|
+
* - "prompt-free": YOLOE LRPC — detects 4,585 categories with no extra prompt.
|
|
66
|
+
* - "text": YOLOE RepRTA — detect only the classes listed in `categories`.
|
|
67
|
+
* - "visual": YOLOE SAVPE — detect objects similar to a reference crop
|
|
68
|
+
* (reference image API to be added in a future release).
|
|
69
|
+
* Defaults to "prompt-free".
|
|
70
|
+
*/
|
|
71
|
+
mode?: ViroDetectorMode;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Text categories for "text" mode, e.g. ["chair", "person", "laptop"].
|
|
75
|
+
* Ignored in other modes.
|
|
76
|
+
*/
|
|
77
|
+
categories?: string[];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Minimum confidence score [0, 1] for a detection to be reported.
|
|
81
|
+
* Defaults to 0.4.
|
|
82
|
+
*/
|
|
83
|
+
confidenceThreshold?: number;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* IoU threshold used by NMS post-processing.
|
|
87
|
+
* Defaults to 0.45.
|
|
88
|
+
*/
|
|
89
|
+
iouThreshold?: number;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Maximum number of inference calls per second. The camera runs at the
|
|
93
|
+
* device's native frame rate; this throttle prevents the inference thread
|
|
94
|
+
* from saturating the CPU/NPU while the AR renderer runs in parallel.
|
|
95
|
+
* Defaults to 15.
|
|
96
|
+
*/
|
|
97
|
+
maxFPS?: number;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Maximum number of detections reported per frame, kept as the top-N by
|
|
101
|
+
* confidence (after NMS). Lower this to reduce clutter, raise it to surface
|
|
102
|
+
* more objects.
|
|
103
|
+
* Defaults to 20.
|
|
104
|
+
*/
|
|
105
|
+
maxDetections?: number;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* When true, each detection includes a `worldPosition` {x, y, z} obtained by
|
|
109
|
+
* raycasting the bbox centre against the AR scene. iOS only (Android emits
|
|
110
|
+
* `screenBoundingBox` but not yet `worldPosition`).
|
|
111
|
+
* Defaults to true.
|
|
112
|
+
*/
|
|
113
|
+
projectToWorld?: boolean;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Called every time the detector produces a new set of detections.
|
|
117
|
+
* May be called with an empty array if nothing is detected in a frame.
|
|
118
|
+
*/
|
|
119
|
+
onDetection?: (event: ViroDetectionEvent) => void;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Called once the model has been loaded and the camera pipeline is running.
|
|
123
|
+
*/
|
|
124
|
+
onReady?: (event: ViroDetectorReadyEvent) => void;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Called if the model fails to load or the camera cannot be opened.
|
|
128
|
+
*/
|
|
129
|
+
onError?: (event: ViroDetectorErrorEvent) => void;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Internal native event types
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
type NativeDetectionEvent = NativeSyntheticEvent<ViroDetectionEvent>;
|
|
137
|
+
type NativeReadyEvent = NativeSyntheticEvent<ViroDetectorReadyEvent>;
|
|
138
|
+
type NativeErrorEvent = NativeSyntheticEvent<ViroDetectorErrorEvent>;
|
|
139
|
+
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
// Component
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
|
|
144
|
+
const VRTObjectDetectorView = requireNativeComponent<any>("VRTObjectDetectorView");
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* ViroObjectDetector — on-device open-vocabulary object detection powered by YOLOE.
|
|
148
|
+
*
|
|
149
|
+
* Runs **only in AR**: it shares the camera feed of the enclosing
|
|
150
|
+
* `ViroARSceneNavigator` (no separate camera session, no preview of its own) and
|
|
151
|
+
* fires `onDetection` with labels, normalized bounding boxes, and an on-screen
|
|
152
|
+
* `screenBoundingBox` (dp) at up to `maxFPS`. Mount it as a child or sibling of a
|
|
153
|
+
* `ViroARSceneNavigator`; it renders nothing itself, so give it `width: 0, height: 0`.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```tsx
|
|
157
|
+
* <ViroARSceneNavigator initialScene={{ scene: MyScene }} />
|
|
158
|
+
* <ViroObjectDetector
|
|
159
|
+
* style={{ position: "absolute", width: 0, height: 0 }}
|
|
160
|
+
* mode="prompt-free"
|
|
161
|
+
* confidenceThreshold={0.4}
|
|
162
|
+
* maxFPS={15}
|
|
163
|
+
* onDetection={({ detections }) => {
|
|
164
|
+
* detections.forEach(d => console.log(d.label, d.confidence, d.screenBoundingBox));
|
|
165
|
+
* }}
|
|
166
|
+
* />
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export const ViroObjectDetector: React.FC<Props> = ({
|
|
170
|
+
model = "yoloe-26s",
|
|
171
|
+
mode = "prompt-free",
|
|
172
|
+
categories = [],
|
|
173
|
+
confidenceThreshold = 0.4,
|
|
174
|
+
iouThreshold = 0.45,
|
|
175
|
+
maxFPS = 15,
|
|
176
|
+
maxDetections = 20,
|
|
177
|
+
projectToWorld = true,
|
|
178
|
+
onDetection,
|
|
179
|
+
onReady,
|
|
180
|
+
onError,
|
|
181
|
+
style,
|
|
182
|
+
...rest
|
|
183
|
+
}) => {
|
|
184
|
+
const handleDetection = React.useCallback(
|
|
185
|
+
(event: NativeDetectionEvent) => {
|
|
186
|
+
onDetection?.(event.nativeEvent);
|
|
187
|
+
},
|
|
188
|
+
[onDetection]
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const handleReady = React.useCallback(
|
|
192
|
+
(event: NativeReadyEvent) => {
|
|
193
|
+
onReady?.(event.nativeEvent);
|
|
194
|
+
},
|
|
195
|
+
[onReady]
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const handleError = React.useCallback(
|
|
199
|
+
(event: NativeErrorEvent) => {
|
|
200
|
+
onError?.(event.nativeEvent);
|
|
201
|
+
},
|
|
202
|
+
[onError]
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<VRTObjectDetectorView
|
|
207
|
+
{...rest}
|
|
208
|
+
style={style}
|
|
209
|
+
model={model}
|
|
210
|
+
mode={mode}
|
|
211
|
+
categories={categories}
|
|
212
|
+
confidenceThreshold={confidenceThreshold}
|
|
213
|
+
iouThreshold={iouThreshold}
|
|
214
|
+
maxFPS={maxFPS}
|
|
215
|
+
maxDetections={maxDetections}
|
|
216
|
+
projectToWorld={projectToWorld}
|
|
217
|
+
onDetectionViro={onDetection ? handleDetection : undefined}
|
|
218
|
+
onReadyViro={onReady ? handleReady : undefined}
|
|
219
|
+
onErrorViro={onError ? handleError : undefined}
|
|
220
|
+
/>
|
|
221
|
+
);
|
|
222
|
+
};
|
|
@@ -17,6 +17,14 @@ type Props = ViroCommonProps & {
|
|
|
17
17
|
onTrackingUpdated?: (state: ViroTrackingState, reason: ViroTrackingReason) => void;
|
|
18
18
|
onPlatformUpdate?: (platformInfoViro: ViroPlatformInfo) => void;
|
|
19
19
|
onAmbientLightUpdate?: (update: ViroAmbientLightInfo) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Fired once when depth data (LiDAR or monocular depth estimation) first becomes
|
|
22
|
+
* available for the session — i.e. hit tests can now return DepthPoints. Useful for
|
|
23
|
+
* hiding an "initializing depth…" state instead of acting on early, inaccurate
|
|
24
|
+
* feature points. On devices using monocular depth estimation, this can take a few
|
|
25
|
+
* seconds after the AR screen appears while the model warms up.
|
|
26
|
+
*/
|
|
27
|
+
onDepthReady?: () => void;
|
|
20
28
|
/**
|
|
21
29
|
* Describes the acoustic properties of the room around the user
|
|
22
30
|
*/
|
|
@@ -47,6 +55,10 @@ export declare class ViroARScene extends ViroBase<Props> {
|
|
|
47
55
|
* Returns object w/ "intensity" and "color" keys
|
|
48
56
|
*/
|
|
49
57
|
_onAmbientLightUpdate: (event: NativeSyntheticEvent<ViroAmbientLightUpdateEvent>) => void;
|
|
58
|
+
/**
|
|
59
|
+
* Fired once when depth data first becomes available for hit testing.
|
|
60
|
+
*/
|
|
61
|
+
_onDepthReady: (_event: NativeSyntheticEvent<{}>) => void;
|
|
50
62
|
_onAnchorFound: (event: NativeSyntheticEvent<ViroARAnchorFoundEvent>) => void;
|
|
51
63
|
_onAnchorUpdated: (event: NativeSyntheticEvent<ViroARAnchorUpdatedEvent>) => void;
|
|
52
64
|
_onAnchorRemoved: (event: NativeSyntheticEvent<ViroARAnchorRemovedEvent>) => void;
|
|
@@ -176,6 +176,12 @@ class ViroARScene extends ViroBase_1.ViroBase {
|
|
|
176
176
|
this.props.onAmbientLightUpdate &&
|
|
177
177
|
this.props.onAmbientLightUpdate(event.nativeEvent.ambientLightInfo);
|
|
178
178
|
};
|
|
179
|
+
/**
|
|
180
|
+
* Fired once when depth data first becomes available for hit testing.
|
|
181
|
+
*/
|
|
182
|
+
_onDepthReady = (_event) => {
|
|
183
|
+
this.props.onDepthReady && this.props.onDepthReady();
|
|
184
|
+
};
|
|
179
185
|
_onAnchorFound = (event) => {
|
|
180
186
|
// TODO: this is in a different format than the other onAnchorFound methods
|
|
181
187
|
this.props.onAnchorFound &&
|
|
@@ -334,7 +340,7 @@ class ViroARScene extends ViroBase_1.ViroBase {
|
|
|
334
340
|
},
|
|
335
341
|
}}>
|
|
336
342
|
<VRTARScene {...this.props} canHover={this.props.onHover != undefined} canClick={this.props.onClick != undefined ||
|
|
337
|
-
this.props.onClickState != undefined} canTouch={this.props.onTouch != undefined} canScroll={this.props.onScroll != undefined} canSwipe={this.props.onSwipe != undefined} canDrag={this.props.onDrag != undefined} canPinch={this.props.onPinch != undefined} canRotate={this.props.onRotate != undefined} canFuse={this.props.onFuse != undefined} canCameraARHitTest={this.props.onCameraARHitTest != undefined} canARPointCloudUpdate={this.props.onARPointCloudUpdate != undefined} canCameraTransformUpdate={this.props.onCameraTransformUpdate != undefined} onHoverViro={this._onHover} onClickViro={this._onClickState} onClick={undefined} onTouchViro={this._onTouch} onScrollViro={this._onScroll} onSwipeViro={this._onSwipe} onDragViro={this._onDrag} onPinchViro={this._onPinch} onRotateViro={this._onRotate} onFuseViro={this._onFuse} onCameraARHitTestViro={this._onCameraARHitTest} onARPointCloudUpdateViro={this._onARPointCloudUpdate} onCameraTransformUpdateViro={this._onCameraTransformUpdate} onPlatformUpdateViro={this._onPlatformUpdate} onTrackingUpdatedViro={this._onTrackingUpdated} onAmbientLightUpdateViro={this._onAmbientLightUpdate} onAnchorFoundViro={this._onAnchorFound} onAnchorUpdatedViro={this._onAnchorUpdated} onAnchorRemovedViro={this._onAnchorRemoved} timeToFuse={timeToFuse} anchorDetectionTypes={anchorDetectionTypes} displayPointCloud={displayPointCloud} pointCloudImage={pointCloudImage} pointCloudScale={pointCloudScale} pointCloudMaxPoints={pointCloudMaxPoints}/>
|
|
343
|
+
this.props.onClickState != undefined} canTouch={this.props.onTouch != undefined} canScroll={this.props.onScroll != undefined} canSwipe={this.props.onSwipe != undefined} canDrag={this.props.onDrag != undefined} canPinch={this.props.onPinch != undefined} canRotate={this.props.onRotate != undefined} canFuse={this.props.onFuse != undefined} canCameraARHitTest={this.props.onCameraARHitTest != undefined} canARPointCloudUpdate={this.props.onARPointCloudUpdate != undefined} canCameraTransformUpdate={this.props.onCameraTransformUpdate != undefined} onHoverViro={this._onHover} onClickViro={this._onClickState} onClick={undefined} onTouchViro={this._onTouch} onScrollViro={this._onScroll} onSwipeViro={this._onSwipe} onDragViro={this._onDrag} onPinchViro={this._onPinch} onRotateViro={this._onRotate} onFuseViro={this._onFuse} onCameraARHitTestViro={this._onCameraARHitTest} onARPointCloudUpdateViro={this._onARPointCloudUpdate} onCameraTransformUpdateViro={this._onCameraTransformUpdate} onPlatformUpdateViro={this._onPlatformUpdate} onTrackingUpdatedViro={this._onTrackingUpdated} onAmbientLightUpdateViro={this._onAmbientLightUpdate} onDepthReadyViro={this._onDepthReady} onAnchorFoundViro={this._onAnchorFound} onAnchorUpdatedViro={this._onAnchorUpdated} onAnchorRemovedViro={this._onAnchorRemoved} timeToFuse={timeToFuse} anchorDetectionTypes={anchorDetectionTypes} displayPointCloud={displayPointCloud} pointCloudImage={pointCloudImage} pointCloudScale={pointCloudScale} pointCloudMaxPoints={pointCloudMaxPoints}/>
|
|
338
344
|
</ViroSceneContext_1.ViroSceneContext.Provider>);
|
|
339
345
|
}
|
|
340
346
|
}
|
|
@@ -368,6 +374,7 @@ ViroARScene, {
|
|
|
368
374
|
onTrackingInitializedViro: true,
|
|
369
375
|
onTrackingUpdatedViro: true,
|
|
370
376
|
onAmbientLightUpdateViro: true,
|
|
377
|
+
onDepthReadyViro: true,
|
|
371
378
|
onAnchorFoundViro: true,
|
|
372
379
|
onAnchorUpdatedViro: true,
|
|
373
380
|
onAnchorRemovedViro: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VIRO_VERSION = "2.
|
|
1
|
+
export declare const VIRO_VERSION = "2.57.0";
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026-present, ReactVision, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import { ViewProps } from "react-native";
|
|
10
|
+
export type ViroDetectorMode = "prompt-free" | "text" | "visual";
|
|
11
|
+
export type ViroDetectionBoundingBox = {
|
|
12
|
+
/** Left edge, normalized [0, 1] */
|
|
13
|
+
x: number;
|
|
14
|
+
/** Top edge, normalized [0, 1] */
|
|
15
|
+
y: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
export type ViroDetectedObject = {
|
|
20
|
+
label: string;
|
|
21
|
+
confidence: number;
|
|
22
|
+
boundingBox: ViroDetectionBoundingBox;
|
|
23
|
+
/** 3D world position (metres), from raycasting the bbox centre. Present when `projectToWorld` is true (iOS only). */
|
|
24
|
+
worldPosition?: {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
z: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Bounding box in density-independent points (dp), aligned to the on-screen AR
|
|
31
|
+
* camera preview. Use directly as { left, top, width, height } in an
|
|
32
|
+
* absolute-positioned View. Present on iOS and Android.
|
|
33
|
+
*/
|
|
34
|
+
screenBoundingBox?: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export type ViroDetectionEvent = {
|
|
42
|
+
detections: ViroDetectedObject[];
|
|
43
|
+
};
|
|
44
|
+
export type ViroDetectorReadyEvent = Record<string, never>;
|
|
45
|
+
export type ViroDetectorErrorEvent = {
|
|
46
|
+
error: string;
|
|
47
|
+
};
|
|
48
|
+
type Props = ViewProps & {
|
|
49
|
+
/**
|
|
50
|
+
* The YOLOE model to run. Either a bundled model **name** (resolved natively as
|
|
51
|
+
* `<name>.onnx` in the app bundle / Android assets), or an absolute `/`-path or
|
|
52
|
+
* `file://` URL to an `.onnx` file. Defaults to "yoloe-26s".
|
|
53
|
+
*/
|
|
54
|
+
model?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Inference mode:
|
|
57
|
+
* - "prompt-free": YOLOE LRPC — detects 4,585 categories with no extra prompt.
|
|
58
|
+
* - "text": YOLOE RepRTA — detect only the classes listed in `categories`.
|
|
59
|
+
* - "visual": YOLOE SAVPE — detect objects similar to a reference crop
|
|
60
|
+
* (reference image API to be added in a future release).
|
|
61
|
+
* Defaults to "prompt-free".
|
|
62
|
+
*/
|
|
63
|
+
mode?: ViroDetectorMode;
|
|
64
|
+
/**
|
|
65
|
+
* Text categories for "text" mode, e.g. ["chair", "person", "laptop"].
|
|
66
|
+
* Ignored in other modes.
|
|
67
|
+
*/
|
|
68
|
+
categories?: string[];
|
|
69
|
+
/**
|
|
70
|
+
* Minimum confidence score [0, 1] for a detection to be reported.
|
|
71
|
+
* Defaults to 0.4.
|
|
72
|
+
*/
|
|
73
|
+
confidenceThreshold?: number;
|
|
74
|
+
/**
|
|
75
|
+
* IoU threshold used by NMS post-processing.
|
|
76
|
+
* Defaults to 0.45.
|
|
77
|
+
*/
|
|
78
|
+
iouThreshold?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Maximum number of inference calls per second. The camera runs at the
|
|
81
|
+
* device's native frame rate; this throttle prevents the inference thread
|
|
82
|
+
* from saturating the CPU/NPU while the AR renderer runs in parallel.
|
|
83
|
+
* Defaults to 15.
|
|
84
|
+
*/
|
|
85
|
+
maxFPS?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Maximum number of detections reported per frame, kept as the top-N by
|
|
88
|
+
* confidence (after NMS). Lower this to reduce clutter, raise it to surface
|
|
89
|
+
* more objects.
|
|
90
|
+
* Defaults to 20.
|
|
91
|
+
*/
|
|
92
|
+
maxDetections?: number;
|
|
93
|
+
/**
|
|
94
|
+
* When true, each detection includes a `worldPosition` {x, y, z} obtained by
|
|
95
|
+
* raycasting the bbox centre against the AR scene. iOS only (Android emits
|
|
96
|
+
* `screenBoundingBox` but not yet `worldPosition`).
|
|
97
|
+
* Defaults to true.
|
|
98
|
+
*/
|
|
99
|
+
projectToWorld?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Called every time the detector produces a new set of detections.
|
|
102
|
+
* May be called with an empty array if nothing is detected in a frame.
|
|
103
|
+
*/
|
|
104
|
+
onDetection?: (event: ViroDetectionEvent) => void;
|
|
105
|
+
/**
|
|
106
|
+
* Called once the model has been loaded and the camera pipeline is running.
|
|
107
|
+
*/
|
|
108
|
+
onReady?: (event: ViroDetectorReadyEvent) => void;
|
|
109
|
+
/**
|
|
110
|
+
* Called if the model fails to load or the camera cannot be opened.
|
|
111
|
+
*/
|
|
112
|
+
onError?: (event: ViroDetectorErrorEvent) => void;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* ViroObjectDetector — on-device open-vocabulary object detection powered by YOLOE.
|
|
116
|
+
*
|
|
117
|
+
* Runs **only in AR**: it shares the camera feed of the enclosing
|
|
118
|
+
* `ViroARSceneNavigator` (no separate camera session, no preview of its own) and
|
|
119
|
+
* fires `onDetection` with labels, normalized bounding boxes, and an on-screen
|
|
120
|
+
* `screenBoundingBox` (dp) at up to `maxFPS`. Mount it as a child or sibling of a
|
|
121
|
+
* `ViroARSceneNavigator`; it renders nothing itself, so give it `width: 0, height: 0`.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```tsx
|
|
125
|
+
* <ViroARSceneNavigator initialScene={{ scene: MyScene }} />
|
|
126
|
+
* <ViroObjectDetector
|
|
127
|
+
* style={{ position: "absolute", width: 0, height: 0 }}
|
|
128
|
+
* mode="prompt-free"
|
|
129
|
+
* confidenceThreshold={0.4}
|
|
130
|
+
* maxFPS={15}
|
|
131
|
+
* onDetection={({ detections }) => {
|
|
132
|
+
* detections.forEach(d => console.log(d.label, d.confidence, d.screenBoundingBox));
|
|
133
|
+
* }}
|
|
134
|
+
* />
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export declare const ViroObjectDetector: React.FC<Props>;
|
|
138
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2026-present, ReactVision, Inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the BSD-style license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.ViroObjectDetector = void 0;
|
|
44
|
+
const React = __importStar(require("react"));
|
|
45
|
+
const react_native_1 = require("react-native");
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Component
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
const VRTObjectDetectorView = (0, react_native_1.requireNativeComponent)("VRTObjectDetectorView");
|
|
50
|
+
/**
|
|
51
|
+
* ViroObjectDetector — on-device open-vocabulary object detection powered by YOLOE.
|
|
52
|
+
*
|
|
53
|
+
* Runs **only in AR**: it shares the camera feed of the enclosing
|
|
54
|
+
* `ViroARSceneNavigator` (no separate camera session, no preview of its own) and
|
|
55
|
+
* fires `onDetection` with labels, normalized bounding boxes, and an on-screen
|
|
56
|
+
* `screenBoundingBox` (dp) at up to `maxFPS`. Mount it as a child or sibling of a
|
|
57
|
+
* `ViroARSceneNavigator`; it renders nothing itself, so give it `width: 0, height: 0`.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <ViroARSceneNavigator initialScene={{ scene: MyScene }} />
|
|
62
|
+
* <ViroObjectDetector
|
|
63
|
+
* style={{ position: "absolute", width: 0, height: 0 }}
|
|
64
|
+
* mode="prompt-free"
|
|
65
|
+
* confidenceThreshold={0.4}
|
|
66
|
+
* maxFPS={15}
|
|
67
|
+
* onDetection={({ detections }) => {
|
|
68
|
+
* detections.forEach(d => console.log(d.label, d.confidence, d.screenBoundingBox));
|
|
69
|
+
* }}
|
|
70
|
+
* />
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
const ViroObjectDetector = ({ model = "yoloe-26s", mode = "prompt-free", categories = [], confidenceThreshold = 0.4, iouThreshold = 0.45, maxFPS = 15, maxDetections = 20, projectToWorld = true, onDetection, onReady, onError, style, ...rest }) => {
|
|
74
|
+
const handleDetection = React.useCallback((event) => {
|
|
75
|
+
onDetection?.(event.nativeEvent);
|
|
76
|
+
}, [onDetection]);
|
|
77
|
+
const handleReady = React.useCallback((event) => {
|
|
78
|
+
onReady?.(event.nativeEvent);
|
|
79
|
+
}, [onReady]);
|
|
80
|
+
const handleError = React.useCallback((event) => {
|
|
81
|
+
onError?.(event.nativeEvent);
|
|
82
|
+
}, [onError]);
|
|
83
|
+
return (<VRTObjectDetectorView {...rest} style={style} model={model} mode={mode} categories={categories} confidenceThreshold={confidenceThreshold} iouThreshold={iouThreshold} maxFPS={maxFPS} maxDetections={maxDetections} projectToWorld={projectToWorld} onDetectionViro={onDetection ? handleDetection : undefined} onReadyViro={onReady ? handleReady : undefined} onErrorViro={onError ? handleError : undefined}/>);
|
|
84
|
+
};
|
|
85
|
+
exports.ViroObjectDetector = ViroObjectDetector;
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ import { ViroMaterials, ViroMaterial, ViroShaderModifiers, ViroShaderUniform, Vi
|
|
|
38
38
|
import { ViroMaterialVideo } from "./components/ViroMaterialVideo";
|
|
39
39
|
import { ViroCameraTexture } from "./components/ViroCameraTexture";
|
|
40
40
|
export type { ViroCameraPosition, ViroCameraReadyEvent } from "./components/ViroCameraTexture";
|
|
41
|
+
import { ViroObjectDetector } from "./components/ViroObjectDetector";
|
|
42
|
+
export type { ViroDetectorMode, ViroDetectedObject, ViroDetectionBoundingBox, ViroDetectionEvent, ViroDetectorReadyEvent, ViroDetectorErrorEvent } from "./components/ViroObjectDetector";
|
|
41
43
|
import { ViroNode } from "./components/ViroNode";
|
|
42
44
|
import { ViroOmniLight } from "./components/ViroOmniLight";
|
|
43
45
|
import { ViroOrbitCamera } from "./components/ViroOrbitCamera";
|
|
@@ -76,7 +78,7 @@ import { VRQuestNavigatorBridge } from "./components/Utilities/VRQuestNavigatorB
|
|
|
76
78
|
import { VRModuleOpenXR, useVRViewTag, exitVRScene } from "./components/Utilities/VRModuleOpenXR";
|
|
77
79
|
import type { VRModuleOpenXRType } from "./components/Utilities/VRModuleOpenXR";
|
|
78
80
|
import { StreamingAudioManager } from "./components/Utilities/StreamingAudioManager";
|
|
79
|
-
export { ViroARImageMarker, ViroARObjectMarker, ViroARTrackingTargets, ViroARPlane, ViroARPlaneSelector, ViroARScene, ViroARSceneNavigator, ViroBox, ViroButton, ViroCamera, ViroController, ViroVirtualJoystick, ViroVirtualButton, ViroGameLoop, ViroGameLoopUtils, useGameLoop, useLateUpdate, useFixedUpdate, ViroDirectionalLight, ViroFlexView, ViroGeometry, ViroLightingEnvironment, ViroImage, ViroMaterials, ViroARCamera, ViroMaterialVideo, ViroCameraTexture, ViroNode, ViroOmniLight, ViroOrbitCamera, ViroParticleEmitter, ViroPolygon, ViroPolyline, ViroPortal, ViroPortalScene, ViroQuad, ViroScene, ViroSurface, ViroSceneNavigator, ViroSkyBox, ViroAnimations, Viro3DObject, Viro360Image, Viro360Video, ViroAnimatedImage, ViroAmbientLight, ViroAnimatedComponent, ViroSound, ViroSoundField, ViroSpatialSound, ViroSphere, ViroSpinner, ViroSpotLight, ViroText, ViroVideo, ViroVRSceneNavigator, ViroXRSceneNavigator, ViroQuestEntryPoint, VRQuestNavigatorBridge, VRModuleOpenXR, useVRViewTag, exitVRScene, Viro3DSceneNavigator, StreamingAudioManager, hasOpenXRSupport, isQuest, useAnySourceHover, useAnySourcePressed, ViroARTrackingReasonConstants, ViroRecordingErrorConstants, ViroTrackingStateConstants, polarToCartesian, polarToCartesianActual, isARSupportedOnDevice, requestRequiredPermissions, checkPermissions, latLngToMercator, gpsToArWorld, ViroARSupportResponse, ViroPermissionsResult, ViroPermission, ViroHoverEvent, ViroClickEvent, ViroClickStateEvent, ViroClickStateTypes, ViroTouchEvent, ViroScrollEvent, ViroSwipeEvent, ViroFuseEvent, ViroPinchEvent, ViroPinchStateTypes, ViroRotateEvent, ViroRotateStateTypes, ViroDragEvent, ViroPlatformEvent, ViroCollisionEvent, ViroPlatformInfo, ViroCameraTransformEvent, ViroPlatformUpdateEvent, ViroCameraTransform, ViroExitViroEvent, ViroErrorEvent, ViroAnimationStartEvent, ViroAnimationFinishEvent, ViroLoadStartEvent, ViroLoadEndEvent, ViroLoadErrorEvent, ViroVideoBufferStartEvent, ViroVideoBufferEndEvent, ViroVideoUpdateTimeEvent, ViroVideoErrorEvent, ViroVideoFinishEvent, ViroAnimatedComponentStartEvent, ViroAnimatedComponentFinishEvent, ViroARAnchorRemovedEvent, ViroARAnchorUpdatedEvent, ViroARAnchorFoundEvent, ViroAnchor, ViroAnchorFoundMap, ViroAnchorUpdatedMap, ViroPlaneUpdatedMap, ViroPlaneUpdatedEvent, ViroARPlaneSizes, ViroCameraARHitTestEvent, ViroCameraARHitTest, ViroARHitTestResult, ViroARPointCloudUpdateEvent, ViroARPointCloud, ViroTrackingUpdatedEvent, ViroTrackingState, ViroTrackingReason, ViroAmbientLightUpdateEvent, ViroAmbientLightInfo, ViroWorldOrigin, ViroNativeTransformUpdateEvent, ViroControllerStatusEvent, ViroControllerStatus, ViroPortalEnterEvent, ViroPortalExitEvent, ViroSoundFinishEvent, ViroTextStyle, ViroStyle, ViroMaterial, ViroShaderModifiers, ViroShaderUniform, ViroShaderModifier, VIRO_VERSION, ViroProvider, ViroCloudAnchorState, ViroCloudAnchorProvider, ViroCloudAnchor, ViroHostCloudAnchorResult, ViroResolveCloudAnchorResult, ViroCloudAnchorStateChangeEvent, ViroGeospatialAnchorProvider, ViroEarthTrackingState, ViroVPSAvailability, ViroGeospatialAnchorType, ViroQuaternion, ViroGeospatialPose, ViroGeospatialAnchor, ViroGeospatialSupportResult, ViroEarthTrackingStateResult, ViroGeospatialPoseResult, ViroVPSAvailabilityResult, ViroCreateGeospatialAnchorResult, ViroMonocularDepthSupportResult, ViroMonocularDepthModelAvailableResult, ViroMonocularDepthPreferenceResult, ViroJoint, ViroHandJoints, ViroHandPinchEvent, ViroHandUpdateEvent, StudioSceneNavigator, StudioARScene, ViroVisionOSModule, isVisionOS, enterImmersiveSpace, exitImmersiveSpace, };
|
|
81
|
+
export { ViroARImageMarker, ViroARObjectMarker, ViroARTrackingTargets, ViroARPlane, ViroARPlaneSelector, ViroARScene, ViroARSceneNavigator, ViroBox, ViroButton, ViroCamera, ViroController, ViroVirtualJoystick, ViroVirtualButton, ViroGameLoop, ViroGameLoopUtils, useGameLoop, useLateUpdate, useFixedUpdate, ViroDirectionalLight, ViroFlexView, ViroGeometry, ViroLightingEnvironment, ViroImage, ViroMaterials, ViroARCamera, ViroMaterialVideo, ViroCameraTexture, ViroObjectDetector, ViroNode, ViroOmniLight, ViroOrbitCamera, ViroParticleEmitter, ViroPolygon, ViroPolyline, ViroPortal, ViroPortalScene, ViroQuad, ViroScene, ViroSurface, ViroSceneNavigator, ViroSkyBox, ViroAnimations, Viro3DObject, Viro360Image, Viro360Video, ViroAnimatedImage, ViroAmbientLight, ViroAnimatedComponent, ViroSound, ViroSoundField, ViroSpatialSound, ViroSphere, ViroSpinner, ViroSpotLight, ViroText, ViroVideo, ViroVRSceneNavigator, ViroXRSceneNavigator, ViroQuestEntryPoint, VRQuestNavigatorBridge, VRModuleOpenXR, useVRViewTag, exitVRScene, Viro3DSceneNavigator, StreamingAudioManager, hasOpenXRSupport, isQuest, useAnySourceHover, useAnySourcePressed, ViroARTrackingReasonConstants, ViroRecordingErrorConstants, ViroTrackingStateConstants, polarToCartesian, polarToCartesianActual, isARSupportedOnDevice, requestRequiredPermissions, checkPermissions, latLngToMercator, gpsToArWorld, ViroARSupportResponse, ViroPermissionsResult, ViroPermission, ViroHoverEvent, ViroClickEvent, ViroClickStateEvent, ViroClickStateTypes, ViroTouchEvent, ViroScrollEvent, ViroSwipeEvent, ViroFuseEvent, ViroPinchEvent, ViroPinchStateTypes, ViroRotateEvent, ViroRotateStateTypes, ViroDragEvent, ViroPlatformEvent, ViroCollisionEvent, ViroPlatformInfo, ViroCameraTransformEvent, ViroPlatformUpdateEvent, ViroCameraTransform, ViroExitViroEvent, ViroErrorEvent, ViroAnimationStartEvent, ViroAnimationFinishEvent, ViroLoadStartEvent, ViroLoadEndEvent, ViroLoadErrorEvent, ViroVideoBufferStartEvent, ViroVideoBufferEndEvent, ViroVideoUpdateTimeEvent, ViroVideoErrorEvent, ViroVideoFinishEvent, ViroAnimatedComponentStartEvent, ViroAnimatedComponentFinishEvent, ViroARAnchorRemovedEvent, ViroARAnchorUpdatedEvent, ViroARAnchorFoundEvent, ViroAnchor, ViroAnchorFoundMap, ViroAnchorUpdatedMap, ViroPlaneUpdatedMap, ViroPlaneUpdatedEvent, ViroARPlaneSizes, ViroCameraARHitTestEvent, ViroCameraARHitTest, ViroARHitTestResult, ViroARPointCloudUpdateEvent, ViroARPointCloud, ViroTrackingUpdatedEvent, ViroTrackingState, ViroTrackingReason, ViroAmbientLightUpdateEvent, ViroAmbientLightInfo, ViroWorldOrigin, ViroNativeTransformUpdateEvent, ViroControllerStatusEvent, ViroControllerStatus, ViroPortalEnterEvent, ViroPortalExitEvent, ViroSoundFinishEvent, ViroTextStyle, ViroStyle, ViroMaterial, ViroShaderModifiers, ViroShaderUniform, ViroShaderModifier, VIRO_VERSION, ViroProvider, ViroCloudAnchorState, ViroCloudAnchorProvider, ViroCloudAnchor, ViroHostCloudAnchorResult, ViroResolveCloudAnchorResult, ViroCloudAnchorStateChangeEvent, ViroGeospatialAnchorProvider, ViroEarthTrackingState, ViroVPSAvailability, ViroGeospatialAnchorType, ViroQuaternion, ViroGeospatialPose, ViroGeospatialAnchor, ViroGeospatialSupportResult, ViroEarthTrackingStateResult, ViroGeospatialPoseResult, ViroVPSAvailabilityResult, ViroCreateGeospatialAnchorResult, ViroMonocularDepthSupportResult, ViroMonocularDepthModelAvailableResult, ViroMonocularDepthPreferenceResult, ViroJoint, ViroHandJoints, ViroHandPinchEvent, ViroHandUpdateEvent, StudioSceneNavigator, StudioARScene, ViroVisionOSModule, isVisionOS, enterImmersiveSpace, exitImmersiveSpace, };
|
|
80
82
|
export type { VRModuleOpenXRType };
|
|
81
83
|
export type { ImmersiveSpaceStyle } from "./components/VisionOS/ViroVisionOSModule";
|
|
82
84
|
export type { StudioSceneResponse, StudioAsset, StudioAnimation, StudioCollisionBinding, StudioSceneFunction, StudioSceneMeta, StudioProjectMeta, } from "./components/Studio";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.exitImmersiveSpace = exports.enterImmersiveSpace = exports.isVisionOS = exports.ViroVisionOSModule = exports.StudioARScene = exports.StudioSceneNavigator = exports.VIRO_VERSION = exports.ViroRotateStateTypes = exports.ViroPinchStateTypes = exports.ViroClickStateTypes = exports.gpsToArWorld = exports.latLngToMercator = exports.checkPermissions = exports.requestRequiredPermissions = exports.isARSupportedOnDevice = exports.polarToCartesianActual = exports.polarToCartesian = exports.ViroTrackingStateConstants = exports.ViroRecordingErrorConstants = exports.ViroARTrackingReasonConstants = exports.useAnySourcePressed = exports.useAnySourceHover = exports.isQuest = exports.hasOpenXRSupport = exports.StreamingAudioManager = exports.Viro3DSceneNavigator = exports.exitVRScene = exports.useVRViewTag = exports.VRModuleOpenXR = exports.VRQuestNavigatorBridge = exports.ViroQuestEntryPoint = exports.ViroXRSceneNavigator = exports.ViroVRSceneNavigator = exports.ViroVideo = exports.ViroText = exports.ViroSpotLight = exports.ViroSpinner = exports.ViroSphere = void 0;
|
|
3
|
+
exports.ViroSoundField = exports.ViroSound = exports.ViroAnimatedComponent = exports.ViroAmbientLight = exports.ViroAnimatedImage = exports.Viro360Video = exports.Viro360Image = exports.Viro3DObject = exports.ViroAnimations = exports.ViroSkyBox = exports.ViroSceneNavigator = exports.ViroSurface = exports.ViroScene = exports.ViroQuad = exports.ViroPortalScene = exports.ViroPortal = exports.ViroPolyline = exports.ViroPolygon = exports.ViroParticleEmitter = exports.ViroOrbitCamera = exports.ViroOmniLight = exports.ViroNode = exports.ViroObjectDetector = exports.ViroCameraTexture = exports.ViroMaterialVideo = exports.ViroARCamera = exports.ViroMaterials = exports.ViroImage = exports.ViroLightingEnvironment = exports.ViroGeometry = exports.ViroFlexView = exports.ViroDirectionalLight = exports.useFixedUpdate = exports.useLateUpdate = exports.useGameLoop = exports.ViroGameLoopUtils = exports.ViroGameLoop = exports.ViroVirtualButton = exports.ViroVirtualJoystick = exports.ViroController = exports.ViroCamera = exports.ViroButton = exports.ViroBox = exports.ViroARSceneNavigator = exports.ViroARScene = exports.ViroARPlaneSelector = exports.ViroARPlane = exports.ViroARTrackingTargets = exports.ViroARObjectMarker = exports.ViroARImageMarker = void 0;
|
|
4
|
+
exports.exitImmersiveSpace = exports.enterImmersiveSpace = exports.isVisionOS = exports.ViroVisionOSModule = exports.StudioARScene = exports.StudioSceneNavigator = exports.VIRO_VERSION = exports.ViroRotateStateTypes = exports.ViroPinchStateTypes = exports.ViroClickStateTypes = exports.gpsToArWorld = exports.latLngToMercator = exports.checkPermissions = exports.requestRequiredPermissions = exports.isARSupportedOnDevice = exports.polarToCartesianActual = exports.polarToCartesian = exports.ViroTrackingStateConstants = exports.ViroRecordingErrorConstants = exports.ViroARTrackingReasonConstants = exports.useAnySourcePressed = exports.useAnySourceHover = exports.isQuest = exports.hasOpenXRSupport = exports.StreamingAudioManager = exports.Viro3DSceneNavigator = exports.exitVRScene = exports.useVRViewTag = exports.VRModuleOpenXR = exports.VRQuestNavigatorBridge = exports.ViroQuestEntryPoint = exports.ViroXRSceneNavigator = exports.ViroVRSceneNavigator = exports.ViroVideo = exports.ViroText = exports.ViroSpotLight = exports.ViroSpinner = exports.ViroSphere = exports.ViroSpatialSound = void 0;
|
|
5
5
|
/**
|
|
6
6
|
* Copyright (c) 2016-present, Viro Media, Inc.
|
|
7
7
|
* All rights reserved.
|
|
@@ -83,6 +83,8 @@ const ViroMaterialVideo_1 = require("./components/ViroMaterialVideo");
|
|
|
83
83
|
Object.defineProperty(exports, "ViroMaterialVideo", { enumerable: true, get: function () { return ViroMaterialVideo_1.ViroMaterialVideo; } });
|
|
84
84
|
const ViroCameraTexture_1 = require("./components/ViroCameraTexture");
|
|
85
85
|
Object.defineProperty(exports, "ViroCameraTexture", { enumerable: true, get: function () { return ViroCameraTexture_1.ViroCameraTexture; } });
|
|
86
|
+
const ViroObjectDetector_1 = require("./components/ViroObjectDetector");
|
|
87
|
+
Object.defineProperty(exports, "ViroObjectDetector", { enumerable: true, get: function () { return ViroObjectDetector_1.ViroObjectDetector; } });
|
|
86
88
|
const ViroNode_1 = require("./components/ViroNode");
|
|
87
89
|
Object.defineProperty(exports, "ViroNode", { enumerable: true, get: function () { return ViroNode_1.ViroNode; } });
|
|
88
90
|
const ViroOmniLight_1 = require("./components/ViroOmniLight");
|
package/dist/plugins/withViro.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEFAULTS = void 0;
|
|
4
|
-
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
4
|
const withViroAndroid_1 = require("./withViroAndroid");
|
|
6
5
|
const withViroIos_1 = require("./withViroIos");
|
|
7
6
|
const CAMERA_USAGE = "Allow $(PRODUCT_NAME) to use your camera";
|
|
@@ -34,20 +33,8 @@ exports.DEFAULTS = {
|
|
|
34
33
|
* @returns expo configuration
|
|
35
34
|
*/
|
|
36
35
|
const withViro = (config, props) => {
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
plugin[0] === "expo-dev-client" &&
|
|
40
|
-
plugin[1]?.newArchEnabled === true) || config.newArchEnabled === true;
|
|
41
|
-
if (!newArchEnabled) {
|
|
42
|
-
config_plugins_1.WarningAggregator.addWarningAndroid("withViro", "ViroReact requires React Native New Architecture (Fabric) to be enabled. " +
|
|
43
|
-
"Please enable New Architecture in your app configuration. " +
|
|
44
|
-
'Add "newArchEnabled": true to your app.json/app.config.js expo configuration, ' +
|
|
45
|
-
"or ensure your React Native project has New Architecture enabled.");
|
|
46
|
-
config_plugins_1.WarningAggregator.addWarningIOS("withViro", "ViroReact requires React Native New Architecture (Fabric) to be enabled. " +
|
|
47
|
-
"Please enable New Architecture in your app configuration. " +
|
|
48
|
-
'Add "newArchEnabled": true to your app.json/app.config.js expo configuration, ' +
|
|
49
|
-
"or ensure your React Native project has New Architecture enabled.");
|
|
50
|
-
}
|
|
36
|
+
// New Architecture is the only architecture in Expo SDK 53+ (and the React
|
|
37
|
+
// Native versions ViroReact supports), so there is nothing to validate here.
|
|
51
38
|
// Apply platform-specific configurations
|
|
52
39
|
config = (0, withViroIos_1.withViroIos)(config, props);
|
|
53
40
|
config = (0, withViroAndroid_1.withViroAndroid)(config, props);
|
|
@@ -101,11 +101,6 @@ const withBranchAndroid = (config) => {
|
|
|
101
101
|
]);
|
|
102
102
|
};
|
|
103
103
|
const withViroProjectBuildGradle = (config) => (0, config_plugins_1.withProjectBuildGradle)(config, async (newConfig) => {
|
|
104
|
-
// Enforce New Architecture requirement
|
|
105
|
-
if (!newConfig.modResults.contents.includes("newArchEnabled=true")) {
|
|
106
|
-
config_plugins_1.WarningAggregator.addWarningAndroid("withViroAndroid", "ViroReact requires New Architecture to be enabled. " +
|
|
107
|
-
'Please add "newArchEnabled=true" to your android/gradle.properties file.');
|
|
108
|
-
}
|
|
109
104
|
newConfig.modResults.contents = newConfig.modResults.contents.replace(/minSdkVersion.*/, `minSdkVersion = 24`);
|
|
110
105
|
// Ensure New Architecture is enabled
|
|
111
106
|
//if (!newConfig.modResults.contents.includes("newArchEnabled=true")) {
|
|
@@ -35,12 +35,6 @@ const withViroPods = (config) => {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
fs_1.default.readFile(`${root}/Podfile`, "utf-8", (err, data) => {
|
|
38
|
-
// Check for New Architecture environment variable
|
|
39
|
-
if (!data.includes('ENV["RCT_NEW_ARCH_ENABLED"]') &&
|
|
40
|
-
!data.includes("RCT_NEW_ARCH_ENABLED=1")) {
|
|
41
|
-
config_plugins_1.WarningAggregator.addWarningIOS("withViroIos", "ViroReact requires New Architecture to be enabled. " +
|
|
42
|
-
"Please set RCT_NEW_ARCH_ENABLED=1 in your ios/.xcode.env file.");
|
|
43
|
-
}
|
|
44
38
|
// ViroReact with integrated Fabric support
|
|
45
39
|
let viroPods = ` # ViroReact with integrated New Architecture (Fabric) support\n` +
|
|
46
40
|
` # Automatically includes Fabric components when RCT_NEW_ARCH_ENABLED=1\n` +
|
package/index.ts
CHANGED
|
@@ -48,6 +48,8 @@ import {
|
|
|
48
48
|
import { ViroMaterialVideo } from "./components/ViroMaterialVideo";
|
|
49
49
|
import { ViroCameraTexture } from "./components/ViroCameraTexture";
|
|
50
50
|
export type { ViroCameraPosition, ViroCameraReadyEvent } from "./components/ViroCameraTexture";
|
|
51
|
+
import { ViroObjectDetector } from "./components/ViroObjectDetector";
|
|
52
|
+
export type { ViroDetectorMode, ViroDetectedObject, ViroDetectionBoundingBox, ViroDetectionEvent, ViroDetectorReadyEvent, ViroDetectorErrorEvent } from "./components/ViroObjectDetector";
|
|
51
53
|
import { ViroNode } from "./components/ViroNode";
|
|
52
54
|
import { ViroOmniLight } from "./components/ViroOmniLight";
|
|
53
55
|
import { ViroOrbitCamera } from "./components/ViroOrbitCamera";
|
|
@@ -223,6 +225,7 @@ export {
|
|
|
223
225
|
ViroARCamera,
|
|
224
226
|
ViroMaterialVideo,
|
|
225
227
|
ViroCameraTexture,
|
|
228
|
+
ViroObjectDetector,
|
|
226
229
|
ViroNode,
|
|
227
230
|
ViroOmniLight,
|
|
228
231
|
ViroOrbitCamera,
|
package/ios/ViroReact.podspec
CHANGED
|
@@ -18,16 +18,20 @@ Pod::Spec.new do |s|
|
|
|
18
18
|
# visionOS: CompositorServices drives the immersive render loop.
|
|
19
19
|
s.visionos.frameworks = ['Metal', 'MetalKit', 'CompositorServices', 'ARKit']
|
|
20
20
|
|
|
21
|
+
# iOS: frameworks required by source files compiled from the pod
|
|
22
|
+
# (VRTObjectDetectorView uses AVFoundation + Accelerate; CoreVideo for CVPixelBuffer)
|
|
23
|
+
s.ios.frameworks = ['AVFoundation', 'Accelerate', 'CoreVideo']
|
|
24
|
+
|
|
21
25
|
# Base source files (always included)
|
|
22
26
|
source_files_array = ['ViroReact/**/*.{h,m,mm,swift}']
|
|
23
27
|
header_files_array = ['ViroReact/**/*.h']
|
|
24
|
-
|
|
28
|
+
|
|
25
29
|
# Include dist files if they exist (for release builds)
|
|
26
30
|
if File.exist?(File.join(__dir__, 'dist/include'))
|
|
27
31
|
source_files_array << 'dist/include/**/*.{h,m,mm}'
|
|
28
32
|
header_files_array << 'dist/include/*.h'
|
|
29
33
|
end
|
|
30
|
-
|
|
34
|
+
|
|
31
35
|
s.source_files = source_files_array
|
|
32
36
|
s.public_header_files = header_files_array
|
|
33
37
|
|
|
@@ -39,15 +43,30 @@ Pod::Spec.new do |s|
|
|
|
39
43
|
if File.exist?(File.join(__dir__, 'dist/lib/libViroReact.a'))
|
|
40
44
|
s.vendored_libraries = 'dist/lib/libViroReact.a'
|
|
41
45
|
end
|
|
42
|
-
|
|
46
|
+
|
|
43
47
|
# React Native dependencies
|
|
44
48
|
s.dependency 'React-Core'
|
|
45
|
-
|
|
49
|
+
|
|
50
|
+
# ONNX Runtime is distributed as a vendored dynamic xcframework (onnxruntime.xcframework).
|
|
51
|
+
# When the xcframework is present in ios/dist/Frameworks/, enable inference by setting:
|
|
52
|
+
# GCC_PREPROCESSOR_DEFINITIONS = $(inherited) VIRO_ONNXRUNTIME_AVAILABLE=1
|
|
53
|
+
# Until then, VRTObjectDetectorView compiles with the camera pipeline active
|
|
54
|
+
# and inference returning empty results.
|
|
55
|
+
if File.exist?(File.join(__dir__, 'dist/Frameworks/onnxruntime.xcframework'))
|
|
56
|
+
s.vendored_frameworks = [
|
|
57
|
+
'dist/ViroRenderer/ViroKit.framework',
|
|
58
|
+
'dist/Frameworks/onnxruntime.xcframework'
|
|
59
|
+
]
|
|
60
|
+
s.pod_target_xcconfig = {
|
|
61
|
+
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) RCT_NEW_ARCH_ENABLED=1 VIRO_ONNXRUNTIME_AVAILABLE=1'
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
46
65
|
# Fabric dependencies
|
|
47
66
|
s.dependency 'React-RCTFabric'
|
|
48
67
|
s.dependency 'React-Fabric'
|
|
49
68
|
s.dependency 'React-FabricComponents'
|
|
50
|
-
|
|
69
|
+
|
|
51
70
|
# Fabric-specific build configuration
|
|
52
71
|
s.pod_target_xcconfig = {
|
|
53
72
|
'SWIFT_VERSION' => '5.0',
|
|
@@ -63,5 +82,5 @@ Pod::Spec.new do |s|
|
|
|
63
82
|
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) RCT_NEW_ARCH_ENABLED=1',
|
|
64
83
|
'OTHER_CPLUSPLUSFLAGS' => '$(inherited) -std=c++17'
|
|
65
84
|
}
|
|
66
|
-
|
|
85
|
+
|
|
67
86
|
end
|
package/ios/dist/ViroRenderer/ViroKit.framework/ARCoreCoreMLSemanticsResources.bundle/Info.plist
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -144,6 +144,15 @@ private:
|
|
|
144
144
|
*/
|
|
145
145
|
float sampleDepthTextureAtUV(std::shared_ptr<VROTexture> texture, float u, float v) const;
|
|
146
146
|
|
|
147
|
+
/*
|
|
148
|
+
Unproject a camera-image-space point (normalized [0,1] in ARKit's landscape image
|
|
149
|
+
space, the same space used for [ARFrame hitTest:]) at a given metric depth (meters
|
|
150
|
+
along the optical axis) to a world-space position. Returns false if camera
|
|
151
|
+
intrinsics are unavailable. Used to build a depth-derived DepthPoint hit result.
|
|
152
|
+
*/
|
|
153
|
+
bool unprojectToWorld(VROVector3f cameraImagePoint, float depthMeters,
|
|
154
|
+
VROVector3f &outWorld) const;
|
|
155
|
+
|
|
147
156
|
};
|
|
148
157
|
|
|
149
158
|
#endif
|
|
@@ -44,6 +44,12 @@ public:
|
|
|
44
44
|
virtual void onTrackingUpdated(VROARTrackingState state, VROARTrackingStateReason reason) = 0;
|
|
45
45
|
virtual void onAmbientLightUpdate(float ambientLightIntensity, VROVector3f ambientLightColor) = 0;
|
|
46
46
|
virtual void onWorldMeshUpdated(const VROWorldMeshStats& stats) {}
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
Called once when depth data (LiDAR or monocular) first becomes available for the
|
|
50
|
+
session, i.e. hit tests can now return DepthPoints. Optional.
|
|
51
|
+
*/
|
|
52
|
+
virtual void onDepthReady() {}
|
|
47
53
|
};
|
|
48
54
|
|
|
49
55
|
class VROARScene : public VROScene {
|
|
@@ -113,6 +119,12 @@ public:
|
|
|
113
119
|
void setDelegate(std::shared_ptr<VROARSceneDelegate> delegate);
|
|
114
120
|
void setTrackingState(VROARTrackingState state, VROARTrackingStateReason reason, bool force);
|
|
115
121
|
|
|
122
|
+
/*
|
|
123
|
+
Notify the delegate that depth data is now available. Fires the delegate's
|
|
124
|
+
onDepthReady() exactly once per scene; subsequent calls are no-ops.
|
|
125
|
+
*/
|
|
126
|
+
void notifyDepthReady();
|
|
127
|
+
|
|
116
128
|
/*
|
|
117
129
|
Get the ambient light estimate of the scene.
|
|
118
130
|
*/
|
|
@@ -180,7 +192,8 @@ private:
|
|
|
180
192
|
std::shared_ptr<VRONode> _pointCloudNode;
|
|
181
193
|
std::shared_ptr<VROFixedParticleEmitter> _pointCloudEmitter;
|
|
182
194
|
std::weak_ptr<VROARSceneDelegate> _delegate;
|
|
183
|
-
|
|
195
|
+
bool _depthReadyNotified = false;
|
|
196
|
+
|
|
184
197
|
/*
|
|
185
198
|
Ambient light estimation. The intensity is in lumens and the color is in linear space.
|
|
186
199
|
*/
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
- (void)onAnchorFound:(std::shared_ptr<VROARAnchor>)anchor;
|
|
39
39
|
- (void)onAnchorUpdated:(std::shared_ptr<VROARAnchor>)anchor;
|
|
40
40
|
- (void)onAnchorRemoved:(std::shared_ptr<VROARAnchor>)anchor;
|
|
41
|
+
@optional
|
|
42
|
+
- (void)onDepthReady;
|
|
41
43
|
@end
|
|
42
44
|
|
|
43
45
|
class VROARSceneDelegateiOS : public VROARSceneDelegate, public VROARDeclarativeSessionDelegate {
|
|
@@ -71,6 +73,12 @@ public:
|
|
|
71
73
|
[_delegate onAmbientLightUpdate:intensity color:color];
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
virtual void onDepthReady() {
|
|
77
|
+
if ([_delegate respondsToSelector:@selector(onDepthReady)]) {
|
|
78
|
+
[_delegate onDepthReady];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
74
82
|
private:
|
|
75
83
|
__weak id<VROARSceneDelegateProtocol> _delegate;
|
|
76
84
|
};
|
|
@@ -188,7 +188,11 @@ private:
|
|
|
188
188
|
static bool processAnimations(const tinygltf::Model &gModel);
|
|
189
189
|
static bool processKeyFrameAnimations(const tinygltf::Model &gModel,
|
|
190
190
|
std::map<int, std::map<int, std::vector<int>>> &gltfAnimatedNodes);
|
|
191
|
-
|
|
191
|
+
// Resample all of a skin's animation channels onto a single common time-grid and merge each
|
|
192
|
+
// joint's per-property channels into one index-aligned VROKeyframeAnimation. Replaces the old
|
|
193
|
+
// drop-mismatched-channels flatten (VIRO-5741) so mixed STEP/LINEAR, multi-time-grid glTF
|
|
194
|
+
// animations (e.g. Blender exports) play fully instead of freezing.
|
|
195
|
+
static void resampleSkeletalChannelsToCommonGrid(
|
|
192
196
|
std::map<int, std::pair<int, std::vector<int>>> &skeletalAnimToNodeSkinPair,
|
|
193
197
|
int skinIndex);
|
|
194
198
|
static std::shared_ptr<VROKeyframeAnimation> convertChannelToKeyFrameAnimation(
|
|
@@ -135,6 +135,16 @@ public:
|
|
|
135
135
|
*/
|
|
136
136
|
void update(const VROARFrame *frame);
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Run a single throwaway inference on a blank image to force CoreML / Neural Engine
|
|
140
|
+
* model specialization up front. Without this, the FIRST real inference pays the
|
|
141
|
+
* full ANE compile cost (many seconds on A-series chips) — the dominant cause of the
|
|
142
|
+
* long delay before the first depth frame appears. Safe to call once right after
|
|
143
|
+
* initWithModel(); runs asynchronously on the depth queue and does not touch the
|
|
144
|
+
* live depth buffers (it uses a private throwaway request).
|
|
145
|
+
*/
|
|
146
|
+
void warmup();
|
|
147
|
+
|
|
138
148
|
#pragma mark - Depth Output
|
|
139
149
|
|
|
140
150
|
/**
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
//
|
|
2
|
+
// VROObjectDetector.h
|
|
3
|
+
// ViroRenderer
|
|
4
|
+
//
|
|
5
|
+
// Copyright © 2026 ReactVision. All rights reserved.
|
|
6
|
+
//
|
|
7
|
+
// Permission is hereby granted, free of charge, to any person obtaining
|
|
8
|
+
// a copy of this software and associated documentation files (the
|
|
9
|
+
// "Software"), to deal in the Software without restriction, including
|
|
10
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
|
11
|
+
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
12
|
+
// permit persons to whom the Software is furnished to do so, subject to
|
|
13
|
+
// the following conditions:
|
|
14
|
+
//
|
|
15
|
+
// The above copyright notice and this permission notice shall be included
|
|
16
|
+
// in all copies or substantial portions of the Software.
|
|
17
|
+
//
|
|
18
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
20
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
21
|
+
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
22
|
+
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
23
|
+
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
24
|
+
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
25
|
+
|
|
26
|
+
#ifndef VROObjectDetector_h
|
|
27
|
+
#define VROObjectDetector_h
|
|
28
|
+
|
|
29
|
+
#include <string>
|
|
30
|
+
#include <vector>
|
|
31
|
+
#include <functional>
|
|
32
|
+
#include <memory>
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
Bounding box in normalized image space [0, 1].
|
|
36
|
+
Origin is top-left corner of the image.
|
|
37
|
+
*/
|
|
38
|
+
struct VRODetectionBoundingBox {
|
|
39
|
+
float x; // left edge
|
|
40
|
+
float y; // top edge
|
|
41
|
+
float width;
|
|
42
|
+
float height;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
struct VRODetectedObject {
|
|
46
|
+
std::string label;
|
|
47
|
+
float confidence;
|
|
48
|
+
VRODetectionBoundingBox boundingBox;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
Inference mode matching YOLOE's three prompting strategies:
|
|
53
|
+
- PromptFree: LRPC head, 4,585 built-in RAM++ categories, no runtime prompt needed.
|
|
54
|
+
- Text: RepRTA, detect arbitrary categories given a list of text labels.
|
|
55
|
+
- Visual: SAVPE, detect objects similar to a reference image crop.
|
|
56
|
+
*/
|
|
57
|
+
enum class VRODetectorMode {
|
|
58
|
+
PromptFree,
|
|
59
|
+
Text,
|
|
60
|
+
Visual,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
using VRODetectionCallback = std::function<void(const std::vector<VRODetectedObject> &)>;
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
Abstract base class for on-device object detectors.
|
|
67
|
+
|
|
68
|
+
Platform implementations (iOS: CoreML / ONNX Runtime, Android: ONNX Runtime)
|
|
69
|
+
subclass this and implement loadModel() and detectInBuffer(). The bridge layer
|
|
70
|
+
owns the camera pipeline and calls detectInBuffer() on each sampled frame.
|
|
71
|
+
*/
|
|
72
|
+
class VROObjectDetector {
|
|
73
|
+
public:
|
|
74
|
+
virtual ~VROObjectDetector() {}
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
Load the model from the given path.
|
|
78
|
+
On iOS: path to a .mlpackage (CoreML) or .onnx file.
|
|
79
|
+
On Android: path to a .onnx file inside the app's assets or files dir.
|
|
80
|
+
Returns true on success.
|
|
81
|
+
*/
|
|
82
|
+
virtual bool loadModel(const std::string &modelPath) = 0;
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
Run detection on a raw RGB pixel buffer.
|
|
86
|
+
- pixels: pointer to contiguous RGB888 data (row-major)
|
|
87
|
+
- width / height: image dimensions in pixels
|
|
88
|
+
Results are delivered asynchronously via the detection callback.
|
|
89
|
+
*/
|
|
90
|
+
virtual void detectInBuffer(const uint8_t *pixels, int width, int height) = 0;
|
|
91
|
+
|
|
92
|
+
// --- configuration (call before loadModel or between frames) ---
|
|
93
|
+
|
|
94
|
+
void setMode(VRODetectorMode mode) {
|
|
95
|
+
_mode = mode;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
Text categories for Text mode (e.g. {"chair", "person", "laptop"}).
|
|
100
|
+
Ignored in PromptFree and Visual modes.
|
|
101
|
+
*/
|
|
102
|
+
void setCategories(const std::vector<std::string> &categories) {
|
|
103
|
+
_categories = categories;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
void setConfidenceThreshold(float threshold) {
|
|
107
|
+
_confidenceThreshold = threshold;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
NMS IoU threshold used during post-processing.
|
|
112
|
+
*/
|
|
113
|
+
void setIouThreshold(float threshold) {
|
|
114
|
+
_iouThreshold = threshold;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void setCallback(VRODetectionCallback callback) {
|
|
118
|
+
_callback = callback;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
VRODetectorMode getMode() const { return _mode; }
|
|
122
|
+
float getConfidenceThreshold() const { return _confidenceThreshold; }
|
|
123
|
+
float getIouThreshold() const { return _iouThreshold; }
|
|
124
|
+
const std::vector<std::string> &getCategories() const { return _categories; }
|
|
125
|
+
|
|
126
|
+
protected:
|
|
127
|
+
VRODetectorMode _mode = VRODetectorMode::PromptFree;
|
|
128
|
+
std::vector<std::string> _categories;
|
|
129
|
+
float _confidenceThreshold = 0.4f;
|
|
130
|
+
float _iouThreshold = 0.45f;
|
|
131
|
+
VRODetectionCallback _callback;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
#endif /* VROObjectDetector_h */
|
|
Binary file
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
dependencies: \
|
|
2
2
|
/Users/dorantes/Documents/ViroWorkspace/virocore/ViroRenderer/Shaders.metal \
|
|
3
|
-
/private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.6.42.0.
|
|
3
|
+
/private/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.6.42.0.h0RVpk/Metal.xctoolchain/usr/metal/32023/lib/clang/32023.883/include/metal/module.modulemap \
|
|
4
4
|
/Users/dorantes/Documents/ViroWorkspace/virocore/ViroRenderer/VROSharedStructures.h \
|
|
5
5
|
/Users/dorantes/Documents/ViroWorkspace/virocore/ViroRenderer/VRODefines.h
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = 'ViroKit'
|
|
3
|
+
s.version = '1.0'
|
|
4
|
+
s.summary = 'Framework containing the ViroRenderer (visionOS / xros)'
|
|
5
|
+
s.description = <<-DESC
|
|
6
|
+
ViroKit is the core rendering framework for ViroReact.
|
|
7
|
+
|
|
8
|
+
This is the visionOS (xros) distribution: a Metal-only build of the
|
|
9
|
+
ViroRenderer packaged as an xcframework with both the device (xros-arm64)
|
|
10
|
+
and simulator (xros-arm64_x86_64-simulator) slices. It plugs into the
|
|
11
|
+
CompositorServices immersive render loop via VRORendererBridge.
|
|
12
|
+
DESC
|
|
13
|
+
s.source = { :path => '.' } # source is required, but path is defined in the user's Podfile (this value is ignored).
|
|
14
|
+
s.vendored_frameworks = 'ViroKit.xcframework'
|
|
15
|
+
s.homepage = 'https://reactvision.xyz'
|
|
16
|
+
s.license = {:type => 'Copyright', :text => "Copyright 2025 ReactVision" }
|
|
17
|
+
s.author = 'ReactVision'
|
|
18
|
+
s.requires_arc = true
|
|
19
|
+
s.platform = :visionos, '1.0'
|
|
20
|
+
s.visionos.deployment_target = '1.0'
|
|
21
|
+
s.dependency 'React'
|
|
22
|
+
|
|
23
|
+
# visionOS requires CompositorServices for the immersive render loop.
|
|
24
|
+
# Metal and MetalKit are available on both iOS and visionOS; ARKit provides
|
|
25
|
+
# world / hand tracking.
|
|
26
|
+
s.visionos.frameworks = ['Metal', 'MetalKit', 'CompositorServices', 'ARKit']
|
|
27
|
+
end
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
@property (nonatomic, copy, nullable) NSArray<NSString *> *anchorDetectionTypes;
|
|
37
37
|
@property (nonatomic, copy, nullable) RCTDirectEventBlock onTrackingUpdatedViro;
|
|
38
38
|
@property (nonatomic, copy, nullable) RCTDirectEventBlock onAmbientLightUpdateViro;
|
|
39
|
+
@property (nonatomic, copy, nullable) RCTDirectEventBlock onDepthReadyViro;
|
|
39
40
|
|
|
40
41
|
@property (nonatomic, copy, nullable) RCTDirectEventBlock onAnchorFoundViro;
|
|
41
42
|
@property (nonatomic, copy, nullable) RCTDirectEventBlock onAnchorUpdatedViro;
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"main": "dist/index.js",
|
|
4
4
|
"module": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.57.0",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
"prepare": "npm run build"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"expo": ">=
|
|
31
|
-
"react
|
|
30
|
+
"expo": ">=55.0.0 <57.0.0",
|
|
31
|
+
"react": ">=18.0.0",
|
|
32
|
+
"react-native": ">=0.83.0 <0.86.0"
|
|
32
33
|
},
|
|
33
34
|
"engines": {
|
|
34
|
-
"react-native": ">=0.
|
|
35
|
+
"react-native": ">=0.83.0 <0.86.0"
|
|
35
36
|
},
|
|
36
37
|
"peerDependenciesMeta": {
|
|
37
38
|
"expo": {
|
|
@@ -56,31 +57,27 @@
|
|
|
56
57
|
"bin",
|
|
57
58
|
"LICENSE"
|
|
58
59
|
],
|
|
59
|
-
"dependencies": {
|
|
60
|
-
"@expo/config-plugins": "^9.0.14",
|
|
61
|
-
"react": "~19.2.0",
|
|
62
|
-
"react-native-gradle-plugin": "^0.71.19"
|
|
63
|
-
},
|
|
64
60
|
"devDependencies": {
|
|
65
61
|
"@babel/core": "^7.25.2",
|
|
66
62
|
"@babel/preset-env": "^7.25.3",
|
|
67
63
|
"@babel/preset-typescript": "^7.26.0",
|
|
64
|
+
"@expo/config-plugins": "~56.0.8",
|
|
68
65
|
"@jest/globals": "^29.7.0",
|
|
69
|
-
"@react-native-community/cli": "^
|
|
70
|
-
"@react-native-community/cli-platform-android": "^
|
|
71
|
-
"@react-native-community/cli-platform-ios": "^
|
|
72
|
-
"@react-native/babel-preset": "^0.
|
|
73
|
-
"@react-native/eslint-config": "^0.
|
|
74
|
-
"@react-native/metro-config": "^0.
|
|
75
|
-
"@react-native/typescript-config": "^0.
|
|
66
|
+
"@react-native-community/cli": "^20.1.3",
|
|
67
|
+
"@react-native-community/cli-platform-android": "^20.1.3",
|
|
68
|
+
"@react-native-community/cli-platform-ios": "^20.1.3",
|
|
69
|
+
"@react-native/babel-preset": "^0.85.3",
|
|
70
|
+
"@react-native/eslint-config": "^0.85.3",
|
|
71
|
+
"@react-native/metro-config": "^0.85.3",
|
|
72
|
+
"@react-native/typescript-config": "^0.85.3",
|
|
76
73
|
"@types/babel__core": "^7.20.5",
|
|
77
74
|
"@types/node": "^22.13.1",
|
|
78
|
-
"@types/react": "~19.2.
|
|
79
|
-
"@types/react-native": "^0.73.0",
|
|
75
|
+
"@types/react": "~19.2.17",
|
|
80
76
|
"babel-jest": "^29.7.0",
|
|
81
|
-
"expo": "~
|
|
77
|
+
"expo": "~56.0.9",
|
|
82
78
|
"jest": "^29.7.0",
|
|
83
|
-
"react
|
|
79
|
+
"react": "~19.2.3",
|
|
80
|
+
"react-native": "~0.85.3",
|
|
84
81
|
"release-it": "^17.1.1",
|
|
85
82
|
"ts-node": "^10.9.2",
|
|
86
83
|
"typescript": "^5.3.0"
|