Files
Cesarus85--mjolnir-vr/source/models/model_animations.c
T

556 lines
15 KiB
C

/*
MODEL_ANIMATIONS.C
symbols in this file:
0010FE40 0010:
_animation_loop_frame_index (0000)
0010FE50 0010:
_animation_second_key_frame_index (0000)
0010FE60 0010:
_animation_sound_frame_index (0000)
0010FE70 0050:
_code_0010fe70 (0000)
0010FEC0 00a0:
_build_damage_animation_index (0000)
0010FF60 0080:
_animation_get_x_offsets (0000)
0010FFE0 0080:
_animation_set_frame_size (0000)
00110060 0060:
_quaternion_decompress_8byte (0000)
001100C0 00c0:
_quaternion_decompress_6byte (0000)
00110180 0020:
_quaternion_decompress_6byte_renormalized (0000)
001101A0 0060:
_quaternion_compress_8byte (0000)
00110200 0090:
_quaternion_compress_6byte (0000)
00110290 0160:
_animation_graph_node_matrices_from_orientations (0000)
001103F0 0110:
_interpolate_node_orientations (0000)
00110500 0060:
_animation_graph_get_animation_by_name (0000)
00110560 01d0:
_code_00110560 (0000)
00110730 0040:
_animation_frame_get_xy_translation (0000)
00110770 00b0:
_animation_choose_random_permutation_internal (0000)
00110820 0360:
_inverse_kinematics_adjust_matrices (0000)
00110B80 0310:
_code_00110b80 (0000)
00110E90 0300:
_code_00110e90 (0000)
00111190 02f0:
_code_00111190 (0000)
00111480 0130:
_animation_update_internal (0000)
001115B0 0300:
_animation_get_node_orientations (0000)
001118B0 01e0:
_replacement_animation_apply (0000)
00111A90 0210:
_overlay_animation_apply (0000)
00111CA0 0240:
_overlay_animation_apply_scaled (0000)
00111EE0 03c0:
_overlay_animation_apply_continuous (0000)
001122A0 0400:
_overlay_animation_apply_continuous_scaled (0000)
001126A0 0620:
_aiming_screen_apply (0000)
00112CC0 0040:
_animation_get_root_matrix (0000)
00112D00 00b0:
_animation_get_root_velocity (0000)
0027F208 000a:
??_C@_09KCBFNMAJ@animation?$AA@ (0000)
0027F214 0029:
??_C@_0CJ@JGGOLPOM@c?3?2halo?2SOURCE?2models?2model_anim@ (0000)
0027F240 0035:
??_C@_0DF@NDBCCBGA@damage_part?$DO?$DN0?5?$CG?$CG?5damage_part?$DMNU@ (0000)
0027F278 004e:
??_C@_0EO@PDDEEPOK@damage_direction?$DO?$DN0?5?$CG?$CG?5damage_di@ (0000)
0027F2C8 003f:
??_C@_0DP@CAICGJCA@damage_type?$DO?$DN0?5?$CG?$CG?5damage_type?$DMNU@ (0000)
0027F308 0004:
__real@38000100 (0000)
0027F30C 0024:
??_C@_0CE@FLNDNLBA@write_index?$DMMAXIMUM_NODES_PER_MO@ (0000)
0027F330 0018:
??_C@_0BI@NCOKEGAP@frame_index?$DMframe_count?$AA@ (0000)
0027F348 000e:
??_C@_0O@HJPIDGAL@frame_count?$DO0?$AA@ (0000)
0027F358 007a:
??_C@_0HK@JCHJDAIG@target_frame_index?$DO?$DNkeyframe_fra@ (0000)
0027F3D4 0035:
??_C@_0DF@BHOCMEDJ@keyframe_index?$DO?$DN0?5?$CG?$CG?5keyframe_in@ (0000)
0027F40C 001b:
??_C@_0BL@NIECDBGN@?$CL?$CLinfinite_loop_killer?$DM200?$AA@ (0000)
0027F428 0033:
??_C@_0DD@DKIDONPD@keyframe_index?$DO?$DN0?5?$CG?$CG?5keyframe_in@ (0000)
0027F460 0055:
??_C@_0FF@IFOFHFLN@target_frame_index?$DO?$DN0?5?$CG?$CG?5target_@ (0000)
0027F4B8 001c:
??_C@_0BM@EIBPKAOD@keyframe_frame_indices?$FL0?$FN?$DO0?$AA@ (0000)
0027F4D4 0017:
??_C@_0BH@FMNFCNKN@keyframe_frame_indices?$AA@ (0000)
0027F4EC 0011:
??_C@_0BB@INOOFBHG@keyframe_count?$DO1?$AA@ (0000)
0027F500 008e:
??_C@_0IO@GIPANHA@?$CIanimation_update_kind_affects_g@ (0000)
0027F590 0004:
__real@3f7ae148 (0000)
0027F594 0032:
??_C@_0DC@FHNJEFLD@real_frame_index?$DM?5?$CIreal?$CJnext_key@ (0000)
0027F5C8 0032:
??_C@_0DC@FGDAEANG@real_frame_index?$DO?$DN?$CIreal?$CJthis_key@ (0000)
0027F600 0043:
??_C@_0ED@ICKGJKPC@keyframe_frame_indices?$FLkeyframe_@ (0000)
0027F648 0048:
??_C@_0EI@OOKDDBPM@frame_index?$DO?$DN0?5?$CG?$CG?5frame_index?$DM?$DNk@ (0000)
0027F690 0012:
??_C@_0BC@GPLHPFMP@keyframe_count?$DO?$DN0?$AA@ (0000)
0027F6A4 002e:
??_C@_0CO@NEGCNKNH@real_frame_index?$DM?$CIreal?$CJanimation@ (0000)
0027F6D4 0017:
??_C@_0BH@JENGDKGC@real_frame_index?$DO?$DN0?40f?$AA@ (0000)
0027F6F0 006f:
??_C@_0GP@FNDBHMKG@compressed?5?$HM?$HM?5?$CIbyte?5?$CK?$CJdefault_da@ (0000)
0027F760 006b:
??_C@_0GL@JOCEOLB@compressed?5?$HM?$HM?5?$CIbyte?5?$CK?$CJdata?9?$CIbyte@ (0000)
0027F7D0 006d:
??_C@_0GN@PACKELMI@compressed?5?$HM?$HM?5?$CI?$CIbyte?5?$CK?$CJdata?9?$CIbyt@ (0000)
0027F840 0077:
??_C@_0HH@GKOAHDOE@compressed?5?$HM?$HM?5?$CI?$CIbyte?5?$CK?$CJnext_data@ (0000)
0027F8B8 0048:
??_C@_0EI@JELMFEDP@?$CD?$CD?$CD?5ERROR?5animation?5frame?5index?5@ (0000)
0027F900 0048:
??_C@_0EI@GGOLLJMH@?$CD?$CD?$CD?5ERROR?5animation?5frame?5index?5@ (0000)
0027F948 0026:
??_C@_0CG@FPLKLLFK@d0?$DN?$DN?$CFf?5direction?$CI?$CFf?$CJ?5yaw_delta?$CI?$CF@ (0000)
0027F970 0019:
??_C@_0BJ@LEBMJMIB@animation?9?$DOframe_count?$DO1?$AA@ (0000)
0030A388 0001:
_hs_model_animation_compression_enabled (0000)
0045662C 0024:
_hs_model_animation_data_compressed_size (0000)
_hs_model_animation_data_uncompressed_size (0004)
_hs_model_animation_data_compression_savings_in_bytes (0008)
_hs_model_animation_data_compression_savings_in_bytes_at_import (000c)
_hs_model_animation_data_compression_savings_in_percent (0010)
_hs_model_animation_bullshit (0014)
*/
/* ---------- headers */
#include "cseries.h"
#include "model_animation_definitions.h"
/* ---------- constants */
enum
{
COMPRESSED_QUATERNION_COMPONENT_MAXIMUM = 32767,
NUMBER_OF_ANIMATION_DAMAGE_TYPES = 4,
NUMBER_OF_ANIMATION_DAMAGE_DIRECTIONS = 4,
NUMBER_OF_DAMAGE_PARTS = 11,
};
enum
{
animation_update_kind_render_only = 0,
animation_update_kind_affects_game_state,
};
/* ---------- macros */
/* ---------- structures */
struct compressed_quaternion_8byte
{
short i;
short j;
short k;
short w;
};
struct compressed_quaternion_6byte
{
word words[3];
};
typedef char verify_compressed_quaternion_8byte_size[
sizeof(struct compressed_quaternion_8byte) == 0x08 ? 1 : -1];
typedef char verify_compressed_quaternion_6byte_size[
sizeof(struct compressed_quaternion_6byte) == 0x06 ? 1 : -1];
struct animation_frame_info_dx_dy
{
real dx;
real dy;
};
struct animation_frame_info_dx_dy_dyaw
{
real dx;
real dy;
real dyaw;
};
struct animation_frame_info_dx_dy_dz_dyaw
{
real dx;
real dy;
real dz;
real dyaw;
};
typedef char verify_animation_frame_info_dx_dy_size[
sizeof(struct animation_frame_info_dx_dy) == 0x08 ? 1 : -1];
typedef char verify_animation_frame_info_dx_dy_dyaw_size[
sizeof(struct animation_frame_info_dx_dy_dyaw) == 0x0C ? 1 : -1];
typedef char verify_animation_frame_info_dx_dy_dz_dyaw_size[
sizeof(struct animation_frame_info_dx_dy_dz_dyaw) == 0x10 ? 1 : -1];
/* ---------- prototypes */
/* ---------- globals */
/* ---------- public code */
short animation_loop_frame_index(
struct animation const *animation)
{
return animation->private_loop_frame_index;
}
short animation_second_key_frame_index(
struct animation const *animation)
{
return animation->private_second_key_frame_index;
}
short animation_sound_frame_index(
struct animation const *animation)
{
return animation->private_sound_frame_index;
}
short build_damage_animation_index(
short damage_type,
short damage_direction,
short damage_part)
{
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
55,
damage_type>=0 && damage_type<NUMBER_OF_ANIMATION_DAMAGE_TYPES);
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
56,
damage_direction>=0 && damage_direction<NUMBER_OF_ANIMATION_DAMAGE_DIRECTIONS);
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
57,
damage_part>=0 && damage_part<NUMBER_OF_DAMAGE_PARTS);
return (damage_type * NUMBER_OF_ANIMATION_DAMAGE_DIRECTIONS + damage_direction) *
NUMBER_OF_DAMAGE_PARTS + damage_part;
}
void animation_get_x_offsets(
struct animation const *animation,
real *key_frame_x_offset,
real *total_x_offset)
{
short frame_index;
real x_offset = 0.f;
real key_x_offset = 0.f;
byte const *frame_info = animation->frame_info.address;
for (frame_index = 0; frame_index < animation->frame_count; frame_index++)
{
switch (animation->frame_info_type)
{
case 1:
x_offset += ((struct animation_frame_info_dx_dy const *)frame_info)->dx;
frame_info += sizeof(struct animation_frame_info_dx_dy);
break;
case 2:
x_offset += ((struct animation_frame_info_dx_dy_dyaw const *)frame_info)->dx;
frame_info += sizeof(struct animation_frame_info_dx_dy_dyaw);
break;
case 3:
x_offset += ((struct animation_frame_info_dx_dy_dz_dyaw const *)frame_info)->dx;
frame_info += sizeof(struct animation_frame_info_dx_dy_dz_dyaw);
break;
}
if (frame_index == animation->private_key_frame_index)
{
key_x_offset = x_offset;
}
}
if (total_x_offset)
{
*total_x_offset = x_offset;
}
if (key_frame_x_offset)
{
*key_frame_x_offset = key_x_offset;
}
return;
}
short animation_graph_get_animation_by_name(
long animation_graph_index,
char const *animation_name)
{
struct animation_graph const *animation_graph = animation_graph_definition_get(animation_graph_index);
short animation_index;
for (animation_index = 0; animation_index < animation_graph->animations.count; animation_index++)
{
struct animation const *animation = TAG_BLOCK_GET_ELEMENT(
&animation_graph->animations,
animation_index,
struct animation);
if (!_stricmp(animation_name, animation->name))
{
return animation_index;
}
}
return NONE;
}
void animation_frame_get_xy_translation(
struct animation const *animation,
short frame_index,
real_vector2d *translation)
{
if (animation->frame_info_type == 1)
{
*translation = *(real_vector2d const *)animation_get_frame_info(
animation,
frame_index,
sizeof(struct animation_frame_info_dx_dy));
}
else
{
translation->i = 0.f;
translation->j = 0.f;
}
return;
}
short animation_choose_random_permutation_internal(
long render_or_affects_game_state,
long animation_graph_index,
short animation_index)
{
struct animation_graph const *animation_graph = animation_graph_definition_get(animation_graph_index);
real random;
if (render_or_affects_game_state == animation_update_kind_affects_game_state)
{
random = real_seed_random(get_global_random_seed_address());
}
else
{
random = real_seed_random(get_global_local_random_seed_address());
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
1008,
(animation_update_kind_affects_game_state==render_or_affects_game_state) ||
(animation_update_kind_render_only==render_or_affects_game_state));
}
while (animation_index != NONE)
{
struct animation const *animation = TAG_BLOCK_GET_ELEMENT(
&animation_graph->animations,
animation_index,
struct animation);
if (random <= animation->runtime_normalized_weight)
{
break;
}
animation_index = animation->next_animation_index;
}
return animation_index;
}
void interpolate_node_orientations(
short node_count,
struct real_orientation *original_node_orientations,
struct real_orientation *target_node_orientations,
short frame_index,
short frame_count)
{
real fraction = (real)(frame_index + 1) / (real)frame_count;
real inverse_fraction = 1.f - fraction;
short node_index;
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
1277,
frame_count>0);
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
1278,
frame_index<frame_count);
for (node_index = 0; node_index < node_count; node_index++)
{
struct real_orientation *target = &target_node_orientations[node_index];
struct real_orientation const *original = &original_node_orientations[node_index];
target->scale = original->scale * inverse_fraction + target->scale * fraction;
quaternions_interpolate_and_normalize(
&original->rotation,
&target->rotation,
fraction,
&target->rotation);
target->translation.x = original->translation.x * inverse_fraction + target->translation.x * fraction;
target->translation.y = original->translation.y * inverse_fraction + target->translation.y * fraction;
target->translation.z = original->translation.z * inverse_fraction + target->translation.z * fraction;
}
return;
}
void animation_get_root_matrix(
struct model const *model,
struct animation const *animation,
short frame_index,
real_matrix4x3 *root_matrix)
{
struct real_orientation node_orientations[MAXIMUM_NODES_PER_ANIMATION];
animation_get_node_orientations(model, animation, frame_index, node_orientations);
matrix4x3_from_point_and_quaternion(
root_matrix,
&node_orientations[0].translation,
&node_orientations[0].rotation);
return;
}
void animation_get_root_velocity(
struct model const *model,
struct animation const *animation,
short frame_index,
real_vector3d *root_velocity)
{
struct real_orientation node_orientations[MAXIMUM_NODES_PER_ANIMATION];
struct real_orientation previous_node_orientations[MAXIMUM_NODES_PER_ANIMATION];
match_assert(
"c:\\halo\\SOURCE\\models\\model_animations.c",
221,
animation->frame_count>1);
if (frame_index == 0)
{
frame_index = 1;
}
animation_get_node_orientations(model, animation, frame_index, node_orientations);
animation_get_node_orientations(model, animation, frame_index - 1, previous_node_orientations);
root_velocity->i = node_orientations[0].translation.x - previous_node_orientations[0].translation.x;
root_velocity->j = node_orientations[0].translation.y - previous_node_orientations[0].translation.y;
root_velocity->k = node_orientations[0].translation.z - previous_node_orientations[0].translation.z;
return;
}
void quaternion_decompress_8byte(
struct compressed_quaternion_8byte const *compressed,
real_quaternion *quaternion)
{
real const scale = 1.f / COMPRESSED_QUATERNION_COMPONENT_MAXIMUM;
quaternion->v.i = compressed->i * scale;
quaternion->v.j = compressed->j * scale;
quaternion->v.k = compressed->k * scale;
quaternion->w = compressed->w * scale;
return;
}
void quaternion_decompress_6byte(
struct compressed_quaternion_6byte const *compressed,
real_quaternion *quaternion)
{
word word0 = compressed->words[0];
word word1 = compressed->words[1];
word word2 = compressed->words[2];
short i = (short)((word0 >> 12) | (word0 & 0xFFF0));
short j = (short)(((word1 >> 4) & 0x0FF0) | (word0 & 0x000F) | (word0 << 12));
short k = (short)(((((word2 >> 4) & 0x0F00) | (word1 & 0x00F0)) >> 4) | (word1 << 8));
short w = (short)(((word2 >> 8) & 0x000F) | (word2 << 4));
real const scale = 1.f / COMPRESSED_QUATERNION_COMPONENT_MAXIMUM;
quaternion->v.i = i * scale;
quaternion->v.j = j * scale;
quaternion->v.k = k * scale;
quaternion->w = w * scale;
return;
}
void quaternion_decompress_6byte_renormalized(
void const *compressed,
real_quaternion *quaternion)
{
quaternion_decompress_6byte(compressed, quaternion);
quaternion_normalize(quaternion);
return;
}
void quaternion_compress_8byte(
real_quaternion const *quaternion,
struct compressed_quaternion_8byte *compressed)
{
compressed->i = (short)(quaternion->v.i * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
compressed->j = (short)(quaternion->v.j * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
compressed->k = (short)(quaternion->v.k * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
compressed->w = (short)(quaternion->w * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
return;
}
void quaternion_compress_6byte(
real_quaternion const *quaternion,
struct compressed_quaternion_6byte *compressed)
{
long j = (long)(quaternion->v.j * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
long k = (long)(quaternion->v.k * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
long w = (long)(quaternion->w * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
long i = (long)(quaternion->v.i * COMPRESSED_QUATERNION_COMPONENT_MAXIMUM);
compressed->words[0] = (word)((i & 0xFFF0) | ((word)j >> 12));
compressed->words[1] = (word)(((j & 0xFFF0) << 4) | (((word)k >> 8) & 0x00FF));
compressed->words[2] = (word)(((k & 0x00F0) << 8) | ((word)w >> 4));
return;
}
/* ---------- private code */