WIP: uncapped framerate 3

This commit is contained in:
MysterD 2022-04-27 18:25:43 -07:00
parent e8fe92bdad
commit 02ab54b3ad
13 changed files with 437 additions and 260 deletions

View file

@ -11,6 +11,7 @@
#include "audio/external.h" #include "audio/external.h"
#include "textures.h" #include "textures.h"
#include "game/rendering_graph_node.h" #include "game/rendering_graph_node.h"
#include "pc/utils/misc.h"
/** /**
* This file implements environment effects that are not snow: * This file implements environment effects that are not snow:
@ -36,17 +37,26 @@ Vtx_t gBubbleTempVtx[3] = {
{ { 0, 0, 0 }, 0, { -498, 964 }, { 0xFF, 0xFF, 0xFF, 0xFF } }, { { 0, 0, 0 }, 0, { -498, 964 }, { 0xFF, 0xFF, 0xFF, 0xFF } },
}; };
static Gfx sGfxSaved[60 / 5]; Gfx *envfx_update_bubble_particles_internal(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated);
static Gfx *sBubbleInterpolatedDisplayListPos[60 / 5];
static Vec3s sPrevBubblePositions[60];
void patch_interpolated_bubble_particles(void) { static s32 sBubbleGfxMode;
s32 i; static Gfx* sBubbleGfxPos;
for (i = 0; i < 60 / 5; i++) { static Vtx* sBubbleInternalGfxPos[65 / 5];
if (sBubbleInterpolatedDisplayListPos[i] != NULL) { static Vec3s sBubbleGfxCamFrom;
*sBubbleInterpolatedDisplayListPos[i] = sGfxSaved[i]; static Vec3s sBubbleGfxCamTo;
sBubbleInterpolatedDisplayListPos[i] = NULL;
void patch_bubble_particles_before(void) {
if (sBubbleGfxPos) {
for (s32 i = 0; i < sBubbleParticleMaxCount; i++) {
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} }
sBubbleGfxPos = NULL;
}
}
void patch_bubble_particles_interpolated(UNUSED f32 delta) {
if (sBubbleGfxPos) {
envfx_update_bubble_particles_internal(sBubbleGfxMode, NULL, sBubbleGfxCamFrom, sBubbleGfxCamTo, true);
} }
} }
@ -103,6 +113,7 @@ void envfx_update_flower(Vec3s centerPos) {
(gEnvFxBuffer + i)->zPos, &floorGeo); (gEnvFxBuffer + i)->zPos, &floorGeo);
(gEnvFxBuffer + i)->isAlive = 1; (gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->animFrame = random_float() * 5.0f; (gEnvFxBuffer + i)->animFrame = random_float() * 5.0f;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else if ((timer & 0x03) == 0) { } else if ((timer & 0x03) == 0) {
(gEnvFxBuffer + i)->animFrame += 1; (gEnvFxBuffer + i)->animFrame += 1;
if ((gEnvFxBuffer + i)->animFrame > 5) { if ((gEnvFxBuffer + i)->animFrame > 5) {
@ -147,8 +158,7 @@ void envfx_set_lava_bubble_position(s32 index, Vec3s centerPos) {
(gEnvFxBuffer + index)->zPos = -16000 - (gEnvFxBuffer + index)->zPos; (gEnvFxBuffer + index)->zPos = -16000 - (gEnvFxBuffer + index)->zPos;
} }
floorY = floorY = find_floor((gEnvFxBuffer + index)->xPos, centerY + 500, (gEnvFxBuffer + index)->zPos, &surface);
find_floor((gEnvFxBuffer + index)->xPos, centerY + 500, (gEnvFxBuffer + index)->zPos, &surface);
if (surface == NULL) { if (surface == NULL) {
(gEnvFxBuffer + index)->yPos = FLOOR_LOWER_LIMIT_MISC; (gEnvFxBuffer + index)->yPos = FLOOR_LOWER_LIMIT_MISC;
return; return;
@ -178,6 +188,7 @@ void envfx_update_lava(Vec3s centerPos) {
for (i = 0; i < sBubbleParticleMaxCount; i++) { for (i = 0; i < sBubbleParticleMaxCount; i++) {
if ((gEnvFxBuffer + i)->isAlive == 0) { if ((gEnvFxBuffer + i)->isAlive == 0) {
envfx_set_lava_bubble_position(i, centerPos); envfx_set_lava_bubble_position(i, centerPos);
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
(gEnvFxBuffer + i)->isAlive = 1; (gEnvFxBuffer + i)->isAlive = 1;
} else if ((timer & 0x01) == 0) { } else if ((timer & 0x01) == 0) {
(gEnvFxBuffer + i)->animFrame += 1; (gEnvFxBuffer + i)->animFrame += 1;
@ -257,10 +268,13 @@ void envfx_update_whirlpool(void) {
(gEnvFxBuffer + i)->unusedBubbleVar = 0; (gEnvFxBuffer + i)->unusedBubbleVar = 0;
(gEnvFxBuffer + i)->isAlive = 1; (gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos, envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos,
&(gEnvFxBuffer + i)->zPos); &(gEnvFxBuffer + i)->zPos);
} else { }
if ((gEnvFxBuffer + i)->isAlive != 0) {
(gEnvFxBuffer + i)->angleAndDist[1] -= 40; (gEnvFxBuffer + i)->angleAndDist[1] -= 40;
(gEnvFxBuffer + i)->angleAndDist[0] += (gEnvFxBuffer + i)->angleAndDist[0] +=
(s16)(3000 - (gEnvFxBuffer + i)->angleAndDist[1] * 2) + 0x400; (s16)(3000 - (gEnvFxBuffer + i)->angleAndDist[1] * 2) + 0x400;
@ -307,15 +321,11 @@ void envfx_update_jetstream(void) {
if ((gEnvFxBuffer + i)->isAlive == 0) { if ((gEnvFxBuffer + i)->isAlive == 0) {
(gEnvFxBuffer + i)->angleAndDist[1] = random_float() * 300.0f; (gEnvFxBuffer + i)->angleAndDist[1] = random_float() * 300.0f;
(gEnvFxBuffer + i)->angleAndDist[0] = random_u16(); (gEnvFxBuffer + i)->angleAndDist[0] = random_u16();
(gEnvFxBuffer + i)->xPos = (gEnvFxBuffer + i)->xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] (gEnvFxBuffer + i)->zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
+ sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; (gEnvFxBuffer + i)->yPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 400.0f - 200.0f);
(gEnvFxBuffer + i)->zPos =
gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z]
+ coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
(gEnvFxBuffer + i)->yPos =
gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 400.0f - 200.0f);
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else { } else {
(gEnvFxBuffer + i)->angleAndDist[1] += 10; (gEnvFxBuffer + i)->angleAndDist[1] += 10;
(gEnvFxBuffer + i)->xPos += sins((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f; (gEnvFxBuffer + i)->xPos += sins((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f;
@ -381,31 +391,31 @@ s32 envfx_init_bubble(s32 mode) {
* Also sets the given vertices to the correct shape for each mode, * Also sets the given vertices to the correct shape for each mode,
* though they are not being rotated yet. * though they are not being rotated yet.
*/ */
void envfx_bubbles_update_switch(s32 mode, Vec3s camTo, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3) { void envfx_bubbles_update_switch(s32 mode, Vec3s camTo, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3, u8 interpolated) {
switch (mode) { switch (mode) {
case ENVFX_FLOWERS: case ENVFX_FLOWERS:
envfx_update_flower(camTo); if (!interpolated) { envfx_update_flower(camTo); }
vertex1[0] = 50; vertex1[1] = 0; vertex1[2] = 0; vertex1[0] = 50; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 75; vertex2[2] = 0; vertex2[0] = 0; vertex2[1] = 75; vertex2[2] = 0;
vertex3[0] = -50; vertex3[1] = 0; vertex3[2] = 0; vertex3[0] = -50; vertex3[1] = 0; vertex3[2] = 0;
break; break;
case ENVFX_LAVA_BUBBLES: case ENVFX_LAVA_BUBBLES:
envfx_update_lava(camTo); if (!interpolated) { envfx_update_lava(camTo); }
vertex1[0] = 100; vertex1[1] = 0; vertex1[2] = 0; vertex1[0] = 100; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 150; vertex2[2] = 0; vertex2[0] = 0; vertex2[1] = 150; vertex2[2] = 0;
vertex3[0] = -100; vertex3[1] = 0; vertex3[2] = 0; vertex3[0] = -100; vertex3[1] = 0; vertex3[2] = 0;
break; break;
case ENVFX_WHIRLPOOL_BUBBLES: case ENVFX_WHIRLPOOL_BUBBLES:
envfx_update_whirlpool(); if (!interpolated) { envfx_update_whirlpool(); }
vertex1[0] = 40; vertex1[1] = 0; vertex1[2] = 0; vertex1[0] = 40; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 60; vertex2[2] = 0; vertex2[0] = 0; vertex2[1] = 60; vertex2[2] = 0;
vertex3[0] = -40; vertex3[1] = 0; vertex3[2] = 0; vertex3[0] = -40; vertex3[1] = 0; vertex3[2] = 0;
break; break;
case ENVFX_JETSTREAM_BUBBLES: case ENVFX_JETSTREAM_BUBBLES:
envfx_update_jetstream(); if (!interpolated) { envfx_update_jetstream(); }
vertex1[0] = 40; vertex1[1] = 0; vertex1[2] = 0; vertex1[0] = 40; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 60; vertex2[2] = 0; vertex2[0] = 0; vertex2[1] = 60; vertex2[2] = 0;
vertex3[0] = -40; vertex3[1] = 0; vertex3[2] = 0; vertex3[0] = -40; vertex3[1] = 0; vertex3[2] = 0;
@ -419,9 +429,15 @@ void envfx_bubbles_update_switch(s32 mode, Vec3s camTo, Vec3s vertex1, Vec3s ver
* that will be translated to bubble positions to draw the bubble image * that will be translated to bubble positions to draw the bubble image
*/ */
void append_bubble_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3, void append_bubble_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3,
Vtx *template) { Vtx *template, u8 interpolated) {
s32 i = 0; s32 i = 0;
Vtx *vertBuf = alloc_display_list(15 * sizeof(Vtx)); Vtx *vertBuf;
if (interpolated) {
vertBuf = sBubbleInternalGfxPos[index/5];
} else {
vertBuf = alloc_display_list(15 * sizeof(Vtx));
sBubbleInternalGfxPos[index/5] = vertBuf;
}
if (vertBuf == NULL) { if (vertBuf == NULL) {
return; return;
@ -429,19 +445,37 @@ void append_bubble_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s verte
for (i = 0; i < 15; i += 3) { for (i = 0; i < 15; i += 3) {
vertBuf[i] = template[0]; vertBuf[i] = template[0];
(vertBuf + i)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex1[0]; s32 xPos;
(vertBuf + i)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex1[1]; s32 yPos;
(vertBuf + i)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex1[2]; s32 zPos;
s32 particleIndex = (index + i / 3);
struct EnvFxParticle* particle = (gEnvFxBuffer + particleIndex);
if (interpolated) {
extern f32 gRenderingDelta;
xPos = delta_interpolate_s32(particle->prevPos[0], particle->xPos, gRenderingDelta);
yPos = delta_interpolate_s32(particle->prevPos[1], particle->yPos, gRenderingDelta);
zPos = delta_interpolate_s32(particle->prevPos[2], particle->zPos, gRenderingDelta);
} else {
xPos = particle->prevPos[0];
yPos = particle->prevPos[1];
zPos = particle->prevPos[2];
}
(vertBuf + i)->v.ob[0] = xPos + vertex1[0];
(vertBuf + i)->v.ob[1] = yPos + vertex1[1];
(vertBuf + i)->v.ob[2] = zPos + vertex1[2];
vertBuf[i + 1] = template[1]; vertBuf[i + 1] = template[1];
(vertBuf + i + 1)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex2[0]; (vertBuf + i + 1)->v.ob[0] = xPos + vertex2[0];
(vertBuf + i + 1)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex2[1]; (vertBuf + i + 1)->v.ob[1] = yPos + vertex2[1];
(vertBuf + i + 1)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex2[2]; (vertBuf + i + 1)->v.ob[2] = zPos + vertex2[2];
vertBuf[i + 2] = template[2]; vertBuf[i + 2] = template[2];
(vertBuf + i + 2)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex3[0]; (vertBuf + i + 2)->v.ob[0] = xPos + vertex3[0];
(vertBuf + i + 2)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex3[1]; (vertBuf + i + 2)->v.ob[1] = yPos + vertex3[1];
(vertBuf + i + 2)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex3[2]; (vertBuf + i + 2)->v.ob[2] = zPos + vertex3[2];
} }
gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0); gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0);
@ -478,28 +512,25 @@ void envfx_set_bubble_texture(s32 mode, s16 index) {
gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D68); gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D68);
} }
/** Gfx *envfx_update_bubble_particles_internal(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated) {
* Updates the bubble particle positions, then generates and returns a display
* list drawing them.
*/
Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo) {
s32 i; s32 i;
s16 radius, pitch, yaw; s16 radius, pitch, yaw;
Vec3s vertex1 = { 0 }; Vec3s vertex1 = { 0 };
Vec3s vertex2 = { 0 }; Vec3s vertex2 = { 0 };
Vec3s vertex3 = { 0 }; Vec3s vertex3 = { 0 };
Vec3s interpolatedVertices[3] = { 0 };
static Vec3s prevVertex1;
static Vec3s prevVertex2;
static Vec3s prevVertex3;
static u32 prevTimestamp;
Gfx *gfxStart; Gfx *gfxStart;
if (interpolated) {
gfxStart = sBubbleGfxPos;
} else {
gfxStart = alloc_display_list(((sBubbleParticleMaxCount / 5) * 10 + sBubbleParticleMaxCount + 3) * sizeof(Gfx));
sBubbleGfxPos = gfxStart;
sBubbleGfxMode = mode;
vec3s_copy(sBubbleGfxCamFrom, camFrom);
vec3s_copy(sBubbleGfxCamTo, camTo);
}
gfxStart = alloc_display_list(((sBubbleParticleMaxCount / 5) * 10 + sBubbleParticleMaxCount + 3)
* sizeof(Gfx));
if (gfxStart == NULL) { if (gfxStart == NULL) {
return NULL; return NULL;
} }
@ -507,60 +538,21 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
sGfxCursor = gfxStart; sGfxCursor = gfxStart;
orbit_from_positions(camTo, camFrom, &radius, &pitch, &yaw); orbit_from_positions(camTo, camFrom, &radius, &pitch, &yaw);
envfx_bubbles_update_switch(mode, camTo, vertex1, vertex2, vertex3); envfx_bubbles_update_switch(mode, camTo, vertex1, vertex2, vertex3, interpolated);
rotate_triangle_vertices(vertex1, vertex2, vertex3, pitch, yaw); rotate_triangle_vertices(vertex1, vertex2, vertex3, pitch, yaw);
if (gGlobalTimer == prevTimestamp + 1) {
// TODO: fixme
//interpolate_vectors_s16(interpolatedVertices[0], prevVertex1, vertex1);
vec3s_copy(interpolatedVertices[0], vertex1);
//interpolate_vectors_s16(interpolatedVertices[1], prevVertex2, vertex2);
vec3s_copy(interpolatedVertices[1], vertex2);
//interpolate_vectors_s16(interpolatedVertices[2], prevVertex3, vertex3);
vec3s_copy(interpolatedVertices[2], vertex3);
}
vec3s_copy(prevVertex1, vertex1);
vec3s_copy(prevVertex2, vertex2);
vec3s_copy(prevVertex3, vertex3);
prevTimestamp = gGlobalTimer;
gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D38); gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D38);
for (i = 0; i < sBubbleParticleMaxCount; i += 5) { for (i = 0; i < sBubbleParticleMaxCount; i += 5) {
Vtx *interpolatedVertBuf = alloc_display_list(15 * sizeof(Vtx));
if (interpolatedVertBuf == NULL) { continue; }
s32 j, k;
gDPPipeSync(sGfxCursor++); gDPPipeSync(sGfxCursor++);
envfx_set_bubble_texture(mode, i); envfx_set_bubble_texture(mode, i);
sBubbleInterpolatedDisplayListPos[i / 5] = sGfxCursor; append_bubble_vertex_buffer(sGfxCursor++, i, vertex1, vertex2, vertex3, (Vtx *) gBubbleTempVtx, interpolated);
for (j = 0; j < 5; j++) {
for (k = 0; k < 3; k++) {
Vtx *v = &interpolatedVertBuf[j * 3 + k];
v->v = gBubbleTempVtx[k];
if (gGlobalTimer != gEnvFxBuffer[i + j].spawnTimestamp && mode != ENVFX_LAVA_BUBBLES) {
v->v.ob[0] = (sPrevBubblePositions[i + j][0] + gEnvFxBuffer[i + j].xPos) / 2.0f + interpolatedVertices[k][0];
v->v.ob[1] = (sPrevBubblePositions[i + j][1] + gEnvFxBuffer[i + j].yPos) / 2.0f + interpolatedVertices[k][1];
v->v.ob[2] = (sPrevBubblePositions[i + j][2] + gEnvFxBuffer[i + j].zPos) / 2.0f + interpolatedVertices[k][2];
} else {
v->v.ob[0] = gEnvFxBuffer[i + j].xPos + interpolatedVertices[k][0];
v->v.ob[1] = gEnvFxBuffer[i + j].yPos + interpolatedVertices[k][1];
v->v.ob[2] = gEnvFxBuffer[i + j].zPos + interpolatedVertices[k][2];
}
}
}
gSPVertex(sGfxCursor++, VIRTUAL_TO_PHYSICAL(interpolatedVertBuf), 15, 0);
append_bubble_vertex_buffer(&sGfxSaved[i / 5], i, vertex1, vertex2, vertex3, (Vtx *) gBubbleTempVtx);
gSP1Triangle(sGfxCursor++, 0, 1, 2, 0); gSP1Triangle(sGfxCursor++, 0, 1, 2, 0);
gSP1Triangle(sGfxCursor++, 3, 4, 5, 0); gSP1Triangle(sGfxCursor++, 3, 4, 5, 0);
gSP1Triangle(sGfxCursor++, 6, 7, 8, 0); gSP1Triangle(sGfxCursor++, 6, 7, 8, 0);
gSP1Triangle(sGfxCursor++, 9, 10, 11, 0); gSP1Triangle(sGfxCursor++, 9, 10, 11, 0);
gSP1Triangle(sGfxCursor++, 12, 13, 14, 0); gSP1Triangle(sGfxCursor++, 12, 13, 14, 0);
} }
for (i = 0; i < sBubbleParticleMaxCount; i++) {
sPrevBubblePositions[i][0] = gEnvFxBuffer[i].xPos;
sPrevBubblePositions[i][1] = gEnvFxBuffer[i].yPos;
sPrevBubblePositions[i][2] = gEnvFxBuffer[i].zPos;
}
gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006AB0); gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006AB0);
gSPEndDisplayList(sGfxCursor++); gSPEndDisplayList(sGfxCursor++);
@ -568,6 +560,14 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
return gfxStart; return gfxStart;
} }
/**
* Updates the bubble particle positions, then generates and returns a display
* list drawing them.
*/
Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo) {
return envfx_update_bubble_particles_internal(mode,marioPos, camFrom, camTo, false);
}
/** /**
* Set the maximum particle count from the gEnvFxBubbleConfig variable, * Set the maximum particle count from the gEnvFxBubbleConfig variable,
* which is set by the whirlpool or jet stream behavior. * which is set by the whirlpool or jet stream behavior.

View file

@ -11,6 +11,7 @@
#include "engine/behavior_script.h" #include "engine/behavior_script.h"
#include "audio/external.h" #include "audio/external.h"
#include "obj_behaviors.h" #include "obj_behaviors.h"
#include "pc/utils/misc.h"
/** /**
* This file contains the function that handles 'environment effects', * This file contains the function that handles 'environment effects',
@ -54,23 +55,27 @@ extern void *tiny_bubble_dl_0B006AB0;
extern void *tiny_bubble_dl_0B006A50; extern void *tiny_bubble_dl_0B006A50;
extern void *tiny_bubble_dl_0B006CD8; extern void *tiny_bubble_dl_0B006CD8;
static struct { Gfx *envfx_update_snow_internal(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated);
Gfx *pos;
Vtx vertices[15];
} sPrevSnowVertices[140 / 5];
static s16 sPrevSnowParticleCount;
static u32 sPrevSnowTimestamp;
void patch_interpolated_snow_particles(void) { static s32 sSnowGfxMode;
int i; static Gfx* sSnowGfxPos;
static Vtx* sSnowInternalGfxPos[140 / 5];
static Vec3s sSnowGfxCamFrom;
static Vec3s sSnowGfxCamTo;
static Vec3s sSnowGfxMarioPos;
if (gGlobalTimer != sPrevSnowTimestamp + 1) { void patch_snow_particles_before(void) {
return; if (sSnowGfxPos) {
for (s32 i = 0; i < gSnowParticleCount; i++) {
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
}
sSnowGfxPos = NULL;
} }
}
for (i = 0; i < sPrevSnowParticleCount; i += 5) { void patch_snow_particles_interpolated(UNUSED f32 delta) {
gSPVertex(sPrevSnowVertices[i / 5].pos, if (sSnowGfxPos) {
VIRTUAL_TO_PHYSICAL(sPrevSnowVertices[i / 5].vertices), 15, 0); envfx_update_snow_internal(sSnowGfxMode, sSnowGfxMarioPos, sSnowGfxCamFrom, sSnowGfxCamTo, true);
} }
} }
@ -238,6 +243,7 @@ void envfx_update_snow_normal(s32 snowCylinderX, s32 snowCylinderY, s32 snowCyli
(gEnvFxBuffer + i)->yPos = 200.0f * random_float() + snowCylinderY; (gEnvFxBuffer + i)->yPos = 200.0f * random_float() + snowCylinderY;
(gEnvFxBuffer + i)->isAlive = 1; (gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else { } else {
(gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2); (gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2);
(gEnvFxBuffer + i)->yPos -= 2 -(s16)(deltaY * 0.8); (gEnvFxBuffer + i)->yPos -= 2 -(s16)(deltaY * 0.8);
@ -273,6 +279,7 @@ void envfx_update_snow_blizzard(s32 snowCylinderX, s32 snowCylinderY, s32 snowCy
(gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY; (gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY;
(gEnvFxBuffer + i)->isAlive = 1; (gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else { } else {
(gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2) + 20.0f; (gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2) + 20.0f;
(gEnvFxBuffer + i)->yPos -= 5 -(s16)(deltaY * 0.8); (gEnvFxBuffer + i)->yPos -= 5 -(s16)(deltaY * 0.8);
@ -317,6 +324,7 @@ void envfx_update_snow_water(s32 snowCylinderX, s32 snowCylinderY, s32 snowCylin
(gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY; (gEnvFxBuffer + i)->yPos = 400.0f * random_float() - 200.0f + snowCylinderY;
(gEnvFxBuffer + i)->isAlive = 1; (gEnvFxBuffer + i)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} }
} }
} }
@ -364,57 +372,61 @@ void rotate_triangle_vertices(Vec3s vertex1, Vec3s vertex2, Vec3s vertex3, s16 p
* around (0,0,0) that will be translated to snowflake positions to draw the * around (0,0,0) that will be translated to snowflake positions to draw the
* snowflake image. * snowflake image.
*/ */
void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3) { void append_snowflake_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3, u8 interpolated) {
s32 i = 0; s32 i = 0;
Vtx *vertBuf = (Vtx *) alloc_display_list(15 * sizeof(Vtx)); Vtx *vertBuf;
Vtx *vertBufInterpolated = (Vtx *) alloc_display_list(15 * sizeof(Vtx));
Vtx *v;
if (vertBuf == NULL || vertBufInterpolated == NULL) { if (interpolated) {
vertBuf = sSnowInternalGfxPos[index/5];
} else {
vertBuf = (Vtx *) alloc_display_list(15 * sizeof(Vtx));
sSnowInternalGfxPos[index/5] = vertBuf;
}
if (vertBuf == NULL) {
return; return;
} }
for (i = 0; i < 15; i += 3) { for (i = 0; i < 15; i += 3) {
vertBuf[i] = gSnowTempVtx[0]; vertBuf[i] = gSnowTempVtx[0];
(vertBuf + i)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex1[0];
(vertBuf + i)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex1[1]; s32 xPos;
(vertBuf + i)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex1[2]; s32 yPos;
s32 zPos;
s32 particleIndex = (index + i / 3);
struct EnvFxParticle* particle = (gEnvFxBuffer + particleIndex);
if (interpolated) {
extern f32 gRenderingDelta;
xPos = delta_interpolate_s32(particle->prevPos[0], particle->xPos, gRenderingDelta);
yPos = delta_interpolate_s32(particle->prevPos[1], particle->yPos, gRenderingDelta);
zPos = delta_interpolate_s32(particle->prevPos[2], particle->zPos, gRenderingDelta);
} else {
xPos = particle->prevPos[0];
yPos = particle->prevPos[1];
zPos = particle->prevPos[2];
}
(vertBuf + i)->v.ob[0] = xPos + vertex1[0];
(vertBuf + i)->v.ob[1] = yPos + vertex1[1];
(vertBuf + i)->v.ob[2] = zPos + vertex1[2];
vertBuf[i + 1] = gSnowTempVtx[1]; vertBuf[i + 1] = gSnowTempVtx[1];
(vertBuf + i + 1)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex2[0]; (vertBuf + i + 1)->v.ob[0] = xPos + vertex2[0];
(vertBuf + i + 1)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex2[1]; (vertBuf + i + 1)->v.ob[1] = yPos + vertex2[1];
(vertBuf + i + 1)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex2[2]; (vertBuf + i + 1)->v.ob[2] = zPos + vertex2[2];
vertBuf[i + 2] = gSnowTempVtx[2]; vertBuf[i + 2] = gSnowTempVtx[2];
(vertBuf + i + 2)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex3[0]; (vertBuf + i + 2)->v.ob[0] = xPos + vertex3[0];
(vertBuf + i + 2)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex3[1]; (vertBuf + i + 2)->v.ob[1] = yPos + vertex3[1];
(vertBuf + i + 2)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex3[2]; (vertBuf + i + 2)->v.ob[2] = zPos + vertex3[2];
} }
for (i = 0; i < 15; i++) { gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0);
v = &sPrevSnowVertices[index / 5].vertices[i];
vertBufInterpolated[i] = gSnowTempVtx[i % 3];
if (index < sPrevSnowParticleCount && gGlobalTimer == sPrevSnowTimestamp + 1 &&
gGlobalTimer != gEnvFxBuffer[index + i / 3].spawnTimestamp) {
vertBufInterpolated[i].v.ob[0] = (v->v.ob[0] + vertBuf[i].v.ob[0]) / 2;
vertBufInterpolated[i].v.ob[1] = (v->v.ob[1] + vertBuf[i].v.ob[1]) / 2;
vertBufInterpolated[i].v.ob[2] = (v->v.ob[2] + vertBuf[i].v.ob[2]) / 2;
} else {
vertBufInterpolated[i].v.ob[0] = vertBuf[i].v.ob[0];
vertBufInterpolated[i].v.ob[1] = vertBuf[i].v.ob[1];
vertBufInterpolated[i].v.ob[2] = vertBuf[i].v.ob[2];
}
*v = vertBuf[i];
}
sPrevSnowVertices[index / 5].pos = gfx;
gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBufInterpolated), 15, 0);
} }
/**
* Updates positions of snow particles and returns a pointer to a display list Gfx *envfx_update_snow_internal(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated) {
* drawing all snowflakes.
*/
Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo) {
s32 i; s32 i;
s16 radius, pitch, yaw; s16 radius, pitch, yaw;
Vec3s snowCylinderPos; Vec3s snowCylinderPos;
@ -426,7 +438,17 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
vertex2 = gSnowFlakeVertex2; vertex2 = gSnowFlakeVertex2;
vertex3 = gSnowFlakeVertex3; vertex3 = gSnowFlakeVertex3;
gfxStart = (Gfx *) alloc_display_list((gSnowParticleCount * 6 + 3) * sizeof(Gfx)); if (interpolated) {
gfxStart = sSnowGfxPos;
} else {
gfxStart = (Gfx *) alloc_display_list((gSnowParticleCount * 6 + 3) * sizeof(Gfx));
sSnowGfxPos = gfxStart;
sSnowGfxMode = snowMode;
vec3s_copy(sSnowGfxMarioPos, marioPos);
vec3s_copy(sSnowGfxCamFrom, camFrom);
vec3s_copy(sSnowGfxCamTo, camTo);
}
gfx = gfxStart; gfx = gfxStart;
if (gfxStart == NULL) { if (gfxStart == NULL) {
@ -449,7 +471,7 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
} }
pos_from_orbit(camTo, snowCylinderPos, radius, pitch, yaw); pos_from_orbit(camTo, snowCylinderPos, radius, pitch, yaw);
envfx_update_snow_normal(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); if (!interpolated) { envfx_update_snow_normal(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); }
break; break;
case ENVFX_SNOW_WATER: case ENVFX_SNOW_WATER:
@ -460,7 +482,7 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
} }
pos_from_orbit(camTo, snowCylinderPos, radius, pitch, yaw); pos_from_orbit(camTo, snowCylinderPos, radius, pitch, yaw);
envfx_update_snow_water(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); if (!interpolated) { envfx_update_snow_water(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); }
break; break;
case ENVFX_SNOW_BLIZZARD: case ENVFX_SNOW_BLIZZARD:
if (radius > 250) { if (radius > 250) {
@ -470,7 +492,7 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
} }
pos_from_orbit(camTo, snowCylinderPos, radius, pitch, yaw); pos_from_orbit(camTo, snowCylinderPos, radius, pitch, yaw);
envfx_update_snow_blizzard(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); if (!interpolated) { envfx_update_snow_blizzard(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); }
break; break;
} }
@ -483,7 +505,7 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
} }
for (i = 0; i < gSnowParticleCount; i += 5) { for (i = 0; i < gSnowParticleCount; i += 5) {
append_snowflake_vertex_buffer(gfx++, i, (s16 *) &vertex1, (s16 *) &vertex2, (s16 *) &vertex3); append_snowflake_vertex_buffer(gfx++, i, (s16 *) &vertex1, (s16 *) &vertex2, (s16 *) &vertex3, interpolated);
gSP1Triangle(gfx++, 0, 1, 2, 0); gSP1Triangle(gfx++, 0, 1, 2, 0);
gSP1Triangle(gfx++, 3, 4, 5, 0); gSP1Triangle(gfx++, 3, 4, 5, 0);
@ -491,14 +513,20 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
gSP1Triangle(gfx++, 9, 10, 11, 0); gSP1Triangle(gfx++, 9, 10, 11, 0);
gSP1Triangle(gfx++, 12, 13, 14, 0); gSP1Triangle(gfx++, 12, 13, 14, 0);
} }
sPrevSnowParticleCount = gSnowParticleCount;
sPrevSnowTimestamp = gGlobalTimer;
gSPDisplayList(gfx++, &tiny_bubble_dl_0B006AB0) gSPEndDisplayList(gfx++); gSPDisplayList(gfx++, &tiny_bubble_dl_0B006AB0) gSPEndDisplayList(gfx++);
return gfxStart; return gfxStart;
} }
/**
* Updates positions of snow particles and returns a pointer to a display list
* drawing all snowflakes.
*/
Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo) {
return envfx_update_snow_internal(snowMode, marioPos, camFrom, camTo, false);
}
/** /**
* Updates the environment effects (snow, flowers, bubbles) * Updates the environment effects (snow, flowers, bubbles)
* and returns a display list drawing them. * and returns a display list drawing them.

View file

@ -27,6 +27,7 @@ struct EnvFxParticle {
s32 bubbleY; // for Bubbles, yPos is always set to this s32 bubbleY; // for Bubbles, yPos is always set to this
//s8 filler20[56 - 0x20]; //s8 filler20[56 - 0x20];
u32 spawnTimestamp; u32 spawnTimestamp;
Vec3s prevPos;
}; };
extern s8 gEnvFxMode; extern s8 gEnvFxMode;

View file

@ -17,6 +17,7 @@
#include "print.h" #include "print.h"
#include "pc/configfile.h" #include "pc/configfile.h"
#include "pc/network/network.h" #include "pc/network/network.h"
#include "pc/utils/misc.h"
extern bool gDjuiInMainMenu; extern bool gDjuiInMainMenu;
u8 gOverrideHideHud; u8 gOverrideHideHud;
@ -64,18 +65,26 @@ static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 };
static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE }; static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE };
static u32 sPowerMeterLastRenderTimestamp; static u32 sPowerMeterPrevTimestamp;
static s16 sPowerMeterLastY; static f32 sPowerMeterPrevY;
static Gfx *sPowerMeterDisplayListPos; static Gfx *sPowerMeterDisplayListPos;
void patch_interpolated_hud(void) { void patch_hud_before(void) {
if (sPowerMeterDisplayListPos != NULL) {
sPowerMeterPrevY = sPowerMeterHUD.y;
sPowerMeterPrevTimestamp = gGlobalTimer;
sPowerMeterDisplayListPos = NULL;
}
}
void patch_hud_interpolated(f32 delta) {
if (sPowerMeterDisplayListPos != NULL) { if (sPowerMeterDisplayListPos != NULL) {
Mtx *mtx = alloc_display_list(sizeof(Mtx)); Mtx *mtx = alloc_display_list(sizeof(Mtx));
if (mtx == NULL) { return; } if (mtx == NULL) { return; }
guTranslate(mtx, (f32) sPowerMeterHUD.x, (f32) sPowerMeterHUD.y, 0); f32 interpY = delta_interpolate_f32(sPowerMeterPrevY, (f32)sPowerMeterHUD.y, delta);
guTranslate(mtx, (f32) sPowerMeterHUD.x, interpY, 0);
gSPMatrix(sPowerMeterDisplayListPos, VIRTUAL_TO_PHYSICAL(mtx), gSPMatrix(sPowerMeterDisplayListPos, VIRTUAL_TO_PHYSICAL(mtx),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH); G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
sPowerMeterDisplayListPos = NULL;
} }
} }
@ -131,7 +140,6 @@ void render_power_meter_health_segment(s16 numHealthWedges) {
*/ */
void render_dl_power_meter(s16 numHealthWedges) { void render_dl_power_meter(s16 numHealthWedges) {
Mtx *mtx; Mtx *mtx;
f32 interpolatedY;
mtx = alloc_display_list(sizeof(Mtx)); mtx = alloc_display_list(sizeof(Mtx));
@ -139,14 +147,7 @@ void render_dl_power_meter(s16 numHealthWedges) {
return; return;
} }
if (gGlobalTimer == sPowerMeterLastRenderTimestamp + 1) { guTranslate(mtx, (f32) sPowerMeterHUD.x, sPowerMeterPrevY, 0);
interpolatedY = (sPowerMeterLastY + sPowerMeterHUD.y) / 2.0f;
} else {
interpolatedY = sPowerMeterHUD.y;
}
guTranslate(mtx, (f32) sPowerMeterHUD.x, interpolatedY, 0);
sPowerMeterLastY = sPowerMeterHUD.y;
sPowerMeterLastRenderTimestamp = gGlobalTimer;
sPowerMeterDisplayListPos = gDisplayListHead; sPowerMeterDisplayListPos = gDisplayListHead;
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++), gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++),
@ -202,6 +203,7 @@ static void animate_power_meter_deemphasizing(void) {
if (sPowerMeterHUD.y >= 201) { if (sPowerMeterHUD.y >= 201) {
sPowerMeterHUD.y = 200; sPowerMeterHUD.y = 200;
sPowerMeterPrevY = 200;
sPowerMeterHUD.animation = POWER_METER_VISIBLE; sPowerMeterHUD.animation = POWER_METER_VISIBLE;
} }
} }
@ -226,6 +228,7 @@ void handle_power_meter_actions(s16 numHealthWedges) {
if (numHealthWedges < 8 && sPowerMeterStoredHealth == 8 && sPowerMeterHUD.animation == POWER_METER_HIDDEN) { if (numHealthWedges < 8 && sPowerMeterStoredHealth == 8 && sPowerMeterHUD.animation == POWER_METER_HIDDEN) {
sPowerMeterHUD.animation = POWER_METER_EMPHASIZED; sPowerMeterHUD.animation = POWER_METER_EMPHASIZED;
sPowerMeterHUD.y = 166; sPowerMeterHUD.y = 166;
sPowerMeterPrevY = 166;
} }
// Show power meter if health is full, has 8 // Show power meter if health is full, has 8

View file

@ -27,6 +27,7 @@
#include "pc/cheats.h" #include "pc/cheats.h"
#include "pc/network/network.h" #include "pc/network/network.h"
#include "pc/djui/djui.h" #include "pc/djui/djui.h"
#include "pc/utils/misc.h"
#ifdef BETTERCAMERA #ifdef BETTERCAMERA
#include "bettercamera.h" #include "bettercamera.h"
#endif #endif
@ -130,44 +131,63 @@ s32 gDialogResponse = 0;
static struct CachedChar { u8 used; u8 data[CHCACHE_BUFLEN]; } charCache[256]; static struct CachedChar { u8 used; u8 data[CHCACHE_BUFLEN]; } charCache[256];
#endif // VERSION #endif // VERSION
static Gfx *sInterpolatedDialogOffsetPos; static Gfx *sDialogOffsetPos;
static f32 sInterpolatedDialogOffset; static Gfx *sDialogRotationPos;
static Gfx *sInterpolatedDialogRotationPos; static Gfx *sDialogZoomPos;
static f32 sInterpolatedDialogScale;
static f32 sInterpolatedDialogRotation;
static Gfx *sInterpolatedDialogZoomPos;
void patch_interpolated_dialog(void) { static f32 sDialogOffset;
static f32 sDialogOffsetPrev;
static f32 sDialogScale;
static f32 sDialogScalePrev;
static f32 sDialogRotation;
static f32 sDialogRotationPrev;
void patch_dialog_before(void) {
sDialogOffsetPos = NULL;
sDialogRotationPos = NULL;
sDialogZoomPos = NULL;
}
void patch_dialog_interpolated(f32 delta) {
Mtx *matrix; Mtx *matrix;
if (sInterpolatedDialogOffsetPos != NULL) { if (sDialogOffsetPos != NULL) {
matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
if (matrix == NULL) { return; } if (matrix == NULL) { return; }
guTranslate(matrix, 0, sInterpolatedDialogOffset, 0); f32 interpOffset = delta_interpolate_f32(sDialogOffsetPrev, sDialogOffset, delta);
gSPMatrix(sInterpolatedDialogOffsetPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); guTranslate(matrix, 0, interpOffset, 0);
sInterpolatedDialogOffsetPos = NULL; gSPMatrix(sDialogOffsetPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
} }
if (sInterpolatedDialogRotationPos != NULL) {
if (sDialogRotationPos != NULL) {
matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
if (matrix == NULL) { return; } if (matrix == NULL) { return; }
guScale(matrix, 1.0 / sInterpolatedDialogScale, 1.0 / sInterpolatedDialogScale, 1.0f);
gSPMatrix(sInterpolatedDialogRotationPos++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); f32 interpScale = delta_interpolate_f32(sDialogScalePrev, sDialogScale, delta);
guScale(matrix, 1.0 / interpScale, 1.0 / interpScale, 1.0f);
gSPMatrix(sDialogRotationPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
if (matrix == NULL) { return; } if (matrix == NULL) { return; }
guRotate(matrix, sInterpolatedDialogRotation * 4.0f, 0, 0, 1.0f);
gSPMatrix(sInterpolatedDialogRotationPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); f32 interpRotation = delta_interpolate_f32(sDialogRotationPrev, sDialogRotation, delta);
sInterpolatedDialogRotationPos = NULL; guRotate(matrix, interpRotation * 4.0f, 0, 0, 1.0f);
gSPMatrix((sDialogRotationPos + 1), VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
} }
if (sInterpolatedDialogZoomPos != NULL) {
if (sDialogZoomPos != NULL) {
matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
if (matrix == NULL) { return; } if (matrix == NULL) { return; }
guTranslate(matrix, 65.0 - (65.0 / sInterpolatedDialogScale), (40.0 / sInterpolatedDialogScale) - 40, 0);
gSPMatrix(sInterpolatedDialogZoomPos++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); f32 interpScale = delta_interpolate_f32(sDialogScalePrev, sDialogScale, delta);
guTranslate(matrix, 65.0 - (65.0 / interpScale), (40.0 / interpScale) - 40, 0);
gSPMatrix(sDialogZoomPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); matrix = (Mtx *) alloc_display_list(sizeof(Mtx));
if (matrix == NULL) { return; } if (matrix == NULL) { return; }
guScale(matrix, 1.0 / sInterpolatedDialogScale, 1.0 / sInterpolatedDialogScale, 1.0f);
gSPMatrix(sInterpolatedDialogZoomPos, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); guScale(matrix, 1.0 / interpScale, 1.0 / interpScale, 1.0f);
sInterpolatedDialogZoomPos = NULL; gSPMatrix((sDialogZoomPos + 1), VIRTUAL_TO_PHYSICAL(matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
} }
} }
@ -1121,31 +1141,34 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) {
switch (gDialogBoxType) { switch (gDialogBoxType) {
case DIALOG_TYPE_ROTATE: // Renders a dialog black box with zoom and rotation case DIALOG_TYPE_ROTATE: // Renders a dialog black box with zoom and rotation
if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) { if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) {
sInterpolatedDialogRotationPos = gDisplayListHead; sDialogRotationPos = gDisplayListHead;
if (gDialogBoxState == DIALOG_STATE_OPENING) { if (gDialogBoxState == DIALOG_STATE_OPENING) {
sInterpolatedDialogScale = gDialogBoxScale - 2 / 2; sDialogScale = gDialogBoxScale - 1.5f;
sInterpolatedDialogRotation = gDialogBoxOpenTimer - 7.5f / 2; sDialogRotation = gDialogBoxOpenTimer - 7.5f;
} else { } else {
sInterpolatedDialogScale = gDialogBoxScale + 2 / 2; sDialogScale = gDialogBoxScale + 2.0f;
sInterpolatedDialogRotation = gDialogBoxOpenTimer + 7.5f / 2; sDialogRotation = gDialogBoxOpenTimer + 10.0f;
} }
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / gDialogBoxScale, 1.0 / gDialogBoxScale, 1.0f); sDialogScalePrev = gDialogBoxScale;
sDialogRotationPrev = gDialogBoxOpenTimer;
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / sDialogScalePrev, 1.0 / sDialogScalePrev, 1.0f);
// convert the speed into angle // convert the speed into angle
create_dl_rotation_matrix(MENU_MTX_NOPUSH, gDialogBoxOpenTimer * 4.0f, 0, 0, 1.0f); create_dl_rotation_matrix(MENU_MTX_NOPUSH, sDialogRotationPrev * 4.0f, 0, 0, 1.0f);
} }
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 150); gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 150);
break; break;
case DIALOG_TYPE_ZOOM: // Renders a dialog white box with zoom case DIALOG_TYPE_ZOOM: // Renders a dialog white box with zoom
if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) { if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) {
sInterpolatedDialogZoomPos = gDisplayListHead; sDialogZoomPos = gDisplayListHead;
if (gDialogBoxState == DIALOG_STATE_OPENING) { if (gDialogBoxState == DIALOG_STATE_OPENING) {
sInterpolatedDialogScale = gDialogBoxScale - 2 / 2; sDialogScale = gDialogBoxScale - 2;
} else { } else {
sInterpolatedDialogScale = gDialogBoxScale + 2 / 2; sDialogScale = gDialogBoxScale + 2;
} }
create_dl_translation_matrix(MENU_MTX_NOPUSH, 65.0 - (65.0 / gDialogBoxScale), sDialogScalePrev = gDialogBoxScale;
(40.0 / gDialogBoxScale) - 40, 0); create_dl_translation_matrix(MENU_MTX_NOPUSH, 65.0 - (65.0 / sDialogScalePrev),
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / gDialogBoxScale, 1.0 / gDialogBoxScale, 1.0f); (40.0 / sDialogScalePrev) - 40, 0);
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / sDialogScalePrev, 1.0 / sDialogScalePrev, 1.0f);
} }
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 150); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 150);
break; break;
@ -1425,9 +1448,10 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
#ifdef VERSION_EU #ifdef VERSION_EU
gDialogY -= gDialogScrollOffsetY; gDialogY -= gDialogScrollOffsetY;
#else #else
sInterpolatedDialogOffset = gDialogScrollOffsetY + dialog->linesPerBox; sDialogOffset = gDialogScrollOffsetY + dialog->linesPerBox * 2;
sInterpolatedDialogOffsetPos = gDisplayListHead; sDialogOffsetPrev = gDialogScrollOffsetY;
create_dl_translation_matrix(MENU_MTX_NOPUSH, 0, (f32) gDialogScrollOffsetY, 0); sDialogOffsetPos = gDisplayListHead;
create_dl_translation_matrix(MENU_MTX_NOPUSH, 0, (f32) sDialogOffsetPrev, 0);
#endif #endif
} }

