Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/openxr/src/common/xr_linear.h
9903 views
1
// Copyright (c) 2017-2025 The Khronos Group Inc.
2
// Copyright (c) 2016, Oculus VR, LLC.
3
//
4
// SPDX-License-Identifier: Apache-2.0
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
21
#ifndef XR_LINEAR_H_
22
#define XR_LINEAR_H_
23
24
#include <openxr/openxr.h>
25
26
/* REUSE-IgnoreStart */
27
/* The following has copyright notices that duplicate the header above */
28
29
/*
30
================================================================================================
31
32
Description : Vector, matrix and quaternion math.
33
Orig. Author : J.M.P. van Waveren
34
Orig. Date : 12/10/2016
35
Language : C99
36
Copyright : Copyright (c) 2016 Oculus VR, LLC. All Rights reserved.
37
38
39
DESCRIPTION
40
===========
41
42
All matrices are column-major.
43
44
INTERFACE
45
=========
46
47
XrVector2f
48
XrVector3f
49
XrVector4f
50
XrQuaternionf
51
XrPosef
52
XrMatrix4x4f
53
54
inline static void XrVector3f_Set(XrVector3f* v, const float value);
55
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
56
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
57
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
58
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
59
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value);
60
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction);
61
inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor);
62
inline static void XrVector3f_Normalize(XrVector3f* v);
63
inline static float XrVector3f_Length(const XrVector3f* v);
64
65
inline static void XrQuaternionf_CreateIdentity(XrQuaternionf* q);
66
inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians);
67
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction);
68
inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b);
69
inline static void XrQuaternionf_Invert(XrQuaternionf* result, const XrQuaternionf* q);
70
inline static void XrQuaternionf_Normalize(XrQuaternionf* q);
71
inline static void XrQuaternionf_RotateVector3f(XrVector3f* result, const XrQuaternionf* a, const XrVector3f* v);
72
73
inline static void XrPosef_CreateIdentity(XrPosef* result);
74
inline static void XrPosef_TransformVector3f(XrVector3f* result, const XrPosef* a, const XrVector3f* v);
75
inline static void XrPosef_Multiply(XrPosef* result, const XrPosef* a, const XrPosef* b);
76
inline static void XrPosef_Invert(XrPosef* result, const XrPosef* a);
77
78
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result);
79
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z);
80
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
81
const float degreesZ);
82
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z);
83
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
84
const XrQuaternionf* rotation, const XrVector3f* scale);
85
inline static void XrMatrix4x4f_CreateFromRigidTransform(XrMatrix4x4f* result, const XrPosef* s);
86
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
87
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
88
const float nearZ, const float farZ);
89
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
90
const float nearZ, const float farZ);
91
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat);
92
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
93
const XrVector3f* maxs);
94
95
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon);
96
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon);
97
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon);
98
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon);
99
100
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src);
101
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src);
102
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src);
103
104
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b);
105
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src);
106
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src);
107
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src);
108
109
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v);
110
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v);
111
112
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
113
const XrVector3f* mins, const XrVector3f* maxs);
114
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs);
115
116
================================================================================================
117
*/
118
119
#include <assert.h>
120
#include <math.h>
121
#include <stdbool.h>
122
123
#define MATH_PI 3.14159265358979323846f
124
125
#define DEFAULT_NEAR_Z 0.015625f // exact floating point representation
126
#define INFINITE_FAR_Z 0.0f
127
128
static const XrColor4f XrColorRed = {1.0f, 0.0f, 0.0f, 1.0f};
129
static const XrColor4f XrColorGreen = {0.0f, 1.0f, 0.0f, 1.0f};
130
static const XrColor4f XrColorBlue = {0.0f, 0.0f, 1.0f, 1.0f};
131
static const XrColor4f XrColorYellow = {1.0f, 1.0f, 0.0f, 1.0f};
132
static const XrColor4f XrColorPurple = {1.0f, 0.0f, 1.0f, 1.0f};
133
static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f};
134
static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f};
135
static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f};
136
137
typedef enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D, GRAPHICS_METAL } GraphicsAPI;
138
139
// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
140
typedef struct XrMatrix4x4f {
141
float m[16];
142
} XrMatrix4x4f;
143
144
inline static float XrRcpSqrt(const float x) {
145
const float SMALLEST_NON_DENORMAL = 1.1754943508222875e-038f; // ( 1U << 23 )
146
const float rcp = (x >= SMALLEST_NON_DENORMAL) ? 1.0f / sqrtf(x) : 1.0f;
147
return rcp;
148
}
149
150
inline static float XrVector2f_Length(const XrVector2f* v) { return sqrtf(v->x * v->x + v->y * v->y); }
151
152
inline static void XrVector3f_Set(XrVector3f* v, const float value) {
153
v->x = value;
154
v->y = value;
155
v->z = value;
156
}
157
158
inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
159
result->x = a->x + b->x;
160
result->y = a->y + b->y;
161
result->z = a->z + b->z;
162
}
163
164
inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
165
result->x = a->x - b->x;
166
result->y = a->y - b->y;
167
result->z = a->z - b->z;
168
}
169
170
inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
171
result->x = (a->x < b->x) ? a->x : b->x;
172
result->y = (a->y < b->y) ? a->y : b->y;
173
result->z = (a->z < b->z) ? a->z : b->z;
174
}
175
176
inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
177
result->x = (a->x > b->x) ? a->x : b->x;
178
result->y = (a->y > b->y) ? a->y : b->y;
179
result->z = (a->z > b->z) ? a->z : b->z;
180
}
181
182
inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value) {
183
result->x = (fabsf(a->x) > value) ? ((a->x > 0.0f) ? (a->x - value) : (a->x + value)) : 0.0f;
184
result->y = (fabsf(a->y) > value) ? ((a->y > 0.0f) ? (a->y - value) : (a->y + value)) : 0.0f;
185
result->z = (fabsf(a->z) > value) ? ((a->z > 0.0f) ? (a->z - value) : (a->z + value)) : 0.0f;
186
}
187
188
inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction) {
189
result->x = a->x + fraction * (b->x - a->x);
190
result->y = a->y + fraction * (b->y - a->y);
191
result->z = a->z + fraction * (b->z - a->z);
192
}
193
194
inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor) {
195
result->x = a->x * scaleFactor;
196
result->y = a->y * scaleFactor;
197
result->z = a->z * scaleFactor;
198
}
199
200
inline static float XrVector3f_Dot(const XrVector3f* a, const XrVector3f* b) { return a->x * b->x + a->y * b->y + a->z * b->z; }
201
202
// Compute cross product, which generates a normal vector.
203
// Direction vector can be determined by right-hand rule: Pointing index finder in
204
// direction a and middle finger in direction b, thumb will point in Cross(a, b).
205
inline static void XrVector3f_Cross(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
206
result->x = a->y * b->z - a->z * b->y;
207
result->y = a->z * b->x - a->x * b->z;
208
result->z = a->x * b->y - a->y * b->x;
209
}
210
211
inline static void XrVector3f_Normalize(XrVector3f* v) {
212
const float lengthRcp = XrRcpSqrt(v->x * v->x + v->y * v->y + v->z * v->z);
213
v->x *= lengthRcp;
214
v->y *= lengthRcp;
215
v->z *= lengthRcp;
216
}
217
218
inline static float XrVector3f_Length(const XrVector3f* v) { return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); }
219
220
inline static void XrQuaternionf_CreateIdentity(XrQuaternionf* q) {
221
q->x = 0.0f;
222
q->y = 0.0f;
223
q->z = 0.0f;
224
q->w = 1.0f;
225
}
226
227
inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians) {
228
float s = sinf(angleInRadians / 2.0f);
229
float lengthRcp = XrRcpSqrt(axis->x * axis->x + axis->y * axis->y + axis->z * axis->z);
230
result->x = s * axis->x * lengthRcp;
231
result->y = s * axis->y * lengthRcp;
232
result->z = s * axis->z * lengthRcp;
233
result->w = cosf(angleInRadians / 2.0f);
234
}
235
236
inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction) {
237
const float s = a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w;
238
const float fa = 1.0f - fraction;
239
const float fb = (s < 0.0f) ? -fraction : fraction;
240
const float x = a->x * fa + b->x * fb;
241
const float y = a->y * fa + b->y * fb;
242
const float z = a->z * fa + b->z * fb;
243
const float w = a->w * fa + b->w * fb;
244
const float lengthRcp = XrRcpSqrt(x * x + y * y + z * z + w * w);
245
result->x = x * lengthRcp;
246
result->y = y * lengthRcp;
247
result->z = z * lengthRcp;
248
result->w = w * lengthRcp;
249
}
250
251
inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b) {
252
result->x = (b->w * a->x) + (b->x * a->w) + (b->y * a->z) - (b->z * a->y);
253
result->y = (b->w * a->y) - (b->x * a->z) + (b->y * a->w) + (b->z * a->x);
254
result->z = (b->w * a->z) + (b->x * a->y) - (b->y * a->x) + (b->z * a->w);
255
result->w = (b->w * a->w) - (b->x * a->x) - (b->y * a->y) - (b->z * a->z);
256
}
257
258
inline static void XrQuaternionf_Invert(XrQuaternionf* result, const XrQuaternionf* q) {
259
result->x = -q->x;
260
result->y = -q->y;
261
result->z = -q->z;
262
result->w = q->w;
263
}
264
265
inline static void XrQuaternionf_Normalize(XrQuaternionf* q) {
266
const float lengthRcp = XrRcpSqrt(q->x * q->x + q->y * q->y + q->z * q->z + q->w * q->w);
267
q->x *= lengthRcp;
268
q->y *= lengthRcp;
269
q->z *= lengthRcp;
270
q->w *= lengthRcp;
271
}
272
273
inline static void XrQuaternionf_RotateVector3f(XrVector3f* result, const XrQuaternionf* a, const XrVector3f* v) {
274
XrQuaternionf q = {v->x, v->y, v->z, 0.0f};
275
XrQuaternionf aq;
276
XrQuaternionf_Multiply(&aq, &q, a);
277
XrQuaternionf aInv;
278
XrQuaternionf_Invert(&aInv, a);
279
XrQuaternionf aqaInv;
280
XrQuaternionf_Multiply(&aqaInv, &aInv, &aq);
281
282
result->x = aqaInv.x;
283
result->y = aqaInv.y;
284
result->z = aqaInv.z;
285
}
286
287
inline static void XrPosef_CreateIdentity(XrPosef* result) {
288
XrQuaternionf_CreateIdentity(&result->orientation);
289
XrVector3f_Set(&result->position, 0);
290
}
291
292
inline static void XrPosef_TransformVector3f(XrVector3f* result, const XrPosef* a, const XrVector3f* v) {
293
XrVector3f r0;
294
XrQuaternionf_RotateVector3f(&r0, &a->orientation, v);
295
XrVector3f_Add(result, &r0, &a->position);
296
}
297
298
inline static void XrPosef_Multiply(XrPosef* result, const XrPosef* a, const XrPosef* b) {
299
XrQuaternionf_Multiply(&result->orientation, &b->orientation, &a->orientation);
300
XrPosef_TransformVector3f(&result->position, a, &b->position);
301
}
302
303
inline static void XrPosef_Invert(XrPosef* result, const XrPosef* a) {
304
XrQuaternionf_Invert(&result->orientation, &a->orientation);
305
XrVector3f aPosNeg;
306
XrVector3f_Scale(&aPosNeg, &a->position, -1.0f);
307
XrQuaternionf_RotateVector3f(&result->position, &result->orientation, &aPosNeg);
308
}
309
310
// Use left-multiplication to accumulate transformations.
311
inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
312
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];
313
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];
314
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];
315
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];
316
317
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];
318
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];
319
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];
320
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];
321
322
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];
323
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];
324
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];
325
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];
326
327
result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
328
result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
329
result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
330
result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
331
}
332
333
// Creates the transpose of the given matrix.
334
inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
335
result->m[0] = src->m[0];
336
result->m[1] = src->m[4];
337
result->m[2] = src->m[8];
338
result->m[3] = src->m[12];
339
340
result->m[4] = src->m[1];
341
result->m[5] = src->m[5];
342
result->m[6] = src->m[9];
343
result->m[7] = src->m[13];
344
345
result->m[8] = src->m[2];
346
result->m[9] = src->m[6];
347
result->m[10] = src->m[10];
348
result->m[11] = src->m[14];
349
350
result->m[12] = src->m[3];
351
result->m[13] = src->m[7];
352
result->m[14] = src->m[11];
353
result->m[15] = src->m[15];
354
}
355
356
// Returns a 3x3 minor of a 4x4 matrix.
357
inline static float XrMatrix4x4f_Minor(const XrMatrix4x4f* matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
358
return matrix->m[4 * r0 + c0] *
359
(matrix->m[4 * r1 + c1] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c1] * matrix->m[4 * r1 + c2]) -
360
matrix->m[4 * r0 + c1] *
361
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c2]) +
362
matrix->m[4 * r0 + c2] *
363
(matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c1] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c1]);
364
}
365
366
// Calculates the inverse of a 4x4 matrix.
367
inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
368
const float rcpDet =
369
1.0f / (src->m[0] * XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) - src->m[1] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) +
370
src->m[2] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) - src->m[3] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2));
371
372
result->m[0] = XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) * rcpDet;
373
result->m[1] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 1, 2, 3) * rcpDet;
374
result->m[2] = XrMatrix4x4f_Minor(src, 0, 1, 3, 1, 2, 3) * rcpDet;
375
result->m[3] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 1, 2, 3) * rcpDet;
376
result->m[4] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) * rcpDet;
377
result->m[5] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 2, 3) * rcpDet;
378
result->m[6] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 2, 3) * rcpDet;
379
result->m[7] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 2, 3) * rcpDet;
380
result->m[8] = XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) * rcpDet;
381
result->m[9] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 3) * rcpDet;
382
result->m[10] = XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 3) * rcpDet;
383
result->m[11] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 3) * rcpDet;
384
result->m[12] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2) * rcpDet;
385
result->m[13] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 2) * rcpDet;
386
result->m[14] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 2) * rcpDet;
387
result->m[15] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 2) * rcpDet;
388
}
389
390
// Calculates the inverse of a rigid body transform.
391
inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
392
result->m[0] = src->m[0];
393
result->m[1] = src->m[4];
394
result->m[2] = src->m[8];
395
result->m[3] = 0.0f;
396
result->m[4] = src->m[1];
397
result->m[5] = src->m[5];
398
result->m[6] = src->m[9];
399
result->m[7] = 0.0f;
400
result->m[8] = src->m[2];
401
result->m[9] = src->m[6];
402
result->m[10] = src->m[10];
403
result->m[11] = 0.0f;
404
result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
405
result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
406
result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
407
result->m[15] = 1.0f;
408
}
409
410
// Creates an identity matrix.
411
inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result) {
412
result->m[0] = 1.0f;
413
result->m[1] = 0.0f;
414
result->m[2] = 0.0f;
415
result->m[3] = 0.0f;
416
result->m[4] = 0.0f;
417
result->m[5] = 1.0f;
418
result->m[6] = 0.0f;
419
result->m[7] = 0.0f;
420
result->m[8] = 0.0f;
421
result->m[9] = 0.0f;
422
result->m[10] = 1.0f;
423
result->m[11] = 0.0f;
424
result->m[12] = 0.0f;
425
result->m[13] = 0.0f;
426
result->m[14] = 0.0f;
427
result->m[15] = 1.0f;
428
}
429
430
// Creates a translation matrix.
431
inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z) {
432
result->m[0] = 1.0f;
433
result->m[1] = 0.0f;
434
result->m[2] = 0.0f;
435
result->m[3] = 0.0f;
436
result->m[4] = 0.0f;
437
result->m[5] = 1.0f;
438
result->m[6] = 0.0f;
439
result->m[7] = 0.0f;
440
result->m[8] = 0.0f;
441
result->m[9] = 0.0f;
442
result->m[10] = 1.0f;
443
result->m[11] = 0.0f;
444
result->m[12] = x;
445
result->m[13] = y;
446
result->m[14] = z;
447
result->m[15] = 1.0f;
448
}
449
450
// Creates a rotation matrix.
451
// If -Z=forward, +Y=up, +X=right, then radiansX=pitch, radiansY=yaw, radiansZ=roll.
452
inline static void XrMatrix4x4f_CreateRotationRadians(XrMatrix4x4f* result, const float radiansX, const float radiansY,
453
const float radiansZ) {
454
const float sinX = sinf(radiansX);
455
const float cosX = cosf(radiansX);
456
const XrMatrix4x4f rotationX = {{1, 0, 0, 0, 0, cosX, sinX, 0, 0, -sinX, cosX, 0, 0, 0, 0, 1}};
457
const float sinY = sinf(radiansY);
458
const float cosY = cosf(radiansY);
459
const XrMatrix4x4f rotationY = {{cosY, 0, -sinY, 0, 0, 1, 0, 0, sinY, 0, cosY, 0, 0, 0, 0, 1}};
460
const float sinZ = sinf(radiansZ);
461
const float cosZ = cosf(radiansZ);
462
const XrMatrix4x4f rotationZ = {{cosZ, sinZ, 0, 0, -sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
463
XrMatrix4x4f rotationXY;
464
XrMatrix4x4f_Multiply(&rotationXY, &rotationY, &rotationX);
465
XrMatrix4x4f_Multiply(result, &rotationZ, &rotationXY);
466
}
467
468
// Creates a rotation matrix.
469
// If -Z=forward, +Y=up, +X=right, then degreesX=pitch, degreesY=yaw, degreesZ=roll.
470
inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
471
const float degreesZ) {
472
XrMatrix4x4f_CreateRotationRadians(result, degreesX * (MATH_PI / 180.0f), degreesY * (MATH_PI / 180.0f),
473
degreesZ * (MATH_PI / 180.0f));
474
}
475
476
// Creates a scale matrix.
477
inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z) {
478
result->m[0] = x;
479
result->m[1] = 0.0f;
480
result->m[2] = 0.0f;
481
result->m[3] = 0.0f;
482
result->m[4] = 0.0f;
483
result->m[5] = y;
484
result->m[6] = 0.0f;
485
result->m[7] = 0.0f;
486
result->m[8] = 0.0f;
487
result->m[9] = 0.0f;
488
result->m[10] = z;
489
result->m[11] = 0.0f;
490
result->m[12] = 0.0f;
491
result->m[13] = 0.0f;
492
result->m[14] = 0.0f;
493
result->m[15] = 1.0f;
494
}
495
496
// Creates a matrix from a quaternion.
497
inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat) {
498
const float x2 = quat->x + quat->x;
499
const float y2 = quat->y + quat->y;
500
const float z2 = quat->z + quat->z;
501
502
const float xx2 = quat->x * x2;
503
const float yy2 = quat->y * y2;
504
const float zz2 = quat->z * z2;
505
506
const float yz2 = quat->y * z2;
507
const float wx2 = quat->w * x2;
508
const float xy2 = quat->x * y2;
509
const float wz2 = quat->w * z2;
510
const float xz2 = quat->x * z2;
511
const float wy2 = quat->w * y2;
512
513
result->m[0] = 1.0f - yy2 - zz2;
514
result->m[1] = xy2 + wz2;
515
result->m[2] = xz2 - wy2;
516
result->m[3] = 0.0f;
517
518
result->m[4] = xy2 - wz2;
519
result->m[5] = 1.0f - xx2 - zz2;
520
result->m[6] = yz2 + wx2;
521
result->m[7] = 0.0f;
522
523
result->m[8] = xz2 + wy2;
524
result->m[9] = yz2 - wx2;
525
result->m[10] = 1.0f - xx2 - yy2;
526
result->m[11] = 0.0f;
527
528
result->m[12] = 0.0f;
529
result->m[13] = 0.0f;
530
result->m[14] = 0.0f;
531
result->m[15] = 1.0f;
532
}
533
534
// Creates a combined translation(rotation(scale(object))) matrix.
535
inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
536
const XrQuaternionf* rotation, const XrVector3f* scale) {
537
XrMatrix4x4f scaleMatrix;
538
XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
539
540
XrMatrix4x4f rotationMatrix;
541
XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
542
543
XrMatrix4x4f translationMatrix;
544
XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
545
546
XrMatrix4x4f combinedMatrix;
547
XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
548
XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
549
}
550
551
inline static void XrMatrix4x4f_CreateFromRigidTransform(XrMatrix4x4f* result, const XrPosef* s) {
552
const XrVector3f identityScale = {1.0f, 1.0f, 1.0f};
553
XrMatrix4x4f_CreateTranslationRotationScale(result, &s->position, &s->orientation, &identityScale);
554
}
555
556
// Creates a projection matrix based on the specified dimensions.
557
// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
558
// The far plane is placed at infinity if farZ <= nearZ.
559
// An infinite projection matrix is preferred for rasterization because, except for
560
// things *right* up against the near plane, it always provides better precision:
561
// "Tightening the Precision of Perspective Rendering"
562
// Paul Upchurch, Mathieu Desbrun
563
// Journal of Graphics Tools, Volume 16, Issue 1, 2012
564
inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
565
const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
566
const float nearZ, const float farZ) {
567
const float tanAngleWidth = tanAngleRight - tanAngleLeft;
568
569
// Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
570
// Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
571
const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
572
573
// Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
574
// Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
575
const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
576
577
if (farZ <= nearZ) {
578
// place the far plane at infinity
579
result->m[0] = 2.0f / tanAngleWidth;
580
result->m[4] = 0.0f;
581
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
582
result->m[12] = 0.0f;
583
584
result->m[1] = 0.0f;
585
result->m[5] = 2.0f / tanAngleHeight;
586
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
587
result->m[13] = 0.0f;
588
589
result->m[2] = 0.0f;
590
result->m[6] = 0.0f;
591
result->m[10] = -1.0f;
592
result->m[14] = -(nearZ + offsetZ);
593
594
result->m[3] = 0.0f;
595
result->m[7] = 0.0f;
596
result->m[11] = -1.0f;
597
result->m[15] = 0.0f;
598
} else {
599
// normal projection
600
result->m[0] = 2.0f / tanAngleWidth;
601
result->m[4] = 0.0f;
602
result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
603
result->m[12] = 0.0f;
604
605
result->m[1] = 0.0f;
606
result->m[5] = 2.0f / tanAngleHeight;
607
result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
608
result->m[13] = 0.0f;
609
610
result->m[2] = 0.0f;
611
result->m[6] = 0.0f;
612
result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
613
result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
614
615
result->m[3] = 0.0f;
616
result->m[7] = 0.0f;
617
result->m[11] = -1.0f;
618
result->m[15] = 0.0f;
619
}
620
}
621
622
// Creates a projection matrix based on the specified FOV.
623
inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
624
const float nearZ, const float farZ) {
625
const float tanLeft = tanf(fov.angleLeft);
626
const float tanRight = tanf(fov.angleRight);
627
628
const float tanDown = tanf(fov.angleDown);
629
const float tanUp = tanf(fov.angleUp);
630
631
XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
632
}
633
634
// Creates a matrix that transforms the -1 to 1 cube to cover the given 'mins' and 'maxs' transformed with the given 'matrix'.
635
inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
636
const XrVector3f* maxs) {
637
const XrVector3f offset = {(maxs->x + mins->x) * 0.5f, (maxs->y + mins->y) * 0.5f, (maxs->z + mins->z) * 0.5f};
638
const XrVector3f scale = {(maxs->x - mins->x) * 0.5f, (maxs->y - mins->y) * 0.5f, (maxs->z - mins->z) * 0.5f};
639
640
result->m[0] = matrix->m[0] * scale.x;
641
result->m[1] = matrix->m[1] * scale.x;
642
result->m[2] = matrix->m[2] * scale.x;
643
result->m[3] = matrix->m[3] * scale.x;
644
645
result->m[4] = matrix->m[4] * scale.y;
646
result->m[5] = matrix->m[5] * scale.y;
647
result->m[6] = matrix->m[6] * scale.y;
648
result->m[7] = matrix->m[7] * scale.y;
649
650
result->m[8] = matrix->m[8] * scale.z;
651
result->m[9] = matrix->m[9] * scale.z;
652
result->m[10] = matrix->m[10] * scale.z;
653
result->m[11] = matrix->m[11] * scale.z;
654
655
result->m[12] = matrix->m[12] + matrix->m[0] * offset.x + matrix->m[4] * offset.y + matrix->m[8] * offset.z;
656
result->m[13] = matrix->m[13] + matrix->m[1] * offset.x + matrix->m[5] * offset.y + matrix->m[9] * offset.z;
657
result->m[14] = matrix->m[14] + matrix->m[2] * offset.x + matrix->m[6] * offset.y + matrix->m[10] * offset.z;
658
result->m[15] = matrix->m[15] + matrix->m[3] * offset.x + matrix->m[7] * offset.y + matrix->m[11] * offset.z;
659
}
660
661
// Returns true if the given matrix is affine.
662
inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon) {
663
return fabsf(matrix->m[3]) <= epsilon && fabsf(matrix->m[7]) <= epsilon && fabsf(matrix->m[11]) <= epsilon &&
664
fabsf(matrix->m[15] - 1.0f) <= epsilon;
665
}
666
667
// Returns true if the given matrix is orthogonal.
668
inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon) {
669
for (int i = 0; i < 3; i++) {
670
for (int j = 0; j < 3; j++) {
671
if (i != j) {
672
if (fabsf(matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
673
matrix->m[4 * i + 2] * matrix->m[4 * j + 2]) > epsilon) {
674
return false;
675
}
676
if (fabsf(matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
677
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j]) > epsilon) {
678
return false;
679
}
680
}
681
}
682
}
683
return true;
684
}
685
686
// Returns true if the given matrix is orthonormal.
687
inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon) {
688
for (int i = 0; i < 3; i++) {
689
for (int j = 0; j < 3; j++) {
690
const float kd = (i == j) ? 1.0f : 0.0f; // Kronecker delta
691
if (fabsf(kd - (matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
692
matrix->m[4 * i + 2] * matrix->m[4 * j + 2])) > epsilon) {
693
return false;
694
}
695
if (fabsf(kd - (matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
696
matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j])) > epsilon) {
697
return false;
698
}
699
}
700
}
701
return true;
702
}
703
704
// Returns true if the given matrix is a rigid body transform.
705
inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon) {
706
return XrMatrix4x4f_IsAffine(matrix, epsilon) && XrMatrix4x4f_IsOrthonormal(matrix, epsilon);
707
}
708
709
// Get the translation from a combined translation(rotation(scale(object))) matrix.
710
inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src) {
711
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
712
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
713
714
result->x = src->m[12];
715
result->y = src->m[13];
716
result->z = src->m[14];
717
}
718
719
// Get the rotation from a combined translation(rotation(scale(object))) matrix.
720
inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src) {
721
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
722
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
723
724
const float rcpScaleX = XrRcpSqrt(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
725
const float rcpScaleY = XrRcpSqrt(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
726
const float rcpScaleZ = XrRcpSqrt(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
727
const float m[9] = {src->m[0] * rcpScaleX, src->m[1] * rcpScaleX, src->m[2] * rcpScaleX,
728
src->m[4] * rcpScaleY, src->m[5] * rcpScaleY, src->m[6] * rcpScaleY,
729
src->m[8] * rcpScaleZ, src->m[9] * rcpScaleZ, src->m[10] * rcpScaleZ};
730
if (m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] > 0.0f) {
731
float t = +m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
732
float s = XrRcpSqrt(t) * 0.5f;
733
result->w = s * t;
734
result->z = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
735
result->y = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
736
result->x = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
737
} else if (m[0 * 3 + 0] > m[1 * 3 + 1] && m[0 * 3 + 0] > m[2 * 3 + 2]) {
738
float t = +m[0 * 3 + 0] - m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
739
float s = XrRcpSqrt(t) * 0.5f;
740
result->x = s * t;
741
result->y = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
742
result->z = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
743
result->w = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
744
} else if (m[1 * 3 + 1] > m[2 * 3 + 2]) {
745
float t = -m[0 * 3 + 0] + m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
746
float s = XrRcpSqrt(t) * 0.5f;
747
result->y = s * t;
748
result->x = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
749
result->w = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
750
result->z = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
751
} else {
752
float t = -m[0 * 3 + 0] - m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
753
float s = XrRcpSqrt(t) * 0.5f;
754
result->z = s * t;
755
result->w = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
756
result->x = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
757
result->y = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
758
}
759
}
760
761
// Get the scale from a combined translation(rotation(scale(object))) matrix.
762
inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src) {
763
assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
764
assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
765
766
result->x = sqrtf(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
767
result->y = sqrtf(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
768
result->z = sqrtf(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
769
}
770
771
// Transforms a 3D vector.
772
inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v) {
773
const float w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15];
774
const float rcpW = 1.0f / w;
775
result->x = (m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12]) * rcpW;
776
result->y = (m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13]) * rcpW;
777
result->z = (m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14]) * rcpW;
778
}
779
780
// Transforms a 4D vector.
781
inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v) {
782
result->x = m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12] * v->w;
783
result->y = m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13] * v->w;
784
result->z = m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14] * v->w;
785
result->w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15] * v->w;
786
}
787
788
// Transforms the 'mins' and 'maxs' bounds with the given 'matrix'.
789
inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
790
const XrVector3f* mins, const XrVector3f* maxs) {
791
assert(XrMatrix4x4f_IsAffine(matrix, 1e-4f));
792
793
const XrVector3f center = {(mins->x + maxs->x) * 0.5f, (mins->y + maxs->y) * 0.5f, (mins->z + maxs->z) * 0.5f};
794
const XrVector3f extents = {maxs->x - center.x, maxs->y - center.y, maxs->z - center.z};
795
const XrVector3f newCenter = {matrix->m[0] * center.x + matrix->m[4] * center.y + matrix->m[8] * center.z + matrix->m[12],
796
matrix->m[1] * center.x + matrix->m[5] * center.y + matrix->m[9] * center.z + matrix->m[13],
797
matrix->m[2] * center.x + matrix->m[6] * center.y + matrix->m[10] * center.z + matrix->m[14]};
798
const XrVector3f newExtents = {
799
fabsf(extents.x * matrix->m[0]) + fabsf(extents.y * matrix->m[4]) + fabsf(extents.z * matrix->m[8]),
800
fabsf(extents.x * matrix->m[1]) + fabsf(extents.y * matrix->m[5]) + fabsf(extents.z * matrix->m[9]),
801
fabsf(extents.x * matrix->m[2]) + fabsf(extents.y * matrix->m[6]) + fabsf(extents.z * matrix->m[10])};
802
XrVector3f_Sub(resultMins, &newCenter, &newExtents);
803
XrVector3f_Add(resultMaxs, &newCenter, &newExtents);
804
}
805
806
// Returns true if the 'mins' and 'maxs' bounds is completely off to one side of the projection matrix.
807
inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs) {
808
if (maxs->x <= mins->x && maxs->y <= mins->y && maxs->z <= mins->z) {
809
return false;
810
}
811
812
XrVector4f c[8];
813
for (int i = 0; i < 8; i++) {
814
const XrVector4f corner = {(i & 1) != 0 ? maxs->x : mins->x, (i & 2) != 0 ? maxs->y : mins->y,
815
(i & 4) != 0 ? maxs->z : mins->z, 1.0f};
816
XrMatrix4x4f_TransformVector4f(&c[i], mvp, &corner);
817
}
818
819
int i;
820
for (i = 0; i < 8; i++) {
821
if (c[i].x > -c[i].w) {
822
break;
823
}
824
}
825
if (i == 8) {
826
return true;
827
}
828
for (i = 0; i < 8; i++) {
829
if (c[i].x < c[i].w) {
830
break;
831
}
832
}
833
if (i == 8) {
834
return true;
835
}
836
837
for (i = 0; i < 8; i++) {
838
if (c[i].y > -c[i].w) {
839
break;
840
}
841
}
842
if (i == 8) {
843
return true;
844
}
845
for (i = 0; i < 8; i++) {
846
if (c[i].y < c[i].w) {
847
break;
848
}
849
}
850
if (i == 8) {
851
return true;
852
}
853
for (i = 0; i < 8; i++) {
854
if (c[i].z > -c[i].w) {
855
break;
856
}
857
}
858
if (i == 8) {
859
return true;
860
}
861
for (i = 0; i < 8; i++) {
862
if (c[i].z < c[i].w) {
863
break;
864
}
865
}
866
return i == 8;
867
}
868
869
#endif // XR_LINEAR_H_
870
871