Added additional sync track tests.
parent
5e6e81b60b
commit
d006b43d04
|
@ -25,53 +25,90 @@ constexpr int cSyncTrackMaxIntervals = 8;
|
||||||
struct SyncTrack {
|
struct SyncTrack {
|
||||||
float m_duration;
|
float m_duration;
|
||||||
int m_num_intervals;
|
int m_num_intervals;
|
||||||
|
float m_sync_markers[cSyncTrackMaxIntervals];
|
||||||
|
float m_interval_start[cSyncTrackMaxIntervals];
|
||||||
|
float m_interval_end[cSyncTrackMaxIntervals];
|
||||||
float m_interval_durations[cSyncTrackMaxIntervals];
|
float m_interval_durations[cSyncTrackMaxIntervals];
|
||||||
|
|
||||||
float CalcSyncFromAbsTime (float abs_time) {
|
void CalcIntervals() {
|
||||||
float sync_time = fmodf (abs_time, m_duration) / m_duration;
|
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;
|
int interval_index = 0;
|
||||||
while (sync_time >= m_interval_durations[interval_index]) {
|
while (sync_time >= m_interval_durations[interval_index]) {
|
||||||
sync_time -= m_interval_durations[interval_index];
|
sync_time -= m_interval_durations[interval_index];
|
||||||
interval_index ++;
|
interval_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return float(interval_index) + sync_time / m_interval_durations[interval_index];
|
return float(interval_index)
|
||||||
|
+ sync_time / m_interval_durations[interval_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
float CalcRatioFromSyncTime (float sync_time) {
|
float CalcRatioFromSyncTime(float sync_time) {
|
||||||
float interval_ratio = fmodf(sync_time, 1.0f);
|
float interval_ratio = fmodf(sync_time, 1.0f);
|
||||||
int interval = int(sync_time - interval_ratio);
|
int interval = int(sync_time - interval_ratio);
|
||||||
|
|
||||||
float result = 0.f;
|
return fmodf(
|
||||||
int i = 0;
|
m_interval_start[interval]
|
||||||
while (i < interval) {
|
+ m_interval_durations[interval] * interval_ratio,
|
||||||
result += m_interval_durations[i];
|
1.0f);
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result += m_interval_durations[i] * interval_ratio;
|
static SyncTrack
|
||||||
|
Blend(float weight, const SyncTrack& track_A, const SyncTrack& track_B) {
|
||||||
|
assert(track_A.m_num_intervals == track_B.m_num_intervals);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SyncTrack Blend(float weight, const SyncTrack& track_A, const SyncTrack& track_B) {
|
|
||||||
SyncTrack result;
|
SyncTrack result;
|
||||||
|
|
||||||
assert (track_A.m_num_intervals == track_B.m_num_intervals);
|
|
||||||
result.m_num_intervals = track_A.m_num_intervals;
|
result.m_num_intervals = track_A.m_num_intervals;
|
||||||
|
|
||||||
result.m_duration = (1.0f - weight) * track_A.m_duration + weight * track_B.m_duration;
|
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++) {
|
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_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;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SkinnedMesh {
|
struct SkinnedMesh {
|
||||||
virtual ~SkinnedMesh();
|
virtual ~SkinnedMesh();
|
||||||
bool LoadSkeleton(const char* filename);
|
bool LoadSkeleton(const char* filename);
|
||||||
|
@ -79,8 +116,12 @@ struct SkinnedMesh {
|
||||||
//bool LoadMesh (const char* filename);
|
//bool LoadMesh (const char* filename);
|
||||||
|
|
||||||
void SetCurrentAnimation(int index);
|
void SetCurrentAnimation(int index);
|
||||||
const ozz::animation::Animation* GetCurrentAnimation() {return m_current_animation; };
|
const ozz::animation::Animation* GetCurrentAnimation() {
|
||||||
float GetCurrentAnimationDuration() {return m_current_animation->duration(); };
|
return m_current_animation;
|
||||||
|
};
|
||||||
|
float GetCurrentAnimationDuration() {
|
||||||
|
return m_current_animation->duration();
|
||||||
|
};
|
||||||
|
|
||||||
void EvalAnimation(float in_time);
|
void EvalAnimation(float in_time);
|
||||||
void DrawSkeleton();
|
void DrawSkeleton();
|
||||||
|
|
|
@ -2,79 +2,154 @@
|
||||||
// Created by martin on 16.11.21.
|
// Created by martin on 16.11.21.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "SkinnedMesh.h"
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "SkinnedMesh.h"
|
TEST_CASE("Basic", "[SyncTrack]") {
|
||||||
|
|
||||||
TEST_CASE("SyncTrackBlendSimple", "[SyncTrackBlend]") {
|
|
||||||
SyncTrack track_A;
|
SyncTrack track_A;
|
||||||
track_A.m_num_intervals = 2;
|
track_A.m_num_intervals = 2;
|
||||||
track_A.m_duration = 2.0;
|
track_A.m_duration = 2.0;
|
||||||
|
track_A.m_interval_start[0] = 0.f;
|
||||||
|
track_A.m_interval_end[0] = 0.7f;
|
||||||
track_A.m_interval_durations[0] = 0.7;
|
track_A.m_interval_durations[0] = 0.7;
|
||||||
|
track_A.m_interval_start[1] = 0.7f;
|
||||||
|
track_A.m_interval_end[1] = 1.0f;
|
||||||
track_A.m_interval_durations[1] = 0.3;
|
track_A.m_interval_durations[1] = 0.3;
|
||||||
|
|
||||||
SyncTrack track_B;
|
SyncTrack track_B;
|
||||||
track_B.m_num_intervals = 2;
|
track_B.m_num_intervals = 2;
|
||||||
track_B.m_duration = 1.5;
|
track_B.m_duration = 1.5;
|
||||||
|
track_B.m_interval_start[0] = 0.0f;
|
||||||
|
track_B.m_interval_end[0] = 0.6f;
|
||||||
track_B.m_interval_durations[0] = 0.6;
|
track_B.m_interval_durations[0] = 0.6;
|
||||||
|
track_B.m_interval_start[1] = 0.6f;
|
||||||
|
track_B.m_interval_end[1] = 1.0f;
|
||||||
track_B.m_interval_durations[1] = 0.4;
|
track_B.m_interval_durations[1] = 0.4;
|
||||||
|
|
||||||
WHEN ("Calculating sync time of track_B at 0.5 duration") {
|
WHEN("Calculating sync time of track_B at 0.5 duration") {
|
||||||
float sync_time_at_0_75 = track_B.CalcSyncFromAbsTime(0.5 * track_B.m_duration);
|
float sync_time_at_0_75 =
|
||||||
|
track_B.CalcSyncFromAbsTime(0.5 * track_B.m_duration);
|
||||||
REQUIRE(sync_time_at_0_75 == Catch::Detail::Approx(0.83333));
|
REQUIRE(sync_time_at_0_75 == Catch::Detail::Approx(0.83333));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN ("Calculating sync time of track_B at 0.6 duration") {
|
WHEN("Calculating sync time of track_B at 0.6 duration") {
|
||||||
float sync_time_at_0_6 = track_B.CalcSyncFromAbsTime(0.6 * track_B.m_duration);
|
float sync_time_at_0_6 =
|
||||||
|
track_B.CalcSyncFromAbsTime(0.6 * track_B.m_duration);
|
||||||
REQUIRE(sync_time_at_0_6 == Catch::Detail::Approx(1.0));
|
REQUIRE(sync_time_at_0_6 == Catch::Detail::Approx(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN ("Calculating sync time of track_B at 0.7 duration") {
|
WHEN("Calculating sync time of track_B at 0.7 duration") {
|
||||||
float sync_time_at_0_7 = track_B.CalcSyncFromAbsTime(0.7 * track_B.m_duration);
|
float sync_time_at_0_7 =
|
||||||
|
track_B.CalcSyncFromAbsTime(0.7 * track_B.m_duration);
|
||||||
REQUIRE(sync_time_at_0_7 == Catch::Detail::Approx(1.25));
|
REQUIRE(sync_time_at_0_7 == Catch::Detail::Approx(1.25));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN ("Calculating sync time of track_B at 0.0 duration") {
|
WHEN("Calculating sync time of track_B at 0.0 duration") {
|
||||||
float sync_time_at_1_0 = track_B.CalcSyncFromAbsTime(0.0 * track_B.m_duration);
|
float sync_time_at_1_0 =
|
||||||
|
track_B.CalcSyncFromAbsTime(0.0 * track_B.m_duration);
|
||||||
REQUIRE(sync_time_at_1_0 == Catch::Detail::Approx(0.0));
|
REQUIRE(sync_time_at_1_0 == Catch::Detail::Approx(0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN ("Calculating sync time of track_B at 1.0 duration") {
|
WHEN("Calculating sync time of track_B at 1.0 duration") {
|
||||||
float sync_time_at_1_0 = track_B.CalcSyncFromAbsTime(0.9999 * track_B.m_duration);
|
float sync_time_at_1_0 =
|
||||||
|
track_B.CalcSyncFromAbsTime(0.9999 * track_B.m_duration);
|
||||||
REQUIRE(sync_time_at_1_0 == Catch::Detail::Approx(2.0).epsilon(0.001f));
|
REQUIRE(sync_time_at_1_0 == Catch::Detail::Approx(2.0).epsilon(0.001f));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN ("Calculating ratio from sync time on track_A at 0.83333") {
|
WHEN("Calculating ratio from sync time on track_A at 0.83333") {
|
||||||
float ratio = track_A.CalcRatioFromSyncTime(0.83333333);
|
float ratio = track_A.CalcRatioFromSyncTime(0.83333333);
|
||||||
REQUIRE (ratio == Catch::Detail::Approx(0.5833333));
|
REQUIRE(ratio == Catch::Detail::Approx(0.5833333));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN ("Calculating ratio from sync time on track_A at 0.83333") {
|
WHEN("Calculating ratio from sync time on track_A at 0.83333") {
|
||||||
float ratio = track_A.CalcRatioFromSyncTime(1.25);
|
float ratio = track_A.CalcRatioFromSyncTime(1.25);
|
||||||
REQUIRE (ratio == Catch::Detail::Approx(0.775));
|
REQUIRE(ratio == Catch::Detail::Approx(0.775));
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN("Blending two synctracks with weight 0.") {
|
WHEN("Blending two synctracks with weight 0.") {
|
||||||
SyncTrack blended = SyncTrack::Blend(0.f, track_A, track_B);
|
SyncTrack blended = SyncTrack::Blend(0.f, track_A, track_B);
|
||||||
|
|
||||||
THEN ("Result must equal track_A") {
|
THEN("Result must equal track_A") {
|
||||||
REQUIRE(blended.m_duration == track_A.m_duration);
|
REQUIRE(blended.m_duration == track_A.m_duration);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
blended.m_interval_durations[0] == track_A.m_interval_durations[0]);
|
blended.m_interval_durations[0] == track_A.m_interval_durations[0]);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
blended.m_interval_durations[1] == track_A.m_interval_durations[1]);
|
blended.m_interval_durations[1] == track_A.m_interval_durations[1]);
|
||||||
|
|
||||||
|
REQUIRE(blended.m_sync_markers[0] == track_A.m_sync_markers[0]);
|
||||||
|
REQUIRE(blended.m_sync_markers[1] == track_A.m_sync_markers[1]);
|
||||||
|
|
||||||
|
REQUIRE(blended.m_interval_start[0] == track_A.m_interval_start[0]);
|
||||||
|
REQUIRE(blended.m_interval_start[1] == track_A.m_interval_start[1]);
|
||||||
|
|
||||||
|
REQUIRE(blended.m_interval_end[0] == track_A.m_interval_end[0]);
|
||||||
|
REQUIRE(blended.m_interval_end[1] == track_A.m_interval_end[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WHEN("Blending two synctracks with weight 1.") {
|
WHEN("Blending two synctracks with weight 1.") {
|
||||||
SyncTrack blended = SyncTrack::Blend(1.f, track_A, track_B);
|
SyncTrack blended = SyncTrack::Blend(1.f, track_A, track_B);
|
||||||
|
|
||||||
THEN ("Result must equal track_B") {
|
THEN("Result must equal track_B") {
|
||||||
REQUIRE(blended.m_duration == track_B.m_duration);
|
REQUIRE(blended.m_duration == track_B.m_duration);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
blended.m_interval_durations[0] == track_B.m_interval_durations[0]);
|
blended.m_interval_durations[0] == track_B.m_interval_durations[0]);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
blended.m_interval_durations[1] == track_B.m_interval_durations[1]);
|
blended.m_interval_durations[1] == track_B.m_interval_durations[1]);
|
||||||
|
|
||||||
|
REQUIRE(blended.m_sync_markers[0] == track_B.m_sync_markers[0]);
|
||||||
|
REQUIRE(blended.m_sync_markers[1] == track_B.m_sync_markers[1]);
|
||||||
|
|
||||||
|
REQUIRE(blended.m_interval_start[0] == track_B.m_interval_start[0]);
|
||||||
|
REQUIRE(blended.m_interval_start[1] == track_B.m_interval_start[1]);
|
||||||
|
|
||||||
|
REQUIRE(blended.m_interval_end[0] == track_B.m_interval_end[0]);
|
||||||
|
REQUIRE(blended.m_interval_end[1] == track_B.m_interval_end[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Sync Marker Interval Calculation", "[SyncTrack]") {
|
||||||
|
SyncTrack track_A;
|
||||||
|
track_A.m_num_intervals = 2;
|
||||||
|
track_A.m_duration = 2.0;
|
||||||
|
track_A.m_sync_markers[0] = 0.9;
|
||||||
|
track_A.m_sync_markers[1] = 0.2;
|
||||||
|
|
||||||
|
WHEN("Calculating intervals") {
|
||||||
|
track_A.CalcIntervals();
|
||||||
|
|
||||||
|
CHECK(track_A.m_interval_start[0] == 0.9f);
|
||||||
|
CHECK(track_A.m_interval_end[0] == 0.2f);
|
||||||
|
CHECK(track_A.m_interval_durations[0] == 0.3f);
|
||||||
|
|
||||||
|
CHECK(track_A.m_interval_start[1] == 0.2f);
|
||||||
|
CHECK(track_A.m_interval_end[1] == 0.9f);
|
||||||
|
CHECK(track_A.m_interval_durations[1] == 0.7f);
|
||||||
|
|
||||||
|
WHEN("Querying ratio at sync time at 1.001") {
|
||||||
|
float ratio = track_A.CalcRatioFromSyncTime(1.0001f);
|
||||||
|
CHECK(ratio == Catch::Detail::Approx(0.2).epsilon(0.001));
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Querying ratio at sync time at 1.001") {
|
||||||
|
float ratio = track_A.CalcRatioFromSyncTime(0.0001f);
|
||||||
|
CHECK(ratio == Catch::Detail::Approx(0.9).epsilon(0.001));
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN("Querying ratio at sync time at 1.9999") {
|
||||||
|
float ratio = track_A.CalcRatioFromSyncTime(0.9999f);
|
||||||
|
CHECK(ratio == Catch::Detail::Approx(0.2).epsilon(0.001));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WHEN ("Blending with another sync track") {
|
||||||
|
SyncTrack track_B;
|
||||||
|
track_B.m_num_intervals = 2;
|
||||||
|
track_B.m_duration = 1.0;
|
||||||
|
track_B.m_sync_markers[0] = 0.9;
|
||||||
|
track_B.m_sync_markers[1] = 0.2;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue