Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
camera: fix Camera_Update
Browse files Browse the repository at this point in the history
Resolves #4.

The bug was introduced by replacing a bit-shift operation with an
integer division. I thought these operations are interchangeable, but
turns out they're not:

(-1) / 2    = 0
(-1) >> 1  = -1
  • Loading branch information
rr- committed Nov 3, 2023
1 parent 2828b2d commit a3ff248
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 39 deletions.
26 changes: 13 additions & 13 deletions docs/progress.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,7 @@ typedef enum LARA_MESH {
00410650 00000372 + void __cdecl Camera_Move(const struct GAME_VECTOR *target, int32_t speed);
004109D0 000000D7 + void __cdecl Camera_Clip(int32_t *x, int32_t *y, int32_t *h, int32_t target_x, int32_t target_y, int32_t target_h, int32_t left, int32_t top, int32_t right, int32_t bottom);
00410AB0 00000154 + void __cdecl Camera_Shift(int32_t *x, int32_t *y, int32_t *h, int32_t target_x, int32_t target_y, int32_t target_h, int32_t left, int32_t top, int32_t right, int32_t bottom);
00410C10 00000050 + const struct FLOOR_INFO __cdecl *Camera_GoodPosition(int32_t x, int32_t y, int32_t z, int16_t room_num);
00410C10 00000050 + const struct FLOOR_INFO *__cdecl Camera_GoodPosition(int32_t x, int32_t y, int32_t z, int16_t room_num);
00410C60 00000781 + void __cdecl Camera_SmartShift(struct GAME_VECTOR *target, void (*__cdecl shift)(int32_t *x, int32_t *y, int32_t *h, int32_t target_x, int32_t target_y, int32_t target_h, int32_t left, int32_t top, int32_t right, int32_t bottom));
004113F0 000000ED + void __cdecl Camera_Chase(const struct ITEM_INFO *item);
004114E0 0000019E + int32_t __cdecl Camera_ShiftClamp(struct GAME_VECTOR *pos, int32_t clamp);
Expand Down Expand Up @@ -1331,7 +1331,7 @@ typedef enum LARA_MESH {
004146F0 00000338 - void __cdecl Item_Animate(struct ITEM_INFO *item);
00414A60 000000AB - int32_t __cdecl Item_GetAnimChange(struct ITEM_INFO *item, struct ANIM_STRUCT *anim);
00414B10 0000005F - void __cdecl Item_Translate(struct ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
00414B70 00000198 * struct FLOOR_INFO __cdecl *Room_GetFloor(int32_t x, int32_t y, int32_t z, int16_t *room_num);
00414B70 00000198 * struct FLOOR_INFO *__cdecl Room_GetFloor(int32_t x, int32_t y, int32_t z, int16_t *room_num);
00414D10 00000168 - int32_t __cdecl Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
00414E80 00000265 * int32_t __cdecl Room_GetHeight(const struct FLOOR_INFO *floor, int32_t x, int32_t y, int32_t z);
00415100 000000E7 - void __cdecl Camera_RefreshFromTrigger(int16_t type, int16_t *data);
Expand Down Expand Up @@ -2452,11 +2452,11 @@ typedef enum LARA_MESH {
# Offset Flags Declaration

00464060 - int32_t g_PerspectiveDistance;
00464068 - void (__cdecl *g_PolyDrawRoutines[9])(const int16_t *);
00464068 - void (*__cdecl g_PolyDrawRoutines[9])(const int16_t *);
0046408C - float g_RhwFactor;
004640BC - int16_t g_CD_TrackID;
004640C4 - int32_t g_FlipEffect;
004641F8 - void (__cdecl *g_EffectRoutines[32])(struct ITEM_INFO *item);
004641F8 - void (*__cdecl g_EffectRoutines[32])(struct ITEM_INFO *item);
00465A60 - int16_t g_OptionMusicVolume;
00465AD4 - int32_t g_JumpPermitted = 1;
00465AD8 - int16_t g_LaraOldSlideAngle = 1;
Expand All @@ -2473,12 +2473,12 @@ typedef enum LARA_MESH {
0047031C - float g_FltWinBottom;
00470320 - float g_FltResZBuf;
00470324 - float g_FltResZ;
00470328 - void (__cdecl *g_Output_InsertTransQuad)(int32_t x, int32_t y, int32_t width, int32_t height, int32_t z);
00470328 - void (*__cdecl g_Output_InsertTransQuad)(int32_t x, int32_t y, int32_t width, int32_t height, int32_t z);
0047032C - int32_t g_PhdWinHeight;
00470330 - int32_t g_PhdWinCenterX;
00470334 - int32_t g_PhdWinCenterY;
00470338 - int16_t g_LsYaw;
0047033C - void (__cdecl *g_Output_InsertTrans8)(const struct PHD_VBUF *vbuf, int16_t shade);
0047033C - void (*__cdecl g_Output_InsertTrans8)(const struct PHD_VBUF *vbuf, int16_t shade);
00470340 - float g_FltWinTop;
00470348 - struct SORT_ITEM g_SortBuffer[4000];
00478048 - float g_FltWinLeft;
Expand All @@ -2488,7 +2488,7 @@ typedef enum LARA_MESH {
00478060 - int32_t g_PhdWinBottom;
00478064 - int32_t g_PhdPersp;
00478068 - int32_t g_PhdWinLeft;
0047806C - void (__cdecl *g_Output_InsertFlatRect)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t z, uint8_t color_idx);
0047806C - void (*__cdecl g_Output_InsertFlatRect)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t z, uint8_t color_idx);
00478070 - int16_t g_Info3DBuffer[120000];
004B29F0 - int32_t g_PhdWinMaxX;
004B29F4 - int32_t g_PhdNearZ;
Expand All @@ -2502,23 +2502,23 @@ typedef enum LARA_MESH {
004B2A14 - float g_FltPerspONearZ;
004B2A18 - float g_FltRhwONearZ;
004B2A1C - int32_t g_PhdWinMaxY;
004B2A20 - void (__cdecl *g_Output_InsertSprite)(int32_t z, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t sprite_idx, int16_t shade);
004B2A20 - void (*__cdecl g_Output_InsertSprite)(int32_t z, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t sprite_idx, int16_t shade);
004B2A24 - float g_FltNearZ;
004B2A28 - struct MATRIX *g_MatrixPtr;
004B2A2C - const int16_t *(__cdecl *g_Output_DrawObjectGT3)(const int16_t*, int32_t, enum SORT_TYPE);
004B2A30 - const int16_t *(__cdecl *g_Output_DrawObjectGT4)(const int16_t*, int32_t, enum SORT_TYPE);
004B2A2C - const int16_t *(*__cdecl g_Output_DrawObjectGT3)(const int16_t*, int32_t, enum SORT_TYPE);
004B2A30 - const int16_t *(*__cdecl g_Output_DrawObjectGT4)(const int16_t*, int32_t, enum SORT_TYPE);
004B2A38 - int32_t g_RandomTable[32];
004B2AB8 - float g_FltPersp;
004B2AC0 - struct MATRIX g_W2VMatrix;
004B2AF0 - int16_t *g_Info3DPtr;
004B2AF4 - int32_t g_PhdWinWidth;
004B2AF8 - void (__cdecl *g_Output_DrawLine)(int32_t, int32_t, int32_t, int32_t, int32_t, uint8_t);
004B2AF8 - void (*__cdecl g_Output_DrawLine)(int32_t, int32_t, int32_t, int32_t, int32_t, uint8_t);
004B2B00 - struct PHD_TEXTURE g_PhdTextureInfo[0x800];
004BCB00 - int32_t g_PhdViewDistance;
004BCB04 - int16_t g_LsPitch;
004BCB08 - const int16_t *(__cdecl *g_Output_DrawObjectG4)(const int16_t*,int32_t, enum SORT_TYPE);
004BCB08 - const int16_t *(*__cdecl g_Output_DrawObjectG4)(const int16_t*,int32_t, enum SORT_TYPE);
004BCB10 - int16_t g_ShadesTable[32];
004BCB50 - const int16_t *(__cdecl *g_Output_DrawObjectG3)(const int16_t*,int32_t, enum SORT_TYPE);
004BCB50 - const int16_t *(*__cdecl g_Output_DrawObjectG3)(const int16_t*,int32_t, enum SORT_TYPE);
004BCB58 - struct MATRIX g_MatrixStack[];
004BD2D8 - struct DEPTHQ_ENTRY g_DepthQTable[32];
004BF3D8 - int32_t g_PhdScreenWidth;
Expand Down
54 changes: 28 additions & 26 deletions src/game/camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,8 @@ int32_t __cdecl Camera_ShiftClamp(struct GAME_VECTOR *pos, int32_t clamp)
int32_t height = Room_GetHeight(floor, x, y, z) - clamp;
int32_t ceiling = Room_GetCeiling(floor, x, y, z) + clamp;
if (height < ceiling) {
ceiling = height = (height + ceiling) / 2;
ceiling = (height + ceiling) >> 1;
height = ceiling;
}

if (y > height) {
Expand Down Expand Up @@ -669,9 +670,10 @@ void __cdecl Camera_Update(void)
g_IsChunkyCamera = 1;
}

int32_t fixed_camera = g_Camera.item
const int32_t fixed_camera = g_Camera.item != NULL
&& (g_Camera.type == CAM_FIXED || g_Camera.type == CAM_HEAVY);
const struct ITEM_INFO *item = fixed_camera ? g_Camera.item : g_LaraItem;
const struct ITEM_INFO *const item =
fixed_camera ? g_Camera.item : g_LaraItem;

const int16_t *bounds = Item_GetBoundsAccurate(item);

Expand All @@ -680,63 +682,61 @@ void __cdecl Camera_Update(void)
y += (bounds[FBBOX_MIN_Y] + bounds[FBBOX_MAX_Y]) / 2;
} else {
y += bounds[FBBOX_MAX_Y]
+ ((bounds[FBBOX_MIN_Y] - bounds[FBBOX_MAX_Y]) * 3 / 4);
+ (((int32_t)(bounds[FBBOX_MIN_Y] - bounds[FBBOX_MAX_Y])) * 3 >> 2);
}

if (g_Camera.item && !fixed_camera) {
bounds = Item_GetBoundsAccurate(g_Camera.item);

int32_t dz = g_Camera.item->pos.z - item->pos.z;
int32_t dx = g_Camera.item->pos.x - item->pos.x;
int32_t shift = Math_Sqrt(SQUARE(dx) + SQUARE(dz));
const int32_t dx = g_Camera.item->pos.x - item->pos.x;
const int32_t dz = g_Camera.item->pos.z - item->pos.z;
const int32_t shift = Math_Sqrt(SQUARE(dx) + SQUARE(dz));
int16_t angle = Math_Atan(dz, dx) - item->pos.y_rot;

int16_t tilt = Math_Atan(
shift,
y - (bounds[FBBOX_MIN_Y] + bounds[FBBOX_MAX_Y]) / 2
- g_Camera.item->pos.y);
tilt /= 2;
angle /= 2;
angle >>= 1;
tilt >>= 1;

if (angle > MIN_HEAD_ROTATION && angle < MAX_HEAD_ROTATION
&& tilt > MIN_HEAD_TILT_CAM && tilt < MAX_HEAD_TILT_CAM) {
int16_t change = angle - g_Lara.head_y_rot;
if (change > HEAD_TURN) {
g_Lara.head_y_rot += HEAD_TURN;
} else if (change >= -HEAD_TURN) {
g_Lara.head_y_rot = angle;
} else {
} else if (change < -HEAD_TURN) {
g_Lara.head_y_rot -= HEAD_TURN;
} else {
g_Lara.head_y_rot = angle;
}

change = tilt - g_Lara.head_x_rot;
if (change > HEAD_TURN) {
g_Lara.head_x_rot = g_Lara.head_x_rot + HEAD_TURN;
} else if (change >= -HEAD_TURN) {
g_Lara.head_x_rot = change + g_Lara.head_x_rot;
g_Lara.head_x_rot += HEAD_TURN;
} else if (change < -HEAD_TURN) {
g_Lara.head_x_rot -= HEAD_TURN;
} else {
g_Lara.head_x_rot = g_Lara.head_x_rot - HEAD_TURN;
g_Lara.head_x_rot += change;
}

g_Lara.torso_y_rot = g_Lara.head_y_rot;
g_Lara.torso_x_rot = g_Lara.head_x_rot;
g_Lara.torso_y_rot = g_Lara.head_y_rot;
g_Camera.type = CAM_LOOK;
g_Camera.item->looked_at = 1;
}
}

if (g_Camera.type == CAM_LOOK || g_Camera.type == CAM_COMBAT) {
y -= STEP_L;

g_Camera.target.room_num = item->room_num;
if (g_Camera.fixed_camera) {
g_Camera.target.y = y;
g_Camera.speed = 1;
} else {
g_Camera.target.y += (y - g_Camera.target.y) / 4;
g_Camera.target.y += (y - g_Camera.target.y) >> 2;
g_Camera.speed =
g_Camera.type == CAM_LOOK ? LOOK_SPEED : COMBAT_SPEED;
}

g_Camera.fixed_camera = 0;
if (g_Camera.type == CAM_LOOK) {
Camera_Look(item);
Expand All @@ -746,27 +746,29 @@ void __cdecl Camera_Update(void)
} else {
g_Camera.target.x = item->pos.x;
g_Camera.target.z = item->pos.z;

if (g_Camera.flags == CF_FOLLOW_CENTRE) {
int32_t shift = (bounds[FBBOX_MIN_Z] + bounds[FBBOX_MAX_Z]) / 2;
const int32_t shift =
(bounds[FBBOX_MIN_Z] + bounds[FBBOX_MAX_Z]) / 2;
g_Camera.target.z +=
(shift * Math_Cos(item->pos.y_rot)) >> W2V_SHIFT;
g_Camera.target.x +=
(shift * Math_Sin(item->pos.y_rot)) >> W2V_SHIFT;
}
g_Camera.target.room_num = item->room_num;

g_Camera.target.room_num = item->room_num;
if (g_Camera.fixed_camera != fixed_camera) {
g_Camera.target.y = y;
g_Camera.fixed_camera = 1;
g_Camera.speed = 1;
} else {
g_Camera.target.y += (y - g_Camera.target.y) / 4;
g_Camera.fixed_camera = 0;
g_Camera.target.y += (y - g_Camera.target.y) / 4;
}

const struct FLOOR_INFO *floor = Room_GetFloor(
const struct FLOOR_INFO *const floor = Room_GetFloor(
g_Camera.target.x, y, g_Camera.target.z, &g_Camera.target.room_num);
int32_t height = Room_GetHeight(
const int32_t height = Room_GetHeight(
floor, g_Camera.target.x, g_Camera.target.y, g_Camera.target.z);
if (g_Camera.target.y > height) {
g_IsChunkyCamera = 0;
Expand Down

0 comments on commit a3ff248

Please sign in to comment.