1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit;
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::{DomRoot, MutNullableDom};
use crate::dom::bindings::utils::create_typed_array;
use crate::dom::dompointreadonly::DOMPointReadOnly;
use crate::dom::globalscope::GlobalScope;
use crate::dom::window::Window;
use crate::dom::xrsession::ApiRigidTransform;
use crate::script_runtime::JSContext;
use dom_struct::dom_struct;
use euclid::{RigidTransform3D, Rotation3D, Vector3D};
use js::jsapi::{Heap, JSObject};
use std::ptr::NonNull;
#[dom_struct]
pub struct XRRigidTransform {
reflector_: Reflector,
position: MutNullableDom<DOMPointReadOnly>,
orientation: MutNullableDom<DOMPointReadOnly>,
#[ignore_malloc_size_of = "defined in euclid"]
transform: ApiRigidTransform,
inverse: MutNullableDom<XRRigidTransform>,
#[ignore_malloc_size_of = "defined in mozjs"]
matrix: Heap<*mut JSObject>,
}
impl XRRigidTransform {
fn new_inherited(transform: ApiRigidTransform) -> XRRigidTransform {
XRRigidTransform {
reflector_: Reflector::new(),
position: MutNullableDom::default(),
orientation: MutNullableDom::default(),
transform,
inverse: MutNullableDom::default(),
matrix: Heap::default(),
}
}
pub fn new(global: &GlobalScope, transform: ApiRigidTransform) -> DomRoot<XRRigidTransform> {
reflect_dom_object(Box::new(XRRigidTransform::new_inherited(transform)), global)
}
pub fn identity(window: &GlobalScope) -> DomRoot<XRRigidTransform> {
let transform = RigidTransform3D::identity();
XRRigidTransform::new(window, transform)
}
#[allow(non_snake_case)]
pub fn Constructor(
window: &Window,
position: &DOMPointInit,
orientation: &DOMPointInit,
) -> Fallible<DomRoot<Self>> {
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 f32, position.y as f32, position.z as f32);
let rotate = Rotation3D::unit_quaternion(
orientation.x as f32,
orientation.y as f32,
orientation.z as f32,
orientation.w as f32,
);
if !rotate.i.is_finite() {
return Err(Error::InvalidState);
}
let transform = RigidTransform3D::new(rotate, translate);
Ok(XRRigidTransform::new(&window.global(), transform))
}
}
impl XRRigidTransformMethods for XRRigidTransform {
fn Position(&self) -> DomRoot<DOMPointReadOnly> {
self.position.or_init(|| {
let t = &self.transform.translation;
DOMPointReadOnly::new(&self.global(), t.x.into(), t.y.into(), t.z.into(), 1.0)
})
}
fn Orientation(&self) -> DomRoot<DOMPointReadOnly> {
self.orientation.or_init(|| {
let r = &self.transform.rotation;
DOMPointReadOnly::new(
&self.global(),
r.i.into(),
r.j.into(),
r.k.into(),
r.r.into(),
)
})
}
fn Inverse(&self) -> DomRoot<XRRigidTransform> {
self.inverse.or_init(|| {
let transform = XRRigidTransform::new(&self.global(), self.transform.inverse());
transform.inverse.set(Some(self));
transform
})
}
fn Matrix(&self, _cx: JSContext) -> NonNull<JSObject> {
if self.matrix.get().is_null() {
let cx = self.global().get_cx();
let arr = self.transform.to_transform().to_row_major_array();
create_typed_array(cx, &arr, &self.matrix);
}
NonNull::new(self.matrix.get()).unwrap()
}
}
impl XRRigidTransform {
pub fn transform(&self) -> ApiRigidTransform {
self.transform
}
}