Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@JSandusky
Created February 20, 2019 01:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JSandusky/2c590178c23c4ce958fd9a1d0c1c7ccc to your computer and use it in GitHub Desktop.
Save JSandusky/2c590178c23c4ce958fd9a1d0c1c7ccc to your computer and use it in GitHub Desktop.
Keyframe extraction
#include "AnimProc.h"
#include "../Graphics/Animation.h"
#include "../IO/Log.h"
namespace Urho3D
{
/// Pulls out an interpolated keyframe from a track based on time.
/// The time value of the key will be set to the given time value, overwrite if undesired.
static AnimationKeyFrame ExtractKeyFrame(AnimationTrack* track, float time)
{
AnimationKeyFrame* prevKey = nullptr;
AnimationKeyFrame* nextKey = nullptr;
for (unsigned k = 0; k < track->GetNumKeyFrames(); ++k)
{
auto key = track->GetKeyFrame(k);
if (key->time_ <= time)
prevKey = key;
else if (key->time_ > time && prevKey != nullptr)
{
nextKey = key;
break;
}
}
if (prevKey && nextKey)
{
const float lerpFactor = NORMALIZE(time, prevKey->time_, nextKey->time_);
AnimationKeyFrame ret;
ret.position_ = prevKey->position_.Lerp(nextKey->position_, lerpFactor);
ret.rotation_ = prevKey->rotation_.Slerp(nextKey->rotation_, lerpFactor);
ret.scale_ = prevKey->scale_.Lerp(nextKey->scale_, lerpFactor);
ret.time_ = time;
return ret;
}
else if (prevKey)
{
AnimationKeyFrame ret = *prevKey;
ret.time_ = time;
return ret;
}
AnimationKeyFrame ret = track->keyFrames_.Front();
ret.time_ = time;
return ret;
}
/// Extracts the given key indices into a new animation, that runs a specified length of time.
/// Times are sliced evenly
Animation* ExtractAnimation(Animation* src, const PODVector<unsigned>& keyIndices, float totalTime)
{
const float fracTime = totalTime / (keyIndices.Size() - 1);
PODVector<float> frameTimes;
frameTimes.Reserve(keyIndices.Size());
float runningTime = 0.0f;
for (unsigned i = 0; i < keyIndices.Size(); ++i, runningTime += fracTime)
frameTimes.Push(runningTime);
return ExtractAnimation(src, keyIndices, frameTimes);
}
/// Extracts the given key times into a new animation, that runs a specified length of time.
/// Times are sliced evenly
Animation* ExtractAnimation(Animation* src, const PODVector<float>& times, float totalTime)
{
const float fracTime = totalTime / (times.Size() - 1);
PODVector<float> frameTimes;
frameTimes.Reserve(times.Size());
float runningTime = 0.0f;
for (unsigned i = 0; i < times.Size(); ++i, runningTime += fracTime)
frameTimes.Push(runningTime);
return ExtractAnimation(src, times, frameTimes);
}
/// Extracts frames by index to create a new animation where each frame has the given times.
/// ANIMATION IS EXPECTED TO BE FAT
Animation* ExtractAnimation(Animation* src, const PODVector<unsigned>& keyIndices, const PODVector<float>& frameTimes)
{
if (src == nullptr)
return nullptr;
Animation* ret = new Animation(src->GetContext());
for (unsigned t = 0; t < src->GetNumTracks(); ++t)
{
auto track = src->GetTrack(t);
AnimationTrack* newTrack = ret->CreateTrack(track->name_);
newTrack->channelMask_ = track->channelMask_;
for (unsigned i = 0; i < keyIndices.Size(); ++i)
{
if (auto key = track->GetKeyFrame(keyIndices[i]))
{
AnimationKeyFrame newKey = *key;
newKey.time_ = frameTimes[i];
newTrack->AddKeyFrame(newKey);
}
}
}
ret->SetLength(frameTimes.Back());
return ret;
}
/// Extracts samples of given frame times into a new animation set with the specified times.
Animation* ExtractAnimation(Animation* src, const PODVector<float>& times, const PODVector<float>& frameTimes)
{
if (src == nullptr)
return nullptr;
Animation* ret = new Animation(src->GetContext());
for (unsigned t = 0; t < src->GetNumTracks(); ++t)
{
auto track = src->GetTrack(t);
AnimationTrack* newTrack = ret->CreateTrack(track->name_);
newTrack->channelMask_ = track->channelMask_;
for (unsigned i = 0; i < times.Size(); ++i)
{
float time = times[i];
auto newKey = ExtractKeyFrame(track, time);
newKey.time_ = frameTimes[i];
newTrack->AddKeyFrame(newKey);
}
}
ret->SetLength(frameTimes.Back());
return ret;
}
}
#pragma once
#include <Urho3D/Container/Vector.h>
namespace Urho3D
{
class Animation;
/*
These functions provide wolfire style utilities for extracting defined keys into a sequence of animation.
Should survive extracting a single key just as well as several, though at least 2 is the `real` case.
*/
/// Extracts a newly made animation from specific key indices (data must be fat), resulting keys are given the specified times.
URHO3D_API Animation* ExtractAnimation(Animation* src, const PODVector<unsigned>& keyIndices, const PODVector<float>& frameTimes);
/// Extracts a newly made animation from specific times, resulting keys are given the specified times.
URHO3D_API Animation* ExtractAnimation(Animation* src, const PODVector<float>& times, const PODVector<float>& frameTimes);
/// Extracts a newly made animation from specific key indices (data must be fat), resulting keys are given a fraction of the total-time.
URHO3D_API Animation* ExtractAnimation(Animation* src, const PODVector<unsigned>& keyIndices, float totalTime);
/// Extracts a newly made animation from specific times, resulting keys are given a fraction of the total-time.
URHO3D_API Animation* ExtractAnimation(Animation* src, const PODVector<float>& times, float totalTime);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment