aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/xrrigidtransform.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/xrrigidtransform.rs')
-rw-r--r--components/script/dom/xrrigidtransform.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/components/script/dom/xrrigidtransform.rs b/components/script/dom/xrrigidtransform.rs
index 3f726475517..ad7cbe7543b 100644
--- a/components/script/dom/xrrigidtransform.rs
+++ b/components/script/dom/xrrigidtransform.rs
@@ -3,6 +3,7 @@
* 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::Fallible;
@@ -12,12 +13,17 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::dompointreadonly::DOMPointReadOnly;
use crate::dom::window::Window;
use dom_struct::dom_struct;
+use euclid::{Rotation3D, Transform3D};
#[dom_struct]
pub struct XRRigidTransform {
reflector_: Reflector,
position: Dom<DOMPointReadOnly>,
orientation: Dom<DOMPointReadOnly>,
+ #[ignore_malloc_size_of = "defined in euclid"]
+ translate: Transform3D<f64>,
+ #[ignore_malloc_size_of = "defined in euclid"]
+ rotate: Rotation3D<f64>,
}
impl XRRigidTransform {
@@ -25,10 +31,23 @@ impl XRRigidTransform {
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,
+ );
XRRigidTransform {
reflector_: Reflector::new(),
position: Dom::from_ref(position),
orientation: Dom::from_ref(orientation),
+ translate,
+ rotate,
}
}
@@ -65,6 +84,7 @@ impl XRRigidTransform {
) -> 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))
}
@@ -79,4 +99,48 @@ impl XRRigidTransformMethods for XRRigidTransform {
fn Orientation(&self) -> DomRoot<DOMPointReadOnly> {
DomRoot::from_ref(&self.orientation)
}
+ // 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)
+ }
+}
+
+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())
+ }
}