WIP: uncapped framerate 5

This commit is contained in:
MysterD 2022-04-27 19:43:55 -07:00
parent 0eece3001f
commit 6e47f226c9
4 changed files with 149 additions and 62 deletions

View file

@ -38,7 +38,7 @@
* - Script node (Cannon overlay) * - Script node (Cannon overlay)
* *
*/ */
#define MATRIX_STACK_SIZE 32 #define MATRIX_STACK_SIZE 32
s16 gMatStackIndex; s16 gMatStackIndex;
@ -155,6 +155,11 @@ Vtx* gBackgroundSkyboxVerts[3][3] = { 0 };
Mtx* gBackgroundSkyboxMtx = NULL; Mtx* gBackgroundSkyboxMtx = NULL;
struct GraphNodeRoot* sBackgroundNodeRoot = NULL; struct GraphNodeRoot* sBackgroundNodeRoot = NULL;
#define MAX_SHADOW_NODES 128
struct ShadowInterp sShadowInterp[MAX_SHADOW_NODES] = { 0 };
struct ShadowInterp* gShadowInterpCurrent = NULL;
static u8 sShadowInterpCount = 0;
struct { struct {
Gfx *pos; Gfx *pos;
void *mtx; void *mtx;
@ -189,6 +194,8 @@ void patch_mtx_before(void) {
sBackgroundNode = NULL; sBackgroundNode = NULL;
gBackgroundSkyboxGfx = NULL; gBackgroundSkyboxGfx = NULL;
} }
sShadowInterpCount = 0;
} }
void patch_mtx_interpolated(f32 delta) { void patch_mtx_interpolated(f32 delta) {
@ -232,6 +239,20 @@ void patch_mtx_interpolated(f32 delta) {
gCurGraphNodeRoot = rootCopy; gCurGraphNodeRoot = rootCopy;
} }
struct GraphNodeObject* savedObj = gCurGraphNodeObject;
for (s32 i = 0; i < sShadowInterpCount; i++) {
struct ShadowInterp* interp = &sShadowInterp[i];
gShadowInterpCurrent = interp;
Vec3f posInterp;
delta_interpolate_vec3f(posInterp, interp->shadowPosPrev, interp->shadowPos, delta);
if (i == 0) {
printf("XXX: %f <--> %f == %f\n", interp->shadowPosPrev[1], interp->shadowPos[1], posInterp[1]);
}
gCurGraphNodeObject = interp->obj;
create_shadow_below_xyz(posInterp[0], posInterp[1], posInterp[2], interp->shadowScale, interp->node->shadowSolidity, interp->node->shadowType);
}
gCurGraphNodeObject = savedObj;
for (s32 i = 0; i < gMtxTblSize; i++) { for (s32 i = 0; i < gMtxTblSize; i++) {
Gfx *pos = gMtxTbl[i].pos; Gfx *pos = gMtxTbl[i].pos;
delta_interpolate_mtx(&gMtxTbl[i].interp, (Mtx*) gMtxTbl[i].mtxPrev, (Mtx*) gMtxTbl[i].mtx, delta); delta_interpolate_mtx(&gMtxTbl[i].interp, (Mtx*) gMtxTbl[i].mtxPrev, (Mtx*) gMtxTbl[i].mtx, delta);
@ -241,6 +262,7 @@ void patch_mtx_interpolated(f32 delta) {
gSPDisplayList(pos++, gMtxTbl[i].displayList); gSPDisplayList(pos++, gMtxTbl[i].displayList);
} }
} }
} }
/** /**
@ -250,7 +272,7 @@ static u8 increment_mat_stack() {
Mtx *mtx = alloc_display_list(sizeof(*mtx)); Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxPrev = alloc_display_list(sizeof(*mtxPrev)); Mtx *mtxPrev = alloc_display_list(sizeof(*mtxPrev));
if (mtx == NULL || mtxPrev == NULL) { return FALSE; } if (mtx == NULL || mtxPrev == NULL) { return FALSE; }
gMatStackIndex++; gMatStackIndex++;
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
mtxf_to_mtx(mtxPrev, gMatStackPrev[gMatStackIndex]); mtxf_to_mtx(mtxPrev, gMatStackPrev[gMatStackIndex]);
@ -446,10 +468,10 @@ static void geo_process_switch(struct GraphNodeSwitchCase *node) {
*/ */
static void geo_process_camera(struct GraphNodeCamera *node) { static void geo_process_camera(struct GraphNodeCamera *node) {
Mat4 cameraTransform; Mat4 cameraTransform;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx)); Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx));
if (rollMtx == NULL) { return; } if (rollMtx == NULL) { return; }
@ -477,7 +499,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (node->fnNode.node.children != 0) { if (node->fnNode.node.children != 0) {
gCurGraphNodeCamera = node; gCurGraphNodeCamera = node;
node->matrixPtr = &gMatStack[gMatStackIndex]; node->matrixPtr = &gMatStack[gMatStackIndex];
@ -497,7 +519,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
static void geo_process_translation_rotation(struct GraphNodeTranslationRotation *node) { static void geo_process_translation_rotation(struct GraphNodeTranslationRotation *node) {
Mat4 mtxf; Mat4 mtxf;
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -505,10 +527,10 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation); mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (node->displayList != NULL) { if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8); geo_append_display_list(node->displayList, node->node.flags >> 8);
} }
@ -526,7 +548,7 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
static void geo_process_translation(struct GraphNodeTranslation *node) { static void geo_process_translation(struct GraphNodeTranslation *node) {
Mat4 mtxf; Mat4 mtxf;
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -534,10 +556,10 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero); mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (node->displayList != NULL) { if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8); geo_append_display_list(node->displayList, node->node.flags >> 8);
} }
@ -554,7 +576,7 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
*/ */
static void geo_process_rotation(struct GraphNodeRotation *node) { static void geo_process_rotation(struct GraphNodeRotation *node) {
Mat4 mtxf; Mat4 mtxf;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -569,10 +591,10 @@ static void geo_process_rotation(struct GraphNodeRotation *node) {
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
vec3s_copy(node->prevRotation, node->rotation); vec3s_copy(node->prevRotation, node->rotation);
node->prevTimestamp = gGlobalTimer; node->prevTimestamp = gGlobalTimer;
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (node->displayList != NULL) { if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8); geo_append_display_list(node->displayList, node->node.flags >> 8);
} }
@ -590,7 +612,7 @@ static void geo_process_rotation(struct GraphNodeRotation *node) {
static void geo_process_scale(struct GraphNodeScale *node) { static void geo_process_scale(struct GraphNodeScale *node) {
Vec3f scaleVec; Vec3f scaleVec;
Vec3f prevScaleVec; Vec3f prevScaleVec;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -603,7 +625,7 @@ static void geo_process_scale(struct GraphNodeScale *node) {
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (node->displayList != NULL) { if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8); geo_append_display_list(node->displayList, node->node.flags >> 8);
} }
@ -621,12 +643,12 @@ static void geo_process_scale(struct GraphNodeScale *node) {
*/ */
static void geo_process_billboard(struct GraphNodeBillboard *node) { static void geo_process_billboard(struct GraphNodeBillboard *node) {
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
s16 nextMatStackIndex = gMatStackIndex + 1; s16 nextMatStackIndex = gMatStackIndex + 1;
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);
mtxf_billboard(gMatStack[nextMatStackIndex], gMatStack[gMatStackIndex], translation, mtxf_billboard(gMatStack[nextMatStackIndex], gMatStack[gMatStackIndex], translation,
gCurGraphNodeCamera->roll); gCurGraphNodeCamera->roll);
@ -646,7 +668,7 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) {
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (node->displayList != NULL) { if (node->displayList != NULL) {
geo_append_display_list(node->displayList, node->node.flags >> 8); geo_append_display_list(node->displayList, node->node.flags >> 8);
} }
@ -792,10 +814,10 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
Vec3f translation; Vec3f translation;
Vec3s rotationPrev; Vec3s rotationPrev;
Vec3f translationPrev; Vec3f translationPrev;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
u16 *animAttribute = gCurrAnimAttribute; u16 *animAttribute = gCurrAnimAttribute;
u8 animType = gCurAnimType; u8 animType = gCurAnimType;
@ -813,7 +835,7 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
mtxf_rotate_xyz_and_translate(matrix, translationPrev, rotationPrev); mtxf_rotate_xyz_and_translate(matrix, translationPrev, rotationPrev);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
@ -886,7 +908,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
Vec3f shadowPosPrev; Vec3f shadowPosPrev;
Vec3f animOffset; Vec3f animOffset;
f32 shadowScale; f32 shadowScale;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -949,30 +971,44 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer; gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer;
} }
if (sShadowInterpCount < MAX_SHADOW_NODES) {
struct ShadowInterp* interp = &sShadowInterp[sShadowInterpCount++];
gShadowInterpCurrent = interp;
interp->gfx = NULL;
interp->node = node;
interp->shadowScale = shadowScale;
interp->obj = gCurGraphNodeObject;
vec3f_copy(interp->shadowPos, shadowPos);
vec3f_copy(interp->shadowPosPrev, shadowPosPrev);
} else {
gShadowInterpCurrent = NULL;
}
Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1], Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1],
shadowPosPrev[2], shadowScale, shadowPosPrev[2], shadowScale,
node->shadowSolidity, node->shadowType); node->shadowSolidity, node->shadowType);
Gfx *shadowList = create_shadow_below_xyz(shadowPos[0], shadowPos[1], shadowPos[2], shadowScale, if (gShadowInterpCurrent != NULL) {
node->shadowSolidity, node->shadowType); gShadowInterpCurrent->gfx = shadowListPrev;
if (shadowListPrev != NULL && shadowList != NULL) { }
if (shadowListPrev != NULL) {
mtxf_translate(mtxf, shadowPos); mtxf_translate(mtxf, shadowPos);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtr);
mtxf_translate(mtxf, shadowPosPrev); mtxf_translate(mtxf, shadowPosPrev);
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrPrev); mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, *gCurGraphNodeCamera->matrixPtrPrev);
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
if (gShadowAboveWaterOrLava == TRUE) { if (gShadowAboveWaterOrLava == TRUE) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowListPrev),
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 4); (void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 4);
} else if (gMarioOnIceOrCarpet == TRUE) { } else if (gMarioOnIceOrCarpet == TRUE) {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowListPrev),
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 5); (void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 5);
} else { } else {
geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowList), geo_append_display_list2((void *) VIRTUAL_TO_PHYSICAL(shadowListPrev),
(void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 6); (void *) VIRTUAL_TO_PHYSICAL(shadowListPrev), 6);
} }
gMatStackIndex--; gMatStackIndex--;
@ -1034,7 +1070,7 @@ static s32 obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
// This multiplication should really be performed on 4:3 as well, // This multiplication should really be performed on 4:3 as well,
// but the issue will be more apparent on widescreen. // but the issue will be more apparent on widescreen.
hScreenEdge *= GFX_DIMENSIONS_ASPECT_RATIO; hScreenEdge *= GFX_DIMENSIONS_ASPECT_RATIO;
s16 cullingRadius = 300; s16 cullingRadius = 300;
struct GraphNode *geo = node->sharedChild; struct GraphNode *geo = node->sharedChild;
if (geo != NULL && geo->type == GRAPH_NODE_TYPE_CULLING_RADIUS) { if (geo != NULL && geo->type == GRAPH_NODE_TYPE_CULLING_RADIUS) {
@ -1260,7 +1296,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
Mat4 mat; Mat4 mat;
Vec3f translation; Vec3f translation;
Vec3f scalePrev; Vec3f scalePrev;
// Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return top prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; } if (gMatStackIndex >= MATRIX_STACK_SIZE) { return; }
@ -1304,10 +1340,10 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
if (node->fnNode.func != NULL) { if (node->fnNode.func != NULL) {
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]); node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct AllocOnlyPool *) gMatStack[gMatStackIndex + 1]);
} }
// Increment the matrix stack, If we fail to do so. Just return. // Increment the matrix stack, If we fail to do so. Just return.
if (!increment_mat_stack()) { return; } if (!increment_mat_stack()) { return; }
gGeoTempState.type = gCurAnimType; gGeoTempState.type = gCurAnimType;
gGeoTempState.enabled = gCurAnimEnabled; gGeoTempState.enabled = gCurAnimEnabled;
gGeoTempState.frame = gCurrAnimFrame; gGeoTempState.frame = gCurrAnimFrame;
@ -1461,7 +1497,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
Mtx *initialMatrix = alloc_display_list(sizeof(*initialMatrix)); Mtx *initialMatrix = alloc_display_list(sizeof(*initialMatrix));
if (initialMatrix == NULL) { return; } if (initialMatrix == NULL) { return; }
gMatStackIndex = 0; gMatStackIndex = 0;
gCurAnimType = 0; gCurAnimType = 0;
vec3s_set(viewport->vp.vtrans, node->x * 4, node->y * 4, 511); vec3s_set(viewport->vp.vtrans, node->x * 4, node->y * 4, 511);
@ -1493,7 +1529,7 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor)
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&sViewportPrev)); gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&sViewportPrev));
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gMatStackFixed[gMatStackIndex]), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(gMatStackFixed[gMatStackIndex]), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gCurGraphNodeRoot = node; gCurGraphNodeRoot = node;
if (node->node.children != NULL) { if (node->node.children != NULL) {
geo_process_node_and_siblings(node->node.children); geo_process_node_and_siblings(node->node.children);

View file

@ -33,4 +33,15 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor);
void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b); void interpolate_vectors(Vec3f res, Vec3f a, Vec3f b);
void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b); void interpolate_vectors_s16(Vec3s res, Vec3s a, Vec3s b);
struct ShadowInterp {
Gfx* gfx;
Vec3f shadowPos;
Vec3f shadowPosPrev;
Vtx *verts;
Gfx *displayList;
struct GraphNodeShadow *node;
f32 shadowScale;
struct GraphNodeObject *obj;
};
#endif // RENDERING_GRAPH_NODE_H #endif // RENDERING_GRAPH_NODE_H

