@@ -1541,17 +1541,61 @@ void VROARSessionARCore::checkVPSAvailability(double latitude, double longitude,
15411541 });
15421542}
15431543
1544+ // Create a local ARCore anchor at the GPS-computed world position using
1545+ // acquireNewAnchor. No VPS required — placed by GPS + compass + VIO.
1546+ // AR placement math is delegated to RVCCAGeospatialProvider::computeArPosition()
1547+ // (proprietary algorithm inside libreactvisioncca — not exposed in open-source virocore).
1548+ static std::shared_ptr<VROGeospatialAnchor> createLocalGPSAnchor (
1549+ arcore::Session *session,
1550+ const VROGeospatialPose &devicePose,
1551+ double anchorLat, double anchorLng, double anchorAlt,
1552+ VROGeospatialAnchorType type, VROQuaternion quaternion,
1553+ std::shared_ptr<VROARSessionARCore> arSession,
1554+ ReactVisionCCA::RVCCAGeospatialProvider *provider,
1555+ std::string &outError) {
1556+ if (devicePose.latitude == 0.0 && devicePose.longitude == 0.0 ) {
1557+ outError = " GPS position not available yet. Ensure location permissions are granted." ;
1558+ return nullptr ;
1559+ }
1560+ auto pos = provider->computeArPosition (
1561+ devicePose.latitude , devicePose.longitude , devicePose.altitude , devicePose.heading ,
1562+ anchorLat, anchorLng, anchorAlt);
1563+ float arX = pos[0 ], arY = pos[1 ], arZ = pos[2 ];
1564+
1565+ arcore::Pose *pose = session->createPose (arX, arY, arZ,
1566+ quaternion.X , quaternion.Y , quaternion.Z , quaternion.W );
1567+ arcore::Anchor *nativeAnchor = session->acquireNewAnchor (pose);
1568+ delete pose;
1569+
1570+ if (!nativeAnchor) {
1571+ outError = " Failed to create local anchor at GPS position." ;
1572+ return nullptr ;
1573+ }
1574+ std::shared_ptr<arcore::Anchor> anchorShared (nativeAnchor);
1575+ std::string key = VROStringUtil::toString64 (anchorShared->getId ());
1576+
1577+ auto geoAnchor = std::make_shared<VROGeospatialAnchor>(type, anchorLat, anchorLng, anchorAlt, quaternion);
1578+ geoAnchor->setId (key);
1579+ geoAnchor->setResolveState (VROGeospatialAnchorResolveState::Success);
1580+
1581+ auto vAnchor = std::make_shared<VROARAnchorARCore>(key, anchorShared, geoAnchor, arSession);
1582+ arSession->addAnchor (vAnchor);
1583+ return geoAnchor;
1584+ }
1585+
15441586void VROARSessionARCore::createGeospatialAnchor (double latitude, double longitude, double altitude,
15451587 VROQuaternion quaternion,
15461588 std::function<void (std::shared_ptr<VROGeospatialAnchor>)> onSuccess,
15471589 std::function<void(std::string error)> onFailure) {
15481590#if RVCCA_AVAILABLE
15491591 if (getGeospatialAnchorProvider () == VROGeospatialAnchorProvider::ReactVision) {
1550- // ReactVision has no VPS — cannot map GPS coordinates to AR world space.
1551- // Use rvCreateGeospatialAnchor to store GPS metadata, and resolveCloudAnchor
1552- // to place anchors in AR via visual feature matching.
1553- if (onFailure) onFailure (" createGeospatialAnchor requires ARCore VPS (provider='arcore'). "
1554- " ReactVision provider does not support GPS→AR placement." );
1592+ std::string error;
1593+ auto anchor = createLocalGPSAnchor (_session, _lastKnownGPSPose,
1594+ latitude, longitude, altitude,
1595+ VROGeospatialAnchorType::WGS84, quaternion,
1596+ shared_from_this (), _geospatialProviderRV.get (), error);
1597+ if (anchor) { if (onSuccess) onSuccess (anchor); }
1598+ else { if (onFailure) onFailure (error); }
15551599 return ;
15561600 }
15571601#endif
@@ -1595,8 +1639,15 @@ void VROARSessionARCore::createTerrainAnchor(double latitude, double longitude,
15951639 std::function<void(std::string error)> onFailure) {
15961640#if RVCCA_AVAILABLE
15971641 if (getGeospatialAnchorProvider () == VROGeospatialAnchorProvider::ReactVision) {
1598- if (onFailure) onFailure (" createTerrainAnchor requires ARCore VPS (provider='arcore'). "
1599- " ReactVision provider does not support GPS→AR placement." );
1642+ // Terrain alt = device altitude + offset above terrain (approximation)
1643+ double absoluteAlt = _lastKnownGPSPose.altitude + altitudeAboveTerrain;
1644+ std::string error;
1645+ auto anchor = createLocalGPSAnchor (_session, _lastKnownGPSPose,
1646+ latitude, longitude, absoluteAlt,
1647+ VROGeospatialAnchorType::Terrain, quaternion,
1648+ shared_from_this (), _geospatialProviderRV.get (), error);
1649+ if (anchor) { if (onSuccess) onSuccess (anchor); }
1650+ else { if (onFailure) onFailure (error); }
16001651 return ;
16011652 }
16021653#endif
@@ -1650,8 +1701,15 @@ void VROARSessionARCore::createRooftopAnchor(double latitude, double longitude,
16501701 std::function<void(std::string error)> onFailure) {
16511702#if RVCCA_AVAILABLE
16521703 if (getGeospatialAnchorProvider () == VROGeospatialAnchorProvider::ReactVision) {
1653- if (onFailure) onFailure (" createRooftopAnchor requires ARCore VPS (provider='arcore'). "
1654- " ReactVision provider does not support GPS→AR placement." );
1704+ // Rooftop alt = device altitude + offset above rooftop (approximation)
1705+ double absoluteAlt = _lastKnownGPSPose.altitude + altitudeAboveRooftop;
1706+ std::string error;
1707+ auto anchor = createLocalGPSAnchor (_session, _lastKnownGPSPose,
1708+ latitude, longitude, absoluteAlt,
1709+ VROGeospatialAnchorType::Rooftop, quaternion,
1710+ shared_from_this (), _geospatialProviderRV.get (), error);
1711+ if (anchor) { if (onSuccess) onSuccess (anchor); }
1712+ else { if (onFailure) onFailure (error); }
16551713 return ;
16561714 }
16571715#endif
0 commit comments