From a7707da2238ab6c95a68f45ed592f1761bc90b98 Mon Sep 17 00:00:00 2001 From: Jan Herling Date: Wed, 6 Nov 2024 09:45:27 -0800 Subject: [PATCH] Added event functions for ARKit anchor events to AKDevice Summary: Now, each AKDevice can react to anchor events. Reviewed By: enpe Differential Revision: D65502864 Privacy Context Container: L1191897 fbshipit-source-id: 26a71c8753cf86760eb2fa1c1de2eb2f84e94261 --- impl/ocean/devices/arkit/AKDevice.h | 28 +++++++ impl/ocean/devices/arkit/AKDevice.mm | 114 +++++++++++++++++++-------- 2 files changed, 107 insertions(+), 35 deletions(-) diff --git a/impl/ocean/devices/arkit/AKDevice.h b/impl/ocean/devices/arkit/AKDevice.h index 760b38d53..18cce42f6 100644 --- a/impl/ocean/devices/arkit/AKDevice.h +++ b/impl/ocean/devices/arkit/AKDevice.h @@ -69,6 +69,16 @@ class OCEAN_DEVICES_ARKIT_EXPORT AKDevice : virtual public Device TC_FACE = 1u << 5u }; + /** + * Definition of a vector holding ARAnchors. + */ + using ARAnchors = std::vector; + + /** + * Definition of an unordered map mapping devices to usage counters. + */ + using DeviceMap = std::unordered_map; + protected: /** @@ -145,6 +155,24 @@ class OCEAN_DEVICES_ARKIT_EXPORT AKDevice : virtual public Device */ inline TrackerCapabilities trackerCapabilities() const; + /** + * Event function for added anchors. + * @param anchors The added anchors, at least one + */ + virtual void onAddedAnchors(const ARAnchors& anchors); + + /** + * Event function for updated anchors. + * @param anchors The updated anchors, at least one + */ + virtual void onUpdateAnchors(const ARAnchors& anchors); + + /** + * Event function for removed anchors. + * @param anchors The removed anchors, at least one + */ + virtual void onRemovedAnchors(const ARAnchors& anchors); + /** * Translates the value of an ARGeoTrackingState to a readable string. * @param state The state to translate diff --git a/impl/ocean/devices/arkit/AKDevice.mm b/impl/ocean/devices/arkit/AKDevice.mm index 7c911d22e..0f0245ca5 100644 --- a/impl/ocean/devices/arkit/AKDevice.mm +++ b/impl/ocean/devices/arkit/AKDevice.mm @@ -44,10 +44,10 @@ @implementation AKTracker6DOFDelegate Media::LiveVideoRef inputLiveVideo_; /// The map mapping devices to reference counters. - std::unordered_map deviceMap_; + AKDevice::DeviceMap deviceMap_; - /// The map mapping object ids to anchors. - std::unordered_map anchorMap_; + /// The map mapping object ids to geo anchors. + std::unordered_map geoAnchorMap_; /// The last ARGeoTrackingState value. API_AVAILABLE(ios(14.0)) ARGeoTrackingState lastARGeoTrackingState_; @@ -58,6 +58,9 @@ @implementation AKTracker6DOFDelegate /// The last ARGeoTrackingAccuracy value. API_AVAILABLE(ios(14.0)) ARGeoTrackingAccuracy lastARGeoTrackingAccuracy_; + /// Reusable anchors. + AKDevice::ARAnchors reusableAnchors_; + /// The delegate's lock. @public Lock lock_; } @@ -97,7 +100,7 @@ - (bool)restart:(AKDevice*)device withMedium:(const Media::LiveVideoRef&)inputLi } #ifdef OCEAN_DEBUG - for (std::unordered_map::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) + for (AKDevice::DeviceMap::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) { ocean_assert(iDevice->first == device || iDevice->first->name() != device->name()); } @@ -375,7 +378,7 @@ - (bool)pause:(AKDevice*)tracker - (bool)stop:(AKDevice*)tracker { - std::unordered_map::iterator iDevice = deviceMap_.find(tracker); + AKDevice::DeviceMap::iterator iDevice = deviceMap_.find(tracker); ocean_assert(iDevice != deviceMap_.cend()); ocean_assert(iDevice->second >= 1u); @@ -399,12 +402,12 @@ - (bool)stop:(AKDevice*)tracker return false; } - for (std::pair pair : anchorMap_) + for (std::pair pair : geoAnchorMap_) { [arSession_ removeAnchor:pair.second]; } - anchorMap_.clear(); + geoAnchorMap_.clear(); [arSession_ pause]; @@ -432,7 +435,7 @@ - (bool)addGeoAnchor:(Devices::Measurement::ObjectId)objectId withLatitude:(doub return false; } - if (anchorMap_.find(objectId) != anchorMap_.cend()) + if (geoAnchorMap_.find(objectId) != geoAnchorMap_.cend()) { ocean_assert(false && "This should never happen!"); return false; @@ -473,7 +476,7 @@ - (bool)addGeoAnchor:(Devices::Measurement::ObjectId)objectId withLatitude:(doub [arSession_ addAnchor:geoAnchor]; - anchorMap_.emplace(objectId, geoAnchor); + geoAnchorMap_.emplace(objectId, geoAnchor); return true; } @@ -483,9 +486,9 @@ - (bool)addGeoAnchor:(Devices::Measurement::ObjectId)objectId withLatitude:(doub - (bool)removeGeoAnchor:(Devices::Measurement::ObjectId)objectId { - const std::unordered_map::const_iterator iAnchor = anchorMap_.find(objectId); + const std::unordered_map::const_iterator iAnchor = geoAnchorMap_.find(objectId); - if (iAnchor == anchorMap_.cend()) + if (iAnchor == geoAnchorMap_.cend()) { ocean_assert(false && "This should never happen!"); return false; @@ -493,7 +496,7 @@ - (bool)removeGeoAnchor:(Devices::Measurement::ObjectId)objectId [arSession_ removeAnchor:iAnchor->second]; - anchorMap_.erase(iAnchor); + geoAnchorMap_.erase(iAnchor); return true; } @@ -565,7 +568,7 @@ - (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame bool containsGeoTracker = false; - for (std::unordered_map::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) + for (AKDevice::DeviceMap::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) { AKDevice* device = iDevice->first; @@ -655,35 +658,61 @@ - (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame - (void)session:(ARSession *)session didAddAnchors:(NSArray<__kindof ARAnchor *> *)anchors { - if (@available(iOS 14.0, *)) + ocean_assert(anchors.count > 0); + + reusableAnchors_.clear(); + reusableAnchors_.reserve(anchors.count); + + for (ARAnchor* anchor in anchors) { -#ifdef OCEAN_DEBUG - for (ARAnchor* anchor in anchors) - { - const std::string anchorName = StringApple::toUTF8(anchor.name); - if (!anchorName.empty()) - { - Log::debug() << "Added anchor with id '" << anchorName; - } - } -#endif + reusableAnchors_.push_back(anchor); + } + + const ScopedLock scopedLock(lock_); + + for (AKDevice::DeviceMap::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) + { + iDevice->first->onAddedAnchors(reusableAnchors_); + } +} + +- (void)session:(ARSession *)session didUpdateAnchors:(NSArray<__kindof ARAnchor *> *)anchors +{ + ocean_assert(anchors.count > 0); + + reusableAnchors_.clear(); + reusableAnchors_.reserve(anchors.count); + + for (ARAnchor* anchor in anchors) + { + reusableAnchors_.push_back(anchor); + } + + const ScopedLock scopedLock(lock_); + + for (AKDevice::DeviceMap::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) + { + iDevice->first->onUpdateAnchors(reusableAnchors_); } } - (void)session:(ARSession *)session didRemoveAnchors:(NSArray<__kindof ARAnchor *> *)anchors { - if (@available(iOS 14.0, *)) + ocean_assert(anchors.count > 0); + + reusableAnchors_.clear(); + reusableAnchors_.reserve(anchors.count); + + for (ARAnchor* anchor in anchors) { -#ifdef OCEAN_DEBUG - for (ARAnchor* anchor in anchors) - { - const std::string anchorName = StringApple::toUTF8(anchor.name); - if (!anchorName.empty()) - { - Log::debug() << "Removed anchor with id '" << anchorName; - } - } -#endif + reusableAnchors_.push_back(anchor); + } + + const ScopedLock scopedLock(lock_); + + for (AKDevice::DeviceMap::const_iterator iDevice = deviceMap_.cbegin(); iDevice != deviceMap_.cend(); ++iDevice) + { + iDevice->first->onRemovedAnchors(reusableAnchors_); } } @@ -933,6 +962,21 @@ + (ARVideoFormat*)determinePreferredVideoFormat:(NSArray *)supp return nameARKitLibrary(); } +void AKDevice::onAddedAnchors(const ARAnchors& /*anchors*/) +{ + // nothing to do here +} + +void AKDevice::onUpdateAnchors(const ARAnchors& /*anchors*/) +{ + // nothing to do here +} + +void AKDevice::onRemovedAnchors(const ARAnchors& /*anchors*/) +{ + // nothing to do here +} + API_AVAILABLE(ios(14.0)) std::string AKDevice::translateGeoTrackingState(const ARGeoTrackingState& state) {