You've already forked HackerSM64
mirror of
https://github.com/HackerN64/HackerSM64.git
synced 2026-01-21 10:35:32 -08:00
Improved transitions (#642)
* Improved transitions Code quality improvements. Shape transitions now all scale down to 0 instead of 16 (mario and bowser). Ease in was added which leads to far smoother transitions. HD_TRANSITIONS define added, makes use of the tex edge render mode to deliver smooth transition textures. lerpf was added to math utils. * Cleaner textures, rounding only during vertex creation * Another attempt * cozies naming suggestion * Improvements and suggestions SHARP_TRANSITION_TEXTURES is now off by default (I still think the textures for it could be improved). lerpf, to_smoothstop, smoothstart, smoothstop and smoothstep have all been added. make_vertex has been inlined. make_simple_vertex has been added (colourless vertex). Transition colors (and canon colors) are now defined using primative colour instead of setting individual vertices color´s. Transition´s now use smoothstep (ease-in-out) instead of ease out only. Naming has been improved. * Proper function inling and removal of GBI_FLOATS variant of make_vertex and make_simple_vertex * More requested changes * Accidental final new line removal fixed * Comment about pop in fix. * Comment fix The issue with writing comments for stuff is when you want to change code later on.
This commit is contained in:
@@ -2673,6 +2673,25 @@ UNUSED ALIGNED8 static const Texture texture_radial_light[] = {
|
||||
#include "textures/segment2/light_quarter_circle.ia16.inc.c"
|
||||
};
|
||||
|
||||
#ifdef SHARP_TRANSITION_TEXTURES
|
||||
const Texture texture_transition_star_half[] = {
|
||||
#include "textures/segment2/transition_star_half.i8.inc.c"
|
||||
};
|
||||
|
||||
const Texture texture_transition_circle_half[] = {
|
||||
#include "textures/segment2/transition_circle_half.i8.inc.c"
|
||||
};
|
||||
|
||||
const Texture texture_transition_mario[] = {
|
||||
#include "textures/segment2/transition_mario.i8.inc.c"
|
||||
};
|
||||
|
||||
const Texture texture_transition_bowser_half[] = {
|
||||
#include "textures/segment2/transition_bowser_half.i8.inc.c"
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
const Texture texture_transition_star_half[] = {
|
||||
#include "textures/segment2/segment2.0F458.ia8.inc.c"
|
||||
};
|
||||
@@ -2688,6 +2707,7 @@ const Texture texture_transition_mario[] = {
|
||||
const Texture texture_transition_bowser_half[] = {
|
||||
#include "textures/segment2/segment2.11458.ia8.inc.c"
|
||||
};
|
||||
#endif
|
||||
|
||||
const Texture texture_waterbox_water[] = {
|
||||
#include "textures/segment2/segment2.11C58.rgba16.inc.c"
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
/**
|
||||
* Limits the horizontal fov on emulator like on console. May break viewport widescreen hacks.
|
||||
*/
|
||||
//#define HORIZONTAL_CULLING_ON_EMULATOR
|
||||
// #define HORIZONTAL_CULLING_ON_EMULATOR
|
||||
|
||||
/**
|
||||
* Makes objects bellow the screen be culled.
|
||||
@@ -150,3 +150,13 @@
|
||||
* will be used instead.
|
||||
*/
|
||||
#define DEFAULT_CULLING_RADIUS 300
|
||||
|
||||
/**
|
||||
* Eases the textured screen transitions to make them look smoother.
|
||||
*/
|
||||
#define EASE_IN_OUT_TRANSITIONS
|
||||
|
||||
/**
|
||||
* Makes use of the tex edge render mode to deliver smooth transition textures
|
||||
*/
|
||||
// #define SHARP_TRANSITION_TEXTURES
|
||||
|
||||
@@ -598,4 +598,30 @@ ALWAYS_INLINE f32 remap(f32 x, f32 fromA, f32 toA, f32 fromB, f32 toB) {
|
||||
return (x - fromA) / (toA - fromA) * (toB - fromB) + fromB;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE f32 lerpf(f32 from, f32 to, f32 amount) {
|
||||
return (from + (to - from) * amount);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE f32 to_smoothstop(f32 x) {
|
||||
f32 sq = sqr(1.0f - x);
|
||||
return 1.0f - sq;
|
||||
}
|
||||
|
||||
// Commonly known as ease-in
|
||||
ALWAYS_INLINE f32 smoothstart(f32 from, f32 to, f32 amount) {
|
||||
return lerpf(from, to, sqr(amount));
|
||||
}
|
||||
|
||||
// Commonly known as ease-out
|
||||
ALWAYS_INLINE f32 smoothstop(f32 from, f32 to, f32 amount) {
|
||||
return lerpf(from, to, to_smoothstop(amount));
|
||||
}
|
||||
|
||||
// Commonly known as ease-in-out
|
||||
ALWAYS_INLINE f32 smoothstep(f32 from, f32 to, f32 amount) {
|
||||
amount = sqr(amount) * (3.0f - 2.0f * amount);
|
||||
|
||||
return lerpf(from, to, amount);
|
||||
}
|
||||
|
||||
#endif // MATH_UTIL_H
|
||||
|
||||
@@ -349,22 +349,34 @@ void play_transition(s16 transType, s16 time, Color red, Color green, Color blue
|
||||
gWarpTransition.data.endTexX = SCREEN_CENTER_X;
|
||||
gWarpTransition.data.endTexY = SCREEN_CENTER_Y;
|
||||
|
||||
gWarpTransition.data.texTimer = 0;
|
||||
gWarpTransition.data.angleSpeed = DEGREES(0);
|
||||
|
||||
s16 fullRadius = GFX_DIMENSIONS_FULL_RADIUS;
|
||||
|
||||
// HackerSM64: this fixes the pop-in with texture transition, comment out this switch
|
||||
// statement if you want to restore the original full radius.
|
||||
switch (transType){
|
||||
case WARP_TRANSITION_TYPE_BOWSER:
|
||||
case WARP_TRANSITION_FADE_INTO_BOWSER:
|
||||
fullRadius *= 4;
|
||||
break;
|
||||
|
||||
case WARP_TRANSITION_FADE_FROM_MARIO:
|
||||
case WARP_TRANSITION_FADE_INTO_MARIO:
|
||||
|
||||
case WARP_TRANSITION_FADE_FROM_STAR:
|
||||
case WARP_TRANSITION_FADE_INTO_STAR:
|
||||
fullRadius *= 1.5f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (transType & WARP_TRANSITION_FADE_INTO) { // Is the image fading in?
|
||||
gWarpTransition.data.startTexRadius = GFX_DIMENSIONS_FULL_RADIUS;
|
||||
if (transType >= WARP_TRANSITION_FADES_INTO_LARGE) {
|
||||
gWarpTransition.data.endTexRadius = 16;
|
||||
} else {
|
||||
gWarpTransition.data.endTexRadius = 0;
|
||||
}
|
||||
gWarpTransition.data.startTexRadius = fullRadius;
|
||||
gWarpTransition.data.endTexRadius = 0;
|
||||
|
||||
} else { // The image is fading out. (Reverses start & end circles)
|
||||
if (transType >= WARP_TRANSITION_FADES_FROM_LARGE) {
|
||||
gWarpTransition.data.startTexRadius = 16;
|
||||
} else {
|
||||
gWarpTransition.data.startTexRadius = 0;
|
||||
}
|
||||
gWarpTransition.data.endTexRadius = GFX_DIMENSIONS_FULL_RADIUS;
|
||||
gWarpTransition.data.startTexRadius = 0;
|
||||
gWarpTransition.data.endTexRadius = fullRadius;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -419,7 +431,7 @@ void render_game(void) {
|
||||
|
||||
if (gWarpTransition.isActive) {
|
||||
if (gWarpTransDelay == 0) {
|
||||
gWarpTransition.isActive = !render_screen_transition(0, gWarpTransition.type, gWarpTransition.time,
|
||||
gWarpTransition.isActive = !render_screen_transition(gWarpTransition.type, gWarpTransition.time,
|
||||
&gWarpTransition.data);
|
||||
if (!gWarpTransition.isActive) {
|
||||
if (gWarpTransition.type & WARP_TRANSITION_FADE_INTO) {
|
||||
|
||||
@@ -93,7 +93,7 @@ struct WarpTransitionData {
|
||||
/*0x0C*/ s16 endTexX;
|
||||
/*0x0E*/ s16 endTexY;
|
||||
|
||||
/*0x10*/ s16 texTimer; // always 0, does seems to affect transition when disabled
|
||||
/*0x10*/ s16 angleSpeed;
|
||||
};
|
||||
|
||||
enum WarpTransitionFadeDirections {
|
||||
|
||||
@@ -36,31 +36,6 @@ static s16 sFlyingCarpetRippleTimer = 0;
|
||||
|
||||
s8 gFlyingCarpetState;
|
||||
|
||||
/**
|
||||
* Create a vertex with the given parameters and insert it into `vtx` at
|
||||
* position `n`.
|
||||
*
|
||||
* Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5.
|
||||
*/
|
||||
#ifndef GBI_FLOATS
|
||||
void make_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) {
|
||||
#else
|
||||
void make_vertex(Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) {
|
||||
#endif
|
||||
vtx[n].v.ob[0] = x;
|
||||
vtx[n].v.ob[1] = y;
|
||||
vtx[n].v.ob[2] = z;
|
||||
|
||||
vtx[n].v.flag = 0;
|
||||
|
||||
vtx[n].v.tc[0] = tx;
|
||||
vtx[n].v.tc[1] = ty;
|
||||
|
||||
vtx[n].v.cn[0] = r;
|
||||
vtx[n].v.cn[1] = g;
|
||||
vtx[n].v.cn[2] = b;
|
||||
vtx[n].v.cn[3] = a;
|
||||
}
|
||||
|
||||
#define NUM_STARS_REQUIRED_FOR_WING_CAP_LIGHT 10
|
||||
/**
|
||||
|
||||
@@ -12,15 +12,50 @@ enum FlyingCarpetState {
|
||||
|
||||
extern s8 gFlyingCarpetState;
|
||||
|
||||
#ifndef GBI_FLOATS
|
||||
extern void make_vertex(
|
||||
Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a
|
||||
);
|
||||
#else
|
||||
extern void make_vertex(
|
||||
Vtx *vtx, s32 n, f32 x, f32 y, f32 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a
|
||||
);
|
||||
#endif
|
||||
/**
|
||||
* Create a vertex with the given parameters and insert it into `vtx` at
|
||||
* position `n`.
|
||||
*
|
||||
* Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5.
|
||||
*/
|
||||
ALWAYS_INLINE void make_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty, u8 r, u8 g, u8 b, u8 a) {
|
||||
vtx[n].v.ob[0] = x;
|
||||
vtx[n].v.ob[1] = y;
|
||||
vtx[n].v.ob[2] = z;
|
||||
|
||||
vtx[n].v.flag = 0;
|
||||
|
||||
vtx[n].v.tc[0] = tx;
|
||||
vtx[n].v.tc[1] = ty;
|
||||
|
||||
vtx[n].v.cn[0] = r;
|
||||
vtx[n].v.cn[1] = g;
|
||||
vtx[n].v.cn[2] = b;
|
||||
vtx[n].v.cn[3] = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a colourless vertex with the given parameters and insert it into `vtx` at
|
||||
* position `n`.
|
||||
*
|
||||
* Texture coordinates are s10.5 fixed-point, which means you should left-shift the actual coordinates by 5.
|
||||
*/
|
||||
ALWAYS_INLINE void make_simple_vertex(Vtx *vtx, s32 n, s16 x, s16 y, s16 z, s16 tx, s16 ty) {
|
||||
vtx[n].v.ob[0] = x;
|
||||
vtx[n].v.ob[1] = y;
|
||||
vtx[n].v.ob[2] = z;
|
||||
|
||||
vtx[n].v.flag = 0;
|
||||
|
||||
vtx[n].v.tc[0] = tx;
|
||||
vtx[n].v.tc[1] = ty;
|
||||
|
||||
vtx[n].v.cn[0] = 255;
|
||||
vtx[n].v.cn[1] = 255;
|
||||
vtx[n].v.cn[2] = 255;
|
||||
vtx[n].v.cn[3] = 255;
|
||||
}
|
||||
|
||||
extern Gfx *geo_exec_inside_castle_light(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx);
|
||||
extern Gfx *geo_exec_flying_carpet_timer_update(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx);
|
||||
extern Gfx *geo_exec_flying_carpet_create(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx);
|
||||
|
||||
@@ -13,150 +13,8 @@
|
||||
#include "segment2.h"
|
||||
#include "sm64.h"
|
||||
|
||||
u8 sTransitionColorFadeCount[4] = { 0 };
|
||||
u16 sTransitionTextureFadeCount[2] = { 0 };
|
||||
|
||||
s32 set_and_reset_transition_fade_timer(s8 fadeTimer, u8 transTime) {
|
||||
s32 reset = FALSE;
|
||||
|
||||
sTransitionColorFadeCount[fadeTimer]++;
|
||||
|
||||
if (sTransitionColorFadeCount[fadeTimer] >= transTime) {
|
||||
sTransitionColorFadeCount[fadeTimer] = 0;
|
||||
sTransitionTextureFadeCount[fadeTimer] = 0;
|
||||
reset = TRUE;
|
||||
}
|
||||
return reset;
|
||||
}
|
||||
|
||||
u8 set_transition_color_fade_alpha(s8 fadeType, s8 fadeTimer, u8 transTime) {
|
||||
u8 time = 0;
|
||||
|
||||
switch (fadeType) {
|
||||
case COLOR_TRANS_FADE_INTO_COLOR:
|
||||
time = (f32) sTransitionColorFadeCount[fadeTimer] * 255.0 / (f32)(transTime - 1) + 0.5; // fade in
|
||||
break;
|
||||
case COLOR_TRANS_FADE_FROM_COLOR:
|
||||
time = (1.0 - sTransitionColorFadeCount[fadeTimer] / (f32)(transTime - 1)) * 255.0 + 0.5; // fade out
|
||||
break;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
Vtx *vertex_transition_color(struct WarpTransitionData *transData, u8 alpha) {
|
||||
Vtx *verts = alloc_display_list(4 * sizeof(*verts));
|
||||
u8 r = transData->red;
|
||||
u8 g = transData->green;
|
||||
u8 b = transData->blue;
|
||||
|
||||
if (verts != NULL) {
|
||||
make_vertex(verts, 0, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, r, g, b, alpha);
|
||||
make_vertex(verts, 1, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, r, g, b, alpha);
|
||||
make_vertex(verts, 2, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, r, g, b, alpha);
|
||||
make_vertex(verts, 3, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, r, g, b, alpha);
|
||||
}
|
||||
return verts;
|
||||
}
|
||||
|
||||
s32 dl_transition_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData, u8 alpha) {
|
||||
Vtx *verts = vertex_transition_color(transData, alpha);
|
||||
|
||||
if (verts != NULL) {
|
||||
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
|
||||
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0);
|
||||
gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123);
|
||||
gSPDisplayList(gDisplayListHead++, dl_screen_transition_end);
|
||||
}
|
||||
return set_and_reset_transition_fade_timer(fadeTimer, transTime);
|
||||
}
|
||||
|
||||
s32 render_fade_transition_from_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData) {
|
||||
u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_FROM_COLOR, fadeTimer, transTime);
|
||||
|
||||
return dl_transition_color(fadeTimer, transTime, transData, alpha);
|
||||
}
|
||||
|
||||
s32 render_fade_transition_into_color(s8 fadeTimer, u8 transTime, struct WarpTransitionData *transData) {
|
||||
u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_INTO_COLOR, fadeTimer, transTime);
|
||||
|
||||
return dl_transition_color(fadeTimer, transTime, transData, alpha);
|
||||
}
|
||||
|
||||
s16 calc_tex_transition_radius(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) {
|
||||
f32 texRadius = transData->endTexRadius - transData->startTexRadius;
|
||||
f32 radiusTime = sTransitionColorFadeCount[fadeTimer] * texRadius / (f32)(transTime - 1);
|
||||
f32 result = transData->startTexRadius + radiusTime;
|
||||
|
||||
return (s16)(result + 0.5f);
|
||||
}
|
||||
|
||||
f32 calc_tex_transition_time(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData) {
|
||||
f32 startX = transData->startTexX;
|
||||
f32 startY = transData->startTexY;
|
||||
f32 endX = transData->endTexX;
|
||||
f32 endY = transData->endTexY;
|
||||
f32 sqrtfXY = sqrtf((startX - endX) * (startX - endX) + (startY - endY) * (startY - endY));
|
||||
f32 result = (f32) sTransitionColorFadeCount[fadeTimer] * sqrtfXY / (f32)(transTime - 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u16 convert_tex_transition_angle_to_pos(struct WarpTransitionData *transData) {
|
||||
f32 x = transData->endTexX - transData->startTexX;
|
||||
f32 y = transData->endTexY - transData->startTexY;
|
||||
|
||||
return atan2s(x, y);
|
||||
}
|
||||
|
||||
s16 center_tex_transition_x(struct WarpTransitionData *transData, f32 texTransTime, u16 texTransPos) {
|
||||
f32 x = transData->startTexX + coss(texTransPos) * texTransTime;
|
||||
|
||||
return (s16)(x + 0.5);
|
||||
}
|
||||
|
||||
s16 center_tex_transition_y(struct WarpTransitionData *transData, f32 texTransTime, u16 texTransPos) {
|
||||
f32 y = transData->startTexY + sins(texTransPos) * texTransTime;
|
||||
|
||||
return (s16)(y + 0.5);
|
||||
}
|
||||
|
||||
void make_tex_transition_vertex(Vtx *verts, s32 n, s8 fadeTimer, struct WarpTransitionData *transData, s16 centerTransX, s16 centerTransY,
|
||||
s16 texRadius1, s16 texRadius2, s16 tx, s16 ty) {
|
||||
u8 r = transData->red;
|
||||
u8 g = transData->green;
|
||||
u8 b = transData->blue;
|
||||
u16 zeroTimer = sTransitionTextureFadeCount[fadeTimer];
|
||||
f32 centerX = texRadius1 * coss(zeroTimer) - texRadius2 * sins(zeroTimer) + centerTransX;
|
||||
f32 centerY = texRadius1 * sins(zeroTimer) + texRadius2 * coss(zeroTimer) + centerTransY;
|
||||
s16 x = roundf(centerX);
|
||||
s16 y = roundf(centerY);
|
||||
|
||||
make_vertex(verts, n, x, y, -1, tx * 32, ty * 32, r, g, b, 255);
|
||||
}
|
||||
|
||||
void load_tex_transition_vertex(Vtx *verts, s8 fadeTimer, struct WarpTransitionData *transData, s16 centerTransX, s16 centerTransY,
|
||||
s16 texTransRadius, s8 transTexType) {
|
||||
switch (transTexType) {
|
||||
case TRANS_TYPE_MIRROR:
|
||||
make_tex_transition_vertex(verts, 0, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, -texTransRadius, -31, 63);
|
||||
make_tex_transition_vertex(verts, 1, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, -texTransRadius, 31, 63);
|
||||
make_tex_transition_vertex(verts, 2, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, texTransRadius, 31, 0);
|
||||
make_tex_transition_vertex(verts, 3, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, texTransRadius, -31, 0);
|
||||
break;
|
||||
case TRANS_TYPE_CLAMP:
|
||||
make_tex_transition_vertex(verts, 0, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, -texTransRadius, 0, 63);
|
||||
make_tex_transition_vertex(verts, 1, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, -texTransRadius, 63, 63);
|
||||
make_tex_transition_vertex(verts, 2, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, texTransRadius, 63, 0);
|
||||
make_tex_transition_vertex(verts, 3, fadeTimer, transData, centerTransX, centerTransY, -texTransRadius, texTransRadius, 0, 0);
|
||||
break;
|
||||
}
|
||||
make_tex_transition_vertex(verts, 4, fadeTimer, transData, centerTransX, centerTransY, -2000, -2000, 0, 0);
|
||||
make_tex_transition_vertex(verts, 5, fadeTimer, transData, centerTransX, centerTransY, 2000, -2000, 0, 0);
|
||||
make_tex_transition_vertex(verts, 6, fadeTimer, transData, centerTransX, centerTransY, 2000, 2000, 0, 0);
|
||||
make_tex_transition_vertex(verts, 7, fadeTimer, transData, centerTransX, centerTransY, -2000, 2000, 0, 0);
|
||||
}
|
||||
u8 sTransitionFadeTimer = 0;
|
||||
u16 sTransitionTextureAngle = 0;
|
||||
|
||||
void *sTextureTransitionID[] = {
|
||||
texture_transition_star_half,
|
||||
@@ -165,108 +23,302 @@ void *sTextureTransitionID[] = {
|
||||
texture_transition_bowser_half,
|
||||
};
|
||||
|
||||
s32 render_textured_transition(s8 fadeTimer, s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) {
|
||||
f32 texTransTime = calc_tex_transition_time(fadeTimer, transTime, transData);
|
||||
u16 texTransPos = convert_tex_transition_angle_to_pos(transData);
|
||||
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, transTime, transData);
|
||||
Vtx *verts = alloc_display_list(8 * sizeof(*verts));
|
||||
s32 set_and_reset_transition_fade_timer(u8 transTime) {
|
||||
sTransitionFadeTimer++;
|
||||
|
||||
if (sTransitionFadeTimer >= transTime) {
|
||||
sTransitionFadeTimer = 0;
|
||||
sTransitionTextureAngle = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void make_tex_transition_vertex(Vtx *verts, s32 n, f32 centerTransX, f32 centerTransY,
|
||||
f32 vertX, f32 vertY, s16 tx, s16 ty) {
|
||||
// Rotate around the center
|
||||
s16 angle = sTransitionTextureAngle;
|
||||
f32 x = vertX * coss(angle) - vertY * sins(angle) + centerTransX;
|
||||
f32 y = vertX * sins(angle) + vertY * coss(angle) + centerTransY;
|
||||
|
||||
s16 roundedX = roundf(x);
|
||||
s16 roundedY = roundf(y);
|
||||
|
||||
make_simple_vertex(verts, n, roundedX, roundedY, -1, tx * 32, ty * 32);
|
||||
}
|
||||
|
||||
#define SOLID_COL_RADIUS 2000
|
||||
void make_tex_transition_vertices(Vtx *verts, f32 centerTransX, f32 centerTransY, f32 texTransRadius,
|
||||
s8 transTexType) {
|
||||
|
||||
s16 leftUV, rightUV, downUV, upUV;
|
||||
|
||||
if (transTexType == TRANS_TYPE_MIRROR) {
|
||||
leftUV = -31;
|
||||
rightUV = 31;
|
||||
downUV = 0;
|
||||
upUV = 63;
|
||||
}
|
||||
else {
|
||||
leftUV = 0;
|
||||
rightUV = 63;
|
||||
downUV = 0;
|
||||
upUV = 63;
|
||||
}
|
||||
|
||||
// Shape texture
|
||||
make_tex_transition_vertex(verts, 0, centerTransX, centerTransY, -texTransRadius, -texTransRadius, leftUV, upUV);
|
||||
make_tex_transition_vertex(verts, 1, centerTransX, centerTransY, texTransRadius, -texTransRadius, rightUV, upUV);
|
||||
make_tex_transition_vertex(verts, 2, centerTransX, centerTransY, texTransRadius, texTransRadius, rightUV, downUV);
|
||||
make_tex_transition_vertex(verts, 3, centerTransX, centerTransY, -texTransRadius, texTransRadius, leftUV, downUV);
|
||||
|
||||
// Solid color
|
||||
make_tex_transition_vertex(verts, 4, centerTransX, centerTransY, -SOLID_COL_RADIUS, -SOLID_COL_RADIUS, 0, 0);
|
||||
make_tex_transition_vertex(verts, 5, centerTransX, centerTransY, SOLID_COL_RADIUS, -SOLID_COL_RADIUS, 0, 0);
|
||||
make_tex_transition_vertex(verts, 6, centerTransX, centerTransY, SOLID_COL_RADIUS, SOLID_COL_RADIUS, 0, 0);
|
||||
make_tex_transition_vertex(verts, 7, centerTransX, centerTransY, -SOLID_COL_RADIUS, SOLID_COL_RADIUS, 0, 0);
|
||||
}
|
||||
|
||||
f32 calc_tex_transition_radius(s8 transTime, struct WarpTransitionData *transData) {
|
||||
f32 amount = (f32) sTransitionFadeTimer / (f32) (transTime - 1);
|
||||
|
||||
#ifdef EASE_IN_OUT_TRANSITIONS
|
||||
return smoothstep(transData->startTexRadius, transData->endTexRadius, amount);
|
||||
#else
|
||||
return lerpf(transData->startTexRadius, transData->endTexRadius, amount);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
f32 center_tex_transition_x(struct WarpTransitionData *transData, f32 posDistance, u16 texTransDir) {
|
||||
f32 x = transData->startTexX + coss(texTransDir) * posDistance;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
f32 center_tex_transition_y(struct WarpTransitionData *transData, f32 posDistance, u16 texTransDir) {
|
||||
f32 y = transData->startTexY + sins(texTransDir) * posDistance;
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
f32 calc_tex_transition_pos_distance(s8 transTime, struct WarpTransitionData *transData) {
|
||||
f32 startX = transData->startTexX;
|
||||
f32 startY = transData->startTexY;
|
||||
f32 endX = transData->endTexX;
|
||||
f32 endY = transData->endTexY;
|
||||
|
||||
f32 distance = sqrtf(sqr(startX - endX) + sqr(startY - endY));
|
||||
|
||||
f32 amount = (f32) sTransitionFadeTimer / (f32)(transTime - 1);
|
||||
|
||||
return distance * amount;
|
||||
}
|
||||
|
||||
u16 calc_tex_transition_direction(struct WarpTransitionData *transData) {
|
||||
f32 x = transData->endTexX - transData->startTexX;
|
||||
f32 y = transData->endTexY - transData->startTexY;
|
||||
|
||||
return atan2s(x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during render_screen_transition.
|
||||
* Handles shape transitions (such as the star, circle and Mario and bowser´s heads).
|
||||
*/
|
||||
s32 render_textured_transition(s8 transTime, struct WarpTransitionData *transData, s8 texID, s8 transTexType) {
|
||||
u16 texTransDir = calc_tex_transition_direction(transData);
|
||||
|
||||
f32 posDistance = calc_tex_transition_pos_distance(transTime, transData);
|
||||
f32 centerTransX = center_tex_transition_x(transData, posDistance, texTransDir);
|
||||
f32 centerTransY = center_tex_transition_y(transData, posDistance, texTransDir);
|
||||
|
||||
f32 texTransRadius = calc_tex_transition_radius(transTime, transData);
|
||||
Vtx *verts = alloc_display_list(8 * sizeof(Vtx));
|
||||
|
||||
|
||||
if (verts != NULL) {
|
||||
load_tex_transition_vertex(verts, fadeTimer, transData, centerTransX, centerTransY, texTransRadius, transTexType);
|
||||
make_tex_transition_vertices(verts, centerTransX, centerTransY, texTransRadius, transTexType);
|
||||
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE);
|
||||
|
||||
u8 r = transData->red;
|
||||
u8 g = transData->green;
|
||||
u8 b = transData->blue;
|
||||
gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, 255);
|
||||
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
|
||||
|
||||
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 8, 0);
|
||||
gSPDisplayList(gDisplayListHead++, dl_transition_draw_filled_region);
|
||||
gDPPipeSync(gDisplayListHead++);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
|
||||
|
||||
gDPSetCombineLERP(gDisplayListHead++, 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0,
|
||||
0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0);
|
||||
|
||||
#ifdef SHARP_TRANSITION_TEXTURES
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_TEX_EDGE, G_RM_AA_TEX_EDGE2);
|
||||
s32 textureType = G_IM_FMT_I;
|
||||
#else
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
|
||||
s32 textureType = G_IM_FMT_IA;
|
||||
#endif
|
||||
|
||||
gDPSetTextureFilter(gDisplayListHead++, G_TF_BILERP);
|
||||
|
||||
switch (transTexType) {
|
||||
case TRANS_TYPE_MIRROR:
|
||||
gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0,
|
||||
G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD);
|
||||
break;
|
||||
case TRANS_TYPE_CLAMP:
|
||||
gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], G_IM_FMT_IA, G_IM_SIZ_8b, 64, 64, 0,
|
||||
G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
|
||||
break;
|
||||
case TRANS_TYPE_MIRROR:
|
||||
gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], textureType, G_IM_SIZ_8b, 32, 64, 0,
|
||||
G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD);
|
||||
break;
|
||||
case TRANS_TYPE_CLAMP:
|
||||
gDPLoadTextureBlock(gDisplayListHead++, sTextureTransitionID[texID], textureType, G_IM_SIZ_8b, 64, 64, 0,
|
||||
G_TX_CLAMP, G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
|
||||
break;
|
||||
}
|
||||
gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
|
||||
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 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);
|
||||
sTransitionTextureFadeCount[fadeTimer] += transData->texTimer;
|
||||
sTransitionTextureAngle += transData->angleSpeed;
|
||||
}
|
||||
return set_and_reset_transition_fade_timer(fadeTimer, transTime);
|
||||
return set_and_reset_transition_fade_timer(transTime);
|
||||
}
|
||||
|
||||
s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData) {
|
||||
Vtx *vertex_transition_color() {
|
||||
Vtx *verts = alloc_display_list(4 * sizeof(Vtx));
|
||||
|
||||
if (verts != NULL) {
|
||||
make_simple_vertex(verts, 0, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0);
|
||||
make_simple_vertex(verts, 1, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0);
|
||||
make_simple_vertex(verts, 2, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0);
|
||||
make_simple_vertex(verts, 3, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0);
|
||||
}
|
||||
return verts;
|
||||
}
|
||||
|
||||
s32 dl_transition_color(u8 transTime, struct WarpTransitionData *transData, u8 alpha) {
|
||||
Vtx *verts = vertex_transition_color();
|
||||
|
||||
if (verts != NULL) {
|
||||
u8 r = transData->red;
|
||||
u8 g = transData->green;
|
||||
u8 b = transData->blue;
|
||||
gDPSetPrimColor(gDisplayListHead++, 0, 0, r, g, b, alpha);
|
||||
|
||||
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen);
|
||||
gDPSetCombineMode(gDisplayListHead++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
|
||||
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
|
||||
gSPVertex(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(verts), 4, 0);
|
||||
gSPDisplayList(gDisplayListHead++, dl_draw_quad_verts_0123);
|
||||
gSPDisplayList(gDisplayListHead++, dl_screen_transition_end);
|
||||
}
|
||||
return set_and_reset_transition_fade_timer(transTime);
|
||||
}
|
||||
|
||||
u8 set_transition_color_fade_alpha(s8 fadeType, u8 transTime) {
|
||||
u8 time = 0;
|
||||
f32 amount = (f32) sTransitionFadeTimer / (f32) (transTime - 1);
|
||||
switch (fadeType) {
|
||||
case COLOR_TRANS_FADE_INTO_COLOR:
|
||||
time = lerpf(0.f, 255.0f, amount);
|
||||
break;
|
||||
case COLOR_TRANS_FADE_FROM_COLOR:
|
||||
time = lerpf(255.0f, 0.f, amount);
|
||||
break;
|
||||
}
|
||||
return roundf(time);
|
||||
}
|
||||
|
||||
s32 render_fade_transition_from_color(u8 transTime, struct WarpTransitionData *transData) {
|
||||
u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_FROM_COLOR, transTime);
|
||||
|
||||
return dl_transition_color(transTime, transData, alpha);
|
||||
}
|
||||
|
||||
s32 render_fade_transition_into_color(u8 transTime, struct WarpTransitionData *transData) {
|
||||
u8 alpha = set_transition_color_fade_alpha(COLOR_TRANS_FADE_INTO_COLOR, transTime);
|
||||
|
||||
return dl_transition_color(transTime, transData, alpha);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during rendering if gWarpTransition.isActive is on.
|
||||
* Handles solid colour transitions and shape transitions
|
||||
* (such as the star, circle and Mario and bowser´s heads).
|
||||
*/
|
||||
s32 render_screen_transition(s8 transType, u8 transTime, struct WarpTransitionData *transData) {
|
||||
switch (transType) {
|
||||
case WARP_TRANSITION_FADE_FROM_COLOR:
|
||||
return render_fade_transition_from_color(fadeTimer, transTime, transData);
|
||||
return render_fade_transition_from_color(transTime, transData);
|
||||
break;
|
||||
case WARP_TRANSITION_FADE_INTO_COLOR:
|
||||
return render_fade_transition_into_color(fadeTimer, transTime, transData);
|
||||
return render_fade_transition_into_color(transTime, transData);
|
||||
break;
|
||||
|
||||
case WARP_TRANSITION_FADE_FROM_STAR:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR);
|
||||
break;
|
||||
case WARP_TRANSITION_FADE_INTO_STAR:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR);
|
||||
break;
|
||||
|
||||
case WARP_TRANSITION_FADE_FROM_CIRCLE:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR);
|
||||
break;
|
||||
case WARP_TRANSITION_FADE_INTO_CIRCLE:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR);
|
||||
break;
|
||||
|
||||
case WARP_TRANSITION_FADE_FROM_MARIO:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP);
|
||||
break;
|
||||
case WARP_TRANSITION_FADE_INTO_MARIO:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP);
|
||||
break;
|
||||
|
||||
case WARP_TRANSITION_FADE_FROM_BOWSER:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR);
|
||||
break;
|
||||
case WARP_TRANSITION_FADE_INTO_BOWSER:
|
||||
return render_textured_transition(fadeTimer, transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR);
|
||||
return render_textured_transition(transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR);
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Gfx *render_cannon_circle_base(void) {
|
||||
#ifdef WIDESCREEN
|
||||
Vtx *verts = alloc_display_list(8 * sizeof(*verts));
|
||||
Gfx *dlist = alloc_display_list(20 * sizeof(*dlist));
|
||||
Vtx *verts = alloc_display_list(8 * sizeof(Vtx));
|
||||
Gfx *dlist = alloc_display_list(20 * sizeof(Gfx));
|
||||
#else
|
||||
Vtx *verts = alloc_display_list(4 * sizeof(*verts));
|
||||
Gfx *dlist = alloc_display_list(16 * sizeof(*dlist));
|
||||
Vtx *verts = alloc_display_list(4 * sizeof(Vtx));
|
||||
Gfx *dlist = alloc_display_list(16 * sizeof(Gfx));
|
||||
#endif
|
||||
Gfx *g = dlist;
|
||||
|
||||
if (verts != NULL && dlist != NULL) {
|
||||
make_vertex(verts, 0, 0, 0, -1, -1152, 1824, 0, 0, 0, 255);
|
||||
make_vertex(verts, 1, SCREEN_WIDTH, 0, -1, 1152, 1824, 0, 0, 0, 255);
|
||||
make_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192, 0, 0, 0, 255);
|
||||
make_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192, 0, 0, 0, 255);
|
||||
gDPSetPrimColor(gDisplayListHead++, 0, 0, 0, 0, 0, 255);
|
||||
|
||||
make_simple_vertex(verts, 0, 0, 0, -1, -1152, 1824);
|
||||
make_simple_vertex(verts, 1, SCREEN_WIDTH, 0, -1, 1152, 1824);
|
||||
make_simple_vertex(verts, 2, SCREEN_WIDTH, SCREEN_HEIGHT, -1, 1152, 192);
|
||||
make_simple_vertex(verts, 3, 0, SCREEN_HEIGHT, -1, -1152, 192);
|
||||
|
||||
#ifdef WIDESCREEN
|
||||
// Render black rectangles outside the 4:3 area.
|
||||
make_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0, 0, 0, 0, 255);
|
||||
make_simple_vertex(verts, 4, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), 0, -1, 0, 0, 0);
|
||||
make_simple_vertex(verts, 5, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), 0, -1, 0, 0, 0);
|
||||
make_simple_vertex(verts, 6, GFX_DIMENSIONS_FROM_RIGHT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0);
|
||||
make_simple_vertex(verts, 7, GFX_DIMENSIONS_FROM_LEFT_EDGE(0), SCREEN_HEIGHT, -1, 0, 0);
|
||||
#endif
|
||||
|
||||
gSPDisplayList(g++, dl_proj_mtx_fullscreen);
|
||||
gDPSetCombineMode(g++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
|
||||
gDPSetCombineMode(g++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
|
||||
gDPSetTextureFilter(g++, G_TF_BILERP);
|
||||
gDPLoadTextureBlock(g++, sTextureTransitionID[TEX_TRANS_CIRCLE], G_IM_FMT_IA, G_IM_SIZ_8b, 32, 64, 0,
|
||||
G_TX_WRAP | G_TX_MIRROR, G_TX_WRAP | G_TX_MIRROR, 5, 6, G_TX_NOLOD, G_TX_NOLOD);
|
||||
|
||||
@@ -24,7 +24,7 @@ enum ColorTransitionFade {
|
||||
COLOR_TRANS_FADE_FROM_COLOR,
|
||||
};
|
||||
|
||||
s32 render_screen_transition(s8 fadeTimer, s8 transType, u8 transTime, struct WarpTransitionData *transData);
|
||||
s32 render_screen_transition(s8 transType, u8 transTime, struct WarpTransitionData *transData);
|
||||
Gfx *geo_cannon_circle_base(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx);
|
||||
|
||||
#endif // SCREEN_TRANSITION_H
|
||||
|
||||
BIN
textures/segment2/transition_bowser_half.i8.png
Normal file
BIN
textures/segment2/transition_bowser_half.i8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
textures/segment2/transition_circle_half.i8.png
Normal file
BIN
textures/segment2/transition_circle_half.i8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
textures/segment2/transition_mario.i8.png
Normal file
BIN
textures/segment2/transition_mario.i8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
BIN
textures/segment2/transition_star_half.i8.png
Normal file
BIN
textures/segment2/transition_star_half.i8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Reference in New Issue
Block a user