Skip to content

Commit

Permalink
Updates data with constant track optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaumeblanc committed May 22, 2024
1 parent d3599e9 commit ca1a4f0
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 25 deletions.
Binary file modified media/bin/pab_atlas.ozz
Binary file not shown.
Binary file modified media/bin/pab_atlas_motion_track.ozz
Binary file not shown.
Binary file modified media/bin/pab_atlas_no_motion.ozz
Binary file not shown.
Binary file modified media/bin/pab_atlas_raw.ozz
Binary file not shown.
Binary file modified media/bin/pab_jog_motion_track.ozz
Binary file not shown.
Binary file modified media/bin/pab_jog_no_motion.ozz
Binary file not shown.
Binary file modified media/bin/pab_run_motion_track.ozz
Binary file not shown.
Binary file modified media/bin/pab_run_no_motion.ozz
Binary file not shown.
Binary file modified media/bin/pab_walk_motion_track.ozz
Binary file not shown.
Binary file modified media/bin/pab_walk_no_motion.ozz
Binary file not shown.
6 changes: 3 additions & 3 deletions src/animation/offline/animation_optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,13 @@ bool AnimationOptimizer::operator()(const RawAnimation& _input,
// Filters independently T, R and S tracks.
// This joint translation is affected by parent scale.
const PositionAdapter tadap(parent_scale);
Decimate(input.translations, tadap, tolerance, &output.translations);
output.translations = Decimate(input.translations, tadap, tolerance);
// This joint rotation affects children translations/length.
const RotationAdapter radap(joint_length);
Decimate(input.rotations, radap, tolerance, &output.rotations);
output.rotations = Decimate(input.rotations, radap, tolerance);
// This joint scale affects children translations/length.
const ScaleAdapter sadap(joint_length);
Decimate(input.scales, sadap, tolerance, &output.scales);
output.scales = Decimate(input.scales, sadap, tolerance);
}

// Output animation is always valid though.
Expand Down
42 changes: 21 additions & 21 deletions src/animation/offline/decimate.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ namespace offline {
// float Distance(const Value& _a, const Value& _b) const;
// };
template <typename _Track, typename _Adapter>
void Decimate(const _Track& _src, const _Adapter& _adapter, float _tolerance,
_Track* _dest) {
_Track Decimate(const _Track& _src, const _Adapter& _adapter,
float _tolerance) {
_Track output;
if (_src.size() < 2) { // Nothing to decimate.
*_dest = _src;
output = _src;
} else {
// Stack of segments to process.
typedef std::pair<size_t, size_t> Segment;
Expand Down Expand Up @@ -110,33 +111,32 @@ void Decimate(const _Track& _src, const _Adapter& _adapter, float _tolerance,
}

// Copy all included points.
_dest->clear();
for (size_t i = 0; i < _src.size(); ++i) {
if (included[i]) {
_dest->push_back(_src[i]);
output.push_back(_src[i]);
}
}
}

// Removes last key if constant.
if (_dest->size() > 1) {
typename _Track::const_iterator end = _dest->end();
typename _Track::const_reference last = *(--end);
typename _Track::const_reference penultimate = *(--end);
const float distance = _adapter.Distance(penultimate.value, last.value);
if (_adapter.Decimable(last) && distance <= _tolerance) {
_dest->pop_back();
// RDP algo ends with a minimum of 2 points (first and last).
// Removes last keys if track is constant or identity.
while (!output.empty()) {
const bool last_key = output.size() == 1;
typename _Track::const_reference back = output.back();
if (!last_key && !_adapter.Decimable(back)) {
break; // Not allowed, only meaningful if not last key
}
}

// Completely removes the key if constant and identity
if (_dest->size() == 1) {
const float distance =
_adapter.Distance(_dest->front().value, _Adapter::identity());
if (distance <= _tolerance) {
_dest->clear();
const auto& penultimate =
last_key ? _Adapter::identity() : output[output.size() - 2].value;
const float distance = _adapter.Distance(penultimate, back.value);
if (distance > _tolerance) {
break; // Too far, not decimable
}
// Decimation is possible, remove last key.
output.pop_back();
}

return output;
}
} // namespace offline
} // namespace animation
Expand Down
2 changes: 1 addition & 1 deletion src/animation/offline/track_optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ inline bool Optimize(float _tolerance, const _Track& _input, _Track* _output) {

// Optimizes.
const Adapter<typename _Track::Keyframe> adapter;
Decimate(_input.keyframes, adapter, _tolerance, &_output->keyframes);
_output->keyframes = Decimate(_input.keyframes, adapter, _tolerance);

// Output animation is always valid though.
return _output->Validate();
Expand Down
60 changes: 60 additions & 0 deletions test/animation/offline/track_optimizer_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,66 @@ TEST(Name, FloatTrackOptimizer) {
EXPECT_STREQ(raw_float_track.name.c_str(), output.name.c_str());
}

TEST(Identity, TrackOptimizer) {
TrackOptimizer optimizer;

RawFloatTrack raw_float_track;
const RawFloatTrack::Keyframe key0 = {RawTrackInterpolation::kLinear, .5f,
0.f};
raw_float_track.keyframes.push_back(key0);
const RawFloatTrack::Keyframe key1 = {RawTrackInterpolation::kLinear, .7f,
0.f};
raw_float_track.keyframes.push_back(key1);
const RawFloatTrack::Keyframe key2 = {RawTrackInterpolation::kLinear, .8f,
0.f};
raw_float_track.keyframes.push_back(key2);

RawFloatTrack output;
ASSERT_TRUE(optimizer(raw_float_track, &output));
EXPECT_TRUE(output.keyframes.empty());

// Step keys aren't optimized.
raw_float_track.keyframes[1].interpolation = RawTrackInterpolation::kStep;
ASSERT_TRUE(optimizer(raw_float_track, &output));
EXPECT_EQ(output.keyframes.size(), 2u);
}

TEST(Constant, TrackOptimizer) {
TrackOptimizer optimizer;

RawFloatTrack raw_float_track;
const RawFloatTrack::Keyframe key0 = {RawTrackInterpolation::kLinear, .5f,
46.f};
raw_float_track.keyframes.push_back(key0);
const RawFloatTrack::Keyframe key1 = {RawTrackInterpolation::kLinear, .7f,
46.f};
raw_float_track.keyframes.push_back(key1);
const RawFloatTrack::Keyframe key2 = {RawTrackInterpolation::kLinear, .8f,
46.f};
raw_float_track.keyframes.push_back(key2);

RawFloatTrack output;
ASSERT_TRUE(optimizer(raw_float_track, &output));
EXPECT_EQ(output.keyframes.size(), 1u);

EXPECT_EQ(output.keyframes[0].interpolation, key0.interpolation);
EXPECT_FLOAT_EQ(output.keyframes[0].ratio, key0.ratio);
EXPECT_FLOAT_EQ(output.keyframes[0].value, key0.value);

// Step keys aren't optimized.
raw_float_track.keyframes[2].interpolation = RawTrackInterpolation::kStep;
ASSERT_TRUE(optimizer(raw_float_track, &output));
EXPECT_EQ(output.keyframes.size(), 2u);

EXPECT_EQ(output.keyframes[0].interpolation, key0.interpolation);
EXPECT_FLOAT_EQ(output.keyframes[0].ratio, key0.ratio);
EXPECT_FLOAT_EQ(output.keyframes[0].value, key0.value);

EXPECT_EQ(output.keyframes[1].interpolation, RawTrackInterpolation::kStep);
EXPECT_FLOAT_EQ(output.keyframes[1].ratio, key2.ratio);
EXPECT_FLOAT_EQ(output.keyframes[1].value, key2.value);
}

TEST(OptimizeSteps, TrackOptimizer) {
// Step keys aren't optimized.
TrackOptimizer optimizer;
Expand Down

0 comments on commit ca1a4f0

Please sign in to comment.