Skip to content

Commit

Permalink
fix interpolation for kankyo particles and effects
Browse files Browse the repository at this point in the history
  • Loading branch information
Archez committed Nov 28, 2024
1 parent 77d69c5 commit e7bd18a
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 16 deletions.
34 changes: 28 additions & 6 deletions mm/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ void DemoKakyo_LostWoodsSparkleActionFunc(DemoKankyo* this, PlayState* play) {
this->effects[i].posOffset.z = 0.0f;
this->effects[i].posBase.z = posCenterZ + repositionLimit;
}

// 2S2H [Interpolation] Skip particle interpolation on next frame
this->effects[i].epoch++;
}
break;

Expand Down Expand Up @@ -396,10 +399,17 @@ void DemoKakyo_MoonSparklesActionFunc(DemoKankyo* this, PlayState* play) {
}

if (((this->effects[i].posBase.x + this->effects[i].posOffset.x) - newEye.x) > halfScreenHeight) {
// 2S2H [Interpolation] Here and below, skip particle interpolation on next frame when positionmoves
if (ABS(this->effects[i].posBase.x - (newEye.x - halfScreenHeight)) >= 120.0f) {
this->effects[i].epoch++;
}
this->effects[i].posBase.x = newEye.x - halfScreenHeight;
}

if (((this->effects[i].posBase.x + this->effects[i].posOffset.x) - newEye.x) < -halfScreenHeight) {
if (ABS(this->effects[i].posBase.x - (newEye.x + halfScreenHeight)) >= 120.0f) {
this->effects[i].epoch++;
}
this->effects[i].posBase.x = newEye.x + halfScreenHeight;
}

Expand All @@ -413,18 +423,30 @@ void DemoKakyo_MoonSparklesActionFunc(DemoKankyo* this, PlayState* play) {

// I think this code is shifting the effects 1 frame -> half screen at a time to keep it in-view
if (halfScreenWidth < ((this->effects[i].posBase.y + this->effects[i].posOffset.y) - newEye.y)) {
if (ABS(this->effects[i].posBase.y - (newEye.y - halfScreenWidth)) >= 120.0f) {
this->effects[i].epoch++;
}
this->effects[i].posBase.y = newEye.y - halfScreenWidth;
}

if (((this->effects[i].posBase.y + this->effects[i].posOffset.y) - newEye.y) < -halfScreenWidth) {
if (ABS(this->effects[i].posBase.y - (newEye.y + halfScreenWidth)) >= 120.0f) {
this->effects[i].epoch++;
}
this->effects[i].posBase.y = newEye.y + halfScreenWidth;
}

if (((this->effects[i].posBase.z + this->effects[i].posOffset.z) - newEye.z) > halfScreenHeight) {
if (ABS(this->effects[i].posBase.z - (newEye.z - halfScreenHeight)) >= 120.0f) {
this->effects[i].epoch++;
}
this->effects[i].posBase.z = newEye.z - halfScreenHeight;
}

if (((this->effects[i].posBase.z + this->effects[i].posOffset.z) - newEye.z) < -halfScreenHeight) {
if (ABS(this->effects[i].posBase.z - (newEye.z + halfScreenHeight)) >= 120.0f) {
this->effects[i].epoch++;
}
this->effects[i].posBase.z = newEye.z + halfScreenHeight;
}

Expand Down Expand Up @@ -516,7 +538,6 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL);

for (i = 0; i < play->envCtx.precipitation[PRECIP_SNOW_MAX]; i++) {
FrameInterpolation_RecordOpenChild(this, i);
worldPos.x = this->effects[i].posBase.x + this->effects[i].posOffset.x;
worldPos.y = this->effects[i].posBase.y + this->effects[i].posOffset.y;
worldPos.z = this->effects[i].posBase.z + this->effects[i].posOffset.z;
Expand All @@ -530,11 +551,12 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
xMin = OTRGetDimensionFromLeftEdge(xMin);
xMax = OTRGetDimensionFromRightEdge(xMax);
}
// #pragma endregion
// #endregion

// checking if particle is on screen
if ((screenPos.x >= xMin) && (screenPos.x < xMax) && (screenPos.y >= 0.0f) &&
(screenPos.y < SCREEN_HEIGHT)) {
FrameInterpolation_RecordOpenChild(&this->effects[i], this->effects[i].epoch);
Matrix_Translate(worldPos.x, worldPos.y, worldPos.z, MTXMODE_NEW);
scaleAlpha = this->effects[i].alpha / 50.0f;
if (scaleAlpha > 1.0f) {
Expand Down Expand Up @@ -591,8 +613,8 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL);
FrameInterpolation_RecordCloseChild();
}
FrameInterpolation_RecordCloseChild();
}

CLOSE_DISPS(play->state.gfxCtx);
Expand All @@ -617,7 +639,6 @@ void DemoKankyo_DrawMoonAndGiant(Actor* thisx, PlayState* play2) {
Gfx_SetupDL25_Xlu(gfxCtx);

for (i = 0; i < play->envCtx.precipitation[PRECIP_SNOW_MAX]; i++) {
FrameInterpolation_RecordOpenChild(this, i);
worldPos.x = this->effects[i].posBase.x + this->effects[i].posOffset.x;
worldPos.y = this->effects[i].posBase.y + this->effects[i].posOffset.y;
worldPos.z = this->effects[i].posBase.z + this->effects[i].posOffset.z;
Expand All @@ -631,11 +652,12 @@ void DemoKankyo_DrawMoonAndGiant(Actor* thisx, PlayState* play2) {
xMin = OTRGetDimensionFromLeftEdge(xMin);
xMax = OTRGetDimensionFromRightEdge(xMax);
}
// #pragma endregion
// #endregion

// checking if effect is on screen
if ((screenPos.x >= xMin) && (screenPos.x < xMax) && (screenPos.y >= 0.0f) &&
(screenPos.y < SCREEN_HEIGHT)) {
FrameInterpolation_RecordOpenChild(&this->effects[i], this->effects[i].epoch);
Matrix_Translate(worldPos.x, worldPos.y, worldPos.z, MTXMODE_NEW);
alphaScale = this->effects[i].alpha / 50.0f;
if (alphaScale > 1.0f) {
Expand Down Expand Up @@ -680,8 +702,8 @@ void DemoKankyo_DrawMoonAndGiant(Actor* thisx, PlayState* play2) {
} else {
gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL);
}
FrameInterpolation_RecordCloseChild();
}
FrameInterpolation_RecordCloseChild();
}

CLOSE_DISPS(gfxCtx);
Expand Down
2 changes: 2 additions & 0 deletions mm/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ typedef struct {
/* 0x4A */ u16 LostWoodsSkyFishPosOffsetMax; // The x-z range the lost woods skyfish oscillates around player. random value between 15-65
/* 0x4C */ f32 LostWoodsSkyFishSpeedY; // the y speed (angular velocity) the lost woods skyfish oscillates around player.
/* 0x50 */ u16 pad50; // unused, always assigned to 0, nothing else in this actor uses it
// 2S2H [Port]
/* */ s16 epoch; // Tracks when an effect is reset for use with interpolation skipping
} DemoKankyoEffect; // size = 0x54

#define DEMOKANKYO_EFFECT_COUNT 64
Expand Down
38 changes: 28 additions & 10 deletions mm/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ void func_808DC454(ObjectKankyo* this, PlayState* play) {
this->unk_14C[i].unk_18 = (Rand_ZeroOne() * 3.0f) + 8.0f;
}
this->unk_14C[i].unk_1C++;
this->unk_14C[i].epoch++;
break;

case 1:
Expand Down Expand Up @@ -280,10 +281,12 @@ void func_808DC454(ObjectKankyo* this, PlayState* play) {

if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f24) > temp_120) {
this->unk_14C[i].unk_00 = temp_f24 - temp_120;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f24) < -temp_120) {
this->unk_14C[i].unk_00 = temp_f24 + temp_120;
this->unk_14C[i].epoch++;
}

sp88.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C;
Expand All @@ -296,18 +299,22 @@ void func_808DC454(ObjectKankyo* this, PlayState* play) {

if (temp_f0_4 < (this->unk_14C[i].unk_04 + (this->unk_14C[i].unk_10) - temp_f28)) {
this->unk_14C[i].unk_04 = temp_f28 - temp_f0_4;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) - temp_f28) < -temp_f0_4) {
this->unk_14C[i].unk_04 = temp_f28 + temp_f0_4;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f30) > temp_120) {
this->unk_14C[i].unk_08 = temp_f30 - temp_120;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f30) < -temp_120) {
this->unk_14C[i].unk_08 = temp_f30 + temp_120;
this->unk_14C[i].epoch++;
}

if ((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) < ((play->view.eye.y - temp_f22) - 40.0f)) {
Expand Down Expand Up @@ -406,6 +413,7 @@ void func_808DCDB4(ObjectKankyo* this, PlayState* play) {
this->unk_14C[i].unk_14 = (Rand_ZeroOne() - 0.5f) * (temp_120 * 2.0f);
this->unk_14C[i].unk_18 = Rand_ZeroOne() + 0.2f;
this->unk_14C[i].unk_1C++;
this->unk_14C[i].epoch++;
break;

case 1:
Expand Down Expand Up @@ -447,26 +455,32 @@ void func_808DCDB4(ObjectKankyo* this, PlayState* play) {

if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f26) > temp_80) {
this->unk_14C[i].unk_00 = temp_f26 - temp_80;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f26) < -temp_80) {
this->unk_14C[i].unk_00 = temp_f26 + temp_80;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) - temp_f28) > temp_80) {
this->unk_14C[i].unk_04 = temp_f28 - temp_80;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) - temp_f28) < -temp_80) {
this->unk_14C[i].unk_04 = temp_f28 + temp_80;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f18) > temp_80) {
this->unk_14C[i].unk_08 = temp_f18 - temp_80;
this->unk_14C[i].epoch++;
}

if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f18) < -temp_80) {
this->unk_14C[i].unk_08 = temp_f18 + temp_80;
this->unk_14C[i].epoch++;
}
break;
}
Expand Down Expand Up @@ -541,7 +555,7 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {
worldPos.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C;
worldPos.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10;
worldPos.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14;
FrameInterpolation_RecordOpenChild(this, i);

Play_GetScreenPos(play, &worldPos, &screenPos);

// #region 2S2H [Cosmetic] Increase snow render area for widescreen
Expand All @@ -551,9 +565,10 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {
xMin = OTRGetDimensionFromLeftEdge(xMin);
xMax = OTRGetDimensionFromRightEdge(xMax);
}
// #pragma endregion
// #endregion

if ((screenPos.x >= xMin) && (screenPos.x < xMax) && (screenPos.y >= 0.0f) && (screenPos.y < SCREEN_HEIGHT)) {
FrameInterpolation_RecordOpenChild(&this->unk_14C[i], this->unk_14C[i].epoch);
if (!spB4) {
spB4 = true;

Expand All @@ -573,6 +588,7 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {
Matrix_Scale(0.05f + tempf, 0.05f + tempf, 0.05f + tempf, MTXMODE_APPLY);
temp_f2 = Math_Vec3f_DistXYZ(&worldPos, &play->view.eye) / 300.0f;
temp_f2 = ((1.0f < temp_f2) ? 0.0f : (((1.0f - temp_f2) > 1.0f) ? 1.0f : 1.0f - temp_f2));
temp_f2 = 1.59375f;

gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)(160.0f * temp_f2));
Expand All @@ -581,8 +597,8 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {

gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gEffDustDL);
FrameInterpolation_RecordCloseChild();
}
FrameInterpolation_RecordCloseChild();
}

CLOSE_DISPS(play->state.gfxCtx);
Expand Down Expand Up @@ -624,7 +640,7 @@ void func_808DD970(Actor* thisx, PlayState* play2) {
worldPos.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C;
worldPos.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10;
worldPos.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14;
FrameInterpolation_RecordOpenChild(this, i);

Play_GetScreenPos(play, &worldPos, &screenPos);

// #region 2S2H [Cosmetic] Increase deep underwater dust render area for widescreen
Expand All @@ -634,13 +650,15 @@ void func_808DD970(Actor* thisx, PlayState* play2) {
xMin = OTRGetDimensionFromLeftEdge(xMin);
xMax = OTRGetDimensionFromRightEdge(xMax);
}
// #pragma endregion
// #endregion

if ((screenPos.x >= xMin) && (screenPos.x < xMax) && (screenPos.y >= 0.0f) && (screenPos.y < SCREEN_HEIGHT)) {
FrameInterpolation_RecordOpenChild(&this->unk_14C[i], this->unk_14C[i].epoch);
Matrix_Translate(worldPos.x, worldPos.y, worldPos.z, MTXMODE_NEW);
Matrix_Scale(0.03f, 0.03f, 0.03f, MTXMODE_APPLY);
temp_f0 = Math_Vec3f_DistXYZ(&worldPos, &play->view.eye);
temp_f0 = (u8)(255.0f * phi_f26) * (1.0f - (temp_f0 / 300.0f));
temp_f0 = 255;

gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 55, temp_f0);
Expand All @@ -657,8 +675,8 @@ void func_808DD970(Actor* thisx, PlayState* play2) {
gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_CLD_SURF2);
gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG);
gSPDisplayList(POLY_XLU_DISP++, gEffDustDL);
FrameInterpolation_RecordCloseChild();
}
FrameInterpolation_RecordCloseChild();
}

CLOSE_DISPS(play->state.gfxCtx);
Expand Down Expand Up @@ -693,8 +711,8 @@ void func_808DDE9C(Actor* thisx, PlayState* play2) {
temp_f22 = this->unk_14C[0].unk_04 + ((Rand_ZeroOne() - 0.7f) * this->unk_144);
temp_f2 = this->unk_14C[0].unk_08 + ((Rand_ZeroOne() - 0.7f) * this->unk_144);

FrameInterpolation_RecordOpenChild(this, i);
if (!((temp_f20 < -252.0f) && (temp_f20 > -500.0f) && (temp_f2 > 3820.0f) && (temp_f2 < 4150.0f))) {
FrameInterpolation_RecordOpenChild(this, i);
Matrix_Translate(temp_f20, temp_f22, temp_f2, MTXMODE_NEW);

gSPMatrix(POLY_XLU_DISP++, D_01000000_TO_SEGMENTED, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
Expand All @@ -710,14 +728,13 @@ void func_808DDE9C(Actor* thisx, PlayState* play2) {

gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFallingRainDropDL);
FrameInterpolation_RecordCloseChild();
}
FrameInterpolation_RecordCloseChild();
}

phi_s5 = false;
if (player->actor.floorHeight < play->view.eye.y) {
for (i = 0; i < end; i++) {
FrameInterpolation_RecordOpenChild(this, i + end);
if (!phi_s5) {
Gfx_SetupDL25_Xlu(play->state.gfxCtx);

Expand All @@ -731,15 +748,16 @@ void func_808DDE9C(Actor* thisx, PlayState* play2) {
temp_f2 = this->unk_14C[1].unk_08 + (func_808DDE74() * 220.0f);

if (!((temp_f20 < -252.0f) && (temp_f20 > -500.0f) && (temp_f2 > 3820.0f) && (temp_f2 < 4150.0f))) {
FrameInterpolation_RecordOpenChild(this, i + end);
Matrix_Translate(temp_f20, temp_f22, temp_f2, MTXMODE_NEW);
temp_f12 = (Rand_ZeroOne() * 0.05f) + 0.05f;
Matrix_Scale(temp_f12, temp_f12, temp_f12, MTXMODE_APPLY);

gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gEffShockwaveDL);
FrameInterpolation_RecordCloseChild();
}
FrameInterpolation_RecordCloseChild();
}
}

Expand Down
2 changes: 2 additions & 0 deletions mm/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ typedef struct {
/* 0x14 */ f32 unk_14;
/* 0x18 */ f32 unk_18;
/* 0x1C */ u8 unk_1C;
// 2S2H [Port]
/* */ s16 epoch; // Tracks when an effect is reset for use with interpolation skipping
} ObjectKankyoStruct; // size = 0x20

typedef struct ObjectKankyo {
Expand Down

0 comments on commit e7bd18a

Please sign in to comment.