mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
tr2/lara/hair: add interpolation control
This improves the overall animation of Lara's hair to respond to interpolated frames in her main animation. Resolves #2094.
This commit is contained in:
parent
336d775410
commit
2d92771e2c
3 changed files with 183 additions and 75 deletions
|
@ -17,6 +17,7 @@
|
|||
- fixed the camera getting stuck at the start of Home Sweet Home (#2129, regression from 0.7)
|
||||
- fixed bubbles spawning from flares if Lara is in shallow water (#1590)
|
||||
- fixed flare sound effects not always playing when Lara is in shallow water (#1590)
|
||||
- improved the animation of Lara's braid (#2094)
|
||||
|
||||
## [0.7.1](https://github.com/LostArtefacts/TRX/compare/tr2-0.7...tr2-0.7.1) - 2024-12-17
|
||||
- fixed a crash when selecting the sound option (#2057, regression from 0.6)
|
||||
|
|
|
@ -62,6 +62,7 @@ game with new enhancements and features.
|
|||
- **Ice Palace**: fixed door 143's position to resolve the invisible wall in front of it, and added an extra pickup trigger beside the Gong Hammer in room 29
|
||||
- **Temple of Xian**: fixed missing death tiles in room 91
|
||||
- **Floating Islands**: fixed door 72's position to resolve the invisible wall in front of it
|
||||
- improved the animation of Lara's braid
|
||||
|
||||
#### Cheats
|
||||
- added a fly cheat
|
||||
|
|
|
@ -45,9 +45,15 @@ void Lara_Hair_Initialise(void)
|
|||
|
||||
void Lara_Hair_Control(const bool in_cutscene)
|
||||
{
|
||||
const FRAME_INFO *frame;
|
||||
const FRAME_INFO *frame1;
|
||||
const FRAME_INFO *frame2;
|
||||
int32_t frac;
|
||||
int32_t rate;
|
||||
if (g_Lara.hit_direction < 0) {
|
||||
frame = Item_GetBestFrame(g_LaraItem);
|
||||
FRAME_INFO *frmptr[2];
|
||||
frac = Item_GetFrames(g_LaraItem, frmptr, &rate);
|
||||
frame1 = frmptr[0];
|
||||
frame2 = frmptr[1];
|
||||
} else {
|
||||
LARA_ANIMATION lara_anim;
|
||||
switch (g_Lara.hit_direction) {
|
||||
|
@ -67,13 +73,13 @@ void Lara_Hair_Control(const bool in_cutscene)
|
|||
|
||||
const int16_t *const frame_ptr = g_Anims[lara_anim].frame_ptr;
|
||||
const int32_t interpolation = g_Anims[lara_anim].interpolation;
|
||||
frame =
|
||||
frame1 =
|
||||
(FRAME_INFO *)&frame_ptr[g_Lara.hit_frame * (interpolation >> 8)];
|
||||
frac = 0;
|
||||
}
|
||||
|
||||
const int32_t *bone;
|
||||
const int16_t *mesh;
|
||||
const int16_t *mesh_rots;
|
||||
SPHERE spheres[5];
|
||||
|
||||
Matrix_PushUnit();
|
||||
|
@ -81,78 +87,175 @@ void Lara_Hair_Control(const bool in_cutscene)
|
|||
g_MatrixPtr->_13 = g_LaraItem->pos.y << W2V_SHIFT;
|
||||
g_MatrixPtr->_23 = g_LaraItem->pos.z << W2V_SHIFT;
|
||||
Matrix_RotYXZ(g_LaraItem->rot.y, g_LaraItem->rot.x, g_LaraItem->rot.z);
|
||||
mesh_rots = frame->mesh_rots;
|
||||
Matrix_TranslateRel(frame->offset.x, frame->offset.y, frame->offset.z);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 0);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HIPS];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[0].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[0].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[0].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[0].r = mesh[3];
|
||||
Matrix_Pop();
|
||||
|
||||
bone = &g_AnimBones[g_Objects[O_LARA].bone_idx];
|
||||
Matrix_TranslateRel(bone[25], bone[26], bone[27]);
|
||||
if (g_Lara.weapon_item != NO_ITEM && g_Lara.gun_type == LGT_M16
|
||||
&& (g_Items[g_Lara.weapon_item].current_anim_state == 0
|
||||
|| g_Items[g_Lara.weapon_item].current_anim_state == 2
|
||||
|| g_Items[g_Lara.weapon_item].current_anim_state == 4)) {
|
||||
mesh_rots =
|
||||
&g_Lara.right_arm.frame_base
|
||||
[g_Lara.right_arm.frame_num
|
||||
* (g_Anims[g_Lara.right_arm.anim_num].interpolation >> 8)
|
||||
+ FBBOX_ROT];
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 7);
|
||||
if (frac != 0) {
|
||||
const int16_t *mesh_rots1 = frame1->mesh_rots;
|
||||
const int16_t *mesh_rots2 = frame2->mesh_rots;
|
||||
Matrix_InitInterpolate(frac, rate);
|
||||
Matrix_TranslateRel_ID(
|
||||
frame1->offset.x, frame1->offset.y, frame1->offset.z,
|
||||
frame2->offset.x, frame2->offset.y, frame2->offset.z);
|
||||
Matrix_RotYXZsuperpack_I(&mesh_rots1, &mesh_rots2, 0);
|
||||
|
||||
Matrix_Push_I();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HIPS];
|
||||
Matrix_TranslateRel_I(mesh[0], mesh[1], mesh[2]);
|
||||
Matrix_Interpolate();
|
||||
spheres[0].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[0].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[0].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[0].r = mesh[3];
|
||||
Matrix_Pop_I();
|
||||
|
||||
bone = &g_AnimBones[g_Objects[O_LARA].bone_idx];
|
||||
Matrix_TranslateRel_I(bone[25], bone[26], bone[27]);
|
||||
if (g_Lara.weapon_item != NO_ITEM && g_Lara.gun_type == LGT_M16
|
||||
&& (g_Items[g_Lara.weapon_item].current_anim_state == 0
|
||||
|| g_Items[g_Lara.weapon_item].current_anim_state == 2
|
||||
|| g_Items[g_Lara.weapon_item].current_anim_state == 4)) {
|
||||
mesh_rots1 =
|
||||
&g_Lara.right_arm.frame_base
|
||||
[g_Lara.right_arm.frame_num
|
||||
* (g_Anims[g_Lara.right_arm.anim_num].interpolation
|
||||
>> 8)
|
||||
+ FBBOX_ROT];
|
||||
mesh_rots2 = mesh_rots1;
|
||||
Matrix_RotYXZsuperpack_I(&mesh_rots1, &mesh_rots2, 7);
|
||||
} else {
|
||||
Matrix_RotYXZsuperpack_I(&mesh_rots1, &mesh_rots2, 6);
|
||||
}
|
||||
Matrix_RotYXZ_I(
|
||||
g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
|
||||
|
||||
Matrix_Push_I();
|
||||
mesh = g_Lara.mesh_ptrs[LM_TORSO];
|
||||
Matrix_TranslateRel_I(mesh[0], mesh[1], mesh[2]);
|
||||
Matrix_Interpolate();
|
||||
spheres[1].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[1].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[1].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[1].r = mesh[3];
|
||||
Matrix_Pop_I();
|
||||
|
||||
Matrix_Push_I();
|
||||
Matrix_TranslateRel_I(bone[29], bone[30], bone[31]);
|
||||
Matrix_RotYXZsuperpack_I(&mesh_rots1, &mesh_rots2, 0);
|
||||
|
||||
mesh = g_Lara.mesh_ptrs[LM_UARM_R];
|
||||
Matrix_TranslateRel_I(mesh[0], mesh[1], mesh[2]);
|
||||
Matrix_Interpolate();
|
||||
spheres[3].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[3].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[3].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[3].r = mesh[3] * 3 / 2;
|
||||
Matrix_Pop_I();
|
||||
|
||||
Matrix_Push_I();
|
||||
Matrix_TranslateRel_I(bone[41], bone[42], bone[43]);
|
||||
Matrix_RotYXZsuperpack_I(&mesh_rots1, &mesh_rots2, 2);
|
||||
mesh = g_Lara.mesh_ptrs[LM_UARM_L];
|
||||
Matrix_TranslateRel_I(mesh[0], mesh[1], mesh[2]);
|
||||
Matrix_Interpolate();
|
||||
spheres[4].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[4].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[4].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[4].r = mesh[3] * 3 / 2;
|
||||
Matrix_Pop_I();
|
||||
|
||||
Matrix_TranslateRel_I(bone[53], bone[54], bone[55]);
|
||||
Matrix_RotYXZsuperpack_I(&mesh_rots1, &mesh_rots2, 2);
|
||||
Matrix_RotYXZ_I(
|
||||
g_Lara.head_y_rot, g_Lara.head_x_rot, g_Lara.head_z_rot);
|
||||
Matrix_Push_I();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HEAD];
|
||||
Matrix_TranslateRel_I(mesh[0], mesh[1], mesh[2]);
|
||||
Matrix_Interpolate();
|
||||
spheres[2].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[2].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[2].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[2].r = mesh[3];
|
||||
Matrix_Pop_I();
|
||||
|
||||
Matrix_TranslateRel_I(0, -23, -55);
|
||||
Matrix_Interpolate();
|
||||
} else {
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 6);
|
||||
const int16_t *mesh_rots = frame1->mesh_rots;
|
||||
Matrix_TranslateRel(
|
||||
frame1->offset.x, frame1->offset.y, frame1->offset.z);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 0);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HIPS];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[0].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[0].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[0].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[0].r = mesh[3];
|
||||
Matrix_Pop();
|
||||
|
||||
bone = &g_AnimBones[g_Objects[O_LARA].bone_idx];
|
||||
Matrix_TranslateRel(bone[25], bone[26], bone[27]);
|
||||
if (g_Lara.weapon_item != NO_ITEM && g_Lara.gun_type == LGT_M16
|
||||
&& (g_Items[g_Lara.weapon_item].current_anim_state == 0
|
||||
|| g_Items[g_Lara.weapon_item].current_anim_state == 2
|
||||
|| g_Items[g_Lara.weapon_item].current_anim_state == 4)) {
|
||||
mesh_rots =
|
||||
&g_Lara.right_arm.frame_base
|
||||
[g_Lara.right_arm.frame_num
|
||||
* (g_Anims[g_Lara.right_arm.anim_num].interpolation
|
||||
>> 8)
|
||||
+ FBBOX_ROT];
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 7);
|
||||
} else {
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 6);
|
||||
}
|
||||
Matrix_RotYXZ(
|
||||
g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_TORSO];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[1].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[1].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[1].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[1].r = mesh[3];
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateRel(bone[29], bone[30], bone[31]);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 0);
|
||||
mesh = g_Lara.mesh_ptrs[LM_UARM_R];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[3].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[3].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[3].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[3].r = mesh[3] * 3 / 2;
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateRel(bone[41], bone[42], bone[43]);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 2);
|
||||
mesh = g_Lara.mesh_ptrs[LM_UARM_L];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[4].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[4].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[4].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[4].r = mesh[3] * 3 / 2;
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_TranslateRel(bone[53], bone[54], bone[55]);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 2);
|
||||
Matrix_RotYXZ(g_Lara.head_y_rot, g_Lara.head_x_rot, g_Lara.head_z_rot);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HEAD];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[2].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[2].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[2].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[2].r = mesh[3];
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_TranslateRel(0, -23, -55);
|
||||
}
|
||||
Matrix_RotYXZ(g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_TORSO];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[1].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[1].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[1].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[1].r = mesh[3];
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateRel(bone[29], bone[30], bone[31]);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 0);
|
||||
mesh = g_Lara.mesh_ptrs[LM_UARM_R];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[3].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[3].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[3].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[3].r = mesh[3] * 3 / 2;
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateRel(bone[41], bone[42], bone[43]);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 2);
|
||||
mesh = g_Lara.mesh_ptrs[LM_UARM_R];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[4].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[4].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[4].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[4].r = mesh[3] * 3 / 2;
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_TranslateRel(bone[53], bone[54], bone[55]);
|
||||
Matrix_RotYXZsuperpack(&mesh_rots, 2);
|
||||
Matrix_RotYXZ(g_Lara.head_y_rot, g_Lara.head_x_rot, g_Lara.head_z_rot);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HEAD];
|
||||
Matrix_TranslateRel(mesh[0], mesh[1], mesh[2]);
|
||||
spheres[2].x = g_MatrixPtr->_03 >> W2V_SHIFT;
|
||||
spheres[2].y = g_MatrixPtr->_13 >> W2V_SHIFT;
|
||||
spheres[2].z = g_MatrixPtr->_23 >> W2V_SHIFT;
|
||||
spheres[2].r = mesh[3];
|
||||
Matrix_Pop();
|
||||
|
||||
Matrix_TranslateRel(0, -23, -55);
|
||||
const XYZ_32 pos = {
|
||||
.x = g_MatrixPtr->_03 >> W2V_SHIFT,
|
||||
.y = g_MatrixPtr->_13 >> W2V_SHIFT,
|
||||
|
@ -196,9 +299,12 @@ void Lara_Hair_Control(const bool in_cutscene)
|
|||
water_height = NO_HEIGHT;
|
||||
} else {
|
||||
water_height = Room_GetWaterHeight(
|
||||
g_LaraItem->pos.x + (frame->bounds.min_x + frame->bounds.max_x) / 2,
|
||||
g_LaraItem->pos.y + (frame->bounds.max_y + frame->bounds.min_y) / 2,
|
||||
g_LaraItem->pos.z + (frame->bounds.max_z + frame->bounds.min_z) / 2,
|
||||
g_LaraItem->pos.x
|
||||
+ (frame1->bounds.min_x + frame1->bounds.max_x) / 2,
|
||||
g_LaraItem->pos.y
|
||||
+ (frame1->bounds.max_y + frame1->bounds.min_y) / 2,
|
||||
g_LaraItem->pos.z
|
||||
+ (frame1->bounds.max_z + frame1->bounds.min_z) / 2,
|
||||
room_num);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue