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 "textures.h"
#include "game/rendering_graph_node.h"
#include "pc/utils/misc.h"
/**
* 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 } },
};
static Gfx sGfxSaved[60 / 5];
static Gfx *sBubbleInterpolatedDisplayListPos[60 / 5];
static Vec3s sPrevBubblePositions[60];
Gfx *envfx_update_bubble_particles_internal(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated);
void patch_interpolated_bubble_particles(void) {
s32 i;
for (i = 0; i < 60 / 5; i++) {
if (sBubbleInterpolatedDisplayListPos[i] != NULL) {
*sBubbleInterpolatedDisplayListPos[i] = sGfxSaved[i];
sBubbleInterpolatedDisplayListPos[i] = NULL;
static s32 sBubbleGfxMode;
static Gfx* sBubbleGfxPos;
static Vtx* sBubbleInternalGfxPos[65 / 5];
static Vec3s sBubbleGfxCamFrom;
static Vec3s sBubbleGfxCamTo;
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)->isAlive = 1;
(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) {
(gEnvFxBuffer + i)->animFrame += 1;
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;
}
floorY =
find_floor((gEnvFxBuffer + index)->xPos, centerY + 500, (gEnvFxBuffer + index)->zPos, &surface);
floorY = find_floor((gEnvFxBuffer + index)->xPos, centerY + 500, (gEnvFxBuffer + index)->zPos, &surface);
if (surface == NULL) {
(gEnvFxBuffer + index)->yPos = FLOOR_LOWER_LIMIT_MISC;
return;
@ -178,6 +188,7 @@ void envfx_update_lava(Vec3s centerPos) {
for (i = 0; i < sBubbleParticleMaxCount; i++) {
if ((gEnvFxBuffer + i)->isAlive == 0) {
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;
} else if ((timer & 0x01) == 0) {
(gEnvFxBuffer + i)->animFrame += 1;
@ -257,10 +268,13 @@ void envfx_update_whirlpool(void) {
(gEnvFxBuffer + i)->unusedBubbleVar = 0;
(gEnvFxBuffer + i)->isAlive = 1;
(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,
&(gEnvFxBuffer + i)->zPos);
} else {
}
if ((gEnvFxBuffer + i)->isAlive != 0) {
(gEnvFxBuffer + i)->angleAndDist[1] -= 40;
(gEnvFxBuffer + i)->angleAndDist[0] +=
(s16)(3000 - (gEnvFxBuffer + i)->angleAndDist[1] * 2) + 0x400;
@ -307,15 +321,11 @@ void envfx_update_jetstream(void) {
if ((gEnvFxBuffer + i)->isAlive == 0) {
(gEnvFxBuffer + i)->angleAndDist[1] = random_float() * 300.0f;
(gEnvFxBuffer + i)->angleAndDist[0] = random_u16();
(gEnvFxBuffer + i)->xPos =
gEnvFxBubbleConfig[ENVFX_STATE_SRC_X]
+ sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
(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)->xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
(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;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else {
(gEnvFxBuffer + i)->angleAndDist[1] += 10;
(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,
* 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) {
case ENVFX_FLOWERS:
envfx_update_flower(camTo);
if (!interpolated) { envfx_update_flower(camTo); }
vertex1[0] = 50; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 75; vertex2[2] = 0;
vertex3[0] = -50; vertex3[1] = 0; vertex3[2] = 0;
break;
case ENVFX_LAVA_BUBBLES:
envfx_update_lava(camTo);
if (!interpolated) { envfx_update_lava(camTo); }
vertex1[0] = 100; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 150; vertex2[2] = 0;
vertex3[0] = -100; vertex3[1] = 0; vertex3[2] = 0;
break;
case ENVFX_WHIRLPOOL_BUBBLES:
envfx_update_whirlpool();
if (!interpolated) { envfx_update_whirlpool(); }
vertex1[0] = 40; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 60; vertex2[2] = 0;
vertex3[0] = -40; vertex3[1] = 0; vertex3[2] = 0;
break;
case ENVFX_JETSTREAM_BUBBLES:
envfx_update_jetstream();
if (!interpolated) { envfx_update_jetstream(); }
vertex1[0] = 40; vertex1[1] = 0; vertex1[2] = 0;
vertex2[0] = 0; vertex2[1] = 60; vertex2[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
*/
void append_bubble_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3,
Vtx *template) {
Vtx *template, u8 interpolated) {
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) {
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) {
vertBuf[i] = template[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];
(vertBuf + i)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex1[2];
s32 xPos;
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] = template[1];
(vertBuf + i + 1)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex2[0];
(vertBuf + i + 1)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex2[1];
(vertBuf + i + 1)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex2[2];
(vertBuf + i + 1)->v.ob[0] = xPos + vertex2[0];
(vertBuf + i + 1)->v.ob[1] = yPos + vertex2[1];
(vertBuf + i + 1)->v.ob[2] = zPos + vertex2[2];
vertBuf[i + 2] = template[2];
(vertBuf + i + 2)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex3[0];
(vertBuf + i + 2)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex3[1];
(vertBuf + i + 2)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex3[2];
(vertBuf + i + 2)->v.ob[0] = xPos + vertex3[0];
(vertBuf + i + 2)->v.ob[1] = yPos + vertex3[1];
(vertBuf + i + 2)->v.ob[2] = zPos + vertex3[2];
}
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);
}
/**
* 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) {
Gfx *envfx_update_bubble_particles_internal(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated) {
s32 i;
s16 radius, pitch, yaw;
Vec3s vertex1 = { 0 };
Vec3s vertex2 = { 0 };
Vec3s vertex3 = { 0 };
Vec3s interpolatedVertices[3] = { 0 };
static Vec3s prevVertex1;
static Vec3s prevVertex2;
static Vec3s prevVertex3;
static u32 prevTimestamp;
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) {
return NULL;
}
@ -507,60 +538,21 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
sGfxCursor = gfxStart;
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);
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);
for (i = 0; i < sBubbleParticleMaxCount; i += 5) {
Vtx *interpolatedVertBuf = alloc_display_list(15 * sizeof(Vtx));
if (interpolatedVertBuf == NULL) { continue; }
s32 j, k;
gDPPipeSync(sGfxCursor++);
envfx_set_bubble_texture(mode, i);
sBubbleInterpolatedDisplayListPos[i / 5] = sGfxCursor;
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);
append_bubble_vertex_buffer(sGfxCursor++, i, vertex1, vertex2, vertex3, (Vtx *) gBubbleTempVtx, interpolated);
gSP1Triangle(sGfxCursor++, 0, 1, 2, 0);
gSP1Triangle(sGfxCursor++, 3, 4, 5, 0);
gSP1Triangle(sGfxCursor++, 6, 7, 8, 0);
gSP1Triangle(sGfxCursor++, 9, 10, 11, 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);
gSPEndDisplayList(sGfxCursor++);
@ -568,6 +560,14 @@ Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFro
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,
* which is set by the whirlpool or jet stream behavior.

View file

@ -11,6 +11,7 @@
#include "engine/behavior_script.h"
#include "audio/external.h"
#include "obj_behaviors.h"
#include "pc/utils/misc.h"
/**
* 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_0B006CD8;
static struct {
Gfx *pos;
Vtx vertices[15];
} sPrevSnowVertices[140 / 5];
static s16 sPrevSnowParticleCount;
static u32 sPrevSnowTimestamp;
Gfx *envfx_update_snow_internal(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated);
void patch_interpolated_snow_particles(void) {
int i;
static s32 sSnowGfxMode;
static Gfx* sSnowGfxPos;
static Vtx* sSnowInternalGfxPos[140 / 5];
static Vec3s sSnowGfxCamFrom;
static Vec3s sSnowGfxCamTo;
static Vec3s sSnowGfxMarioPos;
if (gGlobalTimer != sPrevSnowTimestamp + 1) {
return;
void patch_snow_particles_before(void) {
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) {
gSPVertex(sPrevSnowVertices[i / 5].pos,
VIRTUAL_TO_PHYSICAL(sPrevSnowVertices[i / 5].vertices), 15, 0);
void patch_snow_particles_interpolated(UNUSED f32 delta) {
if (sSnowGfxPos) {
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)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else {
(gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2);
(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)->isAlive = 1;
(gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer;
vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos);
} else {
(gEnvFxBuffer + i)->xPos += random_float() * 2 - 1.0f + (s16)(deltaX / 1.2) + 20.0f;
(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)->isAlive = 1;
(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
* 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;
Vtx *vertBuf = (Vtx *) alloc_display_list(15 * sizeof(Vtx));
Vtx *vertBufInterpolated = (Vtx *) alloc_display_list(15 * sizeof(Vtx));
Vtx *v;
Vtx *vertBuf;
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;
}
for (i = 0; i < 15; i += 3) {
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];
(vertBuf + i)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex1[2];
s32 xPos;
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)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex2[0];
(vertBuf + i + 1)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex2[1];
(vertBuf + i + 1)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex2[2];
(vertBuf + i + 1)->v.ob[0] = xPos + vertex2[0];
(vertBuf + i + 1)->v.ob[1] = yPos + vertex2[1];
(vertBuf + i + 1)->v.ob[2] = zPos + vertex2[2];
vertBuf[i + 2] = gSnowTempVtx[2];
(vertBuf + i + 2)->v.ob[0] = (gEnvFxBuffer + (index + i / 3))->xPos + vertex3[0];
(vertBuf + i + 2)->v.ob[1] = (gEnvFxBuffer + (index + i / 3))->yPos + vertex3[1];
(vertBuf + i + 2)->v.ob[2] = (gEnvFxBuffer + (index + i / 3))->zPos + vertex3[2];
(vertBuf + i + 2)->v.ob[0] = xPos + vertex3[0];
(vertBuf + i + 2)->v.ob[1] = yPos + vertex3[1];
(vertBuf + i + 2)->v.ob[2] = zPos + vertex3[2];
}
for (i = 0; i < 15; i++) {
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);
gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0);
}
/**
* 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) {
Gfx *envfx_update_snow_internal(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo, u8 interpolated) {
s32 i;
s16 radius, pitch, yaw;
Vec3s snowCylinderPos;
@ -426,7 +438,17 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
vertex2 = gSnowFlakeVertex2;
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;
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);
envfx_update_snow_normal(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]);
if (!interpolated) { envfx_update_snow_normal(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); }
break;
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);
envfx_update_snow_water(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]);
if (!interpolated) { envfx_update_snow_water(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); }
break;
case ENVFX_SNOW_BLIZZARD:
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);
envfx_update_snow_blizzard(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]);
if (!interpolated) { envfx_update_snow_blizzard(snowCylinderPos[0], snowCylinderPos[1], snowCylinderPos[2]); }
break;
}
@ -483,7 +505,7 @@ Gfx *envfx_update_snow(s32 snowMode, Vec3s marioPos, Vec3s camFrom, Vec3s camTo)
}
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++, 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++, 12, 13, 14, 0);
}
sPrevSnowParticleCount = gSnowParticleCount;
sPrevSnowTimestamp = gGlobalTimer;
gSPDisplayList(gfx++, &tiny_bubble_dl_0B006AB0) gSPEndDisplayList(gfx++);
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)
* 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
//s8 filler20[56 - 0x20];
u32 spawnTimestamp;
Vec3s prevPos;
};
extern s8 gEnvFxMode;

View file

@ -17,6 +17,7 @@
#include "print.h"
#include "pc/configfile.h"
#include "pc/network/network.h"
#include "pc/utils/misc.h"
extern bool gDjuiInMainMenu;
u8 gOverrideHideHud;
@ -64,18 +65,26 @@ static struct UnusedHUDStruct sUnusedHUDValues = { 0x00, 0x0A, 0x00 };
static struct CameraHUD sCameraHUD = { CAM_STATUS_NONE };
static u32 sPowerMeterLastRenderTimestamp;
static s16 sPowerMeterLastY;
static u32 sPowerMeterPrevTimestamp;
static f32 sPowerMeterPrevY;
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) {
Mtx *mtx = alloc_display_list(sizeof(Mtx));
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),
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) {
Mtx *mtx;
f32 interpolatedY;
mtx = alloc_display_list(sizeof(Mtx));
@ -139,14 +147,7 @@ void render_dl_power_meter(s16 numHealthWedges) {
return;
}
if (gGlobalTimer == sPowerMeterLastRenderTimestamp + 1) {
interpolatedY = (sPowerMeterLastY + sPowerMeterHUD.y) / 2.0f;
} else {
interpolatedY = sPowerMeterHUD.y;
}
guTranslate(mtx, (f32) sPowerMeterHUD.x, interpolatedY, 0);
sPowerMeterLastY = sPowerMeterHUD.y;
sPowerMeterLastRenderTimestamp = gGlobalTimer;
guTranslate(mtx, (f32) sPowerMeterHUD.x, sPowerMeterPrevY, 0);
sPowerMeterDisplayListPos = gDisplayListHead;
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(mtx++),
@ -202,6 +203,7 @@ static void animate_power_meter_deemphasizing(void) {
if (sPowerMeterHUD.y >= 201) {
sPowerMeterHUD.y = 200;
sPowerMeterPrevY = 200;
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) {
sPowerMeterHUD.animation = POWER_METER_EMPHASIZED;
sPowerMeterHUD.y = 166;
sPowerMeterPrevY = 166;
}
// Show power meter if health is full, has 8

View file

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

View file

@ -16,6 +16,7 @@
#include "paintings.h"
#include "save_file.h"
#include "segment2.h"
#include "pc/utils/misc.h"
/**
* @file paintings.c
@ -189,29 +190,74 @@ struct Painting **sPaintingGroups[] = {
s16 gPaintingUpdateCounter = 1;
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 s32 sVerticesCount;
void patch_interpolated_paintings(void) {
if (sVerticesPtr[0] != NULL) {
void patch_paintings_before(void) {
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;
if (sVerticesPtr[1] != NULL) {
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++) {
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 {
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;
}
for (map = 0; map < numVtx; map++) {
Vtx v = verts[map];
if (gGlobalTimer == sLastVerticesTimestamp + 1) {
Vtx* v = &verts[map];
if (gGlobalTimer == sVerticesPrevTimestamp + 1) {
s32 i;
Vtx_Interp* vCur = &sVerticesCur[sVerticesCount + map];
Vtx_Interp* vPrev = (sVerticesPrev && sVertexSwaps > 2) ? &sVerticesPrev[sVerticesCount + map] : NULL;
for (i = 0; i < 3; i++) {
verts[map].n.ob[i] = (v.n.ob[i] + sLastVertices[sVerticesCount + map].n.ob[i]) / 2;
verts[map].n.n[i] = (v.n.n[i] + sLastVertices[sVerticesCount + map].n.n[i]) / 2;
// save current
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;
sVerticesCount += numVtx;
@ -1010,7 +1065,7 @@ Gfx *painting_ripple_image(struct Painting *painting) {
meshTris = textureMap[meshVerts * 3 + 1];
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.
painting_update_ripple_state(painting);
@ -1048,7 +1103,7 @@ Gfx *painting_ripple_env_mapped(struct Painting *painting) {
meshVerts = textureMap[0];
meshTris = textureMap[meshVerts * 3 + 1];
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.
painting_update_ripple_state(painting);

View file

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

View file

@ -12,25 +12,42 @@
#include "screen_transition.h"
#include "segment2.h"
#include "sm64.h"
#include "pc/utils/misc.h"
u8 sTransitionColorFadeCount[4] = { 0 };
u16 sTransitionTextureFadeCount[2] = { 0 };
static Gfx *sScreenTransitionVerticesPos[2];
static Vtx *sScreenTransitionVertices;
static Vtx *sScreenTransitionVerticesPrev;
static Vtx sScreenTransitionInterp[8] = { 0 };
void reset_screen_transition_timers(void) {
for (s32 i = 0; i < 4; i++) { sTransitionColorFadeCount[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) {
gSPVertex(sScreenTransitionVerticesPos[0], VIRTUAL_TO_PHYSICAL(sScreenTransitionVertices), 8, 0);
gSPVertex(sScreenTransitionVerticesPos[1], VIRTUAL_TO_PHYSICAL(sScreenTransitionVertices), 4, 0);
sScreenTransitionVerticesPos[0] = NULL;
sScreenTransitionVerticesPos[1] = NULL;
sScreenTransitionVertices = NULL;
for (s32 i = 0; i < 8; i++) {
sScreenTransitionInterp[i] = sScreenTransitionVerticesPrev[i];
delta_interpolate_vec3f(sScreenTransitionInterp[i].n.ob,
sScreenTransitionVerticesPrev[i].n.ob,
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 centerTransY = center_tex_transition_y(transData, texTransTime, texTransPos);
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 *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(vertsInterpolated, fadeTimer, transData, centerTransX, centerTransY, texTransRadiusInterpolated, transTexType);
load_tex_transition_vertex(vertsPrev, fadeTimer, transData, centerTransX, centerTransY, texTransRadiusPrev, transTexType);
sScreenTransitionVertices = verts;
sScreenTransitionVerticesPrev = vertsPrev;
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen)
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
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);
gDPPipeSync(gDisplayListHead++);
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);
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);
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
gSPDisplayList(gDisplayListHead++, dl_screen_transition_end);

View file

@ -15,6 +15,7 @@
#include "gfx_dimensions.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
#define INTRO_STEPS_ZOOM_IN 20
@ -60,14 +61,20 @@ s8 gameOverBackgroundFlipOrder[] = { 0x00, 0x01, 0x02, 0x03, 0x07, 0x0B,
static Gfx *sIntroScalePos;
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) {
Mtx *scaleMat = alloc_display_list(sizeof(*scaleMat));
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);
sIntroScalePos = NULL;
}
}
@ -82,7 +89,6 @@ Gfx *geo_title_screen(s32 state, struct GraphNode *sp54, UNUSED void *context) {
f32 scaleY; // sp30
f32 scaleZ; // sp2c
Vec3f scale;
Vec3f scaleInterpolated;
graphNode = sp54;
dl = NULL;
dlIter = NULL;
@ -119,14 +125,12 @@ Gfx *geo_title_screen(s32 state, struct GraphNode *sp54, UNUSED void *context) {
scaleY = 0.0f;
scaleZ = 0.0f;
}
vec3f_copy(sIntroScalePrev, sIntroScale);
vec3f_set(scale, scaleX, scaleY, scaleZ);
// TODO: fixme
//interpolate_vectors(scaleInterpolated, sIntroScale, scale);
vec3f_copy(scaleInterpolated, scale);
vec3f_set(sIntroScale, scaleX, scaleY, scaleZ);
guScale(scaleMat, scaleInterpolated[0], scaleInterpolated[1], scaleInterpolated[2]);
guScale(scaleMat, sIntroScalePrev[0], sIntroScalePrev[1], sIntroScalePrev[2]);
sIntroScalePos = dlIter;
gSPMatrix(dlIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
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() {
// warp to credits
set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
return;
//set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0);
//return;
dynos_warp_to_level(LEVEL_BOB, 1, 1);
dynos_warp_to_level(LEVEL_CCM, 1, 1);
}
static void debug_warp_level2() {

View file

@ -100,28 +100,42 @@ void send_display_list(struct SPTask *spTask) {
static void patch_interpolations_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();
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) {
extern void mtx_patch_interpolated(f32 delta);
extern void patch_screen_transition_interpolated(void);
extern void patch_title_screen_scales(void);
extern void patch_interpolated_dialog(void);
extern void patch_interpolated_hud(void);
extern void patch_interpolated_paintings(void);
extern void patch_interpolated_bubble_particles(void);
extern void patch_interpolated_snow_particles(void);
extern void patch_screen_transition_interpolated(f32 delta);
extern void patch_title_screen_interpolated(f32 delta);
extern void patch_dialog_interpolated(f32 delta);
extern void patch_hud_interpolated(f32 delta);
extern void patch_paintings_interpolated(f32 delta);
extern void patch_bubble_particles_interpolated(f32 delta);
extern void patch_snow_particles_interpolated(f32 delta);
extern void djui_render_patch(void);
mtx_patch_interpolated(delta);
/*patch_screen_transition_interpolated();
patch_title_screen_scales();
patch_interpolated_dialog();
patch_interpolated_hud();
patch_interpolated_paintings();
patch_interpolated_bubble_particles();
patch_interpolated_snow_particles();
djui_render_patch();*/
patch_screen_transition_interpolated(delta);
patch_title_screen_interpolated(delta);
patch_dialog_interpolated(delta);
patch_hud_interpolated(delta);
patch_paintings_interpolated(delta);
patch_bubble_particles_interpolated(delta);
patch_snow_particles_interpolated(delta);
/*djui_render_patch();*/
}
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;
}
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;
res[0] = ((a[0] * antiDelta) + (b[0] * 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) {

View file

@ -15,7 +15,11 @@ u32 clock_elapsed_ticks(void);
void file_get_line(char* buffer, size_t maxLength, FILE* fp);
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_rgba(u8* res, u8* a, u8* b, f32 delta);
#endif