mirror of https://github.com/zeldaret/mm.git
code_801780F0 OK and documented, EnPaper documented (#1061)
* File split * Split, OK and documented Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com> Co-authored-by: engineer124 <engineer124engineer124@gmail.com> Co-authored-by: Synray <31429825+Synray@users.noreply.github.com> * Document relevant parts of DmBal * Some EnPaper docs * Document EnPaper * Name functions * Defake Actor_UpdateActor a bit * Reword * \cdot * Fiddle with the description of the DE again * Actually force is probably more correct * Probably time to stop fiddling * Format? * Review * Remove bug comment * Review * Rename to su_mtx, split off code_80140CE0 * Format Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com> Co-authored-by: engineer124 <engineer124engineer124@gmail.com> Co-authored-by: Synray <31429825+Synray@users.noreply.github.com> Co-authored-by: angie <angheloalf95@gmail.com>
This commit is contained in:
parent
b73d18b154
commit
bbbe0b1821
|
@ -76,6 +76,6 @@
|
|||
<Animation Name="object_bal_Anim_00C8D8" Offset="0xC8D8" /> <!-- Original name is "bal_talk4" -->
|
||||
<Animation Name="object_bal_Anim_00CB78" Offset="0xCB78" /> <!-- Original name is "bal_tereru" ("to be shy; to be bashful") -->
|
||||
<Animation Name="object_bal_Anim_00D530" Offset="0xD530" /> <!-- Original name is "bal_wait" -->
|
||||
<DList Name="object_bal_DL_00D5A0" Offset="0xD5A0" /> <!-- Original name is "bal_cube32_model" -->
|
||||
<DList Name="gTingleConfettiDL" Offset="0xD5A0" /> <!-- Original name is "bal_cube32_model" -->
|
||||
</File>
|
||||
</Root>
|
||||
|
|
|
@ -2551,9 +2551,11 @@ void SpeedMeter_DrawTimeEntries(void* displayList, GraphicsContext* gfxCtx);
|
|||
// void func_80177A84(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7, UNK_TYPE4 param_8, UNK_TYPE4 param_9);
|
||||
//void func_80177AC8(void);
|
||||
void SpeedMeter_DrawAllocEntries(void* displayList, GraphicsContext* gfxCtx, GameState* gameState);
|
||||
void func_801780F0(Mtx* param_1, f32 param_2, f32 param_3, f32 param_4, f32 param_5, f32 param_6, f32 param_7);
|
||||
// void func_801781EC(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
|
||||
void func_8017842C(MtxF* arg0, f32 arg1, f32 arg2, f32 arg3, s16 arg4, f32 arg5, f32 arg6, f32 arg7, f32 arg8, f32 arg9, f32 arg10);
|
||||
|
||||
void Mtx_SetTranslateScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY, f32 translateZ);
|
||||
void Mtx_SetRotationMtx(Mtx* mtx, s32 angle, f32 axisX, f32 axisY, f32 axisZ);
|
||||
void Mtx_SetTranslationRotationScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, s32 angle, f32 axisX, f32 axisY, f32 axisZ,f32 translateX, f32 translateY, f32 translateZ);
|
||||
|
||||
// void func_80178750(void);
|
||||
// void func_80178818(void);
|
||||
void func_80178978(void);
|
||||
|
|
4
spec
4
spec
|
@ -528,7 +528,8 @@ beginseg
|
|||
include "build/src/code/z_rumble.o"
|
||||
include "build/src/code/z_view.o"
|
||||
include "build/src/code/z_vimode.o"
|
||||
include "build/data/code/z_vimode.data.o"
|
||||
include "build/src/code/code_80140CE0.o"
|
||||
include "build/data/code/code_80140CE0.data.o"
|
||||
include "build/src/code/code_80140E80.o"
|
||||
include "build/src/code/z_vismono.o"
|
||||
include "build/src/code/code_801420C0.o"
|
||||
|
@ -580,6 +581,7 @@ beginseg
|
|||
include "build/src/code/speed_meter.o"
|
||||
include "build/data/code/speed_meter.data.o"
|
||||
include "build/data/code/speed_meter.bss.o"
|
||||
include "build/src/code/su_mtx.o"
|
||||
include "build/data/code/sys_cfb.bss.o"
|
||||
include "build/src/code/sys_cmpdma.o"
|
||||
include "build/data/code/sys_cmpdma.bss.o"
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#include "global.h"
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140CE0/func_80140CE0.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140CE0/func_80140D04.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/code_80140CE0/func_80140D10.s")
|
|
@ -15,9 +15,3 @@
|
|||
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_80177AC8.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/SpeedMeter_DrawAllocEntries.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_801780F0.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_801781EC.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_8017842C.s")
|
||||
|
|
|
@ -0,0 +1,361 @@
|
|||
/**
|
||||
* @file su_mtx.c
|
||||
* @brief "Fast" functions for constructing RSP-compatible matrices directly
|
||||
*
|
||||
* The three functions in this file construct scaling, rotation, and translation matrices, and combinations thereof. The
|
||||
* intention appears to be to exploit the peculiar structure of the RSP's fixed-point matrix format, which we recall is
|
||||
*
|
||||
* typedef long int Mtx_t[4][4];
|
||||
* typedef union {
|
||||
* Mtx_t m;
|
||||
* struct {
|
||||
* u16 intPart[4][4];
|
||||
* u16 fracPart[4][4];
|
||||
* };
|
||||
* long long int forc_structure_alignment;
|
||||
* } Mtx; // size = 0x40
|
||||
*
|
||||
* This means it can be written to as either words or two sets of shorts; the latter is the correct format for
|
||||
* interpreting it the way the RSP does, but the first is likely faster to access and write to. The functions save
|
||||
* writing halves by
|
||||
*
|
||||
* - writing a word 0 if two adjacent elements are 0 in a convenient place, or 1 if they are 0 and 1,
|
||||
* - writing a word using a shift and overwriting the dirty half afterwards.
|
||||
*
|
||||
* Examples of both of these are seen in Mtx_SetTranslateScaleMtx(); we explain there in full detail due to the
|
||||
* function's relative simplicity. The other two functions we merely point out the interesting parts rather than
|
||||
* explaining the whole process.
|
||||
*
|
||||
* We use the following notation throughout: round brackets denote the word-sized elements, square the pairs they cover.
|
||||
* The integer and fractional parts of a fixed-point number are denoted by i and f respectively, and these letters are
|
||||
* also used to represent which half each of the pairs belongs to.
|
||||
*
|
||||
* (00) [i00,i01], (01) [i02,i03]
|
||||
* (02) [i10,i11], (03) [i12,i13]
|
||||
* (10) [i20,i21], (11) [i22,i23]
|
||||
* (12) [i30,i31], (13) [i32,i33]
|
||||
* (20) [f00,f01], (21) [f02,f03]
|
||||
* (22) [f10,f11], (23) [f12,f13]
|
||||
* (30) [f20,f21], (31) [f22,f23]
|
||||
* (32) [f30,f31], (33) [f32,f33]
|
||||
*
|
||||
* We keep the RSP's column-major convention; this file is confusing enough without attempting to transpose everything.
|
||||
* Bear in mind therefore that we are acting on *row vectors* on the *right*.
|
||||
*
|
||||
* @warning The behaviour of the output of the functions in this file is undefined in C89, since both members of the
|
||||
* union are used to set the mtxs. (C99+ allow type-punning, but the behaviour is still implementation-defined because
|
||||
* it relies on the storage being big-endian.)
|
||||
*
|
||||
* @remark Name inferred from shared Animal Forest functions, meaning of "su" is unclear.
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
|
||||
/**
|
||||
* Constructs a matrix \$f ST \$f, i.e. a scaling \$f S \$f followed by a translation \$f T \$f.
|
||||
*
|
||||
* The final result is
|
||||
*
|
||||
* \f[
|
||||
* \begin{bmatrix}
|
||||
* s_x & 0 & 0 & 0 \\
|
||||
* 0 & s_y & 0 & 0 \\
|
||||
* 0 & 0 & s_z & 0 \\
|
||||
* t_x & t_y & t_z & 1
|
||||
* \end{bmatrix}
|
||||
* \f]
|
||||
*
|
||||
* @param[out] mtx Fixed-point matrix pointer to output to
|
||||
* @param[in] scaleX Scale in the X direction
|
||||
* @param[in] scaleY Scale in the Y direction
|
||||
* @param[in] scaleZ Scale in the Z direction
|
||||
* @param[in] translateX X component of translation
|
||||
* @param[in] translateY Y component of translation
|
||||
* @param[in] translateZ Z component of translation
|
||||
*
|
||||
* @remark Original name: "suMtxMakeTS"
|
||||
*/
|
||||
void Mtx_SetTranslateScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY,
|
||||
f32 translateZ) {
|
||||
Mtx* m = mtx;
|
||||
s32 fixedPoint;
|
||||
|
||||
m->m[0][1] = 0; // [i02, i03] == [0, 0]
|
||||
m->m[2][1] = 0; // [f02, f03] == [0, 0]
|
||||
m->m[0][3] = 0; // [i12, i13] == [0, 0]
|
||||
m->m[2][3] = 0; // [f22, f23] == [0, 0]
|
||||
m->m[1][0] = 0; // [i20, i21] == [0, 0]
|
||||
//
|
||||
fixedPoint = scaleX * 0x10000; //
|
||||
m->m[0][0] = fixedPoint; // [i00, i01] == [scaleX.i, scaleX.f]; i01 is now "dirty"
|
||||
m->intPart[0][1] = 0; // Clean i01 by zeroing it: [i00, i01] == [scaleX.i, 0]
|
||||
m->m[2][0] = (u32)fixedPoint << 16; // [f00, f01] == [scaleX.f, 0]
|
||||
//
|
||||
fixedPoint = scaleY * 0x10000; //
|
||||
m->m[0][2] = (u32)fixedPoint >> 16; // [i10, i11] == [0, scaleY.i]
|
||||
m->m[2][2] = fixedPoint & 0xFFFF; // [f10, f11] == [0, scaleY.f]
|
||||
//
|
||||
fixedPoint = scaleZ * 0x10000; //
|
||||
m->m[1][1] = fixedPoint; // [i22, i23] == [scaleZ.i, scaleZ.f]
|
||||
m->intPart[2][3] = 0; // [i22, i23] == [scaleZ.i, 0]
|
||||
m->m[3][1] = (u32)fixedPoint << 16; // [f22, f23] == [scaleZ.f, 0]
|
||||
//
|
||||
m->m[3][0] = 0; // [f20, f21] == [0, 0]
|
||||
//
|
||||
fixedPoint = translateX * 0x10000; //
|
||||
m->intPart[3][0] = ((u32)fixedPoint >> 16) & 0xFFFF; // [i30, i31] == [translateX.i, ?]
|
||||
m->fracPart[3][0] = fixedPoint & 0xFFFF; // [f30, f31] == [translateX.f, ?]
|
||||
//
|
||||
fixedPoint = translateY * 0x10000; //
|
||||
m->intPart[3][1] = ((u32)fixedPoint >> 16) & 0xFFFF; // [i30, i31] == [translateX.i, translateY.i]
|
||||
m->fracPart[3][1] = fixedPoint & 0xFFFF; // [f30, f31] == [translateX.f, translateY.f]
|
||||
//
|
||||
fixedPoint = translateZ * 0x10000; //
|
||||
m->intPart[3][2] = ((u32)fixedPoint >> 16) & 0xFFFF; // [i30, i31] == [translateZ.i, ?]
|
||||
m->intPart[3][3] = 1; // [i32, i33] == [translateZ.i, 1]
|
||||
m->m[3][3] = (u32)fixedPoint << 16; // [f32, f33] == [translateZ.f, 0]
|
||||
|
||||
// So we end up with
|
||||
// [scaleX.i, 0], [0, 0],
|
||||
// [0, scaleY.i], [0, 0],
|
||||
// [0, 0], [scaleZ.i, 0],
|
||||
// [translateX.i, translateY.i], [translateZ.i, 1]
|
||||
//
|
||||
// [scaleX.f, 0], [0, 0],
|
||||
// [0, scaleY.f], [0, 0],
|
||||
// [0, 0], [scaleZ.f, 0]
|
||||
// [translateX.f, translateY.f], [translateZ.f, 0]
|
||||
}
|
||||
|
||||
// Unused
|
||||
/**
|
||||
* Should create an axis-angle rotation matrix.
|
||||
*
|
||||
* @note The axis vector is expected to be normalised.
|
||||
*
|
||||
* The result should be:
|
||||
*
|
||||
* \f[
|
||||
* \begin{bmatrix}
|
||||
* (1-a_x^2) \cos \theta + a_x^2 & a_x a_y (1 - \cos \theta) + a_z \sin \theta & a_z a_x (1 - \cos \theta) - a_y
|
||||
* \sin \theta & 0 \\
|
||||
* a_x a_y (1 - \cos \theta) - a_z \sin \theta & (1-a_y^2) \cos \theta + a_y^2 & a_y a_z (1 - \cos \theta) + a_x
|
||||
* \sin \theta & 0 \\
|
||||
* a_z a_x (1 - \cos \theta) + a_y \sin \theta & a_y a_z (1 - \cos \theta) - a_x \sin \theta & (1-a_z^2) \cos
|
||||
* \theta
|
||||
* + a_z^2 & 0 \\
|
||||
* t_x & t_y & t_z & 1
|
||||
* \end{bmatrix}
|
||||
* \f]
|
||||
*
|
||||
* @warning There is a significant bug in this function, which means it does not actually produce this correct rotation
|
||||
* matrix; see inline for details.
|
||||
*
|
||||
* @param[out] mtx Fixed-point matrix pointer to output to
|
||||
* @param[in] angle angle to rotate about axis
|
||||
* @param[in] axisX X component of axis to rotate about
|
||||
* @param[in] axisY Y component of axis to rotate about
|
||||
* @param[in] axisZ Z component of axis to rotate about
|
||||
*
|
||||
* @remark Original name: probably something like "suMtxMakeR" or "suMtxMakeRotateVector"
|
||||
*/
|
||||
void Mtx_SetRotationMtx(Mtx* mtx, s32 angle, f32 axisX, f32 axisY, f32 axisZ) {
|
||||
//! FAKE? The somewhat peculiar distribution of temps in this function seems necessary to match?
|
||||
f32 tempX;
|
||||
f32 tempZ;
|
||||
f32 tempY;
|
||||
f32 sin = Math_SinS(angle);
|
||||
f32 cos = Math_CosS(angle);
|
||||
f32 tempXX;
|
||||
f32 tempYY;
|
||||
f32 tempZZ;
|
||||
|
||||
s32 fixedPoint;
|
||||
|
||||
mtx->m[1][2] = 0; // [i30, i31] == [0, 0]
|
||||
mtx->m[1][3] = 1; // [i32, i33] == [0, 1]
|
||||
mtx->m[3][2] = 0; // [f30, f31] == [0, 0]
|
||||
mtx->m[3][3] = 0; // [f31, f32] == [0, 0]
|
||||
|
||||
tempXX = axisX * axisX;
|
||||
tempX = (axisY * axisZ) * (1.0f - cos);
|
||||
|
||||
// i00 and f00
|
||||
fixedPoint = (((1.0f - tempXX) * cos) + tempXX) * 0x10000;
|
||||
mtx->intPart[0][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[0][0] = fixedPoint & 0xFFFF;
|
||||
|
||||
tempZ = ((axisX * axisY) * (1.0f - cos));
|
||||
tempZZ = axisZ * axisZ;
|
||||
|
||||
// i21 and f21
|
||||
fixedPoint = (tempX - (axisX * sin)) * 0x10000;
|
||||
mtx->intPart[2][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[2][1] = fixedPoint & 0xFFFF;
|
||||
|
||||
tempY = (axisZ * axisX) * (1.0f - cos);
|
||||
tempYY = axisY * axisY;
|
||||
|
||||
// [i12, i13] and [f12, f13]
|
||||
fixedPoint = (tempX + (axisX * sin)) * 0x10000;
|
||||
mtx->m[0][3] = fixedPoint; // i13 dirty
|
||||
mtx->intPart[1][3] = 0; // clean i13
|
||||
mtx->m[2][3] = fixedPoint << 0x10;
|
||||
|
||||
// i11 and f11
|
||||
fixedPoint = ((((1.0f - tempYY) * cos) + tempYY) * 0x10000);
|
||||
mtx->intPart[1][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[1][1] = fixedPoint & 0xFFFF;
|
||||
|
||||
//! @bug The sign of the `axisY * sin` term is wrong on the next two elements (i/f20 and i/f02), which causes the
|
||||
//! matrix to not be a rotation matrix (and indeed not even necessarily invertible).
|
||||
// i20 and f20
|
||||
fixedPoint = (tempY - (axisY * sin)) * 0x10000;
|
||||
mtx->intPart[2][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[2][0] = fixedPoint & 0xFFFF;
|
||||
|
||||
// [i02, i03] and [f02, f03]
|
||||
fixedPoint = (tempY + (axisY * sin)) * 0x10000;
|
||||
mtx->m[0][1] = fixedPoint; // i03 dirty
|
||||
mtx->intPart[0][3] = 0; // clean i03
|
||||
mtx->m[2][1] = fixedPoint << 0x10;
|
||||
|
||||
// [i22, i23] and [f22, f23]
|
||||
fixedPoint = ((((1.0f - tempZZ) * cos) + tempZZ) * 0x10000);
|
||||
mtx->m[1][1] = fixedPoint; // i23 dirty
|
||||
mtx->intPart[2][3] = 0; // clean i23
|
||||
mtx->m[3][1] = fixedPoint << 0x10;
|
||||
|
||||
// i10 and f10
|
||||
fixedPoint = (tempZ - axisZ * sin) * 0x10000;
|
||||
mtx->intPart[1][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[1][0] = fixedPoint & 0xFFFF;
|
||||
|
||||
// i01 and f01
|
||||
fixedPoint = (tempZ + axisZ * sin) * 0x10000;
|
||||
mtx->intPart[0][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[0][1] = fixedPoint & 0xFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a general scale, rotation, translation matrix.
|
||||
*
|
||||
* @note The axis vector is expected to be normalised.
|
||||
*
|
||||
* The transformations are applied in the order scale, rotate, translate: \$f SRT \$f
|
||||
*
|
||||
* The result should be
|
||||
* \f[
|
||||
* \begin{bmatrix}
|
||||
* s_x((1-a_x^2) \cos \theta + a_x^2) & s_x(a_x a_y (1 - \cos \theta) + a_z \sin \theta) & s_x(a_z a_x (1 - \cos
|
||||
* \theta) - a_y \sin \theta & 0) \\
|
||||
* s_y(a_x a_y (1 - \cos \theta) - a_z \sin \theta) & s_y((1-a_y^2) \cos \theta + a_y^2) & s_z(a_y a_z (1 - \cos
|
||||
* \theta) + a_x \sin \theta) & 0 \\
|
||||
* s_z(a_z a_x (1 - \cos \theta) + a_y \sin \theta) & s_z(a_y a_z (1 - \cos \theta) - a_x \sin \theta) &
|
||||
* s_z((1-a_z^2) \cos \theta + a_z^2) & 0 \\
|
||||
* 0 & 0 & 0 & 1
|
||||
* \end{bmatrix} .
|
||||
* \f]
|
||||
*
|
||||
* @warning There is a significant bug in this function, which means it does not actually produce a proper rotation
|
||||
* matrix; see inline for details.
|
||||
*
|
||||
* @param[out] mtx Fixed-point matrix pointer to output to
|
||||
* @param[in] scaleX Scale in the X direction
|
||||
* @param[in] scaleY Scale in the Y direction
|
||||
* @param[in] scaleZ Scale in the Z direction
|
||||
* @param[in] angle angle to rotate about axis
|
||||
* @param[in] axisX X component of axis to rotate about
|
||||
* @param[in] axisY Y component of axis to rotate about
|
||||
* @param[in] axisZ Z component of axis to rotate about
|
||||
* @param[in] translateX X component of translation
|
||||
* @param[in] translateY Y component of translation
|
||||
* @param[in] translateZ Z component of translation
|
||||
*
|
||||
* @remark Original name: probably something like "suMtxMakeSRT", although Animal Forest function is a Tait-Bryan
|
||||
* rotation rather than axis-angle.
|
||||
*/
|
||||
void Mtx_SetTranslationRotationScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, s32 angle, f32 axisX, f32 axisY,
|
||||
f32 axisZ, f32 translateX, f32 translateY, f32 translateZ) {
|
||||
f32 tempX;
|
||||
f32 tempY;
|
||||
f32 tempZ;
|
||||
f32 sin = Math_SinS(angle);
|
||||
f32 cos = Math_CosS(angle);
|
||||
f32 tempXX = axisX * axisX;
|
||||
f32 tempYY = axisY * axisY;
|
||||
f32 tempZZ = axisZ * axisZ;
|
||||
s32 fixedPoint;
|
||||
|
||||
tempX = axisY * axisZ * (1.0f - cos);
|
||||
|
||||
// i00 and f00
|
||||
fixedPoint = (tempXX + (1.0f - tempXX) * cos) * scaleX * 0x10000;
|
||||
mtx->intPart[0][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[0][0] = fixedPoint & 0xFFFF;
|
||||
|
||||
tempY = axisZ * axisX * (1.0f - cos);
|
||||
|
||||
// i21 and f21
|
||||
fixedPoint = (tempX - axisX * sin) * scaleZ * 0x10000;
|
||||
mtx->intPart[2][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[2][1] = fixedPoint & 0xFFFF;
|
||||
|
||||
tempZ = axisX * axisY * (1.0f - cos);
|
||||
|
||||
// [i12, i13] and [f12, f13]
|
||||
fixedPoint = (tempX + axisX * sin) * scaleY * 0x10000;
|
||||
mtx->m[0][3] = fixedPoint; // i13 dirty
|
||||
mtx->intPart[1][3] = 0; // clean i13
|
||||
mtx->m[2][3] = fixedPoint << 0x10;
|
||||
|
||||
// i11 and f11
|
||||
fixedPoint = (tempYY + (1.0f - tempYY) * cos) * scaleY * 0x10000;
|
||||
mtx->intPart[1][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[1][1] = fixedPoint & 0xFFFF;
|
||||
|
||||
//! @bug The sign of the `axisY * sin` term is wrong on the next two elements (i/f20 and i/f02), which causes the
|
||||
//! matrix to not be a rotation matrix (and indeed not even necessarily invertible).
|
||||
// i20, f20
|
||||
fixedPoint = (tempY - axisY * sin) * scaleZ * 0x10000;
|
||||
mtx->intPart[2][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[2][0] = fixedPoint & 0xFFFF;
|
||||
|
||||
// [i02, i03] and [f02, f03]
|
||||
fixedPoint = (tempY + axisY * sin) * scaleX * 0x10000;
|
||||
mtx->m[0][1] = fixedPoint; // [i03, i03], i03 dirty
|
||||
mtx->intPart[0][3] = 0; // clean i03
|
||||
mtx->m[2][1] = fixedPoint << 0x10; // [f02, f03]
|
||||
|
||||
// [i22, i23] and [f22, f23]
|
||||
fixedPoint = (tempZZ + (1.0f - tempZZ) * cos) * scaleZ * 0x10000;
|
||||
mtx->m[1][1] = fixedPoint;
|
||||
mtx->intPart[2][3] = 0;
|
||||
mtx->m[3][1] = fixedPoint << 0x10;
|
||||
|
||||
// i10 and f10
|
||||
fixedPoint = (tempZ - axisZ * sin) * scaleY * 0x10000;
|
||||
mtx->intPart[1][0] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[1][0] = fixedPoint & 0xFFFF;
|
||||
|
||||
// i01 and f01
|
||||
fixedPoint = (tempZ + axisZ * sin) * scaleX * 0x10000;
|
||||
mtx->intPart[0][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF;
|
||||
mtx->fracPart[0][1] = fixedPoint & 0xFFFF;
|
||||
|
||||
// [i30, i31] and f30
|
||||
fixedPoint = translateX * 0x10000;
|
||||
mtx->m[1][2] = fixedPoint; // [i30, i31], i31 dirty
|
||||
mtx->fracPart[3][0] = fixedPoint & 0xFFFF; // f30
|
||||
|
||||
// i31 and f31
|
||||
fixedPoint = translateY * 0x10000;
|
||||
mtx->intPart[3][1] = ((u32)fixedPoint >> 0x10) & 0xFFFF; // overwrite i31
|
||||
mtx->fracPart[3][1] = fixedPoint & 0xFFFF; // overwrite f31
|
||||
|
||||
// [i32, i33] and [f32, f33]
|
||||
fixedPoint = translateZ * 0x10000;
|
||||
mtx->m[1][3] = fixedPoint; // [i32, i33]
|
||||
mtx->intPart[3][3] = 1; // clean i33
|
||||
mtx->m[3][3] = (fixedPoint << 0x10); // [f32, f33]
|
||||
}
|
|
@ -2353,10 +2353,8 @@ Actor* Actor_UpdateActor(UpdateActor_Params* params) {
|
|||
if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
||||
Actor_Kill(actor);
|
||||
} else {
|
||||
s32 tmp = (params->unk_08 == 0);
|
||||
|
||||
if (((params->unk_08) && !(actor->flags & params->unk_08)) ||
|
||||
((tmp = (params->unk_08 == 0)) &&
|
||||
((((!params->unk_08) != 0)) &&
|
||||
(!(actor->flags & ACTOR_FLAG_100000) ||
|
||||
((actor->category == ACTORCAT_EXPLOSIVES) && (params->player->stateFlags1 & PLAYER_STATE1_200))) &&
|
||||
(params->unkC != 0) && (actor != params->unk10) && ((actor != params->player->heldActor)) &&
|
||||
|
|
|
@ -235,6 +235,7 @@ void LifeMeter_Draw(PlayState* play) {
|
|||
if ((gSaveContext.save.playerData.health % 0x10) == 0) {
|
||||
fullHeartCount--;
|
||||
}
|
||||
|
||||
offsetY = 0.0f;
|
||||
offsetX = 0.0f;
|
||||
curColorSet = -1;
|
||||
|
@ -381,12 +382,13 @@ void LifeMeter_Draw(PlayState* play) {
|
|||
}
|
||||
}
|
||||
mtx = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
|
||||
func_801780F0(mtx, 1.0f - (0.32f * lifesize), 1.0f - (0.32f * lifesize), 1.0f - (0.32f * lifesize),
|
||||
-130.0f + offsetX, 94.5f - offsetY, 0.0f);
|
||||
Mtx_SetTranslateScaleMtx(mtx, 1.0f - (0.32f * lifesize), 1.0f - (0.32f * lifesize),
|
||||
1.0f - (0.32f * lifesize), -130.0f + offsetX, 94.5f - offsetY, 0.0f);
|
||||
gSPMatrix(OVERLAY_DISP++, mtx, G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPVertex(OVERLAY_DISP++, beatingHeartVtx, 4, 0);
|
||||
gSP1Quadrangle(OVERLAY_DISP++, 0, 2, 3, 1, 0);
|
||||
}
|
||||
|
||||
offsetX += 10.0f;
|
||||
if (i == 9) {
|
||||
offsetY += 10.0f;
|
||||
|
@ -423,10 +425,8 @@ u32 LifeMeter_IsCritical(void) {
|
|||
|
||||
if (gSaveContext.save.playerData.healthCapacity <= 0x50) {
|
||||
criticalThreshold = 0x10;
|
||||
|
||||
} else if (gSaveContext.save.playerData.healthCapacity <= 0xA0) {
|
||||
criticalThreshold = 0x18;
|
||||
|
||||
} else if (gSaveContext.save.playerData.healthCapacity <= 0xF0) {
|
||||
criticalThreshold = 0x20;
|
||||
} else {
|
||||
|
|
|
@ -15,9 +15,3 @@
|
|||
#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_8014090C.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140970.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140CE0.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140D04.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/code/z_vimode/func_80140D10.s")
|
||||
|
|
|
@ -15,8 +15,8 @@ void DmBal_Destroy(Actor* thisx, PlayState* play);
|
|||
void DmBal_Update(Actor* thisx, PlayState* play);
|
||||
void DmBal_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
void func_80C1EAC4(DmBal* this);
|
||||
void func_80C1EAD8(DmBal* this, PlayState* play);
|
||||
void DmBal_SetupDoNothing(DmBal* this);
|
||||
void DmBal_DoNothing(DmBal* this, PlayState* play);
|
||||
|
||||
ActorInit Dm_Bal_InitVars = {
|
||||
ACTOR_DM_BAL,
|
||||
|
@ -59,18 +59,18 @@ void DmBal_Init(Actor* thisx, PlayState* play) {
|
|||
Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4);
|
||||
this->timer = 60;
|
||||
this->eyeIndex = 0;
|
||||
this->unk_336 = 0;
|
||||
func_80C1EAC4(this);
|
||||
this->keepEyesShut = false;
|
||||
DmBal_SetupDoNothing(this);
|
||||
}
|
||||
|
||||
void DmBal_Destroy(Actor* thisx, PlayState* play) {
|
||||
}
|
||||
|
||||
void func_80C1EAC4(DmBal* this) {
|
||||
this->actionFunc = func_80C1EAD8;
|
||||
void DmBal_SetupDoNothing(DmBal* this) {
|
||||
this->actionFunc = DmBal_DoNothing;
|
||||
}
|
||||
|
||||
void func_80C1EAD8(DmBal* this, PlayState* play) {
|
||||
void DmBal_DoNothing(DmBal* this, PlayState* play) {
|
||||
}
|
||||
|
||||
void func_80C1EAE8(DmBal* this, PlayState* play) {
|
||||
|
@ -84,12 +84,12 @@ void func_80C1EAE8(DmBal* this, PlayState* play) {
|
|||
D_80C1F2C0 = play->csCtx.actorActions[actionIndex]->action;
|
||||
switch (play->csCtx.actorActions[actionIndex]->action) {
|
||||
case 1:
|
||||
this->unk_336 = 0;
|
||||
this->keepEyesShut = false;
|
||||
this->eyeIndex = 0;
|
||||
Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 0);
|
||||
break;
|
||||
case 2:
|
||||
this->unk_336 = 1;
|
||||
this->keepEyesShut = true;
|
||||
Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 12);
|
||||
break;
|
||||
case 3:
|
||||
|
@ -98,34 +98,34 @@ void func_80C1EAE8(DmBal* this, PlayState* play) {
|
|||
}
|
||||
} else if (D_80C1F2C0 == 3) {
|
||||
if (Animation_OnFrame(&this->skelAnime, 0.0f)) {
|
||||
this->unk_336 = 1;
|
||||
this->keepEyesShut = true;
|
||||
} else if (Animation_OnFrame(&this->skelAnime, 29.0f)) {
|
||||
this->unk_336 = 0;
|
||||
this->keepEyesShut = false;
|
||||
this->eyeIndex = 0;
|
||||
}
|
||||
}
|
||||
Cutscene_ActorTranslateAndYaw(&this->actor, play, actionIndex);
|
||||
this->actor.home.pos = this->actor.world.pos;
|
||||
} else {
|
||||
this->unk_336 = 0;
|
||||
this->keepEyesShut = false;
|
||||
this->eyeIndex = 0;
|
||||
D_80C1F2C0 = 0x63;
|
||||
}
|
||||
}
|
||||
|
||||
void func_80C1EC60(DmBal* this, PlayState* play) {
|
||||
f32 temp_fv1_2;
|
||||
f32 scaleX;
|
||||
|
||||
this->unk_338 += 0x320;
|
||||
this->unk_33A += 0x3E8;
|
||||
this->scale.y = this->scale.z = Math_CosS(this->unk_338) * 0.1f + 1.0f;
|
||||
temp_fv1_2 = (Math_SinS(this->unk_338) * 0.1f) + 1.0f;
|
||||
this->scale.x = SQ(temp_fv1_2);
|
||||
scaleX = (Math_SinS(this->unk_338) * 0.1f) + 1.0f;
|
||||
this->scale.x = SQ(scaleX);
|
||||
this->actor.world.pos.y = this->actor.home.pos.y + (Math_SinS(this->unk_338) * 25.0f);
|
||||
}
|
||||
|
||||
void func_80C1ED0C(DmBal* this) {
|
||||
if (this->unk_336 == 1) {
|
||||
void DmBal_UpdateEyes(DmBal* this) {
|
||||
if (this->keepEyesShut == true) {
|
||||
this->eyeIndex = 1;
|
||||
} else if (this->timer >= 4) {
|
||||
this->timer--;
|
||||
|
@ -138,38 +138,36 @@ void func_80C1ED0C(DmBal* this) {
|
|||
}
|
||||
}
|
||||
|
||||
void func_80C1ED64(DmBal* this, PlayState* play, Vec3f* arg2, Vec3f* arg3, f32 arg4) {
|
||||
Actor* paper = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PAPER, arg2->x, arg2->y, arg2->z, 0, 0, 0, 0);
|
||||
void DmBal_SpawnPaper(DmBal* this, PlayState* play, Vec3f* pos, Vec3f* vel, f32 gravity) {
|
||||
Actor* paper = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_PAPER, pos->x, pos->y, pos->z, 0, 0, 0, 0);
|
||||
|
||||
if (paper != NULL) {
|
||||
paper->velocity = *arg3;
|
||||
paper->gravity = arg4;
|
||||
paper->velocity = *vel;
|
||||
paper->gravity = gravity;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3f D_80C1F2C4 = { 0.0f, 9.0f, 0.0f };
|
||||
|
||||
void DmBal_Update(Actor* thisx, PlayState* play) {
|
||||
s32 pad;
|
||||
DmBal* this = THIS;
|
||||
Vec3f sp3C;
|
||||
Vec3f sp30;
|
||||
|
||||
// Throw confetti
|
||||
if (Animation_OnFrame(&this->skelAnime, 29.0f) && (this->skelAnime.animation == &object_bal_Anim_001804)) {
|
||||
sp3C = this->actor.world.pos;
|
||||
sp30 = D_80C1F2C4;
|
||||
sp3C.x += 7.0f * Math_SinS(this->actor.shape.rot.y);
|
||||
sp3C.y += 2.5f;
|
||||
sp3C.z += 7.0f * Math_CosS(this->actor.shape.rot.y);
|
||||
sp30.x = Math_SinS(this->actor.shape.rot.y) * 5.0f;
|
||||
sp30.z = Math_CosS(this->actor.shape.rot.y) * 5.0f;
|
||||
func_80C1ED64(this, play, &sp3C, &sp30, -0.4f);
|
||||
func_80C1ED64(this, play, &sp3C, &sp30, -0.5f);
|
||||
Vec3f pos = this->actor.world.pos;
|
||||
Vec3f vel = { 0.0f, 9.0f, 0.0f };
|
||||
|
||||
pos.x += 7.0f * Math_SinS(this->actor.shape.rot.y);
|
||||
pos.y += 2.5f;
|
||||
pos.z += 7.0f * Math_CosS(this->actor.shape.rot.y);
|
||||
vel.x = Math_SinS(this->actor.shape.rot.y) * 5.0f;
|
||||
vel.z = Math_CosS(this->actor.shape.rot.y) * 5.0f;
|
||||
DmBal_SpawnPaper(this, play, &pos, &vel, -0.4f);
|
||||
DmBal_SpawnPaper(this, play, &pos, &vel, -0.5f);
|
||||
}
|
||||
this->actionFunc(this, play);
|
||||
func_80C1EAE8(this, play);
|
||||
func_80C1EC60(this, play);
|
||||
func_80C1ED0C(this);
|
||||
DmBal_UpdateEyes(this);
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
}
|
||||
|
||||
|
@ -178,8 +176,8 @@ s32 DmBal_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p
|
|||
Vec3s rots;
|
||||
|
||||
if (limbIndex == 6) {
|
||||
rots.x = Math_SinS(this->unk_33A) * 3640.0f;
|
||||
rots.z = Math_CosS(this->unk_33A) * 3640.0f;
|
||||
rots.x = Math_SinS(this->unk_33A) * (0x10000 / 18);
|
||||
rots.z = Math_CosS(this->unk_33A) * (0x10000 / 18);
|
||||
Matrix_RotateZYX(rots.x, 0, rots.z, MTXMODE_APPLY);
|
||||
Matrix_Scale(this->scale.x, this->scale.y, this->scale.z, MTXMODE_APPLY);
|
||||
Matrix_RotateZS(-rots.z, MTXMODE_APPLY);
|
||||
|
|
|
@ -18,7 +18,7 @@ typedef struct DmBal {
|
|||
/* 0x19C */ Vec3s morphTable[OBJECT_BAL_LIMB_MAX];
|
||||
/* 0x328 */ UNK_TYPE1 pad_328[12];
|
||||
/* 0x334 */ s16 timer;
|
||||
/* 0x336 */ s16 unk_336;
|
||||
/* 0x336 */ s16 keepEyesShut;
|
||||
/* 0x338 */ s16 unk_338;
|
||||
/* 0x33A */ s16 unk_33A;
|
||||
} DmBal; /* size = 0x33C */
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
/*
|
||||
* File: z_en_paper.c
|
||||
/**
|
||||
* @file z_en_paper.c
|
||||
* Overlay: ovl_En_Paper
|
||||
* Description: Tingle Confetti
|
||||
* Description: Tingle confetti group
|
||||
*
|
||||
* Complex actor for its length, that creates and manages a group of confetti effects. Each is a triangle of a
|
||||
* particular colour, that rotates around a fixed axis at a randomly-chosen fixed velocity, and is subject to gravity,
|
||||
* drag and wind forces.
|
||||
*/
|
||||
|
||||
#include "z_en_paper.h"
|
||||
|
@ -16,12 +20,12 @@ void EnPaper_Destroy(Actor* thisx, PlayState* play);
|
|||
void EnPaper_Update(Actor* thisx, PlayState* play);
|
||||
void EnPaper_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
void func_80C1F480(EnPaper* this, PlayState* play);
|
||||
void func_80C1F4FC(EnPaper* this, PlayState* play);
|
||||
void func_80C1F46C(EnPaper* this);
|
||||
void func_80C1F4E8(EnPaper* this);
|
||||
void func_80C1F55C(EnPaper* this, EnPaperStruct* arg1);
|
||||
void func_80C1F6E0(EnPaper* this, EnPaperStruct* arg1);
|
||||
void EnPaper_SetupSpreadConfettiGroup(EnPaper* this);
|
||||
void EnPaper_SpreadConfettiGroup(EnPaper* this, PlayState* play);
|
||||
void EnPaper_SetupFlyConfettiGroup(EnPaper* this);
|
||||
void EnPaper_FlyConfettiGroup(EnPaper* this, PlayState* play);
|
||||
void EnPaper_InitConfettiPiece(EnPaper* this, EnPaperConfetto* piece);
|
||||
void EnPaper_FlyConfettiPiece(EnPaper* this, EnPaperConfetto* piece);
|
||||
|
||||
ActorInit En_Paper_InitVars = {
|
||||
ACTOR_EN_PAPER,
|
||||
|
@ -35,114 +39,155 @@ ActorInit En_Paper_InitVars = {
|
|||
(ActorFunc)EnPaper_Draw,
|
||||
};
|
||||
|
||||
Vec3f D_80C1FC60 = { 0.0f, 0.0f, 1.0f };
|
||||
static Vec3f sUnitVecZ = { 0.0f, 0.0f, 1.0f };
|
||||
|
||||
void EnPaper_Init(Actor* thisx, PlayState* play) {
|
||||
EnPaper* this = THIS;
|
||||
|
||||
Actor_SetScale(&this->actor, 0.01f);
|
||||
this->timer = 70;
|
||||
this->unk_D78 = D_80C1FC60;
|
||||
this->windForce = sUnitVecZ;
|
||||
Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4);
|
||||
func_80C1F46C(this);
|
||||
EnPaper_SetupSpreadConfettiGroup(this);
|
||||
}
|
||||
|
||||
void EnPaper_Destroy(Actor* thisx, PlayState* play) {
|
||||
}
|
||||
|
||||
void func_80C1F46C(EnPaper* this) {
|
||||
this->actionFunc = func_80C1F480;
|
||||
void EnPaper_SetupSpreadConfettiGroup(EnPaper* this) {
|
||||
this->actionFunc = EnPaper_SpreadConfettiGroup;
|
||||
}
|
||||
|
||||
void func_80C1F480(EnPaper* this, PlayState* play) {
|
||||
/**
|
||||
* Set up the pieces of confetti.
|
||||
*/
|
||||
void EnPaper_SpreadConfettiGroup(EnPaper* this, PlayState* play) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->unk_148); i++) {
|
||||
func_80C1F55C(this, &this->unk_148[i]);
|
||||
for (i = 0; i < ARRAY_COUNT(this->pieces); i++) {
|
||||
EnPaper_InitConfettiPiece(this, &this->pieces[i]);
|
||||
}
|
||||
|
||||
func_80C1F4E8(this);
|
||||
EnPaper_SetupFlyConfettiGroup(this);
|
||||
}
|
||||
|
||||
void func_80C1F4E8(EnPaper* this) {
|
||||
this->actionFunc = func_80C1F4FC;
|
||||
void EnPaper_SetupFlyConfettiGroup(EnPaper* this) {
|
||||
this->actionFunc = EnPaper_FlyConfettiGroup;
|
||||
}
|
||||
|
||||
void func_80C1F4FC(EnPaper* this, PlayState* play) {
|
||||
/**
|
||||
* Main action function for the group.
|
||||
*/
|
||||
void EnPaper_FlyConfettiGroup(EnPaper* this, PlayState* play) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->unk_148); i++) {
|
||||
func_80C1F6E0(this, &this->unk_148[i]);
|
||||
for (i = 0; i < ARRAY_COUNT(this->pieces); i++) {
|
||||
EnPaper_FlyConfettiPiece(this, &this->pieces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void func_80C1F55C(EnPaper* this, EnPaperStruct* arg1) {
|
||||
void EnPaper_InitConfettiPiece(EnPaper* this, EnPaperConfetto* piece) {
|
||||
// Pick rotation axis randomly (significantly biased towards the z = 0 plane)
|
||||
Matrix_RotateZYX(Rand_Next(), Rand_Next(), Rand_Next(), MTXMODE_NEW);
|
||||
Matrix_MultVec3f(&D_80C1FC60, &arg1->unk_0C);
|
||||
Matrix_MultVec3f(&sUnitVecZ, &piece->rotAxis);
|
||||
|
||||
arg1->unk_18 = this->actor.world.pos;
|
||||
// copy actor position and distribute uniformly in a cube of side 2 around it
|
||||
piece->pos = this->actor.world.pos;
|
||||
piece->pos.x += Rand_Centered() * 4.0f;
|
||||
piece->pos.y += Rand_Centered() * 4.0f;
|
||||
piece->pos.z += Rand_Centered() * 4.0f;
|
||||
|
||||
arg1->unk_18.x += Rand_Centered() * 4.0f;
|
||||
arg1->unk_18.y += Rand_Centered() * 4.0f;
|
||||
arg1->unk_18.z += Rand_Centered() * 4.0f;
|
||||
// copy actor velocity and distrbute uniformly in a cuboid with sides 9, 6, 9 with actor.velocity in the middle
|
||||
// of the base.
|
||||
piece->vel = this->actor.velocity;
|
||||
piece->vel.x += Rand_Centered() * 9.0f;
|
||||
piece->vel.y += Rand_ZeroOne() * 6.0f;
|
||||
piece->vel.z += Rand_Centered() * 9.0f;
|
||||
|
||||
arg1->unk_24 = this->actor.velocity;
|
||||
// Choose random starting angle and angular velocity
|
||||
piece->angle = Rand_Next();
|
||||
piece->angVel = (Rand_Next() >> 4) + (0x10000 / 180);
|
||||
|
||||
arg1->unk_24.x += Rand_Centered() * 9.0f;
|
||||
arg1->unk_24.y += Rand_ZeroOne() * 6.0f;
|
||||
arg1->unk_24.z += Rand_Centered() * 9.0f;
|
||||
|
||||
arg1->unk_30 = Rand_Next();
|
||||
arg1->unk_32 = (Rand_Next() >> 4) + 0x16C;
|
||||
|
||||
Matrix_RotateAxisS(arg1->unk_30, &arg1->unk_0C, MTXMODE_NEW);
|
||||
Matrix_MultVec3f(&D_80C1FC60, &arg1->unk_00);
|
||||
// Rotate the unit Z-vector by the random starting axis and angle
|
||||
Matrix_RotateAxisS(piece->angle, &piece->rotAxis, MTXMODE_NEW);
|
||||
Matrix_MultVec3f(&sUnitVecZ, &piece->normal);
|
||||
}
|
||||
|
||||
void func_80C1F6E0(EnPaper* this, EnPaperStruct* arg1) {
|
||||
f32 sp1C = Math_CosS(arg1->unk_30);
|
||||
f32 sp18 = Math_SinS(arg1->unk_30);
|
||||
f32 temp_ft4 = 1.0f - sp1C;
|
||||
/**
|
||||
* Main falling function for a single piece, handles dynamics.
|
||||
*
|
||||
* Position \f$ \mathbf{x} \f$ essentially satisfies discretised version of the equation
|
||||
*
|
||||
* \f[
|
||||
* \ddot{\mathbf{x}} = -0.2 \mathbf{n} (\dot{\mathbf{x}} + \mathbf{W}) + \mathbf{g} ,
|
||||
* \f]
|
||||
*
|
||||
* where
|
||||
*
|
||||
* - \f$ \mathbf{n} \f$ is the unit normal to the confetti triangle's plane
|
||||
* - \f$ \mathbf{W} \f$ is the random wind pressure
|
||||
* - \f$ \mathbf{g} \f$ is gravity
|
||||
*
|
||||
* and the product is componentwise: the normal is being used as a cross-sectional area measure rather than vectorially.
|
||||
*/
|
||||
void EnPaper_FlyConfettiPiece(EnPaper* this, EnPaperConfetto* piece) {
|
||||
f32 cos = Math_CosS(piece->angle);
|
||||
f32 sin = Math_SinS(piece->angle);
|
||||
f32 versin = 1.0f - cos;
|
||||
|
||||
if (arg1->unk_18.y < (this->actor.floorHeight - 40.0f)) {
|
||||
if (piece->pos.y < (this->actor.floorHeight - 40.0f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
arg1->unk_24.y += this->actor.gravity;
|
||||
// acceleration due to gravity
|
||||
piece->vel.y += this->actor.gravity;
|
||||
|
||||
arg1->unk_24.x -= 0.2f * fabsf(arg1->unk_00.x) * (arg1->unk_24.x + this->unk_D78.x);
|
||||
arg1->unk_24.y -= 0.2f * fabsf(arg1->unk_00.y) * (arg1->unk_24.y + this->unk_D78.y);
|
||||
arg1->unk_24.z -= 0.2f * fabsf(arg1->unk_00.z) * (arg1->unk_24.z + this->unk_D78.z);
|
||||
// drag and wind force: normal is used to simulate cross-section size of piece, although
|
||||
piece->vel.x -= 0.2f * fabsf(piece->normal.x) * (piece->vel.x + this->windForce.x);
|
||||
piece->vel.y -= 0.2f * fabsf(piece->normal.y) * (piece->vel.y + this->windForce.y);
|
||||
piece->vel.z -= 0.2f * fabsf(piece->normal.z) * (piece->vel.z + this->windForce.z);
|
||||
|
||||
arg1->unk_30 += arg1->unk_32;
|
||||
// rotate around axis
|
||||
piece->angle += piece->angVel;
|
||||
|
||||
arg1->unk_18.x += arg1->unk_24.x;
|
||||
arg1->unk_18.y += arg1->unk_24.y;
|
||||
arg1->unk_18.z += arg1->unk_24.z;
|
||||
// move
|
||||
piece->pos.x += piece->vel.x;
|
||||
piece->pos.y += piece->vel.y;
|
||||
piece->pos.z += piece->vel.z;
|
||||
|
||||
arg1->unk_00.x = (arg1->unk_0C.x * temp_ft4 * arg1->unk_0C.z) - (arg1->unk_0C.y * sp18);
|
||||
arg1->unk_00.y = (arg1->unk_0C.y * temp_ft4 * arg1->unk_0C.z) + (arg1->unk_0C.x * sp18);
|
||||
arg1->unk_00.z = (arg1->unk_0C.z * temp_ft4 * arg1->unk_0C.z) + sp1C;
|
||||
// Rotate unit Z vector about `axis` by `angle` to get forward direction. This is the same calculation as at the
|
||||
// bottom of EnPaper_InitConfettiPiece(), but done manually instead of using any matrix functions.
|
||||
piece->normal.x = (versin * piece->rotAxis.x * piece->rotAxis.z) - (piece->rotAxis.y * sin);
|
||||
piece->normal.y = (versin * piece->rotAxis.y * piece->rotAxis.z) + (piece->rotAxis.x * sin);
|
||||
piece->normal.z = (versin * piece->rotAxis.z * piece->rotAxis.z) + cos;
|
||||
}
|
||||
|
||||
void func_80C1F87C(EnPaper* this) {
|
||||
f32 sp2C = (Rand_Centered() * 4.0f) + 6.0f;
|
||||
f32 sp28;
|
||||
#define WIND_PITCH_BOUND (0x10000 / 12)
|
||||
|
||||
this->unk_D78.y = Math_SinS(this->actor.shape.rot.x) * -sp2C;
|
||||
/**
|
||||
* Sets the wind force for the whole group, using the shape.rot from the previous frame, and picks a new random one
|
||||
* for the next frame.
|
||||
*/
|
||||
void EnPaper_UpdateWind(EnPaper* this) {
|
||||
f32 strength = (Rand_Centered() * 4.0f) + 6.0f;
|
||||
f32 cosX;
|
||||
|
||||
sp28 = Math_CosS(this->actor.shape.rot.x) * -sp2C;
|
||||
this->unk_D78.x = Math_SinS(this->actor.shape.rot.y) * sp28;
|
||||
this->unk_D78.z = Math_CosS(this->actor.shape.rot.y) * sp28;
|
||||
this->windForce.y = Math_SinS(this->actor.shape.rot.x) * -strength;
|
||||
cosX = Math_CosS(this->actor.shape.rot.x) * -strength;
|
||||
this->windForce.x = Math_SinS(this->actor.shape.rot.y) * cosX;
|
||||
this->windForce.z = Math_CosS(this->actor.shape.rot.y) * cosX;
|
||||
|
||||
// New random wind direction. A uniform distribution of the angles in spherical coordinates is not uniformly
|
||||
// distributed on the sphere, so this is biased more towards up and down.
|
||||
this->actor.shape.rot.x += (s16)(Rand_Next() >> 8);
|
||||
this->actor.shape.rot.y += (s16)(Rand_Next() >> 6);
|
||||
|
||||
if (ABS_ALT(this->actor.shape.rot.x) > 0x1555) {
|
||||
// Essentially a clamp
|
||||
if (ABS_ALT(this->actor.shape.rot.x) > WIND_PITCH_BOUND) {
|
||||
if (this->actor.shape.rot.x > 0) {
|
||||
this->actor.shape.rot.x = 0x1555;
|
||||
this->actor.shape.rot.x = WIND_PITCH_BOUND;
|
||||
} else {
|
||||
this->actor.shape.rot.x = -0x1555;
|
||||
this->actor.shape.rot.x = -WIND_PITCH_BOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,8 +196,8 @@ void EnPaper_Update(Actor* thisx, PlayState* play) {
|
|||
EnPaper* this = THIS;
|
||||
|
||||
this->actionFunc(this, play);
|
||||
EnPaper_UpdateWind(this);
|
||||
|
||||
func_80C1F87C(this);
|
||||
if (this->timer == 0) {
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
|
@ -163,7 +208,7 @@ void EnPaper_Update(Actor* thisx, PlayState* play) {
|
|||
|
||||
void EnPaper_Draw(Actor* thisx, PlayState* play) {
|
||||
EnPaper* this = THIS;
|
||||
EnPaperStruct* ptr = this->unk_148;
|
||||
EnPaperConfetto* piece = this->pieces;
|
||||
s32 i;
|
||||
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
@ -174,7 +219,8 @@ void EnPaper_Draw(Actor* thisx, PlayState* play) {
|
|||
gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, SHADE, 0, 0, 0, SHADE, PRIMITIVE, 0, COMBINED, 0, 0, 0, 0, COMBINED);
|
||||
gSPLoadGeometryMode(POLY_OPA_DISP++, G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_LIGHTING | G_SHADING_SMOOTH);
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->unk_148); i++, ptr++) {
|
||||
for (i = 0; i < ARRAY_COUNT(this->pieces); i++, piece++) {
|
||||
// colour the first 30 white and 10 each of the other 3 colours
|
||||
if (i == 0) {
|
||||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
|
||||
} else if (i == 30) {
|
||||
|
@ -185,14 +231,15 @@ void EnPaper_Draw(Actor* thisx, PlayState* play) {
|
|||
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 64, 255, 128, 255);
|
||||
}
|
||||
|
||||
if ((this->actor.floorHeight - 40.0f) < ptr->unk_18.y) {
|
||||
MtxF* mf = GRAPH_ALLOC(play->state.gfxCtx, sizeof(MtxF));
|
||||
if ((this->actor.floorHeight - 40.0f) < piece->pos.y) {
|
||||
Mtx* mtx = GRAPH_ALLOC(play->state.gfxCtx, sizeof(Mtx));
|
||||
|
||||
func_8017842C(mf, this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, ptr->unk_30, ptr->unk_0C.x,
|
||||
ptr->unk_0C.y, ptr->unk_0C.z, ptr->unk_18.x, ptr->unk_18.y, ptr->unk_18.z);
|
||||
Mtx_SetTranslationRotationScaleMtx(mtx, this->actor.scale.x, this->actor.scale.y, this->actor.scale.z,
|
||||
piece->angle, piece->rotAxis.x, piece->rotAxis.y, piece->rotAxis.z,
|
||||
piece->pos.x, piece->pos.y, piece->pos.z);
|
||||
|
||||
gSPMatrix(POLY_OPA_DISP++, mf, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, object_bal_DL_00D5A0);
|
||||
gSPMatrix(POLY_OPA_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gTingleConfettiDL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,20 +7,22 @@ struct EnPaper;
|
|||
|
||||
typedef void (*EnPaperActionFunc)(struct EnPaper*, PlayState*);
|
||||
|
||||
#define ENPAPER_PIECES_COUNT 60
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ Vec3f unk_00;
|
||||
/* 0x0C */ Vec3f unk_0C;
|
||||
/* 0x18 */ Vec3f unk_18;
|
||||
/* 0x24 */ Vec3f unk_24;
|
||||
/* 0x30 */ s16 unk_30;
|
||||
/* 0x32 */ s16 unk_32;
|
||||
} EnPaperStruct; // size = 0x34
|
||||
/* 0x00 */ Vec3f normal; // normal to the plane of the confetti piece
|
||||
/* 0x0C */ Vec3f rotAxis; // axis to spin around
|
||||
/* 0x18 */ Vec3f pos;
|
||||
/* 0x24 */ Vec3f vel;
|
||||
/* 0x30 */ s16 angle; // angle to rotate around `rotAxis`
|
||||
/* 0x32 */ s16 angVel; // angular velocity of `angle`
|
||||
} EnPaperConfetto; // size = 0x34
|
||||
|
||||
typedef struct EnPaper {
|
||||
/* 0x000 */ Actor actor;
|
||||
/* 0x144 */ EnPaperActionFunc actionFunc;
|
||||
/* 0x148 */ EnPaperStruct unk_148[60];
|
||||
/* 0xD78 */ Vec3f unk_D78;
|
||||
/* 0x148 */ EnPaperConfetto pieces[ENPAPER_PIECES_COUNT];
|
||||
/* 0xD78 */ Vec3f windForce;
|
||||
/* 0xD84 */ s16 timer;
|
||||
} EnPaper; // size = 0xD88
|
||||
|
||||
|
|
|
@ -428,6 +428,7 @@
|
|||
0x8013EC10 : "z_rumble",
|
||||
0x8013EE60 : "z_view",
|
||||
0x80140260 : "z_vimode",
|
||||
0x80140CE0 : "code_80140CE0",
|
||||
0x80140E80 : "code_80140E80",
|
||||
0x801418B0 : "z_vismono",
|
||||
0x801420C0 : "code_801420C0",
|
||||
|
@ -464,6 +465,7 @@
|
|||
0x80174F10 : "padmgr",
|
||||
0x80176280 : "sched",
|
||||
0x80177390 : "speed_meter",
|
||||
0x801780F0 : "su_mtx",
|
||||
0x80178750 : "sys_cmpdma",
|
||||
0x80178F30 : "sys_initial_check",
|
||||
0x80179300 : "sys_math",
|
||||
|
@ -558,7 +560,7 @@
|
|||
0x801C5CB0 : "z_skelanime",
|
||||
0x801C5CD0 : "z_skin_matrix",
|
||||
0x801C5D10 : "z_sub_s",
|
||||
0x801C5DD0 : "z_vimode",
|
||||
0x801C5DD0 : "code_80140CE0",
|
||||
0x801C5E30 : "z_vr_box",
|
||||
0x801C5FC0 : "z_sram_NES",
|
||||
0x801C6A70 : "z_message",
|
||||
|
|
|
@ -3222,9 +3222,9 @@
|
|||
0x80177A84:("func_80177A84",),
|
||||
0x80177AC8:("func_80177AC8",),
|
||||
0x80177E58:("SpeedMeter_DrawAllocEntries",),
|
||||
0x801780F0:("func_801780F0",),
|
||||
0x801781EC:("func_801781EC",),
|
||||
0x8017842C:("func_8017842C",),
|
||||
0x801780F0:("Mtx_SetTranslateScaleMtx",),
|
||||
0x801781EC:("Mtx_SetRotationMtx",),
|
||||
0x8017842C:("Mtx_SetTranslationRotationScaleMtx",),
|
||||
0x80178750:("func_80178750",),
|
||||
0x80178818:("func_80178818",),
|
||||
0x80178978:("func_80178978",),
|
||||
|
@ -16990,25 +16990,25 @@
|
|||
0x80C1E84C:("EnEndingHero_Draw",),
|
||||
0x80C1E9E0:("DmBal_Init",),
|
||||
0x80C1EAB4:("DmBal_Destroy",),
|
||||
0x80C1EAC4:("func_80C1EAC4",),
|
||||
0x80C1EAD8:("func_80C1EAD8",),
|
||||
0x80C1EAC4:("DmBal_SetupDoNothing",),
|
||||
0x80C1EAD8:("DmBal_DoNothing",),
|
||||
0x80C1EAE8:("func_80C1EAE8",),
|
||||
0x80C1EC60:("func_80C1EC60",),
|
||||
0x80C1ED0C:("func_80C1ED0C",),
|
||||
0x80C1ED64:("func_80C1ED64",),
|
||||
0x80C1ED0C:("DmBal_UpdateEyes",),
|
||||
0x80C1ED64:("DmBal_SpawnPaper",),
|
||||
0x80C1EDE4:("DmBal_Update",),
|
||||
0x80C1EF80:("DmBal_OverrideLimbDraw",),
|
||||
0x80C1F060:("DmBal_PostLimbDraw",),
|
||||
0x80C1F078:("DmBal_Draw",),
|
||||
0x80C1F3D0:("EnPaper_Init",),
|
||||
0x80C1F45C:("EnPaper_Destroy",),
|
||||
0x80C1F46C:("func_80C1F46C",),
|
||||
0x80C1F480:("func_80C1F480",),
|
||||
0x80C1F4E8:("func_80C1F4E8",),
|
||||
0x80C1F4FC:("func_80C1F4FC",),
|
||||
0x80C1F55C:("func_80C1F55C",),
|
||||
0x80C1F6E0:("func_80C1F6E0",),
|
||||
0x80C1F87C:("func_80C1F87C",),
|
||||
0x80C1F46C:("EnPaper_SetupSpreadConfettiGroup",),
|
||||
0x80C1F480:("EnPaper_SpreadConfettiGroup",),
|
||||
0x80C1F4E8:("EnPaper_SetupFlyConfettiGroup",),
|
||||
0x80C1F4FC:("EnPaper_FlyConfettiGroup",),
|
||||
0x80C1F55C:("EnPaper_InitConfettiPiece",),
|
||||
0x80C1F6E0:("EnPaper_FlyConfettiPiece",),
|
||||
0x80C1F87C:("EnPaper_UpdateWind",),
|
||||
0x80C1F97C:("EnPaper_Update",),
|
||||
0x80C1F9D0:("EnPaper_Draw",),
|
||||
0x80C1FCF0:("EnHintSkb_Init",),
|
||||
|
|
Loading…
Reference in New Issue