Commit e18bb0f7 authored by Piotr Bialecki's avatar Piotr Bialecki Committed by Commit Bot

Implement anchor creation from XRSession and XRPlane

Bug: 992033
Change-Id: I5d79658062e574b7c910af03b0ec0c838c169f05
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1774659
Auto-Submit: Piotr Bialecki <bialpio@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Commit-Queue: Piotr Bialecki <bialpio@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695250}
parent 8a22cc26
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
#include "device/vr/public/mojom/vr_service.mojom.h" #include "device/vr/public/mojom/vr_service.mojom.h"
#include "ui/display/display.h" #include "ui/display/display.h"
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
...@@ -54,6 +55,13 @@ class ArCore { ...@@ -54,6 +55,13 @@ class ArCore {
const mojom::XRRayPtr& ray, const mojom::XRRayPtr& ray,
std::vector<mojom::XRHitResultPtr>* hit_results) = 0; std::vector<mojom::XRHitResultPtr>* hit_results) = 0;
virtual base::Optional<int32_t> CreateAnchor(
const mojom::VRPosePtr& pose) = 0;
virtual base::Optional<int32_t> CreateAnchor(const mojom::VRPosePtr& pose,
int32_t plane_id) = 0;
virtual void DetachAnchor(int32_t anchor_id) = 0;
virtual void Pause() = 0; virtual void Pause() = 0;
virtual void Resume() = 0; virtual void Resume() = 0;
}; };
......
...@@ -583,6 +583,42 @@ void ArCoreGl::RequestHitTest( ...@@ -583,6 +583,42 @@ void ArCoreGl::RequestHitTest(
hit_test_requests_.push_back(std::move(request)); hit_test_requests_.push_back(std::move(request));
} }
void ArCoreGl::CreateAnchor(mojom::VRPosePtr anchor_pose,
CreateAnchorCallback callback) {
DVLOG(2) << __func__;
base::Optional<int32_t> maybe_anchor_id = arcore_->CreateAnchor(anchor_pose);
if (maybe_anchor_id) {
std::move(callback).Run(device::mojom::CreateAnchorResult::SUCCESS,
*maybe_anchor_id);
} else {
std::move(callback).Run(device::mojom::CreateAnchorResult::FAILURE, 0);
}
}
void ArCoreGl::CreatePlaneAnchor(mojom::VRPosePtr anchor_pose,
int32_t plane_id,
CreatePlaneAnchorCallback callback) {
DVLOG(2) << __func__;
base::Optional<int32_t> maybe_anchor_id =
arcore_->CreateAnchor(anchor_pose, plane_id);
if (maybe_anchor_id) {
std::move(callback).Run(device::mojom::CreateAnchorResult::SUCCESS,
*maybe_anchor_id);
} else {
std::move(callback).Run(device::mojom::CreateAnchorResult::FAILURE, 0);
}
}
void ArCoreGl::DetachAnchor(int32_t anchor_id) {
DVLOG(2) << __func__;
arcore_->DetachAnchor(anchor_id);
}
void ArCoreGl::SetFrameDataRestricted(bool frame_data_restricted) { void ArCoreGl::SetFrameDataRestricted(bool frame_data_restricted) {
DCHECK(IsOnGlThread()); DCHECK(IsOnGlThread());
DCHECK(is_initialized_); DCHECK(is_initialized_);
......
...@@ -108,6 +108,14 @@ class ArCoreGl : public mojom::XRFrameDataProvider, ...@@ -108,6 +108,14 @@ class ArCoreGl : public mojom::XRFrameDataProvider,
mojom::XRRayPtr, mojom::XRRayPtr,
mojom::XREnvironmentIntegrationProvider::RequestHitTestCallback) override; mojom::XREnvironmentIntegrationProvider::RequestHitTestCallback) override;
void CreateAnchor(mojom::VRPosePtr anchor_pose,
CreateAnchorCallback callback) override;
void CreatePlaneAnchor(mojom::VRPosePtr anchor_pose,
int32_t plane_id,
CreatePlaneAnchorCallback callback) override;
void DetachAnchor(int32_t anchor_id) override;
// mojom::XRSessionController // mojom::XRSessionController
void SetFrameDataRestricted(bool restricted) override; void SetFrameDataRestricted(bool restricted) override;
......
...@@ -37,6 +37,36 @@ device::mojom::VRPosePtr GetMojomPoseFromArPose( ...@@ -37,6 +37,36 @@ device::mojom::VRPosePtr GetMojomPoseFromArPose(
return result; return result;
} }
device::internal::ScopedArCoreObject<ArPose*> GetArPoseFromMojomPose(
ArSession* session,
const device::mojom::VRPosePtr& pose) {
float pose_raw[7] = {}; // 7 = orientation(4) + position(3).
if (pose->orientation) {
pose_raw[0] = pose->orientation->x();
pose_raw[1] = pose->orientation->y();
pose_raw[2] = pose->orientation->z();
pose_raw[3] = pose->orientation->w();
} else {
// Only need to set the .w to 1.
pose_raw[3] = 1;
}
if (pose->position) {
pose_raw[4] = pose->position->x();
pose_raw[5] = pose->position->y();
pose_raw[6] = pose->position->z();
}
device::internal::ScopedArCoreObject<ArPose*> result;
ArPose_create(
session, pose_raw,
device::internal::ScopedArCoreObject<ArPose*>::Receiver(result).get());
return result;
}
} // namespace } // namespace
namespace device { namespace device {
...@@ -259,7 +289,7 @@ void ArCoreImpl::ForEachArCorePlane(FunctionType fn) { ...@@ -259,7 +289,7 @@ void ArCoreImpl::ForEachArCorePlane(FunctionType fn) {
continue; continue;
} }
fn(ar_plane); fn(std::move(trackable), ar_plane);
} }
} // namespace device } // namespace device
...@@ -293,6 +323,10 @@ std::vector<mojom::XRAnchorDataPtr> ArCoreImpl::GetUpdatedAnchorsData() { ...@@ -293,6 +323,10 @@ std::vector<mojom::XRAnchorDataPtr> ArCoreImpl::GetUpdatedAnchorsData() {
bool created; bool created;
std::tie(anchor_id, created) = *maybe_anchor_id_and_created; std::tie(anchor_id, created) = *maybe_anchor_id_and_created;
DCHECK(!created)
<< "Anchor creation is app-initiated - we should never encounter an "
"anchor that was created outside of `ArCoreImpl::CreateAnchor()`.";
result.push_back(mojom::XRAnchorData::New(anchor_id, std::move(pose))); result.push_back(mojom::XRAnchorData::New(anchor_id, std::move(pose)));
}); });
...@@ -319,9 +353,9 @@ std::vector<int32_t> ArCoreImpl::GetAllAnchorIds() { ...@@ -319,9 +353,9 @@ std::vector<int32_t> ArCoreImpl::GetAllAnchorIds() {
bool created; bool created;
std::tie(anchor_id, created) = *maybe_anchor_id_and_created; std::tie(anchor_id, created) = *maybe_anchor_id_and_created;
// TODO(https://crbug.com/992033): Add explanation for the below DCHECK when DCHECK(!created)
// implementing anchor creation. << "Anchor creation is app-initiated - we should never encounter an "
DCHECK(!created); "anchor that was created outside of `ArCoreImpl::CreateAnchor()`.";
result.emplace_back(anchor_id); result.emplace_back(anchor_id);
}); });
...@@ -365,7 +399,9 @@ std::vector<mojom::XRPlaneDataPtr> ArCoreImpl::GetUpdatedPlanesData() { ...@@ -365,7 +399,9 @@ std::vector<mojom::XRPlaneDataPtr> ArCoreImpl::GetUpdatedPlanesData() {
ArFrame_getUpdatedTrackables(arcore_session_.get(), arcore_frame_.get(), ArFrame_getUpdatedTrackables(arcore_session_.get(), arcore_frame_.get(),
plane_tracked_type, arcore_planes_.get()); plane_tracked_type, arcore_planes_.get());
ForEachArCorePlane([this, &result](ArPlane* ar_plane) { ForEachArCorePlane([this, &result](
internal::ScopedArCoreObject<ArTrackable*> trackable,
ArPlane* ar_plane) {
// orientation // orientation
ArPlaneType plane_type; ArPlaneType plane_type;
ArPlane_getType(arcore_session_.get(), ar_plane, &plane_type); ArPlane_getType(arcore_session_.get(), ar_plane, &plane_type);
...@@ -426,7 +462,13 @@ std::vector<int32_t> ArCoreImpl::GetAllPlaneIds() { ...@@ -426,7 +462,13 @@ std::vector<int32_t> ArCoreImpl::GetAllPlaneIds() {
ArSession_getAllTrackables(arcore_session_.get(), plane_tracked_type, ArSession_getAllTrackables(arcore_session_.get(), plane_tracked_type,
arcore_planes_.get()); arcore_planes_.get());
ForEachArCorePlane([this, &result](ArPlane* ar_plane) { std::unordered_map<int32_t,
device::internal::ScopedArCoreObject<ArTrackable*>>
plane_id_to_plane_object;
ForEachArCorePlane([this, &plane_id_to_plane_object, &result](
internal::ScopedArCoreObject<ArTrackable*> trackable,
ArPlane* ar_plane) {
// ID // ID
auto maybe_plane_id_and_created = CreateOrGetPlaneId(ar_plane); auto maybe_plane_id_and_created = CreateOrGetPlaneId(ar_plane);
if (!maybe_plane_id_and_created) { if (!maybe_plane_id_and_created) {
...@@ -443,8 +485,11 @@ std::vector<int32_t> ArCoreImpl::GetAllPlaneIds() { ...@@ -443,8 +485,11 @@ std::vector<int32_t> ArCoreImpl::GetAllPlaneIds() {
<< "Newly detected planes should be handled by GetUpdatedPlanesData()."; << "Newly detected planes should be handled by GetUpdatedPlanesData().";
result.emplace_back(plane_id); result.emplace_back(plane_id);
plane_id_to_plane_object[plane_id] = std::move(trackable);
}); });
plane_id_to_plane_object_.swap(plane_id_to_plane_object);
return result; return result;
} }
...@@ -672,6 +717,81 @@ bool ArCoreImpl::RequestHitTest( ...@@ -672,6 +717,81 @@ bool ArCoreImpl::RequestHitTest(
return true; return true;
} }
base::Optional<int32_t> ArCoreImpl::CreateAnchor(
const device::mojom::VRPosePtr& pose) {
DCHECK(pose);
auto ar_pose = GetArPoseFromMojomPose(arcore_session_.get(), pose);
device::internal::ScopedArCoreObject<ArAnchor*> ar_anchor;
ArSession_acquireNewAnchor(
arcore_session_.get(), ar_pose.get(),
device::internal::ScopedArCoreObject<ArAnchor*>::Receiver(ar_anchor)
.get());
auto maybe_anchor_id_and_created = CreateOrGetAnchorId(ar_anchor.get());
if (!maybe_anchor_id_and_created) {
return base::nullopt;
}
int32_t anchor_id;
bool created;
std::tie(anchor_id, created) = *maybe_anchor_id_and_created;
DCHECK(created) << "This should always be a new anchor, not something we've "
"seen previously.";
anchor_id_to_anchor_object_[anchor_id] = std::move(ar_anchor);
return anchor_id;
}
base::Optional<int32_t> ArCoreImpl::CreateAnchor(
const device::mojom::VRPosePtr& pose,
int32_t plane_id) {
DCHECK(pose);
auto ar_pose = GetArPoseFromMojomPose(arcore_session_.get(), pose);
auto it = plane_id_to_plane_object_.find(plane_id);
if (it == plane_id_to_plane_object_.end()) {
return base::nullopt;
}
device::internal::ScopedArCoreObject<ArAnchor*> ar_anchor;
ArTrackable_acquireNewAnchor(
arcore_session_.get(), it->second.get(), ar_pose.get(),
device::internal::ScopedArCoreObject<ArAnchor*>::Receiver(ar_anchor)
.get());
auto maybe_anchor_id_and_created = CreateOrGetAnchorId(ar_anchor.get());
if (!maybe_anchor_id_and_created) {
return base::nullopt;
}
int32_t anchor_id;
bool created;
std::tie(anchor_id, created) = *maybe_anchor_id_and_created;
DCHECK(created) << "This should always be a new anchor, not something we've "
"seen previously.";
anchor_id_to_anchor_object_[anchor_id] = std::move(ar_anchor);
return anchor_id;
}
void ArCoreImpl::DetachAnchor(int32_t anchor_id) {
auto it = anchor_id_to_anchor_object_.find(anchor_id);
if (it == anchor_id_to_anchor_object_.end()) {
return;
}
ArAnchor_detach(arcore_session_.get(), it->second.get());
anchor_id_to_anchor_object_.erase(it);
}
bool ArCoreImpl::IsOnGlThread() { bool ArCoreImpl::IsOnGlThread() {
return gl_thread_task_runner_->BelongsToCurrentThread(); return gl_thread_task_runner_->BelongsToCurrentThread();
} }
......
...@@ -55,6 +55,11 @@ void inline ScopedGenericArObject<ArPlane*>::Free(ArPlane* ar_plane) { ...@@ -55,6 +55,11 @@ void inline ScopedGenericArObject<ArPlane*>::Free(ArPlane* ar_plane) {
ArTrackable_release(ArAsTrackable(ar_plane)); ArTrackable_release(ArAsTrackable(ar_plane));
} }
template <>
void inline ScopedGenericArObject<ArAnchor*>::Free(ArAnchor* ar_anchor) {
ArAnchor_release(ar_anchor);
}
template <> template <>
void inline ScopedGenericArObject<ArTrackableList*>::Free( void inline ScopedGenericArObject<ArTrackableList*>::Free(
ArTrackableList* ar_trackable_list) { ArTrackableList* ar_trackable_list) {
...@@ -109,6 +114,13 @@ class ArCoreImpl : public ArCore { ...@@ -109,6 +114,13 @@ class ArCoreImpl : public ArCore {
bool RequestHitTest(const mojom::XRRayPtr& ray, bool RequestHitTest(const mojom::XRRayPtr& ray,
std::vector<mojom::XRHitResultPtr>* hit_results) override; std::vector<mojom::XRHitResultPtr>* hit_results) override;
base::Optional<int32_t> CreateAnchor(
const device::mojom::VRPosePtr& pose) override;
base::Optional<int32_t> CreateAnchor(const device::mojom::VRPosePtr& pose,
int32_t plane_id) override;
void DetachAnchor(int32_t anchor_id) override;
private: private:
bool IsOnGlThread(); bool IsOnGlThread();
base::WeakPtr<ArCoreImpl> GetWeakPtr() { base::WeakPtr<ArCoreImpl> GetWeakPtr() {
...@@ -162,7 +174,12 @@ class ArCoreImpl : public ArCore { ...@@ -162,7 +174,12 @@ class ArCoreImpl : public ArCore {
int32_t next_id_ = 1; int32_t next_id_ = 1;
std::unordered_map<void*, int32_t> ar_plane_address_to_id_; std::unordered_map<void*, int32_t> ar_plane_address_to_id_;
std::unordered_map<int32_t,
device::internal::ScopedArCoreObject<ArTrackable*>>
plane_id_to_plane_object_;
std::unordered_map<void*, int32_t> ar_anchor_address_to_id_; std::unordered_map<void*, int32_t> ar_anchor_address_to_id_;
std::unordered_map<int32_t, device::internal::ScopedArCoreObject<ArAnchor*>>
anchor_id_to_anchor_object_;
// Returns tuple containing plane id and a boolean signifying that the plane // Returns tuple containing plane id and a boolean signifying that the plane
// was created. The result will be a nullopt in case the ID should be assigned // was created. The result will be a nullopt in case the ID should be assigned
......
...@@ -64,6 +64,7 @@ namespace { ...@@ -64,6 +64,7 @@ namespace {
CALL(ArSession_setCameraTextureName) \ CALL(ArSession_setCameraTextureName) \
CALL(ArSession_setDisplayGeometry) \ CALL(ArSession_setDisplayGeometry) \
CALL(ArSession_update) \ CALL(ArSession_update) \
CALL(ArTrackable_acquireNewAnchor) \
CALL(ArTrackable_getTrackingState) \ CALL(ArTrackable_getTrackingState) \
CALL(ArTrackable_getType) \ CALL(ArTrackable_getType) \
CALL(ArTrackable_release) \ CALL(ArTrackable_release) \
...@@ -276,6 +277,14 @@ void ArHitResult_acquireTrackable(const ArSession* session, ...@@ -276,6 +277,14 @@ void ArHitResult_acquireTrackable(const ArSession* session,
out_trackable); out_trackable);
} }
ArStatus ArTrackable_acquireNewAnchor(ArSession* session,
ArTrackable* trackable,
ArPose* pose,
ArAnchor** out_anchor) {
return arcore_api->impl_ArTrackable_acquireNewAnchor(session, trackable, pose,
out_anchor);
}
void ArTrackable_getTrackingState(const ArSession* session, void ArTrackable_getTrackingState(const ArSession* session,
const ArTrackable* trackable, const ArTrackable* trackable,
ArTrackingState* out_tracking_state) { ArTrackingState* out_tracking_state) {
......
...@@ -231,15 +231,52 @@ mojom::XRPlaneDetectionDataPtr FakeArCore::GetDetectedPlanesData() { ...@@ -231,15 +231,52 @@ mojom::XRPlaneDetectionDataPtr FakeArCore::GetDetectedPlanesData() {
mojom::XRAnchorsDataPtr FakeArCore::GetAnchorsData() { mojom::XRAnchorsDataPtr FakeArCore::GetAnchorsData() {
std::vector<mojom::XRAnchorDataPtr> result; std::vector<mojom::XRAnchorDataPtr> result;
std::vector<int32_t> result_ids;
// 2m ahead of the origin, neutral orientation facing forward. for (auto& anchor_id_and_data : anchors_) {
mojom::VRPosePtr pose = mojom::VRPose::New(); mojom::VRPosePtr pose = mojom::VRPose::New();
pose->position = gfx::Point3F(0.0, 0.0, -2.0); pose->position = anchor_id_and_data.second.position;
pose->orientation = gfx::Quaternion(); pose->orientation = anchor_id_and_data.second.orientation;
result.push_back(
mojom::XRAnchorData::New(anchor_id_and_data.first, std::move(pose)));
result_ids.push_back(anchor_id_and_data.first);
}
return mojom::XRAnchorsData::New(std::move(result_ids), std::move(result));
}
base::Optional<int32_t> FakeArCore::CreateAnchor(const mojom::VRPosePtr& pose,
int32_t plane_id) {
// TODO(992035): Fix this when implementing tests.
return CreateAnchor(pose);
}
base::Optional<int32_t> FakeArCore::CreateAnchor(const mojom::VRPosePtr& pose) {
DCHECK(pose);
gfx::Point3F position =
pose->position ? gfx::Point3F(pose->position->x(), pose->position->y(),
pose->position->z())
: gfx::Point3F();
gfx::Quaternion orientation =
pose->orientation
? gfx::Quaternion(pose->orientation->x(), pose->orientation->y(),
pose->orientation->z(), pose->orientation->w())
: gfx::Quaternion(0, 0, 0, 1);
result.push_back(mojom::XRAnchorData::New(2, std::move(pose))); anchors_[next_id_] = {position, orientation};
int32_t anchor_id = next_id_;
next_id_++;
return anchor_id;
}
return mojom::XRAnchorsData::New(std::vector<int32_t>{2}, std::move(result)); void FakeArCore::DetachAnchor(int32_t anchor_id) {
auto count = anchors_.erase(anchor_id);
DCHECK_EQ(1u, count);
} }
void FakeArCore::Pause() { void FakeArCore::Pause() {
......
...@@ -40,6 +40,12 @@ class FakeArCore : public ArCore { ...@@ -40,6 +40,12 @@ class FakeArCore : public ArCore {
mojom::XRPlaneDetectionDataPtr GetDetectedPlanesData() override; mojom::XRPlaneDetectionDataPtr GetDetectedPlanesData() override;
mojom::XRAnchorsDataPtr GetAnchorsData() override; mojom::XRAnchorsDataPtr GetAnchorsData() override;
base::Optional<int32_t> CreateAnchor(
const device::mojom::VRPosePtr& pose) override;
base::Optional<int32_t> CreateAnchor(const device::mojom::VRPosePtr& pose,
int32_t plane_id) override;
void DetachAnchor(int32_t anchor_id) override;
void SetCameraAspect(float aspect) { camera_aspect_ = aspect; } void SetCameraAspect(float aspect) { camera_aspect_ = aspect; }
private: private:
...@@ -52,6 +58,14 @@ class FakeArCore : public ArCore { ...@@ -52,6 +58,14 @@ class FakeArCore : public ArCore {
display::Display::Rotation::ROTATE_0; display::Display::Rotation::ROTATE_0;
gfx::Size frame_size_; gfx::Size frame_size_;
struct FakeAnchorData {
gfx::Point3F position;
gfx::Quaternion orientation;
};
int32_t next_id_ = 100;
std::unordered_map<int32_t, FakeAnchorData> anchors_;
DISALLOW_COPY_AND_ASSIGN(FakeArCore); DISALLOW_COPY_AND_ASSIGN(FakeArCore);
}; };
......
...@@ -454,9 +454,17 @@ interface VRServiceClient { ...@@ -454,9 +454,17 @@ interface VRServiceClient {
OnDeviceChanged(); OnDeviceChanged();
}; };
enum CreateAnchorResult {
SUCCESS = 0,
FAILURE = 1,
};
// Provides functionality for integrating environment information into an // Provides functionality for integrating environment information into an
// XRSession. For example, some AR sessions would implement hit test to allow // XRSession. For example, some AR sessions would implement hit test to allow
// developers to get the information about the world that its sensors supply. // developers to get the information about the world that its sensors supply.
// On XRSession end, the message pipe will be destroyed - we need to clean up
// all outstanding JavaScript promises at that time. The XRsession might end for
// example due to a call to XRSession::end() method (exposed to JavaScript).
interface XREnvironmentIntegrationProvider { interface XREnvironmentIntegrationProvider {
// Performs a raycast into the scene and returns a list of XRHitResults sorted // Performs a raycast into the scene and returns a list of XRHitResults sorted
// from closest to furthest hit from the ray. Each hit result contains a // from closest to furthest hit from the ray. Each hit result contains a
...@@ -465,6 +473,27 @@ interface XREnvironmentIntegrationProvider { ...@@ -465,6 +473,27 @@ interface XREnvironmentIntegrationProvider {
// An empty result list means there were no hits. If a nullopt is returned, // An empty result list means there were no hits. If a nullopt is returned,
// there was an error. // there was an error.
RequestHitTest(XRRay ray) => (array<XRHitResult>? results); RequestHitTest(XRRay ray) => (array<XRHitResult>? results);
// Issues a request to create an anchor attached to a session.
// |result| will contain status code of the request. |anchor_id| will be valid
// only if the |result| is SUCCESS.
CreateAnchor(VRPose anchor_pose) => (CreateAnchorResult result,
int32 anchor_id);
// TODO(https://crbug.com/657632): Switch anchor_id to nullable integer once
// that's available. This will allow us to remove CreateAnchorResult if we're
// not interested in obtaining detailed error information from the device.
// Issues a request to create an anchor attached to a plane.
// |result| will contain status code of the request. |anchor_id| will be valid
// only if the |result| is SUCCESS.
CreatePlaneAnchor(VRPose anchor_pose, int32 plane_id) =>
(CreateAnchorResult result, int32 anchor_id);
// TODO(https://crbug.com/657632): Ditto - make anchor_id a nullable integer..
// Detaches an existing anchor. The |anchor_id| must be a valid id of an
// anchor created by one of the CreateAnchor calls, otherwise the call will be
// ignored.
DetachAnchor(int32 anchor_id);
}; };
// Provides a mechanism for a channel to plumb up any button click events // Provides a mechanism for a channel to plumb up any button click events
......
...@@ -79,6 +79,8 @@ class XR final : public EventTargetWithInlineData, ...@@ -79,6 +79,8 @@ class XR final : public EventTargetWithInlineData,
int64_t GetSourceId() const { return ukm_source_id_; } int64_t GetSourceId() const { return ukm_source_id_; }
using EnvironmentProviderErrorCallback = base::OnceCallback<void()>; using EnvironmentProviderErrorCallback = base::OnceCallback<void()>;
// Registers a callback that'll be invoked when mojo invokes a disconnect
// handler on the underlying XREnvironmentIntegrationProvider remote.
void AddEnvironmentProviderErrorHandler( void AddEnvironmentProviderErrorHandler(
EnvironmentProviderErrorCallback callback); EnvironmentProviderErrorCallback callback);
......
...@@ -68,8 +68,7 @@ double XRAnchor::lastChangedTime(bool& is_null) const { ...@@ -68,8 +68,7 @@ double XRAnchor::lastChangedTime(bool& is_null) const {
} }
void XRAnchor::detach() { void XRAnchor::detach() {
// TODO(992033): Actually detach anchor once anchor creation is implemented. session_->xr()->xrEnvironmentProviderPtr()->DetachAnchor(id_);
DVLOG(2) << "Detaching anchor, id_=" << id_;
} }
void XRAnchor::Trace(blink::Visitor* visitor) { void XRAnchor::Trace(blink::Visitor* visitor) {
......
...@@ -376,12 +376,12 @@ void XRFrameProvider::ProcessScheduledFrame( ...@@ -376,12 +376,12 @@ void XRFrameProvider::ProcessScheduledFrame(
immersive_session_->UpdateStageParameters(frame_data->stage_parameters); immersive_session_->UpdateStageParameters(frame_data->stage_parameters);
} }
if (frame_data) { if (frame_data) {
immersive_session_->OnFrame(high_res_now_ms, std::move(pose_matrix), immersive_session_->OnFrame(
buffer_mailbox_holder_, high_res_now_ms, std::move(pose_matrix), buffer_mailbox_holder_,
frame_data->detected_planes_data); frame_data->detected_planes_data, frame_data->anchors_data);
} else { } else {
immersive_session_->OnFrame(high_res_now_ms, std::move(pose_matrix), immersive_session_->OnFrame(high_res_now_ms, std::move(pose_matrix),
buffer_mailbox_holder_, nullptr); buffer_mailbox_holder_, nullptr, nullptr);
} }
} else { } else {
// In the process of fulfilling the frame requests for each session they are // In the process of fulfilling the frame requests for each session they are
...@@ -425,10 +425,11 @@ void XRFrameProvider::ProcessScheduledFrame( ...@@ -425,10 +425,11 @@ void XRFrameProvider::ProcessScheduledFrame(
getPoseMatrix(frame_pose_); getPoseMatrix(frame_pose_);
if (frame_data) { if (frame_data) {
session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt, session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt,
frame_data->detected_planes_data); frame_data->detected_planes_data,
frame_data->anchors_data);
} else { } else {
session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt, session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt,
nullptr); nullptr, nullptr);
} }
} }
......
...@@ -83,14 +83,10 @@ HeapVector<Member<DOMPointReadOnly>> XRPlane::polygon() const { ...@@ -83,14 +83,10 @@ HeapVector<Member<DOMPointReadOnly>> XRPlane::polygon() const {
ScriptPromise XRPlane::createAnchor(ScriptState* script_state, ScriptPromise XRPlane::createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose, XRRigidTransform* initial_pose,
XRSpace* space) { XRSpace* space,
// TODO(https://crbug.com/992033): Implement anchor creation from a plane ExceptionState& exception_state) {
// instead of rejecting the promise. This'll cause the string literal used return session_->CreateAnchor(script_state, initial_pose, space, this,
// below to be removed. exception_state);
return ScriptPromise::RejectWithDOMException(
script_state,
MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
"Device does not support anchors!"));
} }
void XRPlane::Update(const device::mojom::blink::XRPlaneDataPtr& plane_data, void XRPlane::Update(const device::mojom::blink::XRPlaneDataPtr& plane_data,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
namespace blink { namespace blink {
class ExceptionState;
class XRRigidTransform; class XRRigidTransform;
class XRSession; class XRSession;
class XRSpace; class XRSpace;
...@@ -49,7 +50,8 @@ class XRPlane : public ScriptWrappable { ...@@ -49,7 +50,8 @@ class XRPlane : public ScriptWrappable {
ScriptPromise createAnchor(ScriptState* script_state, ScriptPromise createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose, XRRigidTransform* initial_pose,
XRSpace* space); XRSpace* space,
ExceptionState& exception_state);
// Updates plane data from passed in |plane_data|. The resulting instance // Updates plane data from passed in |plane_data|. The resulting instance
// should be equivalent to the instance that would be create by calling // should be equivalent to the instance that would be create by calling
......
...@@ -20,5 +20,5 @@ interface XRPlane { ...@@ -20,5 +20,5 @@ interface XRPlane {
readonly attribute XRPlaneOrientation? orientation; readonly attribute XRPlaneOrientation? orientation;
readonly attribute DOMHighResTimeStamp lastChangedTime; readonly attribute DOMHighResTimeStamp lastChangedTime;
[RuntimeEnabled=WebXRAnchors, CallWith=ScriptState] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space); [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space);
}; };
...@@ -33,9 +33,11 @@ class ResizeObserver; ...@@ -33,9 +33,11 @@ class ResizeObserver;
class ScriptPromiseResolver; class ScriptPromiseResolver;
class V8XRFrameRequestCallback; class V8XRFrameRequestCallback;
class XR; class XR;
class XRAnchor;
class XRAnchorSet; class XRAnchorSet;
class XRCanvasInputProvider; class XRCanvasInputProvider;
class XRHitTestOptionsInit; class XRHitTestOptionsInit;
class XRPlane;
class XRRay; class XRRay;
class XRReferenceSpace; class XRReferenceSpace;
class XRRenderState; class XRRenderState;
...@@ -81,7 +83,7 @@ class XRSession final ...@@ -81,7 +83,7 @@ class XRSession final
XRRenderState* renderState() const { return render_state_; } XRRenderState* renderState() const { return render_state_; }
XRWorldTrackingState* worldTrackingState() { return world_tracking_state_; } XRWorldTrackingState* worldTrackingState() { return world_tracking_state_; }
XRSpace* viewerSpace() const; XRSpace* viewerSpace() const;
XRAnchorSet* trackedAnchors() const { return nullptr; } XRAnchorSet* trackedAnchors() const;
bool immersive() const; bool immersive() const;
...@@ -101,10 +103,18 @@ class XRSession final ...@@ -101,10 +103,18 @@ class XRSession final
const String& type, const String& type,
ExceptionState&); ExceptionState&);
// IDL-exposed
ScriptPromise createAnchor(ScriptState* script_state, ScriptPromise createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose, XRRigidTransform* initial_pose,
XRSpace* space, XRSpace* space,
ExceptionState&); ExceptionState& exception_state);
// helper, not IDL-exposed
ScriptPromise CreateAnchor(ScriptState* script_state,
XRRigidTransform* pose,
XRSpace* space,
XRPlane* plane,
ExceptionState& exception_state);
int requestAnimationFrame(V8XRFrameRequestCallback* callback); int requestAnimationFrame(V8XRFrameRequestCallback* callback);
void cancelAnimationFrame(int id); void cancelAnimationFrame(int id);
...@@ -149,11 +159,12 @@ class XRSession final ...@@ -149,11 +159,12 @@ class XRSession final
const AtomicString& InterfaceName() const override; const AtomicString& InterfaceName() const override;
void OnFocusChanged(); void OnFocusChanged();
void OnFrame(double timestamp, void OnFrame(
std::unique_ptr<TransformationMatrix> base_pose_matrix, double timestamp,
const base::Optional<gpu::MailboxHolder>& output_mailbox_holder, std::unique_ptr<TransformationMatrix> base_pose_matrix,
const device::mojom::blink::XRPlaneDetectionDataPtr& const base::Optional<gpu::MailboxHolder>& output_mailbox_holder,
detected_planes_data); const device::mojom::blink::XRPlaneDetectionDataPtr& detected_planes_data,
const device::mojom::blink::XRAnchorsDataPtr& tracked_anchors_data);
void OnInputStateChange( void OnInputStateChange(
int16_t frame_id, int16_t frame_id,
...@@ -241,9 +252,17 @@ class XRSession final ...@@ -241,9 +252,17 @@ class XRSession final
base::Optional<WTF::Vector<device::mojom::blink::XRHitResultPtr>> base::Optional<WTF::Vector<device::mojom::blink::XRHitResultPtr>>
results); results);
void OnCreateAnchorResult(ScriptPromiseResolver* resolver,
device::mojom::CreateAnchorResult result,
int32_t id);
void EnsureEnvironmentErrorHandler(); void EnsureEnvironmentErrorHandler();
void OnEnvironmentProviderError(); void OnEnvironmentProviderError();
void ProcessAnchorsData(
const device::mojom::blink::XRAnchorsDataPtr& tracked_anchors_data,
double timestamp);
const Member<XR> xr_; const Member<XR> xr_;
const SessionMode mode_; const SessionMode mode_;
const bool environment_integration_; const bool environment_integration_;
...@@ -255,6 +274,10 @@ class XRSession final ...@@ -255,6 +274,10 @@ class XRSession final
HeapVector<Member<XRRenderStateInit>> pending_render_state_; HeapVector<Member<XRRenderStateInit>> pending_render_state_;
XRSessionFeatureSet enabled_features_; XRSessionFeatureSet enabled_features_;
bool is_tracked_anchors_null_ = true;
HeapHashMap<int32_t, Member<XRAnchor>> anchor_ids_to_anchors_;
WTF::Vector<XRViewData> views_; WTF::Vector<XRViewData> views_;
Member<XRInputSourceArray> input_sources_; Member<XRInputSourceArray> input_sources_;
...@@ -262,6 +285,8 @@ class XRSession final ...@@ -262,6 +285,8 @@ class XRSession final
Member<XRCanvasInputProvider> canvas_input_provider_; Member<XRCanvasInputProvider> canvas_input_provider_;
bool environment_error_handler_subscribed_ = false; bool environment_error_handler_subscribed_ = false;
HeapHashSet<Member<ScriptPromiseResolver>> hit_test_promises_; HeapHashSet<Member<ScriptPromiseResolver>> hit_test_promises_;
// Set of promises returned from CreateAnchor that are still in-flight.
HeapHashSet<Member<ScriptPromiseResolver>> create_anchor_promises_;
HeapVector<Member<XRReferenceSpace>> reference_spaces_; HeapVector<Member<XRReferenceSpace>> reference_spaces_;
bool has_xr_focus_ = true; bool has_xr_focus_ = true;
......
...@@ -28,7 +28,9 @@ class XRSpace : public EventTargetWithInlineData { ...@@ -28,7 +28,9 @@ class XRSpace : public EventTargetWithInlineData {
explicit XRSpace(XRSession*); explicit XRSpace(XRSession*);
~XRSpace() override; ~XRSpace() override;
// Get a transform that maps from this space to mojo space. // Get a transform that maps from this space to mojo space (aka device space).
// Unless noted otherwise, all data returned over vr_service.mojom interfaces
// is relative to mojo space.
// Returns nullptr if computing a transform is not possible. // Returns nullptr if computing a transform is not possible.
virtual std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace(); virtual std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment