diff --git a/ViroRenderer/VROARSession.h b/ViroRenderer/VROARSession.h index 71abb88e0..b40bf52dd 100644 --- a/ViroRenderer/VROARSession.h +++ b/ViroRenderer/VROARSession.h @@ -571,6 +571,11 @@ class VROARSession { std::function callback) { if (callback) callback(false, "Not supported"); } + virtual void rvGetScene( + const std::string& sceneId, + std::function callback) { + if (callback) callback(false, "", "Not supported"); + } virtual void rvGetSceneAssets( const std::string& sceneId, std::function callback) { diff --git a/android/sharedCode/src/main/cpp/arcore/ARSceneController_JNI.cpp b/android/sharedCode/src/main/cpp/arcore/ARSceneController_JNI.cpp index 376634419..1e9dbfb16 100644 --- a/android/sharedCode/src/main/cpp/arcore/ARSceneController_JNI.cpp +++ b/android/sharedCode/src/main/cpp/arcore/ARSceneController_JNI.cpp @@ -922,6 +922,29 @@ VRO_METHOD(void, nativeRvGetSceneAssets)(VRO_ARGS }); } +VRO_METHOD(void, nativeRvGetScene)(VRO_ARGS + VRO_REF(VROARSceneController) arSceneControllerPtr, + jstring key_j, + jstring sceneId_j) { + std::string keyStr = VRO_STRING_STL(key_j); + std::string sceneIdStr = VRO_STRING_STL(sceneId_j); + std::weak_ptr arScene_w = std::dynamic_pointer_cast( + VRO_REF_GET(VROARSceneController, arSceneControllerPtr)->getScene()); + VRO_WEAK weakObj = VRO_NEW_WEAK_GLOBAL_REF(obj); + VROPlatformDispatchAsyncRenderer([arScene_w, weakObj, keyStr, sceneIdStr] { + std::shared_ptr arScene = arScene_w.lock(); + std::shared_ptr arSession = arScene ? arScene->getARSession() : nullptr; + if (!arSession) { + rvFireCloudResult(weakObj, keyStr, false, "", "AR session not available"); + return; + } + arSession->rvGetScene(sceneIdStr, + [weakObj, keyStr](bool success, std::string jsonData, std::string error) { + rvFireCloudResult(weakObj, keyStr, success, jsonData, error); + }); + }); +} + VRO_METHOD(void, nativeResetPointCloudSurface)(VRO_ARGS VRO_REF(VROARSceneController) arSceneControllerPtr) { std::weak_ptr arScene_w = std::dynamic_pointer_cast( @@ -1465,22 +1488,24 @@ VRO_METHOD(void, nativeResolveCloudAnchor)(VRO_ARGS VRO_METHOD(void, nativeSetReactVisionConfig)(VRO_ARGS VRO_REF(VROARSceneController) sceneController_j, VRO_STRING apiKey_j, - VRO_STRING projectId_j) { + VRO_STRING projectId_j, + VRO_STRING endpoint_j) { VRO_METHOD_PREAMBLE; std::string apiKey = VRO_STRING_STL(apiKey_j); std::string projectId = VRO_STRING_STL(projectId_j); + std::string endpoint = VRO_STRING_STL(endpoint_j); std::weak_ptr scene_w = std::dynamic_pointer_cast( VRO_REF_GET(VROARSceneController, sceneController_j)->getScene()); - VROPlatformDispatchAsyncRenderer([scene_w, apiKey, projectId] { + VROPlatformDispatchAsyncRenderer([scene_w, apiKey, projectId, endpoint] { std::shared_ptr scene = scene_w.lock(); if (!scene) return; std::shared_ptr session = std::dynamic_pointer_cast(scene->getARSession()); if (!session) return; - session->setReactVisionConfig(apiKey, projectId); + session->setReactVisionConfig(apiKey, projectId, endpoint); }); } diff --git a/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.cpp b/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.cpp index aa2baf31e..522851679 100644 --- a/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.cpp +++ b/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.cpp @@ -279,9 +279,11 @@ bool VROARSessionARCore::setAnchorDetection( } void VROARSessionARCore::setReactVisionConfig(const std::string &apiKey, - const std::string &projectId) { + const std::string &projectId, + const std::string &endpoint) { _rvApiKey = apiKey; _rvProjectId = projectId; + _rvEndpoint = endpoint; // Credentials supplied — activate the ReactVision cloud anchor provider. setCloudAnchorProvider(VROCloudAnchorProvider::ReactVision); #if RVCCA_AVAILABLE @@ -292,6 +294,7 @@ void VROARSessionARCore::setReactVisionConfig(const std::string &apiKey, ReactVisionCCA::RVCCAGeospatialProvider::Config cfg; cfg.apiKey = _rvApiKey; cfg.projectId = _rvProjectId; + if (!_rvEndpoint.empty()) cfg.endpoint = _rvEndpoint; _geospatialProviderRV = std::make_shared(cfg); pinfo("VROARSessionARCore: ReactVision Geospatial provider initialized"); } @@ -311,7 +314,7 @@ void VROARSessionARCore::setCloudAnchorProvider( // renderer-task batch. if (!_cloudAnchorProviderRV && !_rvApiKey.empty() && !_rvProjectId.empty()) { _cloudAnchorProviderRV = std::make_shared( - shared_from_this(), _rvApiKey, _rvProjectId); + shared_from_this(), _rvApiKey, _rvProjectId, _rvEndpoint); // Improvement 1 + 6B: register as frame listener so onFrameDidRender() // drives multi-frame host accumulation and resolve localization. if (_synchronizer) { @@ -2497,6 +2500,26 @@ void VROARSessionARCore::rvTrackCloudAnchorResolution( if (callback) callback(false, "ReactVision cloud anchor provider not available"); } +void VROARSessionARCore::rvGetScene( + const std::string& sceneId, + std::function callback) { +#if RVCCA_AVAILABLE + if (_cloudAnchorProviderRV) { + auto p = _cloudAnchorProviderRV->getProvider(); + if (p) { + p->getScene(sceneId, + [callback](ReactVisionCCA::ApiResult r) { + if (callback) { + callback(r.success, r.data, r.success ? "" : r.error.message); + } + }); + return; + } + } +#endif + if (callback) callback(false, "", "ReactVision cloud anchor provider not available"); +} + void VROARSessionARCore::rvGetSceneAssets( const std::string& sceneId, std::function callback) { diff --git a/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.h b/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.h index 1e2a041c5..c3e76480f 100644 --- a/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.h +++ b/android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.h @@ -82,7 +82,8 @@ class VROARSessionARCore : public VROARSession, Must be called before setCloudAnchorProvider(ReactVision). Reads RVApiKey / RVProjectId from AndroidManifest meta-data if not called. */ - void setReactVisionConfig(const std::string &apiKey, const std::string &projectId); + void setReactVisionConfig(const std::string &apiKey, const std::string &projectId, + const std::string &endpoint = ""); /* Update the cached GPS pose used by getCameraGeospatialPose() when the @@ -224,6 +225,8 @@ class VROARSessionARCore : public VROARSession, double confidence, int matchCount, int inlierCount, int processingTimeMs, const std::string& platform, const std::string& externalUserId, std::function callback) override; + void rvGetScene(const std::string& sceneId, + std::function callback) override; void rvGetSceneAssets(const std::string& sceneId, std::function callback) override; @@ -369,6 +372,7 @@ class VROARSessionARCore : public VROARSession, std::shared_ptr _cloudAnchorProviderRV; std::string _rvApiKey; std::string _rvProjectId; + std::string _rvEndpoint; /* Manages geospatial anchors via ReactVision backend. diff --git a/android/sharedCode/src/main/cpp/arcore/VROCloudAnchorProviderReactVision.cpp b/android/sharedCode/src/main/cpp/arcore/VROCloudAnchorProviderReactVision.cpp index 0b0746f33..d1ebf4a14 100644 --- a/android/sharedCode/src/main/cpp/arcore/VROCloudAnchorProviderReactVision.cpp +++ b/android/sharedCode/src/main/cpp/arcore/VROCloudAnchorProviderReactVision.cpp @@ -47,6 +47,7 @@ class VROCloudAnchorProviderReactVision::Impl { ReactVisionCCA::RVCCACloudAnchorProvider::Config cfg; cfg.apiKey = apiKey; cfg.projectId = projectId; + if (!endpoint.empty()) cfg.endpoint = endpoint; // ARCore feature points have much lower confidence values than ARKit (typically // 0.1–0.5 vs 0.8–1.0). The default minPointConfidence of 0.5 discards the diff --git a/android/sharedCode/src/main/java/com/viro/core/ARScene.java b/android/sharedCode/src/main/java/com/viro/core/ARScene.java index 945dc66a5..f5e6d31ac 100644 --- a/android/sharedCode/src/main/java/com/viro/core/ARScene.java +++ b/android/sharedCode/src/main/java/com/viro/core/ARScene.java @@ -929,7 +929,11 @@ public void hostCloudAnchor(ARAnchor anchor, int ttlDays, CloudAnchorHostListene * @hide */ public void setReactVisionConfig(String apiKey, String projectId) { - nativeSetReactVisionConfig(mNativeRef, apiKey, projectId); + setReactVisionConfig(apiKey, projectId, ""); + } + + public void setReactVisionConfig(String apiKey, String projectId, String endpoint) { + nativeSetReactVisionConfig(mNativeRef, apiKey, projectId, endpoint != null ? endpoint : ""); } public void setGeospatialAnchorProvider(String provider) { @@ -1389,6 +1393,12 @@ public void rvRemoveAssetFromCloudAnchor(String anchorId, String assetId, nativeRvRemoveAssetFromCloudAnchor(mNativeRef, key, anchorId, assetId); } + public void rvGetScene(String sceneId, RvCloudAnchorCallback callback) { + String key = "rvGetScene_" + System.nanoTime(); + mRvCloudCallbacks.put(key, callback); + nativeRvGetScene(mNativeRef, key, sceneId); + } + public void rvGetSceneAssets(String sceneId, RvCloudAnchorCallback callback) { String key = "rvGetSceneAssets_" + System.nanoTime(); mRvCloudCallbacks.put(key, callback); @@ -1633,7 +1643,7 @@ public void setWorldMeshConfig(int stride, float minConfidence, float maxDepth, private native void nativeRemoveARImageTargetDeclarative(long sceneControllerRef, long arImageTargetRef); private native void nativeHostCloudAnchor(long sceneControllerRef, String anchorId, int ttlDays); private native void nativeResolveCloudAnchor(long sceneControllerRef, String cloudAnchorId); - private native void nativeSetReactVisionConfig(long sceneControllerRef, String apiKey, String projectId); + private native void nativeSetReactVisionConfig(long sceneControllerRef, String apiKey, String projectId, String endpoint); private native void nativeSetGeospatialAnchorProvider(long sceneControllerRef, String provider); private native float nativeGetAmbientLightIntensity(long sceneControllerRef); private native long nativeCreateAnchoredNode(long sceneControllerRef, float px, float py, float pz, @@ -1696,6 +1706,7 @@ private native void nativeRvUpdateCloudAnchor(long sceneControllerRef, String ke private native void nativeRvFindNearbyCloudAnchors(long sceneControllerRef, String key, double lat, double lng, double radius, int limit); + private native void nativeRvGetScene(long sceneControllerRef, String key, String sceneId); private native void nativeRvGetSceneAssets(long sceneControllerRef, String key, String sceneId); private native void nativeRvAttachAssetToCloudAnchor(long sceneControllerRef, String key, String anchorId, String fileUrl, diff --git a/android/sharedCode/src/main/jniLibs/arm64-v8a/libreactvisioncca.so b/android/sharedCode/src/main/jniLibs/arm64-v8a/libreactvisioncca.so index c2efe22df..81672aeaa 100755 Binary files a/android/sharedCode/src/main/jniLibs/arm64-v8a/libreactvisioncca.so and b/android/sharedCode/src/main/jniLibs/arm64-v8a/libreactvisioncca.so differ diff --git a/android/sharedCode/src/main/jniLibs/armeabi-v7a/libreactvisioncca.so b/android/sharedCode/src/main/jniLibs/armeabi-v7a/libreactvisioncca.so index 300a10fdf..fbdcff2b0 100755 Binary files a/android/sharedCode/src/main/jniLibs/armeabi-v7a/libreactvisioncca.so and b/android/sharedCode/src/main/jniLibs/armeabi-v7a/libreactvisioncca.so differ diff --git a/ios/Libraries/reactvisioncca/arm64/libreactvisioncca.a b/ios/Libraries/reactvisioncca/arm64/libreactvisioncca.a index 732682a7f..46dd4e47a 100644 Binary files a/ios/Libraries/reactvisioncca/arm64/libreactvisioncca.a and b/ios/Libraries/reactvisioncca/arm64/libreactvisioncca.a differ diff --git a/ios/Libraries/reactvisioncca/arm64_simulator/libreactvisioncca.a b/ios/Libraries/reactvisioncca/arm64_simulator/libreactvisioncca.a index af5db5a12..dba18fe3a 100644 Binary files a/ios/Libraries/reactvisioncca/arm64_simulator/libreactvisioncca.a and b/ios/Libraries/reactvisioncca/arm64_simulator/libreactvisioncca.a differ diff --git a/ios/ViroKit/VROARSessioniOS.cpp b/ios/ViroKit/VROARSessioniOS.cpp index fc990d16a..4dec0f4d8 100644 --- a/ios/ViroKit/VROARSessioniOS.cpp +++ b/ios/ViroKit/VROARSessioniOS.cpp @@ -527,10 +527,12 @@ void VROARSessioniOS::setCloudAnchorProvider(VROCloudAnchorProvider provider) { // Initialize ReactVision cloud anchor provider; reads credentials from Info.plist NSString *apiKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RVApiKey"]; NSString *projectId = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RVProjectId"]; + NSString *endpoint = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RVEndpoint"]; + if (apiKey.length && projectId.length) { if (_cloudAnchorProviderRV == nil) { _cloudAnchorProviderRV = [[VROCloudAnchorProviderReactVision alloc] - initWithApiKey:apiKey projectId:projectId endpoint:nil]; + initWithApiKey:apiKey projectId:projectId endpoint:endpoint]; if (_cloudAnchorProviderRV) { pinfo("ReactVision Cloud Anchor provider initialized successfully"); } else { @@ -545,6 +547,7 @@ void VROARSessioniOS::setCloudAnchorProvider(VROCloudAnchorProvider provider) { ReactVisionCCA::RVCCAGeospatialProvider::Config cfg; cfg.apiKey = std::string([apiKey UTF8String]); cfg.projectId = std::string([projectId UTF8String]); + if (endpoint.length) cfg.endpoint = std::string([endpoint UTF8String]); _rvGeoProjectId = cfg.projectId; _geospatialProviderRV = std::make_shared(cfg); pinfo("ReactVision Geospatial provider initialized via setCloudAnchorProvider"); @@ -2503,6 +2506,24 @@ void VROARSessioniOS::rvTrackCloudAnchorResolution( if (callback) callback(false, "ReactVision cloud anchor provider not available"); } +void VROARSessioniOS::rvGetScene( + const std::string& sceneId, + std::function callback) { +#if RVCCA_AVAILABLE + auto p = [_cloudAnchorProviderRV cppProvider]; + if (p) { + p->getScene(sceneId, + [callback](ReactVisionCCA::ApiResult r) { + if (callback) { + callback(r.success, r.data, r.success ? "" : r.error.message); + } + }); + return; + } +#endif + if (callback) callback(false, "", "ReactVision cloud anchor provider not available"); +} + void VROARSessioniOS::rvGetSceneAssets( const std::string& sceneId, std::function callback) { diff --git a/ios/ViroKit/VROARSessioniOS.h b/ios/ViroKit/VROARSessioniOS.h index 10a5ef07e..d778f1570 100644 --- a/ios/ViroKit/VROARSessioniOS.h +++ b/ios/ViroKit/VROARSessioniOS.h @@ -197,6 +197,8 @@ class API_AVAILABLE(ios(12.0)) VROARSessioniOS : public VROARSession, public std double confidence, int matchCount, int inlierCount, int processingTimeMs, const std::string& platform, const std::string& externalUserId, std::function callback) override; + void rvGetScene(const std::string& sceneId, + std::function callback) override; void rvGetSceneAssets(const std::string& sceneId, std::function callback) override; diff --git a/ios/ViroKit/VROCloudAnchorProviderReactVision.mm b/ios/ViroKit/VROCloudAnchorProviderReactVision.mm index e127a7433..2604340b8 100644 --- a/ios/ViroKit/VROCloudAnchorProviderReactVision.mm +++ b/ios/ViroKit/VROCloudAnchorProviderReactVision.mm @@ -297,6 +297,7 @@ - (nullable instancetype)initWithApiKey:(NSString *)apiKey ReactVisionCCA::RVCCACloudAnchorProvider::Config cfg; cfg.apiKey = apiKey.UTF8String; cfg.projectId = projectId.UTF8String; + if (endpoint.length) cfg.endpoint = endpoint.UTF8String; cfg.enableLogging = YES; // DEBUG: enable to trace SIFT pipeline try {