Created
February 20, 2019 01:42
-
-
Save JSandusky/2c590178c23c4ce958fd9a1d0c1c7ccc to your computer and use it in GitHub Desktop.
Keyframe extraction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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