View file

@ -16,6 +16,7 @@
#include "paintings.h" #include "paintings.h"
#include "save_file.h" #include "save_file.h"
#include "segment2.h" #include "segment2.h"
#include "pc/utils/misc.h"
/** /**
* @file paintings.c * @file paintings.c
@ -189,29 +190,74 @@ struct Painting **sPaintingGroups[] = {
s16 gPaintingUpdateCounter = 1; s16 gPaintingUpdateCounter = 1;
s16 gLastPaintingUpdateCounter = 0; s16 gLastPaintingUpdateCounter = 0;
static Vtx sLastVertices[2 * 264 * 3];
static u32 sLastVerticesTimestamp; typedef struct {
float ob[3]; /* x, y, z */
signed char n[3]; /* normal */
} Vtx_Interp;
static Vtx_Interp sVertexBuffers[2][2 * 264 * 3];
static u8 sVerticesCurIndex = 0;
static u8 sVertexSwaps = 0;
static Vtx_Interp* sVerticesCur = sVertexBuffers[0];
static Vtx_Interp* sVerticesPrev = NULL;
static u32 sVerticesPrevTimestamp;
static Vtx *sVerticesPtr[2]; static Vtx *sVerticesPtr[2];
static s32 sVerticesCount; static s32 sVerticesCount;
void patch_interpolated_paintings(void) { void patch_paintings_before(void) {
if (sVerticesPtr[0] != NULL) {
if (gGlobalTimer == sVerticesPrevTimestamp + 1) {
sVerticesCurIndex = !sVerticesCurIndex;
sVerticesCur = sVertexBuffers[sVerticesCurIndex];
sVerticesPrev = sVertexBuffers[!sVerticesCurIndex];
sVertexSwaps++;
} else {
sVerticesPrev = NULL;
sVertexSwaps = 0;
}
sVerticesPtr[0] = NULL;
sVerticesPtr[1] = NULL;
sVerticesCount = 0;
}
void patch_paintings_interpolated(f32 delta) {
if (sVerticesPtr[0] != NULL && sVerticesPrev != NULL && sVertexSwaps > 2) {
s32 i; s32 i;
if (sVerticesPtr[1] != NULL) { if (sVerticesPtr[1] != NULL) {
for (i = 0; i < sVerticesCount / 2; i++) { for (i = 0; i < sVerticesCount / 2; i++) {
sVerticesPtr[0][i] = sLastVertices[i]; Vec3f obInterp;
delta_interpolate_vec3f(obInterp, sVerticesPrev[i].ob, sVerticesCur[i].ob, delta);
s8 nInterp[3];
delta_interpolate_normal(nInterp, sVerticesPrev[i].n, sVerticesCur[i].n, delta);
for (u8 j = 0; j < 3; j++) {
sVerticesPtr[0][i].n.ob[j] = obInterp[j];
sVerticesPtr[0][i].n.n[j] = nInterp[j];
}
} }
for (; i < sVerticesCount; i++) { for (; i < sVerticesCount; i++) {
sVerticesPtr[1][i - sVerticesCount / 2] = sLastVertices[i]; Vec3f obInterp;
delta_interpolate_vec3f(obInterp, sVerticesPrev[i].ob, sVerticesCur[i].ob, delta);
s8 nInterp[3];
delta_interpolate_normal(nInterp, sVerticesPrev[i].n, sVerticesCur[i].n, delta);
for (u8 j = 0; j < 3; j++) {
sVerticesPtr[1][i - sVerticesCount / 2].n.ob[j] = obInterp[j];
sVerticesPtr[1][i - sVerticesCount / 2].n.n[j] = nInterp[j];
}
} }
} else { } else {
for (i = 0; i < sVerticesCount; i++) { for (i = 0; i < sVerticesCount; i++) {
sVerticesPtr[0][i] = sLastVertices[i]; Vec3f obInterp;
delta_interpolate_vec3f(obInterp, sVerticesPrev[i].ob, sVerticesCur[i].ob, delta);
s8 nInterp[3];
delta_interpolate_normal(nInterp, sVerticesPrev[i].n, sVerticesCur[i].n, delta);
for (u8 j = 0; j < 3; j++) {
sVerticesPtr[0][i].n.ob[j] = obInterp[j];
sVerticesPtr[0][i].n.n[j] = nInterp[j];
}
} }
} }
sVerticesPtr[0] = NULL;
sVerticesPtr[1] = NULL;
sVerticesCount = 0;
} }
} }
@ -932,16 +978,25 @@ Gfx *render_painting(u8 *img, s16 tWidth, s16 tHeight, s16 *textureMap, s16 mapV
sVerticesCount = 0; sVerticesCount = 0;
} }
for (map = 0; map < numVtx; map++) { for (map = 0; map < numVtx; map++) {
Vtx v = verts[map]; Vtx* v = &verts[map];
if (gGlobalTimer == sLastVerticesTimestamp + 1) { if (gGlobalTimer == sVerticesPrevTimestamp + 1) {
s32 i; s32 i;
Vtx_Interp* vCur = &sVerticesCur[sVerticesCount + map];
Vtx_Interp* vPrev = (sVerticesPrev && sVertexSwaps > 2) ? &sVerticesPrev[sVerticesCount + map] : NULL;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
verts[map].n.ob[i] = (v.n.ob[i] + sLastVertices[sVerticesCount + map].n.ob[i]) / 2; // save current
verts[map].n.n[i] = (v.n.n[i] + sLastVertices[sVerticesCount + map].n.n[i]) / 2; vCur->ob[i] = v->n.ob[i];
vCur->n[i] = v->n.n[i];
// override verts with prev
if (vPrev) {
v->n.ob[i] = vPrev->ob[i];
v->n.n[i] = vPrev->n[i];
}
} }
} }
sLastVertices[sVerticesCount + map] = v;
} }
sVerticesPtr[sVerticesCount / numVtx] = verts; sVerticesPtr[sVerticesCount / numVtx] = verts;
sVerticesCount += numVtx; sVerticesCount += numVtx;
@ -1010,7 +1065,7 @@ Gfx *painting_ripple_image(struct Painting *painting) {
meshTris = textureMap[meshVerts * 3 + 1]; meshTris = textureMap[meshVerts * 3 + 1];
gSPDisplayList(gfx++, render_painting(textures[i], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha)); gSPDisplayList(gfx++, render_painting(textures[i], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha));
} }
sLastVerticesTimestamp = gGlobalTimer; sVerticesPrevTimestamp = gGlobalTimer;
// Update the ripple, may automatically reset the painting's state. // Update the ripple, may automatically reset the painting's state.
painting_update_ripple_state(painting); painting_update_ripple_state(painting);
@ -1048,7 +1103,7 @@ Gfx *painting_ripple_env_mapped(struct Painting *painting) {
meshVerts = textureMap[0]; meshVerts = textureMap[0];
meshTris = textureMap[meshVerts * 3 + 1]; meshTris = textureMap[meshVerts * 3 + 1];
gSPDisplayList(gfx++, render_painting(tArray[0], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha)); gSPDisplayList(gfx++, render_painting(tArray[0], tWidth, tHeight, textureMap, meshVerts, meshTris, painting->alpha));
sLastVerticesTimestamp = gGlobalTimer; sVerticesPrevTimestamp = gGlobalTimer;
// Update the ripple, may automatically reset the painting's state. // Update the ripple, may automatically reset the painting's state.
painting_update_ripple_state(painting); painting_update_ripple_state(painting);

View file

@ -170,8 +170,8 @@ void mtx_patch_interpolated(f32 delta) {
} }
if (sViewportClipPos != NULL) { if (sViewportClipPos != NULL) {
delta_interpolate_vectors_s16(sViewportInterp.vp.vtrans, sViewportPrev.vp.vtrans, sViewport->vp.vtrans, delta); delta_interpolate_vec3s(sViewportInterp.vp.vtrans, sViewportPrev.vp.vtrans, sViewport->vp.vtrans, delta);
delta_interpolate_vectors_s16(sViewportInterp.vp.vscale, sViewportPrev.vp.vscale, sViewport->vp.vscale, delta); delta_interpolate_vec3s(sViewportInterp.vp.vscale, sViewportPrev.vp.vscale, sViewport->vp.vscale, delta);
Gfx *saved = gDisplayListHead; Gfx *saved = gDisplayListHead;

View file

@ -12,25 +12,42 @@
#include "screen_transition.h" #include "screen_transition.h"
#include "segment2.h" #include "segment2.h"
#include "sm64.h" #include "sm64.h"
#include "pc/utils/misc.h"
u8 sTransitionColorFadeCount[4] = { 0 }; u8 sTransitionColorFadeCount[4] = { 0 };
u16 sTransitionTextureFadeCount[2] = { 0 }; u16 sTransitionTextureFadeCount[2] = { 0 };
static Gfx *sScreenTransitionVerticesPos[2]; static Gfx *sScreenTransitionVerticesPos[2];
static Vtx *sScreenTransitionVertices; static Vtx *sScreenTransitionVertices;
static Vtx *sScreenTransitionVerticesPrev;
static Vtx sScreenTransitionInterp[8] = { 0 };
void reset_screen_transition_timers(void) { void reset_screen_transition_timers(void) {
for (s32 i = 0; i < 4; i++) { sTransitionColorFadeCount[i] = 0; } for (s32 i = 0; i < 4; i++) { sTransitionColorFadeCount[i] = 0; }
for (s32 i = 0; i < 2; i++) { sTransitionTextureFadeCount[i] = 0; } for (s32 i = 0; i < 2; i++) { sTransitionTextureFadeCount[i] = 0; }
} }
void patch_screen_transition_interpolated(void) {
extern void patch_screen_transition_before(void) {
sScreenTransitionVerticesPos[0] = NULL;
sScreenTransitionVerticesPos[1] = NULL;
sScreenTransitionVertices = NULL;
sScreenTransitionVerticesPrev = NULL;
}
void patch_screen_transition_interpolated(f32 delta) {
if (sScreenTransitionVerticesPos[0] != NULL) { if (sScreenTransitionVerticesPos[0] != NULL) {
gSPVertex(sScreenTransitionVerticesPos[0], VIRTUAL_TO_PHYSICAL(sScreenTransitionVertices), 8, 0); for (s32 i = 0; i < 8; i++) {
gSPVertex(sScreenTransitionVerticesPos[1], VIRTUAL_TO_PHYSICAL(sScreenTransitionVertices), 4, 0); sScreenTransitionInterp[i] = sScreenTransitionVerticesPrev[i];
sScreenTransitionVerticesPos[0] = NULL; delta_interpolate_vec3f(sScreenTransitionInterp[i].n.ob,
sScreenTransitionVerticesPos[1] = NULL; sScreenTransitionVerticesPrev[i].n.ob,
sScreenTransitionVertices = NULL; sScreenTransitionVertices[i].n.ob, delta);
delta_interpolate_rgba(sScreenTransitionInterp[i].v.cn,
sScreenTransitionVerticesPrev[i].v.cn,
sScreenTransitionVertices[i].v.cn, delta);
}
gSPVertex(sScreenTransitionVerticesPos[0], VIRTUAL_TO_PHYSICAL(sScreenTransitionInterp), 8, 0);
gSPVertex(sScreenTransitionVerticesPos[1], VIRTUAL_TO_PHYSICAL(sScreenTransitionInterp), 4, 0);
} }
} }
@ -249,19 +266,20 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition
s16 centerTransX = center_tex_transition_x(transData, texTransTime, texTransPos); s16 centerTransX = center_tex_transition_x(transData, texTransTime, texTransPos);
s16 centerTransY = center_tex_transition_y(transData, texTransTime, texTransPos); s16 centerTransY = center_tex_transition_y(transData, texTransTime, texTransPos);
s16 texTransRadius = calc_tex_transition_radius(fadeTimer, 1.0f, transTime, transData); s16 texTransRadius = calc_tex_transition_radius(fadeTimer, 1.0f, transTime, transData);
s16 texTransRadiusInterpolated = calc_tex_transition_radius(fadeTimer, 0.5f, transTime, transData); s16 texTransRadiusPrev = calc_tex_transition_radius(fadeTimer, 0.0f, transTime, transData);
Vtx *verts = alloc_display_list(8 * sizeof(*verts)); Vtx *verts = alloc_display_list(8 * sizeof(*verts));
Vtx *vertsInterpolated = alloc_display_list(8 * sizeof(*vertsInterpolated)); Vtx *vertsPrev = alloc_display_list(8 * sizeof(*vertsPrev));
if (verts != NULL && vertsInterpolated != NULL) { if (verts != NULL && vertsPrev != NULL) {
load_tex_transition_vertex(verts, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, transTexType); load_tex_transition_vertex(verts, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, transTexType);
load_tex_transition_vertex(vertsInterpolated, fadeTimer, transData, centerTransX, centerTransY, texTransRadiusInterpolated, transTexType); load_tex_transition_vertex(vertsPrev, fadeTimer, transData, centerTransX, centerTransY, texTransRadiusPrev, transTexType);
sScreenTransitionVertices = verts; sScreenTransitionVertices = verts;
sScreenTransitionVerticesPrev = vertsPrev;
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen) gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen)
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2); gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
sScreenTransitionVerticesPos[0] = gDisplayListHead; sScreenTransitionVerticesPos[0] = gDisplayListHead;
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(vertsInterpolated), 8, 0); gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(vertsPrev), 8, 0);
gSPDisplayList(gDisplayListHead++, dl_transition_draw_filled_region); gSPDisplayList(gDisplayListHead++, dl_transition_draw_filled_region);
gDPPipeSync(gDisplayListHead++); gDPPipeSync(gDisplayListHead++);
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA); gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
@ -279,7 +297,7 @@ s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransition
} }
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
sScreenTransitionVerticesPos[1] = gDisplayListHead; sScreenTransitionVerticesPos[1] = gDisplayListHead;
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(vertsInterpolated), 4, 0); gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(vertsPrev), 4, 0);
gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123); gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
gSPDisplayList(gDisplayListHead++, dl_screen_transition_end); gSPDisplayList(gDisplayListHead++, dl_screen_transition_end);

