aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-04-04 11:36:56 -0400
committerGitHub <noreply@github.com>2019-04-04 11:36:56 -0400
commitf1b82f8573d825a40e4fe0d32559b1acb169ac9c (patch)
treef2d1912d54abfe3f00186b177c5804d0af38952d /components/script/dom
parent3e86aec26e8f0626a6c66faa56d6edb0fce8d793 (diff)
parente055884564f6bf1db0ea2ca6af3b3aaafd4fd17b (diff)
downloadservo-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.rs6
-rw-r--r--components/script/dom/dompointreadonly.rs5
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/webidls/XRPose.webidl11
-rw-r--r--components/script/dom/webidls/XRRigidTransform.webidl4
-rw-r--r--components/script/dom/webidls/XRView.webidl3
-rw-r--r--components/script/dom/webidls/XRViewerPose.webidl3
-rw-r--r--components/script/dom/xrframe.rs17
-rw-r--r--components/script/dom/xrpose.rs44
-rw-r--r--components/script/dom/xrreferencespace.rs37
-rw-r--r--components/script/dom/xrrigidtransform.rs151
-rw-r--r--components/script/dom/xrsession.rs7
-rw-r--r--components/script/dom/xrspace.rs6
-rw-r--r--components/script/dom/xrstationaryreferencespace.rs17
-rw-r--r--components/script/dom/xrview.rs35
-rw-r--r--components/script/dom/xrviewerpose.rs28
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());
}