blob: 5f1d4cab4f1b5c3a271a06fe1dce1261b2e87fbd [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_VR_ANDROID_ARCORE_ARCORE_ANCHOR_MANAGER_H_
#define DEVICE_VR_ANDROID_ARCORE_ARCORE_ANCHOR_MANAGER_H_
#include <map>
#include "base/types/id_type.h"
#include "base/types/pass_key.h"
#include "device/vr/android/arcore/address_to_id_map.h"
#include "device/vr/android/arcore/arcore_plane_manager.h"
#include "device/vr/android/arcore/arcore_sdk.h"
#include "device/vr/android/arcore/scoped_arcore_objects.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace device {
class ArCoreImpl;
using AnchorId = base::IdTypeU64<class AnchorTag>;
class ArCoreAnchorManager {
public:
ArCoreAnchorManager(base::PassKey<ArCoreImpl> pass_key,
ArSession* arcore_session);
~ArCoreAnchorManager();
// Updates anchor manager state - it should be called in every frame if the
// ARCore session has anchors feature enabled.
void Update(ArFrame* ar_frame);
mojom::XRAnchorsDataPtr GetAnchorsData() const;
bool AnchorExists(AnchorId id) const;
// Returns absl::nullopt if anchor with the given id does not exist.
absl::optional<gfx::Transform> GetMojoFromAnchor(AnchorId id) const;
// Creates Anchor object given a plane ID.
absl::optional<AnchorId> CreateAnchor(ArCorePlaneManager* plane_manager,
const device::mojom::Pose& pose,
PlaneId plane_id);
// Creates free-floating Anchor.
absl::optional<AnchorId> CreateAnchor(const device::mojom::Pose& pose);
void DetachAnchor(AnchorId anchor_id);
private:
struct AnchorInfo {
device::internal::ScopedArCoreObject<ArAnchor*> anchor;
ArTrackingState tracking_state;
AnchorInfo(device::internal::ScopedArCoreObject<ArAnchor*> anchor,
ArTrackingState tracking_state);
AnchorInfo(AnchorInfo&& other);
~AnchorInfo();
};
// Executes |fn| for each still tracked, anchor present in |arcore_anchors|.
// |fn| will receive a `device::internal::ScopedArCoreObject<ArAnchor*>` that
// can be stored, as well as ArTrackingState of the passed in anchor. An
// anchor is tracked if its state is not AR_TRACKING_STATE_STOPPED.
template <typename FunctionType>
void ForEachArCoreAnchor(ArAnchorList* arcore_anchors, FunctionType fn);
// Owned by ArCoreImpl - non-owning pointer is fine since ArCoreAnchorManager
// is also owned by ArCoreImpl.
ArSession* arcore_session_;
// Allows reuse of the pose object; ARCore will populate it with new data on
// each call to the ARCore SDK.
internal::ScopedArCoreObject<ArPose*> ar_pose_;
internal::ScopedArCoreObject<ArAnchorList*> arcore_anchors_;
// Mapping from anchor address to anchor ID. It should be modified only during
// calls to |Update()| and anchor creation.
AddressToIdMap<AnchorId> anchor_address_to_id_;
// Mapping from anchor ID to ARCore anchor information. It should be modified
// only during calls to |Update()|.
std::map<AnchorId, AnchorInfo> anchor_id_to_anchor_info_;
// Set containing IDs of anchors updated in the last frame. It should be
// modified only during calls to |Update()|.
std::set<AnchorId> updated_anchor_ids_;
#if DCHECK_IS_ON()
// True if |GetAnchorsData()| was called after |Update()|. It is used to track
// if |Update()| was called twice in a row w/o a call to |GetAnchorsData()| in
// between. Initially true since we expect the call to |Update()| to happen
// next.
// TODO(https://crbug.com/1192844): remove the assumption that the calls to
// |Update()| will always be followed by at least one call to
// |GetAnchorsData()| before the next call to |Update()| happens.
mutable bool was_anchor_data_retrieved_in_current_frame_ = true;
#endif
};
} // namespace device
#endif // DEVICE_VR_ANDROID_ARCORE_ARCORE_ANCHOR_MANAGER_H_