Files
libsm64/src/decomp/game/platform_displacement.c
T

169 lines
4.7 KiB
C

#include <math.h>
#include "../engine/math_util.h"
#include "../engine/surface_collision.h"
#include "level_update.h"
#include "../include/object_fields.h"
#include "object_stuff.h"
#include "platform_displacement.h"
#include "../shim.h"
#include "../global_state.h"
#include "../../load_surfaces.h"
#define absfx( x ) ( (x) < 0.0f ? -(x) : (x) )
/**
* Determine if Mario is standing on a platform object, meaning that he is
* within 4 units of the floor. Set his referenced platform object accordingly.
*/
void update_mario_platform(void) {
struct Surface *floor;
UNUSED u32 unused;
f32 marioX;
f32 marioY;
f32 marioZ;
f32 floorHeight;
u32 awayFromFloor;
if (gMarioObject == NULL) {
return;
}
//! If Mario moves onto a rotating platform in a PU, the find_floor call
// will detect the platform and he will end up receiving a large amount
// of displacement since he is considered to be far from the platform's
// axis of rotation.
marioX = gMarioObject->oPosX;
marioY = gMarioObject->oPosY;
marioZ = gMarioObject->oPosZ;
floorHeight = find_floor(marioX, marioY, marioZ, &floor);
if (absfx(marioY - floorHeight) < 4.0f) {
awayFromFloor = 0;
} else {
awayFromFloor = 1;
}
switch (awayFromFloor) {
case 1:
gMarioObject->platform = NULL;
break;
case 0:
if (floor != NULL && floor->transform != NULL) {
gMarioObject->platform = floor->transform;
} else {
gMarioObject->platform = NULL;
}
break;
}
}
/**
* Get Mario's position and store it in x, y, and z.
*/
static void get_mario_pos(f32 *x, f32 *y, f32 *z) {
*x = gMarioState->pos[0];
*y = gMarioState->pos[1];
*z = gMarioState->pos[2];
}
/**
* Set Mario's position.
*/
static void set_mario_pos(f32 x, f32 y, f32 z) {
gMarioState->pos[0] = x;
gMarioState->pos[1] = y;
gMarioState->pos[2] = z;
}
/**
* 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 SurfaceObjectTransform *platform) {
f32 x;
f32 y;
f32 z;
f32 platformPosX;
f32 platformPosY;
f32 platformPosZ;
Vec3f currentObjectOffset;
Vec3f relativeOffset;
Vec3f newObjectOffset;
Vec3s rotation;
UNUSED s16 unused1;
UNUSED s16 unused2;
UNUSED s16 unused3;
f32 displaceMatrix[4][4];
rotation[0] = platform->aAngleVelPitch;
rotation[1] = platform->aAngleVelYaw;
rotation[2] = platform->aAngleVelRoll;
// if (isMario) {
// D_8032FEC0 = 0;
get_mario_pos(&x, &y, &z);
// } else {
// x = gCurrentObject->aPosX;
// y = gCurrentObject->aPosY;
// z = gCurrentObject->aPosZ;
// }
x += platform->aVelX;
z += platform->aVelZ;
if (rotation[0] != 0 || rotation[1] != 0 || rotation[2] != 0) {
unused1 = rotation[0];
unused2 = rotation[2];
unused3 = platform->aFaceAngleYaw;
if (isMario) {
gMarioState->faceAngle[1] += rotation[1];
}
platformPosX = platform->aPosX;
platformPosY = platform->aPosY;
platformPosZ = platform->aPosZ;
currentObjectOffset[0] = x - platformPosX;
currentObjectOffset[1] = y - platformPosY;
currentObjectOffset[2] = z - platformPosZ;
rotation[0] = platform->aFaceAnglePitch - platform->aAngleVelPitch;
rotation[1] = platform->aFaceAngleYaw - platform->aAngleVelYaw;
rotation[2] = platform->aFaceAngleRoll - platform->aAngleVelRoll;
mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
linear_mtxf_transpose_mul_vec3f(displaceMatrix, relativeOffset, currentObjectOffset);
rotation[0] = platform->aFaceAnglePitch;
rotation[1] = platform->aFaceAngleYaw;
rotation[2] = platform->aFaceAngleRoll;
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) {
if (gMarioObject != NULL && gMarioObject->platform != NULL) {
apply_platform_displacement(TRUE, gMarioObject->platform);
}
}