mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Hook webxr data into XRFrame/XRView/XRSpace
This commit is contained in:
parent
104a712a28
commit
8780edb165
12 changed files with 110 additions and 106 deletions
|
@ -57,8 +57,8 @@ use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
|
||||||
use encoding_rs::{Decoder, Encoding};
|
use encoding_rs::{Decoder, Encoding};
|
||||||
use euclid::Length as EuclidLength;
|
use euclid::Length as EuclidLength;
|
||||||
use euclid::{
|
use euclid::{
|
||||||
Point2D, Rect, RigidTransform3D, Rotation3D, Transform2D, Transform3D, TypedScale, TypedSize2D,
|
Point2D, Rect, RigidTransform3D, Rotation3D, Transform2D, Transform3D, TypedRigidTransform3D,
|
||||||
Vector2D,
|
TypedScale, TypedSize2D, Vector2D,
|
||||||
};
|
};
|
||||||
use html5ever::buffer_queue::BufferQueue;
|
use html5ever::buffer_queue::BufferQueue;
|
||||||
use html5ever::{LocalName, Namespace, Prefix, QualName};
|
use html5ever::{LocalName, Namespace, Prefix, QualName};
|
||||||
|
@ -486,7 +486,7 @@ unsafe_no_jsmanaged_fields!(WebGLVersion);
|
||||||
unsafe_no_jsmanaged_fields!(WebGLSLVersion);
|
unsafe_no_jsmanaged_fields!(WebGLSLVersion);
|
||||||
unsafe_no_jsmanaged_fields!(MediaList);
|
unsafe_no_jsmanaged_fields!(MediaList);
|
||||||
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);
|
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);
|
||||||
unsafe_no_jsmanaged_fields!(webxr_api::Registry, webxr_api::Session);
|
unsafe_no_jsmanaged_fields!(webxr_api::Registry, webxr_api::Session, webxr_api::Frame);
|
||||||
unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
|
unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
|
||||||
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
||||||
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
||||||
|
@ -607,6 +607,13 @@ unsafe impl<T, U> JSTraceable for TypedScale<f32, T, U> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<T, U> JSTraceable for TypedRigidTransform3D<f32, T, U> {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn trace(&self, _trc: *mut JSTracer) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl<T> JSTraceable for EuclidLength<u64, T> {
|
unsafe impl<T> JSTraceable for EuclidLength<u64, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn trace(&self, _trc: *mut JSTracer) {
|
unsafe fn trace(&self, _trc: *mut JSTracer) {
|
||||||
|
|
|
@ -839,7 +839,7 @@ impl VRDisplay {
|
||||||
|
|
||||||
let now = self.global().as_window().Performance().Now();
|
let now = self.global().as_window().Performance().Now();
|
||||||
|
|
||||||
if let Some(session) = self.xr_session.get() {
|
if let Some(_) = self.xr_session.get() {
|
||||||
unreachable!("old webxr-on-webvr cruft")
|
unreachable!("old webxr-on-webvr cruft")
|
||||||
} else {
|
} else {
|
||||||
self.running_display_raf.set(true);
|
self.running_display_raf.set(true);
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
enum XREye {
|
enum XREye {
|
||||||
"left",
|
"left",
|
||||||
"right"
|
"right",
|
||||||
|
"unknown",
|
||||||
};
|
};
|
||||||
|
|
||||||
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||||
|
|
|
@ -15,7 +15,6 @@ use crate::dom::xrsession::XRSession;
|
||||||
use crate::dom::xrspace::XRSpace;
|
use crate::dom::xrspace::XRSpace;
|
||||||
use crate::dom::xrviewerpose::XRViewerPose;
|
use crate::dom::xrviewerpose::XRViewerPose;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use webvr_traits::WebVRFrameData;
|
|
||||||
use webxr_api::Frame;
|
use webxr_api::Frame;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -23,11 +22,11 @@ pub struct XRFrame {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
session: Dom<XRSession>,
|
session: Dom<XRSession>,
|
||||||
#[ignore_malloc_size_of = "defined in rust-webvr"]
|
#[ignore_malloc_size_of = "defined in rust-webvr"]
|
||||||
data: WebVRFrameData,
|
data: Frame,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XRFrame {
|
impl XRFrame {
|
||||||
fn new_inherited(session: &XRSession, data: WebVRFrameData) -> XRFrame {
|
fn new_inherited(session: &XRSession, data: Frame) -> XRFrame {
|
||||||
XRFrame {
|
XRFrame {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
session: Dom::from_ref(session),
|
session: Dom::from_ref(session),
|
||||||
|
@ -36,7 +35,6 @@ impl XRFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(global: &GlobalScope, session: &XRSession, data: Frame) -> DomRoot<XRFrame> {
|
pub fn new(global: &GlobalScope, session: &XRSession, data: Frame) -> DomRoot<XRFrame> {
|
||||||
let data = unimplemented!();
|
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(XRFrame::new_inherited(session, data)),
|
Box::new(XRFrame::new_inherited(session, data)),
|
||||||
global,
|
global,
|
||||||
|
@ -60,12 +58,7 @@ impl XRFrameMethods for XRFrame {
|
||||||
return Err(Error::InvalidState);
|
return Err(Error::InvalidState);
|
||||||
}
|
}
|
||||||
let pose = reference.get_viewer_pose(&self.data);
|
let pose = reference.get_viewer_pose(&self.data);
|
||||||
Ok(Some(XRViewerPose::new(
|
Ok(Some(XRViewerPose::new(&self.global(), &self.session, pose)))
|
||||||
&self.global(),
|
|
||||||
&self.session,
|
|
||||||
pose,
|
|
||||||
&self.data,
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://immersive-web.github.io/webxr/#dom-xrframe-getpose
|
/// https://immersive-web.github.io/webxr/#dom-xrframe-getpose
|
||||||
|
|
|
@ -10,10 +10,10 @@ use crate::dom::bindings::codegen::Bindings::XRInputSourceBinding::{
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::{ApiPose, XRSession};
|
||||||
use crate::dom::xrspace::XRSpace;
|
use crate::dom::xrspace::XRSpace;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState, WebVRPose};
|
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct XRInputSource {
|
pub struct XRInputSource {
|
||||||
|
@ -58,8 +58,8 @@ impl XRInputSource {
|
||||||
*self.state.borrow_mut() = state;
|
*self.state.borrow_mut() = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pose(&self) -> WebVRPose {
|
pub fn pose(&self) -> ApiPose {
|
||||||
self.state.borrow().pose
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::xrrigidtransform::XRRigidTransform;
|
use crate::dom::xrrigidtransform::XRRigidTransform;
|
||||||
|
use crate::dom::xrsession::ApiRigidTransform;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::RigidTransform3D;
|
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct XRPose {
|
pub struct XRPose {
|
||||||
|
@ -26,7 +26,7 @@ impl XRPose {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn new(global: &GlobalScope, transform: RigidTransform3D<f64>) -> DomRoot<XRPose> {
|
pub fn new(global: &GlobalScope, transform: ApiRigidTransform) -> DomRoot<XRPose> {
|
||||||
let transform = XRRigidTransform::new(global, transform);
|
let transform = XRRigidTransform::new(global, transform);
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(XRPose::new_inherited(&transform)),
|
Box::new(XRPose::new_inherited(&transform)),
|
||||||
|
|
|
@ -10,11 +10,13 @@ use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::xrrigidtransform::XRRigidTransform;
|
use crate::dom::xrrigidtransform::XRRigidTransform;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::{
|
||||||
|
cast_transform, cast_transform_to_pose, ApiPose, ApiRigidTransform, XRSession,
|
||||||
|
};
|
||||||
use crate::dom::xrspace::XRSpace;
|
use crate::dom::xrspace::XRSpace;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::{RigidTransform3D, Vector3D};
|
use euclid::{TypedRigidTransform3D, TypedVector3D};
|
||||||
use webvr_traits::WebVRFrameData;
|
use webxr_api::Frame;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct XRReferenceSpace {
|
pub struct XRReferenceSpace {
|
||||||
|
@ -80,7 +82,7 @@ impl XRReferenceSpace {
|
||||||
///
|
///
|
||||||
/// This is equivalent to `get_pose(self).inverse() * get_pose(viewerSpace)` (in column vector notation),
|
/// This is equivalent to `get_pose(self).inverse() * get_pose(viewerSpace)` (in column vector notation),
|
||||||
/// however we specialize it to be efficient
|
/// however we specialize it to be efficient
|
||||||
pub fn get_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
|
pub fn get_viewer_pose(&self, base_pose: &Frame) -> ApiRigidTransform {
|
||||||
let pose = self.get_unoffset_viewer_pose(base_pose);
|
let pose = self.get_unoffset_viewer_pose(base_pose);
|
||||||
|
|
||||||
// This may change, see https://github.com/immersive-web/webxr/issues/567
|
// This may change, see https://github.com/immersive-web/webxr/issues/567
|
||||||
|
@ -98,8 +100,8 @@ impl XRReferenceSpace {
|
||||||
/// Gets pose of the viewer with respect to this space
|
/// Gets pose of the viewer with respect to this space
|
||||||
///
|
///
|
||||||
/// Does not apply originOffset, use get_viewer_pose instead if you need it
|
/// Does not apply originOffset, use get_viewer_pose instead if you need it
|
||||||
pub fn get_unoffset_viewer_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
|
pub fn get_unoffset_viewer_pose(&self, base_pose: &Frame) -> ApiRigidTransform {
|
||||||
let viewer_pose = XRSpace::pose_to_transform(&base_pose.pose);
|
let viewer_pose = cast_transform(base_pose.transform);
|
||||||
// all math is in column-vector notation
|
// all math is in column-vector notation
|
||||||
// we use the following equation to verify correctness here:
|
// we use the following equation to verify correctness here:
|
||||||
// get_viewer_pose(space) = get_pose(space).inverse() * get_pose(viewer_space)
|
// get_viewer_pose(space) = get_pose(space).inverse() * get_pose(viewer_space)
|
||||||
|
@ -120,13 +122,13 @@ impl XRReferenceSpace {
|
||||||
// = Translate(2) * viewer_pose
|
// = Translate(2) * viewer_pose
|
||||||
|
|
||||||
// assume approximate user height of 2 meters
|
// assume approximate user height of 2 meters
|
||||||
let floor_to_eye: RigidTransform3D<f64> = Vector3D::new(0., 2., 0.).into();
|
let floor_to_eye: ApiRigidTransform = TypedVector3D::new(0., 2., 0.).into();
|
||||||
floor_to_eye.pre_mul(&viewer_pose)
|
floor_to_eye.pre_mul(&viewer_pose)
|
||||||
},
|
},
|
||||||
XRReferenceSpaceType::Viewer => {
|
XRReferenceSpaceType::Viewer => {
|
||||||
// This reference space follows the viewer around, so the viewer is
|
// This reference space follows the viewer around, so the viewer is
|
||||||
// always at an identity transform with respect to it
|
// always at an identity transform with respect to it
|
||||||
RigidTransform3D::identity()
|
TypedRigidTransform3D::identity()
|
||||||
},
|
},
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -137,7 +139,7 @@ impl XRReferenceSpace {
|
||||||
/// The reference origin used is common between all
|
/// The reference origin used is common between all
|
||||||
/// get_pose calls for spaces from the same device, so this can be used to compare
|
/// get_pose calls for spaces from the same device, so this can be used to compare
|
||||||
/// with other spaces
|
/// with other spaces
|
||||||
pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
|
pub fn get_pose(&self, base_pose: &Frame) -> ApiPose {
|
||||||
let pose = self.get_unoffset_pose(base_pose);
|
let pose = self.get_unoffset_pose(base_pose);
|
||||||
|
|
||||||
// This may change, see https://github.com/immersive-web/webxr/issues/567
|
// This may change, see https://github.com/immersive-web/webxr/issues/567
|
||||||
|
@ -148,21 +150,21 @@ impl XRReferenceSpace {
|
||||||
/// Gets pose represented by this space
|
/// Gets pose represented by this space
|
||||||
///
|
///
|
||||||
/// Does not apply originOffset, use get_viewer_pose instead if you need it
|
/// Does not apply originOffset, use get_viewer_pose instead if you need it
|
||||||
pub fn get_unoffset_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
|
pub fn get_unoffset_pose(&self, base_pose: &Frame) -> ApiPose {
|
||||||
match self.ty {
|
match self.ty {
|
||||||
XRReferenceSpaceType::Local => {
|
XRReferenceSpaceType::Local => {
|
||||||
// The eye-level pose is basically whatever the headset pose was at t=0, which
|
// The eye-level pose is basically whatever the headset pose was at t=0, which
|
||||||
// for most devices is (0, 0, 0)
|
// for most devices is (0, 0, 0)
|
||||||
RigidTransform3D::identity()
|
TypedRigidTransform3D::identity()
|
||||||
},
|
},
|
||||||
XRReferenceSpaceType::Local_floor => {
|
XRReferenceSpaceType::Local_floor => {
|
||||||
// XXXManishearth support getting floor info from stage parameters
|
// XXXManishearth support getting floor info from stage parameters
|
||||||
|
|
||||||
// Assume approximate height of 2m
|
// Assume approximate height of 2m
|
||||||
// the floor-level space is 2m below the eye-level space, which is (0, 0, 0)
|
// the floor-level space is 2m below the eye-level space, which is (0, 0, 0)
|
||||||
Vector3D::new(0., -2., 0.).into()
|
TypedVector3D::new(0., -2., 0.).into()
|
||||||
},
|
},
|
||||||
XRReferenceSpaceType::Viewer => XRSpace::pose_to_transform(&base_pose.pose),
|
XRReferenceSpaceType::Viewer => cast_transform_to_pose(base_pose.transform),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,9 @@ use crate::dom::dompointreadonly::DOMPointReadOnly;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::vrframedata::create_typed_array;
|
use crate::dom::vrframedata::create_typed_array;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
|
use crate::dom::xrsession::ApiRigidTransform;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::{RigidTransform3D, Rotation3D, Vector3D};
|
use euclid::{TypedRigidTransform3D, TypedRotation3D, TypedVector3D};
|
||||||
use js::jsapi::{Heap, JSContext, JSObject};
|
use js::jsapi::{Heap, JSContext, JSObject};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
@ -25,14 +26,14 @@ pub struct XRRigidTransform {
|
||||||
position: MutNullableDom<DOMPointReadOnly>,
|
position: MutNullableDom<DOMPointReadOnly>,
|
||||||
orientation: MutNullableDom<DOMPointReadOnly>,
|
orientation: MutNullableDom<DOMPointReadOnly>,
|
||||||
#[ignore_malloc_size_of = "defined in euclid"]
|
#[ignore_malloc_size_of = "defined in euclid"]
|
||||||
transform: RigidTransform3D<f64>,
|
transform: ApiRigidTransform,
|
||||||
inverse: MutNullableDom<XRRigidTransform>,
|
inverse: MutNullableDom<XRRigidTransform>,
|
||||||
#[ignore_malloc_size_of = "defined in mozjs"]
|
#[ignore_malloc_size_of = "defined in mozjs"]
|
||||||
matrix: Heap<*mut JSObject>,
|
matrix: Heap<*mut JSObject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XRRigidTransform {
|
impl XRRigidTransform {
|
||||||
fn new_inherited(transform: RigidTransform3D<f64>) -> XRRigidTransform {
|
fn new_inherited(transform: ApiRigidTransform) -> XRRigidTransform {
|
||||||
XRRigidTransform {
|
XRRigidTransform {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
position: MutNullableDom::default(),
|
position: MutNullableDom::default(),
|
||||||
|
@ -43,10 +44,7 @@ impl XRRigidTransform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(global: &GlobalScope, transform: ApiRigidTransform) -> DomRoot<XRRigidTransform> {
|
||||||
global: &GlobalScope,
|
|
||||||
transform: RigidTransform3D<f64>,
|
|
||||||
) -> DomRoot<XRRigidTransform> {
|
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(XRRigidTransform::new_inherited(transform)),
|
Box::new(XRRigidTransform::new_inherited(transform)),
|
||||||
global,
|
global,
|
||||||
|
@ -55,7 +53,7 @@ impl XRRigidTransform {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn identity(window: &GlobalScope) -> DomRoot<XRRigidTransform> {
|
pub fn identity(window: &GlobalScope) -> DomRoot<XRRigidTransform> {
|
||||||
let transform = RigidTransform3D::identity();
|
let transform = TypedRigidTransform3D::identity();
|
||||||
XRRigidTransform::new(window, transform)
|
XRRigidTransform::new(window, transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,14 +70,14 @@ impl XRRigidTransform {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let translate = Vector3D::new(position.x as f64, position.y as f64, position.z as f64);
|
let translate = TypedVector3D::new(position.x as f32, position.y as f32, position.z as f32);
|
||||||
let rotate = Rotation3D::unit_quaternion(
|
let rotate = TypedRotation3D::unit_quaternion(
|
||||||
orientation.x as f64,
|
orientation.x as f32,
|
||||||
orientation.y as f64,
|
orientation.y as f32,
|
||||||
orientation.z as f64,
|
orientation.z as f32,
|
||||||
orientation.w as f64,
|
orientation.w as f32,
|
||||||
);
|
);
|
||||||
let transform = RigidTransform3D::new(rotate, translate);
|
let transform = TypedRigidTransform3D::new(rotate, translate);
|
||||||
Ok(XRRigidTransform::new(&window.global(), transform))
|
Ok(XRRigidTransform::new(&window.global(), transform))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,14 +87,20 @@ impl XRRigidTransformMethods for XRRigidTransform {
|
||||||
fn Position(&self) -> DomRoot<DOMPointReadOnly> {
|
fn Position(&self) -> DomRoot<DOMPointReadOnly> {
|
||||||
self.position.or_init(|| {
|
self.position.or_init(|| {
|
||||||
let t = &self.transform.translation;
|
let t = &self.transform.translation;
|
||||||
DOMPointReadOnly::new(&self.global(), t.x, t.y, t.z, 1.0)
|
DOMPointReadOnly::new(&self.global(), t.x.into(), t.y.into(), t.z.into(), 1.0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// https://immersive-web.github.io/webxr/#dom-xrrigidtransform-orientation
|
// https://immersive-web.github.io/webxr/#dom-xrrigidtransform-orientation
|
||||||
fn Orientation(&self) -> DomRoot<DOMPointReadOnly> {
|
fn Orientation(&self) -> DomRoot<DOMPointReadOnly> {
|
||||||
self.orientation.or_init(|| {
|
self.orientation.or_init(|| {
|
||||||
let r = &self.transform.rotation;
|
let r = &self.transform.rotation;
|
||||||
DOMPointReadOnly::new(&self.global(), r.i, r.j, r.k, r.r)
|
DOMPointReadOnly::new(
|
||||||
|
&self.global(),
|
||||||
|
r.i.into(),
|
||||||
|
r.j.into(),
|
||||||
|
r.k.into(),
|
||||||
|
r.r.into(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// https://immersive-web.github.io/webxr/#dom-xrrigidtransform-inverse
|
// https://immersive-web.github.io/webxr/#dom-xrrigidtransform-inverse
|
||||||
|
@ -114,7 +118,7 @@ impl XRRigidTransformMethods for XRRigidTransform {
|
||||||
let cx = self.global().get_cx();
|
let cx = self.global().get_cx();
|
||||||
// According to the spec all matrices are column-major,
|
// According to the spec all matrices are column-major,
|
||||||
// however euclid uses row vectors so we use .to_row_major_array()
|
// however euclid uses row vectors so we use .to_row_major_array()
|
||||||
let arr = self.transform.to_transform().cast().to_row_major_array();
|
let arr = self.transform.to_transform().to_row_major_array();
|
||||||
create_typed_array(cx, &arr, &self.matrix);
|
create_typed_array(cx, &arr, &self.matrix);
|
||||||
}
|
}
|
||||||
NonNull::new(self.matrix.get()).unwrap()
|
NonNull::new(self.matrix.get()).unwrap()
|
||||||
|
@ -123,7 +127,7 @@ impl XRRigidTransformMethods for XRRigidTransform {
|
||||||
|
|
||||||
impl XRRigidTransform {
|
impl XRRigidTransform {
|
||||||
/// https://immersive-web.github.io/webxr/#dom-xrpose-transform
|
/// https://immersive-web.github.io/webxr/#dom-xrpose-transform
|
||||||
pub fn transform(&self) -> RigidTransform3D<f64> {
|
pub fn transform(&self) -> ApiRigidTransform {
|
||||||
self.transform
|
self.transform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crate::dom::xrspace::XRSpace;
|
||||||
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
||||||
use crate::task_source::TaskSource;
|
use crate::task_source::TaskSource;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::Vector3D;
|
use euclid::TypedRigidTransform3D;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use profile_traits::ipc;
|
use profile_traits::ipc;
|
||||||
|
@ -92,12 +92,9 @@ impl XRSession {
|
||||||
self.base_layer.set(Some(layer))
|
self.base_layer.set(Some(layer))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn left_eye_params_offset(&self) -> Vector3D<f64> {
|
pub fn with_session<F: FnOnce(&Session)>(&self, with: F) {
|
||||||
unimplemented!()
|
let session = self.session.borrow();
|
||||||
}
|
with(&session)
|
||||||
|
|
||||||
pub fn right_eye_params_offset(&self) -> Vector3D<f64> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://immersive-web.github.io/webxr/#xr-animation-frame
|
/// https://immersive-web.github.io/webxr/#xr-animation-frame
|
||||||
|
@ -278,3 +275,22 @@ impl XRSessionMethods for XRSession {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct ApiSpace;
|
||||||
|
// The pose of an object in native-space. Should never be exposed.
|
||||||
|
pub type ApiPose = TypedRigidTransform3D<f32, ApiSpace, webxr_api::Native>;
|
||||||
|
// A transform between objects in some API-space
|
||||||
|
pub type ApiRigidTransform = TypedRigidTransform3D<f32, ApiSpace, ApiSpace>;
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
pub fn cast_transform_to_pose<T>(
|
||||||
|
transform: TypedRigidTransform3D<f32, T, webxr_api::Native>,
|
||||||
|
) -> ApiPose {
|
||||||
|
unsafe { mem::transmute(transform) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
pub fn cast_transform<T, U>(transform: TypedRigidTransform3D<f32, T, U>) -> ApiRigidTransform {
|
||||||
|
unsafe { mem::transmute(transform) }
|
||||||
|
}
|
||||||
|
|
|
@ -10,10 +10,9 @@ use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::xrinputsource::XRInputSource;
|
use crate::dom::xrinputsource::XRInputSource;
|
||||||
use crate::dom::xrreferencespace::XRReferenceSpace;
|
use crate::dom::xrreferencespace::XRReferenceSpace;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::{ApiPose, XRSession};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::{RigidTransform3D, Rotation3D, Vector3D};
|
use webxr_api::Frame;
|
||||||
use webvr_traits::{WebVRFrameData, WebVRPose};
|
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct XRSpace {
|
pub struct XRSpace {
|
||||||
|
@ -58,30 +57,16 @@ impl XRSpace {
|
||||||
/// The reference origin used is common between all
|
/// The reference origin used is common between all
|
||||||
/// get_pose calls for spaces from the same device, so this can be used to compare
|
/// get_pose calls for spaces from the same device, so this can be used to compare
|
||||||
/// with other spaces
|
/// with other spaces
|
||||||
pub fn get_pose(&self, base_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
|
pub fn get_pose(&self, base_pose: &Frame) -> ApiPose {
|
||||||
if let Some(reference) = self.downcast::<XRReferenceSpace>() {
|
if let Some(reference) = self.downcast::<XRReferenceSpace>() {
|
||||||
reference.get_pose(base_pose)
|
reference.get_pose(base_pose)
|
||||||
} else if let Some(source) = self.input_source.get() {
|
} else if let Some(source) = self.input_source.get() {
|
||||||
XRSpace::pose_to_transform(&source.pose())
|
source.pose()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pose_to_transform(pose: &WebVRPose) -> RigidTransform3D<f64> {
|
|
||||||
let pos = pose.position.unwrap_or([0., 0., 0.]);
|
|
||||||
let translation = Vector3D::new(pos[0] as f64, pos[1] as f64, pos[2] as f64);
|
|
||||||
let orient = pose.orientation.unwrap_or([0., 0., 0., 0.]);
|
|
||||||
let rotation = Rotation3D::quaternion(
|
|
||||||
orient[0] as f64,
|
|
||||||
orient[1] as f64,
|
|
||||||
orient[2] as f64,
|
|
||||||
orient[3] as f64,
|
|
||||||
)
|
|
||||||
.normalize();
|
|
||||||
RigidTransform3D::new(rotation, translation)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn session(&self) -> &XRSession {
|
pub fn session(&self) -> &XRSession {
|
||||||
&self.session
|
&self.session
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,11 @@ use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::vrframedata::create_typed_array;
|
use crate::dom::vrframedata::create_typed_array;
|
||||||
use crate::dom::xrrigidtransform::XRRigidTransform;
|
use crate::dom::xrrigidtransform::XRRigidTransform;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::{cast_transform, ApiRigidTransform, XRSession};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::RigidTransform3D;
|
|
||||||
use js::jsapi::{Heap, JSContext, JSObject};
|
use js::jsapi::{Heap, JSContext, JSObject};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use webvr_traits::WebVRFrameData;
|
use webxr_api::View;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct XRView {
|
pub struct XRView {
|
||||||
|
@ -41,25 +40,15 @@ impl XRView {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn new(
|
pub fn new<V: Copy>(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
session: &XRSession,
|
session: &XRSession,
|
||||||
|
view: &View<V>,
|
||||||
eye: XREye,
|
eye: XREye,
|
||||||
pose: &RigidTransform3D<f64>,
|
pose: &ApiRigidTransform,
|
||||||
data: &WebVRFrameData,
|
|
||||||
) -> DomRoot<XRView> {
|
) -> DomRoot<XRView> {
|
||||||
// XXXManishearth compute and cache projection matrices on the Display
|
// XXXManishearth compute and cache projection matrices on the Display
|
||||||
let (proj, offset) = if eye == XREye::Left {
|
let offset = cast_transform(view.transform);
|
||||||
(
|
|
||||||
&data.left_projection_matrix,
|
|
||||||
session.left_eye_params_offset(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
&data.right_projection_matrix,
|
|
||||||
session.right_eye_params_offset(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let transform = pose.post_mul(&offset.into());
|
let transform = pose.post_mul(&offset.into());
|
||||||
let transform = XRRigidTransform::new(global, transform);
|
let transform = XRRigidTransform::new(global, transform);
|
||||||
|
@ -70,9 +59,11 @@ impl XRView {
|
||||||
XRViewBinding::Wrap,
|
XRViewBinding::Wrap,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// row_major since euclid uses row vectors
|
||||||
|
let proj = view.projection.to_row_major_array();
|
||||||
let cx = global.get_cx();
|
let cx = global.get_cx();
|
||||||
unsafe {
|
unsafe {
|
||||||
create_typed_array(cx, proj, &ret.proj);
|
create_typed_array(cx, &proj, &ret.proj);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,13 @@ use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::xrpose::XRPose;
|
use crate::dom::xrpose::XRPose;
|
||||||
use crate::dom::xrrigidtransform::XRRigidTransform;
|
use crate::dom::xrrigidtransform::XRRigidTransform;
|
||||||
use crate::dom::xrsession::XRSession;
|
use crate::dom::xrsession::{ApiRigidTransform, XRSession};
|
||||||
use crate::dom::xrview::XRView;
|
use crate::dom::xrview::XRView;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::RigidTransform3D;
|
|
||||||
use js::conversions::ToJSValConvertible;
|
use js::conversions::ToJSValConvertible;
|
||||||
use js::jsapi::{Heap, JSContext};
|
use js::jsapi::{Heap, JSContext};
|
||||||
use js::jsval::{JSVal, UndefinedValue};
|
use js::jsval::{JSVal, UndefinedValue};
|
||||||
use webvr_traits::WebVRFrameData;
|
use webxr_api::Views;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct XRViewerPose {
|
pub struct XRViewerPose {
|
||||||
|
@ -38,11 +37,18 @@ impl XRViewerPose {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
session: &XRSession,
|
session: &XRSession,
|
||||||
pose: RigidTransform3D<f64>,
|
pose: ApiRigidTransform,
|
||||||
data: &WebVRFrameData,
|
|
||||||
) -> DomRoot<XRViewerPose> {
|
) -> DomRoot<XRViewerPose> {
|
||||||
let left = XRView::new(global, session, XREye::Left, &pose, &data);
|
rooted_vec!(let mut views);
|
||||||
let right = XRView::new(global, session, XREye::Right, &pose, &data);
|
session.with_session(|s| match s.views() {
|
||||||
|
Views::Mono(view) => {
|
||||||
|
views.push(XRView::new(global, session, &view, XREye::Unknown, &pose))
|
||||||
|
},
|
||||||
|
Views::Stereo(left, right) => {
|
||||||
|
views.push(XRView::new(global, session, &left, XREye::Left, &pose));
|
||||||
|
views.push(XRView::new(global, session, &right, XREye::Right, &pose));
|
||||||
|
},
|
||||||
|
});
|
||||||
let transform = XRRigidTransform::new(global, pose);
|
let transform = XRRigidTransform::new(global, pose);
|
||||||
let pose = reflect_dom_object(
|
let pose = reflect_dom_object(
|
||||||
Box::new(XRViewerPose::new_inherited(&transform)),
|
Box::new(XRViewerPose::new_inherited(&transform)),
|
||||||
|
@ -53,8 +59,7 @@ impl XRViewerPose {
|
||||||
unsafe {
|
unsafe {
|
||||||
let cx = global.get_cx();
|
let cx = global.get_cx();
|
||||||
rooted!(in(cx) let mut jsval = UndefinedValue());
|
rooted!(in(cx) let mut jsval = UndefinedValue());
|
||||||
let vec = vec![left, right];
|
views.to_jsval(cx, jsval.handle_mut());
|
||||||
vec.to_jsval(cx, jsval.handle_mut());
|
|
||||||
pose.views.set(jsval.get());
|
pose.views.set(jsval.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue