174 lines
5.1 KiB
C
Raw Normal View History

//
// 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"
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_ratio[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_ratio[0] = 1.f;
2021-11-16 22:57:24 +01:00
} else {
for (i = 0; i < m_num_intervals; i++) {
assert (m_sync_markers[i] >= 0.f && m_sync_markers[i] <= 1.0f);
2021-11-16 22:57:24 +01:00
int end_index = i < m_num_intervals - 1 ? i + 1 : 0;
m_interval_start[i] = m_sync_markers[i];
float interval_end = m_sync_markers[end_index];
2021-11-16 22:57:24 +01:00
if (interval_end < m_interval_start[i]) {
interval_end += 1.0f;
2021-11-16 22:57:24 +01:00
}
m_interval_ratio[i] = interval_end - m_interval_start[i];
2021-11-16 22:57:24 +01:00
}
}
}
float CalcSyncFromAbsTime(float abs_time) {
float sync_time = fmodf(abs_time, m_duration) / m_duration;
int interval_index = 0;
while (sync_time >= m_interval_ratio[interval_index]) {
sync_time -= m_interval_ratio[interval_index];
2021-11-16 22:57:24 +01:00
interval_index++;
}
return float(interval_index) + sync_time / m_interval_ratio[interval_index];
}
2021-11-16 22:57:24 +01:00
float CalcRatioFromSyncTime(float sync_time) {
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_ratio[interval] * interval_ratio,
2021-11-16 22:57:24 +01:00
1.0f);
}
bool operator==(const SyncTrack& other) const {
bool result = m_duration == other.m_duration
&& m_num_intervals == other.m_num_intervals;
if (!result) {
return false;
}
for (int i = 0; i < m_num_intervals; i++) {
if ((fabsf(m_interval_start[i] - other.m_interval_start[i]) > 1.0e-5)
|| (fabsf(m_interval_ratio[i] - other.m_interval_ratio[i])
> 1.0e-5)) {
return false;
}
}
return true;
}
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 22:57:24 +01:00
SyncTrack result;
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;
float interval_0_offset =
track_B.m_interval_start[0] - track_A.m_interval_start[0];
if (interval_0_offset > 0.5f) {
interval_0_offset = -fmodf(1.f - interval_0_offset, 1.0f);
} else if (interval_0_offset < -0.5) {
interval_0_offset = fmodf(1.f + interval_0_offset, 1.0f);
}
2021-11-16 22:57:24 +01:00
result.m_interval_start[0] = fmodf(
1.0 + (1.0f - weight) * track_A.m_interval_start[0]
+ weight * (track_A.m_interval_start[0] + interval_0_offset),
1.0f);
result.m_sync_markers[0] = result.m_interval_start[0];
2021-11-16 22:57:24 +01:00
for (int i = 0; i < result.m_num_intervals; i++) {
float interval_duration_A = track_A.m_interval_ratio[i];
float interval_duration_B = track_B.m_interval_ratio[i];
result.m_interval_ratio[i] =
(1.0f - weight) * interval_duration_A + weight * interval_duration_B;
if (i < cSyncTrackMaxIntervals) {
result.m_interval_start[i + 1] =
result.m_interval_start[i] + result.m_interval_ratio[i];
if (result.m_interval_start[i + 1] > 1.0f) {
result.m_interval_start[i + 1] =
fmodf(result.m_interval_start[i + 1], 1.0f);
}
}
}
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);
2021-11-16 22:57:24 +01:00
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);
2021-11-12 20:10:56 +01:00
void DrawDebugUi();
// void DrawSkinnedMesh();
ozz::vector<ozz::animation::Animation*> m_animations;
std::vector<std::string> m_animation_names;
std::vector<SyncTrack> m_animation_sync_track;
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