Hi all,
Thanks for all your help so far in achieving the various goals I have for this project - this is a great community. ๐
I am currently trying to figure out how to implement additive animation blending. If you're unfamiliar with the concept, the idea is similar to additive image blending, wherein the result of the blend is (a * alpha + b) instead of (a * alpha + b * (1 - alpha)). The result, in animation, is a reusable/cheap mechanism for implementing subtle animation effects like breathing or hand shake. Additionally, with blend shapes (aka FFD), additive blending allows more advanced handles for combining blend shapes for effects like facial animation and advanced character body/face customization.
The Uncharted team gave a talk about Additive and partial animations that I attended a while back - it's online now, and should be a good watch: http://www.gdcvault.com/play/1012300/Animation-and-Player-Control-in
So far, I haven't found anything in the C runtime that allows additive animation, but I do think I see a very easy/cheap set of changes that would allow it to be possible/efficient within the current runtime with no changes to the editor. All that would be needed is for a new function be added such as:
void spAnimation_mixEx (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events, int* eventsCount, float alpha, float targetAlpha) {
int i, n = self->timelinesCount;
if (loop && self->duration) {
time = FMOD(time, self->duration);
lastTime = FMOD(lastTime, self->duration);
}
for (i = 0; i < n; ++i)
spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, targetAlpha);
}
Then, mix would become:
void spAnimation_mix (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events, int* eventsCount, float alpha) {
spAnimation_mixEx(self, skeleton, lastTime, time, loop, events, eventsCount, alpha, 1.0f - alpha);
}
The last (and most intrusive) step would be to modify the _spTimelineVtable interface to accept the targetAlpha parameter on blend, and to instrument each of the sp*Timeline_apply() functions to use the parameter where appropriate. Skimming the source code, this would be Rotate, Translate, Scale, Color, FFD, and IK, and the actual changes would be extremely straightforward/safe/performant.
Anyway, I'm considering making this change on my local branch, but I thought I'd check in here first to see a) if it's already been planned/discussed, b) if it's already possible through some other means, or c) if there are problems with this implementation that others more familiar with the codebase might be able to see.
Let me know if you have any thoughts! ๐
Cheers,
Tim A.
P.S. An interesting side-effect of this approach would be the ability to mix animations with pre-calculated final blend coefficients. That is, if you wanted the final blend of 3 anims to be 25%, 25%, and 50%, you could mix them in any order, providing 0.25, 0.25, and 0.5 for alpha, and 1 for targetAlpha. I have used a similar technique in the past in OpenGL graphics code for combining both additive blend and decal blend into a single unified blend mode for more efficient sprite batching (by reducing draw calls). A neat "follow-on feature".