Facebook
From Gabriel Dechichi, 3 Weeks ago, written in C.
Embed
Download Paste or View Raw
Hits: 4683
  1. #include "animation.h"
  2. #include "lib/array.h"
  3. #include "lib/assert.h"
  4. #include "lib/math.h"
  5. #include "lib/typedefs.h"
  6. #include "renderer.h"
  7. #include "vendor/cglm/types.h"
  8.  
  9. void apply_joint_transform_recursive(Joint_Array joints,
  10.                                      mat4_Array joint_matrices, u32 joint_idx,
  11.                                      mat4 parent_transform) {
  12.   mat4 *joint_transform = arr_get_ptr(joint_matrices, joint_idx);
  13.   mat4_mul(parent_transform, *joint_transform, *joint_transform);
  14.   Joint *joint = arr_get_ptr(joints, joint_idx);
  15.   arr_foreach(joint->children, u32, child_idx) {
  16.     apply_joint_transform_recursive(joints, joint_matrices, child_idx,
  17.                                     *joint_transform);
  18.   }
  19.  
  20.   mat4_mul(*joint_transform, joint->inverse_bind_matrix, *joint_transform);
  21. }
  22.  
  23. b32 find_start_end_keyframe(AnimationState *animation,
  24.                             _out_ i32 *start_keyframe_idx,
  25.                             _out_ i32 *end_keyframe_idx, _out_ f32 *t) {
  26.   debug_assert(animation->animation->keyframes.len > 0);
  27.   if (animation->animation->keyframes.len <= 0) {
  28.     return false;
  29.   }
  30.  
  31.   u32 len = animation->animation->keyframes.len;
  32.   f32 time = animation->time;
  33.  
  34.   // handle wrap case
  35.   if (animation->animation->keyframes.items[0].timestamp >= time) {
  36.     *start_keyframe_idx = len - 1;
  37.     *end_keyframe_idx = 0;
  38.     *t = lerp_inverse(
  39.         animation->animation->keyframes.items[*start_keyframe_idx].timestamp,
  40.         animation->animation->keyframes.items[*end_keyframe_idx].timestamp,
  41.         animation->time);
  42.     return true;
  43.   }
  44.  
  45.   // binary search for the keyframe
  46.   u32 left = 0;
  47.   u32 right = len - 1;
  48.  
  49.   while (left < right) {
  50.     u32 mid = left + (right - left) / 2;
  51.     if (animation->animation->keyframes.items[mid].timestamp <= time) {
  52.       left = mid + 1;
  53.     } else {
  54.       right = mid;
  55.     }
  56.   }
  57.  
  58.   // left is now the first keyframe with timestamp > time
  59.   *start_keyframe_idx = left - 1;
  60.   *end_keyframe_idx = left;
  61.   *t = lerp_inverse(
  62.       animation->animation->keyframes.items[*start_keyframe_idx].timestamp,
  63.       animation->animation->keyframes.items[*end_keyframe_idx].timestamp,
  64.       animation->time);
  65.  
  66.   return true;
  67. }
  68.  
  69. void animation_update(AnimationState *animation, f32 dt) {
  70.   f32 length = animation->animation->length;
  71.  
  72.   animation->time += dt * animation->speed;
  73.  
  74.   if (length > 0.0f) {
  75.     // Use fmod to handle multiple wraps and negative values
  76.     animation->time = fmodf(animation->time, length);
  77.  
  78.     // Ensure positive time for negative wrap-around
  79.     if (animation->time < 0.0f) {
  80.       animation->time += length;
  81.     }
  82.   }
  83. }
  84.  
  85. void animation_evaluate(AnimationState *animation,
  86.                         _out_ mat4_Array joint_matrices) {
  87.   assert(animation && animation->animation);
  88.   if (!animation || !animation->animation) {
  89.     return;
  90.   }
  91.  
  92.   i32 start_keyframe_idx, end_keyframe_idx;
  93.   f32 percent;
  94.   if (!find_start_end_keyframe(animation, &start;_keyframe_idx,
  95.                                &end;_keyframe_idx, &percent;)) {
  96.     return;
  97.   }
  98.  
  99.   Keyframe *start_keyframe =
  100.       &animation;->animation->keyframes.items[start_keyframe_idx];
  101.   Keyframe *end_keyframe =
  102.       &animation;->animation->keyframes.items[end_keyframe_idx];
  103.  
  104.   // evaluate all joints for keyframe and store local transforms
  105.   for (u32 i = 0; i < start_keyframe->joint_transforms.len; i++) {
  106.     KeyframeJointTransform *start_joint_transform =
  107.         &start;_keyframe->joint_transforms.items[i];
  108.     KeyframeJointTransform *end_joint_transform =
  109.         &end;_keyframe->joint_transforms.items[i];
  110.  
  111.     // again, every keyframe defines every joint in the same order
  112.     assert(start_joint_transform->index == end_joint_transform->index);
  113.  
  114.     vec3 translation;
  115.     quaternion rotation;
  116.     vec3_lerp(start_joint_transform->translation,
  117.               end_joint_transform->translation, percent, translation);
  118.     quat_slerp(start_joint_transform->rotation, end_joint_transform->rotation,
  119.                percent, rotation);
  120.  
  121.     mat4 *joint_mat = arr_get_ptr(joint_matrices, start_joint_transform->index);
  122.     debug_assert(joint_mat);
  123.     if (!joint_mat) {
  124.       continue;
  125.     }
  126.  
  127.     mat_tr(translation, rotation, *joint_mat);
  128.   }
  129.  
  130.   // apply hierarchy
  131.   Model3DData *model = animation->animation->model;
  132.   Joint_Array model_joints =
  133.       arr_from_c_array(Joint, model->joints, model->len_joints);
  134.   apply_joint_transform_recursive(model_joints, joint_matrices, 0,
  135.                                   MAT4_IDENTITY);
  136. }
  137.  

Replies to animation.c rss

Title Name Language When
Re: animation.c Lafllamme c 2 Weeks ago.