r3d_animation_player.odin 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /* r3d_animation_player.odin -- R3D Animation Player Module.
  2. *
  3. * Copyright (c) 2025-2026 Le Juez Victor
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * For conditions of distribution and use, see accompanying LICENSE file.
  7. */
  8. package r3d
  9. import rl "vendor:raylib"
  10. when ODIN_OS == .Windows {
  11. foreign import lib {
  12. "windows/libr3d.a",
  13. "system:raylib",
  14. "system:assimp",
  15. }
  16. } else when ODIN_OS == .Linux {
  17. foreign import lib {
  18. "linux/libr3d.a",
  19. "system:raylib",
  20. "system:assimp",
  21. }
  22. } else when ODIN_OS == .Darwin {
  23. foreign import lib {
  24. "darwin/libr3d.a",
  25. "system:raylib",
  26. "system:assimp",
  27. }
  28. }
  29. /**
  30. * @brief Types of events that an animation player can emit.
  31. */
  32. AnimationEvent :: enum u32 {
  33. FINISHED = 0, ///< Animation has finished playing (non-looping).
  34. LOOPED = 1, ///< Animation has completed a loop.
  35. }
  36. /**
  37. * @brief Callback type for receiving animation events.
  38. *
  39. * @param player Pointer to the animation player emitting the event.
  40. * @param eventType Type of the event (finished, looped).
  41. * @param animIndex Index of the animation triggering the event.
  42. * @param userData Optional user-defined data passed when the callback was registered.
  43. */
  44. AnimationEventCallback :: proc "c" (player: ^AnimationPlayer, eventType: AnimationEvent, animIndex: i32, userData: rawptr)
  45. /**
  46. * @brief Describes the playback state of a single animation within a player.
  47. *
  48. * Tracks the current time, blending weight, speed, play/pause state, and looping behavior.
  49. */
  50. AnimationState :: struct {
  51. currentTime: f32, ///< Current playback time in animation ticks.
  52. weight: f32, ///< Blending weight; any positive value is valid.
  53. speed: f32, ///< Playback speed; can be negative for reverse playback.
  54. play: bool, ///< Whether the animation is currently playing.
  55. loop: bool, ///< True to enable looping playback.
  56. }
  57. // ========================================
  58. // FORWARD DECLARATIONS
  59. // ========================================
  60. AnimationPlayer :: struct {
  61. states: [^]AnimationState, ///< Array of active animation states, one per animation.
  62. animLib: AnimationLib, ///< Animation library providing the available animations.
  63. skeleton: Skeleton, ///< Skeleton to animate.
  64. localPose: [^]rl.Matrix, ///< Array of bone transforms representing the blended local pose.
  65. modelPose: [^]rl.Matrix, ///< Array of bone transforms in model space, obtained by hierarchical accumulation.
  66. skinBuffer: [^]rl.Matrix, ///< Array of final skinning matrices (invBind * modelPose), sent to the GPU.
  67. skinTexture: u32, ///< GPU texture ID storing the skinning matrices as a 1D RGBA16F texture.
  68. eventCallback: AnimationEventCallback, ///< Callback function to receive animation events.
  69. eventUserData: rawptr, ///< Optional user data pointer passed to the callback.
  70. }
  71. @(default_calling_convention="c", link_prefix="R3D_")
  72. foreign lib {
  73. /**
  74. * @brief Creates an animation player for a skeleton and animation library.
  75. *
  76. * Allocates memory for animation states and pose buffers.
  77. *
  78. * @param skeleton Skeleton to animate.
  79. * @param animLib Animation library providing animations.
  80. * @return Newly created animation player, or a zeroed struct on failure.
  81. */
  82. LoadAnimationPlayer :: proc(skeleton: Skeleton, animLib: AnimationLib) -> AnimationPlayer ---
  83. /**
  84. * @brief Releases all resources used by an animation player.
  85. *
  86. * @param player Animation player to unload.
  87. */
  88. UnloadAnimationPlayer :: proc(player: AnimationPlayer) ---
  89. /**
  90. * @brief Checks whether an animation player is valid.
  91. *
  92. * @param player Animation player to check.
  93. * @return true if valid, false otherwise.
  94. */
  95. IsAnimationPlayerValid :: proc(player: AnimationPlayer) -> bool ---
  96. /**
  97. * @brief Returns whether a given animation is currently playing.
  98. *
  99. * @param player Animation player.
  100. * @param animIndex Index of the animation.
  101. * @return true if playing, false otherwise.
  102. */
  103. IsAnimationPlaying :: proc(player: AnimationPlayer, animIndex: i32) -> bool ---
  104. /**
  105. * @brief Starts playback of the specified animation.
  106. *
  107. * @param player Animation player.
  108. * @param animIndex Index of the animation to play.
  109. */
  110. PlayAnimation :: proc(player: ^AnimationPlayer, animIndex: i32) ---
  111. /**
  112. * @brief Pauses the specified animation.
  113. *
  114. * @param player Animation player.
  115. * @param animIndex Index of the animation to pause.
  116. */
  117. PauseAnimation :: proc(player: ^AnimationPlayer, animIndex: i32) ---
  118. /**
  119. * @brief Stops the specified animation and clamps its time.
  120. *
  121. * @param player Animation player.
  122. * @param animIndex Index of the animation to stop.
  123. */
  124. StopAnimation :: proc(player: ^AnimationPlayer, animIndex: i32) ---
  125. /**
  126. * @brief Rewinds the animation to the start or end depending on playback direction.
  127. *
  128. * @param player Animation player.
  129. * @param animIndex Index of the animation to rewind.
  130. */
  131. RewindAnimation :: proc(player: ^AnimationPlayer, animIndex: i32) ---
  132. /**
  133. * @brief Gets the current playback time of an animation.
  134. *
  135. * @param player Animation player.
  136. * @param animIndex Index of the animation.
  137. * @return Current time in animation ticks.
  138. */
  139. GetAnimationTime :: proc(player: AnimationPlayer, animIndex: i32) -> f32 ---
  140. /**
  141. * @brief Sets the current playback time of an animation.
  142. *
  143. * @param player Animation player.
  144. * @param animIndex Index of the animation.
  145. * @param time Time in animation ticks.
  146. */
  147. SetAnimationTime :: proc(player: ^AnimationPlayer, animIndex: i32, time: f32) ---
  148. /**
  149. * @brief Gets the blending weight of an animation.
  150. *
  151. * @param player Animation player.
  152. * @param animIndex Index of the animation.
  153. * @return Current weight.
  154. */
  155. GetAnimationWeight :: proc(player: AnimationPlayer, animIndex: i32) -> f32 ---
  156. /**
  157. * @brief Sets the blending weight of an animation.
  158. *
  159. * @param player Animation player.
  160. * @param animIndex Index of the animation.
  161. * @param weight Blending weight to apply.
  162. */
  163. SetAnimationWeight :: proc(player: ^AnimationPlayer, animIndex: i32, weight: f32) ---
  164. /**
  165. * @brief Gets the playback speed of an animation.
  166. *
  167. * @param player Animation player.
  168. * @param animIndex Index of the animation.
  169. * @return Current speed (may be negative for reverse playback).
  170. */
  171. GetAnimationSpeed :: proc(player: AnimationPlayer, animIndex: i32) -> f32 ---
  172. /**
  173. * @brief Sets the playback speed of an animation.
  174. *
  175. * Negative values play the animation backwards. If setting a negative speed
  176. * on a stopped animation, consider calling RewindAnimation() to start at the end.
  177. *
  178. * @param player Animation player.
  179. * @param animIndex Index of the animation.
  180. * @param speed Playback speed.
  181. */
  182. SetAnimationSpeed :: proc(player: ^AnimationPlayer, animIndex: i32, speed: f32) ---
  183. /**
  184. * @brief Gets whether the animation is set to loop.
  185. *
  186. * @param player Animation player.
  187. * @param animIndex Index of the animation.
  188. * @return True if looping is enabled.
  189. */
  190. GetAnimationLoop :: proc(player: AnimationPlayer, animIndex: i32) -> bool ---
  191. /**
  192. * @brief Enables or disables looping for the animation.
  193. *
  194. * @param player Animation player.
  195. * @param animIndex Index of the animation.
  196. * @param loop True to enable looping.
  197. */
  198. SetAnimationLoop :: proc(player: ^AnimationPlayer, animIndex: i32, loop: bool) ---
  199. /**
  200. * @brief Advances the time of all active animations.
  201. *
  202. * Updates all internal animation timers based on speed and delta time.
  203. * Does NOT recalculate the skeleton pose.
  204. *
  205. * @param player Animation player.
  206. * @param dt Delta time in seconds.
  207. */
  208. AdvanceAnimationPlayerTime :: proc(player: ^AnimationPlayer, dt: f32) ---
  209. /**
  210. * @brief Calculates the current blended local pose of the skeleton.
  211. *
  212. * Interpolates keyframes and blends all active animations according to their weights,
  213. * but only computes the local transforms of each bone relative to its parent.
  214. * Does NOT advance animation time.
  215. *
  216. * @param player Animation player whose local pose will be updated.
  217. */
  218. CalculateAnimationPlayerLocalPose :: proc(player: ^AnimationPlayer) ---
  219. /**
  220. * @brief Calculates the current blended model (global) pose of the skeleton.
  221. *
  222. * Interpolates keyframes and blends all active animations according to their weights,
  223. * but only computes the global transforms of each bone in model space.
  224. * This assumes the local pose is already up-to-date.
  225. * Does NOT advance animation time.
  226. *
  227. * @param player Animation player whose model pose will be updated.
  228. */
  229. CalculateAnimationPlayerModelPose :: proc(player: ^AnimationPlayer) ---
  230. /**
  231. * @brief Calculates the current blended skeleton pose (local and model).
  232. *
  233. * Interpolates keyframes and blends all active animations according to their weights,
  234. * then computes both local and model transforms for the entire skeleton.
  235. * Does NOT advance animation time.
  236. *
  237. * @param player Animation player whose local and model poses will be updated.
  238. */
  239. CalculateAnimationPlayerPose :: proc(player: ^AnimationPlayer) ---
  240. /**
  241. * @brief Calculates the skinning matrices and uploads them to the GPU.
  242. *
  243. * @param player Animation player.
  244. */
  245. UploadAnimationPlayerPose :: proc(player: ^AnimationPlayer) ---
  246. /**
  247. * @brief Updates the animation player: calculates and upload blended pose, then advances time.
  248. *
  249. * Equivalent to calling R3D_CalculateAnimationPlayerPose() followed by
  250. * R3D_UploadAnimationPlayerPose() and R3D_AdvanceAnimationPlayerTime().
  251. *
  252. * @param player Animation player.
  253. * @param dt Delta time in seconds.
  254. */
  255. UpdateAnimationPlayer :: proc(player: ^AnimationPlayer, dt: f32) ---
  256. }