mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Support nullable origins and floors
This commit is contained in:
parent
0bace66f70
commit
322463450d
7 changed files with 51 additions and 27 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -6391,7 +6391,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr"
|
name = "webxr"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#b223bc02b04c8ce0905f34a58802af323457bef4"
|
source = "git+https://github.com/servo/webxr#a098d39811ad73a070b578d62606aef169aef8e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen",
|
"bindgen",
|
||||||
"euclid",
|
"euclid",
|
||||||
|
@ -6412,7 +6412,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webxr-api"
|
name = "webxr-api"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/servo/webxr#b223bc02b04c8ce0905f34a58802af323457bef4"
|
source = "git+https://github.com/servo/webxr#a098d39811ad73a070b578d62606aef169aef8e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
|
|
|
@ -134,7 +134,7 @@ impl FakeXRDeviceMethods for FakeXRDevice {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md
|
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-setviewerorigin
|
||||||
fn SetViewerOrigin(
|
fn SetViewerOrigin(
|
||||||
&self,
|
&self,
|
||||||
origin: &FakeXRRigidTransformInit,
|
origin: &FakeXRRigidTransformInit,
|
||||||
|
@ -142,7 +142,25 @@ impl FakeXRDeviceMethods for FakeXRDevice {
|
||||||
) -> Fallible<()> {
|
) -> Fallible<()> {
|
||||||
let _ = self
|
let _ = self
|
||||||
.sender
|
.sender
|
||||||
.send(MockDeviceMsg::SetViewerOrigin(get_origin(origin)?));
|
.send(MockDeviceMsg::SetViewerOrigin(Some(get_origin(origin)?)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-clearviewerorigin
|
||||||
|
fn ClearViewerOrigin(&self) {
|
||||||
|
let _ = self.sender.send(MockDeviceMsg::SetViewerOrigin(None));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-clearfloororigin
|
||||||
|
fn ClearFloorOrigin(&self) {
|
||||||
|
let _ = self.sender.send(MockDeviceMsg::SetFloorOrigin(None));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrdevice-setfloororigin
|
||||||
|
fn SetFloorOrigin(&self, origin: &FakeXRRigidTransformInit) -> Fallible<()> {
|
||||||
|
let _ = self
|
||||||
|
.sender
|
||||||
|
.send(MockDeviceMsg::SetFloorOrigin(Some(get_origin(origin)?)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,11 @@ interface FakeXRDevice {
|
||||||
// // behaves as if device was disconnected
|
// // behaves as if device was disconnected
|
||||||
// Promise<void> disconnect();
|
// Promise<void> disconnect();
|
||||||
|
|
||||||
// Sets the origin of the viewer
|
|
||||||
[Throws] void setViewerOrigin(FakeXRRigidTransformInit origin, optional boolean emulatedPosition = false);
|
[Throws] void setViewerOrigin(FakeXRRigidTransformInit origin, optional boolean emulatedPosition = false);
|
||||||
|
void clearViewerOrigin();
|
||||||
|
|
||||||
|
[Throws] void setFloorOrigin(FakeXRRigidTransformInit origin);
|
||||||
|
void clearFloorOrigin();
|
||||||
|
|
||||||
// // Simulates devices focusing and blurring sessions.
|
// // Simulates devices focusing and blurring sessions.
|
||||||
// void simulateVisibilityChange(XRVisibilityState);
|
// void simulateVisibilityChange(XRVisibilityState);
|
||||||
|
|
|
@ -77,7 +77,11 @@ impl XRFrameMethods for XRFrame {
|
||||||
return Err(Error::InvalidState);
|
return Err(Error::InvalidState);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pose = reference.get_viewer_pose(&self.data);
|
let pose = if let Some(pose) = reference.get_viewer_pose(&self.data) {
|
||||||
|
pose
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
Ok(Some(XRViewerPose::new(&self.global(), &self.session, pose)))
|
Ok(Some(XRViewerPose::new(&self.global(), &self.session, pose)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,8 @@ 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: &Frame) -> ApiViewerPose {
|
pub fn get_viewer_pose(&self, base_pose: &Frame) -> Option<ApiViewerPose> {
|
||||||
let pose = self.get_unoffset_viewer_pose(base_pose);
|
let pose = self.get_unoffset_viewer_pose(base_pose)?;
|
||||||
// in column-vector notation,
|
// in column-vector notation,
|
||||||
// get_viewer_pose(space) = get_pose(space).inverse() * get_pose(viewer_space)
|
// get_viewer_pose(space) = get_pose(space).inverse() * get_pose(viewer_space)
|
||||||
// = (get_unoffset_pose(space) * offset).inverse() * get_pose(viewer_space)
|
// = (get_unoffset_pose(space) * offset).inverse() * get_pose(viewer_space)
|
||||||
|
@ -89,14 +89,14 @@ impl XRReferenceSpace {
|
||||||
// = offset.inverse() * get_unoffset_viewer_pose(space)
|
// = offset.inverse() * get_unoffset_viewer_pose(space)
|
||||||
let offset = self.offset.transform();
|
let offset = self.offset.transform();
|
||||||
let inverse = offset.inverse();
|
let inverse = offset.inverse();
|
||||||
inverse.pre_transform(&pose)
|
Some(inverse.pre_transform(&pose))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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: &Frame) -> ApiViewerPose {
|
pub fn get_unoffset_viewer_pose(&self, base_pose: &Frame) -> Option<ApiViewerPose> {
|
||||||
let viewer_pose: ApiViewerPose = cast_transform(base_pose.transform);
|
let viewer_pose: ApiViewerPose = 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)
|
||||||
|
@ -107,7 +107,7 @@ impl XRReferenceSpace {
|
||||||
// = viewer_pose
|
// = viewer_pose
|
||||||
|
|
||||||
// we get viewer poses in eye-level space by default
|
// we get viewer poses in eye-level space by default
|
||||||
viewer_pose
|
Some(viewer_pose)
|
||||||
},
|
},
|
||||||
XRReferenceSpaceType::Local_floor => {
|
XRReferenceSpaceType::Local_floor => {
|
||||||
// XXXManishearth support getting floor info from stage parameters
|
// XXXManishearth support getting floor info from stage parameters
|
||||||
|
@ -118,12 +118,12 @@ impl XRReferenceSpace {
|
||||||
|
|
||||||
// assume approximate user height of 2 meters
|
// assume approximate user height of 2 meters
|
||||||
let floor_to_eye: ApiRigidTransform = Vector3D::new(0., 2., 0.).into();
|
let floor_to_eye: ApiRigidTransform = Vector3D::new(0., 2., 0.).into();
|
||||||
floor_to_eye.pre_transform(&viewer_pose)
|
Some(floor_to_eye.pre_transform(&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()
|
Some(RigidTransform3D::identity())
|
||||||
},
|
},
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -134,34 +134,34 @@ 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: &Frame) -> ApiPose {
|
pub fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
|
||||||
let pose = self.get_unoffset_pose(base_pose);
|
let pose = self.get_unoffset_pose(base_pose)?;
|
||||||
let offset = self.offset.transform();
|
let offset = self.offset.transform();
|
||||||
// pose is a transform from the unoffset space to native space,
|
// pose is a transform from the unoffset space to native space,
|
||||||
// offset is a transform from offset space to unoffset space,
|
// offset is a transform from offset space to unoffset space,
|
||||||
// we want a transform from unoffset space to native space,
|
// we want a transform from unoffset space to native space,
|
||||||
// which is pose * offset in column vector notation
|
// which is pose * offset in column vector notation
|
||||||
pose.pre_transform(&offset)
|
Some(pose.pre_transform(&offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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: &Frame) -> ApiPose {
|
pub fn get_unoffset_pose(&self, base_pose: &Frame) -> Option<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()
|
Some(RigidTransform3D::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()
|
Some(Vector3D::new(0., -2., 0.).into())
|
||||||
},
|
},
|
||||||
XRReferenceSpaceType::Viewer => cast_transform(base_pose.transform),
|
XRReferenceSpaceType::Viewer => base_pose.transform.map(cast_transform),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl XRSpace {
|
||||||
/// with other spaces
|
/// with other spaces
|
||||||
pub fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
|
pub fn get_pose(&self, base_pose: &Frame) -> Option<ApiPose> {
|
||||||
if let Some(reference) = self.downcast::<XRReferenceSpace>() {
|
if let Some(reference) = self.downcast::<XRReferenceSpace>() {
|
||||||
Some(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() {
|
||||||
// XXXManishearth we should be able to request frame information
|
// XXXManishearth we should be able to request frame information
|
||||||
// for inputs when necessary instead of always loading it
|
// for inputs when necessary instead of always loading it
|
||||||
|
|
|
@ -21,7 +21,6 @@ use crate::dom::promise::Promise;
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
use crate::task_source::TaskSource;
|
use crate::task_source::TaskSource;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::RigidTransform3D;
|
|
||||||
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;
|
||||||
|
@ -75,26 +74,26 @@ impl XRTestMethods for XRTest {
|
||||||
|
|
||||||
let origin = if let Some(ref o) = init.viewerOrigin {
|
let origin = if let Some(ref o) = init.viewerOrigin {
|
||||||
match get_origin(&o) {
|
match get_origin(&o) {
|
||||||
Ok(origin) => origin,
|
Ok(origin) => Some(origin),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
p.reject_error(e);
|
p.reject_error(e);
|
||||||
return p;
|
return p;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RigidTransform3D::identity()
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let floor_origin = if let Some(ref o) = init.floorOrigin {
|
let floor_origin = if let Some(ref o) = init.floorOrigin {
|
||||||
match get_origin(&o) {
|
match get_origin(&o) {
|
||||||
Ok(origin) => origin,
|
Ok(origin) => Some(origin),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
p.reject_error(e);
|
p.reject_error(e);
|
||||||
return p;
|
return p;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RigidTransform3D::identity()
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let views = match get_views(&init.views) {
|
let views = match get_views(&init.views) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue