You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/EMotionFX/Code/Tests/MotionDataTests.cpp

166 lines
5.1 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/UnitTest.h>
#include <EMotionFX/Source/MotionData/MotionData.h>
#include <Tests/SystemComponentFixture.h>
namespace EMotionFX
{
class MotionDataTests
: public SystemComponentFixture
, public UnitTest::TraceBusRedirector
{
public:
void SetUp()
{
UnitTest::TraceBusRedirector::BusConnect();
SystemComponentFixture::SetUp();
}
void TearDown()
{
SystemComponentFixture::TearDown();
UnitTest::TraceBusRedirector::BusDisconnect();
}
};
TEST_F(MotionDataTests, CalculateSampleInformation)
{
struct TestSample
{
float m_duration;
float m_sampleRate;
float m_expectedSampleRate;
float m_expectedSampleSpacing;
size_t m_expectedNumSamples;
};
AZStd::vector<TestSample> samples{
{ 1.0f, 10.0f, 10.0f, 0.1f, 11 },
{ 1.0f, 3.0f, 3.0f, 1.0f / 3.0f, 4 },
{ 0.5f, 1.0f, 2.0f, 0.5f, 2 },
{ 1.05f, 10.0f, 1.0f / (1.05f / 10.0f), 1.05f / 10.0f, 11 }
};
for (const TestSample& sample : samples)
{
float sampleRate = sample.m_sampleRate;
float sampleSpacing = -1.0f;
size_t numSamples = InvalidIndex;
MotionData::CalculateSampleInformation(sample.m_duration, sampleRate, numSamples, sampleSpacing);
EXPECT_NEAR(sampleSpacing, sample.m_expectedSampleSpacing, 0.0001f);
EXPECT_NEAR(sampleRate, sample.m_expectedSampleRate, 0.0001f);
EXPECT_EQ(numSamples, sample.m_expectedNumSamples);
}
}
TEST_F(MotionDataTests, CalculateNumRequiredSamples)
{
EXPECT_EQ(MotionData::CalculateNumRequiredSamples(1.0f, 0.1f), 11);
EXPECT_EQ(MotionData::CalculateNumRequiredSamples(1.0f, 2.0f), 2);
EXPECT_EQ(MotionData::CalculateNumRequiredSamples(1.0f, 0.333333f), 4);
EXPECT_EQ(MotionData::CalculateNumRequiredSamples(1.0f, 1.0f), 2);
}
TEST_F(MotionDataTests, CalculateInterpolationIndices)
{
struct TestSample
{
float m_sampleTime = 0.0f;
size_t m_indexA = InvalidIndex;
size_t m_indexB = InvalidIndex;
float m_t = -1.0f;
};
AZStd::vector<TestSample> testSamples = {
{
// Negative time value, out of range.
-1.0f, // Sample time.
0, // Expected IndexA.
0, // Expected IndexB.
0.0f // Expected t.
},
{
// Exactly on the first sample.
0.0f,
0,
1,
0.0f
},
{
// Exactly on the last sample.
1.0f,
10,
10,
0.0f
},
{
// Exactly on the second sample.
0.1f,
1,
2,
0.0f
},
{
// In between two samples.
0.15f,
1,
2,
0.5f
},
{
// Another in-between two samples test.
0.725f,
7,
8,
0.25f
},
{
// Past the maximum duration.
100.0f,
10,
10,
0.0f
}
};
// Create some track for our non-uniform test.
AZStd::vector<float> track;
const float sampleSpacing = 0.1f;
const float duration = 1.0f;
const size_t numSamples = 11;
track.resize(numSamples);
for (size_t i = 0; i < numSamples; ++i)
{
track[i] = static_cast<float>(i * sampleSpacing);
}
for (TestSample& testSample : testSamples)
{
// Test uniform sampling.
size_t indexA = InvalidIndex;
size_t indexB = InvalidIndex;
float t = -1.0f;
MotionData::CalculateInterpolationIndicesUniform(testSample.m_sampleTime, sampleSpacing, duration, numSamples, indexA, indexB, t);
EXPECT_EQ(indexA, testSample.m_indexA);
EXPECT_EQ(indexB, testSample.m_indexB);
EXPECT_TRUE(AZ::IsClose(t, testSample.m_t, 0.0001f));
// Test non-uniform sampling.
indexA = InvalidIndex;
indexB = InvalidIndex;
t = -1.0f;
MotionData::CalculateInterpolationIndicesNonUniform(track, testSample.m_sampleTime, indexA, indexB, t);
EXPECT_EQ(indexA, testSample.m_indexA);
EXPECT_EQ(indexB, testSample.m_indexB);
EXPECT_TRUE(AZ::IsClose(t, testSample.m_t, 0.0001f));
}
}
}; // namespace EMotionFX