2021-11-12 12:48:56 +01:00
|
|
|
//
|
|
|
|
// Created by martin on 12.11.21.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef ANIMTESTBED_SKINNEDMESH_H
|
|
|
|
#define ANIMTESTBED_SKINNEDMESH_H
|
|
|
|
|
|
|
|
// ozz-animation headers
|
|
|
|
#include <cmath> // fmodf
|
|
|
|
#include <memory> // 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"
|
|
|
|
|
2021-11-16 18:15:56 +01:00
|
|
|
constexpr int cSyncTrackMaxIntervals = 8;
|
|
|
|
|
|
|
|
struct SyncTrack {
|
|
|
|
float m_duration;
|
|
|
|
int m_num_intervals;
|
2021-11-16 22:57:24 +01:00
|
|
|
float m_sync_markers[cSyncTrackMaxIntervals];
|
|
|
|
float m_interval_start[cSyncTrackMaxIntervals];
|
|
|
|
float m_interval_end[cSyncTrackMaxIntervals];
|
2021-11-16 18:15:56 +01:00
|
|
|
float m_interval_durations[cSyncTrackMaxIntervals];
|
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
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;
|
2021-11-16 18:15:56 +01:00
|
|
|
|
|
|
|
int interval_index = 0;
|
2021-11-16 20:14:22 +01:00
|
|
|
while (sync_time >= m_interval_durations[interval_index]) {
|
2021-11-16 18:15:56 +01:00
|
|
|
sync_time -= m_interval_durations[interval_index];
|
2021-11-16 22:57:24 +01:00
|
|
|
interval_index++;
|
2021-11-16 18:15:56 +01:00
|
|
|
}
|
2021-11-16 20:14:22 +01:00
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
return float(interval_index)
|
|
|
|
+ sync_time / m_interval_durations[interval_index];
|
2021-11-16 20:14:22 +01:00
|
|
|
}
|
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
float CalcRatioFromSyncTime(float sync_time) {
|
2021-11-16 20:14:22 +01:00
|
|
|
float interval_ratio = fmodf(sync_time, 1.0f);
|
|
|
|
int interval = int(sync_time - interval_ratio);
|
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
return fmodf(
|
|
|
|
m_interval_start[interval]
|
|
|
|
+ m_interval_durations[interval] * interval_ratio,
|
|
|
|
1.0f);
|
2021-11-16 18:15:56 +01:00
|
|
|
}
|
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
static SyncTrack
|
|
|
|
Blend(float weight, const SyncTrack& track_A, const SyncTrack& track_B) {
|
|
|
|
assert(track_A.m_num_intervals == track_B.m_num_intervals);
|
2021-11-16 18:15:56 +01:00
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
SyncTrack result;
|
2021-11-16 18:15:56 +01:00
|
|
|
result.m_num_intervals = track_A.m_num_intervals;
|
|
|
|
|
2021-11-16 22:57:24 +01:00
|
|
|
result.m_duration =
|
|
|
|
(1.0f - weight) * track_A.m_duration + weight * track_B.m_duration;
|
2021-11-16 18:15:56 +01:00
|
|
|
|
|
|
|
for (int i = 0; i < result.m_num_intervals; i++) {
|
2021-11-16 22:57:24 +01:00
|
|
|
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];
|
2021-11-16 18:15:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-11-12 12:48:56 +01:00
|
|
|
struct SkinnedMesh {
|
|
|
|
virtual ~SkinnedMesh();
|
|
|
|
bool LoadSkeleton(const char* filename);
|
|
|
|
bool LoadAnimation(const char* filename);
|
|
|
|
//bool LoadMesh (const char* filename);
|
|
|
|
|
|
|
|
void SetCurrentAnimation(int index);
|
2021-11-16 22:57:24 +01:00
|
|
|
const ozz::animation::Animation* GetCurrentAnimation() {
|
|
|
|
return m_current_animation;
|
|
|
|
};
|
|
|
|
float GetCurrentAnimationDuration() {
|
|
|
|
return m_current_animation->duration();
|
|
|
|
};
|
2021-11-12 12:48:56 +01:00
|
|
|
|
|
|
|
void EvalAnimation(float in_time);
|
|
|
|
void DrawSkeleton();
|
|
|
|
void DrawJoint(int joint_index, int parent_joint_index);
|
|
|
|
|
2021-11-12 20:10:56 +01:00
|
|
|
void DrawDebugUi();
|
2021-11-12 12:48:56 +01:00
|
|
|
// void DrawSkinnedMesh();
|
|
|
|
|
|
|
|
ozz::vector<ozz::animation::Animation*> m_animations;
|
|
|
|
std::vector<std::string> m_animation_names;
|
2021-11-16 18:15:56 +01:00
|
|
|
std::vector<SyncTrack> m_animation_sync_track;
|
2021-11-12 12:48:56 +01:00
|
|
|
ozz::animation::Skeleton m_skeleton;
|
|
|
|
ozz::animation::Animation* m_current_animation;
|
|
|
|
ozz::animation::SamplingCache m_cache;
|
|
|
|
ozz::vector<ozz::math::SoaTransform> m_local_matrices;
|
|
|
|
ozz::vector<ozz::math::Float4x4> m_model_matrices;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif //ANIMTESTBED_SKINNEDMESH_H
|