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