mirror of
https://github.com/izzy2lost/Diddy-Kong-Racing.git
synced 2026-06-19 01:16:26 -07:00
* wip * wip * wip * wip * document audio_vehicle.c * update score once again * unify function prefix * small tweaks
802 lines
23 KiB
C
802 lines
23 KiB
C
#include "math_util.h"
|
|
|
|
#include <math.h>
|
|
#include "types.h"
|
|
#include "macros.h"
|
|
#include "structs.h"
|
|
#include "game.h"
|
|
#include "string.h"
|
|
#include "PR/os_internal_reg.h"
|
|
|
|
extern s32 gIntDisFlag;
|
|
extern s32 gCurrentRNGSeed; // Official Name: rngSeed
|
|
extern s32 gPrevRNGSeed;
|
|
extern s16 gSineTable[];
|
|
extern s16 gArcTanTable[];
|
|
|
|
/**
|
|
* Most files below are handwritten assembly. Because of this, matching C code is impossible.
|
|
* Nonmatching is not, so functionally equivalent C code can be here to replace these handwritten functions in
|
|
* nonmatching builds. Variables cannot be declared here because of the way they're aligned, so they have to stay in an
|
|
* assembly file.
|
|
*/
|
|
|
|
/******************************/
|
|
|
|
#ifdef NON_MATCHING
|
|
/**
|
|
* Zero out the interrupt mask. This stops this thread
|
|
* from being interrupted by others, letting you safely
|
|
* work with delicate areas in memory. Kind of like a mutex.
|
|
* Returns what the interrupt mask wask before.
|
|
* Official Name: disableInterrupts */
|
|
u32 interrupts_disable(void) {
|
|
if (gIntDisFlag) {
|
|
return __osDisableInt();
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/disable_interrupts.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/**
|
|
* Set the interrupt mask to whichever flags were given.
|
|
* Required after zeroing them out, otherwise system
|
|
* operation won't work as normal.
|
|
* Official Name: enableInterrupts */
|
|
void interrupts_enable(u32 flags) {
|
|
if (gIntDisFlag) {
|
|
__osRestoreInt(flags);
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/enable_interrupts.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official Name: setIntDisFlag */
|
|
void set_gIntDisFlag(s8 setting) {
|
|
gIntDisFlag = setting;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/set_gIntDisFlag.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official Name: getIntDisFlag */
|
|
s8 get_gIntDisFlag(void) {
|
|
return gIntDisFlag;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/get_gIntDisFlag.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT // Untested
|
|
UNUSED void s32_matrix_to_s16_matrix(s32 **input, s16 **output) {
|
|
s32 i;
|
|
for (i = 0; i < 4; i++) {
|
|
output[i][2] = input[i][0];
|
|
output[i][3] = input[i + 4][0];
|
|
output[i][6] = input[i][1];
|
|
output[i][7] = input[i + 4][1];
|
|
output[i][0] = input[i][0] >> 16;
|
|
output[i][1] = input[i + 4][0] >> 16;
|
|
output[i][4] = input[i][1] >> 16;
|
|
output[i][5] = input[i + 4][1] >> 16;
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s32_matrix_to_s16_matrix.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
void f32_matrix_to_s32_matrix(Matrix *input, MatrixS *output) {
|
|
s32 i;
|
|
for (i = 0; i < 4; i++) {
|
|
(*output)[i][0] = (s32) ((*input)[i][0] * 65536.0f);
|
|
(*output)[i][1] = (s32) ((*input)[i][1] * 65536.0f);
|
|
(*output)[i][2] = (s32) ((*input)[i][2] * 65536.0f);
|
|
(*output)[i][3] = (s32) ((*input)[i][3] * 65536.0f);
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_to_s32_matrix.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official name: mathMtxXFMF */
|
|
void guMtxXFMF(Matrix mf, float x, float y, float z, float *ox, float *oy, float *oz) {
|
|
*ox = mf[0][0] * x + mf[1][0] * y + mf[2][0] * z + mf[3][0];
|
|
*oy = mf[0][1] * x + mf[1][1] * y + mf[2][1] * z + mf[3][1];
|
|
*oz = mf[0][2] * x + mf[1][2] * y + mf[2][2] * z + mf[3][2];
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/guMtxXFMF.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official name: mathMtxFastXFMF */
|
|
void f32_matrix_dot(Matrix *mat1, Matrix *mat2, Matrix *output) {
|
|
f32 temp_f4;
|
|
f32 temp_f6;
|
|
f32 temp_f8;
|
|
|
|
temp_f4 = (*mat2)[0][0];
|
|
temp_f6 = (*mat2)[0][1];
|
|
temp_f8 = (*mat2)[0][2];
|
|
(*output)[0][0] = (temp_f4 * (*mat1)[0][0]) + (temp_f6 * (*mat1)[1][0]) + (temp_f8 * (*mat1)[2][0]);
|
|
(*output)[0][1] = (temp_f4 * (*mat1)[0][1]) + (temp_f6 * (*mat1)[1][1]) + (temp_f8 * (*mat1)[2][1]);
|
|
(*output)[0][2] = (temp_f4 * (*mat1)[0][2]) + (temp_f6 * (*mat1)[1][2]) + (temp_f8 * (*mat1)[2][2]);
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_dot.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official name: mathMtxCatF */
|
|
void f32_matrix_mult(Matrix *mat1, Matrix *mat2, Matrix *output) {
|
|
s32 i;
|
|
f32 x;
|
|
f32 y;
|
|
f32 z;
|
|
f32 w;
|
|
for (i = 0; i < 4; i++) {
|
|
x = (*mat1)[i][0];
|
|
y = (*mat1)[i][1];
|
|
z = (*mat1)[i][2];
|
|
w = (*mat1)[i][3];
|
|
(*output)[i][0] =
|
|
(f32) ((y * (*mat2)[1][0]) + (z * (*mat2)[2][0]) + ((x * (*mat2)[0][0]) + (w * (*mat2)[3][0])));
|
|
(*output)[i][1] =
|
|
(f32) ((y * (*mat2)[1][1]) + (z * (*mat2)[2][1]) + ((x * (*mat2)[0][1]) + (w * (*mat2)[3][1])));
|
|
(*output)[i][2] =
|
|
(f32) ((y * (*mat2)[1][2]) + (z * (*mat2)[2][2]) + ((x * (*mat2)[0][2]) + (w * (*mat2)[3][2])));
|
|
(*output)[i][3] =
|
|
(f32) ((y * (*mat2)[1][3]) + (z * (*mat2)[2][3]) + ((x * (*mat2)[0][3]) + (w * (*mat2)[3][3])));
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_mult.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official name: mathMtxF2L */
|
|
void f32_matrix_to_s16_matrix(Matrix *input, MatrixS *output) {
|
|
guMtxF2L((float (*)[4]) input, (Mtx *) output);
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_to_s16_matrix.s")
|
|
#endif
|
|
|
|
/* Official Name: mathSeed */
|
|
void set_rng_seed(s32 num) {
|
|
gCurrentRNGSeed = num;
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
void save_rng_seed(void) {
|
|
s32 num = gCurrentRNGSeed;
|
|
gPrevRNGSeed = num;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/save_rng_seed.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
void load_rng_seed(void) {
|
|
s32 num = gPrevRNGSeed;
|
|
gCurrentRNGSeed = num;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/load_rng_seed.s")
|
|
#endif
|
|
|
|
s32 get_rng_seed(void) {
|
|
return gCurrentRNGSeed;
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official Name: mathRnd */
|
|
s32 get_random_number_from_range(s32 min, s32 max) {
|
|
s32 newSeed;
|
|
u64 curSeed;
|
|
|
|
curSeed = (((u64) ((s64) gCurrentRNGSeed << 0x3F) >> 0x1F) | ((u64) ((s64) gCurrentRNGSeed << 0x1F) >> 0x20)) ^
|
|
((u64) ((s64) gCurrentRNGSeed << 0x2C) >> 0x20);
|
|
newSeed = ((curSeed >> 0x14) & 0xFFF) ^ curSeed;
|
|
gCurrentRNGSeed = newSeed;
|
|
return ((u32) (newSeed - min) % (u32) ((max - min) + 1)) + min;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/rng.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
/* Official name: fastShortReflection */
|
|
void s16_matrix_rotate(s16 *arg0[4][4], s16 arg1[4][4]) {
|
|
s32 temp_t6;
|
|
|
|
temp_t6 = (s32) ((*arg0[0][0] * arg1[0][0]) + (*arg0[0][1] * arg1[0][1]) + (*arg0[0][2] * *arg0[0][2])) >> 12;
|
|
*arg0[1][0] = (s16) (((s32) (temp_t6 * arg1[0][0]) >> 13) - *arg0[0][0]);
|
|
*arg0[1][1] = (s16) (((s32) (temp_t6 * arg1[0][1]) >> 13) - *arg0[0][1]);
|
|
*arg0[1][2] =
|
|
(s16) (((s32) (temp_t6 * arg1[0][2]) >> 13) - *arg0[0][0]); // Did they mean to do `- *arg0[0][2]` here?
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s16_matrix_rotate.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT // Untested
|
|
UNUSED void s16_matrix_to_s32_matrix(s16 **arg0, s32 **arg1) {
|
|
s32 i, j;
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
arg1[i][j] = (arg0[i][j] << 16) | arg0[i + 4][j];
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s16_matrix_to_s32_matrix.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT // Untested
|
|
UNUSED void s16_vec3_mult_by_s32_matrix_full(s32 **input, s16 *output) {
|
|
output[0] = ((output[0] * input[0][0]) + (output[1] * input[1][0]) + (output[2] * input[2][0]) + input[3][0]) >> 16;
|
|
output[1] = ((output[0] * input[0][1]) + (output[1] * input[1][1]) + (output[2] * input[2][1]) + input[3][1]) >> 16;
|
|
output[2] = ((output[0] * input[0][2]) + (output[1] * input[1][2]) + (output[2] * input[2][2]) + input[3][2]) >> 16;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s16_vec3_mult_by_s32_matrix_full.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
void s16_vec3_mult_by_s32_matrix(MatrixS input, Vec3s *output) {
|
|
s32 x;
|
|
s32 y;
|
|
s32 z;
|
|
|
|
x = output->x;
|
|
y = output->y;
|
|
z = output->z;
|
|
output->x = ((x * input[0][0]) + (y * input[1][0]) + (z * input[2][0])) >> 16;
|
|
output->y = ((x * input[0][1]) + (y * input[1][1]) + (z * input[2][1])) >> 16;
|
|
output->z = ((x * input[0][2]) + (y * input[1][2]) + (z * input[2][2])) >> 16;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s16_vec3_mult_by_s32_matrix.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/**
|
|
* Converts an ObjectTransform into a transformation matrix and writes it to `mtx`.
|
|
* The matrix is built by applying the following operations in order:
|
|
* 1. Scaling
|
|
* 2. Rotation around Z axis (roll)
|
|
* 3. Rotation around X axis (pitch)
|
|
* 4. Rotation around Y axis (yaw)
|
|
* 5. Translation
|
|
*/
|
|
void object_transform_to_matrix(Matrix mtx, ObjectTransform *trans) {
|
|
f32 yRotSine;
|
|
f32 yRotCosine;
|
|
f32 xRotSine;
|
|
f32 xRotCosine;
|
|
f32 zRotSine;
|
|
f32 zRotCosine;
|
|
f32 scale;
|
|
|
|
yRotSine = sins_s16(trans->rotation.y_rotation) * (1.0f / 0x10000);
|
|
yRotCosine = coss_s16(trans->rotation.y_rotation) * (1.0f / 0x10000);
|
|
xRotSine = sins_s16(trans->rotation.x_rotation) * (1.0f / 0x10000);
|
|
xRotCosine = coss_s16(trans->rotation.x_rotation) * (1.0f / 0x10000);
|
|
zRotSine = sins_s16(trans->rotation.z_rotation) * (1.0f / 0x10000);
|
|
zRotCosine = coss_s16(trans->rotation.z_rotation) * (1.0f / 0x10000);
|
|
scale = trans->scale;
|
|
|
|
mtx[0][0] = (xRotSine * yRotSine * zRotSine + zRotCosine * yRotCosine) * scale;
|
|
mtx[0][1] = (zRotSine * xRotCosine) * scale;
|
|
mtx[0][2] = (xRotSine * yRotCosine * zRotSine - zRotCosine * yRotSine) * scale;
|
|
mtx[0][3] = 0;
|
|
mtx[1][0] = (xRotSine * yRotSine * zRotCosine - zRotSine * yRotCosine) * scale;
|
|
mtx[1][1] = (zRotCosine * xRotCosine) * scale;
|
|
mtx[1][2] = (xRotSine * yRotCosine * zRotCosine + zRotSine * yRotSine) * scale;
|
|
mtx[1][3] = 0;
|
|
mtx[2][0] = (xRotCosine * yRotSine) * scale;
|
|
mtx[2][1] = -(xRotSine * scale);
|
|
mtx[2][2] = (xRotCosine * yRotCosine) * scale;
|
|
mtx[2][3] = 0;
|
|
mtx[3][0] = trans->x_position;
|
|
mtx[3][1] = trans->y_position;
|
|
mtx[3][2] = trans->z_position;
|
|
mtx[3][3] = 1.0f;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/object_transform_to_matrix.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official name: mathSquashY */
|
|
void f32_matrix_scale_y_axis(Matrix *input, f32 scale) {
|
|
input[0][1][0] *= scale;
|
|
input[0][1][1] *= scale;
|
|
input[0][1][2] *= scale;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_scale_y_axis.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official name: mathTransY */
|
|
void f32_matrix_translate_y_axis(Matrix *input, f32 offset) {
|
|
input[0][3][0] += input[0][1][0] * offset;
|
|
input[0][3][1] += input[0][1][1] * offset;
|
|
input[0][3][2] += input[0][1][2] * offset;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_translate_y_axis.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
/**
|
|
* Writes an inverse transformation matrix to `mtx` based on a pre-inverted `ObjectTransform`.
|
|
* This is used to convert world-space coordinates to local object-space coordinates.
|
|
* Unlike the standard transform, this version:
|
|
* - Omits scaling
|
|
* - Applies the transformation steps in reverse order
|
|
* - Assumes that the translation and rotation values in `trans` are already negated
|
|
*
|
|
* Operation order:
|
|
* 1. Translate (negative offset)
|
|
* 2. Rotate Y (negative yaw)
|
|
* 3. Rotate X (negative pitch)
|
|
* 4. Rotate Z (negative roll)
|
|
*/
|
|
/* Official Name: mathRpyXyzMtx */
|
|
void object_inverse_transform_to_matrix(Matrix mtx, ObjectTransform *trans) {
|
|
f32 yRotSine;
|
|
f32 yRotCosine;
|
|
f32 xRotSine;
|
|
f32 xRotCosine;
|
|
f32 zRotSine;
|
|
f32 zRotCosine;
|
|
|
|
yRotCosine = coss_s16(trans->rotation.y_rotation) * (1.0f / 0x10000);
|
|
yRotSine = sins_s16(trans->rotation.y_rotation) * (1.0f / 0x10000);
|
|
xRotCosine = coss_s16(trans->rotation.x_rotation) * (1.0f / 0x10000);
|
|
xRotSine = sins_s16(trans->rotation.x_rotation) * (1.0f / 0x10000);
|
|
zRotCosine = coss_s16(trans->rotation.z_rotation) * (1.0f / 0x10000);
|
|
zRotSine = sins_s16(trans->rotation.z_rotation) * (1.0f / 0x10000);
|
|
|
|
mtx[0][0] = yRotCosine * zRotCosine - xRotSine * zRotSine * yRotSine;
|
|
mtx[0][1] = xRotSine * zRotCosine * yRotSine + yRotCosine * zRotSine;
|
|
mtx[0][2] = -(yRotSine * xRotCosine);
|
|
mtx[0][3] = 0;
|
|
mtx[1][0] = -(xRotCosine * zRotSine);
|
|
mtx[1][1] = xRotCosine * zRotCosine;
|
|
mtx[1][2] = xRotSine;
|
|
mtx[1][3] = 0;
|
|
mtx[2][0] = xRotSine * zRotSine * yRotCosine + yRotSine * zRotCosine;
|
|
mtx[2][1] = yRotSine * zRotSine - xRotSine * zRotCosine * yRotCosine;
|
|
mtx[2][2] = yRotCosine * xRotCosine;
|
|
mtx[2][3] = 0;
|
|
mtx[3][0] = (mtx[0][0] * trans->x_position) + (mtx[1][0] * trans->y_position) + (mtx[2][0] * trans->z_position);
|
|
mtx[3][1] = (mtx[0][1] * trans->x_position) + (mtx[1][1] * trans->y_position) + (mtx[2][1] * trans->z_position);
|
|
mtx[3][2] = (mtx[0][2] * trans->x_position) + (mtx[1][2] * trans->y_position) + (mtx[2][2] * trans->z_position);
|
|
mtx[3][3] = 1.0f;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/object_inverse_transform_to_matrix.s")
|
|
#endif
|
|
|
|
GLOBAL_ASM("asm/math_util/func_80070058.s")
|
|
|
|
#ifdef NON_MATCHING
|
|
void f32_matrix_from_rotation_and_scale(Matrix mtx, s32 angle, f32 scale, f32 scaleY) {
|
|
f32 cosine, sine;
|
|
|
|
sine = sins_s16(angle) * (1.0f / 0x10000);
|
|
cosine = coss_s16(angle) * (1.0f / 0x10000);
|
|
mtx[0][0] = cosine * scale;
|
|
mtx[0][1] = sine * scale;
|
|
mtx[0][2] = 0;
|
|
mtx[0][3] = 0;
|
|
mtx[1][0] = -sine * scale;
|
|
mtx[1][1] = (cosine * scale) * scaleY;
|
|
mtx[1][2] = 0;
|
|
mtx[1][3] = 0;
|
|
mtx[2][0] = 0;
|
|
mtx[2][1] = 0;
|
|
mtx[2][2] = scale;
|
|
mtx[2][3] = 0;
|
|
mtx[3][0] = 0;
|
|
mtx[3][1] = 0;
|
|
mtx[3][2] = 0;
|
|
mtx[3][3] = 1.0f;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_from_rotation_and_scale.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
void s16_vec3_apply_object_rotation(ObjectTransform *trans, s16 *vec3Arg) {
|
|
s32 yRotSine;
|
|
s32 yRotCosine;
|
|
s32 xRotSine;
|
|
s32 xRotCosine;
|
|
s32 zRotSine;
|
|
s32 zRotCosine;
|
|
s32 temp_t3;
|
|
s32 temp_t4;
|
|
s32 temp_t5;
|
|
|
|
yRotCosine = coss_s16(trans->rotation.y_rotation);
|
|
yRotSine = sins_s16(trans->rotation.y_rotation);
|
|
xRotCosine = coss_s16(trans->rotation.x_rotation);
|
|
xRotSine = sins_s16(trans->rotation.x_rotation);
|
|
zRotCosine = coss_s16(trans->rotation.z_rotation);
|
|
zRotSine = sins_s16(trans->rotation.z_rotation);
|
|
|
|
temp_t3 = ((vec3Arg[0] * yRotSine) - (vec3Arg[1] * yRotCosine)) >> 16;
|
|
temp_t4 = ((vec3Arg[1] * yRotSine) + (vec3Arg[0] * yRotCosine)) >> 16;
|
|
|
|
temp_t4 = ((temp_t4 * xRotSine) - (vec3Arg[2] * xRotCosine)) >> 16;
|
|
temp_t5 = ((vec3Arg[2] * xRotSine) + (temp_t4 * xRotCosine)) >> 16;
|
|
|
|
vec3Arg[1] = temp_t4;
|
|
|
|
temp_t3 = ((temp_t3 * zRotSine) + (temp_t5 * zRotCosine)) >> 16;
|
|
temp_t5 = ((temp_t5 * zRotSine) - (temp_t3 * zRotCosine)) >> 16;
|
|
|
|
vec3Arg[0] = temp_t3;
|
|
vec3Arg[2] = temp_t5;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s16_vec3_apply_object_rotation.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
/* Official Name: mathOneFloatRPY */
|
|
void f32_vec3_apply_object_rotation(ObjectTransform *trans, f32 *vec3_f32) {
|
|
f32 yRotSine;
|
|
f32 yRotCosine;
|
|
f32 xRotSine;
|
|
f32 xRotCosine;
|
|
f32 zRotSine;
|
|
f32 zRotCosine;
|
|
f32 x, y, z;
|
|
f32 temp;
|
|
|
|
zRotSine = sinf(trans->rotation.z_rotation);
|
|
zRotCosine = cosf(trans->rotation.z_rotation);
|
|
xRotSine = sinf(trans->rotation.x_rotation);
|
|
xRotCosine = cosf(trans->rotation.x_rotation);
|
|
yRotSine = sinf(trans->rotation.y_rotation);
|
|
yRotCosine = cosf(trans->rotation.y_rotation);
|
|
|
|
x = vec3_f32[0];
|
|
y = vec3_f32[1];
|
|
z = vec3_f32[2];
|
|
|
|
x = (vec3_f32[0] * zRotCosine) - (vec3_f32[1] * zRotSine);
|
|
y = (vec3_f32[1] * zRotCosine) + (vec3_f32[0] * zRotSine);
|
|
|
|
temp = y;
|
|
y = (temp * xRotCosine) - (vec3_f32[2] * xRotSine);
|
|
z = (vec3_f32[2] * xRotCosine) + (temp * xRotSine);
|
|
|
|
temp = x;
|
|
x = (temp * yRotCosine) + (z * yRotSine);
|
|
z = (z * yRotCosine) - (temp * yRotSine);
|
|
|
|
vec3_f32[0] = x;
|
|
vec3_f32[1] = y;
|
|
vec3_f32[2] = z;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_vec3_apply_object_rotation.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
/* Official Name: mathOneFloatYPR */
|
|
void f32_vec3_apply_object_rotation2(ObjectTransform *trans, f32 *arg1) {
|
|
f32 yRotSine;
|
|
f32 yRotCosine;
|
|
f32 xRotSine;
|
|
f32 xRotCosine;
|
|
f32 zRotSine;
|
|
f32 zRotCosine;
|
|
f32 temp_f4;
|
|
f32 temp_f6;
|
|
f32 temp_f8;
|
|
|
|
xRotSine = sinf(trans->rotation.x_rotation);
|
|
xRotCosine = cosf(trans->rotation.x_rotation);
|
|
yRotSine = sinf(trans->rotation.y_rotation);
|
|
yRotCosine = cosf(trans->rotation.y_rotation);
|
|
zRotCosine = cosf(trans->rotation.z_rotation);
|
|
zRotSine = sinf(trans->rotation.z_rotation);
|
|
|
|
temp_f4 = (arg1[0] * xRotSine) + (arg1[2] * xRotCosine);
|
|
temp_f8 = (arg1[2] * xRotSine) - (arg1[0] * xRotCosine);
|
|
|
|
temp_f6 = (arg1[1] * yRotSine) - (temp_f8 * yRotCosine);
|
|
temp_f8 = (temp_f8 * yRotSine) + (arg1[1] * yRotCosine);
|
|
|
|
arg1[2] = temp_f8;
|
|
|
|
temp_f4 = (temp_f4 * zRotSine) - (temp_f6 * zRotCosine);
|
|
temp_f6 = (temp_f6 * zRotSine) + (temp_f4 * zRotCosine);
|
|
|
|
arg1[0] = temp_f4;
|
|
arg1[1] = temp_f6;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_vec3_apply_object_rotation2.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
/* Official Name: mathOneFloatPY */
|
|
void f32_vec3_apply_object_rotation3(Vec3s *trans, f32 *vec3_f32) {
|
|
f32 xRotSine;
|
|
f32 xRotCosine;
|
|
f32 yRotSine;
|
|
f32 yRotCosine;
|
|
f32 x, y, z;
|
|
|
|
xRotSine = sinf(trans->x_rotation);
|
|
xRotCosine = cosf(trans->x_rotation);
|
|
yRotSine = sinf(trans->y_rotation);
|
|
yRotCosine = cosf(trans->y_rotation);
|
|
|
|
z = vec3_f32[2];
|
|
y = -(z * xRotSine);
|
|
z = z * xRotCosine;
|
|
x = (z * yRotSine);
|
|
z = z * yRotCosine;
|
|
|
|
vec3_f32[0] = x;
|
|
vec3_f32[1] = y;
|
|
vec3_f32[2] = z;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_vec3_apply_object_rotation3.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/* Official Name: mathXZInTri */
|
|
s32 point_triangle_2d_xz_intersection(s32 x, s32 z, s16 *vec3A, s16 *vec3B, s16 *vec3C) {
|
|
s32 result;
|
|
s32 aX;
|
|
s32 aZ;
|
|
s32 bX;
|
|
s32 bZ;
|
|
s32 cX;
|
|
s32 cZ;
|
|
s32 var_a1;
|
|
s32 var_a2;
|
|
s32 var_a3;
|
|
|
|
aX = vec3A[0];
|
|
aZ = vec3A[2];
|
|
bX = vec3B[0];
|
|
bZ = vec3B[2];
|
|
cX = vec3C[0];
|
|
cZ = vec3C[2];
|
|
result = FALSE;
|
|
var_a1 = 1;
|
|
var_a2 = 1;
|
|
var_a3 = 1;
|
|
if ((((x - aX) * (bZ - aZ)) - ((bX - aX) * (z - aZ))) < 0) {
|
|
var_a3 ^= 1;
|
|
}
|
|
if ((((x - bX) * (cZ - bZ)) - ((cX - bX) * (z - bZ))) < 0) {
|
|
var_a2 ^= 1;
|
|
}
|
|
if (var_a3 == var_a2) {
|
|
if ((((x - cX) * (aZ - cZ)) - ((aX - cX) * (z - cZ))) < 0) {
|
|
var_a1 ^= 1;
|
|
}
|
|
if (var_a1 == var_a2) {
|
|
result = TRUE;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/point_triangle_2d_xz_intersection.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT
|
|
/* Official Name: mathTranslateMtx */
|
|
void f32_matrix_from_position(Matrix *mtx, f32 x, f32 y, f32 z) {
|
|
s32 j;
|
|
s32 i;
|
|
// Clear matrix
|
|
for (i = 0; i < 4; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
*mtx[i][j] = 0;
|
|
}
|
|
}
|
|
*mtx[0][0] = 1.0f;
|
|
*mtx[1][1] = 1.0f;
|
|
*mtx[2][2] = 1.0f;
|
|
*mtx[3][3] = 1.0f;
|
|
*mtx[3][0] = x;
|
|
*mtx[3][1] = y;
|
|
*mtx[3][2] = z;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_from_position.s")
|
|
#endif
|
|
|
|
/* Official Name: mathScaleMtx */
|
|
GLOBAL_ASM("asm/math_util/f32_matrix_from_scale.s")
|
|
|
|
#ifdef NON_MATCHING
|
|
// Blatantly stolen from SM64 :)
|
|
static u16 atan2_lookup(f32 y, f32 x) {
|
|
u16 ret;
|
|
|
|
if (x == 0) {
|
|
ret = gArcTanTable[0];
|
|
} else {
|
|
ret = gArcTanTable[(s32) (y / x * 1024 + 0.5f)];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
s32 atan2s(s32 xDelta, s32 zDelta) {
|
|
u16 ret;
|
|
|
|
if (xDelta >= 0) {
|
|
if (zDelta >= 0) {
|
|
if (zDelta >= xDelta) {
|
|
ret = atan2_lookup(xDelta, zDelta);
|
|
} else {
|
|
ret = 0x4000 - atan2_lookup(zDelta, xDelta);
|
|
}
|
|
} else {
|
|
zDelta = -zDelta;
|
|
if (zDelta < xDelta) {
|
|
ret = 0x4000 + atan2_lookup(zDelta, xDelta);
|
|
} else {
|
|
ret = 0x8000 - atan2_lookup(xDelta, zDelta);
|
|
}
|
|
}
|
|
} else {
|
|
xDelta = -xDelta;
|
|
if (zDelta < 0) {
|
|
zDelta = -zDelta;
|
|
if (zDelta >= xDelta) {
|
|
ret = 0x8000 + atan2_lookup(xDelta, zDelta);
|
|
} else {
|
|
ret = 0xC000 - atan2_lookup(zDelta, xDelta);
|
|
}
|
|
} else {
|
|
if (zDelta < xDelta) {
|
|
ret = 0xC000 + atan2_lookup(zDelta, xDelta);
|
|
} else {
|
|
ret = -atan2_lookup(xDelta, zDelta);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/atan2s.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
u16 arctan2_f(f32 y, f32 x) {
|
|
return atan2s((s32) (y * 255.0f), (s32) (x * 255.0f));
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/arctan2_f.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT // Untested
|
|
UNUSED s32 s32_matrix_cell_sqrt(s32 arg0) {
|
|
return (s32) (sqrtf((f32) arg0 / 65536.0f) * 65536.0f);
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/s32_matrix_cell_sqrt.s")
|
|
#endif
|
|
|
|
#ifdef NON_EQUIVALENT // Untested
|
|
UNUSED s32 bad_int_sqrt(s32 arg0) {
|
|
return (s32) (sqrtf((f32) arg0 / 65536.0f) * 65536.0f);
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/bad_int_sqrt.s")
|
|
#endif
|
|
|
|
GLOBAL_ASM("asm/math_util/sins_f.s")
|
|
GLOBAL_ASM("asm/math_util/coss_f.s")
|
|
GLOBAL_ASM("asm/math_util/coss.s")
|
|
GLOBAL_ASM("asm/math_util/sins_2.s")
|
|
|
|
#ifdef NON_EQUIVALENT // Untested
|
|
UNUSED s32 calc_dyn_lighting_for_level_segment(LevelModelSegment *segment, s32 *vec3_ints) {
|
|
s32 dotProduct;
|
|
s32 numVertsInBatch;
|
|
s32 vertCount;
|
|
s32 upperColor;
|
|
s32 alpha;
|
|
s32 numBatches;
|
|
s32 i, j;
|
|
Vertex *verts;
|
|
Vertex *verts2C;
|
|
TriangleBatchInfo *batches;
|
|
|
|
numBatches = segment->numberOfBatches;
|
|
batches = segment->batches;
|
|
vertCount = 0;
|
|
for (i = 0; i < numBatches; i++) {
|
|
// batches[i].unk6 is 0xFF if vertex colors are used. Otherwise dynamic lighting is used.
|
|
if ((batches[i].unk6 - 0xFF) != 0) {
|
|
verts = &segment->vertices[vertCount];
|
|
verts2C = &segment->unk2C[vertCount];
|
|
numVertsInBatch = batches[i + 1].verticesOffset - batches[i].verticesOffset;
|
|
for (j = 0; j < numVertsInBatch; j++) {
|
|
alpha = verts2C[j].a;
|
|
dotProduct =
|
|
(verts2C[j].x * vec3_ints[0]) + (verts2C[j].y * vec3_ints[1]) + (verts2C[j].z * vec3_ints[2]);
|
|
if (dotProduct > 0) {
|
|
alpha += dotProduct >> 22;
|
|
if (alpha > 128) {
|
|
alpha = 128;
|
|
}
|
|
}
|
|
upperColor = (alpha * (verts2C[j].r | (verts2C[j].g << 16))) >> 7;
|
|
verts[j].r = (s8) upperColor;
|
|
verts[j].g = (s8) (upperColor >> 16);
|
|
verts[j].b = (s8) ((u32) (alpha * verts2C[j].b) >> 7);
|
|
}
|
|
vertCount += numVertsInBatch;
|
|
} else {
|
|
vertCount += batches[i + 1].verticesOffset - batches[i].verticesOffset;
|
|
}
|
|
}
|
|
return vertCount;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/calc_dyn_lighting_for_level_segment.s")
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
/**
|
|
* Signed distance field calculation. It's used to calculate the level of intersection between a point and a triangle.
|
|
*/
|
|
f32 area_triangle_2d(f32 x0, f32 z0, f32 x1, f32 z1, f32 x2, f32 z2) {
|
|
f32 dx0 = x1 - x0;
|
|
f32 dz0 = z1 - z0;
|
|
f32 dx1 = x2 - x1;
|
|
f32 dz1 = z2 - z1;
|
|
f32 dx2 = x0 - x2;
|
|
f32 dz2 = z0 - z2;
|
|
f32 d0 = sqrtf((dx0 * dx0) + (dz0 * dz0)); // Distance between points 0 & 1
|
|
f32 d1 = sqrtf((dx1 * dx1) + (dz1 * dz1)); // Distance between points 1 & 2
|
|
f32 d2 = sqrtf((dx2 * dx2) + (dz2 * dz2)); // Distance between points 2 & 0
|
|
f32 m = 0.5f * (d0 + d1 + d2); // Half the sum of the distances?
|
|
f32 result = m * (m - d0) * (m - d1) * (m - d2);
|
|
if (result < 0.0f) {
|
|
result = 0.0f;
|
|
}
|
|
return sqrtf(result);
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/area_triangle_2d.s")
|
|
#endif
|
|
|
|
GLOBAL_ASM("asm/math_util/set_breakpoint.s")
|
|
|
|
#ifdef NON_MATCHING
|
|
void dmacopy_doubleword(void *src, void *dst, s32 end) {
|
|
s32 size = end - (u32) dst;
|
|
memcpy(dst, src, size);
|
|
}
|
|
#else
|
|
GLOBAL_ASM("asm/math_util/dmacopy_doubleword.s")
|
|
#endif
|