Files
Microtransactions64/src/game/screen_transition.c
Lilaa3 af3b538ed9 Remove sharp transitions (#702)
* Cannon render mode fix

Slipped past me.

* Removed sharp transitions

I like the idea but it really isn´t vanilla and causes issues.
Might be worth revisiting but for now lets just get rid of it.

* fixes

Missing render mode set for transitions, reduced display list alloc for cannon
tested more this time
2023-09-25 08:26:31 -05:00

350 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <PR/ultratypes.h>
#include <PR/gbi.h>
#include "area.h"
#include "camera.h"
#include "engine/graph_node.h"
#include "engine/math_util.h"
#include "game/game_init.h"
#include "geo_misc.h"
#include "gfx_dimensions.h"
#include "memory.h"
#include "screen_transition.h"
#include "segment2.h"
#include "sm64.h"
u8 sTransitionFadeTimer = 0;
u16 sTransitionTextureAngle = 0;
void *sTextureTransitionID[] = {
texture_transition_star_half,
texture_transition_circle_half,
texture_transition_mario,
texture_transition_bowser_half,
};
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) {
make_tex_transition_vertices(verts, centerTransX, centerTransY, texTransRadius, transTexType);
gSPDisplayList(gDisplayListHead++, dl_proj_mtx_fullscreen);
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++);
gDPSetCombineLERP(gDisplayListHead++, 0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0,
0, 0, 0, PRIMITIVE, 0, 0, 0, TEXEL0);
gDPSetRenderMode(gDisplayListHead++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
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;
}
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);
sTransitionTextureAngle += transData->angleSpeed;
}
return set_and_reset_transition_fade_timer(transTime);
}
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(transTime, transData);
break;
case WARP_TRANSITION_FADE_INTO_COLOR:
return render_fade_transition_into_color(transTime, transData);
break;
case WARP_TRANSITION_FADE_FROM_STAR:
return render_textured_transition(transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR);
break;
case WARP_TRANSITION_FADE_INTO_STAR:
return render_textured_transition(transTime, transData, TEX_TRANS_STAR, TRANS_TYPE_MIRROR);
break;
case WARP_TRANSITION_FADE_FROM_CIRCLE:
return render_textured_transition(transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR);
break;
case WARP_TRANSITION_FADE_INTO_CIRCLE:
return render_textured_transition(transTime, transData, TEX_TRANS_CIRCLE, TRANS_TYPE_MIRROR);
break;
case WARP_TRANSITION_FADE_FROM_MARIO:
return render_textured_transition(transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP);
break;
case WARP_TRANSITION_FADE_INTO_MARIO:
return render_textured_transition(transTime, transData, TEX_TRANS_MARIO, TRANS_TYPE_CLAMP);
break;
case WARP_TRANSITION_FADE_FROM_BOWSER:
return render_textured_transition(transTime, transData, TEX_TRANS_BOWSER, TRANS_TYPE_MIRROR);
break;
case WARP_TRANSITION_FADE_INTO_BOWSER:
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(Vtx));
Gfx *dlist = alloc_display_list(20 * sizeof(Gfx));
#else
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) {
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_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_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);
gSPTexture(g++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts), 4, 0);
gSPDisplayList(g++, dl_draw_quad_verts_0123);
gSPTexture(g++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF);
#ifdef WIDESCREEN
gDPSetCombineMode(g++, G_CC_SHADE, G_CC_SHADE);
gSPVertex(g++, VIRTUAL_TO_PHYSICAL(verts + 4), 4, 4);
gSP2Triangles(g++, 4, 0, 3, 0x0, 4, 3, 7, 0x0);
gSP2Triangles(g++, 1, 5, 6, 0x0, 1, 6, 2, 0x0);
#endif
gSPDisplayList(g++, dl_screen_transition_end);
gSPEndDisplayList(g);
} else {
return NULL;
}
return dlist;
}
Gfx *geo_cannon_circle_base(s32 callContext, struct GraphNode *node, UNUSED Mat4 mtx) {
struct GraphNodeGenerated *graphNode = (struct GraphNodeGenerated *) node;
Gfx *dlist = NULL;
if (callContext == GEO_CONTEXT_RENDER && gCurrentArea != NULL
&& gCurrentArea->camera->mode == CAMERA_MODE_INSIDE_CANNON) {
SET_GRAPH_NODE_LAYER(graphNode->fnNode.node.flags, LAYER_TRANSPARENT);
#ifndef L3DEX2_ALONE
dlist = render_cannon_circle_base();
#endif
}
return dlist;
}