WebXR - anchors - fix anchor creation from hit test
Anchor creation based off of hit test result was incorrectly using unstable native origin (planes' origins may change diametrically from frame to frame) - this CL fixes the issue. Additionally, hit test logic did not correctly treat hit test results as computed based off of plane intersection - the issue did not cause any problems with hit test API, but is problematic for anchor creation API. Changes: - plane-attached anchor creation now accepts native origin information and pose relative to passed in native origin - this is done to ensure that anchor creation uses a frame of reference that is stable w.r.t. the environment (plane pose is not a correct choice as it changes when plane extents are changing) - fixed an issue in ArCoreImpl::RequestHitTest() - it would not report results as computed based off of a plane even if they were - mojom's hit test result now uses pose instead of matrix - pose is directly provided by ARCore SDK and has smaller cognitive load as it does not require considering column-major vs. row-major memory layouts - IDL - anchor creation based on hit test result and on plane no longer accepts initial pose since the spec draft has changed - initial pose was considered confusing and unnecessary since it did not extend the capabilities of the API - JS-exposed anchor creation from XRHitTestResult and from XRPlane no longer accepts an XRRigidTransform - the spec draft was already changed to account for this All other changes (parameter renames, comment updates, fixing call sites to account for parameter count changes, etc.) are related to the above major changes. Change-Id: I5acb872c5a9d9003f1f85173edd82e6e6fa002bb Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2236592 Commit-Queue: Piotr Bialecki <bialpio@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Alexander Cooper <alcooper@chromium.org> Cr-Commit-Position: refs/heads/master@{#777463}
This commit is contained in:

committed by
Commit Bot

parent
09012467f8
commit
828ed3231d
chrome/browser/android/vr/arcore_device
device/vr/public/mojom
third_party/blink
renderer
modules
web_tests
external
wpt
resources
chromium
@ -114,9 +114,11 @@ class ArCore {
|
||||
// Creates plane-attached anchor. This call will be deferred and the actual
|
||||
// call may be postponed until ARCore is in correct state and the pose of
|
||||
// the plane is known.
|
||||
virtual void CreatePlaneAttachedAnchor(const mojom::Pose& plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) = 0;
|
||||
virtual void CreatePlaneAttachedAnchor(
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) = 0;
|
||||
|
||||
// Starts processing anchor creation requests created by calls to
|
||||
// |CreateAnchor()| & |CreatePlaneAttachedAnchor()| (see above). It should be
|
||||
|
@ -797,14 +797,19 @@ void ArCoreGl::CreateAnchor(
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void ArCoreGl::CreatePlaneAnchor(mojom::PosePtr plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreatePlaneAnchorCallback callback) {
|
||||
void ArCoreGl::CreatePlaneAnchor(
|
||||
mojom::XRNativeOriginInformationPtr native_origin_information,
|
||||
mojom::PosePtr native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreatePlaneAnchorCallback callback) {
|
||||
DVLOG(2) << __func__ << ": plane_id=" << plane_id;
|
||||
|
||||
DCHECK(plane_from_anchor);
|
||||
DCHECK(native_origin_information);
|
||||
DCHECK(native_origin_from_anchor);
|
||||
DCHECK(plane_id);
|
||||
|
||||
arcore_->CreatePlaneAttachedAnchor(*plane_from_anchor, plane_id,
|
||||
arcore_->CreatePlaneAttachedAnchor(*native_origin_information,
|
||||
*native_origin_from_anchor, plane_id,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
|
@ -129,9 +129,11 @@ class ArCoreGl : public mojom::XRFrameDataProvider,
|
||||
mojom::XRNativeOriginInformationPtr native_origin_information,
|
||||
mojom::PosePtr native_origin_from_anchor,
|
||||
CreateAnchorCallback callback) override;
|
||||
void CreatePlaneAnchor(mojom::PosePtr anchor_pose,
|
||||
uint64_t plane_id,
|
||||
CreatePlaneAnchorCallback callback) override;
|
||||
void CreatePlaneAnchor(
|
||||
mojom::XRNativeOriginInformationPtr native_origin_information,
|
||||
mojom::PosePtr native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreatePlaneAnchorCallback callback) override;
|
||||
|
||||
void DetachAnchor(uint64_t anchor_id) override;
|
||||
|
||||
|
@ -647,6 +647,11 @@ ArCoreImpl::GetHitTestSubscriptionResults(
|
||||
mojom::XRHitTestSubscriptionResultsDataPtr result =
|
||||
mojom::XRHitTestSubscriptionResultsData::New();
|
||||
|
||||
DVLOG(3) << __func__
|
||||
<< ": calculating hit test subscription results, "
|
||||
"hit_test_subscription_id_to_data_.size()="
|
||||
<< hit_test_subscription_id_to_data_.size();
|
||||
|
||||
for (auto& subscription_id_and_data : hit_test_subscription_id_to_data_) {
|
||||
// First, check if we can find the current transformation for a ray. If not,
|
||||
// skip processing this subscription.
|
||||
@ -666,17 +671,23 @@ ArCoreImpl::GetHitTestSubscriptionResults(
|
||||
*maybe_mojo_from_native_origin));
|
||||
}
|
||||
|
||||
for (const auto& subscribtion_id_and_data :
|
||||
DVLOG(3)
|
||||
<< __func__
|
||||
<< ": calculating hit test subscription results for transient input, "
|
||||
"hit_test_subscription_id_to_transient_hit_test_data_.size()="
|
||||
<< hit_test_subscription_id_to_transient_hit_test_data_.size();
|
||||
|
||||
for (const auto& subscription_id_and_data :
|
||||
hit_test_subscription_id_to_transient_hit_test_data_) {
|
||||
auto input_source_ids_and_transforms =
|
||||
GetMojoFromInputSources(subscribtion_id_and_data.second.profile_name,
|
||||
GetMojoFromInputSources(subscription_id_and_data.second.profile_name,
|
||||
mojo_from_viewer, input_state);
|
||||
|
||||
result->transient_input_results.push_back(
|
||||
GetTransientHitTestSubscriptionResult(
|
||||
HitTestSubscriptionId(subscribtion_id_and_data.first),
|
||||
*subscribtion_id_and_data.second.ray,
|
||||
subscribtion_id_and_data.second.entity_types,
|
||||
HitTestSubscriptionId(subscription_id_and_data.first),
|
||||
*subscription_id_and_data.second.ray,
|
||||
subscription_id_and_data.second.entity_types,
|
||||
input_source_ids_and_transforms));
|
||||
}
|
||||
|
||||
@ -954,9 +965,10 @@ bool ArCoreImpl::RequestHitTest(
|
||||
|
||||
// Only consider trackables listed in arcore_entity_types.
|
||||
if (!base::Contains(arcore_entity_types, ar_trackable_type)) {
|
||||
DVLOG(2)
|
||||
<< __func__
|
||||
<< ": hit a trackable that is not in entity types set, ignoring it";
|
||||
DVLOG(2) << __func__
|
||||
<< ": hit a trackable that is not in entity types set, ignoring "
|
||||
"it. ar_trackable_type="
|
||||
<< ar_trackable_type;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -976,16 +988,19 @@ bool ArCoreImpl::RequestHitTest(
|
||||
// within the actual detected polygon and not just within than the larger
|
||||
// plane.
|
||||
uint64_t plane_id = 0;
|
||||
if (!hit_results->empty() && ar_trackable_type == AR_TRACKABLE_PLANE) {
|
||||
int32_t in_polygon = 0;
|
||||
if (ar_trackable_type == AR_TRACKABLE_PLANE) {
|
||||
ArPlane* ar_plane = ArAsPlane(ar_trackable.get());
|
||||
ArPlane_isPoseInPolygon(arcore_session_.get(), ar_plane,
|
||||
arcore_pose.get(), &in_polygon);
|
||||
if (!in_polygon) {
|
||||
DVLOG(2) << __func__
|
||||
<< ": hit a trackable that is not within detected polygon, "
|
||||
"ignoring it";
|
||||
continue;
|
||||
|
||||
if (!hit_results->empty()) {
|
||||
int32_t in_polygon = 0;
|
||||
ArPlane_isPoseInPolygon(arcore_session_.get(), ar_plane,
|
||||
arcore_pose.get(), &in_polygon);
|
||||
if (!in_polygon) {
|
||||
DVLOG(2) << __func__
|
||||
<< ": hit a trackable that is not within detected polygon, "
|
||||
"ignoring it";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
base::Optional<PlaneId> maybe_plane_id =
|
||||
@ -995,24 +1010,27 @@ bool ArCoreImpl::RequestHitTest(
|
||||
}
|
||||
}
|
||||
|
||||
std::array<float, 16> matrix;
|
||||
ArPose_getMatrix(arcore_session_.get(), arcore_pose.get(), matrix.data());
|
||||
|
||||
mojom::XRHitResultPtr mojo_hit = mojom::XRHitResult::New();
|
||||
|
||||
// ArPose_getMatrix returns the matrix in WebGL style column-major order
|
||||
// and gfx::Transform expects row major order.
|
||||
// clang-format off
|
||||
mojo_hit->hit_matrix = gfx::Transform(
|
||||
matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
mojo_hit->plane_id = plane_id;
|
||||
|
||||
{
|
||||
std::array<float, 7> raw_pose;
|
||||
ArPose_getPoseRaw(arcore_session_.get(), arcore_pose.get(),
|
||||
raw_pose.data());
|
||||
|
||||
gfx::Quaternion orientation(raw_pose[0], raw_pose[1], raw_pose[2],
|
||||
raw_pose[3]);
|
||||
gfx::Point3F position(raw_pose[4], raw_pose[5], raw_pose[6]);
|
||||
|
||||
mojo_hit->mojo_from_result = mojom::Pose::New(orientation, position);
|
||||
|
||||
DVLOG(3) << __func__
|
||||
<< ": adding hit test result, position=" << position.ToString()
|
||||
<< ", orientation=" << orientation.ToString()
|
||||
<< ", plane_id=" << plane_id << " (0 means no plane)";
|
||||
}
|
||||
|
||||
// Insert new results at head to preserver order from ArCore
|
||||
hit_results->insert(hit_results->begin(), std::move(mojo_hit));
|
||||
}
|
||||
@ -1040,20 +1058,25 @@ void ArCoreImpl::CreateAnchor(
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void ArCoreImpl::CreatePlaneAttachedAnchor(const mojom::Pose& plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) {
|
||||
DVLOG(2) << __func__ << ": plane_id=" << plane_id
|
||||
<< ", plane_from_anchor.position="
|
||||
<< plane_from_anchor.position.ToString()
|
||||
<< ", plane_from_anchor.orientation="
|
||||
<< plane_from_anchor.orientation.ToString();
|
||||
void ArCoreImpl::CreatePlaneAttachedAnchor(
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) {
|
||||
DVLOG(2) << __func__ << ": native_origin_information.which()="
|
||||
<< static_cast<uint32_t>(native_origin_information.which())
|
||||
<< ", plane_id=" << plane_id
|
||||
<< ", native_origin_from_anchor.position="
|
||||
<< native_origin_from_anchor.position.ToString()
|
||||
<< ", native_origin_from_anchor.orientation="
|
||||
<< native_origin_from_anchor.orientation.ToString();
|
||||
|
||||
gfx::Transform plane_from_anchor_transform =
|
||||
mojo::ConvertTo<gfx::Transform>(plane_from_anchor);
|
||||
gfx::Transform native_origin_from_anchor_transform =
|
||||
mojo::ConvertTo<gfx::Transform>(native_origin_from_anchor);
|
||||
|
||||
create_plane_attached_anchor_requests_.emplace_back(
|
||||
plane_from_anchor_transform, plane_id, std::move(callback));
|
||||
native_origin_information, native_origin_from_anchor_transform, plane_id,
|
||||
std::move(callback));
|
||||
}
|
||||
|
||||
void ArCoreImpl::ProcessAnchorCreationRequests(
|
||||
@ -1231,10 +1254,12 @@ ArCore::CreateAnchorCallback CreateAnchorRequest::TakeCallback() {
|
||||
}
|
||||
|
||||
CreatePlaneAttachedAnchorRequest::CreatePlaneAttachedAnchorRequest(
|
||||
const gfx::Transform& plane_from_anchor,
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const gfx::Transform& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
ArCore::CreateAnchorCallback callback)
|
||||
: plane_from_anchor_(plane_from_anchor),
|
||||
: native_origin_information_(native_origin_information),
|
||||
native_origin_from_anchor_(native_origin_from_anchor),
|
||||
plane_id_(plane_id),
|
||||
request_start_time_(base::TimeTicks::Now()),
|
||||
callback_(std::move(callback)) {}
|
||||
@ -1244,9 +1269,7 @@ CreatePlaneAttachedAnchorRequest::~CreatePlaneAttachedAnchorRequest() = default;
|
||||
|
||||
mojom::XRNativeOriginInformation
|
||||
CreatePlaneAttachedAnchorRequest::GetNativeOriginInformation() const {
|
||||
mojom::XRNativeOriginInformation result;
|
||||
result.set_plane_id(plane_id_);
|
||||
return result;
|
||||
return native_origin_information_;
|
||||
}
|
||||
|
||||
uint64_t CreatePlaneAttachedAnchorRequest::GetPlaneId() const {
|
||||
@ -1255,7 +1278,7 @@ uint64_t CreatePlaneAttachedAnchorRequest::GetPlaneId() const {
|
||||
|
||||
gfx::Transform CreatePlaneAttachedAnchorRequest::GetNativeOriginFromAnchor()
|
||||
const {
|
||||
return plane_from_anchor_;
|
||||
return native_origin_from_anchor_;
|
||||
}
|
||||
|
||||
base::TimeTicks CreatePlaneAttachedAnchorRequest::GetRequestStartTime() const {
|
||||
|
@ -82,14 +82,17 @@ class CreatePlaneAttachedAnchorRequest {
|
||||
|
||||
ArCore::CreateAnchorCallback TakeCallback();
|
||||
|
||||
CreatePlaneAttachedAnchorRequest(const gfx::Transform& plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
ArCore::CreateAnchorCallback callback);
|
||||
CreatePlaneAttachedAnchorRequest(
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const gfx::Transform& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
ArCore::CreateAnchorCallback callback);
|
||||
CreatePlaneAttachedAnchorRequest(CreatePlaneAttachedAnchorRequest&& other);
|
||||
~CreatePlaneAttachedAnchorRequest();
|
||||
|
||||
private:
|
||||
const gfx::Transform plane_from_anchor_;
|
||||
const mojom::XRNativeOriginInformation native_origin_information_;
|
||||
const gfx::Transform native_origin_from_anchor_;
|
||||
const uint64_t plane_id_;
|
||||
const base::TimeTicks request_start_time_;
|
||||
|
||||
@ -153,9 +156,11 @@ class ArCoreImpl : public ArCore {
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
CreateAnchorCallback callback) override;
|
||||
void CreatePlaneAttachedAnchor(const mojom::Pose& plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) override;
|
||||
void CreatePlaneAttachedAnchor(
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) override;
|
||||
|
||||
void ProcessAnchorCreationRequests(
|
||||
const gfx::Transform& mojo_from_viewer,
|
||||
|
@ -208,8 +208,9 @@ bool FakeArCore::RequestHitTest(
|
||||
const mojom::XRRayPtr& ray,
|
||||
std::vector<mojom::XRHitResultPtr>* hit_results) {
|
||||
mojom::XRHitResultPtr hit = mojom::XRHitResult::New();
|
||||
// Identity matrix - no translation and default orientation.
|
||||
hit->hit_matrix = gfx::Transform();
|
||||
// Default-constructed `hit->mojo_from_result` is fine, no need to set
|
||||
// anything.
|
||||
hit->mojo_from_result = mojom::Pose::New();
|
||||
hit_results->push_back(std::move(hit));
|
||||
|
||||
return true;
|
||||
@ -307,9 +308,11 @@ mojom::XRLightEstimationDataPtr FakeArCore::GetLightEstimationData() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void FakeArCore::CreatePlaneAttachedAnchor(const mojom::Pose& plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) {
|
||||
void FakeArCore::CreatePlaneAttachedAnchor(
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) {
|
||||
// TODO(992035): Fix this when implementing tests.
|
||||
std::move(callback).Run(mojom::CreateAnchorResult::FAILURE, 0);
|
||||
}
|
||||
|
@ -64,9 +64,11 @@ class FakeArCore : public ArCore {
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
CreateAnchorCallback callback) override;
|
||||
void CreatePlaneAttachedAnchor(const mojom::Pose& plane_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) override;
|
||||
void CreatePlaneAttachedAnchor(
|
||||
const mojom::XRNativeOriginInformation& native_origin_information,
|
||||
const mojom::Pose& native_origin_from_anchor,
|
||||
uint64_t plane_id,
|
||||
CreateAnchorCallback callback) override;
|
||||
|
||||
void ProcessAnchorCreationRequests(
|
||||
const gfx::Transform& mojo_from_viewer,
|
||||
|
@ -262,7 +262,7 @@ struct XRRay {
|
||||
};
|
||||
|
||||
struct XRHitResult {
|
||||
gfx.mojom.Transform hit_matrix;
|
||||
Pose mojo_from_result; // Pose of the result (aka intersection point).
|
||||
uint64 plane_id; // If the hit test result was computed based off of a plane,
|
||||
// the plane ID will be stored here. 0 signifies no plane.
|
||||
// TODO(https://crbug.com/657632) - make it optional once
|
||||
@ -795,7 +795,11 @@ interface XREnvironmentIntegrationProvider {
|
||||
// ignored.
|
||||
UnsubscribeFromHitTest(uint64 subscription_id);
|
||||
|
||||
// Issues a request to create an anchor attached to a session.
|
||||
// Issues a request to create a free-floating anchor (not attached to any
|
||||
// particular real world entity).
|
||||
// |native_origin_information| specifies native origin relative to which the
|
||||
// anchor is supposed to be created. |native_origin_from_anchor| describes the
|
||||
// desired pose of the newly created anchor.
|
||||
// |result| will contain status code of the request. |anchor_id| will be valid
|
||||
// only if the |result| is SUCCESS.
|
||||
CreateAnchor(
|
||||
@ -807,11 +811,18 @@ interface XREnvironmentIntegrationProvider {
|
||||
// not interested in obtaining detailed error information from the device.
|
||||
|
||||
// Issues a request to create an anchor attached to a plane.
|
||||
// |native_origin_information| specifies native origin relative to which the
|
||||
// anchor is supposed to be created. |native_origin_from_anchor| describes the
|
||||
// desired pose of the newly created anchor. |plane_id| identifies which plane
|
||||
// the anchor will be attached to.
|
||||
// |result| will contain status code of the request. |anchor_id| will be valid
|
||||
// only if the |result| is SUCCESS.
|
||||
CreatePlaneAnchor(Pose plane_from_anchor, uint64 plane_id) =>
|
||||
(CreateAnchorResult result, uint64 anchor_id);
|
||||
// TODO(https://crbug.com/657632): Ditto - make anchor_id a nullable integer..
|
||||
CreatePlaneAnchor(
|
||||
XRNativeOriginInformation native_origin_information,
|
||||
Pose native_origin_from_anchor,
|
||||
uint64 plane_id)
|
||||
=> (CreateAnchorResult result, uint64 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
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/modules/xr/xr_hit_test_result.h"
|
||||
|
||||
#include "third_party/blink/renderer/modules/xr/type_converters.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_hit_test_source.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_pose.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_reference_space.h"
|
||||
@ -18,7 +19,7 @@ XRHitTestResult::XRHitTestResult(
|
||||
const device::mojom::blink::XRHitResult& hit_result)
|
||||
: session_(session),
|
||||
mojo_from_this_(std::make_unique<TransformationMatrix>(
|
||||
hit_result.hit_matrix.matrix())),
|
||||
mojo::ConvertTo<TransformationMatrix>(hit_result.mojo_from_result))),
|
||||
plane_id_(hit_result.plane_id != 0
|
||||
? base::Optional<uint64_t>(hit_result.plane_id)
|
||||
: base::nullopt) {}
|
||||
@ -41,7 +42,6 @@ XRPose* XRHitTestResult::getPose(XRSpace* other) {
|
||||
}
|
||||
|
||||
ScriptPromise XRHitTestResult::createAnchor(ScriptState* script_state,
|
||||
XRRigidTransform* this_from_anchor,
|
||||
ExceptionState& exception_state) {
|
||||
DVLOG(2) << __func__;
|
||||
|
||||
@ -51,45 +51,45 @@ ScriptPromise XRHitTestResult::createAnchor(ScriptState* script_state,
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!this_from_anchor) {
|
||||
// TODO(https://crbug.com/954236): Revisit the approach of plane poses not
|
||||
// being stable from frame to frame - if we could guarantee that anchor poses
|
||||
// are not so dynamic, anchor creation could be improved.
|
||||
//
|
||||
// Planes are not considered stationary for the purpose of anchor creation
|
||||
// (their poses may change dramatically on a frame-by-frame basis). Grab an
|
||||
// information about reference space that is well-suited for anchor creation
|
||||
// from session:
|
||||
base::Optional<XRSession::ReferenceSpaceInformation>
|
||||
reference_space_information = session_->GetStationaryReferenceSpace();
|
||||
|
||||
if (!reference_space_information) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
XRSession::kNoRigidTransformSpecified);
|
||||
XRSession::kUnableToRetrieveMatrix);
|
||||
return {};
|
||||
}
|
||||
|
||||
const TransformationMatrix& mojo_from_space =
|
||||
reference_space_information->mojo_from_space;
|
||||
|
||||
DCHECK(mojo_from_space.IsInvertible());
|
||||
|
||||
auto space_from_mojo = mojo_from_space.Inverse();
|
||||
auto space_from_anchor = space_from_mojo * (*mojo_from_this_);
|
||||
|
||||
if (plane_id_) {
|
||||
DVLOG(2) << __func__
|
||||
<< ": hit test result's entity is a plane, creating "
|
||||
"plane-attached anchor";
|
||||
return session_->CreatePlaneAnchorHelper(
|
||||
script_state, this_from_anchor->TransformMatrix(), *plane_id_,
|
||||
script_state, space_from_anchor,
|
||||
reference_space_information->native_origin, *plane_id_,
|
||||
exception_state);
|
||||
} else {
|
||||
DVLOG(2) << __func__
|
||||
<< ": hit test result's entity is unavailable, creating "
|
||||
"free-floating anchor ";
|
||||
|
||||
// Let's create free-floating anchor since plane is unavailable. Grab an
|
||||
// information about reference space that is well-suited for anchor creation
|
||||
// from session:
|
||||
base::Optional<XRSession::ReferenceSpaceInformation>
|
||||
reference_space_information = session_->GetStationaryReferenceSpace();
|
||||
|
||||
if (!reference_space_information) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
XRSession::kUnableToRetrieveMatrix);
|
||||
return {};
|
||||
}
|
||||
|
||||
const TransformationMatrix& mojo_from_space =
|
||||
reference_space_information->mojo_from_space;
|
||||
|
||||
DCHECK(mojo_from_space.IsInvertible());
|
||||
|
||||
auto space_from_mojo = mojo_from_space.Inverse();
|
||||
auto space_from_anchor = space_from_mojo * (*mojo_from_this_) *
|
||||
this_from_anchor->TransformMatrix();
|
||||
|
||||
// Let's create free-floating anchor since plane is unavailable.
|
||||
return session_->CreateAnchorHelper(
|
||||
script_state, space_from_anchor,
|
||||
reference_space_information->native_origin, exception_state);
|
||||
|
@ -16,7 +16,6 @@ class ExceptionState;
|
||||
class ScriptState;
|
||||
class TransformationMatrix;
|
||||
class XRPose;
|
||||
class XRRigidTransform;
|
||||
class XRSession;
|
||||
class XRSpace;
|
||||
|
||||
@ -30,7 +29,6 @@ class XRHitTestResult : public ScriptWrappable {
|
||||
XRPose* getPose(XRSpace* relative_to);
|
||||
|
||||
ScriptPromise createAnchor(ScriptState* script_state,
|
||||
XRRigidTransform* initial_pose,
|
||||
ExceptionState& exception_state);
|
||||
|
||||
void Trace(Visitor* visitor) const override;
|
||||
|
@ -7,5 +7,5 @@ interface XRHitTestResult {
|
||||
XRPose? getPose(XRSpace relative_to);
|
||||
|
||||
[RuntimeEnabled=WebXRAnchors, CallWith=ScriptState, RaisesException, MeasureAs=XRHitTestResultCreateAnchor]
|
||||
Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose);
|
||||
Promise<XRAnchor> createAnchor();
|
||||
};
|
||||
|
@ -36,7 +36,7 @@ HeapVector<Member<XRHitTestResult>> XRHitTestSource::Results() {
|
||||
|
||||
for (const auto& result : last_frame_results_) {
|
||||
results.emplace_back(
|
||||
MakeGarbageCollected<XRHitTestResult>(xr_session_, result));
|
||||
MakeGarbageCollected<XRHitTestResult>(xr_session_, *result));
|
||||
}
|
||||
|
||||
return results;
|
||||
@ -47,10 +47,12 @@ void XRHitTestSource::Update(
|
||||
last_frame_results_.clear();
|
||||
|
||||
for (auto& result : hit_test_results) {
|
||||
DVLOG(3) << __func__ << ": processing hit test result, hit matrix: "
|
||||
<< result->hit_matrix.ToString()
|
||||
DVLOG(3) << __func__ << ": processing hit test result, position="
|
||||
<< result->mojo_from_result->position.ToString()
|
||||
<< ", orientation="
|
||||
<< result->mojo_from_result->orientation.ToString()
|
||||
<< ", plane_id=" << result->plane_id;
|
||||
last_frame_results_.push_back(*result);
|
||||
last_frame_results_.emplace_back(result->Clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ class XRHitTestSource : public ScriptWrappable {
|
||||
const uint64_t id_;
|
||||
Member<XRSession> xr_session_;
|
||||
|
||||
Vector<device::mojom::blink::XRHitResult> last_frame_results_;
|
||||
Vector<device::mojom::blink::XRHitResultPtr> last_frame_results_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
|
@ -8,9 +8,14 @@
|
||||
#include "third_party/blink/renderer/modules/xr/type_converters.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_object_space.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_reference_space.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_rigid_transform.h"
|
||||
#include "third_party/blink/renderer/modules/xr/xr_session.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char kUnknownPlanePose[] = "Plane pose is unknown.";
|
||||
|
||||
}
|
||||
|
||||
namespace blink {
|
||||
|
||||
XRPlane::XRPlane(uint64_t id,
|
||||
@ -92,7 +97,6 @@ HeapVector<Member<DOMPointReadOnly>> XRPlane::polygon() const {
|
||||
}
|
||||
|
||||
ScriptPromise XRPlane::createAnchor(ScriptState* script_state,
|
||||
XRRigidTransform* initial_pose,
|
||||
ExceptionState& exception_state) {
|
||||
DVLOG(2) << __func__;
|
||||
|
||||
@ -102,14 +106,37 @@ ScriptPromise XRPlane::createAnchor(ScriptState* script_state,
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!initial_pose) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
XRSession::kNoRigidTransformSpecified);
|
||||
if (!mojo_from_plane_) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
|
||||
kUnknownPlanePose);
|
||||
return {};
|
||||
}
|
||||
|
||||
// Planes are not considered stationary for the purpose of anchor creation
|
||||
// (their poses may change dramatically on a frame-by-frame basis). Grab an
|
||||
// information about reference space that is well-suited for anchor creation
|
||||
// from session:
|
||||
base::Optional<XRSession::ReferenceSpaceInformation>
|
||||
reference_space_information = session_->GetStationaryReferenceSpace();
|
||||
|
||||
if (!reference_space_information) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
XRSession::kUnableToRetrieveMatrix);
|
||||
return {};
|
||||
}
|
||||
|
||||
const TransformationMatrix& mojo_from_space =
|
||||
reference_space_information->mojo_from_space;
|
||||
|
||||
DCHECK(mojo_from_space.IsInvertible());
|
||||
|
||||
auto space_from_mojo = mojo_from_space.Inverse();
|
||||
// We'll create an anchor located at the current plane's pose:
|
||||
auto space_from_anchor = space_from_mojo * (*mojo_from_plane_);
|
||||
|
||||
return session_->CreatePlaneAnchorHelper(
|
||||
script_state, initial_pose->TransformMatrix(), id_, exception_state);
|
||||
script_state, space_from_anchor,
|
||||
reference_space_information->native_origin, id_, exception_state);
|
||||
}
|
||||
|
||||
void XRPlane::Update(const device::mojom::blink::XRPlaneData& plane_data,
|
||||
|
@ -17,7 +17,6 @@
|
||||
namespace blink {
|
||||
|
||||
class ExceptionState;
|
||||
class XRRigidTransform;
|
||||
class XRSession;
|
||||
class XRSpace;
|
||||
|
||||
@ -43,7 +42,6 @@ class XRPlane : public ScriptWrappable {
|
||||
double lastChangedTime() const;
|
||||
|
||||
ScriptPromise createAnchor(ScriptState* script_state,
|
||||
XRRigidTransform* initial_pose,
|
||||
ExceptionState& exception_state);
|
||||
|
||||
// Updates plane data from passed in |plane_data|. The resulting instance
|
||||
|
@ -21,5 +21,5 @@ interface XRPlane {
|
||||
readonly attribute DOMHighResTimeStamp lastChangedTime;
|
||||
|
||||
[CallWith=ScriptState, RaisesException, RuntimeEnabled=WebXRAnchors]
|
||||
Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose);
|
||||
Promise<XRAnchor> createAnchor();
|
||||
};
|
||||
|
@ -640,7 +640,9 @@ ScriptPromise XRSession::CreateAnchorHelper(
|
||||
|
||||
ScriptPromise XRSession::CreatePlaneAnchorHelper(
|
||||
ScriptState* script_state,
|
||||
const blink::TransformationMatrix& plane_from_anchor,
|
||||
const blink::TransformationMatrix& native_origin_from_anchor,
|
||||
const device::mojom::blink::XRNativeOriginInformation&
|
||||
native_origin_information,
|
||||
uint64_t plane_id,
|
||||
ExceptionState& exception_state) {
|
||||
DVLOG(2) << __func__ << ", plane_id=" << plane_id;
|
||||
@ -658,8 +660,9 @@ ScriptPromise XRSession::CreatePlaneAnchorHelper(
|
||||
return ScriptPromise();
|
||||
}
|
||||
|
||||
TransformationMatrix::DecomposedType decomposed_plane_from_anchor;
|
||||
if (!plane_from_anchor.Decompose(decomposed_plane_from_anchor)) {
|
||||
TransformationMatrix::DecomposedType decomposed_native_origin_from_anchor;
|
||||
if (!native_origin_from_anchor.Decompose(
|
||||
decomposed_native_origin_from_anchor)) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
kUnableToDecomposeMatrix);
|
||||
return ScriptPromise();
|
||||
@ -668,13 +671,13 @@ ScriptPromise XRSession::CreatePlaneAnchorHelper(
|
||||
// TODO(https://crbug.com/929841): Remove negation in quaternion once the bug
|
||||
// is fixed.
|
||||
device::mojom::blink::PosePtr pose_ptr = device::mojom::blink::Pose::New(
|
||||
gfx::Quaternion(-decomposed_plane_from_anchor.quaternion_x,
|
||||
-decomposed_plane_from_anchor.quaternion_y,
|
||||
-decomposed_plane_from_anchor.quaternion_z,
|
||||
decomposed_plane_from_anchor.quaternion_w),
|
||||
blink::FloatPoint3D(decomposed_plane_from_anchor.translate_x,
|
||||
decomposed_plane_from_anchor.translate_y,
|
||||
decomposed_plane_from_anchor.translate_z));
|
||||
gfx::Quaternion(-decomposed_native_origin_from_anchor.quaternion_x,
|
||||
-decomposed_native_origin_from_anchor.quaternion_y,
|
||||
-decomposed_native_origin_from_anchor.quaternion_z,
|
||||
decomposed_native_origin_from_anchor.quaternion_w),
|
||||
blink::FloatPoint3D(decomposed_native_origin_from_anchor.translate_x,
|
||||
decomposed_native_origin_from_anchor.translate_y,
|
||||
decomposed_native_origin_from_anchor.translate_z));
|
||||
|
||||
DVLOG(3) << __func__
|
||||
<< ": pose_ptr->orientation = " << pose_ptr->orientation.ToString()
|
||||
@ -684,7 +687,7 @@ ScriptPromise XRSession::CreatePlaneAnchorHelper(
|
||||
ScriptPromise promise = resolver->Promise();
|
||||
|
||||
xr_->xrEnvironmentProviderRemote()->CreatePlaneAnchor(
|
||||
std::move(pose_ptr), plane_id,
|
||||
native_origin_information.Clone(), std::move(pose_ptr), plane_id,
|
||||
WTF::Bind(&XRSession::OnCreateAnchorResult, WrapPersistent(this),
|
||||
WrapPersistent(resolver)));
|
||||
|
||||
|
@ -148,9 +148,9 @@ class XRSession final
|
||||
ExceptionState&);
|
||||
|
||||
// Helper, not IDL-exposed
|
||||
// |native_origin_from_anchor| is a matrix describing transform from native
|
||||
// origin to the initial anchor's position.
|
||||
// |native_origin_information| describes native origin telative to which the
|
||||
// |native_origin_from_anchor| is a matrix describing transform between native
|
||||
// origin and the initial anchor's position.
|
||||
// |native_origin_information| describes native origin relative to which the
|
||||
// transform is expressed.
|
||||
ScriptPromise CreateAnchorHelper(
|
||||
ScriptState* script_state,
|
||||
@ -160,12 +160,16 @@ class XRSession final
|
||||
ExceptionState& exception_state);
|
||||
|
||||
// Helper, not IDL-exposed
|
||||
// |plane_from_anchor| is a matrix describing transform from plane to the
|
||||
// initial anchor's position.
|
||||
// |native_origin_from_anchor| is a matrix describing transform between native
|
||||
// origin and the initial anchor's position.
|
||||
// |native_origin_information| describes native origin relative to which the
|
||||
// transform is expressed.
|
||||
// |plane_id| is the id of the plane to which the anchor should be attached.
|
||||
ScriptPromise CreatePlaneAnchorHelper(
|
||||
ScriptState* script_state,
|
||||
const blink::TransformationMatrix& plane_from_anchor,
|
||||
const blink::TransformationMatrix& native_origin_from_anchor,
|
||||
const device::mojom::blink::XRNativeOriginInformation&
|
||||
native_origin_information,
|
||||
uint64_t plane_id,
|
||||
ExceptionState& exception_state);
|
||||
|
||||
|
@ -1201,32 +1201,32 @@ class MockRuntime extends EventTarget {
|
||||
}
|
||||
|
||||
const hitResult = new device.mojom.XRHitResult();
|
||||
hitResult.hitMatrix = new gfx.mojom.Transform();
|
||||
|
||||
hitResult.distance = distance; // Extend the object with additional information used by higher layers.
|
||||
// It will not be serialized over mojom.
|
||||
|
||||
hitResult.hitMatrix.matrix = new Array(16);
|
||||
const matrix = new Array(16);
|
||||
|
||||
hitResult.hitMatrix.matrix[0] = x_axis.x;
|
||||
hitResult.hitMatrix.matrix[1] = x_axis.y;
|
||||
hitResult.hitMatrix.matrix[2] = x_axis.z;
|
||||
hitResult.hitMatrix.matrix[3] = 0;
|
||||
matrix[0] = x_axis.x;
|
||||
matrix[1] = x_axis.y;
|
||||
matrix[2] = x_axis.z;
|
||||
matrix[3] = 0;
|
||||
|
||||
hitResult.hitMatrix.matrix[4] = y_axis.x;
|
||||
hitResult.hitMatrix.matrix[5] = y_axis.y;
|
||||
hitResult.hitMatrix.matrix[6] = y_axis.z;
|
||||
hitResult.hitMatrix.matrix[7] = 0;
|
||||
matrix[4] = y_axis.x;
|
||||
matrix[5] = y_axis.y;
|
||||
matrix[6] = y_axis.z;
|
||||
matrix[7] = 0;
|
||||
|
||||
hitResult.hitMatrix.matrix[8] = z_axis.x;
|
||||
hitResult.hitMatrix.matrix[9] = z_axis.y;
|
||||
hitResult.hitMatrix.matrix[10] = z_axis.z;
|
||||
hitResult.hitMatrix.matrix[11] = 0;
|
||||
matrix[8] = z_axis.x;
|
||||
matrix[9] = z_axis.y;
|
||||
matrix[10] = z_axis.z;
|
||||
matrix[11] = 0;
|
||||
|
||||
hitResult.hitMatrix.matrix[12] = intersection_point.x;
|
||||
hitResult.hitMatrix.matrix[13] = intersection_point.y;
|
||||
hitResult.hitMatrix.matrix[14] = intersection_point.z;
|
||||
hitResult.hitMatrix.matrix[15] = 1;
|
||||
matrix[12] = intersection_point.x;
|
||||
matrix[13] = intersection_point.y;
|
||||
matrix[14] = intersection_point.z;
|
||||
matrix[15] = 1;
|
||||
|
||||
hitResult.mojoFromResult = XRMathHelper.decomposeRigidTransform(matrix);
|
||||
|
||||
return hitResult;
|
||||
}
|
||||
|
Reference in New Issue
Block a user