gd_math.c (27455B)
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 fatal_print("Non-singular matrix, no inverse!\n"); 402 } 403 404 for (i = 0; i < 4; i++) { 405 for (j = 0; j < 4; j++) { 406 (*dst)[i][j] /= determinant; 407 } 408 } 409 } 410 411 /** 412 * Takes a matrix from src and converts it into its adjunct in dst. 413 */ 414 void gd_adjunct_mat4f(Mat4f *src, Mat4f *dst) { 415 struct InvMat4 inv; 416 417 inv.r3.c3 = (*src)[0][0]; 418 inv.r2.c3 = (*src)[0][1]; 419 inv.r1.c3 = (*src)[0][2]; 420 inv.r0.c3 = (*src)[0][3]; 421 inv.r3.c2 = (*src)[1][0]; 422 inv.r2.c2 = (*src)[1][1]; 423 inv.r1.c2 = (*src)[1][2]; 424 inv.r0.c2 = (*src)[1][3]; 425 inv.r3.c1 = (*src)[2][0]; 426 inv.r2.c1 = (*src)[2][1]; 427 inv.r1.c1 = (*src)[2][2]; 428 inv.r0.c1 = (*src)[2][3]; 429 inv.r3.c0 = (*src)[3][0]; 430 inv.r2.c0 = (*src)[3][1]; 431 inv.r1.c0 = (*src)[3][2]; 432 inv.r0.c0 = (*src)[3][3]; 433 434 (*dst)[0][0] = gd_3x3_det(inv.r2.c2, inv.r2.c1, inv.r2.c0, inv.r1.c2, inv.r1.c1, inv.r1.c0, 435 inv.r0.c2, inv.r0.c1, inv.r0.c0); 436 (*dst)[1][0] = -gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, inv.r1.c2, inv.r1.c1, inv.r1.c0, 437 inv.r0.c2, inv.r0.c1, inv.r0.c0); 438 (*dst)[2][0] = gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, inv.r2.c2, inv.r2.c1, inv.r2.c0, 439 inv.r0.c2, inv.r0.c1, inv.r0.c0); 440 (*dst)[3][0] = -gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, inv.r2.c2, inv.r2.c1, inv.r2.c0, 441 inv.r1.c2, inv.r1.c1, inv.r1.c0); 442 (*dst)[0][1] = -gd_3x3_det(inv.r2.c3, inv.r2.c1, inv.r2.c0, inv.r1.c3, inv.r1.c1, inv.r1.c0, 443 inv.r0.c3, inv.r0.c1, inv.r0.c0); 444 (*dst)[1][1] = gd_3x3_det(inv.r3.c3, inv.r3.c1, inv.r3.c0, inv.r1.c3, inv.r1.c1, inv.r1.c0, 445 inv.r0.c3, inv.r0.c1, inv.r0.c0); 446 (*dst)[2][1] = -gd_3x3_det(inv.r3.c3, inv.r3.c1, inv.r3.c0, inv.r2.c3, inv.r2.c1, inv.r2.c0, 447 inv.r0.c3, inv.r0.c1, inv.r0.c0); 448 (*dst)[3][1] = gd_3x3_det(inv.r3.c3, inv.r3.c1, inv.r3.c0, inv.r2.c3, inv.r2.c1, inv.r2.c0, 449 inv.r1.c3, inv.r1.c1, inv.r1.c0); 450 (*dst)[0][2] = gd_3x3_det(inv.r2.c3, inv.r2.c2, inv.r2.c0, inv.r1.c3, inv.r1.c2, inv.r1.c0, 451 inv.r0.c3, inv.r0.c2, inv.r0.c0); 452 (*dst)[1][2] = -gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c0, inv.r1.c3, inv.r1.c2, inv.r1.c0, 453 inv.r0.c3, inv.r0.c2, inv.r0.c0); 454 (*dst)[2][2] = gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c0, inv.r2.c3, inv.r2.c2, inv.r2.c0, 455 inv.r0.c3, inv.r0.c2, inv.r0.c0); 456 (*dst)[3][2] = -gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c0, inv.r2.c3, inv.r2.c2, inv.r2.c0, 457 inv.r1.c3, inv.r1.c2, inv.r1.c0); 458 (*dst)[0][3] = -gd_3x3_det(inv.r2.c3, inv.r2.c2, inv.r2.c1, inv.r1.c3, inv.r1.c2, inv.r1.c1, 459 inv.r0.c3, inv.r0.c2, inv.r0.c1); 460 (*dst)[1][3] = gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c1, inv.r1.c3, inv.r1.c2, inv.r1.c1, 461 inv.r0.c3, inv.r0.c2, inv.r0.c1); 462 (*dst)[2][3] = -gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c1, inv.r2.c3, inv.r2.c2, inv.r2.c1, 463 inv.r0.c3, inv.r0.c2, inv.r0.c1); 464 (*dst)[3][3] = gd_3x3_det(inv.r3.c3, inv.r3.c2, inv.r3.c1, inv.r2.c3, inv.r2.c2, inv.r2.c1, 465 inv.r1.c3, inv.r1.c2, inv.r1.c1); 466 } 467 468 /** 469 * Returns the determinant of a mat4f matrix. 470 */ 471 f32 gd_mat4f_det(Mat4f *mtx) { 472 f32 det; 473 struct InvMat4 inv; 474 475 inv.r3.c3 = (*mtx)[0][0]; 476 inv.r2.c3 = (*mtx)[0][1]; 477 inv.r1.c3 = (*mtx)[0][2]; 478 inv.r0.c3 = (*mtx)[0][3]; 479 inv.r3.c2 = (*mtx)[1][0]; 480 inv.r2.c2 = (*mtx)[1][1]; 481 inv.r1.c2 = (*mtx)[1][2]; 482 inv.r0.c2 = (*mtx)[1][3]; 483 inv.r3.c1 = (*mtx)[2][0]; 484 inv.r2.c1 = (*mtx)[2][1]; 485 inv.r1.c1 = (*mtx)[2][2]; 486 inv.r0.c1 = (*mtx)[2][3]; 487 inv.r3.c0 = (*mtx)[3][0]; 488 inv.r2.c0 = (*mtx)[3][1]; 489 inv.r1.c0 = (*mtx)[3][2]; 490 inv.r0.c0 = (*mtx)[3][3]; 491 492 det = (inv.r3.c3 493 * gd_3x3_det(inv.r2.c2, inv.r2.c1, inv.r2.c0, 494 inv.r1.c2, inv.r1.c1, inv.r1.c0, 495 inv.r0.c2, inv.r0.c1, inv.r0.c0) 496 - inv.r2.c3 497 * gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, 498 inv.r1.c2, inv.r1.c1, inv.r1.c0, 499 inv.r0.c2, inv.r0.c1, inv.r0.c0)) 500 + inv.r1.c3 501 * gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, 502 inv.r2.c2, inv.r2.c1, inv.r2.c0, 503 inv.r0.c2, inv.r0.c1, inv.r0.c0) 504 - inv.r0.c3 505 * gd_3x3_det(inv.r3.c2, inv.r3.c1, inv.r3.c0, 506 inv.r2.c2, inv.r2.c1, inv.r2.c0, 507 inv.r1.c2, inv.r1.c1, inv.r1.c0); 508 509 return det; 510 } 511 512 /** 513 * Takes the individual values of a 3 by 3 matrix and 514 * returns the determinant. 515 */ 516 f32 gd_3x3_det(f32 r0c0, f32 r0c1, f32 r0c2, 517 f32 r1c0, f32 r1c1, f32 r1c2, 518 f32 r2c0, f32 r2c1, f32 r2c2) { 519 f32 det; 520 521 det = r0c0 * gd_2x2_det(r1c1, r1c2, r2c1, r2c2) - r1c0 * gd_2x2_det(r0c1, r0c2, r2c1, r2c2) 522 + r2c0 * gd_2x2_det(r0c1, r0c2, r1c1, r1c2); 523 524 return det; 525 } 526 527 /** 528 * Takes the individual values of a 2 by 2 matrix and 529 * returns the determinant. 530 */ 531 f32 gd_2x2_det(f32 a, f32 b, f32 c, f32 d) { 532 f32 det = a * d - b * c; 533 534 return det; 535 } 536 537 /** 538 * Creates a vector negative to what was passed in. Also sets the first row of a mat4f 539 * to 1 0 0 0. Perhaps meant to be used at the end of gd_create_quat_rot_mat? Not 540 * sure of the purpose of the vector portion, though. 541 */ 542 void UNUSED gd_create_neg_vec_zero_first_mat_row(Mat4f *mtx, struct GdVec3f *vec, f32 x, f32 y, f32 z) { 543 s32 i; 544 545 vec->x = -x; 546 vec->y = -y; 547 vec->z = -z; 548 549 (*mtx)[0][0] = 1.0f; 550 551 for (i = 1; i < 4; i++) { 552 (*mtx)[0][i] = 0.0f; 553 } 554 } 555 556 /** 557 * This function quite literally does nothing. 558 * Seems to have been meant to create a vector from a quaternion? 559 */ 560 void UNUSED gd_broken_quat_to_vec3f(f32 quat[4], struct GdVec3f *vec, f32 zHalf, s32 i, s32 run) { 561 s32 j; 562 s32 k; 563 UNUSED f32 jVal; 564 UNUSED f32 kVal; 565 UNUSED struct GdVec3f uVec; 566 struct GdVec3f tVec; 567 568 tVec.x = vec->x; 569 tVec.y = vec->y; 570 tVec.z = vec->z; 571 572 if (run < 0) { 573 goto end; 574 } 575 576 if ((j = i + 1) >= 4) { 577 j = 1; 578 } 579 580 if ((k = j + 1) >= 4) { 581 k = 1; 582 } 583 584 jVal = quat[j]; 585 kVal = quat[k]; 586 uVec.x = quat[0]; 587 uVec.y = quat[i]; 588 uVec.z = zHalf + zHalf; 589 590 end: 591 vec->x = tVec.x; 592 vec->y = tVec.y; 593 vec->z = tVec.z; 594 } 595 596 /** 597 * This function is a pitch rotation of a quaternion, with the sign allowing both regular 598 * and inverse multiplication. 599 */ 600 void UNUSED gd_quat_rotation(f32 quat[4], UNUSED s32 unused, f32 c, f32 s, s32 i, s32 sign) { 601 s32 j; 602 s32 k; 603 f32 quatVal; 604 UNUSED u8 filler[8]; 605 606 if ((j = i + 1) >= 4) { 607 j = 1; 608 } 609 if ((k = j + 1) >= 4) { 610 k = 1; 611 } 612 613 quatVal = quat[i]; 614 quat[i] = sign * s * quat[0] + quatVal * c; 615 quat[0] = quat[0] * c - sign * s * quatVal; 616 617 quatVal = quat[j]; 618 quat[j] = quat[k] * s + quatVal * c; 619 quat[k] = quat[k] * c - s * quatVal; 620 } 621 622 /** 623 * Shifts a matrix up by one row, putting the top row on bottom. 624 */ 625 void gd_shift_mat_up(Mat4f *mtx) { 626 s32 i; 627 s32 j; 628 f32 temp[3]; 629 630 for (i = 0; i < 3; i++) { 631 temp[i] = (*mtx)[0][i + 1]; 632 } 633 for (i = 1; i < 4; i++) { 634 for (j = 1; j < 4; j++) { 635 (*mtx)[i - 1][j - 1] = (*mtx)[i][j]; 636 } 637 } 638 639 (*mtx)[0][3] = 0.0f; 640 (*mtx)[1][3] = 0.0f; 641 (*mtx)[2][3] = 0.0f; 642 (*mtx)[3][3] = 1.0f; 643 644 for (i = 0; i < 3; i++) { 645 (*mtx)[3][i] = temp[i]; 646 } 647 } 648 649 /** 650 * Creates a rotation matrix from a quaternion. 651 * 652 * Has form- 653 * | 1 - - - | 654 * | 0 w^2+i^2-j^2-k^2 2ij+2wk 2ik+2wj | 655 * | 0 2ij-2wk w^2+j^2-i^2-k^2 2jk+2wi | 656 * | 0 2ik+2wj 2jk-2wi w^2+k^2-i^2-j^2 | 657 * 658 * Potentially broken if 'mtx' is not an identity matrix/zero'ed. 659 */ 660 void UNUSED gd_create_quat_rot_mat(f32 quat[4], UNUSED s32 unused, Mat4f *mtx) { 661 f32 twoIJ; 662 f32 two0K; 663 f32 sqQuat[4]; 664 s32 i; 665 s32 j; 666 s32 k; 667 668 for (i = 0; i < 4; i++) { 669 sqQuat[i] = SQ(quat[i]); 670 } 671 672 for (i = 1; i < 4; i++) { 673 if ((j = i + 1) >= 4) { 674 j = 1; 675 } 676 677 if ((k = j + 1) >= 4) { 678 k = 1; 679 } 680 681 twoIJ = 2.0 * quat[i] * quat[j]; 682 two0K = 2.0 * quat[k] * quat[0]; 683 684 (*mtx)[j][i] = twoIJ - two0K; 685 (*mtx)[i][j] = twoIJ + two0K; 686 (*mtx)[i][i] = sqQuat[i] + sqQuat[0] - sqQuat[j] - sqQuat[k]; 687 (*mtx)[i][0] = 0.0f; 688 } 689 690 //! The first row only ever has the first value set to 1, but the 691 //! latter portions remain what they were originally. Perhaps this was meant 692 //! to call gd_create_neg_vec_zero_first_mat_row? 693 (*mtx)[0][0] = 1.0f; 694 gd_shift_mat_up(mtx); 695 } 696 697 /** 698 * Creates a rotation matrix to multiply the primary matrix by. 699 * s/c are sin(angle)/cos(angle). That angular rotation is about vector 700 * 'vec'. 701 * 702 * Matrix has form- 703 * 704 * | (1-c)z^2+c (1-c)zy-sx (1-c)xz-sy 0 | 705 * | (1-c)zy-sx (1-c)y^2+c (1-c)xy-sz 0 | 706 * | (1-c)xz-sy (1-c)xy-sz (1-c)x^2+c 0 | 707 * | 0 0 0 1 | 708 */ 709 void gd_create_rot_matrix(Mat4f *mtx, struct GdVec3f *vec, f32 s, f32 c) { 710 f32 oneMinusCos; 711 struct GdVec3f rev; 712 713 rev.z = vec->x; 714 rev.y = vec->y; 715 rev.x = vec->z; 716 717 oneMinusCos = 1.0 - c; 718 719 (*mtx)[0][0] = oneMinusCos * rev.z * rev.z + c; 720 (*mtx)[0][1] = oneMinusCos * rev.z * rev.y + s * rev.x; 721 (*mtx)[0][2] = oneMinusCos * rev.z * rev.x - s * rev.y; 722 (*mtx)[0][3] = 0.0f; 723 724 (*mtx)[1][0] = oneMinusCos * rev.z * rev.y - s * rev.x; 725 (*mtx)[1][1] = oneMinusCos * rev.y * rev.y + c; 726 (*mtx)[1][2] = oneMinusCos * rev.y * rev.x + s * rev.z; 727 (*mtx)[1][3] = 0.0f; 728 729 (*mtx)[2][0] = oneMinusCos * rev.z * rev.x + s * rev.y; 730 (*mtx)[2][1] = oneMinusCos * rev.y * rev.x - s * rev.z; 731 (*mtx)[2][2] = oneMinusCos * rev.x * rev.x + c; 732 (*mtx)[2][3] = 0.0f; 733 734 (*mtx)[3][0] = 0.0f; 735 (*mtx)[3][1] = 0.0f; 736 (*mtx)[3][2] = 0.0f; 737 (*mtx)[3][3] = 1.0f; 738 } 739 740 /** 741 * Creates a rotation matrix about vector 'vec' with ang in degrees. 742 */ 743 void gd_create_rot_mat_angular(Mat4f *mtx, struct GdVec3f *vec, f32 ang) { 744 f32 s; 745 f32 c; 746 747 s = gd_sin_d(ang / (DEG_PER_RAD / 2.0)); 748 c = gd_cos_d(ang / (DEG_PER_RAD / 2.0)); 749 750 gd_create_rot_matrix(mtx, vec, s, c); 751 } 752 753 /** 754 * Sets a mat4f matrix to an identity matrix. 755 */ 756 void gd_set_identity_mat4(Mat4f *mtx) { 757 (*mtx)[0][0] = 1.0f; 758 (*mtx)[0][1] = 0.0f; 759 (*mtx)[0][2] = 0.0f; 760 (*mtx)[0][3] = 0.0f; 761 (*mtx)[1][0] = 0.0f; 762 (*mtx)[1][1] = 1.0f; 763 (*mtx)[1][2] = 0.0f; 764 (*mtx)[1][3] = 0.0f; 765 (*mtx)[2][0] = 0.0f; 766 (*mtx)[2][1] = 0.0f; 767 (*mtx)[2][2] = 1.0f; 768 (*mtx)[2][3] = 0.0f; 769 (*mtx)[3][0] = 0.0f; 770 (*mtx)[3][1] = 0.0f; 771 (*mtx)[3][2] = 0.0f; 772 (*mtx)[3][3] = 1.0f; 773 } 774 775 /** 776 * Copies a mat4f from src to dst. 777 */ 778 void gd_copy_mat4f(const Mat4f *src, Mat4f *dst) { 779 (*dst)[0][0] = (*src)[0][0]; 780 (*dst)[0][1] = (*src)[0][1]; 781 (*dst)[0][2] = (*src)[0][2]; 782 (*dst)[0][3] = (*src)[0][3]; 783 (*dst)[1][0] = (*src)[1][0]; 784 (*dst)[1][1] = (*src)[1][1]; 785 (*dst)[1][2] = (*src)[1][2]; 786 (*dst)[1][3] = (*src)[1][3]; 787 (*dst)[2][0] = (*src)[2][0]; 788 (*dst)[2][1] = (*src)[2][1]; 789 (*dst)[2][2] = (*src)[2][2]; 790 (*dst)[2][3] = (*src)[2][3]; 791 (*dst)[3][0] = (*src)[3][0]; 792 (*dst)[3][1] = (*src)[3][1]; 793 (*dst)[3][2] = (*src)[3][2]; 794 (*dst)[3][3] = (*src)[3][3]; 795 } 796 797 /** 798 * Transforms a vec3f, rotating with the main 3x3 portion of the mat4f 799 * and translating with the 4th column. 800 */ 801 void gd_rotate_and_translate_vec3f(struct GdVec3f *vec, const Mat4f *mtx) { 802 struct GdVec3f out; 803 804 out.x = (*mtx)[0][0] * vec->x + (*mtx)[1][0] * vec->y + (*mtx)[2][0] * vec->z; 805 out.y = (*mtx)[0][1] * vec->x + (*mtx)[1][1] * vec->y + (*mtx)[2][1] * vec->z; 806 out.z = (*mtx)[0][2] * vec->x + (*mtx)[1][2] * vec->y + (*mtx)[2][2] * vec->z; 807 out.x += (*mtx)[3][0]; 808 out.y += (*mtx)[3][1]; 809 out.z += (*mtx)[3][2]; 810 811 vec->x = out.x; 812 vec->y = out.y; 813 vec->z = out.z; 814 } 815 816 /** 817 * Multiples a vec3f by the main 3x3 portion of a mat4f matrix. 818 */ 819 void gd_mat4f_mult_vec3f(struct GdVec3f *vec, const Mat4f *mtx) { 820 struct GdVec3f out; 821 822 out.x = (*mtx)[0][0] * vec->x + (*mtx)[1][0] * vec->y + (*mtx)[2][0] * vec->z; 823 out.y = (*mtx)[0][1] * vec->x + (*mtx)[1][1] * vec->y + (*mtx)[2][1] * vec->z; 824 out.z = (*mtx)[0][2] * vec->x + (*mtx)[1][2] * vec->y + (*mtx)[2][2] * vec->z; 825 826 vec->x = out.x; 827 vec->y = out.y; 828 vec->z = out.z; 829 } 830 831 #define MAT4_DOT_PROD(A, B, R, row, col) \ 832 { \ 833 (R)[(row)][(col)] = (A)[(row)][0] * (B)[0][(col)]; \ 834 (R)[(row)][(col)] += (A)[(row)][1] * (B)[1][(col)]; \ 835 (R)[(row)][(col)] += (A)[(row)][2] * (B)[2][(col)]; \ 836 (R)[(row)][(col)] += (A)[(row)][3] * (B)[3][(col)]; \ 837 } 838 839 #define MAT4_MULTIPLY(A, B, R) \ 840 { \ 841 MAT4_DOT_PROD((A), (B), (R), 0, 0); \ 842 MAT4_DOT_PROD((A), (B), (R), 0, 1); \ 843 MAT4_DOT_PROD((A), (B), (R), 0, 2); \ 844 MAT4_DOT_PROD((A), (B), (R), 0, 3); \ 845 MAT4_DOT_PROD((A), (B), (R), 1, 0); \ 846 MAT4_DOT_PROD((A), (B), (R), 1, 1); \ 847 MAT4_DOT_PROD((A), (B), (R), 1, 2); \ 848 MAT4_DOT_PROD((A), (B), (R), 1, 3); \ 849 MAT4_DOT_PROD((A), (B), (R), 2, 0); \ 850 MAT4_DOT_PROD((A), (B), (R), 2, 1); \ 851 MAT4_DOT_PROD((A), (B), (R), 2, 2); \ 852 MAT4_DOT_PROD((A), (B), (R), 2, 3); \ 853 MAT4_DOT_PROD((A), (B), (R), 3, 0); \ 854 MAT4_DOT_PROD((A), (B), (R), 3, 1); \ 855 MAT4_DOT_PROD((A), (B), (R), 3, 2); \ 856 MAT4_DOT_PROD((A), (B), (R), 3, 3); \ 857 } 858 859 /** 860 * Multiplies two Mat4f matrices and puts it in dst. 861 */ 862 void gd_mult_mat4f(const Mat4f *mA, const Mat4f *mB, Mat4f *dst) { 863 Mat4f res; 864 865 MAT4_MULTIPLY((*mA), (*mB), res); 866 gd_copy_mat4f(&res, dst); 867 } 868 869 #undef MAT4_MULTIPLY 870 #undef MAT4_DOT_PROD 871 872 /** 873 * Prints a vec3f vector. 874 * 875 * Printed the prefix at some point, as shown by how the function is used. 876 */ 877 void gd_print_vec(UNUSED const char *prefix, const struct GdVec3f *vec) { 878 UNUSED u8 filler[8]; 879 880 printf("%f,%f,%f\n", vec->x, vec->y, vec->z); 881 printf("\n"); 882 } 883 884 /** 885 * Prints a plane's boundaries. 886 * 887 * Printed a prefix at some point, as shone by how the function is used. 888 */ 889 void gd_print_bounding_box(UNUSED const char *prefix, UNUSED const struct GdBoundingBox *p) { 890 UNUSED u8 filler[8]; 891 892 printf("Min X = %f, Max X = %f \n", p->minX, p->maxX); 893 printf("Min Y = %f, Max Y = %f \n", p->minY, p->maxY); 894 printf("Min Z = %f, Max Z = %f \n", p->minZ, p->maxZ); 895 printf("\n"); 896 } 897 898 /** 899 * Prints a Mat4f. 900 * 901 * Although the prefix input is unused, the one usage of this function 902 * does have a "Matrix:" prefix, so it was definitely used at one point. 903 */ 904 void gd_print_mtx(UNUSED const char *prefix, const Mat4f *mtx) { 905 s32 i; 906 s32 j; 907 908 for (i = 0; i < 4; i++) { 909 for (j = 0; j < 4; j++) { 910 gd_printf("%f ", (*mtx)[i][j]); 911 } 912 gd_printf("\n"); 913 } 914 } 915 916 /** 917 * Prints a quaternion along with a prefix. 918 */ 919 void UNUSED gd_print_quat(const char *prefix, const f32 f[4]) { 920 s32 i; 921 922 gd_printf(prefix); 923 for (i = 0; i < 4; i++) { 924 gd_printf("%f ", f[i]); 925 } 926 gd_printf("\n"); 927 } 928 929 /** 930 * Rotates a matrix or creates a rotation matrix about a vector made from an offset 931 * of 100 and the passed in x, y, and z values. 932 */ 933 void UNUSED gd_rot_mat_offset(Mat4f *dst, f32 x, f32 y, f32 z, s32 copy) { 934 f32 adj = 100.0f; 935 Mat4f rot; 936 f32 c; 937 f32 s; 938 f32 opp; 939 f32 mag; 940 struct GdVec3f vec; 941 942 opp = gd_sqrt_f(SQ(x) + SQ(y) + SQ(z)); 943 944 if (opp == 0.0f) { 945 if (copy) { 946 gd_set_identity_mat4(dst); 947 } 948 return; 949 } 950 951 mag = gd_sqrt_f(SQ(adj) + SQ(opp)); 952 c = adj / mag; 953 s = opp / mag; 954 955 vec.x = -y / opp; 956 vec.y = -x / opp; 957 vec.z = -z / opp; 958 959 gd_create_rot_matrix(&rot, &vec, s, c); 960 if (!copy) { 961 gd_mult_mat4f(dst, &rot, dst); 962 } else { 963 gd_copy_mat4f(&rot, dst); 964 } 965 }