Refine analog camera implementation, hook up camera inversion to analog camera

This commit is contained in:
Mr-Wiseguy 2024-05-25 13:48:14 -04:00
parent e30e85ea52
commit db0526ca5c
5 changed files with 662 additions and 34 deletions

View file

@ -2,9 +2,11 @@
#include "input.h"
#include "z64quake.h"
#include "play_patches.h"
#include "camera_patches.h"
static bool was_in_analog_cam = false;
static bool is_in_analog_cam = false;
static bool prev_analog_cam_active = false;
static bool can_use_analog_cam = false;
static bool analog_cam_active = false;
VecGeo analog_camera_pos = { .r = 66.0f, .pitch = 0, .yaw = 0 };
@ -16,24 +18,63 @@ float analog_camera_x_sensitivity = 1500.0f;
float analog_camera_y_sensitivity = 500.0f;
// float analog_camera_acceleration = 500.0f;
static const float analog_cam_threshold = 0.1f;
void update_analog_camera_params(Camera* camera) {
analog_camera_pos.yaw = Math_Atan2S(-camera->at.x + camera->eye.x, -camera->at.z + camera->eye.z);
// recomp_printf("Camera at: %.2f %.2f %.2f\n"
// " eye: %.2f %.2f %.2f\n"
// " yaw: %d",
// camera->at.x, camera->at.y, camera->at.z,
// camera->eye.x, camera->eye.y, camera->eye.z,
// analog_camera_pos.yaw);
// Check if the analog camera was usable in this frame.
if (!can_use_analog_cam) {
// It wasn't, so mark the analog cam as being off for this frame.
analog_cam_active = false;
}
prev_analog_cam_active = analog_cam_active;
if (!analog_cam_active) {
recomp_printf("Analog cam not active\n");
analog_camera_pos.yaw = Math_Atan2S(-camera->at.x + camera->eye.x, -camera->at.z + camera->eye.z);
}
}
if (was_in_analog_cam) {
float input_x, input_y;
recomp_get_camera_inputs(&input_x, &input_y);
void update_analog_cam(Camera* c) {
can_use_analog_cam = true;
float input_x, input_y;
recomp_get_camera_inputs(&input_x, &input_y);
analog_camera_yaw_vel = input_x * analog_camera_x_sensitivity;
analog_camera_pitch_vel = input_y * analog_camera_y_sensitivity;
if (fabsf(input_x) >= analog_cam_threshold || fabsf(input_y) >= analog_cam_threshold) {
analog_cam_active = true;
}
if (analog_cam_active) {
s32 inverted_x, inverted_y;
recomp_get_inverted_axes(&inverted_x, &inverted_y);
if (inverted_x) {
input_x = -input_x;
}
if (inverted_y) {
input_y = -input_y;
}
analog_camera_yaw_vel = -input_x * analog_camera_x_sensitivity;
analog_camera_pitch_vel = -input_y * analog_camera_y_sensitivity;
analog_camera_pos.pitch += analog_camera_pitch_vel;
analog_camera_pos.yaw += analog_camera_yaw_vel;
if (analog_camera_pos.pitch > 0x36B0) {
analog_camera_pos.pitch = 0x36B0;
}
// -76.9 degrees
if (analog_camera_pos.pitch < -0x36B0) {
analog_camera_pos.pitch = -0x36B0;
}
}
}
@ -58,8 +99,20 @@ typedef struct {
} CameraSetting;
extern CameraSetting sCameraSettings[];
s32 Camera_GetFocalActorPos(Vec3f* dst, Camera* camera);
f32 Camera_GetFocalActorHeight(Camera* camera);
f32 Camera_Vec3fMagnitude(Vec3f* vec);
f32 Camera_GetFloorY(Camera* camera, Vec3f* pos);
f32 Camera_GetFloorYNorm(Camera* camera, Vec3f* floorNorm, Vec3f* chkPos, s32* bgId);
s16 Camera_ScaledStepToFloorS(s16 target, s16 cur, f32 stepScale, s16 minDiff);
s32 func_800CBC84(Camera* camera, Vec3f* from, CameraCollision* to, s32 arg3);
void func_800CBFA4(Camera* camera, Vec3f* arg1, Vec3f* arg2, s32 arg3);
s32 Camera_CalcAtForParallel(Camera* camera, VecGeo* arg1, f32 yOffset, f32 xzOffsetMax, f32* focalActorPosY,
s16 flags);
Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId);
s32 Camera_IsClimbingLedge(Camera* camera);
void Camera_ScaledStepToCeilVec3f(Vec3f* target, Vec3f* cur, f32 xzStepScale, f32 yStepScale, f32 minDiff);
void Camera_SetFocalActorAtOffset(Camera* camera, Vec3f* focalActorPos);
#if 0
static s32 sIsFalse = false;
@ -267,9 +320,6 @@ Vec3s Camera_Update(Camera* camera) {
// Call the camera update function
sCameraUpdateHandlers[sCameraSettings[camera->setting].cameraModes[camera->mode].funcId](camera);
// @recomp
update_analog_camera_params(camera);
// Update the interface
if (sCameraInitSceneTimer != 0) {
sCameraInitSceneTimer--;
@ -375,6 +425,7 @@ s32 func_800CBA7C(Camera* camera);
#define GET_NEXT_RO_DATA(values) ((values++)->val)
#define RELOAD_PARAMS(camera) ((camera->animState == 0) || (camera->animState == 10) || (camera->animState == 20))
// @recomp Patched for analog cam.
s32 Camera_Normal1(Camera* camera) {
Vec3f* eye = &camera->eye;
Vec3f* at = &camera->at;
@ -685,14 +736,6 @@ s32 Camera_Normal1(Camera* camera) {
}
}
// @recomp
if (recomp_analog_cam_enabled()) {
is_in_analog_cam = true;
spB4.pitch = analog_camera_pos.pitch;
// spB4.r = analog_camera_pos.r;
spB4.yaw = analog_camera_pos.yaw;
}
// 76.9 degrees
if (spB4.pitch > 0x36B0) {
spB4.pitch = 0x36B0;
@ -703,8 +746,16 @@ s32 Camera_Normal1(Camera* camera) {
spB4.pitch = -0x36B0;
}
// @recomp
analog_camera_pos.pitch = spB4.pitch;
// @recomp Update the analog camera.
if (recomp_analog_cam_enabled()) {
update_analog_cam(camera);
if (analog_cam_active) {
spB4.pitch = analog_camera_pos.pitch;
// spB4.r = analog_camera_pos.r;
spB4.yaw = analog_camera_pos.yaw;
}
}
*eyeNext = OLib_AddVecGeoToVec3f(at, &spB4);
@ -779,13 +830,577 @@ s32 Camera_Normal1(Camera* camera) {
return true;
}
/**
* Camera for climbing structures
*/
// @recomp Patched for analog cam.
s32 Camera_Jump2(Camera* camera) {
Vec3f* eye = &camera->eye;
Vec3f* at = &camera->at;
Vec3f* eyeNext = &camera->eyeNext;
Vec3f spC8;
Vec3f spBC;
VecGeo spB4;
VecGeo spAC;
VecGeo spA4;
VecGeo sp9C;
s16 temp_t2;
s16 yawDiff;
s32 pad;
f32 sp90;
f32 sp8C;
s32 sp88;
CameraCollision sp60;
PosRot* focalActorPosRot = &camera->focalActorPosRot;
Jump2ReadOnlyData* roData = &camera->paramData.jump2.roData;
Jump2ReadWriteData* rwData = &camera->paramData.jump2.rwData;
f32 phi_f2;
f32 yNormal; // used twice
f32 focalActorHeight = Camera_GetFocalActorHeight(camera);
f32 temp_f16;
if (RELOAD_PARAMS(camera)) {
CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values;
yNormal = 0.8f - (-0.2f * (68.0f / focalActorHeight));
if (camera->unk_0F0.y > 0.0f) {
phi_f2 = -10.0f;
} else {
phi_f2 = 10.0f;
}
roData->unk_00 = CAM_RODATA_UNSCALE(phi_f2 + GET_NEXT_RO_DATA(values)) * focalActorHeight * yNormal;
roData->unk_04 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * yNormal;
roData->unk_08 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * yNormal;
roData->unk_0C = GET_NEXT_SCALED_RO_DATA(values);
roData->unk_10 = GET_NEXT_RO_DATA(values);
roData->unk_14 = GET_NEXT_SCALED_RO_DATA(values);
roData->unk_18 = GET_NEXT_RO_DATA(values);
roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values);
roData->interfaceFlags = GET_NEXT_RO_DATA(values);
}
sp9C = OLib_Vec3fDiffToVecGeo(at, eye);
spA4 = OLib_Vec3fDiffToVecGeo(at, eyeNext);
sCameraInterfaceFlags = roData->interfaceFlags;
if (RELOAD_PARAMS(camera)) {
spC8 = focalActorPosRot->pos;
rwData->unk_00 = Camera_GetFloorY(camera, &spC8);
rwData->unk_04 = spA4.yaw;
rwData->unk_06 = 0;
if (rwData->unk_00 == BGCHECK_Y_MIN) {
rwData->unk_0A = -1;
rwData->unk_00 = focalActorPosRot->pos.y - 1000.0f;
} else if ((focalActorPosRot->pos.y - rwData->unk_00) < focalActorHeight) {
rwData->unk_0A = 1;
} else {
rwData->unk_0A = -1;
}
yawDiff = BINANG_SUB(BINANG_ROT180(focalActorPosRot->rot.y), spA4.yaw);
rwData->unk_06 = ((yawDiff / 6) / 4) * 3;
if (roData->interfaceFlags & JUMP2_FLAG_1) {
rwData->unk_08 = 10;
} else {
rwData->unk_08 = 10000;
}
focalActorPosRot->pos.x -= camera->unk_0F0.x;
focalActorPosRot->pos.y -= camera->unk_0F0.y;
focalActorPosRot->pos.z -= camera->unk_0F0.z;
rwData->timer = 6;
camera->animState++;
camera->atLerpStepScale = roData->unk_1C;
}
sp90 = camera->speedRatio * 0.5f;
sp8C = camera->speedRatio * 0.2f;
camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(roData->unk_10, camera->yawUpdateRateInv, sp90, 0.1f);
camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(roData->unk_14, camera->yOffsetUpdateRate, sp90, 0.0001f);
camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, sp8C, 0.0001f);
camera->fovUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->fovUpdateRate, camera->speedRatio * .05f, 0.0001f);
camera->rUpdateRateInv = 1800.0f;
Camera_CalcAtDefault(camera, &spA4, roData->unk_00, 0);
spB4 = OLib_Vec3fDiffToVecGeo(at, eye);
//! FAKE: Unused
yNormal = roData->unk_04;
phi_f2 = roData->unk_08 + (roData->unk_08 * roData->unk_0C);
temp_f16 = roData->unk_04 - (roData->unk_04 * roData->unk_0C);
if (spB4.r > phi_f2) {
spB4.r = phi_f2;
} else if (spB4.r < temp_f16) {
spB4.r = temp_f16;
}
yawDiff = BINANG_SUB(BINANG_ROT180(focalActorPosRot->rot.y), spB4.yaw);
if (rwData->timer != 0) {
rwData->unk_04 = BINANG_ROT180(focalActorPosRot->rot.y);
rwData->timer--;
spB4.yaw = Camera_ScaledStepToCeilS(rwData->unk_04, spA4.yaw, 0.5f, 5);
} else if (rwData->unk_08 < ABS(yawDiff)) {
temp_t2 = BINANG_ROT180(focalActorPosRot->rot.y);
spB4.yaw = Camera_ScaledStepToFloorS((yawDiff < 0) ? (temp_t2 + rwData->unk_08) : (temp_t2 - rwData->unk_08),
spA4.yaw, 0.1f, 1);
} else {
spB4.yaw = Camera_ScaledStepToCeilS(spB4.yaw, spA4.yaw, 0.25f, 5);
}
spC8.x = focalActorPosRot->pos.x + (Math_SinS(focalActorPosRot->rot.y) * 25.0f);
spC8.y = focalActorPosRot->pos.y + (focalActorHeight * 2.2f);
spC8.z = focalActorPosRot->pos.z + (Math_CosS(focalActorPosRot->rot.y) * 25.0f);
yNormal = Camera_GetFloorYNorm(camera, &spBC, &spC8, &sp88);
if (camera->focalActor->bgCheckFlags & 0x10) {
camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f);
camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.2f, 0.1f);
spB4.pitch = Camera_ScaledStepToCeilS(-DEG_TO_BINANG(27.47f), spA4.pitch, 0.2f, 5);
} else if ((yNormal != BGCHECK_Y_MIN) && (focalActorPosRot->pos.y < yNormal)) {
camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f);
camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.2f, 0.1f);
if (camera->unk_0F0.y > 1.0f) {
spB4.pitch = Camera_ScaledStepToCeilS(0x1F4, spA4.pitch, 1.0f / camera->pitchUpdateRateInv, 5);
}
} else if ((focalActorPosRot->pos.y - rwData->unk_00) < focalActorHeight) {
camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f);
camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.2f, 0.1f);
if (camera->unk_0F0.y > 1.0f) {
spB4.pitch = Camera_ScaledStepToCeilS(0x1F4, spA4.pitch, 1.0f / camera->pitchUpdateRateInv, 5);
}
} else {
camera->pitchUpdateRateInv = 100.0f;
camera->rUpdateRateInv = 100.0f;
}
// @recomp
if (recomp_analog_cam_enabled()) {
update_analog_cam(camera);
if (analog_cam_active) {
spB4.pitch = analog_camera_pos.pitch;
// spB4.r = analog_camera_pos.r;
spB4.yaw = analog_camera_pos.yaw;
}
}
spB4.pitch = CLAMP_MAX(spB4.pitch, DEG_TO_BINANG(60.43f));
spB4.pitch = CLAMP_MIN(spB4.pitch, -DEG_TO_BINANG(60.43f));
// @recomp Update the analog camera.
if (recomp_analog_cam_enabled()) {
update_analog_cam(camera);
if (analog_cam_active) {
spB4.pitch = analog_camera_pos.pitch;
// spB4.r = analog_camera_pos.r;
spB4.yaw = analog_camera_pos.yaw;
}
}
*eyeNext = OLib_AddVecGeoToVec3f(at, &spB4);
sp60.pos = *eyeNext;
if (func_800CBC84(camera, at, &sp60, 0) != 0) {
spC8 = sp60.pos;
spAC.pitch = 0;
spAC.r = spB4.r;
spAC.yaw = spB4.yaw;
sp60.pos = OLib_AddVecGeoToVec3f(at, &spAC);
if (func_800CBC84(camera, at, &sp60, 0) != 0) {
*eye = spC8;
} else {
spB4.pitch = Camera_ScaledStepToCeilS(0, spB4.pitch, 0.2f, 5);
*eye = OLib_AddVecGeoToVec3f(at, &spB4);
func_800CBFA4(camera, at, eye, 0);
}
} else {
*eye = *eyeNext;
}
camera->dist = spB4.r;
camera->fov = Camera_ScaledStepToCeilF(roData->unk_18, camera->fov, camera->fovUpdateRate, 0.1f);
camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5);
return true;
}
/**
* Used for targeting
*/
// @recomp Patched for analog cam.
s32 Camera_Parallel1(Camera* camera) {
Vec3f* eye = &camera->eye;
Vec3f* at = &camera->at;
Vec3f* eyeNext = &camera->eyeNext;
Vec3f spB0;
Vec3f spA4;
f32 spA0;
f32 sp9C;
PosRot* focalActorPosRot = &camera->focalActorPosRot;
VecGeo sp90;
VecGeo sp88;
VecGeo sp80;
VecGeo sp78;
BgCamFuncData* bgCamFuncData;
s16 sp72;
s16 tangle;
Parallel1ReadOnlyData* roData = &camera->paramData.para1.roData;
Parallel1ReadWriteData* rwData = &camera->paramData.para1.rwData;
s32 parallelFlagCond;
f32 focalActorHeight = Camera_GetFocalActorHeight(camera);
s16 new_var2;
s16 phi_a0;
s32 phi_a0_2;
CameraModeValue* values;
f32 yNormal;
if (!RELOAD_PARAMS(camera)) {
} else {
values = sCameraSettings[camera->setting].cameraModes[camera->mode].values;
roData->unk_00 =
GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f));
roData->unk_04 =
GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f));
roData->unk_08 =
GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f));
roData->unk_20 = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values));
roData->unk_22 = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values));
roData->unk_0C = GET_NEXT_RO_DATA(values);
roData->unk_10 = GET_NEXT_RO_DATA(values);
roData->unk_14 = GET_NEXT_RO_DATA(values);
roData->unk_18 = GET_NEXT_SCALED_RO_DATA(values);
roData->interfaceFlags = GET_NEXT_RO_DATA(values);
roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values);
roData->unk_24 = GET_NEXT_RO_DATA(values);
rwData->unk_00 = roData->unk_04;
}
sp80 = OLib_Vec3fDiffToVecGeo(at, eye);
sp78 = OLib_Vec3fDiffToVecGeo(at, eyeNext);
Camera_GetFocalActorPos(&spA4, camera);
switch (camera->animState) {
case 20:
if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == 0) {
Camera_SetUpdateRatesFastYaw(camera);
}
// fallthrough
case 0:
case 10:
if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) {
rwData->unk_10 = focalActorPosRot->pos;
} else {
camera->xzOffsetUpdateRate = 0.5f;
camera->yOffsetUpdateRate = 0.5f;
}
if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
PARALLEL1_FLAG_3) {
rwData->unk_10 = camera->focalActorPosRot.pos;
}
rwData->timer1 = 200.0f;
if ((2.0f * roData->unk_04) < camera->dist) {
camera->dist = 2.0f * roData->unk_04;
sp78.r = camera->dist;
sp80.r = sp78.r;
*eye = OLib_AddVecGeoToVec3f(at, &sp80);
*eyeNext = *eye;
}
rwData->unk_1C = 0;
if (roData->interfaceFlags & PARALLEL1_FLAG_2) {
rwData->timer2 = 20;
} else {
rwData->timer2 = 6;
}
if ((camera->focalActor == &GET_PLAYER(camera->play)->actor) && (camera->mode == CAM_MODE_CHARGE)) {
rwData->timer2 = 30;
if (((Player*)camera->focalActor)->transformation == PLAYER_FORM_DEKU) {
roData->unk_24 = -1;
}
}
if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_3 | PARALLEL1_FLAG_1)) {
rwData->timer2 = 1;
yNormal = 0.8f - ((68.0f / focalActorHeight) * -0.2f);
bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex);
rwData->unk_20 = bgCamFuncData->rot.x;
rwData->unk_1E = bgCamFuncData->rot.y;
rwData->unk_08 = (bgCamFuncData->fov == -1) ? roData->unk_14
: (bgCamFuncData->fov > 360) ? CAM_RODATA_UNSCALE(bgCamFuncData->fov)
: bgCamFuncData->fov;
rwData->unk_00 = (bgCamFuncData->unk_0E == -1)
? roData->unk_04
: CAM_RODATA_UNSCALE(bgCamFuncData->unk_0E) * focalActorHeight * yNormal;
//! FAKE
dummy:;
} else {
rwData->unk_08 = roData->unk_14;
rwData->unk_00 = roData->unk_04;
}
rwData->timer3 = roData->unk_24;
rwData->unk_04 = focalActorPosRot->pos.y - camera->unk_0F0.y;
rwData->unk_26 = 1;
camera->animState = 1;
sCameraInterfaceFlags = roData->interfaceFlags;
break;
}
if (rwData->timer2 != 0) {
switch (roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) {
case PARALLEL1_FLAG_1:
case (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1):
rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22;
rwData->unk_20 = roData->unk_20;
break;
case PARALLEL1_FLAG_2:
rwData->unk_1E = roData->unk_22;
rwData->unk_20 = roData->unk_20;
break;
case (PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1):
if (rwData->timer3 == 1) {
sp88 = OLib_Vec3fDiffToVecGeo(&rwData->unk_10, &spA4);
rwData->unk_1E = ((ABS(BINANG_SUB(sp88.yaw, sp80.yaw)) < 0x3A98) || Camera_IsClimbingLedge(camera))
? sp80.yaw
: sp80.yaw + (s16)((BINANG_SUB(sp88.yaw, sp80.yaw) >> 2) * 3);
}
rwData->unk_20 = roData->unk_20;
break;
case PARALLEL1_FLAG_3:
rwData->unk_1E = sp80.yaw;
rwData->unk_20 = roData->unk_20;
break;
case (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_1):
break;
default:
rwData->unk_1E = sp78.yaw + roData->unk_22;
rwData->unk_20 = roData->unk_20;
break;
}
} else if (roData->interfaceFlags & PARALLEL1_FLAG_5) {
rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22;
}
if (camera->animState == 21) {
camera->animState = 1;
} else if (camera->animState == 11) {
camera->animState = 1;
}
spA0 = camera->speedRatio * 0.5f;
sp9C = camera->speedRatio * 0.2f;
if (((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ||
((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == PARALLEL1_FLAG_3) ||
(roData->interfaceFlags & PARALLEL1_FLAG_5)) {
camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.5f, 0.1f);
camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(roData->unk_0C, camera->yawUpdateRateInv, 0.5f, 0.1f);
camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f);
} else {
camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, spA0, 0.1f);
camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(roData->unk_0C, camera->yawUpdateRateInv, spA0, 0.1f);
camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(2.0f, camera->pitchUpdateRateInv, sp9C, 0.1f);
}
if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) {
camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.1f, camera->yOffsetUpdateRate, spA0, 0.0001f);
camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.1f, camera->xzOffsetUpdateRate, sp9C, 0.0001f);
} else if (roData->interfaceFlags & PARALLEL1_FLAG_7) {
camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.5f, camera->yOffsetUpdateRate, spA0, 0.0001f);
camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.5f, camera->xzOffsetUpdateRate, sp9C, 0.0001f);
} else {
camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->yOffsetUpdateRate, spA0, 0.0001f);
camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, sp9C, 0.0001f);
}
// TODO: Extra trailing 0 in 0.050f needed?
camera->fovUpdateRate =
Camera_ScaledStepToCeilF(0.050f, camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.0001f);
if (roData->interfaceFlags & PARALLEL1_FLAG_0) {
tangle = Camera_GetPitchAdjFromFloorHeightDiffs(camera, BINANG_ROT180(sp80.yaw), rwData->unk_26 = 1);
spA0 = ((1.0f / roData->unk_10));
spA0 *= 0.6f;
sp9C = ((1.0f / roData->unk_10) * 0.4f) * (1.0f - camera->speedRatio);
rwData->unk_1C = Camera_ScaledStepToCeilS(tangle, rwData->unk_1C, spA0 + sp9C, 5);
} else {
rwData->unk_1C = 0;
}
if (func_800CB950(camera) || (((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_1000) ||
(((Player*)camera->focalActor)->stateFlags3 & PLAYER_STATE3_100)) {
rwData->unk_04 = camera->focalActorPosRot.pos.y;
sp72 = false;
} else {
sp72 = true;
}
if ((((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4000) ||
(((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4) ||
((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1))) {
spB0 = spA4;
spB0.y += ((focalActorHeight * 0.6f) + roData->unk_00);
Camera_ScaledStepToCeilVec3f(&spB0, at, camera->xzOffsetUpdateRate, camera->yOffsetUpdateRate, 0.0001f);
Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos);
} else if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) {
spB0 = focalActorPosRot->pos;
spB0.y += focalActorHeight + roData->unk_00;
Camera_ScaledStepToCeilVec3f(&spB0, at, camera->xzOffsetUpdateRate, camera->yOffsetUpdateRate, 0.0001f);
Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos);
} else if (rwData->timer2 != 0) {
Camera_CalcAtDefault(camera, &sp78, roData->unk_00, 0);
rwData->timer1 = 200.0f;
} else if (!(roData->interfaceFlags & PARALLEL1_FLAG_7) && !sp72) {
Camera_CalcAtForParallel(camera, &sp78, roData->unk_00, roData->unk_08, &rwData->unk_04,
roData->interfaceFlags & (PARALLEL1_FLAG_6 | PARALLEL1_FLAG_0));
rwData->timer1 = 200.0f;
} else {
Camera_CalcAtForScreen(camera, &sp78, roData->unk_00, &rwData->unk_04, rwData->timer1);
if (rwData->timer1 > 10.0f) {
rwData->timer1--;
}
}
camera->dist = Camera_ScaledStepToCeilF(rwData->unk_00, camera->dist, 1.0f / camera->rUpdateRateInv, 0.1f);
if (rwData->timer2 != 0) {
if (rwData->timer3 <= 0) {
if (rwData->timer3 == 0) {
Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE);
}
tangle = ((rwData->timer2 + 1) * rwData->timer2) >> 1;
sp90.yaw = sp80.yaw + ((BINANG_SUB(rwData->unk_1E, sp80.yaw) / tangle) * rwData->timer2);
phi_a0 = ((roData->interfaceFlags & PARALLEL1_FLAG_0) ? BINANG_SUB(rwData->unk_20, rwData->unk_1C)
: rwData->unk_20);
new_var2 = BINANG_SUB(phi_a0, sp80.pitch);
sp90.pitch = sp80.pitch + ((new_var2 / tangle) * rwData->timer2);
sp90.r = camera->dist;
rwData->timer2--;
} else {
sp90 = sp80;
sp90.r = camera->dist;
}
} else {
sp90 = OLib_Vec3fDiffToVecGeo(at, eyeNext);
sp90.r = camera->dist;
if (roData->interfaceFlags & PARALLEL1_FLAG_1) {
sp90.yaw = Camera_ScaledStepToCeilS(rwData->unk_1E, sp78.yaw, 1.0f / camera->yawUpdateRateInv, 0xC8);
}
parallelFlagCond = (roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1));
if (roData->interfaceFlags & PARALLEL1_FLAG_0) {
phi_a0 = (rwData->unk_20 - rwData->unk_1C);
} else {
phi_a0 = rwData->unk_20;
}
if (parallelFlagCond == (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) {
spA0 = CLAMP_MAX(camera->speedRatio, 1.0f);
phi_a0 = (sp90.pitch * spA0) + (phi_a0 * (1.0f - spA0));
sp90.pitch = Camera_ScaledStepToCeilS(phi_a0, sp78.pitch, 1.0f / camera->pitchUpdateRateInv, 5);
} else if (parallelFlagCond != PARALLEL1_FLAG_3) {
sp90.pitch = Camera_ScaledStepToCeilS(phi_a0, sp78.pitch, 1.0f / camera->pitchUpdateRateInv, 5);
}
if (sp90.pitch > DEG_TO_BINANG(79.655f)) {
sp90.pitch = DEG_TO_BINANG(79.655f);
}
if (sp90.pitch < -DEG_TO_BINANG(29.995f)) {
sp90.pitch = -DEG_TO_BINANG(29.995f);
}
}
if (rwData->timer3 > 0) {
rwData->timer3--;
}
// @recomp Update the analog camera.
if (recomp_analog_cam_enabled()) {
update_analog_cam(camera);
if (analog_cam_active) {
sp90.pitch = analog_camera_pos.pitch;
// sp90.r = analog_camera_pos.r;
sp90.yaw = analog_camera_pos.yaw;
}
}
*eyeNext = OLib_AddVecGeoToVec3f(at, &sp90);
if (camera->status == CAM_STATUS_ACTIVE) {
if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & PARALLEL1_FLAG_4)) {
spB0 = *at;
if ((((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4000) ||
(((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4) ||
((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) ==
(PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1))) {
spB0.y += focalActorHeight;
}
*eye = *eyeNext;
func_800CBFA4(camera, &spB0, eye, 0);
} else {
*eye = *eyeNext;
func_800CBFA4(camera, at, eye, 3);
}
if (rwData->timer2 != 0) {
sUpdateCameraDirection = true;
} else {
sUpdateCameraDirection = false;
}
}
camera->fov = Camera_ScaledStepToCeilF(rwData->unk_08, camera->fov, camera->fovUpdateRate, 0.1f);
camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5);
camera->atLerpStepScale = Camera_ClampLerpScale(camera, sp72 ? roData->unk_1C : roData->unk_18);
rwData->unk_26 &= ~1;
return 1;
}
void analog_cam_pre_play_update(PlayState* play) {
Camera *active_cam = play->cameraPtrs[play->activeCamId];
update_analog_camera_params(active_cam);
}
void analog_cam_post_play_update(PlayState* play) {
// recomp_printf("was_in_analog_cam: %d is_in_analog_cam: %d\n", was_in_analog_cam, is_in_analog_cam);
was_in_analog_cam = is_in_analog_cam;
is_in_analog_cam = false;
Camera *active_cam = play->cameraPtrs[play->activeCamId];
// recomp_printf("prev_analog_cam_active: %d can_use_analog_cam: %d\n", prev_analog_cam_active, can_use_analog_cam);
recomp_printf("setting: %d mode: %d func: %d\n", active_cam->setting, active_cam->mode, sCameraSettings[active_cam->setting].cameraModes[active_cam->mode].funcId);
// Update parameters for the analog cam.
update_analog_camera_params(active_cam);
can_use_analog_cam = false;
}

15
patches/camera_patches.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef __CAMERA_PATCHES_H__
#define __CAMERA_PATCHES_H__
#include "z64camera.h"
#define RELOAD_PARAMS(camera) ((camera->animState == 0) || (camera->animState == 10) || (camera->animState == 20))
#define CAM_RODATA_SCALE(x) ((x)*100.0f)
#define CAM_RODATA_UNSCALE(x) ((x)*0.01f)
// Load the next value from camera read-only data stored in CameraModeValue
#define GET_NEXT_RO_DATA(values) ((values++)->val)
// Load the next value and scale down from camera read-only data stored in CameraModeValue
#define GET_NEXT_SCALED_RO_DATA(values) CAM_RODATA_UNSCALE(GET_NEXT_RO_DATA(values))
#endif

View file

@ -1,4 +1,5 @@
#include "patches.h"
#include "camera_patches.h"
#include "transform_ids.h"
#include "z64cutscene.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
@ -286,11 +287,6 @@ void Camera_ScaledStepToCeilVec3f(Vec3f* target, Vec3f* cur, f32 xzStepScale, f3
void Camera_SetFocalActorAtOffset(Camera* camera, Vec3f* focalActorPos);
void Camera_SetUpdateRatesSlow(Camera* camera);
Vec3f Camera_Vec3sToVec3f(Vec3s* src);
#define RELOAD_PARAMS(camera) ((camera->animState == 0) || (camera->animState == 10) || (camera->animState == 20))
#define CAM_RODATA_SCALE(x) ((x)*100.0f)
#define CAM_RODATA_UNSCALE(x) ((x)*0.01f)
#define GET_NEXT_RO_DATA(values) ((values++)->val)
#define GET_NEXT_SCALED_RO_DATA(values) CAM_RODATA_UNSCALE(GET_NEXT_RO_DATA(values))
/**
* Used for many fixed-based camera settings i.e. camera is fixed in rotation, and often position (but not always)

View file

@ -55,5 +55,6 @@ osInvalICache_recomp = 0x8F000094;
recomp_analog_cam_enabled = 0x8F000098;
recomp_get_camera_inputs = 0x8F00009C;
recomp_set_right_analog_suppressed = 0x8F0000A0;
recomp_get_inverted_axes = 0x8F0000A4;
recomp_high_precision_fb_enabled = 0x8F0000A8;
recomp_get_resolution_scale = 0x8F0000AC;

View file

@ -115,9 +115,10 @@ extern "C" void recomp_get_inverted_axes(uint8_t* rdram, recomp_context* ctx) {
s32* x_out = _arg<0, s32*>(rdram, ctx);
s32* y_out = _arg<1, s32*>(rdram, ctx);
// TODO implement this
*x_out = 0;
*y_out = 1;
recomp::CameraInvertMode mode = recomp::get_camera_invert_mode();
*x_out = (mode == recomp::CameraInvertMode::InvertX || mode == recomp::CameraInvertMode::InvertBoth);
*y_out = (mode == recomp::CameraInvertMode::InvertY || mode == recomp::CameraInvertMode::InvertBoth);
}
extern "C" void recomp_analog_cam_enabled(uint8_t* rdram, recomp_context* ctx) {