Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/goddard/gd_math.c
7858 views
1
#include <PR/ultratypes.h>
2
3
#include "debug_utils.h"
4
#include "gd_macros.h"
5
#include "gd_main.h"
6
#include "gd_math.h"
7
#include "gd_types.h"
8
#include "macros.h"
9
#include "renderer.h"
10
11
/**
12
* Finds the square root of a float by treating
13
* it as a double and finding the square root from there.
14
*/
15
f32 gd_sqrt_f(f32 val) {
16
return (f32) gd_sqrt_d(val);
17
}
18
19
/**
20
* Set mtx to a look-at matrix for the camera. The resulting transformation
21
* transforms the world as if there exists a camera at position 'from' pointed
22
* at the position 'to'.
23
* An effective goddard copy of mtxf_lookat.
24
*/
25
void gd_mat4f_lookat(Mat4f *mtx, f32 xFrom, f32 yFrom, f32 zFrom, f32 xTo, f32 yTo, f32 zTo,
26
f32 zColY, f32 yColY, f32 xColY) {
27
f32 invLength;
28
29
struct GdVec3f d;
30
struct GdVec3f colX;
31
struct GdVec3f norm;
32
33
// No reason to do this? mtx is set lower.
34
gd_set_identity_mat4(mtx);
35
36
d.z = xTo - xFrom;
37
d.y = yTo - yFrom;
38
d.x = zTo - zFrom;
39
40
invLength = ABS(d.z) + ABS(d.y) + ABS(d.x);
41
42
// Scales 'd' if smaller than 10 or larger than 10,000 to be
43
// of a magnitude of 10,000.
44
if (invLength > 10000.0f || invLength < 10.0f) {
45
norm.x = d.z;
46
norm.y = d.y;
47
norm.z = d.x;
48
gd_normalize_vec3f(&norm);
49
norm.x *= 10000.0f;
50
norm.y *= 10000.0f;
51
norm.z *= 10000.0f;
52
53
d.z = norm.x;
54
d.y = norm.y;
55
d.x = norm.z;
56
}
57
58
invLength = -1.0 / gd_sqrt_f(SQ(d.z) + SQ(d.y) + SQ(d.x));
59
d.z *= invLength;
60
d.y *= invLength;
61
d.x *= invLength;
62
63
colX.z = yColY * d.x - xColY * d.y;
64
colX.y = xColY * d.z - zColY * d.x;
65
colX.x = zColY * d.y - yColY * d.z;
66
67
invLength = 1.0 / gd_sqrt_f(SQ(colX.z) + SQ(colX.y) + SQ(colX.x));
68
69
colX.z *= invLength;
70
colX.y *= invLength;
71
colX.x *= invLength;
72
73
zColY = d.y * colX.x - d.x * colX.y;
74
yColY = d.x * colX.z - d.z * colX.x;
75
xColY = d.z * colX.y - d.y * colX.z;
76
77
invLength = 1.0 / gd_sqrt_f(SQ(zColY) + SQ(yColY) + SQ(xColY));
78
79
zColY *= invLength;
80
yColY *= invLength;
81
xColY *= invLength;
82
83
(*mtx)[0][0] = colX.z;
84
(*mtx)[1][0] = colX.y;
85
(*mtx)[2][0] = colX.x;
86
(*mtx)[3][0] = -(xFrom * colX.z + yFrom * colX.y + zFrom * colX.x);
87
88
(*mtx)[0][1] = zColY;
89
(*mtx)[1][1] = yColY;
90
(*mtx)[2][1] = xColY;
91
(*mtx)[3][1] = -(xFrom * zColY + yFrom * yColY + zFrom * xColY);
92
93
(*mtx)[0][2] = d.z;
94
(*mtx)[1][2] = d.y;
95
(*mtx)[2][2] = d.x;
96
(*mtx)[3][2] = -(xFrom * d.z + yFrom * d.y + zFrom * d.x);
97
98
(*mtx)[0][3] = 0.0f;
99
(*mtx)[1][3] = 0.0f;
100
(*mtx)[2][3] = 0.0f;
101
(*mtx)[3][3] = 1.0f;
102
}
103
104
/**
105
* Scales a mat4f in each dimension by a vector.
106
*/
107
void gd_scale_mat4f_by_vec3f(Mat4f *mtx, struct GdVec3f *vec) {
108
(*mtx)[0][0] *= vec->x;
109
(*mtx)[0][1] *= vec->x;
110
(*mtx)[0][2] *= vec->x;
111
(*mtx)[1][0] *= vec->y;
112
(*mtx)[1][1] *= vec->y;
113
(*mtx)[1][2] *= vec->y;
114
(*mtx)[2][0] *= vec->z;
115
(*mtx)[2][1] *= vec->z;
116
(*mtx)[2][2] *= vec->z;
117
}
118
119
/**
120
* Rotates the matrix 'mtx' about the vector given.
121
*/
122
void gd_rot_mat_about_vec(Mat4f *mtx, struct GdVec3f *vec) {
123
if (vec->x != 0.0f) {
124
gd_absrot_mat4(mtx, GD_X_AXIS, vec->x);
125
}
126
if (vec->y != 0.0f) {
127
gd_absrot_mat4(mtx, GD_Y_AXIS, vec->y);
128
}
129
if (vec->z != 0.0f) {
130
gd_absrot_mat4(mtx, GD_Z_AXIS, vec->z);
131
}
132
}
133
134
/**
135
* Adds each component of a vector to the
136
* translation column of a mat4f matrix.
137
*/
138
void gd_add_vec3f_to_mat4f_offset(Mat4f *mtx, struct GdVec3f *vec) {
139
UNUSED Mat4f temp;
140
f32 z, y, x;
141
142
x = vec->x;
143
y = vec->y;
144
z = vec->z;
145
146
(*mtx)[3][0] += x;
147
(*mtx)[3][1] += y;
148
(*mtx)[3][2] += z;
149
}
150
151
/**
152
* Creates a lookat matrix, but specifically from the perspective of the origin.
153
* Rolls is only ever 0 in practice, and this is really only ever used once.
154
*
155
* Matrix has form- | -(cz+sxy)/h sh (cx-syz)/h 0 |
156
* | (sz-cxy)/h ch -(sx+cyz)/h 0 |
157
* | -x -y -z 0 |
158
* | 0 0 0 1 |
159
*/
160
void gd_create_origin_lookat(Mat4f *mtx, struct GdVec3f *vec, f32 roll) {
161
f32 invertedHMag;
162
f32 hMag;
163
f32 c;
164
f32 s;
165
f32 radPerDeg = RAD_PER_DEG;
166
struct GdVec3f unit;
167
168
unit.x = vec->x;
169
unit.y = vec->y;
170
unit.z = vec->z;
171
172
gd_normalize_vec3f(&unit);
173
hMag = gd_sqrt_f(SQ(unit.x) + SQ(unit.z));
174
175
roll *= radPerDeg; // convert roll from degrees to radians
176
s = gd_sin_d(roll);
177
c = gd_cos_d(roll);
178
179
gd_set_identity_mat4(mtx);
180
if (hMag != 0.0f) {
181
invertedHMag = 1.0f / hMag;
182
(*mtx)[0][0] = ((-unit.z * c) - (s * unit.y * unit.x)) * invertedHMag;
183
(*mtx)[1][0] = ((unit.z * s) - (c * unit.y * unit.x)) * invertedHMag;
184
(*mtx)[2][0] = -unit.x;
185
(*mtx)[3][0] = 0.0f;
186
187
(*mtx)[0][1] = s * hMag;
188
(*mtx)[1][1] = c * hMag;
189
(*mtx)[2][1] = -unit.y;
190
(*mtx)[3][1] = 0.0f;
191
192
(*mtx)[0][2] = ((c * unit.x) - (s * unit.y * unit.z)) * invertedHMag;
193
(*mtx)[1][2] = ((-s * unit.x) - (c * unit.y * unit.z)) * invertedHMag;
194
(*mtx)[2][2] = -unit.z;
195
(*mtx)[3][2] = 0.0f;
196
197
(*mtx)[0][3] = 0.0f;
198
(*mtx)[1][3] = 0.0f;
199
(*mtx)[2][3] = 0.0f;
200
(*mtx)[3][3] = 1.0f;
201
} else {
202
(*mtx)[0][0] = 0.0f;
203
(*mtx)[1][0] = 1.0f;
204
(*mtx)[2][0] = 0.0f;
205
(*mtx)[3][0] = 0.0f;
206
207
(*mtx)[0][1] = 0.0f;
208
(*mtx)[1][1] = 0.0f;
209
(*mtx)[2][1] = 1.0f;
210
(*mtx)[3][1] = 0.0f;
211
212
(*mtx)[0][2] = 1.0f;
213
(*mtx)[1][2] = 0.0f;
214
(*mtx)[2][2] = 0.0f;
215
(*mtx)[3][2] = 0.0f;
216
217
(*mtx)[0][3] = 0.0f;
218
(*mtx)[1][3] = 0.0f;
219
(*mtx)[2][3] = 0.0f;
220
(*mtx)[3][3] = 1.0f;
221
}
222
}
223
224
/**
225
* Clamps a float within a set range about zero.
226
*/
227
f32 gd_clamp_f32(f32 a, f32 b) {
228
if (b < a) {
229
a = b;
230
} else if (a < -b) {
231
a = -b;
232
}
233
234
return a;
235
}
236
237
/**
238
* Clamps a vector within a set range about zero.
239
*/
240
void gd_clamp_vec3f(struct GdVec3f *vec, f32 limit) {
241
if (vec->x > limit) {
242
vec->x = limit;
243
} else if (vec->x < -limit) {
244
vec->x = -limit;
245
}
246
247
if (vec->y > limit) {
248
vec->y = limit;
249
} else if (vec->y < -limit) {
250
vec->y = -limit;
251
}
252
253
if (vec->z > limit) {
254
vec->z = limit;
255
} else if (vec->z < -limit) {
256
vec->z = -limit;
257
}
258
}
259
260
/**
261
* Rotates a 2D vector by some angle in degrees.
262
*/
263
void gd_rot_2d_vec(f32 deg, f32 *x, f32 *y) {
264
f32 xP;
265
f32 yP;
266
f32 rad;
267
268
rad = deg / DEG_PER_RAD;
269
xP = (*x * gd_cos_d(rad)) - (*y * gd_sin_d(rad));
270
yP = (*x * gd_sin_d(rad)) + (*y * gd_cos_d(rad));
271
*x = xP;
272
*y = yP;
273
}
274
275
/**
276
* Rotates a matrix about one of its rows.
277
*/
278
void UNUSED gd_rot_mat_about_row(Mat4f *mat, s32 row, f32 ang) {
279
Mat4f rot;
280
struct GdVec3f vec;
281
282
vec.x = (*mat)[row][0];
283
vec.y = (*mat)[row][1];
284
vec.z = (*mat)[row][2];
285
286
gd_create_rot_mat_angular(&rot, &vec, ang / 2.0);
287
gd_mult_mat4f(mat, &rot, mat);
288
}
289
290
/**
291
* Rotates a mat4f matrix about a given axis
292
* by a set angle in degrees.
293
*/
294
void gd_absrot_mat4(Mat4f *mtx, s32 axisnum, f32 ang) {
295
Mat4f rMat;
296
struct GdVec3f rot;
297
298
switch (axisnum) {
299
case GD_X_AXIS:
300
rot.x = 1.0f;
301
rot.y = 0.0f;
302
rot.z = 0.0f;
303
break;
304
case GD_Y_AXIS:
305
rot.x = 0.0f;
306
rot.y = 1.0f;
307
rot.z = 0.0f;
308
break;
309
case GD_Z_AXIS:
310
rot.x = 0.0f;
311
rot.y = 0.0f;
312
rot.z = 1.0f;
313
break;
314
default:
315
fatal_printf("absrot_matrix4(): Bad axis num");
316
}
317
318
gd_create_rot_mat_angular(&rMat, &rot, ang / 2.0); //? 2.0f
319
gd_mult_mat4f(mtx, &rMat, mtx);
320
}
321
322
323
f32 gd_vec3f_magnitude(struct GdVec3f *vec) {
324
return gd_sqrt_f(SQ(vec->x) + SQ(vec->y) + SQ(vec->z));
325
}
326
327
/**
328
* Normalizes a vec3f to have a length of 1.
329
*/
330
s32 gd_normalize_vec3f(struct GdVec3f *vec) {
331
f32 mag;
332
if ((mag = SQ(vec->x) + SQ(vec->y) + SQ(vec->z)) == 0.0f) {
333
return FALSE;
334
}
335
336
mag = gd_sqrt_f(mag);
337
// gd_sqrt_f rounds near 0 numbers to 0, so verify again.
338
if (mag == 0.0f) {
339
vec->x = 0.0f;
340
vec->y = 0.0f;
341
vec->z = 0.0f;
342
return FALSE;
343
}
344
345
vec->x /= mag;
346
vec->y /= mag;
347
vec->z /= mag;
348
349
return TRUE;
350
}
351
352
/**
353
* Stores the cross product of 'a' x 'b' in 'dst'.
354
*/
355
void gd_cross_vec3f(struct GdVec3f *a, struct GdVec3f *b, struct GdVec3f *dst) {
356
struct GdVec3f result;
357
358
result.x = (a->y * b->z) - (a->z * b->y);
359
result.y = (a->z * b->x) - (a->x * b->z);
360
result.z = (a->x * b->y) - (a->y * b->x);
361
362
dst->x = result.x;
363
dst->y = result.y;
364
dst->z = result.z;
365
}
366
367
/**
368
* Returns the dot product of 'a' and 'b'.
369
*/
370
f32 gd_dot_vec3f(struct GdVec3f *a, struct GdVec3f *b) {
371
return (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
372
}
373
374
/**
375
* Inverts each element of src into dst.
376
*/
377
void UNUSED gd_invert_elements_mat4f(Mat4f *src, Mat4f *dst) {
378
s32 i;
379
s32 j;
380
381
for (i = 0; i < 4; i++) {
382
for (j = 0; j < 4; j++) {
383
(*dst)[i][j] = 1.0f / (*src)[i][j];
384
}
385
}
386
}
387
388
/**
389
* Inverts a matrix from src and stores it into dst.
390
* Reaches a fatal_print if the determinant is 0.
391
*/
392
void gd_inverse_mat4f(Mat4f *src, Mat4f *dst) {
393
s32 i;
394
s32 j;
395
f32 determinant;
396
397
gd_adjunct_mat4f(src, dst);
398
determinant = gd_mat4f_det(dst);
399
400
if (ABS(determinant) < 1e-5) //? 1e-5f
401
{
402
fatal_print("Non-singular matrix, no inverse!\n");
403
}
404
405
for (i = 0; i < 4; i++) {
406
for (j = 0; j < 4; j++) {
407
(*dst)[i][j] /= determinant;
408
}
409
}
410
}
411
412
/**
413
* Takes a matrix from src and converts it into its adjunct in dst.
414
*/
415
void gd_adjunct_mat4f(Mat4f *src, Mat4f *dst) {
416
struct InvMat4 inv;
417
418
inv.r3.c3 = (*src)[0][0];
419
inv.r2.c3 = (*src)[0][1];
420
inv.r1.c3 = (*src)[0][2];
421
inv.r0.c3 = (*src)[0][3];
422
inv.r3.c2 = (*src)[1][0];
423
inv.r2.c2 = (*src)[1][1];
424
inv.r1.c2 = (*src)[1][2];
425
inv.r0.c2 = (*src)[1][3];
426
inv.r3.c1 = (*src)[2][0];
427
inv.r2.c1 = (*src)[2][1];
428
inv.r1.c1 = (*src)[2][2];
429
inv.r0.c1 = (*src)[2][3];
430
inv.r3.c0 = (*src)[3][0];
431
inv.r2.c0 = (*src)[3][1];
432
inv.r1.c0 = (*src)[3][2];
433
inv.r0.c0 = (*src)[3][3];
434
435
(*dst)[0][0] = gd_3x3_det(inv.r2.c2, inv.r2.c1, inv.r2.c0, inv.r1.c2, inv.r1.c1, inv.r1.c0,
436
inv.r0.c2, inv.r0.c1, inv.r0.c0);
437
(*dst)[1][0] = -gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, inv.r1.c2, inv.r1.c1, inv.r1.c0,
438
inv.r0.c2, inv.r0.c1, inv.r0.c0);
439
(*dst)[2][0] = gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, inv.r2.c2, inv.r2.c1, inv.r2.c0,
440
inv.r0.c2, inv.r0.c1, inv.r0.c0);
441
(*dst)[3][0] = -gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, inv.r2.c2, inv.r2.c1, inv.r2.c0,
442
inv.r1.c2, inv.r1.c1, inv.r1.c0);
443
(*dst)[0][1] = -gd_3x3_det(inv.r2.c3, inv.r2.c1, inv.r2.c0, inv.r1.c3, inv.r1.c1, inv.r1.c0,
444
inv.r0.c3, inv.r0.c1, inv.r0.c0);
445
(*dst)[1][1] = gd_3x3_det(inv.r3.c3, inv.r3.c1, inv.r3.c0, inv.r1.c3, inv.r1.c1, inv.r1.c0,
446
inv.r0.c3, inv.r0.c1, inv.r0.c0);
447
(*dst)[2][1] = -gd_3x3_det(inv.r3.c3, inv.r3.c1, inv.r3.c0, inv.r2.c3, inv.r2.c1, inv.r2.c0,
448
inv.r0.c3, inv.r0.c1, inv.r0.c0);
449
(*dst)[3][1] = gd_3x3_det(inv.r3.c3, inv.r3.c1, inv.r3.c0, inv.r2.c3, inv.r2.c1, inv.r2.c0,
450
inv.r1.c3, inv.r1.c1, inv.r1.c0);
451
(*dst)[0][2] = gd_3x3_det(inv.r2.c3, inv.r2.c2, inv.r2.c0, inv.r1.c3, inv.r1.c2, inv.r1.c0,
452
inv.r0.c3, inv.r0.c2, inv.r0.c0);
453
(*dst)[1][2] = -gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c0, inv.r1.c3, inv.r1.c2, inv.r1.c0,
454
inv.r0.c3, inv.r0.c2, inv.r0.c0);
455
(*dst)[2][2] = gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c0, inv.r2.c3, inv.r2.c2, inv.r2.c0,
456
inv.r0.c3, inv.r0.c2, inv.r0.c0);
457
(*dst)[3][2] = -gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c0, inv.r2.c3, inv.r2.c2, inv.r2.c0,
458
inv.r1.c3, inv.r1.c2, inv.r1.c0);
459
(*dst)[0][3] = -gd_3x3_det(inv.r2.c3, inv.r2.c2, inv.r2.c1, inv.r1.c3, inv.r1.c2, inv.r1.c1,
460
inv.r0.c3, inv.r0.c2, inv.r0.c1);
461
(*dst)[1][3] = gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c1, inv.r1.c3, inv.r1.c2, inv.r1.c1,
462
inv.r0.c3, inv.r0.c2, inv.r0.c1);
463
(*dst)[2][3] = -gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c1, inv.r2.c3, inv.r2.c2, inv.r2.c1,
464
inv.r0.c3, inv.r0.c2, inv.r0.c1);
465
(*dst)[3][3] = gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c1, inv.r2.c3, inv.r2.c2, inv.r2.c1,
466
inv.r1.c3, inv.r1.c2, inv.r1.c1);
467
}
468
469
/**
470
* Returns the determinant of a mat4f matrix.
471
*/
472
f32 gd_mat4f_det(Mat4f *mtx) {
473
f32 det;
474
struct InvMat4 inv;
475
476
inv.r3.c3 = (*mtx)[0][0];
477
inv.r2.c3 = (*mtx)[0][1];
478
inv.r1.c3 = (*mtx)[0][2];
479
inv.r0.c3 = (*mtx)[0][3];
480
inv.r3.c2 = (*mtx)[1][0];
481
inv.r2.c2 = (*mtx)[1][1];
482
inv.r1.c2 = (*mtx)[1][2];
483
inv.r0.c2 = (*mtx)[1][3];
484
inv.r3.c1 = (*mtx)[2][0];
485
inv.r2.c1 = (*mtx)[2][1];
486
inv.r1.c1 = (*mtx)[2][2];
487
inv.r0.c1 = (*mtx)[2][3];
488
inv.r3.c0 = (*mtx)[3][0];
489
inv.r2.c0 = (*mtx)[3][1];
490
inv.r1.c0 = (*mtx)[3][2];
491
inv.r0.c0 = (*mtx)[3][3];
492
493
det = (inv.r3.c3
494
* gd_3x3_det(inv.r2.c2, inv.r2.c1, inv.r2.c0,
495
inv.r1.c2, inv.r1.c1, inv.r1.c0,
496
inv.r0.c2, inv.r0.c1, inv.r0.c0)
497
- inv.r2.c3
498
* gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0,
499
inv.r1.c2, inv.r1.c1, inv.r1.c0,
500
inv.r0.c2, inv.r0.c1, inv.r0.c0))
501
+ inv.r1.c3
502
* gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0,
503
inv.r2.c2, inv.r2.c1, inv.r2.c0,
504
inv.r0.c2, inv.r0.c1, inv.r0.c0)
505
- inv.r0.c3
506
* gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0,
507
inv.r2.c2, inv.r2.c1, inv.r2.c0,
508
inv.r1.c2, inv.r1.c1, inv.r1.c0);
509
510
return det;
511
}
512
513
/**
514
* Takes the individual values of a 3 by 3 matrix and
515
* returns the determinant.
516
*/
517
f32 gd_3x3_det(f32 r0c0, f32 r0c1, f32 r0c2,
518
f32 r1c0, f32 r1c1, f32 r1c2,
519
f32 r2c0, f32 r2c1, f32 r2c2) {
520
f32 det;
521
522
det = r0c0 * gd_2x2_det(r1c1, r1c2, r2c1, r2c2) - r1c0 * gd_2x2_det(r0c1, r0c2, r2c1, r2c2)
523
+ r2c0 * gd_2x2_det(r0c1, r0c2, r1c1, r1c2);
524
525
return det;
526
}
527
528
/**
529
* Takes the individual values of a 2 by 2 matrix and
530
* returns the determinant.
531
*/
532
f32 gd_2x2_det(f32 a, f32 b, f32 c, f32 d) {
533
f32 det = a * d - b * c;
534
535
return det;
536
}
537
538
/**
539
* Creates a vector negative to what was passed in. Also sets the first row of a mat4f
540
* to 1 0 0 0. Perhaps meant to be used at the end of gd_create_quat_rot_mat? Not
541
* sure of the purpose of the vector portion, though.
542
*/
543
void UNUSED gd_create_neg_vec_zero_first_mat_row(Mat4f *mtx, struct GdVec3f *vec, f32 x, f32 y, f32 z) {
544
s32 i;
545
546
vec->x = -x;
547
vec->y = -y;
548
vec->z = -z;
549
550
(*mtx)[0][0] = 1.0f;
551
552
for (i = 1; i < 4; i++) {
553
(*mtx)[0][i] = 0.0f;
554
}
555
}
556
557
/**
558
* This function quite literally does nothing.
559
* Seems to have been meant to create a vector from a quaternion?
560
*/
561
void UNUSED gd_broken_quat_to_vec3f(f32 quat[4], struct GdVec3f *vec, f32 zHalf, s32 i, s32 run) {
562
s32 j;
563
s32 k;
564
UNUSED f32 jVal;
565
UNUSED f32 kVal;
566
UNUSED struct GdVec3f uVec;
567
struct GdVec3f tVec;
568
569
tVec.x = vec->x;
570
tVec.y = vec->y;
571
tVec.z = vec->z;
572
573
if (run < 0) {
574
goto end;
575
}
576
577
if ((j = i + 1) >= 4) {
578
j = 1;
579
}
580
581
if ((k = j + 1) >= 4) {
582
k = 1;
583
}
584
585
jVal = quat[j];
586
kVal = quat[k];
587
uVec.x = quat[0];
588
uVec.y = quat[i];
589
uVec.z = zHalf + zHalf;
590
591
end:
592
vec->x = tVec.x;
593
vec->y = tVec.y;
594
vec->z = tVec.z;
595
}
596
597
/**
598
* This function is a pitch rotation of a quaternion, with the sign allowing both regular
599
* and inverse multiplication.
600
*/
601
void UNUSED gd_quat_rotation(f32 quat[4], UNUSED s32 unused, f32 c, f32 s, s32 i, s32 sign) {
602
s32 j;
603
s32 k;
604
f32 quatVal;
605
UNUSED u32 pad[2];
606
607
if ((j = i + 1) >= 4) {
608
j = 1;
609
}
610
if ((k = j + 1) >= 4) {
611
k = 1;
612
}
613
614
quatVal = quat[i];
615
quat[i] = sign * s * quat[0] + quatVal * c;
616
quat[0] = quat[0] * c - sign * s * quatVal;
617
618
quatVal = quat[j];
619
quat[j] = quat[k] * s + quatVal * c;
620
quat[k] = quat[k] * c - s * quatVal;
621
}
622
623
/**
624
* Shifts a matrix up by one row, putting the top row on bottom.
625
*/
626
void gd_shift_mat_up(Mat4f *mtx) {
627
s32 i;
628
s32 j;
629
f32 temp[3];
630
631
for (i = 0; i < 3; i++) {
632
temp[i] = (*mtx)[0][i + 1];
633
}
634
for (i = 1; i < 4; i++) {
635
for (j = 1; j < 4; j++) {
636
(*mtx)[i - 1][j - 1] = (*mtx)[i][j];
637
}
638
}
639
640
(*mtx)[0][3] = 0.0f;
641
(*mtx)[1][3] = 0.0f;
642
(*mtx)[2][3] = 0.0f;
643
(*mtx)[3][3] = 1.0f;
644
645
for (i = 0; i < 3; i++) {
646
(*mtx)[3][i] = temp[i];
647
}
648
}
649
650
/**
651
* Creates a rotation matrix from a quaternion.
652
*
653
* Has form-
654
* | 1 - - - |
655
* | 0 w^2+i^2-j^2-k^2 2ij+2wk 2ik+2wj |
656
* | 0 2ij-2wk w^2+j^2-i^2-k^2 2jk+2wi |
657
* | 0 2ik+2wj 2jk-2wi w^2+k^2-i^2-j^2 |
658
*
659
* Potentially broken if 'mtx' is not an identity matrix/zero'ed.
660
*/
661
void UNUSED gd_create_quat_rot_mat(f32 quat[4], UNUSED s32 unused, Mat4f *mtx) {
662
f32 twoIJ;
663
f32 two0K;
664
f32 sqQuat[4];
665
s32 i;
666
s32 j;
667
s32 k;
668
669
for (i = 0; i < 4; i++) {
670
sqQuat[i] = SQ(quat[i]);
671
}
672
673
for (i = 1; i < 4; i++) {
674
if ((j = i + 1) >= 4) {
675
j = 1;
676
}
677
678
if ((k = j + 1) >= 4) {
679
k = 1;
680
}
681
682
twoIJ = 2.0 * quat[i] * quat[j];
683
two0K = 2.0 * quat[k] * quat[0];
684
685
(*mtx)[j][i] = twoIJ - two0K;
686
(*mtx)[i][j] = twoIJ + two0K;
687
(*mtx)[i][i] = sqQuat[i] + sqQuat[0] - sqQuat[j] - sqQuat[k];
688
(*mtx)[i][0] = 0.0f;
689
}
690
691
//! The first row only ever has the first value set to 1, but the
692
//! latter portions remain what they were originally. Perhaps this was meant
693
//! to call gd_create_neg_vec_zero_first_mat_row?
694
(*mtx)[0][0] = 1.0f;
695
gd_shift_mat_up(mtx);
696
}
697
698
/**
699
* Creates a rotation matrix to multiply the primary matrix by.
700
* s/c are sin(angle)/cos(angle). That angular rotation is about vector
701
* 'vec'.
702
*
703
* Matrix has form-
704
*
705
* | (1-c)z^2+c (1-c)zy-sx (1-c)xz-sy 0 |
706
* | (1-c)zy-sx (1-c)y^2+c (1-c)xy-sz 0 |
707
* | (1-c)xz-sy (1-c)xy-sz (1-c)x^2+c 0 |
708
* | 0 0 0 1 |
709
*/
710
void gd_create_rot_matrix(Mat4f *mtx, struct GdVec3f *vec, f32 s, f32 c) {
711
f32 oneMinusCos;
712
struct GdVec3f rev;
713
714
rev.z = vec->x;
715
rev.y = vec->y;
716
rev.x = vec->z;
717
718
oneMinusCos = 1.0 - c;
719
720
(*mtx)[0][0] = oneMinusCos * rev.z * rev.z + c;
721
(*mtx)[0][1] = oneMinusCos * rev.z * rev.y + s * rev.x;
722
(*mtx)[0][2] = oneMinusCos * rev.z * rev.x - s * rev.y;
723
(*mtx)[0][3] = 0.0f;
724
725
(*mtx)[1][0] = oneMinusCos * rev.z * rev.y - s * rev.x;
726
(*mtx)[1][1] = oneMinusCos * rev.y * rev.y + c;
727
(*mtx)[1][2] = oneMinusCos * rev.y * rev.x + s * rev.z;
728
(*mtx)[1][3] = 0.0f;
729
730
(*mtx)[2][0] = oneMinusCos * rev.z * rev.x + s * rev.y;
731
(*mtx)[2][1] = oneMinusCos * rev.y * rev.x - s * rev.z;
732
(*mtx)[2][2] = oneMinusCos * rev.x * rev.x + c;
733
(*mtx)[2][3] = 0.0f;
734
735
(*mtx)[3][0] = 0.0f;
736
(*mtx)[3][1] = 0.0f;
737
(*mtx)[3][2] = 0.0f;
738
(*mtx)[3][3] = 1.0f;
739
}
740
741
/**
742
* Creates a rotation matrix about vector 'vec' with ang in degrees.
743
*/
744
void gd_create_rot_mat_angular(Mat4f *mtx, struct GdVec3f *vec, f32 ang) {
745
f32 s;
746
f32 c;
747
748
s = gd_sin_d(ang / (DEG_PER_RAD / 2.0));
749
c = gd_cos_d(ang / (DEG_PER_RAD / 2.0));
750
751
gd_create_rot_matrix(mtx, vec, s, c);
752
}
753
754
/**
755
* Sets a mat4f matrix to an identity matrix.
756
*/
757
void gd_set_identity_mat4(Mat4f *mtx) {
758
(*mtx)[0][0] = 1.0f;
759
(*mtx)[0][1] = 0.0f;
760
(*mtx)[0][2] = 0.0f;
761
(*mtx)[0][3] = 0.0f;
762
(*mtx)[1][0] = 0.0f;
763
(*mtx)[1][1] = 1.0f;
764
(*mtx)[1][2] = 0.0f;
765
(*mtx)[1][3] = 0.0f;
766
(*mtx)[2][0] = 0.0f;
767
(*mtx)[2][1] = 0.0f;
768
(*mtx)[2][2] = 1.0f;
769
(*mtx)[2][3] = 0.0f;
770
(*mtx)[3][0] = 0.0f;
771
(*mtx)[3][1] = 0.0f;
772
(*mtx)[3][2] = 0.0f;
773
(*mtx)[3][3] = 1.0f;
774
}
775
776
/**
777
* Copies a mat4f from src to dst.
778
*/
779
void gd_copy_mat4f(const Mat4f *src, Mat4f *dst) {
780
(*dst)[0][0] = (*src)[0][0];
781
(*dst)[0][1] = (*src)[0][1];
782
(*dst)[0][2] = (*src)[0][2];
783
(*dst)[0][3] = (*src)[0][3];
784
(*dst)[1][0] = (*src)[1][0];
785
(*dst)[1][1] = (*src)[1][1];
786
(*dst)[1][2] = (*src)[1][2];
787
(*dst)[1][3] = (*src)[1][3];
788
(*dst)[2][0] = (*src)[2][0];
789
(*dst)[2][1] = (*src)[2][1];
790
(*dst)[2][2] = (*src)[2][2];
791
(*dst)[2][3] = (*src)[2][3];
792
(*dst)[3][0] = (*src)[3][0];
793
(*dst)[3][1] = (*src)[3][1];
794
(*dst)[3][2] = (*src)[3][2];
795
(*dst)[3][3] = (*src)[3][3];
796
}
797
798
/**
799
* Transforms a vec3f, rotating with the main 3x3 portion of the mat4f
800
* and translating with the 4th column.
801
*/
802
void gd_rotate_and_translate_vec3f(struct GdVec3f *vec, const Mat4f *mtx) {
803
struct GdVec3f out;
804
805
out.x = (*mtx)[0][0] * vec->x + (*mtx)[1][0] * vec->y + (*mtx)[2][0] * vec->z;
806
out.y = (*mtx)[0][1] * vec->x + (*mtx)[1][1] * vec->y + (*mtx)[2][1] * vec->z;
807
out.z = (*mtx)[0][2] * vec->x + (*mtx)[1][2] * vec->y + (*mtx)[2][2] * vec->z;
808
out.x += (*mtx)[3][0];
809
out.y += (*mtx)[3][1];
810
out.z += (*mtx)[3][2];
811
812
vec->x = out.x;
813
vec->y = out.y;
814
vec->z = out.z;
815
}
816
817
/**
818
* Multiples a vec3f by the main 3x3 portion of a mat4f matrix.
819
*/
820
void gd_mat4f_mult_vec3f(struct GdVec3f *vec, const Mat4f *mtx) {
821
struct GdVec3f out;
822
823
out.x = (*mtx)[0][0] * vec->x + (*mtx)[1][0] * vec->y + (*mtx)[2][0] * vec->z;
824
out.y = (*mtx)[0][1] * vec->x + (*mtx)[1][1] * vec->y + (*mtx)[2][1] * vec->z;
825
out.z = (*mtx)[0][2] * vec->x + (*mtx)[1][2] * vec->y + (*mtx)[2][2] * vec->z;
826
827
vec->x = out.x;
828
vec->y = out.y;
829
vec->z = out.z;
830
}
831
832
#define MAT4_DOT_PROD(A, B, R, row, col) \
833
{ \
834
(R)[(row)][(col)] = (A)[(row)][0] * (B)[0][(col)]; \
835
(R)[(row)][(col)] += (A)[(row)][1] * (B)[1][(col)]; \
836
(R)[(row)][(col)] += (A)[(row)][2] * (B)[2][(col)]; \
837
(R)[(row)][(col)] += (A)[(row)][3] * (B)[3][(col)]; \
838
}
839
840
#define MAT4_MULTIPLY(A, B, R) \
841
{ \
842
MAT4_DOT_PROD((A), (B), (R), 0, 0); \
843
MAT4_DOT_PROD((A), (B), (R), 0, 1); \
844
MAT4_DOT_PROD((A), (B), (R), 0, 2); \
845
MAT4_DOT_PROD((A), (B), (R), 0, 3); \
846
MAT4_DOT_PROD((A), (B), (R), 1, 0); \
847
MAT4_DOT_PROD((A), (B), (R), 1, 1); \
848
MAT4_DOT_PROD((A), (B), (R), 1, 2); \
849
MAT4_DOT_PROD((A), (B), (R), 1, 3); \
850
MAT4_DOT_PROD((A), (B), (R), 2, 0); \
851
MAT4_DOT_PROD((A), (B), (R), 2, 1); \
852
MAT4_DOT_PROD((A), (B), (R), 2, 2); \
853
MAT4_DOT_PROD((A), (B), (R), 2, 3); \
854
MAT4_DOT_PROD((A), (B), (R), 3, 0); \
855
MAT4_DOT_PROD((A), (B), (R), 3, 1); \
856
MAT4_DOT_PROD((A), (B), (R), 3, 2); \
857
MAT4_DOT_PROD((A), (B), (R), 3, 3); \
858
}
859
860
/**
861
* Multiplies two Mat4f matrices and puts it in dst.
862
*/
863
void gd_mult_mat4f(const Mat4f *mA, const Mat4f *mB, Mat4f *dst) {
864
Mat4f res;
865
866
MAT4_MULTIPLY((*mA), (*mB), res);
867
gd_copy_mat4f(&res, dst);
868
}
869
870
#undef MAT4_MULTIPLY
871
#undef MAT4_DOT_PROD
872
873
/**
874
* Prints a vec3f vector.
875
*
876
* Printed the prefix at some point, as shown by how the function is used.
877
*/
878
void gd_print_vec(UNUSED const char *prefix, const struct GdVec3f *vec) {
879
UNUSED u8 pad[8];
880
881
printf("%f,%f,%f\n", vec->x, vec->y, vec->z);
882
printf("\n");
883
}
884
885
/**
886
* Prints a plane's boundaries.
887
*
888
* Printed a prefix at some point, as shone by how the function is used.
889
*/
890
void gd_print_bounding_box(UNUSED const char *prefix, UNUSED const struct GdBoundingBox *p) {
891
UNUSED u8 pad[8];
892
893
printf("Min X = %f, Max X = %f \n", p->minX, p->maxX);
894
printf("Min Y = %f, Max Y = %f \n", p->minY, p->maxY);
895
printf("Min Z = %f, Max Z = %f \n", p->minZ, p->maxZ);
896
printf("\n");
897
}
898
899
/**
900
* Prints a Mat4f.
901
*
902
* Although the prefix input is unused, the one usage of this function
903
* does have a "Matrix:" prefix, so it was definitely used at one point.
904
*/
905
void gd_print_mtx(UNUSED const char *prefix, const Mat4f *mtx) {
906
s32 i;
907
s32 j;
908
909
for (i = 0; i < 4; i++) {
910
for (j = 0; j < 4; j++) {
911
gd_printf("%f ", (*mtx)[i][j]);
912
}
913
gd_printf("\n");
914
}
915
}
916
917
/**
918
* Prints a quaternion along with a prefix.
919
*/
920
void UNUSED gd_print_quat(const char *prefix, const f32 f[4]) {
921
s32 i;
922
923
gd_printf(prefix);
924
for (i = 0; i < 4; i++) {
925
gd_printf("%f ", f[i]);
926
}
927
gd_printf("\n");
928
}
929
930
/**
931
* Rotates a matrix or creates a rotation matrix about a vector made from an offset
932
* of 100 and the passed in x, y, and z values.
933
*/
934
void UNUSED gd_rot_mat_offset(Mat4f *dst, f32 x, f32 y, f32 z, s32 copy) {
935
f32 adj = 100.0f;
936
Mat4f rot;
937
f32 c;
938
f32 s;
939
f32 opp;
940
f32 mag;
941
struct GdVec3f vec;
942
943
opp = gd_sqrt_f(SQ(x) + SQ(y) + SQ(z));
944
945
if (opp == 0.0f) {
946
if (copy) {
947
gd_set_identity_mat4(dst);
948
}
949
return;
950
}
951
952
mag = gd_sqrt_f(SQ(adj) + SQ(opp));
953
c = adj / mag;
954
s = opp / mag;
955
956
vec.x = -y / opp;
957
vec.y = -x / opp;
958
vec.z = -z / opp;
959
960
gd_create_rot_matrix(&rot, &vec, s, c);
961
if (!copy) {
962
gd_mult_mat4f(dst, &rot, dst);
963
} else {
964
gd_copy_mat4f(&rot, dst);
965
}
966
}
967
968