OPENXR Scol plugin
xrmath.h
1// adapted from
2
3// Copyright (c) 2017 The Khronos Group Inc.
4// Copyright (c) 2016 Oculus VR, LLC.
5//
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17//
18// Author: J.M.P. van Waveren
19
20#pragma once
21
22#include "openxr/openxr.h"
23#include <string>
24#include <cmath>
25
26typedef enum
27{
28 GRAPHICS_VULKAN,
29 GRAPHICS_D3D11,
30 GRAPHICS_OPENGL,
31 GRAPHICS_OPENGL_ES
32} GraphicsAPI;
33
34typedef struct XrMatrix4x4f
35{
36 float m[16];
38
39
40inline static void
41XrFovInRadians(float &fovY,
42 float &fovX,
43 GraphicsAPI graphicsApi,
44 const XrFovf fov)
45{
46 const float tanAngleLeft = tanf(fov.angleLeft);
47 const float tanAngleRight = tanf(fov.angleRight);
48
49 const float tanAngleDown = tanf(fov.angleDown);
50 const float tanAngleUp = tanf(fov.angleUp);
51
52 fovX = atan(tanAngleRight - tanAngleLeft);
53
54 // Set to tanAngleDown - tanAngleUp for a clip space with positive Y
55 // down (Vulkan). Set to tanAngleUp - tanAngleDown for a clip space with
56 // positive Y up (OpenGL / D3D / Metal).
57 fovY = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
58}
59
60// Creates a projection matrix based on the specified dimensions.
61// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
62// The far plane is placed at infinity if farZ <= nearZ.
63// An infinite projection matrix is preferred for rasterization because, except for
64// things *right* up against the near plane, it always provides better precision:
65// "Tightening the Precision of Perspective Rendering"
66// Paul Upchurch, Mathieu Desbrun
67// Journal of Graphics Tools, Volume 16, Issue 1, 2012
68inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
69 const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
70 const float nearZ, const float farZ) {
71 const float tanAngleWidth = tanAngleRight - tanAngleLeft;
72
73 // Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
74 // Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
75 const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
76
77 // Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
78 // Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
79 const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
80
81 if (farZ <= nearZ) {
82 // place the far plane at infinity
83 result->m[0] = 2.0f / tanAngleWidth;
84 result->m[4] = 0.0f;
85 result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
86 result->m[12] = 0.0f;
87
88 result->m[1] = 0.0f;
89 result->m[5] = 2.0f / tanAngleHeight;
90 result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
91 result->m[13] = 0.0f;
92
93 result->m[2] = 0.0f;
94 result->m[6] = 0.0f;
95 result->m[10] = -1.0f;
96 result->m[14] = -(nearZ + offsetZ);
97
98 result->m[3] = 0.0f;
99 result->m[7] = 0.0f;
100 result->m[11] = -1.0f;
101 result->m[15] = 0.0f;
102 }
103 else {
104 // normal projection
105 result->m[0] = 2.0f / tanAngleWidth;
106 result->m[4] = 0.0f;
107 result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
108 result->m[12] = 0.0f;
109
110 result->m[1] = 0.0f;
111 result->m[5] = 2.0f / tanAngleHeight;
112 result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
113 result->m[13] = 0.0f;
114
115 result->m[2] = 0.0f;
116 result->m[6] = 0.0f;
117 result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
118 result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
119
120 result->m[3] = 0.0f;
121 result->m[7] = 0.0f;
122 result->m[11] = -1.0f;
123 result->m[15] = 0.0f;
124 }
125}
126
127// Creates a projection matrix based on the specified FOV.
128inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
129 const float nearZ, const float farZ) {
130
131 const float tanLeft = tanf(fov.angleLeft);
132 const float tanRight = tanf(fov.angleRight);
133
134 const float tanDown = tanf(fov.angleDown);
135 const float tanUp = tanf(fov.angleUp);
136
137 XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
138}
139
140inline static void
141XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f *result, const XrQuaternionf *quat)
142{
143 const float x2 = quat->x + quat->x;
144 const float y2 = quat->y + quat->y;
145 const float z2 = quat->z + quat->z;
146
147 const float xx2 = quat->x * x2;
148 const float yy2 = quat->y * y2;
149 const float zz2 = quat->z * z2;
150
151 const float yz2 = quat->y * z2;
152 const float wx2 = quat->w * x2;
153 const float xy2 = quat->x * y2;
154 const float wz2 = quat->w * z2;
155 const float xz2 = quat->x * z2;
156 const float wy2 = quat->w * y2;
157
158 result->m[0] = 1.0f - yy2 - zz2;
159 result->m[1] = xy2 + wz2;
160 result->m[2] = xz2 - wy2;
161 result->m[3] = 0.0f;
162
163 result->m[4] = xy2 - wz2;
164 result->m[5] = 1.0f - xx2 - zz2;
165 result->m[6] = yz2 + wx2;
166 result->m[7] = 0.0f;
167
168 result->m[8] = xz2 + wy2;
169 result->m[9] = yz2 - wx2;
170 result->m[10] = 1.0f - xx2 - yy2;
171 result->m[11] = 0.0f;
172
173 result->m[12] = 0.0f;
174 result->m[13] = 0.0f;
175 result->m[14] = 0.0f;
176 result->m[15] = 1.0f;
177}
178
179inline static void
180XrMatrix4x4f_CreateTranslation(XrMatrix4x4f *result, const float x, const float y, const float z)
181{
182 result->m[0] = 1.0f;
183 result->m[1] = 0.0f;
184 result->m[2] = 0.0f;
185 result->m[3] = 0.0f;
186 result->m[4] = 0.0f;
187 result->m[5] = 1.0f;
188 result->m[6] = 0.0f;
189 result->m[7] = 0.0f;
190 result->m[8] = 0.0f;
191 result->m[9] = 0.0f;
192 result->m[10] = 1.0f;
193 result->m[11] = 0.0f;
194 result->m[12] = x;
195 result->m[13] = y;
196 result->m[14] = z;
197 result->m[15] = 1.0f;
198}
199
200inline static void
201XrMatrix4x4f_Multiply(XrMatrix4x4f *result, const XrMatrix4x4f *a, const XrMatrix4x4f *b)
202{
203 result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
204 result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
205 result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
206 result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];
207
208 result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
209 result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
210 result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
211 result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];
212
213 result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
214 result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
215 result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
216 result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];
217
218 result->m[12] =
219 a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
220 result->m[13] =
221 a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
222 result->m[14] =
223 a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
224 result->m[15] =
225 a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
226}
227
228inline static void
229XrMatrix4x4f_Invert(XrMatrix4x4f *result, const XrMatrix4x4f *src)
230{
231 result->m[0] = src->m[0];
232 result->m[1] = src->m[4];
233 result->m[2] = src->m[8];
234 result->m[3] = 0.0f;
235 result->m[4] = src->m[1];
236 result->m[5] = src->m[5];
237 result->m[6] = src->m[9];
238 result->m[7] = 0.0f;
239 result->m[8] = src->m[2];
240 result->m[9] = src->m[6];
241 result->m[10] = src->m[10];
242 result->m[11] = 0.0f;
243 result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
244 result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
245 result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
246 result->m[15] = 1.0f;
247}
248
249inline static void
250XrMatrix4x4f_CreateViewMatrix(XrMatrix4x4f *result,
251 const XrVector3f *translation,
252 const XrQuaternionf *rotation)
253{
254
255 XrMatrix4x4f rotationMatrix;
256 XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
257
258 XrMatrix4x4f translationMatrix;
259 XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
260
261 XrMatrix4x4f viewMatrix;
262 XrMatrix4x4f_Multiply(&viewMatrix, &translationMatrix, &rotationMatrix);
263
264 XrMatrix4x4f_Invert(result, &viewMatrix);
265}
266
267// Creates a scale matrix.
268inline static void
269XrMatrix4x4f_CreateScale(XrMatrix4x4f *result, const float x, const float y, const float z)
270{
271 result->m[0] = x;
272 result->m[1] = 0.0f;
273 result->m[2] = 0.0f;
274 result->m[3] = 0.0f;
275 result->m[4] = 0.0f;
276 result->m[5] = y;
277 result->m[6] = 0.0f;
278 result->m[7] = 0.0f;
279 result->m[8] = 0.0f;
280 result->m[9] = 0.0f;
281 result->m[10] = z;
282 result->m[11] = 0.0f;
283 result->m[12] = 0.0f;
284 result->m[13] = 0.0f;
285 result->m[14] = 0.0f;
286 result->m[15] = 1.0f;
287}
288
289inline static void
290XrMatrix4x4f_CreateModelMatrix(XrMatrix4x4f *result,
291 const XrVector3f *translation,
292 const XrQuaternionf *rotation,
293 const XrVector3f *scale)
294{
295 XrMatrix4x4f scaleMatrix;
296 XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
297
298 XrMatrix4x4f rotationMatrix;
299 XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
300
301 XrMatrix4x4f translationMatrix;
302 XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
303
304 XrMatrix4x4f combinedMatrix;
305 XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
306 XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
307}