View file

@ -16,6 +16,9 @@
// Avoid Z-fighting // Avoid Z-fighting
#define find_floor_height_and_data 0.4 + find_floor_height_and_data #define find_floor_height_and_data 0.4 + find_floor_height_and_data
extern u8 gRenderingInterpolated;
extern struct ShadowInterp* gShadowInterpCurrent;
/** /**
* @file shadow.c * @file shadow.c
* This file implements a self-contained subsystem used to draw shadows. * This file implements a self-contained subsystem used to draw shadows.
@ -114,6 +117,39 @@ s8 gMarioOnIceOrCarpet;
s8 sMarioOnFlyingCarpet; s8 sMarioOnFlyingCarpet;
s16 sSurfaceTypeBelowShadow; s16 sSurfaceTypeBelowShadow;
static Vtx* shadow_get_or_alloc_verts(u8 vertCount) {
if (gRenderingInterpolated) {
if (gShadowInterpCurrent == NULL) {
return NULL;
}
return gShadowInterpCurrent->verts;
} else {
Vtx* verts = alloc_display_list(vertCount * sizeof(Vtx));
if (gShadowInterpCurrent) {
gShadowInterpCurrent->verts = verts;
}
return verts;
}
return NULL;
}
static Gfx* shadow_get_or_alloc_display_list(u8 dlCount) {
if (gRenderingInterpolated) {
if (gShadowInterpCurrent == NULL) {
return NULL;
}
return gShadowInterpCurrent->displayList;
} else {
Gfx *displayList = alloc_display_list(dlCount * sizeof(Gfx));
if (gShadowInterpCurrent) {
gShadowInterpCurrent->displayList = displayList;
}
return displayList;
}
return NULL;
}
/** /**
* Let (oldZ, oldX) be the relative coordinates of a point on a rectangle, * Let (oldZ, oldX) be the relative coordinates of a point on a rectangle,
* assumed to be centered at the origin on the standard SM64 X-Z plane. This * assumed to be centered at the origin on the standard SM64 X-Z plane. This
@ -622,8 +658,8 @@ Gfx *create_shadow_player(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 soli
return NULL; return NULL;
} }
verts = alloc_display_list(9 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(9);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return NULL; return NULL;
} }
@ -650,8 +686,8 @@ Gfx *create_shadow_circle_9_verts(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale,
return NULL; return NULL;
} }
verts = alloc_display_list(9 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(9);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -676,8 +712,8 @@ Gfx *create_shadow_circle_4_verts(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale,
return NULL; return NULL;
} }
verts = alloc_display_list(4 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(4);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -709,8 +745,8 @@ Gfx *create_shadow_circle_assuming_flat_ground(f32 xPos, f32 yPos, f32 zPos, s16
distBelowFloor = floorHeight - yPos; distBelowFloor = floorHeight - yPos;
} }
verts = alloc_display_list(4 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(4);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -738,8 +774,8 @@ Gfx *create_shadow_spike_ext(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 s
return NULL; return NULL;
} }
verts = alloc_display_list(4 * sizeof(Vtx)); verts = shadow_get_or_alloc_verts(4);
displayList = alloc_display_list(5 * sizeof(Gfx)); displayList = shadow_get_or_alloc_display_list(5);
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {
return 0; return 0;
@ -757,8 +793,9 @@ Gfx *create_shadow_spike_ext(f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 s
* underneath the shadow is totally flat. * underneath the shadow is totally flat.
*/ */
Gfx *create_shadow_rectangle(f32 halfWidth, f32 halfLength, f32 relY, u8 solidity) { Gfx *create_shadow_rectangle(f32 halfWidth, f32 halfLength, f32 relY, u8 solidity) {
Vtx *verts = alloc_display_list(4 * sizeof(Vtx)); Vtx *verts = shadow_get_or_alloc_verts(4);
Gfx *displayList = alloc_display_list(5 * sizeof(Gfx)); Gfx *displayList = shadow_get_or_alloc_display_list(5);
f32 frontLeftX, frontLeftZ, frontRightX, frontRightZ, backLeftX, backLeftZ, backRightX, backRightZ; f32 frontLeftX, frontLeftZ, frontRightX, frontRightZ, backLeftX, backLeftZ, backRightX, backRightZ;
if (verts == NULL || displayList == NULL) { if (verts == NULL || displayList == NULL) {

View file

@ -45,10 +45,10 @@
* first, in a display list with the Z buffer disabled * first, in a display list with the Z buffer disabled
*/ */
struct Skybox { struct Skybox {
/// The camera's yaw, from 0 to 65536, which maps to 0 to 360 degrees /// The camera's yaw, from 0 to (M_PI*2), which maps to 0 to 360 degrees
u16 yaw; f32 yaw;
/// The camera's pitch, which is bounded by +-16384, which maps to -90 to 90 degrees /// The camera's pitch, which is bounded by +-(M_PI/2), which maps to -90 to 90 degrees
s16 pitch; f32 pitch;
/// The skybox's X position in world space /// The skybox's X position in world space
f32 scaledX; f32 scaledX;
/// The skybox's Y position in world space /// The skybox's Y position in world space
@ -138,11 +138,11 @@ u8 sSkyboxColors[][3] = {
* (how far is the camera rotated from 0, scaled 0 to 1) * * (how far is the camera rotated from 0, scaled 0 to 1) *
* (the screen width) * (the screen width)
*/ */
s32 calculate_skybox_scaled_x(s8 player, f32 fov) { f32 calculate_skybox_scaled_x(s8 player, f32 fov) {
f32 yaw = sSkyBoxInfo[player].yaw; f32 yaw = sSkyBoxInfo[player].yaw;
//! double literals are used instead of floats //! double literals are used instead of floats
f32 scaledX = SCREEN_WIDTH * 360.0 * yaw / (fov * 65536.0); f32 scaledX = SCREEN_WIDTH * 180.0 * yaw / (fov * M_PI);
if (scaledX > SKYBOX_WIDTH) { if (scaledX > SKYBOX_WIDTH) {
scaledX -= (s32) scaledX / SKYBOX_WIDTH * SKYBOX_WIDTH; scaledX -= (s32) scaledX / SKYBOX_WIDTH * SKYBOX_WIDTH;
@ -156,9 +156,9 @@ s32 calculate_skybox_scaled_x(s8 player, f32 fov) {
* fov may have been used in an earlier version, but the developers changed the function to always use * fov may have been used in an earlier version, but the developers changed the function to always use
* 90 degrees. * 90 degrees.
*/ */
s32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) { f32 calculate_skybox_scaled_y(s8 player, UNUSED f32 fov) {
// Convert pitch to degrees. Pitch is bounded between -90 (looking down) and 90 (looking up). // Convert pitch to degrees. Pitch is bounded between -90 (looking down) and 90 (looking up).
f32 pitchInDegrees = (f32) sSkyBoxInfo[player].pitch * 360.0 / 65535.0; f32 pitchInDegrees = sSkyBoxInfo[player].pitch * 180.0 / M_PI;
// Scale by 360 / fov // Scale by 360 / fov
f32 degreesToScale = 360.0f * pitchInDegrees / 90.0; f32 degreesToScale = 360.0f * pitchInDegrees / 90.0;
@ -193,7 +193,7 @@ static s32 get_top_left_tile_idx(s8 player) {
* into an x and y by modulus and division by SKYBOX_COLS. x and y are then scaled by * into an x and y by modulus and division by SKYBOX_COLS. x and y are then scaled by
* SKYBOX_TILE_WIDTH to get a point in world space. * SKYBOX_TILE_WIDTH to get a point in world space.
*/ */
Vtx *make_skybox_rect(s32 tileIndex, s8 colorIndex, s32 row, s32 col, s8 player) { Vtx *make_skybox_rect(s32 tileIndex, s8 colorIndex, s32 row, s32 col) {
extern Vtx* gBackgroundSkyboxVerts[3][3]; extern Vtx* gBackgroundSkyboxVerts[3][3];
Vtx *verts; Vtx *verts;
@ -242,7 +242,7 @@ void draw_skybox_tile_grid(Gfx **dlist, s8 background, s8 player, s8 colorIndex)
texture = (Texture*)(*(SkyboxTexture *) segmented_to_virtual(sSkyboxTextures[background]))[tileIndex]; texture = (Texture*)(*(SkyboxTexture *) segmented_to_virtual(sSkyboxTextures[background]))[tileIndex];
} }
Vtx *vertices = make_skybox_rect(tileIndex, colorIndex, row, col, player); Vtx *vertices = make_skybox_rect(tileIndex, colorIndex, row, col);
gLoadBlockTexture((*dlist)++, 32, 32, G_IM_FMT_RGBA, texture); gLoadBlockTexture((*dlist)++, 32, 32, G_IM_FMT_RGBA, texture);
gSPVertex((*dlist)++, VIRTUAL_TO_PHYSICAL(vertices), 4, 0); gSPVertex((*dlist)++, VIRTUAL_TO_PHYSICAL(vertices), 4, 0);
@ -342,8 +342,11 @@ Gfx *create_skybox_facing_camera(s8 player, s8 background, f32 fov,
//! fov is always set to 90.0f. If this line is removed, then the game crashes because fov is 0 on //! fov is always set to 90.0f. If this line is removed, then the game crashes because fov is 0 on
//! the first frame, which causes a floating point divide by 0 //! the first frame, which causes a floating point divide by 0
fov = 90.0f; fov = 90.0f;
sSkyBoxInfo[player].yaw = atan2s(cameraFaceZ, cameraFaceX);
sSkyBoxInfo[player].pitch = atan2s(sqrtf(cameraFaceX * cameraFaceX + cameraFaceZ * cameraFaceZ), cameraFaceY); sSkyBoxInfo[player].yaw = (M_PI / 2.0) - atan2(cameraFaceZ, cameraFaceX);
if (sSkyBoxInfo[player].yaw < 0) { sSkyBoxInfo[player].yaw += M_PI * 2.0; }
sSkyBoxInfo[player].pitch = (M_PI / 2.0) - atan2(sqrtf(cameraFaceX * cameraFaceX + cameraFaceZ * cameraFaceZ), cameraFaceY);
sSkyBoxInfo[player].scaledX = calculate_skybox_scaled_x(player, fov); sSkyBoxInfo[player].scaledX = calculate_skybox_scaled_x(player, fov);
sSkyBoxInfo[player].scaledY = calculate_skybox_scaled_y(player, fov); sSkyBoxInfo[player].scaledY = calculate_skybox_scaled_y(player, fov);
sSkyBoxInfo[player].upperLeftTile = get_top_left_tile_idx(player); sSkyBoxInfo[player].upperLeftTile = get_top_left_tile_idx(player);