mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Finish the integration of webxr
into the Cargo workspace (#35229)
- Run `cargo fmt` on `webxr` and `webxr-api` - Fix clippy warnings in the existing `webxr` code - Integrate the new crates into the workspace - Expose `webxr` via the libservo API rather than requiring embedders to depend on it explicitly. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
a4c6c205d2
commit
5466c27f6f
41 changed files with 448 additions and 649 deletions
|
@ -1,14 +1,12 @@
|
|||
[package]
|
||||
name = "webxr-api"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
edition = "2018"
|
||||
|
||||
homepage = "https://github.com/servo/webxr"
|
||||
repository = "https://github.com/servo/webxr"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
publish.workspace = true
|
||||
rust-version.workspace = true
|
||||
keywords = ["ar", "headset", "openxr", "vr", "webxr"]
|
||||
license = "MPL-2.0"
|
||||
|
||||
description = '''A safe Rust API that provides a way to interact with
|
||||
virtual reality and augmented reality devices and integration with OpenXR.
|
||||
The API is inspired by the WebXR Device API (https://www.w3.org/TR/webxr/)
|
||||
|
@ -21,8 +19,8 @@ path = "lib.rs"
|
|||
ipc = ["serde", "ipc-channel", "euclid/serde"]
|
||||
|
||||
[dependencies]
|
||||
euclid = "0.22"
|
||||
ipc-channel = { version = "0.19", optional = true }
|
||||
log = "0.4"
|
||||
serde = { version = "1.0", optional = true }
|
||||
time = { version = "0.1", optional = true }
|
||||
euclid = { workspace = true }
|
||||
ipc-channel = { workspace = true, optional = true }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
time_03 = { workspace = true, optional = true }
|
||||
|
|
|
@ -4,28 +4,14 @@
|
|||
|
||||
//! Traits to be implemented by backends
|
||||
|
||||
use crate::ContextId;
|
||||
use crate::EnvironmentBlendMode;
|
||||
use crate::Error;
|
||||
use crate::Event;
|
||||
use crate::Floor;
|
||||
use crate::Frame;
|
||||
use crate::HitTestId;
|
||||
use crate::HitTestSource;
|
||||
use crate::InputSource;
|
||||
use crate::LayerId;
|
||||
use crate::LayerInit;
|
||||
use crate::Native;
|
||||
use crate::Quitter;
|
||||
use crate::Sender;
|
||||
use crate::Session;
|
||||
use crate::SessionBuilder;
|
||||
use crate::SessionInit;
|
||||
use crate::SessionMode;
|
||||
use crate::Viewports;
|
||||
|
||||
use euclid::{Point2D, RigidTransform3D};
|
||||
|
||||
use crate::{
|
||||
ContextId, EnvironmentBlendMode, Error, Event, Floor, Frame, HitTestId, HitTestSource,
|
||||
InputSource, LayerId, LayerInit, Native, Quitter, Sender, Session, SessionBuilder, SessionInit,
|
||||
SessionMode, Viewports,
|
||||
};
|
||||
|
||||
/// A trait for discovering XR devices
|
||||
pub trait DiscoveryAPI<GL>: 'static {
|
||||
fn request_session(
|
||||
|
@ -105,10 +91,10 @@ impl<GL: 'static> DiscoveryAPI<GL> for Box<dyn DiscoveryAPI<GL>> {
|
|||
init: &SessionInit,
|
||||
xr: SessionBuilder<GL>,
|
||||
) -> Result<Session, Error> {
|
||||
(&mut **self).request_session(mode, init, xr)
|
||||
(**self).request_session(mode, init, xr)
|
||||
}
|
||||
|
||||
fn supports_session(&self, mode: SessionMode) -> bool {
|
||||
(&**self).supports_session(mode)
|
||||
(**self).supports_session(mode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,18 +4,13 @@
|
|||
|
||||
use euclid::RigidTransform3D;
|
||||
|
||||
use crate::ApiSpace;
|
||||
use crate::BaseSpace;
|
||||
use crate::Frame;
|
||||
use crate::InputFrame;
|
||||
use crate::InputId;
|
||||
use crate::InputSource;
|
||||
use crate::SelectEvent;
|
||||
use crate::SelectKind;
|
||||
use crate::Sender;
|
||||
use crate::{
|
||||
ApiSpace, BaseSpace, Frame, InputFrame, InputId, InputSource, SelectEvent, SelectKind, Sender,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Event {
|
||||
/// Input source connected
|
||||
AddInput(InputSource),
|
||||
|
@ -35,7 +30,7 @@ pub enum Event {
|
|||
ReferenceSpaceChanged(BaseSpace, RigidTransform3D<f32, ApiSpace, ApiSpace>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Visibility {
|
||||
/// Session fully displayed to user
|
||||
|
@ -65,7 +60,7 @@ impl EventBuffer {
|
|||
EventBuffer::Buffered(ref mut events) => events.push(event),
|
||||
EventBuffer::Sink(ref dest) => {
|
||||
let _ = dest.send(event);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,20 +2,14 @@
|
|||
* 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::Floor;
|
||||
use crate::HitTestId;
|
||||
use crate::HitTestResult;
|
||||
use crate::InputFrame;
|
||||
use crate::Native;
|
||||
use crate::SubImages;
|
||||
use crate::Viewer;
|
||||
use crate::Viewports;
|
||||
use crate::Views;
|
||||
|
||||
use euclid::RigidTransform3D;
|
||||
|
||||
use crate::{
|
||||
Floor, HitTestId, HitTestResult, InputFrame, Native, SubImages, Viewer, Viewports, Views,
|
||||
};
|
||||
|
||||
/// The per-frame data that is provided by the device.
|
||||
/// https://www.w3.org/TR/webxr/#xrframe
|
||||
/// <https://www.w3.org/TR/webxr/#xrframe>
|
||||
// TODO: other fields?
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
use crate::Native;
|
||||
/* 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 euclid::RigidTransform3D;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
use crate::Native;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct HandSpace;
|
||||
|
||||
|
@ -29,7 +34,7 @@ pub struct Finger<J> {
|
|||
pub phalanx_tip: Option<J>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct JointFrame {
|
||||
pub pose: RigidTransform3D<f32, HandSpace, Native>,
|
||||
|
@ -97,7 +102,7 @@ impl<J> Finger<J> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum FingerJoint {
|
||||
Metacarpal,
|
||||
|
@ -107,7 +112,7 @@ pub enum FingerJoint {
|
|||
PhalanxTip,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Joint {
|
||||
Wrist,
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use crate::ApiSpace;
|
||||
use crate::Native;
|
||||
use crate::Space;
|
||||
use euclid::Point3D;
|
||||
use euclid::RigidTransform3D;
|
||||
use euclid::Rotation3D;
|
||||
use euclid::Vector3D;
|
||||
use std::f32::EPSILON;
|
||||
/* 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 std::iter::FromIterator;
|
||||
|
||||
use euclid::{Point3D, RigidTransform3D, Rotation3D, Vector3D};
|
||||
|
||||
use crate::{ApiSpace, Native, Space};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
/// https://immersive-web.github.io/hit-test/#xrray
|
||||
/// <https://immersive-web.github.io/hit-test/#xrray>
|
||||
pub struct Ray<Space> {
|
||||
/// The origin of the ray
|
||||
pub origin: Vector3D<f32, Space>,
|
||||
|
@ -20,16 +20,16 @@ pub struct Ray<Space> {
|
|||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
/// https://immersive-web.github.io/hit-test/#enumdef-xrhittesttrackabletype
|
||||
/// <https://immersive-web.github.io/hit-test/#enumdef-xrhittesttrackabletype>
|
||||
pub enum EntityType {
|
||||
Point,
|
||||
Plane,
|
||||
Mesh,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
/// https://immersive-web.github.io/hit-test/#dictdef-xrhittestoptionsinit
|
||||
/// <https://immersive-web.github.io/hit-test/#dictdef-xrhittestoptionsinit>
|
||||
pub struct HitTestSource {
|
||||
pub id: HitTestId,
|
||||
pub space: Space,
|
||||
|
@ -37,11 +37,11 @@ pub struct HitTestSource {
|
|||
pub types: EntityTypes,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct HitTestId(pub u32);
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
/// Vec<EntityType>, but better
|
||||
pub struct EntityTypes {
|
||||
|
@ -50,7 +50,7 @@ pub struct EntityTypes {
|
|||
pub mesh: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct HitTestResult {
|
||||
pub id: HitTestId,
|
||||
|
@ -62,7 +62,7 @@ pub struct HitTestResult {
|
|||
/// The coordinate space of a hit test result
|
||||
pub struct HitTestSpace;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct Triangle {
|
||||
pub first: Point3D<f32, Native>,
|
||||
|
@ -101,7 +101,7 @@ impl FromIterator<EntityType> for EntityTypes {
|
|||
}
|
||||
|
||||
impl Triangle {
|
||||
/// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
|
||||
/// <https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm>
|
||||
pub fn intersect(
|
||||
self,
|
||||
ray: Ray<Native>,
|
||||
|
@ -117,7 +117,7 @@ impl Triangle {
|
|||
|
||||
let h = ray.direction.cross(edge2);
|
||||
let a = edge1.dot(h);
|
||||
if a > -EPSILON && a < EPSILON {
|
||||
if a > -f32::EPSILON && a < f32::EPSILON {
|
||||
// ray is parallel to triangle
|
||||
return None;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ impl Triangle {
|
|||
// barycentric coordinate of intersection point u
|
||||
let u = f * s.dot(h);
|
||||
// barycentric coordinates have range (0, 1)
|
||||
if u < 0. || u > 1. {
|
||||
if !(0. ..=1.).contains(&u) {
|
||||
// the intersection is outside the triangle
|
||||
return None;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ impl Triangle {
|
|||
|
||||
let t = f * edge2.dot(q);
|
||||
|
||||
if t > EPSILON {
|
||||
if t > f32::EPSILON {
|
||||
let origin = ray.origin + ray.direction * t;
|
||||
|
||||
// this is not part of the Möller-Trumbore algorithm, the hit test spec
|
||||
|
@ -156,7 +156,7 @@ impl Triangle {
|
|||
let normal = edge1.cross(edge2).normalize();
|
||||
let y = Vector3D::new(0., 1., 0.);
|
||||
let dot = normal.dot(y);
|
||||
let rotation = if dot > -EPSILON && dot < EPSILON {
|
||||
let rotation = if dot > -f32::EPSILON && dot < f32::EPSILON {
|
||||
// vectors are parallel, return the vector itself
|
||||
// XXXManishearth it's possible for the vectors to be
|
||||
// antiparallel, unclear if normals need to be flipped
|
||||
|
|
|
@ -2,18 +2,15 @@
|
|||
* 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::Hand;
|
||||
use crate::Input;
|
||||
use crate::JointFrame;
|
||||
use crate::Native;
|
||||
|
||||
use euclid::RigidTransform3D;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
use crate::{Hand, Input, JointFrame, Native};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct InputId(pub u32);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum Handedness {
|
||||
None,
|
||||
|
@ -21,7 +18,7 @@ pub enum Handedness {
|
|||
Right,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum TargetRayMode {
|
||||
Gaze,
|
||||
|
@ -55,7 +52,7 @@ pub struct InputFrame {
|
|||
pub input_changed: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum SelectEvent {
|
||||
/// Selection started
|
||||
|
@ -66,7 +63,7 @@ pub enum SelectEvent {
|
|||
Select,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum SelectKind {
|
||||
Select,
|
||||
|
|
|
@ -2,16 +2,12 @@
|
|||
* 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::Error;
|
||||
use crate::Viewport;
|
||||
use crate::Viewports;
|
||||
|
||||
use euclid::Rect;
|
||||
use euclid::Size2D;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use euclid::{Rect, Size2D};
|
||||
|
||||
use crate::{Error, Viewport, Viewports};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
|
||||
|
@ -165,12 +161,14 @@ impl LayerManager {
|
|||
impl Drop for LayerManager {
|
||||
fn drop(&mut self) {
|
||||
log::debug!("Dropping LayerManager");
|
||||
for (context_id, layer_id) in self.0.layers().to_vec() {
|
||||
let layers: Vec<_> = self.0.layers().to_vec();
|
||||
for (context_id, layer_id) in layers.into_iter() {
|
||||
self.destroy_layer(context_id, layer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub struct LayerManagerFactory<GL: GLTypes>(
|
||||
Box<
|
||||
dyn Send
|
||||
|
@ -213,16 +211,16 @@ pub struct LayerId(usize);
|
|||
|
||||
static NEXT_LAYER_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
impl LayerId {
|
||||
pub fn new() -> LayerId {
|
||||
impl Default for LayerId {
|
||||
fn default() -> Self {
|
||||
LayerId(NEXT_LAYER_ID.fetch_add(1, Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
|
||||
pub enum LayerInit {
|
||||
// https://www.w3.org/TR/webxr/#dictdef-xrwebgllayerinit
|
||||
/// <https://www.w3.org/TR/webxr/#dictdef-xrwebgllayerinit>
|
||||
WebGLLayer {
|
||||
antialias: bool,
|
||||
depth: bool,
|
||||
|
@ -231,7 +229,7 @@ pub enum LayerInit {
|
|||
ignore_depth_values: bool,
|
||||
framebuffer_scale_factor: f32,
|
||||
},
|
||||
// https://immersive-web.github.io/layers/#xrprojectionlayerinittype
|
||||
/// <https://immersive-web.github.io/layers/#xrprojectionlayerinittype>
|
||||
ProjectionLayer {
|
||||
depth: bool,
|
||||
stencil: bool,
|
||||
|
@ -247,8 +245,8 @@ impl LayerInit {
|
|||
LayerInit::WebGLLayer {
|
||||
framebuffer_scale_factor: scale,
|
||||
..
|
||||
}
|
||||
| LayerInit::ProjectionLayer {
|
||||
} |
|
||||
LayerInit::ProjectionLayer {
|
||||
scale_factor: scale,
|
||||
..
|
||||
} => {
|
||||
|
@ -258,13 +256,13 @@ impl LayerInit {
|
|||
.fold(Rect::zero(), |acc, view| acc.union(view))
|
||||
.size;
|
||||
(native_size.to_f32() * *scale).to_i32()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/layers/#enumdef-xrlayerlayout
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// <https://immersive-web.github.io/layers/#enumdef-xrlayerlayout>
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
|
||||
pub enum LayerLayout {
|
||||
// TODO: Default
|
||||
|
@ -284,7 +282,7 @@ pub struct SubImages {
|
|||
pub view_sub_images: Vec<SubImage>,
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/layers/#xrsubimagetype
|
||||
/// <https://immersive-web.github.io/layers/#xrsubimagetype>
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Deserialize, Serialize))]
|
||||
pub struct SubImage {
|
||||
|
|
|
@ -19,130 +19,48 @@ mod space;
|
|||
pub mod util;
|
||||
mod view;
|
||||
|
||||
pub use device::DeviceAPI;
|
||||
pub use device::DiscoveryAPI;
|
||||
|
||||
pub use error::Error;
|
||||
|
||||
pub use events::Event;
|
||||
pub use events::EventBuffer;
|
||||
pub use events::Visibility;
|
||||
|
||||
pub use frame::Frame;
|
||||
pub use frame::FrameUpdateEvent;
|
||||
pub use frame::ViewerPose;
|
||||
|
||||
pub use hand::Finger;
|
||||
pub use hand::FingerJoint;
|
||||
pub use hand::Hand;
|
||||
pub use hand::HandSpace;
|
||||
pub use hand::Joint;
|
||||
pub use hand::JointFrame;
|
||||
|
||||
pub use hittest::EntityType;
|
||||
pub use hittest::EntityTypes;
|
||||
pub use hittest::HitTestId;
|
||||
pub use hittest::HitTestResult;
|
||||
pub use hittest::HitTestSource;
|
||||
pub use hittest::HitTestSpace;
|
||||
pub use hittest::Ray;
|
||||
pub use hittest::Triangle;
|
||||
|
||||
pub use input::Handedness;
|
||||
pub use input::InputFrame;
|
||||
pub use input::InputId;
|
||||
pub use input::InputSource;
|
||||
pub use input::SelectEvent;
|
||||
pub use input::SelectKind;
|
||||
pub use input::TargetRayMode;
|
||||
|
||||
pub use layer::ContextId;
|
||||
pub use layer::GLContexts;
|
||||
pub use layer::GLTypes;
|
||||
pub use layer::LayerGrandManager;
|
||||
pub use layer::LayerGrandManagerAPI;
|
||||
pub use layer::LayerId;
|
||||
pub use layer::LayerInit;
|
||||
pub use layer::LayerLayout;
|
||||
pub use layer::LayerManager;
|
||||
pub use layer::LayerManagerAPI;
|
||||
pub use layer::LayerManagerFactory;
|
||||
pub use layer::SubImage;
|
||||
pub use layer::SubImages;
|
||||
|
||||
pub use mock::MockButton;
|
||||
pub use mock::MockButtonType;
|
||||
pub use mock::MockDeviceInit;
|
||||
pub use mock::MockDeviceMsg;
|
||||
pub use mock::MockDiscoveryAPI;
|
||||
pub use mock::MockInputInit;
|
||||
pub use mock::MockInputMsg;
|
||||
pub use mock::MockRegion;
|
||||
pub use mock::MockViewInit;
|
||||
pub use mock::MockViewsInit;
|
||||
pub use mock::MockWorld;
|
||||
|
||||
pub use registry::MainThreadRegistry;
|
||||
pub use registry::MainThreadWaker;
|
||||
pub use registry::Registry;
|
||||
|
||||
pub use session::EnvironmentBlendMode;
|
||||
pub use session::MainThreadSession;
|
||||
pub use session::Quitter;
|
||||
pub use session::Session;
|
||||
pub use session::SessionBuilder;
|
||||
pub use session::SessionId;
|
||||
pub use session::SessionInit;
|
||||
pub use session::SessionMode;
|
||||
pub use session::SessionThread;
|
||||
|
||||
pub use space::ApiSpace;
|
||||
pub use space::BaseSpace;
|
||||
pub use space::Space;
|
||||
|
||||
pub use view::Capture;
|
||||
pub use view::CubeBack;
|
||||
pub use view::CubeBottom;
|
||||
pub use view::CubeLeft;
|
||||
pub use view::CubeRight;
|
||||
pub use view::CubeTop;
|
||||
pub use view::Display;
|
||||
pub use view::Floor;
|
||||
pub use view::Input;
|
||||
pub use view::LeftEye;
|
||||
pub use view::Native;
|
||||
pub use view::RightEye;
|
||||
pub use view::SomeEye;
|
||||
pub use view::View;
|
||||
pub use view::Viewer;
|
||||
pub use view::Viewport;
|
||||
pub use view::Viewports;
|
||||
pub use view::Views;
|
||||
pub use view::CUBE_BACK;
|
||||
pub use view::CUBE_BOTTOM;
|
||||
pub use view::CUBE_LEFT;
|
||||
pub use view::CUBE_RIGHT;
|
||||
pub use view::CUBE_TOP;
|
||||
pub use view::LEFT_EYE;
|
||||
pub use view::RIGHT_EYE;
|
||||
pub use view::VIEWER;
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
use std::thread;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc_channel::ipc::IpcSender as Sender;
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc_channel::ipc::IpcReceiver as Receiver;
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc_channel::ipc::channel;
|
||||
|
||||
#[cfg(not(feature = "ipc"))]
|
||||
pub use std::sync::mpsc::{Receiver, RecvTimeoutError, Sender};
|
||||
#[cfg(feature = "ipc")]
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
pub use device::{DeviceAPI, DiscoveryAPI};
|
||||
pub use error::Error;
|
||||
pub use events::{Event, EventBuffer, Visibility};
|
||||
pub use frame::{Frame, FrameUpdateEvent, ViewerPose};
|
||||
pub use hand::{Finger, FingerJoint, Hand, HandSpace, Joint, JointFrame};
|
||||
pub use hittest::{
|
||||
EntityType, EntityTypes, HitTestId, HitTestResult, HitTestSource, HitTestSpace, Ray, Triangle,
|
||||
};
|
||||
pub use input::{
|
||||
Handedness, InputFrame, InputId, InputSource, SelectEvent, SelectKind, TargetRayMode,
|
||||
};
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc_channel::ipc::channel;
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc_channel::ipc::IpcReceiver as Receiver;
|
||||
#[cfg(feature = "ipc")]
|
||||
pub use ipc_channel::ipc::IpcSender as Sender;
|
||||
pub use layer::{
|
||||
ContextId, GLContexts, GLTypes, LayerGrandManager, LayerGrandManagerAPI, LayerId, LayerInit,
|
||||
LayerLayout, LayerManager, LayerManagerAPI, LayerManagerFactory, SubImage, SubImages,
|
||||
};
|
||||
pub use mock::{
|
||||
MockButton, MockButtonType, MockDeviceInit, MockDeviceMsg, MockDiscoveryAPI, MockInputInit,
|
||||
MockInputMsg, MockRegion, MockViewInit, MockViewsInit, MockWorld,
|
||||
};
|
||||
pub use registry::{MainThreadRegistry, MainThreadWaker, Registry};
|
||||
pub use session::{
|
||||
EnvironmentBlendMode, MainThreadSession, Quitter, Session, SessionBuilder, SessionId,
|
||||
SessionInit, SessionMode, SessionThread,
|
||||
};
|
||||
pub use space::{ApiSpace, BaseSpace, Space};
|
||||
pub use view::{
|
||||
Capture, CubeBack, CubeBottom, CubeLeft, CubeRight, CubeTop, Display, Floor, Input, LeftEye,
|
||||
Native, RightEye, SomeEye, View, Viewer, Viewport, Viewports, Views, CUBE_BACK, CUBE_BOTTOM,
|
||||
CUBE_LEFT, CUBE_RIGHT, CUBE_TOP, LEFT_EYE, RIGHT_EYE, VIEWER,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "ipc"))]
|
||||
pub fn channel<T>() -> Result<(Sender<T>, Receiver<T>), ()> {
|
||||
|
@ -169,7 +87,7 @@ where
|
|||
return Ok(msg);
|
||||
}
|
||||
thread::sleep(delay);
|
||||
delay = delay * 2;
|
||||
delay *= 2;
|
||||
}
|
||||
receiver.try_recv()
|
||||
}
|
||||
|
|
|
@ -2,33 +2,16 @@
|
|||
* 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::DiscoveryAPI;
|
||||
use crate::Display;
|
||||
use crate::EntityType;
|
||||
use crate::Error;
|
||||
use crate::Floor;
|
||||
use crate::Handedness;
|
||||
use crate::Input;
|
||||
use crate::InputId;
|
||||
use crate::InputSource;
|
||||
use crate::LeftEye;
|
||||
use crate::Native;
|
||||
use crate::Receiver;
|
||||
use crate::RightEye;
|
||||
use crate::SelectEvent;
|
||||
use crate::SelectKind;
|
||||
use crate::Sender;
|
||||
use crate::TargetRayMode;
|
||||
use crate::Triangle;
|
||||
use crate::Viewer;
|
||||
use crate::Viewport;
|
||||
use crate::Visibility;
|
||||
|
||||
use euclid::{Point2D, Rect, RigidTransform3D, Transform3D};
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
DiscoveryAPI, Display, EntityType, Error, Floor, Handedness, Input, InputId, InputSource,
|
||||
LeftEye, Native, Receiver, RightEye, SelectEvent, SelectKind, Sender, TargetRayMode, Triangle,
|
||||
Viewer, Viewport, Visibility,
|
||||
};
|
||||
|
||||
/// A trait for discovering mock XR devices
|
||||
pub trait MockDiscoveryAPI<GL>: 'static {
|
||||
fn simulate_device_connection(
|
||||
|
@ -103,7 +86,7 @@ pub enum MockInputMsg {
|
|||
SetGripOrigin(Option<RigidTransform3D<f32, Input, Native>>),
|
||||
/// Note: SelectEvent::Select here refers to a complete Select event,
|
||||
/// not just the end event, i.e. it refers to
|
||||
/// https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-simulateselect
|
||||
/// <https://immersive-web.github.io/webxr-test-api/#dom-fakexrinputcontroller-simulateselect>
|
||||
TriggerSelect(SelectKind, SelectEvent),
|
||||
Disconnect,
|
||||
Reconnect,
|
||||
|
|
|
@ -2,28 +2,16 @@
|
|||
* 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::DiscoveryAPI;
|
||||
use crate::Error;
|
||||
use crate::Frame;
|
||||
use crate::GLTypes;
|
||||
use crate::LayerGrandManager;
|
||||
use crate::MainThreadSession;
|
||||
use crate::MockDeviceInit;
|
||||
use crate::MockDeviceMsg;
|
||||
use crate::MockDiscoveryAPI;
|
||||
use crate::Receiver;
|
||||
use crate::Sender;
|
||||
use crate::Session;
|
||||
use crate::SessionBuilder;
|
||||
use crate::SessionId;
|
||||
use crate::SessionInit;
|
||||
use crate::SessionMode;
|
||||
|
||||
use log::warn;
|
||||
|
||||
#[cfg(feature = "ipc")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
DiscoveryAPI, Error, Frame, GLTypes, LayerGrandManager, MainThreadSession, MockDeviceInit,
|
||||
MockDeviceMsg, MockDiscoveryAPI, Receiver, Sender, Session, SessionBuilder, SessionId,
|
||||
SessionInit, SessionMode,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub struct Registry {
|
||||
|
@ -188,13 +176,13 @@ impl<GL: 'static + GLTypes> MainThreadRegistry<GL> {
|
|||
match msg {
|
||||
RegistryMsg::SupportsSession(mode, dest) => {
|
||||
let _ = dest.send(self.supports_session(mode));
|
||||
}
|
||||
},
|
||||
RegistryMsg::RequestSession(mode, init, dest, raf_sender) => {
|
||||
let _ = dest.send(self.request_session(mode, init, raf_sender));
|
||||
}
|
||||
},
|
||||
RegistryMsg::SimulateDeviceConnection(init, dest) => {
|
||||
let _ = dest.send(self.simulate_device_connection(init));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,6 +238,7 @@ impl<GL: 'static + GLTypes> MainThreadRegistry<GL> {
|
|||
}
|
||||
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum RegistryMsg {
|
||||
RequestSession(
|
||||
SessionMode,
|
||||
|
|
|
@ -2,43 +2,24 @@
|
|||
* 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::channel;
|
||||
use crate::ContextId;
|
||||
use crate::DeviceAPI;
|
||||
use crate::Error;
|
||||
use crate::Event;
|
||||
use crate::Floor;
|
||||
use crate::Frame;
|
||||
use crate::FrameUpdateEvent;
|
||||
use crate::HitTestId;
|
||||
use crate::HitTestSource;
|
||||
use crate::InputSource;
|
||||
use crate::LayerGrandManager;
|
||||
use crate::LayerId;
|
||||
use crate::LayerInit;
|
||||
use crate::Native;
|
||||
use crate::Receiver;
|
||||
use crate::Sender;
|
||||
use crate::Viewport;
|
||||
use crate::Viewports;
|
||||
|
||||
use euclid::Point2D;
|
||||
use euclid::Rect;
|
||||
use euclid::RigidTransform3D;
|
||||
use euclid::Size2D;
|
||||
|
||||
use log::warn;
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use euclid::{Point2D, Rect, RigidTransform3D, Size2D};
|
||||
use log::warn;
|
||||
#[cfg(feature = "ipc")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
channel, ContextId, DeviceAPI, Error, Event, Floor, Frame, FrameUpdateEvent, HitTestId,
|
||||
HitTestSource, InputSource, LayerGrandManager, LayerId, LayerInit, Native, Receiver, Sender,
|
||||
Viewport, Viewports,
|
||||
};
|
||||
|
||||
// How long to wait for an rAF.
|
||||
static TIMEOUT: Duration = Duration::from_millis(5);
|
||||
|
||||
/// https://www.w3.org/TR/webxr/#xrsessionmode-enum
|
||||
/// <https://www.w3.org/TR/webxr/#xrsessionmode-enum>
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub enum SessionMode {
|
||||
|
@ -47,7 +28,7 @@ pub enum SessionMode {
|
|||
ImmersiveAR,
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr/#dictdef-xrsessioninit
|
||||
/// <https://immersive-web.github.io/webxr/#dictdef-xrsessioninit>
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub struct SessionInit {
|
||||
|
@ -76,9 +57,9 @@ impl SessionInit {
|
|||
}
|
||||
let mut granted = self.required_features.clone();
|
||||
for f in &self.optional_features {
|
||||
if f == "viewer"
|
||||
|| (f == "local" && mode != SessionMode::Inline)
|
||||
|| supported.contains(f)
|
||||
if f == "viewer" ||
|
||||
(f == "local" && mode != SessionMode::Inline) ||
|
||||
supported.contains(f)
|
||||
{
|
||||
granted.push(f.clone());
|
||||
}
|
||||
|
@ -91,12 +72,11 @@ impl SessionInit {
|
|||
self.required_features
|
||||
.iter()
|
||||
.chain(self.optional_features.iter())
|
||||
.find(|x| *x == f)
|
||||
.is_some()
|
||||
.any(|x| *x == f)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr-ar-module/#xrenvironmentblendmode-enum
|
||||
/// <https://immersive-web.github.io/webxr-ar-module/#xrenvironmentblendmode-enum>
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub enum EnvironmentBlendMode {
|
||||
|
@ -137,7 +117,7 @@ impl Quitter {
|
|||
|
||||
/// An object that represents an XR session.
|
||||
/// This is owned by the content thread.
|
||||
/// https://www.w3.org/TR/webxr/#xrsession-interface
|
||||
/// <https://www.w3.org/TR/webxr/#xrsession-interface>
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub struct Session {
|
||||
floor_transform: Option<RigidTransform3D<f32, Native, Floor>>,
|
||||
|
@ -160,7 +140,7 @@ impl Session {
|
|||
}
|
||||
|
||||
pub fn floor_transform(&self) -> Option<RigidTransform3D<f32, Native, Floor>> {
|
||||
self.floor_transform.clone()
|
||||
self.floor_transform
|
||||
}
|
||||
|
||||
pub fn reference_space_bounds(&self) -> Option<Vec<Point2D<f32, Floor>>> {
|
||||
|
@ -182,7 +162,7 @@ impl Session {
|
|||
}
|
||||
|
||||
/// A resolution large enough to contain all the viewports.
|
||||
/// https://immersive-web.github.io/webxr/#recommended-webgl-framebuffer-resolution
|
||||
/// <https://immersive-web.github.io/webxr/#recommended-webgl-framebuffer-resolution>
|
||||
///
|
||||
/// Returns None if the session is inline
|
||||
pub fn recommended_framebuffer_resolution(&self) -> Option<Size2D<i32, Viewport>> {
|
||||
|
@ -335,13 +315,9 @@ where
|
|||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
loop {
|
||||
if let Ok(msg) = self.receiver.recv() {
|
||||
if !self.handle_msg(msg) {
|
||||
self.running = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
while let Ok(msg) = self.receiver.recv() {
|
||||
if !self.handle_msg(msg) {
|
||||
self.running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -352,24 +328,24 @@ where
|
|||
match msg {
|
||||
SessionMsg::SetEventDest(dest) => {
|
||||
self.device.set_event_dest(dest);
|
||||
}
|
||||
},
|
||||
SessionMsg::RequestHitTest(source) => {
|
||||
self.device.request_hit_test(source);
|
||||
}
|
||||
},
|
||||
SessionMsg::CancelHitTest(id) => {
|
||||
self.device.cancel_hit_test(id);
|
||||
}
|
||||
},
|
||||
SessionMsg::CreateLayer(context_id, layer_init, sender) => {
|
||||
let result = self.device.create_layer(context_id, layer_init);
|
||||
let _ = sender.send(result);
|
||||
}
|
||||
},
|
||||
SessionMsg::DestroyLayer(context_id, layer_id) => {
|
||||
self.layers.retain(|&(_, other_id)| layer_id != other_id);
|
||||
self.device.destroy_layer(context_id, layer_id);
|
||||
}
|
||||
},
|
||||
SessionMsg::SetLayers(layers) => {
|
||||
self.pending_layers = Some(layers);
|
||||
}
|
||||
},
|
||||
SessionMsg::StartRenderLoop => {
|
||||
if let Some(layers) = self.pending_layers.take() {
|
||||
self.layers = layers;
|
||||
|
@ -379,11 +355,11 @@ where
|
|||
None => {
|
||||
warn!("Device stopped providing frames, exiting");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
};
|
||||
self.render_state = RenderState::InRenderLoop;
|
||||
let _ = self.frame_sender.send(frame);
|
||||
}
|
||||
},
|
||||
SessionMsg::UpdateClipPlanes(near, far) => self.device.update_clip_planes(near, far),
|
||||
SessionMsg::RenderAnimationFrame => {
|
||||
self.frame_count += 1;
|
||||
|
@ -404,15 +380,15 @@ where
|
|||
None => {
|
||||
warn!("Device stopped providing frames, exiting");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let _ = self.frame_sender.send(frame);
|
||||
}
|
||||
},
|
||||
SessionMsg::UpdateFrameRate(rate, sender) => {
|
||||
let new_framerate = self.device.update_frame_rate(rate);
|
||||
let _ = sender.send(new_framerate);
|
||||
}
|
||||
},
|
||||
SessionMsg::Quit => {
|
||||
if self.render_state == RenderState::NotInRenderLoop {
|
||||
self.quit();
|
||||
|
@ -420,11 +396,11 @@ where
|
|||
} else {
|
||||
self.render_state = RenderState::PendingQuit;
|
||||
}
|
||||
}
|
||||
},
|
||||
SessionMsg::GetBoundsGeometry(sender) => {
|
||||
let bounds = self.device.reference_space_bounds();
|
||||
let _ = sender.send(bounds);
|
||||
}
|
||||
},
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -506,10 +482,10 @@ impl<'a, GL: 'static> SessionBuilder<'a, GL> {
|
|||
let session = thread.new_session();
|
||||
let _ = acks.send(Ok(session));
|
||||
thread.run();
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
let _ = acks.send(Err(err));
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
ackr.recv().unwrap_or(Err(Error::CommunicationError))
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use crate::InputId;
|
||||
use crate::Joint;
|
||||
/* 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 euclid::RigidTransform3D;
|
||||
|
||||
use crate::{InputId, Joint};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
/// A stand-in type for "the space isn't statically known since
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use crate::FrameUpdateEvent;
|
||||
use crate::HitTestId;
|
||||
use crate::HitTestSource;
|
||||
/* 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 euclid::Transform3D;
|
||||
|
||||
use crate::{FrameUpdateEvent, HitTestId, HitTestSource};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ClipPlanes {
|
||||
|
|
|
@ -4,35 +4,32 @@
|
|||
|
||||
//! This crate uses `euclid`'s typed units, and exposes different coordinate spaces.
|
||||
|
||||
use euclid::Rect;
|
||||
use euclid::RigidTransform3D;
|
||||
use euclid::Transform3D;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use euclid::{Rect, RigidTransform3D, Transform3D};
|
||||
#[cfg(feature = "ipc")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// The coordinate space of the viewer
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrreferencespacetype-viewer
|
||||
/// <https://immersive-web.github.io/webxr/#dom-xrreferencespacetype-viewer>
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub enum Viewer {}
|
||||
|
||||
/// The coordinate space of the floor
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrreferencespacetype-local-floor
|
||||
/// <https://immersive-web.github.io/webxr/#dom-xrreferencespacetype-local-floor>
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub enum Floor {}
|
||||
|
||||
/// The coordinate space of the left eye
|
||||
/// https://immersive-web.github.io/webxr/#dom-xreye-left
|
||||
/// <https://immersive-web.github.io/webxr/#dom-xreye-left>
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub enum LeftEye {}
|
||||
|
||||
/// The coordinate space of the right eye
|
||||
/// https://immersive-web.github.io/webxr/#dom-xreye-right
|
||||
/// <https://immersive-web.github.io/webxr/#dom-xreye-right>
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub enum RightEye {}
|
||||
|
@ -115,7 +112,7 @@ pub enum Capture {}
|
|||
/// its projection onto its display.
|
||||
/// For stereo displays, we have a `View<LeftEye>` and a `View<RightEye>`.
|
||||
/// For mono displays, we hagve a `View<Viewer>`
|
||||
/// https://immersive-web.github.io/webxr/#xrview
|
||||
/// <https://immersive-web.github.io/webxr/#xrview>
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
pub struct View<Eye> {
|
||||
|
@ -144,6 +141,7 @@ impl<Eye> View<Eye> {
|
|||
/// Whether a device is mono or stereo, and the views it supports.
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "ipc", derive(Serialize, Deserialize))]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Views {
|
||||
/// Mono view for inline VR, viewport and projection matrices are calculated by client
|
||||
Inline,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue