Compare commits
2 Commits
c173707a18
...
36c7f7a11e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
36c7f7a11e | ||
![]() |
3b5537fc9d |
@ -129,7 +129,7 @@ struct AnimGraphBlendTree : public AnimNode {
|
||||
*
|
||||
* @tparam T Type of the Socket.
|
||||
* @param name Name of the Socket.
|
||||
* @param value_ptr Pointer where the graph output output is written to at the end of evaluation.
|
||||
* @param value_ptr Pointer where the graph output is written to at the end of evaluation.
|
||||
*/
|
||||
template <typename T>
|
||||
void SetOutput(const char* name, T* value_ptr) {
|
||||
|
@ -380,11 +380,6 @@ struct NodeDescriptorBase {
|
||||
*socket->m_reference.ptr_ptr = value_ptr;
|
||||
}
|
||||
|
||||
void SetOutputUnchecked(const char* name, void* value_ptr) {
|
||||
Socket* socket = FindSocket(name, m_outputs);
|
||||
*socket->m_reference.ptr_ptr = value_ptr;
|
||||
}
|
||||
|
||||
Socket* GetOutputSocket(const char* name) const {
|
||||
return FindSocket(name, m_outputs);
|
||||
}
|
||||
|
41
src/Camera.c
41
src/Camera.c
@ -42,8 +42,8 @@ inline void Camera_Init(Camera* camera) {
|
||||
camera->pitch = 10 * M_PI / 180.0f;
|
||||
|
||||
memcpy(&camera->mtxView, &mtx_identity, sizeof(camera->mtxView));
|
||||
Camera_CalcToMatrix(camera, &camera->mtxView);
|
||||
Camera_CalcFromMatrix(camera, &camera->mtxView);
|
||||
Camera_CalcToMatrix(camera, &camera->mtxView[0]);
|
||||
Camera_CalcFromMatrix(camera, &camera->mtxView[0]);
|
||||
}
|
||||
|
||||
void Camera_CalcFromMatrix(Camera* camera, float* mat) {
|
||||
@ -72,11 +72,11 @@ void Camera_CalcFromMatrix(Camera* camera, float* mat) {
|
||||
camera->pos[1] = -simd4f_get_y(eye);
|
||||
camera->pos[2] = -simd4f_get_z(eye);
|
||||
|
||||
// gLog ("ViewMat");
|
||||
// gLog ("%f, %f, %f, %f", mtx->x[0], mtx->x[1], mtx->x[2], mtx->x[3]);
|
||||
// gLog ("%f, %f, %f, %f", mtx->y[0], mtx->y[1], mtx->y[2], mtx->y[3]);
|
||||
// gLog ("%f, %f, %f, %f", mtx->z[0], mtx->z[1], mtx->z[2], mtx->z[3]);
|
||||
// gLog ("%f, %f, %f, %f", mtx->w[0], mtx->w[1], mtx->w[2], mtx->w[3]);
|
||||
// gLog ("ViewMat");
|
||||
// gLog ("%f, %f, %f, %f", mtx->x[0], mtx->x[1], mtx->x[2], mtx->x[3]);
|
||||
// gLog ("%f, %f, %f, %f", mtx->y[0], mtx->y[1], mtx->y[2], mtx->y[3]);
|
||||
// gLog ("%f, %f, %f, %f", mtx->z[0], mtx->z[1], mtx->z[2], mtx->z[3]);
|
||||
// gLog ("%f, %f, %f, %f", mtx->w[0], mtx->w[1], mtx->w[2], mtx->w[3]);
|
||||
}
|
||||
|
||||
void Camera_CalcToMatrix(Camera* camera, float* mat) {
|
||||
@ -87,9 +87,10 @@ void Camera_CalcToMatrix(Camera* camera, float* mat) {
|
||||
|
||||
const float d = 10.0f;
|
||||
|
||||
simd4f eye = simd4f_create (camera->pos[0], camera->pos[1], camera->pos[2], 1.f);
|
||||
simd4f forward = simd4f_create (-cp * ch, -sp, cp * sh, 0.f);
|
||||
simd4f right = simd4f_cross3 (forward, simd4f_create (0.f, 1.f, 0.f, 1.f));
|
||||
simd4f eye =
|
||||
simd4f_create(camera->pos[0], camera->pos[1], camera->pos[2], 1.f);
|
||||
simd4f forward = simd4f_create(-cp * ch, -sp, cp * sh, 0.f);
|
||||
simd4f right = simd4f_cross3(forward, simd4f_create(0.f, 1.f, 0.f, 1.f));
|
||||
simd4f up = simd4f_cross3(right, forward);
|
||||
simd4f center = simd4f_add(simd4f_mul(forward, simd4f_splat(d)), eye);
|
||||
|
||||
@ -105,9 +106,9 @@ void Camera_CalcToMatrix(Camera* camera, float* mat) {
|
||||
simd4x4f_lookat(&mtx, eye, center, up);
|
||||
|
||||
simd4f_ustore4(mtx.x, mat);
|
||||
simd4f_ustore4(mtx.y, mat +4);
|
||||
simd4f_ustore4(mtx.z, mat +8);
|
||||
simd4f_ustore4(mtx.w, mat +12);
|
||||
simd4f_ustore4(mtx.y, mat + 4);
|
||||
simd4f_ustore4(mtx.z, mat + 8);
|
||||
simd4f_ustore4(mtx.w, mat + 12);
|
||||
}
|
||||
|
||||
inline void Camera_Update(
|
||||
@ -120,14 +121,14 @@ inline void Camera_Update(
|
||||
float accel[3]) {
|
||||
assert(camera);
|
||||
assert((width > 0) && (height > 0));
|
||||
const float w = (float) width;
|
||||
const float h = (float) height;
|
||||
const float w = (float)width;
|
||||
const float h = (float)height;
|
||||
simd4x4f proj;
|
||||
simd4x4f_perspective(&proj, camera->fov, w/h, camera->near, camera->far);
|
||||
simd4x4f_perspective(&proj, camera->fov, w / h, camera->near, camera->far);
|
||||
simd4f_ustore4(proj.x, camera->mtxProj);
|
||||
simd4f_ustore4(proj.y, camera->mtxProj +4);
|
||||
simd4f_ustore4(proj.z, camera->mtxProj +8);
|
||||
simd4f_ustore4(proj.w, camera->mtxProj +12);
|
||||
simd4f_ustore4(proj.y, camera->mtxProj + 4);
|
||||
simd4f_ustore4(proj.z, camera->mtxProj + 8);
|
||||
simd4f_ustore4(proj.w, camera->mtxProj + 12);
|
||||
|
||||
if (mouse_dx != 0.f || mouse_dy != 0.f || accel != NULL) {
|
||||
const float mouse_sensitivity = 20.0f;
|
||||
@ -153,6 +154,6 @@ inline void Camera_Update(
|
||||
camera->vel[i] = camera->vel[i] * 0.1;
|
||||
}
|
||||
|
||||
Camera_CalcToMatrix(camera, &camera->mtxView);
|
||||
Camera_CalcToMatrix(camera, &camera->mtxView[0]);
|
||||
}
|
||||
}
|
177
src/SyncTrack.h
177
src/SyncTrack.h
@ -6,57 +6,62 @@
|
||||
#define ANIMTESTBED_SYNCTRACK_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "3rdparty/json/json.hpp"
|
||||
|
||||
constexpr int cSyncTrackMaxIntervals = 8;
|
||||
|
||||
/// Metadata used for synced animation blending.
|
||||
//
|
||||
// A SyncTrack consists of multiple SyncInterval that are adjacent to each
|
||||
// other.
|
||||
//
|
||||
// Important definitions:
|
||||
//
|
||||
// - Absolute Time: time within an animation duration in seconds.
|
||||
// - Ratio: time relative to the animations duration, e.g. 0.5 corresponds to
|
||||
// 50% of the duration.
|
||||
// - SyncTime is a floating point value where the integer parts defines the
|
||||
// SyncInterval and the fractional part the fraction within the interval. I.e.
|
||||
// a SyncTime of 5.332 means it is ~33% through interval 5.
|
||||
//
|
||||
// A SyncInterval is defined by a ratio of the starting point and the ratio of
|
||||
// the interval's duration.
|
||||
struct SyncTrack {
|
||||
SyncTrack() : m_duration(0.f), m_num_intervals(0) {
|
||||
SyncTrack() : m_duration(0.f), m_num_intervals(1) {
|
||||
for (int i = 0; i < cSyncTrackMaxIntervals; i++) {
|
||||
m_sync_markers[i] = 0.f;
|
||||
m_interval_ratio[i] = 0.f;
|
||||
m_interval_ratio[i] = 0.f;
|
||||
m_interval_start_ratio[i] = 0.f;
|
||||
m_interval_duration_ratio[i] = 0.f;
|
||||
}
|
||||
|
||||
m_interval_duration_ratio[0] = 1.0f;
|
||||
}
|
||||
|
||||
float m_duration;
|
||||
int m_num_intervals;
|
||||
float m_sync_markers[cSyncTrackMaxIntervals];
|
||||
float m_interval_start[cSyncTrackMaxIntervals];
|
||||
float m_interval_ratio[cSyncTrackMaxIntervals];
|
||||
|
||||
void CalcIntervals() {
|
||||
if (m_num_intervals == 0) {
|
||||
m_num_intervals = 1;
|
||||
m_sync_markers[0] = 0.f;
|
||||
}
|
||||
for (int i = 0; i < m_num_intervals; i++) {
|
||||
assert(m_sync_markers[i] >= 0.f && m_sync_markers[i] <= 1.0f);
|
||||
|
||||
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];
|
||||
|
||||
if (interval_end < m_interval_start[i]) {
|
||||
interval_end += 1.0f;
|
||||
}
|
||||
|
||||
m_interval_ratio[i] = interval_end - m_interval_start[i];
|
||||
}
|
||||
}
|
||||
float m_interval_start_ratio
|
||||
[cSyncTrackMaxIntervals]; //< Starting time of interval in absolute time.
|
||||
float m_interval_duration_ratio[cSyncTrackMaxIntervals]; //<
|
||||
|
||||
float CalcSyncFromAbsTime(float abs_time) {
|
||||
float sync_time = fmodf(abs_time, m_duration) / m_duration;
|
||||
for (int i = 0; i < m_num_intervals; i++) {
|
||||
float query_abs_time = abs_time;
|
||||
float interval_start = m_interval_start_ratio[i] * m_duration;
|
||||
float interval_end =
|
||||
interval_start + m_interval_duration_ratio[i] * m_duration;
|
||||
|
||||
int interval_index = 0;
|
||||
while (sync_time >= m_interval_ratio[interval_index]) {
|
||||
sync_time -= m_interval_ratio[interval_index];
|
||||
interval_index++;
|
||||
if (query_abs_time < interval_start) {
|
||||
query_abs_time += m_duration;
|
||||
}
|
||||
if (query_abs_time >= interval_start && query_abs_time < interval_end) {
|
||||
return float(i)
|
||||
+ (query_abs_time - interval_start)
|
||||
/ (interval_end - interval_start);
|
||||
}
|
||||
}
|
||||
|
||||
return float(interval_index) + sync_time / m_interval_ratio[interval_index];
|
||||
assert(false && "Invalid absolute time");
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
float CalcRatioFromSyncTime(float sync_time) {
|
||||
@ -64,8 +69,8 @@ struct SyncTrack {
|
||||
int interval = int(sync_time - interval_ratio);
|
||||
|
||||
return fmodf(
|
||||
m_interval_start[interval]
|
||||
+ m_interval_ratio[interval] * interval_ratio,
|
||||
m_interval_start_ratio[interval]
|
||||
+ m_interval_duration_ratio[interval] * interval_ratio,
|
||||
1.0f);
|
||||
}
|
||||
|
||||
@ -78,8 +83,11 @@ struct SyncTrack {
|
||||
}
|
||||
|
||||
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])
|
||||
if ((fabsf(m_interval_start_ratio[i] - other.m_interval_start_ratio[i])
|
||||
> 1.0e-5)
|
||||
|| (fabsf(
|
||||
m_interval_duration_ratio[i]
|
||||
- other.m_interval_duration_ratio[i])
|
||||
> 1.0e-5)) {
|
||||
return false;
|
||||
}
|
||||
@ -88,18 +96,40 @@ struct SyncTrack {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Constructs SyncTrack from markers.
|
||||
*
|
||||
* Markers are specified in absolute time and must be >= 0 and <= duration.
|
||||
* They define the start of the interval. The last marker is implicitly the
|
||||
* (possibly looped) first marker.
|
||||
*/
|
||||
static SyncTrack CreateFromMarkers(
|
||||
float duration,
|
||||
int n_markers,
|
||||
float markers[cSyncTrackMaxIntervals]) {
|
||||
const std::vector<float>& markers) {
|
||||
assert(markers.size() > 0);
|
||||
assert(markers.size() < cSyncTrackMaxIntervals);
|
||||
|
||||
SyncTrack result;
|
||||
result.m_duration = duration;
|
||||
result.m_num_intervals = n_markers;
|
||||
for (int i = 0; i < n_markers; i++) {
|
||||
result.m_sync_markers[i] = markers[i];
|
||||
}
|
||||
result.m_num_intervals = markers.size();
|
||||
|
||||
result.CalcIntervals();
|
||||
for (int i = 0; i < markers.size(); i++) {
|
||||
assert(markers[i] >= 0.f && markers[i] <= duration);
|
||||
|
||||
int end_index = i == (markers.size() - 1) ? 0 : i + 1;
|
||||
|
||||
float interval_start = markers[i];
|
||||
float interval_end = markers[end_index];
|
||||
|
||||
if (interval_end == interval_start) {
|
||||
interval_end = interval_start + duration;
|
||||
} else if (interval_end < interval_start) {
|
||||
interval_end += duration;
|
||||
}
|
||||
|
||||
result.m_interval_start_ratio[i] = interval_start / duration;
|
||||
result.m_interval_duration_ratio[i] =
|
||||
(interval_end - interval_start) / duration;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -115,41 +145,62 @@ struct SyncTrack {
|
||||
(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];
|
||||
track_B.m_interval_start_ratio[0] - track_A.m_interval_start_ratio[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);
|
||||
}
|
||||
|
||||
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),
|
||||
result.m_interval_start_ratio[0] = fmodf(
|
||||
1.0 + (1.0f - weight) * track_A.m_interval_start_ratio[0]
|
||||
+ weight * (track_A.m_interval_start_ratio[0] + interval_0_offset),
|
||||
1.0f);
|
||||
result.m_sync_markers[0] = result.m_interval_start[0];
|
||||
|
||||
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] =
|
||||
float interval_duration_A = track_A.m_interval_duration_ratio[i];
|
||||
float interval_duration_B = track_B.m_interval_duration_ratio[i];
|
||||
result.m_interval_duration_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);
|
||||
result.m_interval_start_ratio[i + 1] =
|
||||
result.m_interval_start_ratio[i]
|
||||
+ result.m_interval_duration_ratio[i];
|
||||
if (result.m_interval_start_ratio[i + 1] > 1.0f) {
|
||||
result.m_interval_start_ratio[i + 1] =
|
||||
fmodf(result.m_interval_start_ratio[i + 1], 1.0f);
|
||||
}
|
||||
|
||||
result.m_sync_markers[i + 1] = result.m_interval_start[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
assert (result.m_num_intervals < cSyncTrackMaxIntervals);
|
||||
assert(result.m_num_intervals < cSyncTrackMaxIntervals);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
inline void to_json(nlohmann::json& j, const SyncTrack& sync_track) {
|
||||
j["type"] = "SyncTrack";
|
||||
j["duration"] = sync_track.m_duration;
|
||||
for (int i = 0; i < sync_track.m_num_intervals; i++) {
|
||||
j["interval"][i]["start"] = sync_track.m_interval_start_ratio[i];
|
||||
j["interval"][i]["ratio"] = sync_track.m_interval_duration_ratio[i];
|
||||
}
|
||||
}
|
||||
|
||||
inline void from_json(const nlohmann::json& j, SyncTrack& sync_track) {
|
||||
assert(j["type"] == "SyncTrack");
|
||||
|
||||
sync_track.m_duration = j["duration"];
|
||||
|
||||
sync_track.m_num_intervals = j["interval"].size();
|
||||
assert(sync_track.m_num_intervals < cSyncTrackMaxIntervals);
|
||||
|
||||
for (int i = 0; i < sync_track.m_num_intervals; i++) {
|
||||
sync_track.m_interval_start_ratio[i] = j["interval"][i]["start"];
|
||||
sync_track.m_interval_duration_ratio[i] = j["interval"][i]["ratio"];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ANIMTESTBED_SYNCTRACK_H
|
||||
|
@ -175,10 +175,6 @@ TEST_CASE_METHOD(
|
||||
AnimNodeResource* blend_node = blend_tree_resource->GetNode(blend_node_index);
|
||||
blend_node->m_name = "BlendWalkRun";
|
||||
|
||||
// Setup graph outputs and inputs
|
||||
AnimNodeResource* graph_output_node =
|
||||
blend_tree_resource->GetGraphOutputNode();
|
||||
|
||||
blend_tree_resource->RegisterBlendTreeInputSocket<float>("GraphFloatInput");
|
||||
|
||||
// Wire up nodes
|
||||
|
@ -6,197 +6,228 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE("Basic", "[SyncTrack]") {
|
||||
SyncTrack track_A;
|
||||
track_A.m_num_intervals = 2;
|
||||
track_A.m_duration = 2.0;
|
||||
track_A.m_interval_start[0] = 0.f;
|
||||
track_A.m_interval_ratio[0] = 0.7;
|
||||
track_A.m_interval_start[1] = 0.7f;
|
||||
track_A.m_interval_ratio[1] = 0.3;
|
||||
SyncTrack track_a;
|
||||
track_a.m_num_intervals = 2;
|
||||
track_a.m_duration = 2.0;
|
||||
track_a.m_interval_start_ratio[0] = 0.f;
|
||||
track_a.m_interval_duration_ratio[0] = 0.7;
|
||||
track_a.m_interval_start_ratio[1] = 0.7f;
|
||||
track_a.m_interval_duration_ratio[1] = 0.3;
|
||||
|
||||
SyncTrack track_B;
|
||||
track_B.m_num_intervals = 2;
|
||||
track_B.m_duration = 1.5;
|
||||
track_B.m_interval_start[0] = 0.0f;
|
||||
track_B.m_interval_ratio[0] = 0.6;
|
||||
track_B.m_interval_start[1] = 0.6f;
|
||||
track_B.m_interval_ratio[1] = 0.4;
|
||||
SyncTrack track_b;
|
||||
track_b.m_num_intervals = 2;
|
||||
track_b.m_duration = 1.5;
|
||||
track_b.m_interval_start_ratio[0] = 0.0f;
|
||||
track_b.m_interval_duration_ratio[0] = 0.6;
|
||||
track_b.m_interval_start_ratio[1] = 0.6f;
|
||||
track_b.m_interval_duration_ratio[1] = 0.4;
|
||||
|
||||
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);
|
||||
track_b.CalcSyncFromAbsTime(0.5 * track_b.m_duration);
|
||||
REQUIRE(sync_time_at_0_75 == Catch::Detail::Approx(0.83333));
|
||||
}
|
||||
|
||||
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);
|
||||
track_b.CalcSyncFromAbsTime(0.6 * track_b.m_duration);
|
||||
REQUIRE(sync_time_at_0_6 == Catch::Detail::Approx(1.0));
|
||||
}
|
||||
|
||||
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);
|
||||
track_b.CalcSyncFromAbsTime(0.7 * track_b.m_duration);
|
||||
REQUIRE(sync_time_at_0_7 == Catch::Detail::Approx(1.25));
|
||||
}
|
||||
|
||||
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);
|
||||
track_b.CalcSyncFromAbsTime(0.0 * track_b.m_duration);
|
||||
REQUIRE(sync_time_at_1_0 == Catch::Detail::Approx(0.0));
|
||||
}
|
||||
|
||||
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);
|
||||
track_b.CalcSyncFromAbsTime(0.9999 * track_b.m_duration);
|
||||
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") {
|
||||
float ratio = track_A.CalcRatioFromSyncTime(0.83333333);
|
||||
float ratio = track_a.CalcRatioFromSyncTime(0.83333333);
|
||||
REQUIRE(ratio == Catch::Detail::Approx(0.5833333));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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") { REQUIRE(track_A == blended); }
|
||||
THEN("Result must equal track_A") { REQUIRE(track_a == blended); }
|
||||
}
|
||||
|
||||
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") { REQUIRE(track_B == blended); }
|
||||
THEN("Result must equal track_B") { REQUIRE(track_b == blended); }
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
TEST_CASE("Sync Track From Marker", "[SyncTrack]") {
|
||||
SyncTrack track = SyncTrack::CreateFromMarkers(2.0f, {0.9f, 0.2f});
|
||||
|
||||
WHEN("Calculating intervals") {
|
||||
track_A.CalcIntervals();
|
||||
WHEN("Querying Ratios") {
|
||||
CHECK(track.m_interval_start_ratio[0] == Catch::Detail::Approx(0.45f));
|
||||
CHECK(track.m_interval_duration_ratio[0] == Catch::Detail::Approx(0.65f));
|
||||
|
||||
CHECK(track_A.m_interval_start[0] == Catch::Detail::Approx(0.9f));
|
||||
CHECK(track_A.m_interval_ratio[0] == Catch::Detail::Approx(0.3f));
|
||||
CHECK(track.m_interval_start_ratio[1] == Catch::Detail::Approx(0.1f));
|
||||
CHECK(track.m_interval_duration_ratio[1] == Catch::Detail::Approx(0.35f));
|
||||
|
||||
CHECK(track_A.m_interval_start[1] == Catch::Detail::Approx(0.2f));
|
||||
CHECK(track_A.m_interval_ratio[1] == Catch::Detail::Approx(0.7f));
|
||||
WHEN("Querying ratio at sync time at 0.001") {
|
||||
float ratio = track.CalcRatioFromSyncTime(0.0001f);
|
||||
CHECK(ratio == Catch::Detail::Approx(0.45).epsilon(0.001));
|
||||
}
|
||||
|
||||
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 0.9999") {
|
||||
float ratio = track.CalcRatioFromSyncTime(0.9999f);
|
||||
CHECK(ratio == Catch::Detail::Approx(0.1).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));
|
||||
float ratio = track.CalcRatioFromSyncTime(1.0001f);
|
||||
CHECK(ratio == Catch::Detail::Approx(0.1).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));
|
||||
float ratio = track.CalcRatioFromSyncTime(1.9999f);
|
||||
CHECK(ratio == Catch::Detail::Approx(0.45).epsilon(0.001));
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("Blending sync track with 3 events") {
|
||||
track_A.m_num_intervals = 3;
|
||||
track_A.m_duration = 2.0;
|
||||
track_A.m_sync_markers[0] = 0.;
|
||||
track_A.m_sync_markers[1] = 0.3;
|
||||
track_A.m_sync_markers[2] = 0.9;
|
||||
track_A.CalcIntervals();
|
||||
|
||||
SyncTrack track_B;
|
||||
track_B.m_num_intervals = 3;
|
||||
track_B.m_duration = 1.5;
|
||||
track_B.m_sync_markers[0] = 0.7;
|
||||
track_B.m_sync_markers[1] = 0.9;
|
||||
track_B.m_sync_markers[2] = 0.2;
|
||||
track_B.CalcIntervals();
|
||||
|
||||
WHEN("Calculating A's durations") {
|
||||
CHECK(track_A.m_interval_ratio[0] == Catch::Detail::Approx(0.3));
|
||||
CHECK(track_A.m_interval_ratio[1] == Catch::Detail::Approx(0.6));
|
||||
CHECK(track_A.m_interval_ratio[2] == Catch::Detail::Approx(0.1));
|
||||
WHEN("Querying SyncTime from Absolute Time") {
|
||||
WHEN("Querying absolute time at 0.9001s") {
|
||||
float sync_time = track.CalcSyncFromAbsTime(0.9001f);
|
||||
CHECK_THAT(sync_time, Catch::WithinAbs(0.0, 0.001));
|
||||
}
|
||||
|
||||
WHEN("Calculating B's durations") {
|
||||
CHECK(track_B.m_interval_ratio[0] == Catch::Detail::Approx(0.2));
|
||||
CHECK(track_B.m_interval_ratio[1] == Catch::Detail::Approx(0.3));
|
||||
CHECK(track_B.m_interval_ratio[2] == Catch::Detail::Approx(0.5));
|
||||
WHEN("Querying absolute time at 0.2001s") {
|
||||
float sync_time = track.CalcSyncFromAbsTime(0.2001f);
|
||||
CHECK_THAT(sync_time, Catch::WithinAbs(1.0, 0.001));
|
||||
}
|
||||
|
||||
WHEN("Blending two synctracks with weight 0.") {
|
||||
SyncTrack blended = SyncTrack::Blend(0.f, track_A, track_B);
|
||||
|
||||
THEN("Result must equal track_A") { REQUIRE(track_A == blended); }
|
||||
WHEN("Querying absolute time at 0.8999s") {
|
||||
float sync_time = track.CalcSyncFromAbsTime(0.8999f);
|
||||
CHECK_THAT(sync_time, Catch::WithinAbs(1.999, 0.001));
|
||||
}
|
||||
|
||||
WHEN("Blending two synctracks with weight 1.") {
|
||||
SyncTrack blended = SyncTrack::Blend(1.f, track_A, track_B);
|
||||
|
||||
THEN("Result must equal track_B") { REQUIRE(track_B == blended); }
|
||||
WHEN("Querying absolute time at 1.9999s") {
|
||||
float sync_time = track.CalcSyncFromAbsTime(1.9999f);
|
||||
CHECK_THAT(sync_time, Catch::WithinAbs(0.84615384, 0.001));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("Blending with weight 0.2") {
|
||||
float weight = 0.2f;
|
||||
SyncTrack blended = SyncTrack::Blend(weight, track_A, track_B);
|
||||
TEST_CASE("Sync Track Blending", "[SyncTrack]") {
|
||||
SyncTrack track_a = SyncTrack::CreateFromMarkers(2.0, {0., 0.6, 1.8});
|
||||
SyncTrack track_b = SyncTrack::CreateFromMarkers(1.5f, {1.05, 1.35, 0.3});
|
||||
|
||||
REQUIRE(
|
||||
blended.m_duration
|
||||
== (1.0f - weight) * track_A.m_duration
|
||||
+ weight * track_B.m_duration);
|
||||
REQUIRE(
|
||||
blended.m_interval_start[0]
|
||||
== fmodf(
|
||||
(1.0f - weight) * (track_A.m_interval_start[0] + 1.0f)
|
||||
+ weight * (track_B.m_interval_start[0]),
|
||||
1.0f));
|
||||
REQUIRE(
|
||||
blended.m_interval_ratio[1]
|
||||
== (1.0f - weight) * (track_A.m_interval_ratio[1])
|
||||
+ weight * (track_B.m_interval_ratio[1])
|
||||
);
|
||||
REQUIRE(
|
||||
blended.m_interval_ratio[2]
|
||||
== (1.0f - weight) * (track_A.m_interval_ratio[2])
|
||||
+ weight * (track_B.m_interval_ratio[2])
|
||||
);
|
||||
}
|
||||
WHEN("Calculating A's durations") {
|
||||
CHECK(track_a.m_interval_duration_ratio[0] == Catch::Detail::Approx(0.3));
|
||||
CHECK(track_a.m_interval_duration_ratio[1] == Catch::Detail::Approx(0.6));
|
||||
CHECK(track_a.m_interval_duration_ratio[2] == Catch::Detail::Approx(0.1));
|
||||
}
|
||||
|
||||
WHEN("Inverted blending with weight 0.2") {
|
||||
float weight = 0.2f;
|
||||
SyncTrack blended = SyncTrack::Blend(weight, track_B, track_A);
|
||||
WHEN("Calculating B's durations") {
|
||||
CHECK(track_b.m_interval_duration_ratio[0] == Catch::Detail::Approx(0.2));
|
||||
CHECK(track_b.m_interval_duration_ratio[1] == Catch::Detail::Approx(0.3));
|
||||
CHECK(track_b.m_interval_duration_ratio[2] == Catch::Detail::Approx(0.5));
|
||||
}
|
||||
|
||||
REQUIRE(
|
||||
blended.m_duration
|
||||
== (1.0f - weight) * track_B.m_duration
|
||||
+ weight * track_A.m_duration);
|
||||
REQUIRE(
|
||||
blended.m_interval_start[0]
|
||||
== fmodf(
|
||||
(1.0f - weight) * (track_B.m_interval_start[0])
|
||||
+ weight * (track_A.m_interval_start[0] + 1.0f),
|
||||
1.0f));
|
||||
REQUIRE(
|
||||
blended.m_interval_ratio[1]
|
||||
== (1.0f - weight) * (track_B.m_interval_ratio[1])
|
||||
+ weight * (track_A.m_interval_ratio[1])
|
||||
);
|
||||
REQUIRE(
|
||||
blended.m_interval_ratio[2]
|
||||
== (1.0f - weight) * (track_B.m_interval_ratio[2])
|
||||
+ weight * (track_A.m_interval_ratio[2])
|
||||
);
|
||||
}
|
||||
WHEN("Blending two synctracks with weight 0.") {
|
||||
SyncTrack blended = SyncTrack::Blend(0.f, track_a, track_b);
|
||||
|
||||
THEN("Result must equal track_A") { REQUIRE(track_a == blended); }
|
||||
}
|
||||
|
||||
WHEN("Blending two synctracks with weight 1.") {
|
||||
SyncTrack blended = SyncTrack::Blend(1.f, track_a, track_b);
|
||||
|
||||
THEN("Result must equal track_B") { REQUIRE(track_b == blended); }
|
||||
}
|
||||
|
||||
WHEN("Blending with weight 0.2") {
|
||||
float weight = 0.2f;
|
||||
SyncTrack blended = SyncTrack::Blend(weight, track_a, track_b);
|
||||
|
||||
REQUIRE(
|
||||
blended.m_duration
|
||||
== (1.0f - weight) * track_a.m_duration + weight * track_b.m_duration);
|
||||
REQUIRE(
|
||||
blended.m_interval_start_ratio[0]
|
||||
== fmodf(
|
||||
(1.0f - weight) * (track_a.m_interval_start_ratio[0] + 1.0f)
|
||||
+ weight * (track_b.m_interval_start_ratio[0]),
|
||||
1.0f));
|
||||
REQUIRE(
|
||||
blended.m_interval_duration_ratio[1]
|
||||
== (1.0f - weight) * (track_a.m_interval_duration_ratio[1])
|
||||
+ weight * (track_b.m_interval_duration_ratio[1]));
|
||||
REQUIRE(
|
||||
blended.m_interval_duration_ratio[2]
|
||||
== (1.0f - weight) * (track_a.m_interval_duration_ratio[2])
|
||||
+ weight * (track_b.m_interval_duration_ratio[2]));
|
||||
}
|
||||
|
||||
WHEN("Inverted blending with weight 0.2") {
|
||||
float weight = 0.2f;
|
||||
SyncTrack blended = SyncTrack::Blend(weight, track_b, track_a);
|
||||
|
||||
REQUIRE(
|
||||
blended.m_duration
|
||||
== (1.0f - weight) * track_b.m_duration + weight * track_a.m_duration);
|
||||
REQUIRE(
|
||||
blended.m_interval_start_ratio[0]
|
||||
== fmodf(
|
||||
(1.0f - weight) * (track_b.m_interval_start_ratio[0])
|
||||
+ weight * (track_a.m_interval_start_ratio[0] + 1.0f),
|
||||
1.0f));
|
||||
REQUIRE(
|
||||
blended.m_interval_duration_ratio[1]
|
||||
== (1.0f - weight) * (track_b.m_interval_duration_ratio[1])
|
||||
+ weight * (track_a.m_interval_duration_ratio[1]));
|
||||
REQUIRE(
|
||||
blended.m_interval_duration_ratio[2]
|
||||
== (1.0f - weight) * (track_b.m_interval_duration_ratio[2])
|
||||
+ weight * (track_a.m_interval_duration_ratio[2]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Serialization", "[SyncTrack]") {
|
||||
SyncTrack track;
|
||||
track.m_num_intervals = 3;
|
||||
track.m_duration = 2.0;
|
||||
track.m_interval_start_ratio[0] = 0.f;
|
||||
track.m_interval_duration_ratio[0] = 0.7;
|
||||
track.m_interval_start_ratio[1] = 0.7f;
|
||||
track.m_interval_duration_ratio[1] = 0.3;
|
||||
track.m_interval_start_ratio[2] = 0.7f;
|
||||
track.m_interval_duration_ratio[2] = 0.3;
|
||||
|
||||
nlohmann::json synctrack_json = track;
|
||||
|
||||
const SyncTrack synctrack_deserialized = synctrack_json;
|
||||
|
||||
CHECK(synctrack_deserialized.m_duration == track.m_duration);
|
||||
CHECK(synctrack_deserialized.m_num_intervals == track.m_num_intervals);
|
||||
|
||||
for (int i = 0; i < track.m_num_intervals; i++) {
|
||||
CHECK(
|
||||
synctrack_deserialized.m_interval_start_ratio[i]
|
||||
== track.m_interval_start_ratio[i]);
|
||||
CHECK(
|
||||
synctrack_deserialized.m_interval_duration_ratio[i]
|
||||
== track.m_interval_duration_ratio[i]);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user