webxr_api/
view.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! This crate uses `euclid`'s typed units, and exposes different coordinate spaces.
6
7use std::marker::PhantomData;
8
9use euclid::{Rect, RigidTransform3D, Transform3D};
10use serde::{Deserialize, Serialize};
11
12/// The coordinate space of the viewer
13/// <https://immersive-web.github.io/webxr/#dom-xrreferencespacetype-viewer>
14#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
15pub enum Viewer {}
16
17/// The coordinate space of the floor
18/// <https://immersive-web.github.io/webxr/#dom-xrreferencespacetype-local-floor>
19#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
20pub enum Floor {}
21
22/// The coordinate space of the left eye
23/// <https://immersive-web.github.io/webxr/#dom-xreye-left>
24#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
25pub enum LeftEye {}
26
27/// The coordinate space of the right eye
28/// <https://immersive-web.github.io/webxr/#dom-xreye-right>
29#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
30pub enum RightEye {}
31
32/// The coordinate space of the left frustrum of a cubemap
33#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
34pub enum CubeLeft {}
35
36/// The coordinate space of the right frustrum of a cubemap
37#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
38pub enum CubeRight {}
39
40/// The coordinate space of the top frustrum of a cubemap
41#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
42pub enum CubeTop {}
43
44/// The coordinate space of the bottom frustrum of a cubemap
45#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
46pub enum CubeBottom {}
47
48/// The coordinate space of the back frustrum of a cubemap
49#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
50pub enum CubeBack {}
51
52/// Pattern-match on eyes
53#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
54pub struct SomeEye<Eye>(u8, PhantomData<Eye>);
55pub const LEFT_EYE: SomeEye<LeftEye> = SomeEye(0, PhantomData);
56pub const RIGHT_EYE: SomeEye<RightEye> = SomeEye(1, PhantomData);
57pub const VIEWER: SomeEye<Viewer> = SomeEye(2, PhantomData);
58pub const CUBE_LEFT: SomeEye<CubeLeft> = SomeEye(3, PhantomData);
59pub const CUBE_RIGHT: SomeEye<CubeRight> = SomeEye(4, PhantomData);
60pub const CUBE_TOP: SomeEye<CubeTop> = SomeEye(5, PhantomData);
61pub const CUBE_BOTTOM: SomeEye<CubeBottom> = SomeEye(6, PhantomData);
62pub const CUBE_BACK: SomeEye<CubeBack> = SomeEye(7, PhantomData);
63
64impl<Eye1, Eye2> PartialEq<SomeEye<Eye2>> for SomeEye<Eye1> {
65    fn eq(&self, rhs: &SomeEye<Eye2>) -> bool {
66        self.0 == rhs.0
67    }
68}
69
70/// The native 3D coordinate space of the device
71/// This is not part of the webvr specification.
72#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
73pub enum Native {}
74
75/// The normalized device coordinate space, where the display
76/// is from (-1,-1) to (1,1).
77// TODO: are we OK assuming that we can use the same coordinate system for all displays?
78#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
79pub enum Display {}
80
81/// The unnormalized device coordinate space, where the display
82/// is from (0,0) to (w,h), measured in pixels.
83// TODO: are we OK assuming that we can use the same coordinate system for all displays?
84#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
85pub enum Viewport {}
86
87/// The coordinate space of an input device
88#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
89pub enum Input {}
90
91/// The coordinate space of a secondary capture view
92#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
93pub enum Capture {}
94
95/// For each eye, the pose of that eye,
96/// its projection onto its display.
97/// For stereo displays, we have a `View<LeftEye>` and a `View<RightEye>`.
98/// For mono displays, we hagve a `View<Viewer>`
99/// <https://immersive-web.github.io/webxr/#xrview>
100#[derive(Clone, Debug, Serialize, Deserialize)]
101pub struct View<Eye> {
102    pub transform: RigidTransform3D<f32, Eye, Native>,
103    pub projection: Transform3D<f32, Eye, Display>,
104}
105
106impl<Eye> Default for View<Eye> {
107    fn default() -> Self {
108        View {
109            transform: RigidTransform3D::identity(),
110            projection: Transform3D::identity(),
111        }
112    }
113}
114
115impl<Eye> View<Eye> {
116    pub fn cast_unit<NewEye>(&self) -> View<NewEye> {
117        View {
118            transform: self.transform.cast_unit(),
119            projection: Transform3D::from_untyped(&self.projection.to_untyped()),
120        }
121    }
122}
123
124/// Whether a device is mono or stereo, and the views it supports.
125#[derive(Clone, Debug, Serialize, Deserialize)]
126#[expect(clippy::large_enum_variant)]
127pub enum Views {
128    /// Mono view for inline VR, viewport and projection matrices are calculated by client
129    Inline,
130    Mono(View<Viewer>),
131    Stereo(View<LeftEye>, View<RightEye>),
132    StereoCapture(View<LeftEye>, View<RightEye>, View<Capture>),
133    Cubemap(
134        View<Viewer>,
135        View<CubeLeft>,
136        View<CubeRight>,
137        View<CubeTop>,
138        View<CubeBottom>,
139        View<CubeBack>,
140    ),
141}
142
143/// A list of viewports per-eye in the order of fields in Views.
144///
145/// Not all must be in active use.
146#[derive(Clone, Debug, Serialize, Deserialize)]
147pub struct Viewports {
148    pub viewports: Vec<Rect<i32, Viewport>>,
149}