From f852ff4359adffc223f2d291264bf26f92496af2 Mon Sep 17 00:00:00 2001 From: arthurtilly <32559225+arthurtilly@users.noreply.github.com> Date: Mon, 22 Apr 2024 09:14:12 +1200 Subject: [PATCH] Platform Displacement 2.1 (#776) --- data/behavior_data.c | 8 +- include/config/config_movement.h | 6 - include/object_constants.h | 2 +- src/game/behaviors/bowser.inc.c | 17 +- .../behaviors/tilting_inverted_pyramid.inc.c | 27 --- src/game/platform_displacement.c | 219 ++++-------------- src/game/platform_displacement.h | 27 +-- 7 files changed, 69 insertions(+), 237 deletions(-) diff --git a/data/behavior_data.c b/data/behavior_data.c index a0d4303e..e125af26 100644 --- a/data/behavior_data.c +++ b/data/behavior_data.c @@ -2694,7 +2694,7 @@ const BehaviorScript bhvSushiShark[] = { const BehaviorScript bhvJrbSlidingBox[] = { BEGIN(OBJ_LIST_SURFACE), - OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE), + OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE | OBJ_FLAG_NO_AUTO_DISPLACEMENT), LOAD_COLLISION_DATA(jrb_seg7_collision_floating_box), SET_HOME(), BEGIN_LOOP(), @@ -5437,11 +5437,7 @@ const BehaviorScript bhvTTCPendulum[] = { const BehaviorScript bhvTTCTreadmill[] = { BEGIN(OBJ_LIST_SURFACE), -#ifdef PLATFORM_DISPLACEMENT_2 - OR_INT(oFlags, (OBJ_FLAG_COMPUTE_DIST_TO_MARIO | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE | OBJ_FLAG_VELOCITY_PLATFORM)), -#else - OR_INT(oFlags, (OBJ_FLAG_COMPUTE_DIST_TO_MARIO | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE)), -#endif + OR_INT(oFlags, (OBJ_FLAG_COMPUTE_DIST_TO_MARIO | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE | OBJ_FLAG_NO_AUTO_DISPLACEMENT)), SET_FLOAT(oCollisionDistance, 750), CALL_NATIVE(bhv_ttc_treadmill_init), DELAY(1), diff --git a/include/config/config_movement.h b/include/config/config_movement.h index c574ac14..78941544 100644 --- a/include/config/config_movement.h +++ b/include/config/config_movement.h @@ -136,14 +136,8 @@ */ #define BUGFIX_DIALOG_TIME_STOP -/** - * Enables Platform Displacement 2, an upgrade to the physics involving moving platforms and how Mario interacts with them. - */ -#define PLATFORM_DISPLACEMENT_2 - /** * Inertia defines; allow Mario to preserve his momemtum when leaving moving platforms. - * These require Platform Displacement 2 to be enabled. */ #define MARIO_INERTIA_UPWARD // #define MARIO_INERTIA_LATERAL diff --git a/include/object_constants.h b/include/object_constants.h index 949dd8d6..42b1dfd3 100644 --- a/include/object_constants.h +++ b/include/object_constants.h @@ -47,7 +47,7 @@ enum ObjFlags { OBJ_FLAG_1000 = (1 << 12), // 0x00001000 OBJ_FLAG_COMPUTE_ANGLE_TO_MARIO = (1 << 13), // 0x00002000 OBJ_FLAG_PERSISTENT_RESPAWN = (1 << 14), // 0x00004000 - OBJ_FLAG_VELOCITY_PLATFORM = (1 << 15), // 0x00008000 + OBJ_FLAG_NO_AUTO_DISPLACEMENT = (1 << 15), // 0x00008000 OBJ_FLAG_DONT_CALC_COLL_DIST = (1 << 16), // 0x00010000 OBJ_FLAG_SILHOUETTE = (1 << 19), // 0x00080000 OBJ_FLAG_OCCLUDE_SILHOUETTE = (1 << 20), // 0x00100000 diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index e801768a..d1c8aef9 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -1435,9 +1435,7 @@ s32 bowser_check_fallen_off_stage(void) { return FALSE; } -#ifdef PLATFORM_DISPLACEMENT_2 struct PlatformDisplacementInfo sBowserDisplacementInfo; -#endif /** * Set Bowser's actions @@ -1513,18 +1511,13 @@ s8 sBowserHealth[] = { 1, 1, 3 }; */ void bowser_free_update(void) { struct Object *platform = o->platform; -#ifdef PLATFORM_DISPLACEMENT_2 - s16 tmpOFaceAngleYaw = (s16) o->oFaceAngleYaw; + if (platform != NULL) { - // NOTE: This function was at one point using '&o->oFaceAngleYaw', which is a s32 address. Should tmpOFaceAngleYaw be using the first 16 bits instead, or was that a bug? - apply_platform_displacement(&sBowserDisplacementInfo, &o->oPosVec, &tmpOFaceAngleYaw, platform); - o->oFaceAngleYaw = tmpOFaceAngleYaw; + s16 tempYaw = (s16) o->oFaceAngleYaw; + apply_platform_displacement(&sBowserDisplacementInfo, &o->oPosVec, &tempYaw, platform); + o->oFaceAngleYaw = tempYaw; } -#else - if (platform != NULL) { - apply_platform_displacement(FALSE, platform); - } -#endif + // Reset grabbed status o->oBowserGrabbedStatus = BOWSER_GRAB_STATUS_NONE; // Update positions and actions (default action) diff --git a/src/game/behaviors/tilting_inverted_pyramid.inc.c b/src/game/behaviors/tilting_inverted_pyramid.inc.c index 5ae23a70..43eafda7 100644 --- a/src/game/behaviors/tilting_inverted_pyramid.inc.c +++ b/src/game/behaviors/tilting_inverted_pyramid.inc.c @@ -17,29 +17,13 @@ void bhv_platform_normals_init(void) { * then gradually tilt back moving Mario with them. */ void bhv_tilting_inverted_pyramid_loop(void) { -#ifndef PLATFORM_DISPLACEMENT_2 - Vec3f posBeforeRotation, posAfterRotation; - Vec3f marioPos, dist; -#endif Vec3f targetNormal; Mat4 *transform = &o->transform; s32 marioOnPlatform = (gMarioObject->platform == o); if (marioOnPlatform) { -#ifndef PLATFORM_DISPLACEMENT_2 - // Target the normal in Mario's direction - vec3_diff(dist, gMarioStates[0].pos, &o->oPosVec); - - // Get Mario's position before the rotation - vec3f_copy(marioPos, gMarioStates[0].pos); - - linear_mtxf_mul_vec3f(*transform, posBeforeRotation, dist); - targetNormal[0] = dist[0]; - targetNormal[2] = dist[2]; -#else // PLATFORM_DISPLACEMENT_2 targetNormal[0] = gMarioStates[0].pos[0] - o->oPosX; targetNormal[2] = gMarioStates[0].pos[2] - o->oPosZ; -#endif targetNormal[1] = 500.0f; vec3f_normalize(targetNormal); } else { @@ -54,16 +38,5 @@ void bhv_tilting_inverted_pyramid_loop(void) { approach_f32_symmetric_bool(&o->oTiltingPyramidNormalZ, targetNormal[2], 0.01f); mtxf_align_terrain_normal(*transform, &o->oTiltingPyramidNormalVec, &o->oPosVec, 0x0); -#ifndef PLATFORM_DISPLACEMENT_2 - // If Mario is on the platform, adjust his position for the platform tilt. - if (marioOnPlatform) { - linear_mtxf_mul_vec3f(*transform, posAfterRotation, dist); - marioPos[0] += posAfterRotation[0] - posBeforeRotation[0]; - marioPos[1] += posAfterRotation[1] - posBeforeRotation[1]; - marioPos[2] += posAfterRotation[2] - posBeforeRotation[2]; - vec3f_copy(gMarioStates[0].pos, marioPos); - } -#endif - o->header.gfx.throwMatrix = transform; } diff --git a/src/game/platform_displacement.c b/src/game/platform_displacement.c index ae505343..9ec266ef 100644 --- a/src/game/platform_displacement.c +++ b/src/game/platform_displacement.c @@ -10,10 +10,13 @@ #include "types.h" #include "sm64.h" #include "behavior_data.h" +#include "game_init.h" #include "config.h" struct Object *gMarioPlatform = NULL; +static struct PlatformDisplacementInfo sMarioDisplacementInfo; +static Vec3f sMarioAmountDisplaced; /** * Determine if Mario is standing on a platform object, meaning that he is @@ -48,6 +51,11 @@ void update_mario_platform(void) { if (floor != NULL && floor->object != NULL) { gMarioPlatform = floor->object; gMarioObject->platform = floor->object; + // If this is the first frame of Mario standing on the platform, + // then initialise his platform displacement info struct + if ((floor->object != sMarioDisplacementInfo.prevPlatform) || (gGlobalTimer != sMarioDisplacementInfo.prevTimer)) { + update_platform_displacement_info(&sMarioDisplacementInfo, gMarioState->pos, gMarioState->faceAngle[1], floor->object); + } } else { gMarioPlatform = NULL; gMarioObject->platform = NULL; @@ -56,42 +64,28 @@ void update_mario_platform(void) { } /** - * Get Mario's position and store it in x, y, and z. + * Set the values in the platform displacement struct for use next frame */ -void get_mario_pos(f32 *x, f32 *y, f32 *z) { - *x = gMarioStates[0].pos[0]; - *y = gMarioStates[0].pos[1]; - *z = gMarioStates[0].pos[2]; -} +void update_platform_displacement_info(struct PlatformDisplacementInfo *displaceInfo, Vec3f pos, s16 yaw, struct Object *platform) { + Vec3f scaledPos, yawVec, localPos; -/** - * Set Mario's position. - */ -void set_mario_pos(f32 x, f32 y, f32 z) { - gMarioStates[0].pos[0] = x; - gMarioStates[0].pos[1] = y; - gMarioStates[0].pos[2] = z; -} + // Avoid a crash if the platform unloaded its collision while stood on or is static + if (platform->header.gfx.throwMatrix == NULL) return; -#ifdef PLATFORM_DISPLACEMENT_2 -static struct PlatformDisplacementInfo sMarioDisplacementInfo; -static Vec3f sMarioAmountDisplaced; + // Update position + vec3_diff(localPos, pos, (*platform->header.gfx.throwMatrix)[3]); + linear_mtxf_transpose_mul_vec3(*platform->header.gfx.throwMatrix, scaledPos, localPos); + vec3_quot(displaceInfo->prevTransformedPos, scaledPos, platform->header.gfx.scale); + vec3_copy(displaceInfo->prevPos, pos); -extern s32 gGlobalTimer; + // Update yaw + vec3_set(yawVec, sins(yaw), 0, coss(yaw)); + linear_mtxf_transpose_mul_vec3(*platform->header.gfx.throwMatrix, displaceInfo->prevTransformedYawVec, yawVec); + displaceInfo->prevYaw = yaw; -/** - * Upscale or downscale a vector by another vector. - */ -static void scale_vec3f(Vec3f dst, Vec3f src, Vec3f scale, u32 doInverted) { - if (doInverted) { - dst[0] = src[0] / scale[0]; - dst[1] = src[1] / scale[1]; - dst[2] = src[2] / scale[2]; - } else { - dst[0] = src[0] * scale[0]; - dst[1] = src[1] * scale[1]; - dst[2] = src[2] * scale[2]; - } + // Update platform and timer + displaceInfo->prevPlatform = platform; + displaceInfo->prevTimer = gGlobalTimer; } /** @@ -99,74 +93,48 @@ static void scale_vec3f(Vec3f dst, Vec3f src, Vec3f scale, u32 doInverted) { * platform. */ void apply_platform_displacement(struct PlatformDisplacementInfo *displaceInfo, Vec3f pos, s16 *yaw, struct Object *platform) { - Vec3f platformPos; Vec3f posDifference; Vec3f yawVec; Vec3f scaledPos; // Determine how much Mario turned on his own since last frame s16 yawDifference = *yaw - displaceInfo->prevYaw; - // Avoid a crash if the platform unloaded its collision while stood on + // Avoid a crash if the platform unloaded its collision while stood on or is static if (platform->header.gfx.throwMatrix == NULL) return; - vec3f_copy(platformPos, (*platform->header.gfx.throwMatrix)[3]); - // Determine how far Mario moved on his own since last frame - vec3f_copy(posDifference, pos); - vec3f_sub(posDifference, displaceInfo->prevPos); + vec3_diff(posDifference, pos, displaceInfo->prevPos); if ((platform == displaceInfo->prevPlatform) && (gGlobalTimer == displaceInfo->prevTimer + 1)) { - // Transform from relative positions to world positions - scale_vec3f(scaledPos, displaceInfo->prevTransformedPos, platform->header.gfx.scale, FALSE); - linear_mtxf_mul_vec3f(*platform->header.gfx.throwMatrix, pos, scaledPos); + // For certain objects, only use velocity for displacement rather than the transform + // E.g. TTC treadmills + if (platform->oFlags & OBJ_FLAG_NO_AUTO_DISPLACEMENT) { + pos[0] += platform->oVelX; + pos[1] += platform->oVelY; + pos[2] += platform->oVelZ; + } else { + // Transform from relative positions to world positions + vec3_prod(scaledPos, displaceInfo->prevTransformedPos, platform->header.gfx.scale); + linear_mtxf_mul_vec3(*platform->header.gfx.throwMatrix, pos, scaledPos); + vec3_add(pos, (*platform->header.gfx.throwMatrix)[3]); - // Add on how much Mario moved in the previous frame - vec3f_add(pos, posDifference); + // Add on how much Mario moved in the previous frame + vec3_add(pos, posDifference); - // Calculate new yaw - linear_mtxf_mul_vec3f(*platform->header.gfx.throwMatrix, yawVec, displaceInfo->prevTransformedYawVec); - *yaw = atan2s(yawVec[2], yawVec[0]) + yawDifference; - } else { - // First frame of standing on the platform, don't calculate a new position - vec3f_sub(pos, platformPos); - } - - // Apply velocity-based displacement for certain objects (like the TTC Treadmills) - if (platform->oFlags & OBJ_FLAG_VELOCITY_PLATFORM) { - pos[0] += platform->oVelX; - pos[1] += platform->oVelY; - pos[2] += platform->oVelZ; - } - - // Transform from world positions to relative positions for use next frame - linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, scaledPos, pos); - scale_vec3f(displaceInfo->prevTransformedPos, scaledPos, platform->header.gfx.scale, TRUE); - vec3f_add(pos, platformPos); - - // If the object is Mario, set inertia - if (pos == gMarioState->pos) { - vec3f_copy(sMarioAmountDisplaced, pos); - vec3f_sub(sMarioAmountDisplaced, displaceInfo->prevPos); - vec3f_sub(sMarioAmountDisplaced, posDifference); - - // Make sure inertia isn't set on the first frame otherwise the previous value isn't cleared - if ((platform != displaceInfo->prevPlatform) || (gGlobalTimer != displaceInfo->prevTimer + 1)) { - vec3_zero(sMarioAmountDisplaced); + // Calculate new yaw + linear_mtxf_mul_vec3(*platform->header.gfx.throwMatrix, yawVec, displaceInfo->prevTransformedYawVec); + *yaw = atan2s(yawVec[2], yawVec[0]) + yawDifference; } } - // Update info for next frame - // Update position - vec3f_copy(displaceInfo->prevPos, pos); + Vec3f oldPos; + vec3_sum(oldPos, displaceInfo->prevPos, posDifference); + update_platform_displacement_info(displaceInfo, pos, *yaw, platform); - // Set yaw info - vec3f_set(yawVec, sins(*yaw), 0, coss(*yaw)); - linear_mtxf_transpose_mul_vec3f(*platform->header.gfx.throwMatrix, displaceInfo->prevTransformedYawVec, yawVec); - displaceInfo->prevYaw = *yaw; - - // Update platform and timer - displaceInfo->prevPlatform = platform; - displaceInfo->prevTimer = gGlobalTimer; + // If the object is Mario, set inertia + if (pos == gMarioState->pos) { + vec3_diff(sMarioAmountDisplaced, pos, oldPos); + } } // Doesn't change in the code, set this to FALSE if you don't want inertia @@ -223,93 +191,6 @@ void apply_mario_platform_displacement(void) { } } -#else - -/** - * Apply one frame of platform rotation to Mario or an object using the given - * platform. If isMario is false, use gCurrentObject. - */ -void apply_platform_displacement(u32 isMario, struct Object *platform) { - f32 x, y, z; - f32 platformPosX, platformPosY, platformPosZ; - Vec3f currentObjectOffset; - Vec3f relativeOffset; - Vec3f newObjectOffset; - Vec3s rotation; - Mat4 displaceMatrix; - - rotation[0] = platform->oAngleVelPitch; - rotation[1] = platform->oAngleVelYaw; - rotation[2] = platform->oAngleVelRoll; - - if (isMario) { - get_mario_pos(&x, &y, &z); - } else { - x = gCurrentObject->oPosX; - y = gCurrentObject->oPosY; - z = gCurrentObject->oPosZ; - } - - x += platform->oVelX; - z += platform->oVelZ; - - if (rotation[0] != 0 || rotation[1] != 0 || rotation[2] != 0) { - // unusedPitch = rotation[0]; - // unusedRoll = rotation[2]; - // unusedYaw = platform->oFaceAngleYaw; - - if (isMario) { - gMarioStates[0].faceAngle[1] += rotation[1]; - } - - platformPosX = platform->oPosX; - platformPosY = platform->oPosY; - platformPosZ = platform->oPosZ; - - currentObjectOffset[0] = x - platformPosX; - currentObjectOffset[1] = y - platformPosY; - currentObjectOffset[2] = z - platformPosZ; - - rotation[0] = platform->oFaceAnglePitch - platform->oAngleVelPitch; - rotation[1] = platform->oFaceAngleYaw - platform->oAngleVelYaw; - rotation[2] = platform->oFaceAngleRoll - platform->oAngleVelRoll; - - mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation); - linear_mtxf_transpose_mul_vec3f(displaceMatrix, relativeOffset, currentObjectOffset); - - rotation[0] = platform->oFaceAnglePitch; - rotation[1] = platform->oFaceAngleYaw; - rotation[2] = platform->oFaceAngleRoll; - - mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation); - linear_mtxf_mul_vec3f(displaceMatrix, newObjectOffset, relativeOffset); - - x = platformPosX + newObjectOffset[0]; - y = platformPosY + newObjectOffset[1]; - z = platformPosZ + newObjectOffset[2]; - } - - if (isMario) { - set_mario_pos(x, y, z); - } else { - gCurrentObject->oPosX = x; - gCurrentObject->oPosY = y; - gCurrentObject->oPosZ = z; - } -} - -/** - * If Mario's platform is not null, apply platform displacement. - */ -void apply_mario_platform_displacement(void) { - struct Object *platform = gMarioPlatform; - - if (!(gTimeStopState & TIME_STOP_ACTIVE) && gMarioObject != NULL && platform != NULL) { - apply_platform_displacement(TRUE, platform); - } -} -#endif - /** * Set Mario's platform to NULL. */ diff --git a/src/game/platform_displacement.h b/src/game/platform_displacement.h index 6029be9a..590c1bb9 100644 --- a/src/game/platform_displacement.h +++ b/src/game/platform_displacement.h @@ -6,24 +6,19 @@ #include "types.h" #include "config.h" -#ifdef PLATFORM_DISPLACEMENT_2 - struct PlatformDisplacementInfo { - Vec3f prevPos; - Vec3f prevTransformedPos; - Vec3f prevTransformedYawVec; - s16 prevYaw; - struct Object *prevPlatform; - s32 prevTimer; - }; -#endif + +struct PlatformDisplacementInfo { + Vec3f prevPos; + Vec3f prevTransformedPos; + Vec3f prevTransformedYawVec; + s16 prevYaw; + struct Object *prevPlatform; + u32 prevTimer; +}; + void update_mario_platform(void); -void get_mario_pos(f32 *x, f32 *y, f32 *z); -void set_mario_pos(f32 x, f32 y, f32 z); -#ifdef PLATFORM_DISPLACEMENT_2 +void update_platform_displacement_info(struct PlatformDisplacementInfo *displaceInfo, Vec3f pos, s16 yaw, struct Object *platform); void apply_platform_displacement(struct PlatformDisplacementInfo *displaceInfo, Vec3f pos, s16 *yaw, struct Object *platform); -#else -void apply_platform_displacement(u32 isMario, struct Object *platform); -#endif void apply_mario_platform_displacement(void); void clear_mario_platform(void);