Decompile Camera Helper Functions (#1023)

* helper functions

* more pr suggestions
This commit is contained in:
engineer124
2022-08-15 14:36:33 -04:00
committed by GitHub
parent 24ba04d70c
commit 0082c299c6
4 changed files with 433 additions and 111 deletions
+386 -32
View File
@@ -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);
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_LengthVec3f.s")
/**
* Returns the magnitude for 3D float vectors
*/
f32 Camera_Vec3fMagnitude(Vec3f* vec) {
return sqrtf(SQ(vec->x) + SQ(vec->y) + SQ(vec->z));
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB270.s")
/**
* 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
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Lerpf.s")
absX = Camera_fabsf(x);
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Lerps.s")
if (absX > xRange) {
// fixed value outside xMax range
y = 1.0f;
} else {
// inside xMax range
percent60 = 1.0f - percent40;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB42C.s")
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);
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_LerpVec3f.s")
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);
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB544.s")
y = 1.0f - (xQuadratic / xMaxQuadratic);
}
}
return y;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB584.s")
/*
* 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;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB5DC.s")
return (Camera_fabsf(diff) >= minDiff) ? cur + step : target;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB60C.s")
/*
* 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/func_800CB674.s")
return (ABS(diff) >= minDiff) ? cur + step : target;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB6C8.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/func_800CB700.s")
return (ABS(diff) >= minDiff) ? cur + step : cur;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB780.s")
/*
* 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);
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB7CC.s")
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/func_800CB7F8.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;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB828.s")
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;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB854.s")
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
f32 Camera_GetFocalActorHeight(Camera* camera) {
PosRot actorFocus;
Actor* focalActor = camera->focalActor;
f32 focalHeight;
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;
}
f32 Camera_GetRunSpeedLimit(Camera* camera) {
Actor* focalActor = camera->focalActor;
f32 runSpeedLimit;
if (focalActor == &GET_PLAYER(camera->play)->actor) {
runSpeedLimit = Player_GetRunSpeedLimit((Player*)focalActor);
} else {
runSpeedLimit = 10.0f;
}
return runSpeedLimit;
}
s32 func_800CB7CC(Camera* camera) {
Actor* focalActor = camera->focalActor;
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;
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_800000;
} else {
return 0;
}
}
s32 Camera_IsDekuHovering(Camera* camera) {
Actor* focalActor = camera->focalActor;
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->stateFlags3 & PLAYER_STATE3_2000;
} else {
return 0;
}
}
/**
* When walking in a cutscene? Used during Postman's minigame.
*/
s32 func_800CB854(Camera* camera) {
Actor* focalActor = camera->focalActor;
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;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB8F4.s")
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->stateFlags2 & PLAYER_STATE2_800;
} else {
return 0;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB924.s")
s32 Camera_IsPlayerFormZora(Camera* camera) {
Actor* focalActor = camera->focalActor;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CB950.s")
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->transformation == PLAYER_FORM_ZORA;
} else {
return false;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBA08.s")
s32 func_800CB924(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)->stateFlags3 & PLAYER_STATE3_1000;
} else {
return 0;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBA7C.s")
s32 func_800CB950(Camera* camera) {
Player* player;
s32 phi_v0;
s32 ret;
f32 yDiff;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBAAC.s")
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
yDiff = Camera_fabsf(camera->focalActorPosRot.pos.y - camera->playerFloorHeight);
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBAD4.s")
phi_v0 = false;
if (yDiff < 11.0f) {
phi_v0 = true;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBB58.s")
ret = phi_v0;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBB88.s")
if (!ret) {
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBC00.s")
ret = false;
#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBC30.s")
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;
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->meleeWeaponState;
} else {
return 0;
}
}
s32 Camera_GetFocalActorPos(Vec3f* dst, Camera* camera) {
PosRot focalPosRot;
Actor* focalActor = camera->focalActor;
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;
}
}
s32 Camera_IsUnderwaterAsZora(Camera* camera) {
Actor* focalActor = camera->focalActor;
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->currentBoots == PLAYER_BOOTS_ZORA_UNDERWATER;
} else {
return 0;
}
}
/**
* Evaluate if player is in one of two sword animations
*/
s32 func_800CBB88(Camera* camera) {
Actor* focalActor = camera->focalActor;
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
if ((((Player*)focalActor)->meleeWeaponState != 0) &&
(((Player*)focalActor)->meleeWeaponAnimation == PLAYER_MWA_GORON_PUNCH_BUTT)) {
return 3;
}
if ((((Player*)focalActor)->stateFlags2 & PLAYER_STATE2_20000) ||
((((Player*)focalActor)->meleeWeaponState != 0) &&
(((Player*)focalActor)->meleeWeaponAnimation == PLAYER_MWA_ZORA_PUNCH_KICK))) {
return 1;
}
}
return 0;
}
s32 Camera_IsUsingZoraFins(Camera* camera) {
Actor* focalActor = camera->focalActor;
if (camera->focalActor == &GET_PLAYER(camera->play)->actor) {
return ((Player*)focalActor)->stateFlags1 & PLAYER_STATE1_200000;
} else {
return 0;
}
}
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")