diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-04-04 11:36:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-04 11:36:56 -0400 |
commit | f1b82f8573d825a40e4fe0d32559b1acb169ac9c (patch) | |
tree | f2d1912d54abfe3f00186b177c5804d0af38952d /components/script/dom | |
parent | 3e86aec26e8f0626a6c66faa56d6edb0fce8d793 (diff) | |
parent | e055884564f6bf1db0ea2ca6af3b3aaafd4fd17b (diff) | |
download | servo-f1b82f8573d825a40e4fe0d32559b1acb169ac9c.tar.gz servo-f1b82f8573d825a40e4fe0d32559b1acb169ac9c.zip |
Auto merge of #23159 - Manishearth:rigid-transforms, r=asajeffrey
Update XR code to use rigid transforms and new pose/transform stuff from the spec
This updates our XR code to use euclid's new [RigidTransform3D type](https://github.com/servo/euclid/pull/328), which is more efficent and convenient to work with.
It additionally brings us up to speed with the spec:
- `XRViewerPose` was made a subclass of `XRPose` (https://github.com/immersive-web/webxr/pull/496)
- `XRView.viewMatrix` was removed in favor of `XRRigidTransform.inverse.matrix` (https://github.com/immersive-web/webxr/pull/531)
- `XRRigidTransform.inverse` is an attribute (https://github.com/immersive-web/webxr/pull/560)
- `XRRigidTransform` now validates positions in its constructor (https://github.com/immersive-web/webxr/pull/568)
Furthermore, it adds support for `XRRigidTransform.matrix`.
While fixing this I also noticed that our view matrix code was incorrect, we calculated view matrices as `pose.to_column_major_array()`, whereas it *should* be `pose.inverse().to_row_major_array()` (since Euclid uses row vectors, whenever the spec says it wants a column major array we should use `.to_row_major_array()` since all web specs implicitly use column vectors). For 3DOF devices poses are mostly rotations anyway, so the effective transpose behaved _like_ an inversion, but was incorrect.
This PR gets rid of `view.viewMatrix` anyway, however I felt like I should mention this discrepancy, since otherwise the replacement of `view.viewMatrix` with `view.transform.inverse.matrix` doesn't make sense
r? @jdm
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23159)
<!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 6 | ||||
-rw-r--r-- | components/script/dom/dompointreadonly.rs | 5 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webidls/XRPose.webidl | 11 | ||||
-rw-r--r-- | components/script/dom/webidls/XRRigidTransform.webidl | 4 | ||||
-rw-r--r-- | components/script/dom/webidls/XRView.webidl | 3 | ||||
-rw-r--r-- | components/script/dom/webidls/XRViewerPose.webidl | 3 | ||||
-rw-r--r-- | components/script/dom/xrframe.rs | 17 | ||||
-rw-r--r-- | components/script/dom/xrpose.rs | 44 | ||||
-rw-r--r-- | components/script/dom/xrreferencespace.rs | 37 | ||||
-rw-r--r-- | components/script/dom/xrrigidtransform.rs | 151 | ||||
-rw-r--r-- | components/script/dom/xrsession.rs | 7 | ||||
-rw-r--r-- | components/script/dom/xrspace.rs | 6 | ||||
-rw-r--r-- | components/script/dom/xrstationaryreferencespace.rs | 17 | ||||
-rw-r--r-- | components/script/dom/xrview.rs | 35 | ||||
-rw-r--r-- | components/script/dom/xrviewerpose.rs | 28 |
16 files changed, 192 insertions, 183 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 6d704ef7cb7..4ac3505be84 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -57,7 +57,8 @@ use devtools_traits::{CSSError, TimelineMarkerType, WorkerId}; use encoding_rs::{Decoder, Encoding}; use euclid::Length as EuclidLength; use euclid::{ - Point2D, Rect, Rotation3D, Transform2D, Transform3D, TypedScale, TypedSize2D, Vector2D, + Point2D, Rect, RigidTransform3D, Rotation3D, Transform2D, Transform3D, TypedScale, TypedSize2D, + Vector2D, }; use html5ever::buffer_queue::BufferQueue; use html5ever::{LocalName, Namespace, Prefix, QualName}; @@ -494,7 +495,8 @@ unsafe_no_jsmanaged_fields!(ResourceFetchTiming); unsafe_no_jsmanaged_fields!(Timespec); unsafe_no_jsmanaged_fields!(HTMLMediaElementFetchContext); unsafe_no_jsmanaged_fields!(Rotation3D<f64>, Transform2D<f32>, Transform3D<f64>); -unsafe_no_jsmanaged_fields!(Point2D<f32>, Vector2D<f32>, Rect<Au>, Rect<f32>); +unsafe_no_jsmanaged_fields!(Point2D<f32>, Vector2D<f32>, Rect<Au>); +unsafe_no_jsmanaged_fields!(Rect<f32>, RigidTransform3D<f64>); unsafe impl<'a> JSTraceable for &'a str { #[inline] diff --git a/components/script/dom/dompointreadonly.rs b/components/script/dom/dompointreadonly.rs index e8ae7aa4990..2387cb8f6d5 100644 --- a/components/script/dom/dompointreadonly.rs +++ b/components/script/dom/dompointreadonly.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::{ DOMPointReadOnlyMethods, Wrap, }; @@ -51,10 +50,6 @@ impl DOMPointReadOnly { ) -> Fallible<DomRoot<DOMPointReadOnly>> { Ok(DOMPointReadOnly::new(global, x, y, z, w)) } - - pub fn new_from_init(global: &GlobalScope, p: &DOMPointInit) -> DomRoot<DOMPointReadOnly> { - DOMPointReadOnly::new(global, p.x, p.y, p.z, p.w) - } } impl DOMPointReadOnlyMethods for DOMPointReadOnly { diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 15c2e51057c..813f4659a08 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -537,6 +537,7 @@ pub mod xmlserializer; pub mod xr; pub mod xrframe; pub mod xrlayer; +pub mod xrpose; pub mod xrreferencespace; pub mod xrrenderstate; pub mod xrrigidtransform; diff --git a/components/script/dom/webidls/XRPose.webidl b/components/script/dom/webidls/XRPose.webidl new file mode 100644 index 00000000000..a8ffd440010 --- /dev/null +++ b/components/script/dom/webidls/XRPose.webidl @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// https://immersive-web.github.io/webxr/#xrpose-interface + +[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] +interface XRPose { + readonly attribute XRRigidTransform transform; + // readonly attribute boolean emulatedPosition; +}; diff --git a/components/script/dom/webidls/XRRigidTransform.webidl b/components/script/dom/webidls/XRRigidTransform.webidl index 2131ec22356..089dc1732a6 100644 --- a/components/script/dom/webidls/XRRigidTransform.webidl +++ b/components/script/dom/webidls/XRRigidTransform.webidl @@ -9,6 +9,6 @@ interface XRRigidTransform { readonly attribute DOMPointReadOnly position; readonly attribute DOMPointReadOnly orientation; - // readonly attribute Float32Array matrix; - XRRigidTransform inverse(); + readonly attribute Float32Array matrix; + readonly attribute XRRigidTransform inverse; }; diff --git a/components/script/dom/webidls/XRView.webidl b/components/script/dom/webidls/XRView.webidl index ab81136c28d..c56342c6469 100644 --- a/components/script/dom/webidls/XRView.webidl +++ b/components/script/dom/webidls/XRView.webidl @@ -13,6 +13,5 @@ enum XREye { interface XRView { readonly attribute XREye eye; readonly attribute Float32Array projectionMatrix; - readonly attribute Float32Array viewMatrix; - // readonly attribute XRRigidTransform transform; + readonly attribute XRRigidTransform transform; }; diff --git a/components/script/dom/webidls/XRViewerPose.webidl b/components/script/dom/webidls/XRViewerPose.webidl index 8b63fd6cdb5..6a2663067ca 100644 --- a/components/script/dom/webidls/XRViewerPose.webidl +++ b/components/script/dom/webidls/XRViewerPose.webidl @@ -5,8 +5,7 @@ // https://immersive-web.github.io/webxr/#xrviewerpose-interface [SecureContext, Exposed=Window, Pref="dom.webxr.enabled"] -interface XRViewerPose { - // readonly attribute XRRigidTransform transform; +interface XRViewerPose : XRPose { // readonly attribute FrozenArray<XRView> views; // workaround until we have FrozenArray // see https://github.com/servo/servo/issues/10427#issuecomment-449593626 diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs index 37017da9a5a..c9bb240a3bf 100644 --- a/components/script/dom/xrframe.rs +++ b/components/script/dom/xrframe.rs @@ -4,13 +4,11 @@ use crate::dom::bindings::codegen::Bindings::XRFrameBinding; use crate::dom::bindings::codegen::Bindings::XRFrameBinding::XRFrameMethods; -use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; -use crate::dom::xrview::XRView; use crate::dom::xrviewerpose::XRViewerPose; use dom_struct::dom_struct; use webvr_traits::WebVRFrameData; @@ -54,20 +52,11 @@ impl XRFrameMethods for XRFrame { /// https://immersive-web.github.io/webxr/#dom-xrframe-getviewerpose fn GetViewerPose(&self, reference: &XRReferenceSpace) -> Option<DomRoot<XRViewerPose>> { let pose = reference.get_viewer_pose(&self.data); - let left = XRView::new( + Some(XRViewerPose::new( &self.global(), &self.session, - XREye::Left, - &pose, + pose, &self.data, - ); - let right = XRView::new( - &self.global(), - &self.session, - XREye::Right, - &pose, - &self.data, - ); - Some(XRViewerPose::new(&self.global(), &left, &right)) + )) } } diff --git a/components/script/dom/xrpose.rs b/components/script/dom/xrpose.rs new file mode 100644 index 00000000000..9f8aec3a366 --- /dev/null +++ b/components/script/dom/xrpose.rs @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::bindings::codegen::Bindings::XRPoseBinding; +use crate::dom::bindings::codegen::Bindings::XRPoseBinding::XRPoseMethods; +use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::globalscope::GlobalScope; +use crate::dom::xrrigidtransform::XRRigidTransform; +use dom_struct::dom_struct; +use euclid::RigidTransform3D; + +#[dom_struct] +pub struct XRPose { + reflector_: Reflector, + transform: Dom<XRRigidTransform>, +} + +impl XRPose { + pub fn new_inherited(transform: &XRRigidTransform) -> XRPose { + XRPose { + reflector_: Reflector::new(), + transform: Dom::from_ref(transform), + } + } + + #[allow(unused)] + pub fn new(global: &GlobalScope, transform: RigidTransform3D<f64>) -> DomRoot<XRPose> { + let transform = XRRigidTransform::new(global, transform); + reflect_dom_object( + Box::new(XRPose::new_inherited(&transform)), + global, + XRPoseBinding::Wrap, + ) + } +} + +impl XRPoseMethods for XRPose { + /// https://immersive-web.github.io/webxr/#dom-xrpose-transform + fn Transform(&self) -> DomRoot<XRRigidTransform> { + DomRoot::from_ref(&self.transform) + } +} diff --git a/components/script/dom/xrreferencespace.rs b/components/script/dom/xrreferencespace.rs index 1c137d575ce..ed42d63b4be 100644 --- a/components/script/dom/xrreferencespace.rs +++ b/components/script/dom/xrreferencespace.rs @@ -7,14 +7,13 @@ use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenc use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::{DomRoot, MutDom}; -use crate::dom::dompointreadonly::DOMPointReadOnly; -use crate::dom::window::Window; +use crate::dom::globalscope::GlobalScope; use crate::dom::xrrigidtransform::XRRigidTransform; use crate::dom::xrsession::XRSession; use crate::dom::xrspace::XRSpace; use crate::dom::xrstationaryreferencespace::XRStationaryReferenceSpace; use dom_struct::dom_struct; -use euclid::Transform3D; +use euclid::RigidTransform3D; use webvr_traits::WebVRFrameData; #[dom_struct] @@ -32,22 +31,7 @@ impl XRReferenceSpace { } #[allow(unused)] - pub fn new( - global: &Window, - session: &XRSession, - position: &DOMPointReadOnly, - orientation: &DOMPointReadOnly, - ) -> DomRoot<XRReferenceSpace> { - let transform = XRRigidTransform::new(global, position, orientation); - reflect_dom_object( - Box::new(XRReferenceSpace::new_inherited(session, &transform)), - global, - XRReferenceSpaceBinding::Wrap, - ) - } - - #[allow(unused)] - pub fn identity(global: &Window, session: &XRSession) -> DomRoot<XRReferenceSpace> { + pub fn identity(global: &GlobalScope, session: &XRSession) -> DomRoot<XRReferenceSpace> { let transform = XRRigidTransform::identity(global); reflect_dom_object( Box::new(XRReferenceSpace::new_inherited(session, &transform)), @@ -71,30 +55,25 @@ impl XRReferenceSpaceMethods for XRReferenceSpace { impl XRReferenceSpace { /// Gets viewer pose represented by this space - pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> Transform3D<f64> { + pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { let pose = self.get_pose(base_pose); // This may change, see https://github.com/immersive-web/webxr/issues/567 - let offset = self.transform.get().matrix(); - // XXXManishearth we can directly compute the inverse from the transform parameters - // (and perhaps cache it) - // XXXManishearth we can also optimize for the unset/identity offset case - let inverse = offset - .inverse() - .expect("rigid transforms are always invertible"); + let offset = self.transform.get().transform(); + let inverse = offset.inverse(); inverse.pre_mul(&pose) } /// Gets pose represented by this space /// /// Does not apply originOffset, use get_viewer_pose instead if you need it - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> Transform3D<f64> { + pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { if let Some(stationary) = self.downcast::<XRStationaryReferenceSpace>() { stationary.get_pose(base_pose) } else { // non-subclassed XRReferenceSpaces exist, obtained via the "identity" // type. The pose does not depend on the base pose. - Transform3D::identity() + RigidTransform3D::identity() } } } diff --git a/components/script/dom/xrrigidtransform.rs b/components/script/dom/xrrigidtransform.rs index ad7cbe7543b..030905d84fa 100644 --- a/components/script/dom/xrrigidtransform.rs +++ b/components/script/dom/xrrigidtransform.rs @@ -3,77 +3,59 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; -use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointReadOnlyBinding::DOMPointReadOnlyMethods; use crate::dom::bindings::codegen::Bindings::XRRigidTransformBinding; use crate::dom::bindings::codegen::Bindings::XRRigidTransformBinding::XRRigidTransformMethods; +use crate::dom::bindings::error::Error; use crate::dom::bindings::error::Fallible; use crate::dom::bindings::reflector::DomObject; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; -use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::dompointreadonly::DOMPointReadOnly; +use crate::dom::globalscope::GlobalScope; +use crate::dom::vrframedata::create_typed_array; use crate::dom::window::Window; use dom_struct::dom_struct; -use euclid::{Rotation3D, Transform3D}; +use euclid::{RigidTransform3D, Rotation3D, Vector3D}; +use js::jsapi::{Heap, JSContext, JSObject}; +use std::ptr::NonNull; #[dom_struct] pub struct XRRigidTransform { reflector_: Reflector, - position: Dom<DOMPointReadOnly>, - orientation: Dom<DOMPointReadOnly>, + position: MutNullableDom<DOMPointReadOnly>, + orientation: MutNullableDom<DOMPointReadOnly>, #[ignore_malloc_size_of = "defined in euclid"] - translate: Transform3D<f64>, - #[ignore_malloc_size_of = "defined in euclid"] - rotate: Rotation3D<f64>, + transform: RigidTransform3D<f64>, + inverse: MutNullableDom<XRRigidTransform>, + matrix: Heap<*mut JSObject>, } impl XRRigidTransform { - fn new_inherited( - position: &DOMPointReadOnly, - orientation: &DOMPointReadOnly, - ) -> XRRigidTransform { - let translate = Transform3D::create_translation( - position.X() as f64, - position.Y() as f64, - position.Z() as f64, - ); - let rotate = Rotation3D::unit_quaternion( - orientation.X() as f64, - orientation.Y() as f64, - orientation.Z() as f64, - orientation.W() as f64, - ); + fn new_inherited(transform: RigidTransform3D<f64>) -> XRRigidTransform { XRRigidTransform { reflector_: Reflector::new(), - position: Dom::from_ref(position), - orientation: Dom::from_ref(orientation), - translate, - rotate, + position: MutNullableDom::default(), + orientation: MutNullableDom::default(), + transform, + inverse: MutNullableDom::default(), + matrix: Heap::default(), } } - #[allow(unused)] pub fn new( - global: &Window, - position: &DOMPointReadOnly, - orientation: &DOMPointReadOnly, + global: &GlobalScope, + transform: RigidTransform3D<f64>, ) -> DomRoot<XRRigidTransform> { reflect_dom_object( - Box::new(XRRigidTransform::new_inherited(position, orientation)), + Box::new(XRRigidTransform::new_inherited(transform)), global, XRRigidTransformBinding::Wrap, ) } - #[allow(unused)] - pub fn identity(window: &Window) -> DomRoot<XRRigidTransform> { - let global = window.global(); - let position = DOMPointReadOnly::new(&global, 0., 0., 0., 1.); - let orientation = DOMPointReadOnly::new(&global, 0., 0., 0., 1.); - reflect_dom_object( - Box::new(XRRigidTransform::new_inherited(&position, &orientation)), - window, - XRRigidTransformBinding::Wrap, - ) + pub fn identity(window: &GlobalScope) -> DomRoot<XRRigidTransform> { + let transform = RigidTransform3D::identity(); + XRRigidTransform::new(window, transform) } // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-xrrigidtransform @@ -82,65 +64,62 @@ impl XRRigidTransform { position: &DOMPointInit, orientation: &DOMPointInit, ) -> Fallible<DomRoot<Self>> { - let global = window.global(); - let position = DOMPointReadOnly::new_from_init(&global, &position); - // XXXManishearth normalize this - let orientation = DOMPointReadOnly::new_from_init(&global, &orientation); - Ok(XRRigidTransform::new(window, &position, &orientation)) + if position.w != 1.0 { + return Err(Error::Type(format!( + "XRRigidTransform must be constructed with a position that has a w value of of 1.0, not {}", + position.w + ))); + } + + let translate = Vector3D::new(position.x as f64, position.y as f64, position.z as f64); + let rotate = Rotation3D::unit_quaternion( + orientation.x as f64, + orientation.y as f64, + orientation.z as f64, + orientation.w as f64, + ); + let transform = RigidTransform3D::new(rotate, translate); + Ok(XRRigidTransform::new(&window.global(), transform)) } } impl XRRigidTransformMethods for XRRigidTransform { // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-position fn Position(&self) -> DomRoot<DOMPointReadOnly> { - DomRoot::from_ref(&self.position) + self.position.or_init(|| { + let t = &self.transform.translation; + DOMPointReadOnly::new(&self.global(), t.x, t.y, t.z, 1.0) + }) } // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-orientation fn Orientation(&self) -> DomRoot<DOMPointReadOnly> { - DomRoot::from_ref(&self.orientation) + self.position.or_init(|| { + let r = &self.transform.rotation; + DOMPointReadOnly::new(&self.global(), r.i, r.j, r.k, r.r) + }) } // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-inverse fn Inverse(&self) -> DomRoot<XRRigidTransform> { - // An XRRigidTransform is a rotation and a translation, - // i.e. T * R - // - // Its inverse is (T * R)^-1 - // = R^-1 * T^-1 - // = R^-1 * T^-1 * (R * R^-1) - // = (R^-1 * T^-1 * R) * R^-1 - // = T' * R^-1 - // = T' * R' - // - // (R^-1 * T^-1 * R) is a translation matrix, and R^-1 is a - // rotation matrix, so we can use these in the new rigid transform - let r_1 = self.rotate.inverse(); - let t_1 = self - .translate - .inverse() - .expect("translation matrices should be invertible"); - let t_p = r_1 - .to_transform() - .post_mul(&t_1) - .post_mul(&self.rotate.to_transform()); - - let global = self.global(); - let position = - DOMPointReadOnly::new(&global, t_p.m41.into(), t_p.m42.into(), t_p.m43.into(), 1.); - let orientation = DOMPointReadOnly::new( - &global, - r_1.i.into(), - r_1.j.into(), - r_1.k.into(), - r_1.r.into(), - ); - XRRigidTransform::new(global.as_window(), &position, &orientation) + self.inverse + .or_init(|| XRRigidTransform::new(&self.global(), self.transform.inverse())) + } + // https://immersive-web.github.io/webxr/#dom-xrrigidtransform-matrix + #[allow(unsafe_code)] + unsafe fn Matrix(&self, _cx: *mut JSContext) -> NonNull<JSObject> { + if self.matrix.get().is_null() { + let cx = self.global().get_cx(); + // According to the spec all matrices are column-major, + // however euclid uses row vectors so we use .to_row_major_array() + let arr = self.transform.to_transform().cast().to_row_major_array(); + create_typed_array(cx, &arr, &self.matrix); + } + NonNull::new(self.matrix.get()).unwrap() } } impl XRRigidTransform { - pub fn matrix(&self) -> Transform3D<f64> { - // Spec says the orientation applies first, - // so post-multiply (?) - self.translate.post_mul(&self.rotate.to_transform()) + /// https://immersive-web.github.io/webxr/#dom-xrpose-transform + pub fn transform(&self) -> RigidTransform3D<f64> { + self.transform } } diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index 8c96ab66094..bf7dcb92258 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -115,15 +115,12 @@ impl XRSessionMethods for XRSession { match options.type_ { XRReferenceSpaceType::Identity => { - p.resolve_native(&XRReferenceSpace::identity( - &self.global().as_window(), - self, - )); + p.resolve_native(&XRReferenceSpace::identity(&self.global(), self)); }, XRReferenceSpaceType::Stationary => { if let Some(subtype) = options.subtype { p.resolve_native(&XRStationaryReferenceSpace::new( - &self.global().as_window(), + &self.global(), self, subtype, )); diff --git a/components/script/dom/xrspace.rs b/components/script/dom/xrspace.rs index 9dc82e388e5..60589be4054 100644 --- a/components/script/dom/xrspace.rs +++ b/components/script/dom/xrspace.rs @@ -11,7 +11,7 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; -use euclid::Transform3D; +use euclid::RigidTransform3D; use webvr_traits::WebVRFrameData; #[dom_struct] @@ -41,7 +41,7 @@ impl XRSpace { impl XRSpace { /// Gets viewer pose represented by this space #[allow(unused)] - pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> Transform3D<f64> { + pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { if let Some(reference) = self.downcast::<XRReferenceSpace>() { reference.get_viewer_pose(base_pose) } else { @@ -53,7 +53,7 @@ impl XRSpace { /// /// Does not apply originOffset, use get_viewer_pose instead if you need it #[allow(unused)] - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> Transform3D<f64> { + pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { if let Some(reference) = self.downcast::<XRReferenceSpace>() { reference.get_pose(base_pose) } else { diff --git a/components/script/dom/xrstationaryreferencespace.rs b/components/script/dom/xrstationaryreferencespace.rs index e8349ef3581..ddba9aaa20b 100644 --- a/components/script/dom/xrstationaryreferencespace.rs +++ b/components/script/dom/xrstationaryreferencespace.rs @@ -6,12 +6,12 @@ use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding; use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding::XRStationaryReferenceSpaceSubtype; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::DomRoot; -use crate::dom::window::Window; +use crate::dom::globalscope::GlobalScope; use crate::dom::xrreferencespace::XRReferenceSpace; use crate::dom::xrrigidtransform::XRRigidTransform; use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; -use euclid::{Rotation3D, Transform3D}; +use euclid::{RigidTransform3D, Rotation3D, Vector3D}; use webvr_traits::WebVRFrameData; #[dom_struct] @@ -34,16 +34,16 @@ impl XRStationaryReferenceSpace { } pub fn new( - window: &Window, + global: &GlobalScope, session: &XRSession, ty: XRStationaryReferenceSpaceSubtype, ) -> DomRoot<XRStationaryReferenceSpace> { - let transform = XRRigidTransform::identity(window); + let transform = XRRigidTransform::identity(global); reflect_dom_object( Box::new(XRStationaryReferenceSpace::new_inherited( session, ty, &transform, )), - window, + global, XRStationaryReferenceSpaceBinding::Wrap, ) } @@ -53,11 +53,10 @@ impl XRStationaryReferenceSpace { /// Gets pose represented by this space /// /// Does not apply originOffset, use get_viewer_pose instead - pub fn get_pose(&self, base_pose: &WebVRFrameData) -> Transform3D<f64> { + pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> { // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled let pos = base_pose.pose.position.unwrap_or([0., 0., 0.]); - let translation = - Transform3D::create_translation(pos[0] as f64, pos[1] as f64, pos[2] as f64); + let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64); let orient = base_pose.pose.orientation.unwrap_or([0., 0., 0., 0.]); let rotation = Rotation3D::quaternion( orient[0] as f64, @@ -65,6 +64,6 @@ impl XRStationaryReferenceSpace { orient[2] as f64, orient[3] as f64, ); - translation.pre_mul(&rotation.to_transform()) + RigidTransform3D::new(rotation, translation) } } diff --git a/components/script/dom/xrview.rs b/components/script/dom/xrview.rs index 355177880a8..a2eee03581d 100644 --- a/components/script/dom/xrview.rs +++ b/components/script/dom/xrview.rs @@ -8,9 +8,10 @@ use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; use crate::dom::vrframedata::create_typed_array; +use crate::dom::xrrigidtransform::XRRigidTransform; use crate::dom::xrsession::XRSession; use dom_struct::dom_struct; -use euclid::Transform3D; +use euclid::{RigidTransform3D, Vector3D}; use js::jsapi::{Heap, JSContext, JSObject}; use std::ptr::NonNull; use webvr_traits::WebVRFrameData; @@ -22,16 +23,18 @@ pub struct XRView { eye: XREye, proj: Heap<*mut JSObject>, view: Heap<*mut JSObject>, + transform: Dom<XRRigidTransform>, } impl XRView { - fn new_inherited(session: &XRSession, eye: XREye) -> XRView { + fn new_inherited(session: &XRSession, transform: &XRRigidTransform, eye: XREye) -> XRView { XRView { reflector_: Reflector::new(), session: Dom::from_ref(session), eye, proj: Heap::default(), view: Heap::default(), + transform: Dom::from_ref(transform), } } @@ -40,15 +43,9 @@ impl XRView { global: &GlobalScope, session: &XRSession, eye: XREye, - pose: &Transform3D<f64>, + pose: &RigidTransform3D<f64>, data: &WebVRFrameData, ) -> DomRoot<XRView> { - let ret = reflect_dom_object( - Box::new(XRView::new_inherited(session, eye)), - global, - XRViewBinding::Wrap, - ); - let vr_display = session.display(); // XXXManishearth compute and cache projection matrices on the Display @@ -64,14 +61,19 @@ impl XRView { ) }; - let offset = - Transform3D::create_translation(offset[0] as f64, offset[1] as f64, offset[2] as f64); - let view = pose.post_mul(&offset).cast().to_column_major_array(); + let offset = Vector3D::new(offset[0] as f64, offset[1] as f64, offset[2] as f64); + let transform = pose.post_mul(&offset.into()); + let transform = XRRigidTransform::new(global, transform); + + let ret = reflect_dom_object( + Box::new(XRView::new_inherited(session, &transform, eye)), + global, + XRViewBinding::Wrap, + ); let cx = global.get_cx(); unsafe { create_typed_array(cx, proj, &ret.proj); - create_typed_array(cx, &view, &ret.view); } ret } @@ -93,9 +95,8 @@ impl XRViewMethods for XRView { NonNull::new(self.proj.get()).unwrap() } - #[allow(unsafe_code)] - /// https://immersive-web.github.io/webxr/#dom-xrview-projectionmatrix - unsafe fn ViewMatrix(&self, _cx: *mut JSContext) -> NonNull<JSObject> { - NonNull::new(self.view.get()).unwrap() + /// https://immersive-web.github.io/webxr/#dom-xrview-transform + fn Transform(&self) -> DomRoot<XRRigidTransform> { + DomRoot::from_ref(&self.transform) } } diff --git a/components/script/dom/xrviewerpose.rs b/components/script/dom/xrviewerpose.rs index af26b23aeb1..717fdcea16e 100644 --- a/components/script/dom/xrviewerpose.rs +++ b/components/script/dom/xrviewerpose.rs @@ -2,35 +2,49 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::dom::bindings::codegen::Bindings::XRViewBinding::XREye; use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding; use crate::dom::bindings::codegen::Bindings::XRViewerPoseBinding::XRViewerPoseMethods; -use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; +use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::DomRoot; use crate::dom::globalscope::GlobalScope; +use crate::dom::xrpose::XRPose; +use crate::dom::xrrigidtransform::XRRigidTransform; +use crate::dom::xrsession::XRSession; use crate::dom::xrview::XRView; use dom_struct::dom_struct; +use euclid::RigidTransform3D; use js::conversions::ToJSValConvertible; use js::jsapi::{Heap, JSContext}; use js::jsval::{JSVal, UndefinedValue}; +use webvr_traits::WebVRFrameData; #[dom_struct] pub struct XRViewerPose { - reflector_: Reflector, + pose: XRPose, views: Heap<JSVal>, } impl XRViewerPose { - fn new_inherited() -> XRViewerPose { + fn new_inherited(transform: &XRRigidTransform) -> XRViewerPose { XRViewerPose { - reflector_: Reflector::new(), + pose: XRPose::new_inherited(transform), views: Heap::default(), } } #[allow(unsafe_code)] - pub fn new(global: &GlobalScope, left: &XRView, right: &XRView) -> DomRoot<XRViewerPose> { + pub fn new( + global: &GlobalScope, + session: &XRSession, + pose: RigidTransform3D<f64>, + data: &WebVRFrameData, + ) -> DomRoot<XRViewerPose> { + let left = XRView::new(global, session, XREye::Left, &pose, &data); + let right = XRView::new(global, session, XREye::Right, &pose, &data); + let transform = XRRigidTransform::new(global, pose); let pose = reflect_dom_object( - Box::new(XRViewerPose::new_inherited()), + Box::new(XRViewerPose::new_inherited(&transform)), global, XRViewerPoseBinding::Wrap, ); @@ -38,7 +52,7 @@ impl XRViewerPose { unsafe { let cx = global.get_cx(); rooted!(in(cx) let mut jsval = UndefinedValue()); - let vec = vec![DomRoot::from_ref(left), DomRoot::from_ref(right)]; + let vec = vec![left, right]; vec.to_jsval(cx, jsval.handle_mut()); pose.views.set(jsval.get()); } |