diff options
| author | engineer124 <47598039+engineer124@users.noreply.github.com> | 2022-08-15 14:36:33 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-15 14:36:33 -0400 |
| commit | 0082c299c62ca5debfbaee1ce21d67df7fb0b441 (patch) | |
| tree | 28ae5ce6384d7d75eabb89861c9ecc821c213310 /src/code/z_camera.c | |
| parent | 24ba04d70c7e8af692ddaadbe4f356b5c91212c4 (diff) | |
Decompile Camera Helper Functions (#1023)
* helper functions
* more pr suggestions
Diffstat (limited to 'src/code/z_camera.c')
| -rw-r--r-- | src/code/z_camera.c | 418 |
1 files changed, 386 insertions, 32 deletions
diff --git a/src/code/z_camera.c b/src/code/z_camera.c index 20420d6ef..027b78a4a 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -1,42 +1,243 @@ #include "global.h" -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_fabsf.s") +/** + * Returns the absolute value for floats + */ +f32 Camera_fabsf(f32 f) { + return ABS(f); +} + +/** + * Returns the magnitude for 3D float vectors + */ +f32 Camera_Vec3fMagnitude(Vec3f* vec) { + return sqrtf(SQ(vec->x) + SQ(vec->y) + SQ(vec->z)); +} + +/** + * Interpolates along the curve shown below + * returns value y ranging from 0.0f to 1.0f for -xMax <= x <= xMax + * returns 1.0f otherwise + * + * y = 1.0f ________ _________ + * __ __ + * _ _ + * y axis _ _ + * ___ ___ + * _____ + * y = 0.0f | | | + * -xMax 0 xMax + * + * x axis + */ +f32 Camera_QuadraticAttenuation(f32 xRange, f32 x) { + f32 y; + f32 absX; + f32 percent40 = 0.4f; + f32 percent60; + f32 xQuadratic; + f32 xMaxQuadratic; // Normalizing constant + + absX = Camera_fabsf(x); + + if (absX > xRange) { + // fixed value outside xMax range + y = 1.0f; + } else { + // inside xMax range + percent60 = 1.0f - percent40; + + if (absX < (xRange * percent60)) { + // quadratic curve in the inner 60% of xMax range: +concavity (upward curve) + xQuadratic = SQ(x) * (1.0f - percent40); + xMaxQuadratic = SQ(xRange * percent60); + + y = xQuadratic / xMaxQuadratic; + } else { + // quadratic curve in the outer 40% of xMax range: -concavity (flattening curve) + xQuadratic = SQ(xRange - absX) * percent40; + xMaxQuadratic = SQ(0.4f * xRange); + + y = 1.0f - (xQuadratic / xMaxQuadratic); + } + } + return y; +} + +/* + * Performs linear interpoloation between `cur` and `target`. If `cur` is within + * `minDiff` units, the result is rounded up to `target` + */ +f32 Camera_LerpCeilF(f32 target, f32 cur, f32 stepScale, f32 minDiff) { + f32 diff = target - cur; + f32 step = diff * stepScale; + + return (Camera_fabsf(diff) >= minDiff) ? cur + step : target; +} + +/* + * Performs linear interpoloation between `cur` and `target`. If `cur` is within + * `minDiff` units, the result is rounded up to `target` + */ +s16 Camera_LerpCeilS(s16 target, s16 cur, f32 stepScale, s16 minDiff) { + s16 diff = target - cur; + s16 step = diff * stepScale + 0.5f; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_LengthVec3f.s") + return (ABS(diff) >= minDiff) ? cur + step : target; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB270.s") +/* + * Performs linear interpoloation between `cur` and `target`. If `cur` is within + * `minDiff` units, the result is rounded down to `cur` + */ +s16 Camera_LerpFloorS(s16 target, s16 cur, f32 stepScale, s16 minDiff) { + s16 diff = target - cur; + s16 step = diff * stepScale + 0.5f; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Lerpf.s") + return (ABS(diff) >= minDiff) ? cur + step : cur; +} + +/* + * Performs linear interpoloation between `cur` and `target`. If `cur` is within + * `minDiff` units, the result is rounded up to `target`. Output is written to `cur` + */ +void Camera_LerpCeilVec3f(Vec3f* target, Vec3f* cur, f32 xzStepScale, f32 yStepScale, f32 minDiff) { + cur->x = Camera_LerpCeilF(target->x, cur->x, xzStepScale, minDiff); + cur->y = Camera_LerpCeilF(target->y, cur->y, yStepScale, minDiff); + cur->z = Camera_LerpCeilF(target->z, cur->z, xzStepScale, minDiff); +} + +void Camera_SetUpdateRatesFastPitch(Camera* camera) { + camera->yawUpdateRateInv = 100.0f; + camera->pitchUpdateRateInv = 16.0f; + camera->rUpdateRateInv = 20.0f; + camera->yOffsetUpdateRate = 0.05f; + camera->xzOffsetUpdateRate = 0.05f; + camera->fovUpdateRate = 0.05f; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Lerps.s") +void Camera_SetUpdateRatesFastYaw(Camera* camera) { + camera->rUpdateRateInv = 50.0f; + camera->pitchUpdateRateInv = 100.0f; + camera->yawUpdateRateInv = 50.0f; + camera->yOffsetUpdateRate = 0.01f; + camera->xzOffsetUpdateRate = 0.1f; + camera->fovUpdateRate = 0.01f; + if (camera->speedRatio > 1.0f) { + camera->speedRatio = 1.0f; + } +} + +void Camera_SetUpdateRatesSlow(Camera* camera) { + camera->rUpdateRateInv = 1800.0f; + camera->yawUpdateRateInv = 1800.0f; + camera->pitchUpdateRateInv = 1800.0f; + camera->yOffsetUpdateRate = 0.01; + camera->xzOffsetUpdateRate = 0.01; + camera->fovUpdateRate = 0.01; +} + +/** + * Converts a 3D s16 vector into a 3D f32 vector + */ +Vec3f* Camera_Vec3sToVec3f(Vec3f* dest, Vec3s* src) { + Vec3f copy; + + copy.x = src->x; + copy.y = src->y; + copy.z = src->z; + + *dest = copy; + return dest; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB42C.s") +/** + * Returns the difference between two angles and scales the difference up + */ +s16 Camera_AngleDiffAndScale(s16 angle1, s16 angle2, f32 scale) { + return BINANG_SUB(angle1, angle2) * scale; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_LerpVec3f.s") +/** + * Calculates the current offset between the camera's at-coordinates and the centered actor's coordinates + */ +void Camera_UpdateAtActorOffset(Camera* camera, Vec3f* actorOffset) { + camera->atActorOffset.x = camera->at.x - actorOffset->x; + camera->atActorOffset.y = camera->at.y - actorOffset->y; + camera->atActorOffset.z = camera->at.z - actorOffset->z; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB544.s") +f32 Camera_GetFocalActorHeight(Camera* camera) { + PosRot actorFocus; + Actor* focalActor = camera->focalActor; + f32 focalHeight; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB584.s") + if (focalActor == &GET_PLAYER(camera->play)->actor) { + focalHeight = Player_GetHeight((Player*)focalActor); + } else { + Actor_GetFocus(&actorFocus, focalActor); + focalHeight = actorFocus.pos.y - camera->focalActorPosRot.pos.y; + if (focalHeight == 0.0f) { + focalHeight = 10.0f; + } + } + return focalHeight; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB5DC.s") +f32 Camera_GetRunSpeedLimit(Camera* camera) { + Actor* focalActor = camera->focalActor; + f32 runSpeedLimit; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB60C.s") + if (focalActor == &GET_PLAYER(camera->play)->actor) { + runSpeedLimit = Player_GetRunSpeedLimit((Player*)focalActor); + } else { + runSpeedLimit = 10.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB674.s") + return runSpeedLimit; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB6C8.s") +s32 func_800CB7CC(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB700.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags3 & PLAYER_STATE3_10; + } else { + return 0; + } +} +s32 Camera_IsMountedOnHorse(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB780.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_800000; + } else { + return 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB7CC.s") +s32 Camera_IsDekuHovering(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB7F8.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags3 & PLAYER_STATE3_2000; + } else { + return 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB828.s") +/** + * When walking in a cutscene? Used during Postman's minigame. + */ +s32 func_800CB854(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB854.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_20; + } else { + return 0; + } +} s32 Camera_IsSwimming(Camera* camera) { Actor* focalActor = camera->focalActor; @@ -55,31 +256,184 @@ s32 Camera_IsSwimming(Camera* camera) { } } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB8C8.s") +s32 Camera_IsDiving(Camera* camera) { + Actor* focalActor = camera->focalActor; + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags2 & PLAYER_STATE2_800; + } else { + return 0; + } +} + +s32 Camera_IsPlayerFormZora(Camera* camera) { + Actor* focalActor = camera->focalActor; + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->transformation == PLAYER_FORM_ZORA; + } else { + return false; + } +} + +s32 func_800CB924(Camera* camera) { + Actor* focalActor = camera->focalActor; + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags3 & PLAYER_STATE3_1000; + } else { + return 0; + } +} + +s32 func_800CB950(Camera* camera) { + Player* player; + s32 phi_v0; + s32 ret; + f32 yDiff; + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + yDiff = Camera_fabsf(camera->focalActorPosRot.pos.y - camera->playerFloorHeight); + + phi_v0 = false; + if (yDiff < 11.0f) { + phi_v0 = true; + } + + ret = phi_v0; + + if (!ret) { + + ret = false; + + if (camera->focalActor->gravity > -0.1f) { + ret = true; + } + + player = (Player*)camera->focalActor; + if (!ret) { + // Using zora fins + ret = player->stateFlags1 & PLAYER_STATE1_200000; + ret = !!ret; + } + } + return ret; + } else { + return true; + } +} + +s32 Camera_IsClimbingLedge(Camera* camera) { + Actor* focalActor = camera->focalActor; + + if (focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_4; + } else { + return 0; + } +} + +s32 Camera_IsChargingSwordOrDekuFlowerDive(Camera* camera) { + Actor* focalActor = camera->focalActor; + s32 ret; + + if (focalActor == &GET_PLAYER(camera->play)->actor) { + // Charging Sword + ret = !!(((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_1000); + if (!ret) { + // Deku Flower Dive + ret = !!(((Player*)focalActor)->stateFlags3 & PLAYER_STATE3_100); + } + return ret; + } else { + return false; + } +} + +s32 func_800CBA7C(Camera* camera) { + Actor* focalActor = camera->focalActor; + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags2 & PLAYER_STATE2_800000; + } else { + return 0; + } +} + +s32 func_800CBAAC(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB8F4.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->meleeWeaponState; + } else { + return 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB924.s") +s32 Camera_GetFocalActorPos(Vec3f* dst, Camera* camera) { + PosRot focalPosRot; + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB950.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + *dst = ((Player*)focalActor)->bodyPartsPos[0]; + return dst; + } else { + Actor_GetWorldPosShapeRot(&focalPosRot, camera->focalActor); + *dst = focalPosRot.pos; + return dst; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBA08.s") +s32 Camera_IsUnderwaterAsZora(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBA34.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->currentBoots == PLAYER_BOOTS_ZORA_UNDERWATER; + } else { + return 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBA7C.s") +/** + * Evaluate if player is in one of two sword animations + */ +s32 func_800CBB88(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBAAC.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + if ((((Player*)focalActor)->meleeWeaponState != 0) && + (((Player*)focalActor)->meleeWeaponAnimation == PLAYER_MWA_GORON_PUNCH_BUTT)) { + return 3; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBAD4.s") + if ((((Player*)focalActor)->stateFlags2 & PLAYER_STATE2_20000) || + ((((Player*)focalActor)->meleeWeaponState != 0) && + (((Player*)focalActor)->meleeWeaponAnimation == PLAYER_MWA_ZORA_PUNCH_KICK))) { + return 1; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBB58.s") + return 0; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBB88.s") +s32 Camera_IsUsingZoraFins(Camera* camera) { + Actor* focalActor = camera->focalActor; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBC00.s") + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + return ((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_200000; + } else { + return 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBC30.s") +s32 func_800CBC30(Camera* camera, f32 waterYMax, f32 waterYMin) { + if ((camera->playerFloorHeight != camera->waterYPos) && (camera->waterYPos < waterYMax) && + (camera->waterYPos > waterYMin)) { + return true; + } else { + return false; + } +} #pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBC84.s") |
