sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

platform_displacement.c (5111B)


      1 #include <PR/ultratypes.h>
      2 
      3 #include "engine/math_util.h"
      4 #include "engine/surface_collision.h"
      5 #include "level_update.h"
      6 #include "object_fields.h"
      7 #include "object_helpers.h"
      8 #include "object_list_processor.h"
      9 #include "platform_displacement.h"
     10 #include "types.h"
     11 
     12 u16 D_8032FEC0 = 0;
     13 
     14 u32 unused_8032FEC4[4] = { 0 };
     15 
     16 struct Object *gMarioPlatform = NULL;
     17 
     18 /**
     19  * Determine if Mario is standing on a platform object, meaning that he is
     20  * within 4 units of the floor. Set his referenced platform object accordingly.
     21  */
     22 void update_mario_platform(void) {
     23     struct Surface *floor;
     24     UNUSED u8 filler[4];
     25     f32 marioX;
     26     f32 marioY;
     27     f32 marioZ;
     28     f32 floorHeight;
     29     u32 awayFromFloor;
     30 
     31     if (gMarioObject == NULL) {
     32         return;
     33     }
     34 
     35     //! If Mario moves onto a rotating platform in a PU, the find_floor call
     36     //  will detect the platform and he will end up receiving a large amount
     37     //  of displacement since he is considered to be far from the platform's
     38     //  axis of rotation.
     39 
     40     marioX = gMarioObject->oPosX;
     41     marioY = gMarioObject->oPosY;
     42     marioZ = gMarioObject->oPosZ;
     43     floorHeight = find_floor(marioX, marioY, marioZ, &floor);
     44 
     45     if (absf(marioY - floorHeight) < 4.0f) {
     46         awayFromFloor = 0;
     47     } else {
     48         awayFromFloor = 1;
     49     }
     50 
     51     switch (awayFromFloor) {
     52         case 1:
     53             gMarioPlatform = NULL;
     54             gMarioObject->platform = NULL;
     55             break;
     56 
     57         case 0:
     58             if (floor != NULL && floor->object != NULL) {
     59                 gMarioPlatform = floor->object;
     60                 gMarioObject->platform = floor->object;
     61             } else {
     62                 gMarioPlatform = NULL;
     63                 gMarioObject->platform = NULL;
     64             }
     65             break;
     66     }
     67 }
     68 
     69 /**
     70  * Get Mario's position and store it in x, y, and z.
     71  */
     72 void get_mario_pos(f32 *x, f32 *y, f32 *z) {
     73     *x = gMarioStates[0].pos[0];
     74     *y = gMarioStates[0].pos[1];
     75     *z = gMarioStates[0].pos[2];
     76 }
     77 
     78 /**
     79  * Set Mario's position.
     80  */
     81 void set_mario_pos(f32 x, f32 y, f32 z) {
     82     gMarioStates[0].pos[0] = x;
     83     gMarioStates[0].pos[1] = y;
     84     gMarioStates[0].pos[2] = z;
     85 }
     86 
     87 /**
     88  * Apply one frame of platform rotation to Mario or an object using the given
     89  * platform. If isMario is false, use gCurrentObject.
     90  */
     91 void apply_platform_displacement(u32 isMario, struct Object *platform) {
     92     f32 x;
     93     f32 y;
     94     f32 z;
     95     f32 platformPosX;
     96     f32 platformPosY;
     97     f32 platformPosZ;
     98     Vec3f currentObjectOffset;
     99     Vec3f relativeOffset;
    100     Vec3f newObjectOffset;
    101     Vec3s rotation;
    102     UNUSED s16 unusedPitch;
    103     UNUSED s16 unusedRoll;
    104     UNUSED s16 unusedYaw;
    105     f32 displaceMatrix[4][4];
    106 
    107     rotation[0] = platform->oAngleVelPitch;
    108     rotation[1] = platform->oAngleVelYaw;
    109     rotation[2] = platform->oAngleVelRoll;
    110 
    111     if (isMario) {
    112         D_8032FEC0 = 0;
    113         get_mario_pos(&x, &y, &z);
    114     } else {
    115         x = gCurrentObject->oPosX;
    116         y = gCurrentObject->oPosY;
    117         z = gCurrentObject->oPosZ;
    118     }
    119 
    120     x += platform->oVelX;
    121     z += platform->oVelZ;
    122 
    123     if (rotation[0] != 0 || rotation[1] != 0 || rotation[2] != 0) {
    124         unusedPitch = rotation[0];
    125         unusedRoll  = rotation[2];
    126         unusedYaw   = platform->oFaceAngleYaw;
    127 
    128         if (isMario) {
    129             gMarioStates[0].faceAngle[1] += rotation[1];
    130         }
    131 
    132         platformPosX = platform->oPosX;
    133         platformPosY = platform->oPosY;
    134         platformPosZ = platform->oPosZ;
    135 
    136         currentObjectOffset[0] = x - platformPosX;
    137         currentObjectOffset[1] = y - platformPosY;
    138         currentObjectOffset[2] = z - platformPosZ;
    139 
    140         rotation[0] = platform->oFaceAnglePitch - platform->oAngleVelPitch;
    141         rotation[1] = platform->oFaceAngleYaw - platform->oAngleVelYaw;
    142         rotation[2] = platform->oFaceAngleRoll - platform->oAngleVelRoll;
    143 
    144         mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
    145         linear_mtxf_transpose_mul_vec3f(displaceMatrix, relativeOffset, currentObjectOffset);
    146 
    147         rotation[0] = platform->oFaceAnglePitch;
    148         rotation[1] = platform->oFaceAngleYaw;
    149         rotation[2] = platform->oFaceAngleRoll;
    150 
    151         mtxf_rotate_zxy_and_translate(displaceMatrix, currentObjectOffset, rotation);
    152         linear_mtxf_mul_vec3f(displaceMatrix, newObjectOffset, relativeOffset);
    153 
    154         x = platformPosX + newObjectOffset[0];
    155         y = platformPosY + newObjectOffset[1];
    156         z = platformPosZ + newObjectOffset[2];
    157     }
    158 
    159     if (isMario) {
    160         set_mario_pos(x, y, z);
    161     } else {
    162         gCurrentObject->oPosX = x;
    163         gCurrentObject->oPosY = y;
    164         gCurrentObject->oPosZ = z;
    165     }
    166 }
    167 
    168 /**
    169  * If Mario's platform is not null, apply platform displacement.
    170  */
    171 void apply_mario_platform_displacement(void) {
    172     struct Object *platform = gMarioPlatform;
    173 
    174     if (!(gTimeStopState & TIME_STOP_ACTIVE) && gMarioObject != NULL && platform != NULL) {
    175         apply_platform_displacement(TRUE, platform);
    176     }
    177 }
    178 
    179 #ifndef VERSION_JP
    180 /**
    181  * Set Mario's platform to NULL.
    182  */
    183 void clear_mario_platform(void) {
    184     gMarioPlatform = NULL;
    185 }
    186 #endif