// // Created by martin on 12.11.21. // #ifndef ANIMTESTBED_SKINNEDMESH_H #define ANIMTESTBED_SKINNEDMESH_H // ozz-animation headers #include // fmodf #include // std::unique_ptr, std::make_unique #include "ozz/animation/runtime/animation.h" #include "ozz/animation/runtime/local_to_model_job.h" #include "ozz/animation/runtime/sampling_job.h" #include "ozz/animation/runtime/skeleton.h" #include "ozz/base/containers/vector.h" #include "ozz/base/io/archive.h" #include "ozz/base/io/stream.h" #include "ozz/base/log.h" #include "ozz/base/maths/soa_transform.h" #include "ozz/base/maths/vec_float.h" constexpr int cSyncTrackMaxIntervals = 8; struct SyncTrack { float m_duration; int m_num_intervals; float m_sync_markers[cSyncTrackMaxIntervals]; float m_interval_start[cSyncTrackMaxIntervals]; float m_interval_end[cSyncTrackMaxIntervals]; float m_interval_durations[cSyncTrackMaxIntervals]; void CalcIntervals() { int i; if (m_num_intervals == 0) { m_num_intervals = 1; m_interval_start[0] = 0.f; m_interval_end[0] = 1.f; } else { for (i = 0; i < m_num_intervals; i++) { int end_index = i < m_num_intervals - 1 ? i + 1 : 0; m_interval_start[i] = m_sync_markers[i]; m_interval_end[i] = m_sync_markers[end_index]; if (m_interval_end[i] > m_interval_start[i]) { m_interval_durations[i] = m_interval_end[i] - m_interval_start[i]; } else { m_interval_durations[i] = m_interval_end[i] + (1. - m_interval_start[i]); } } } } float CalcSyncFromAbsTime(float abs_time) { float sync_time = fmodf(abs_time, m_duration) / m_duration; int interval_index = 0; while (sync_time >= m_interval_durations[interval_index]) { sync_time -= m_interval_durations[interval_index]; interval_index++; } return float(interval_index) + sync_time / m_interval_durations[interval_index]; } float CalcRatioFromSyncTime(float sync_time) { float interval_ratio = fmodf(sync_time, 1.0f); int interval = int(sync_time - interval_ratio); return fmodf( m_interval_start[interval] + m_interval_durations[interval] * interval_ratio, 1.0f); } static SyncTrack Blend(float weight, const SyncTrack& track_A, const SyncTrack& track_B) { assert(track_A.m_num_intervals == track_B.m_num_intervals); SyncTrack result; result.m_num_intervals = track_A.m_num_intervals; result.m_duration = (1.0f - weight) * track_A.m_duration + weight * track_B.m_duration; for (int i = 0; i < result.m_num_intervals; i++) { result.m_interval_durations[i] = (1.0f - weight) * track_A.m_interval_durations[i] + weight * track_B.m_interval_durations[i]; result.m_interval_start[i] = (1.0f - weight) * track_A.m_interval_start[i] + weight * track_B.m_interval_start[i]; result.m_interval_end[i] = (1.0f - weight) * track_A.m_interval_end[i] + weight * track_B.m_interval_end[i]; result.m_sync_markers[i] = (1.0f - weight) * track_A.m_sync_markers[i] + weight * track_B.m_sync_markers[i]; } return result; } }; struct SkinnedMesh { virtual ~SkinnedMesh(); bool LoadSkeleton(const char* filename); bool LoadAnimation(const char* filename); //bool LoadMesh (const char* filename); void SetCurrentAnimation(int index); const ozz::animation::Animation* GetCurrentAnimation() { return m_current_animation; }; float GetCurrentAnimationDuration() { return m_current_animation->duration(); }; void EvalAnimation(float in_time); void DrawSkeleton(); void DrawJoint(int joint_index, int parent_joint_index); void DrawDebugUi(); // void DrawSkinnedMesh(); ozz::vector m_animations; std::vector m_animation_names; std::vector m_animation_sync_track; ozz::animation::Skeleton m_skeleton; ozz::animation::Animation* m_current_animation; ozz::animation::SamplingCache m_cache; ozz::vector m_local_matrices; ozz::vector m_model_matrices; }; #endif //ANIMTESTBED_SKINNEDMESH_H