File: gfxVR.cpp

package info (click to toggle)
thunderbird 1:60.8.0-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,339,208 kB
  • sloc: cpp: 5,456,704; ansic: 2,360,384; python: 596,095; asm: 340,963; java: 326,291; xml: 258,664; sh: 84,366; makefile: 23,702; perl: 17,317; objc: 3,768; yacc: 1,766; ada: 1,681; lex: 1,364; pascal: 1,264; cs: 879; exp: 527; php: 436; lisp: 258; ruby: 153; awk: 152; sed: 53; csh: 27
file content (177 lines) | stat: -rw-r--r-- 6,080 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 http://mozilla.org/MPL/2.0/. */

#include <math.h>

#include "gfxVR.h"
#include "mozilla/dom/GamepadEventTypes.h"
#include "mozilla/dom/GamepadBinding.h"
#include "VRDisplayHost.h"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

using namespace mozilla;
using namespace mozilla::gfx;

Atomic<uint32_t> VRSystemManager::sDisplayBase(0);
Atomic<uint32_t> VRSystemManager::sControllerBase(0);

/* static */ uint32_t VRSystemManager::AllocateDisplayID() {
  return ++sDisplayBase;
}

/* static */ uint32_t VRSystemManager::AllocateControllerID() {
  return ++sControllerBase;
}

/**
 * VRSystemManager::NotifyVsync must be called even when a WebVR site is
 * not active, in order to poll for respond to VR Platform API requests.
 * This should be called very often, ideally once per frame.
 * VRSystemManager::Refresh will not activate VR hardware or
 * initialize VR runtimes that have not already been activated.
 */
void VRSystemManager::NotifyVSync() {
  // VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
  // through a local copy here.
  nsTArray<RefPtr<VRDisplayHost>> displays;
  GetHMDs(displays);
  for (const auto& display : displays) {
    display->NotifyVSync();
  }

  // Ensure that the controller state is updated at least
  // on every 2d display VSync when not in a VR presentation.
  if (!GetIsPresenting()) {
    HandleInput();
  }
}

/**
 * VRSystemManager::GetHMDs must not be called unless
 * VRSystemManager::ShouldInhibitEnumeration is called
 * on all VRSystemManager instances and they all return
 * false.
 *
 * This is used to ensure that VR devices that can be
 * enumerated by multiple API's are only enumerated by
 * one API.
 *
 * GetHMDs is called for the most specific API
 * (ie. Oculus SDK) first before calling GetHMDs on
 * more generic api's (ie. OpenVR) to ensure that a device
 * is accessed using the API most optimized for it.
 *
 * ShouldInhibitEnumeration may also be used to prevent
 * devices from jumping to other API's when they are
 * intentionally ignored, such as when responding to
 * requests by the VR platform to unload the libraries
 * for runtime software updates.
 */
bool VRSystemManager::ShouldInhibitEnumeration() { return false; }

Matrix4x4 VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
                                                   bool rightHanded) const {
  float upTan = tan(upDegrees * M_PI / 180.0);
  float downTan = tan(downDegrees * M_PI / 180.0);
  float leftTan = tan(leftDegrees * M_PI / 180.0);
  float rightTan = tan(rightDegrees * M_PI / 180.0);

  float handednessScale = rightHanded ? -1.0 : 1.0;

  float pxscale = 2.0f / (leftTan + rightTan);
  float pxoffset = (leftTan - rightTan) * pxscale * 0.5;
  float pyscale = 2.0f / (upTan + downTan);
  float pyoffset = (upTan - downTan) * pyscale * 0.5;

  Matrix4x4 mobj;
  float* m = &mobj._11;

  m[0 * 4 + 0] = pxscale;
  m[2 * 4 + 0] = pxoffset * handednessScale;

  m[1 * 4 + 1] = pyscale;
  m[2 * 4 + 1] = -pyoffset * handednessScale;

  m[2 * 4 + 2] = zFar / (zNear - zFar) * -handednessScale;
  m[3 * 4 + 2] = (zFar * zNear) / (zNear - zFar);

  m[2 * 4 + 3] = handednessScale;
  m[3 * 4 + 3] = 0.0f;

  return mobj;
}

void VRSystemManager::AddGamepad(const VRControllerInfo& controllerInfo) {
  dom::GamepadAdded a(
      NS_ConvertUTF8toUTF16(controllerInfo.GetControllerName()),
      controllerInfo.GetMappingType(), controllerInfo.GetHand(),
      controllerInfo.GetDisplayID(), controllerInfo.GetNumButtons(),
      controllerInfo.GetNumAxes(), controllerInfo.GetNumHaptics());

  VRManager* vm = VRManager::Get();
  vm->NotifyGamepadChange<dom::GamepadAdded>(mControllerCount, a);
}

void VRSystemManager::RemoveGamepad(uint32_t aIndex) {
  dom::GamepadRemoved a;

  VRManager* vm = VRManager::Get();
  vm->NotifyGamepadChange<dom::GamepadRemoved>(aIndex, a);
}

void VRSystemManager::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
                                     bool aPressed, bool aTouched,
                                     double aValue) {
  dom::GamepadButtonInformation a(aButton, aValue, aPressed, aTouched);

  VRManager* vm = VRManager::Get();
  vm->NotifyGamepadChange<dom::GamepadButtonInformation>(aIndex, a);
}

void VRSystemManager::NewAxisMove(uint32_t aIndex, uint32_t aAxis,
                                  double aValue) {
  dom::GamepadAxisInformation a(aAxis, aValue);

  VRManager* vm = VRManager::Get();
  vm->NotifyGamepadChange<dom::GamepadAxisInformation>(aIndex, a);
}

void VRSystemManager::NewPoseState(uint32_t aIndex,
                                   const dom::GamepadPoseState& aPose) {
  dom::GamepadPoseInformation a(aPose);

  VRManager* vm = VRManager::Get();
  vm->NotifyGamepadChange<dom::GamepadPoseInformation>(aIndex, a);
}

void VRSystemManager::NewHandChangeEvent(uint32_t aIndex,
                                         const dom::GamepadHand aHand) {
  dom::GamepadHandInformation a(aHand);

  VRManager* vm = VRManager::Get();
  vm->NotifyGamepadChange<dom::GamepadHandInformation>(aIndex, a);
}

void VRHMDSensorState::CalcViewMatrices(
    const gfx::Matrix4x4* aHeadToEyeTransforms) {
  gfx::Matrix4x4 matHead;
  if (flags & VRDisplayCapabilityFlags::Cap_Orientation) {
    matHead.SetRotationFromQuaternion(gfx::Quaternion(
        orientation[0], orientation[1], orientation[2], orientation[3]));
  }
  matHead.PreTranslate(-position[0], -position[1], -position[2]);

  gfx::Matrix4x4 matView =
      matHead * aHeadToEyeTransforms[VRDisplayInfo::Eye_Left];
  matView.Normalize();
  memcpy(leftViewMatrix, matView.components, sizeof(matView.components));
  matView = matHead * aHeadToEyeTransforms[VRDisplayInfo::Eye_Right];
  matView.Normalize();
  memcpy(rightViewMatrix, matView.components, sizeof(matView.components));
}