/src/mozilla-central/gfx/vr/gfxVR.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include <math.h> |
8 | | |
9 | | #include "gfxVR.h" |
10 | | #include "mozilla/dom/GamepadEventTypes.h" |
11 | | #include "mozilla/dom/GamepadBinding.h" |
12 | | #include "VRDisplayHost.h" |
13 | | |
14 | | #ifndef M_PI |
15 | | # define M_PI 3.14159265358979323846 |
16 | | #endif |
17 | | |
18 | | using namespace mozilla; |
19 | | using namespace mozilla::gfx; |
20 | | |
21 | | Atomic<uint32_t> VRSystemManager::sDisplayBase(0); |
22 | | Atomic<uint32_t> VRSystemManager::sControllerBase(0); |
23 | | |
24 | | /* static */ uint32_t |
25 | | VRSystemManager::AllocateDisplayID() |
26 | 0 | { |
27 | 0 | return ++sDisplayBase; |
28 | 0 | } |
29 | | |
30 | | /* static */ uint32_t |
31 | | VRSystemManager::AllocateControllerID() |
32 | 0 | { |
33 | 0 | return ++sControllerBase; |
34 | 0 | } |
35 | | |
36 | | /** |
37 | | * VRSystemManager::NotifyVsync must be called even when a WebVR site is |
38 | | * not active, in order to poll for respond to VR Platform API requests. |
39 | | * This should be called very often, ideally once per frame. |
40 | | * VRSystemManager::Refresh will not activate VR hardware or |
41 | | * initialize VR runtimes that have not already been activated. |
42 | | */ |
43 | | void |
44 | | VRSystemManager::NotifyVSync() |
45 | 0 | { |
46 | 0 | // VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate |
47 | 0 | // through a local copy here. |
48 | 0 | nsTArray<RefPtr<VRDisplayHost>> displays; |
49 | 0 | GetHMDs(displays); |
50 | 0 | for (const auto& display : displays) { |
51 | 0 | display->NotifyVSync(); |
52 | 0 | } |
53 | 0 |
|
54 | 0 | // Ensure that the controller state is updated at least |
55 | 0 | // on every 2d display VSync when not in a VR presentation. |
56 | 0 | if (!GetIsPresenting()) { |
57 | 0 | HandleInput(); |
58 | 0 | } |
59 | 0 | } |
60 | | |
61 | | /** |
62 | | * VRSystemManager::GetHMDs must not be called unless |
63 | | * VRSystemManager::ShouldInhibitEnumeration is called |
64 | | * on all VRSystemManager instances and they all return |
65 | | * false. |
66 | | * |
67 | | * This is used to ensure that VR devices that can be |
68 | | * enumerated by multiple API's are only enumerated by |
69 | | * one API. |
70 | | * |
71 | | * GetHMDs is called for the most specific API |
72 | | * (ie. Oculus SDK) first before calling GetHMDs on |
73 | | * more generic api's (ie. OpenVR) to ensure that a device |
74 | | * is accessed using the API most optimized for it. |
75 | | * |
76 | | * ShouldInhibitEnumeration may also be used to prevent |
77 | | * devices from jumping to other API's when they are |
78 | | * intentionally ignored, such as when responding to |
79 | | * requests by the VR platform to unload the libraries |
80 | | * for runtime software updates. |
81 | | */ |
82 | | bool |
83 | | VRSystemManager::ShouldInhibitEnumeration() |
84 | 0 | { |
85 | 0 | return false; |
86 | 0 | } |
87 | | |
88 | | Matrix4x4 |
89 | | VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar, |
90 | | bool rightHanded) const |
91 | 0 | { |
92 | 0 | float upTan = tan(upDegrees * M_PI / 180.0); |
93 | 0 | float downTan = tan(downDegrees * M_PI / 180.0); |
94 | 0 | float leftTan = tan(leftDegrees * M_PI / 180.0); |
95 | 0 | float rightTan = tan(rightDegrees * M_PI / 180.0); |
96 | 0 |
|
97 | 0 | float handednessScale = rightHanded ? -1.0 : 1.0; |
98 | 0 |
|
99 | 0 | float pxscale = 2.0f / (leftTan + rightTan); |
100 | 0 | float pxoffset = (leftTan - rightTan) * pxscale * 0.5; |
101 | 0 | float pyscale = 2.0f / (upTan + downTan); |
102 | 0 | float pyoffset = (upTan - downTan) * pyscale * 0.5; |
103 | 0 |
|
104 | 0 | Matrix4x4 mobj; |
105 | 0 | float *m = &mobj._11; |
106 | 0 |
|
107 | 0 | m[0*4+0] = pxscale; |
108 | 0 | m[2*4+0] = pxoffset * handednessScale; |
109 | 0 |
|
110 | 0 | m[1*4+1] = pyscale; |
111 | 0 | m[2*4+1] = -pyoffset * handednessScale; |
112 | 0 |
|
113 | 0 | m[2*4+2] = zFar / (zNear - zFar) * -handednessScale; |
114 | 0 | m[3*4+2] = (zFar * zNear) / (zNear - zFar); |
115 | 0 |
|
116 | 0 | m[2*4+3] = handednessScale; |
117 | 0 | m[3*4+3] = 0.0f; |
118 | 0 |
|
119 | 0 | return mobj; |
120 | 0 | } |
121 | | |
122 | | void |
123 | | VRSystemManager::AddGamepad(const VRControllerInfo& controllerInfo) |
124 | 0 | { |
125 | 0 | dom::GamepadAdded a(NS_ConvertUTF8toUTF16(controllerInfo.GetControllerName()), |
126 | 0 | controllerInfo.GetMappingType(), |
127 | 0 | controllerInfo.GetHand(), |
128 | 0 | controllerInfo.GetDisplayID(), |
129 | 0 | controllerInfo.GetNumButtons(), |
130 | 0 | controllerInfo.GetNumAxes(), |
131 | 0 | controllerInfo.GetNumHaptics()); |
132 | 0 |
|
133 | 0 | VRManager* vm = VRManager::Get(); |
134 | 0 | vm->NotifyGamepadChange<dom::GamepadAdded>(mControllerCount, a); |
135 | 0 | } |
136 | | |
137 | | void |
138 | | VRSystemManager::RemoveGamepad(uint32_t aIndex) |
139 | 0 | { |
140 | 0 | dom::GamepadRemoved a; |
141 | 0 |
|
142 | 0 | VRManager* vm = VRManager::Get(); |
143 | 0 | vm->NotifyGamepadChange<dom::GamepadRemoved>(aIndex, a); |
144 | 0 | } |
145 | | |
146 | | void |
147 | | VRSystemManager::NewButtonEvent(uint32_t aIndex, uint32_t aButton, |
148 | | bool aPressed, bool aTouched, double aValue) |
149 | 0 | { |
150 | 0 | dom::GamepadButtonInformation a(aButton, aValue, aPressed, aTouched); |
151 | 0 |
|
152 | 0 | VRManager* vm = VRManager::Get(); |
153 | 0 | vm->NotifyGamepadChange<dom::GamepadButtonInformation>(aIndex, a); |
154 | 0 | } |
155 | | |
156 | | void |
157 | | VRSystemManager::NewAxisMove(uint32_t aIndex, uint32_t aAxis, |
158 | | double aValue) |
159 | 0 | { |
160 | 0 | dom::GamepadAxisInformation a(aAxis, aValue); |
161 | 0 |
|
162 | 0 | VRManager* vm = VRManager::Get(); |
163 | 0 | vm->NotifyGamepadChange<dom::GamepadAxisInformation>(aIndex, a); |
164 | 0 | } |
165 | | |
166 | | void |
167 | | VRSystemManager::NewPoseState(uint32_t aIndex, |
168 | | const dom::GamepadPoseState& aPose) |
169 | 0 | { |
170 | 0 | dom::GamepadPoseInformation a(aPose); |
171 | 0 |
|
172 | 0 | VRManager* vm = VRManager::Get(); |
173 | 0 | vm->NotifyGamepadChange<dom::GamepadPoseInformation>(aIndex, a); |
174 | 0 | } |
175 | | |
176 | | void |
177 | | VRSystemManager::NewHandChangeEvent(uint32_t aIndex, |
178 | | const dom::GamepadHand aHand) |
179 | 0 | { |
180 | 0 | dom::GamepadHandInformation a(aHand); |
181 | 0 |
|
182 | 0 | VRManager* vm = VRManager::Get(); |
183 | 0 | vm->NotifyGamepadChange<dom::GamepadHandInformation>(aIndex, a); |
184 | 0 | } |
185 | | |
186 | | void |
187 | | VRHMDSensorState::CalcViewMatrices(const gfx::Matrix4x4* aHeadToEyeTransforms) |
188 | 0 | { |
189 | 0 |
|
190 | 0 | gfx::Matrix4x4 matHead; |
191 | 0 | if (flags & VRDisplayCapabilityFlags::Cap_Orientation) { |
192 | 0 | matHead.SetRotationFromQuaternion(gfx::Quaternion(pose.orientation[0], pose.orientation[1], |
193 | 0 | pose.orientation[2], pose.orientation[3])); |
194 | 0 | } |
195 | 0 | matHead.PreTranslate(-pose.position[0], -pose.position[1], -pose.position[2]); |
196 | 0 |
|
197 | 0 | gfx::Matrix4x4 matView = matHead * aHeadToEyeTransforms[VRDisplayState::Eye_Left]; |
198 | 0 | matView.Normalize(); |
199 | 0 | memcpy(leftViewMatrix, matView.components, sizeof(matView.components)); |
200 | 0 | matView = matHead * aHeadToEyeTransforms[VRDisplayState::Eye_Right]; |
201 | 0 | matView.Normalize(); |
202 | 0 | memcpy(rightViewMatrix, matView.components, sizeof(matView.components)); |
203 | 0 | } |
204 | | |
205 | | const IntSize |
206 | | VRDisplayInfo::SuggestedEyeResolution() const |
207 | 0 | { |
208 | 0 | return IntSize(mDisplayState.mEyeResolution.width, |
209 | 0 | mDisplayState.mEyeResolution.height); |
210 | 0 | } |
211 | | |
212 | | const Point3D |
213 | | VRDisplayInfo::GetEyeTranslation(uint32_t whichEye) const |
214 | 0 | { |
215 | 0 | return Point3D(mDisplayState.mEyeTranslation[whichEye].x, |
216 | 0 | mDisplayState.mEyeTranslation[whichEye].y, |
217 | 0 | mDisplayState.mEyeTranslation[whichEye].z); |
218 | 0 | } |
219 | | |
220 | | const Size |
221 | | VRDisplayInfo::GetStageSize() const |
222 | 0 | { |
223 | 0 | return Size(mDisplayState.mStageSize.width, |
224 | 0 | mDisplayState.mStageSize.height); |
225 | 0 | } |
226 | | |
227 | | const Matrix4x4 |
228 | | VRDisplayInfo::GetSittingToStandingTransform() const |
229 | 0 | { |
230 | 0 | Matrix4x4 m; |
231 | 0 | // If we could replace Matrix4x4 with a pod type, we could |
232 | 0 | // use it directly from the VRDisplayInfo struct. |
233 | 0 | memcpy(m.components, mDisplayState.mSittingToStandingTransform, sizeof(float) * 16); |
234 | 0 | return m; |
235 | 0 | } |