View file

@ -15,6 +15,7 @@
#include "gfx_dimensions.h" #include "gfx_dimensions.h"
#include "game/rendering_graph_node.h" #include "game/rendering_graph_node.h"
#include "pc/utils/misc.h"
// frame counts for the zoom in, hold, and zoom out of title model // frame counts for the zoom in, hold, and zoom out of title model
#define INTRO_STEPS_ZOOM_IN 20 #define INTRO_STEPS_ZOOM_IN 20
@ -60,14 +61,20 @@ s8 gameOverBackgroundFlipOrder[] = { 0x00, 0x01, 0x02, 0x03, 0x07, 0x0B,
static Gfx *sIntroScalePos; static Gfx *sIntroScalePos;
static Vec3f sIntroScale; static Vec3f sIntroScale;
static Vec3f sIntroScalePrev;
void patch_title_screen_scales(void) { void patch_title_screen_before(void) {
sIntroScalePos = NULL;
}
void patch_title_screen_interpolated(f32 delta) {
if (sIntroScalePos != NULL) { if (sIntroScalePos != NULL) {
Mtx *scaleMat = alloc_display_list(sizeof(*scaleMat)); Mtx *scaleMat = alloc_display_list(sizeof(*scaleMat));
if (scaleMat == NULL) { return; } if (scaleMat == NULL) { return; }
guScale(scaleMat, sIntroScale[0], sIntroScale[1], sIntroScale[2]); Vec3f scaleInterp;
delta_interpolate_vec3f(scaleInterp, sIntroScalePrev, sIntroScale, delta);
guScale(scaleMat, scaleInterp[0], scaleInterp[1], scaleInterp[2]);
gSPMatrix(sIntroScalePos, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH); gSPMatrix(sIntroScalePos, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
sIntroScalePos = NULL;
} }
} }
@ -82,7 +89,6 @@ Gfx *geo_title_screen(s32 state, struct GraphNode *sp54, UNUSED void *context) {
f32 scaleY; // sp30 f32 scaleY; // sp30
f32 scaleZ; // sp2c f32 scaleZ; // sp2c
Vec3f scale; Vec3f scale;
Vec3f scaleInterpolated;
graphNode = sp54; graphNode = sp54;
dl = NULL; dl = NULL;
dlIter = NULL; dlIter = NULL;
@ -119,14 +125,12 @@ Gfx *geo_title_screen(s32 state, struct GraphNode *sp54, UNUSED void *context) {
scaleY = 0.0f; scaleY = 0.0f;
scaleZ = 0.0f; scaleZ = 0.0f;
} }
vec3f_copy(sIntroScalePrev, sIntroScale);
vec3f_set(scale, scaleX, scaleY, scaleZ); vec3f_set(scale, scaleX, scaleY, scaleZ);
// TODO: fixme
//interpolate_vectors(scaleInterpolated, sIntroScale, scale);
vec3f_copy(scaleInterpolated, scale);
vec3f_set(sIntroScale, scaleX, scaleY, scaleZ); vec3f_set(sIntroScale, scaleX, scaleY, scaleZ);
guScale(scaleMat, scaleInterpolated[0], scaleInterpolated[1], scaleInterpolated[2]);
guScale(scaleMat, sIntroScalePrev[0], sIntroScalePrev[1], sIntroScalePrev[2]);
sIntroScalePos = dlIter; sIntroScalePos = dlIter;
gSPMatrix(dlIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH); gSPMatrix(dlIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
gSPDisplayList(dlIter++, &intro_seg7_dl_0700B3A0); // draw model gSPDisplayList(dlIter++, &intro_seg7_dl_0700B3A0); // draw model

View file

@ -39,10 +39,10 @@ extern bool dynos_warp_to_level(s32 aLevel, s32 aArea, s32 aAct);
static void debug_warp_level1() { static void debug_warp_level1() {
// warp to credits // warp to credits
set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0); //set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
return; //return;
dynos_warp_to_level(LEVEL_BOB, 1, 1); dynos_warp_to_level(LEVEL_CCM, 1, 1);
} }
static void debug_warp_level2() { static void debug_warp_level2() {

View file

@ -100,28 +100,42 @@ void send_display_list(struct SPTask *spTask) {
static void patch_interpolations_before(void) { static void patch_interpolations_before(void) {
extern void mtx_patch_before(void); extern void mtx_patch_before(void);
extern void patch_screen_transition_before(void);
extern void patch_title_screen_before(void);
extern void patch_dialog_before(void);
extern void patch_hud_before(void);
extern void patch_paintings_before(void);
extern void patch_bubble_particles_before(void);
extern void patch_snow_particles_before(void);
mtx_patch_before(); mtx_patch_before();
patch_screen_transition_before();
patch_title_screen_before();
patch_dialog_before();
patch_hud_before();
patch_paintings_before();
patch_bubble_particles_before();
patch_snow_particles_before();
} }
static inline void patch_interpolations(f32 delta) { static inline void patch_interpolations(f32 delta) {
extern void mtx_patch_interpolated(f32 delta); extern void mtx_patch_interpolated(f32 delta);
extern void patch_screen_transition_interpolated(void); extern void patch_screen_transition_interpolated(f32 delta);
extern void patch_title_screen_scales(void); extern void patch_title_screen_interpolated(f32 delta);
extern void patch_interpolated_dialog(void); extern void patch_dialog_interpolated(f32 delta);
extern void patch_interpolated_hud(void); extern void patch_hud_interpolated(f32 delta);
extern void patch_interpolated_paintings(void); extern void patch_paintings_interpolated(f32 delta);
extern void patch_interpolated_bubble_particles(void); extern void patch_bubble_particles_interpolated(f32 delta);
extern void patch_interpolated_snow_particles(void); extern void patch_snow_particles_interpolated(f32 delta);
extern void djui_render_patch(void); extern void djui_render_patch(void);
mtx_patch_interpolated(delta); mtx_patch_interpolated(delta);
/*patch_screen_transition_interpolated(); patch_screen_transition_interpolated(delta);
patch_title_screen_scales(); patch_title_screen_interpolated(delta);
patch_interpolated_dialog(); patch_dialog_interpolated(delta);
patch_interpolated_hud(); patch_hud_interpolated(delta);
patch_interpolated_paintings(); patch_paintings_interpolated(delta);
patch_interpolated_bubble_particles(); patch_bubble_particles_interpolated(delta);
patch_interpolated_snow_particles(); patch_snow_particles_interpolated(delta);
djui_render_patch();*/ /*djui_render_patch();*/
} }
void produce_uncapped_frames(void) { void produce_uncapped_frames(void) {

View file

@ -120,7 +120,25 @@ f32 delta_interpolate_f32(f32 start, f32 end, f32 delta) {
return start * (1.0f - delta) + end * delta; return start * (1.0f - delta) + end * delta;
} }
void delta_interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b, f32 delta) { s32 delta_interpolate_s32(s32 a, s32 b, f32 delta) {
return a * (1.0f - delta) + b * delta;
}
void delta_interpolate_vec3f(Vec3f res, Vec3f a, Vec3f b, f32 delta) {
f32 antiDelta = 1.0f - delta;
res[0] = ((a[0] * antiDelta) + (b[0] * delta));
res[1] = ((a[1] * antiDelta) + (b[1] * delta));
res[2] = ((a[2] * antiDelta) + (b[2] * delta));
}
void delta_interpolate_vec3s(Vec3s res, Vec3s a, Vec3s b, f32 delta) {
f32 antiDelta = 1.0f - delta;
res[0] = ((a[0] * antiDelta) + (b[0] * delta));
res[1] = ((a[1] * antiDelta) + (b[1] * delta));
res[2] = ((a[2] * antiDelta) + (b[2] * delta));
}
void delta_interpolate_normal(s8* res, s8* a, s8* b, f32 delta) {
f32 antiDelta = 1.0f - delta; f32 antiDelta = 1.0f - delta;
res[0] = ((a[0] * antiDelta) + (b[0] * delta)); res[0] = ((a[0] * antiDelta) + (b[0] * delta));
res[1] = ((a[1] * antiDelta) + (b[1] * delta)); res[1] = ((a[1] * antiDelta) + (b[1] * delta));
@ -136,6 +154,14 @@ void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta) {
} }
} }
void delta_interpolate_rgba(u8* res, u8* a, u8* b, f32 delta) {
f32 antiDelta = 1.0f - delta;
res[0] = ((a[0] * antiDelta) + (b[0] * delta));
res[1] = ((a[1] * antiDelta) + (b[1] * delta));
res[2] = ((a[2] * antiDelta) + (b[2] * delta));
res[3] = ((a[3] * antiDelta) + (b[3] * delta));
}
/* /*
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b) { void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b) {

View file

@ -15,7 +15,11 @@ u32 clock_elapsed_ticks(void);
void file_get_line(char* buffer, size_t maxLength, FILE* fp); void file_get_line(char* buffer, size_t maxLength, FILE* fp);
f32 delta_interpolate_f32(f32 start, f32 end, f32 delta); f32 delta_interpolate_f32(f32 start, f32 end, f32 delta);
void delta_interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b, f32 delta); s32 delta_interpolate_s32(s32 a, s32 b, f32 delta);
void delta_interpolate_vec3f(Vec3f res, Vec3f a, Vec3f b, f32 delta);
void delta_interpolate_vec3s(Vec3s res, Vec3s a, Vec3s b, f32 delta);
void delta_interpolate_normal(s8* res, s8* a, s8* b, f32 delta);
void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta); void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta);
void delta_interpolate_rgba(u8* res, u8* a, u8* b, f32 delta);
#endif #endif