From 33ff7f2b9cb09663dffbd1242b6c9157c6bace6b Mon Sep 17 00:00:00 2001 From: bjorn Date: Mon, 6 Nov 2017 17:12:29 -0800 Subject: [PATCH] Add lovrAnimatorEvaluate; --- src/api/types/model.c | 2 +- src/graphics/animator.c | 122 +++++++++++++++++++++++++++++++++++++--- src/graphics/animator.h | 4 +- 3 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/api/types/model.c b/src/api/types/model.c index 5782f508..000473ba 100644 --- a/src/api/types/model.c +++ b/src/api/types/model.c @@ -47,7 +47,7 @@ const luaL_Reg lovrModel[] = { { "draw", l_lovrModelDraw }, { "getAABB", l_lovrModelGetAABB }, { "getAnimator", l_lovrModelGetAnimator }, - { "setAnimator", l_lovrModelGetAnimator }, + { "setAnimator", l_lovrModelSetAnimator }, { "getMesh", l_lovrModelGetMesh }, { NULL, NULL } }; diff --git a/src/graphics/animator.c b/src/graphics/animator.c index 73249734..70c9c5a0 100644 --- a/src/graphics/animator.c +++ b/src/graphics/animator.c @@ -1,5 +1,6 @@ #include "graphics/animator.h" -#include "math/math.h" +#include "math/vec3.h" +#include "math/quat.h" #include static Track* lovrAnimatorEnsureTrack(Animator* animator, const char* animation) { @@ -56,13 +57,120 @@ void lovrAnimatorUpdate(Animator* animator, float dt) { const char* key; while ((key = map_next(&animator->timeline, &iter)) != NULL) { Track* track = map_get(&animator->timeline, key); - track->time += dt * track->speed * animator->speed; - if (track->looping) { - track->time = fmodf(track->time, track->animation->duration); - } else if (track->time > track->animation->duration) { - track->time = 0; - track->playing = false; + if (track->playing) { + track->time += dt * track->speed * animator->speed; + + if (track->looping) { + track->time = fmodf(track->time, track->animation->duration); + } else if (track->time > track->animation->duration) { + track->time = 0; + track->playing = false; + } + } + } +} + +void lovrAnimatorEvaluate(Animator* animator, const char* bone, mat4 transform) { + map_iter_t iter = map_iter(&animator->timeline); + const char* key; + while ((key = map_next(&animator->timeline, &iter)) != NULL) { + Track* track = map_get(&animator->timeline, key); + Animation* animation = track->animation; + AnimationChannel* channel = map_get(&animation->channels, bone); + + if (!channel || !track->playing) { + continue; + } + + float time = fmodf(track->time, animation->duration); + int i; + + // Position + if (channel->positionKeyframes.length > 0) { + i = 0; + while (i < channel->positionKeyframes.length) { + if (channel->positionKeyframes.data[i].time >= time) { + break; + } else { + i++; + } + } + + float translation[3]; + if (i == 0) { + Keyframe keyframe = channel->positionKeyframes.data[0]; + vec3_init(translation, keyframe.data); + } else if (i >= channel->positionKeyframes.length) { + Keyframe keyframe = channel->positionKeyframes.data[channel->positionKeyframes.length - 1]; + vec3_init(translation, keyframe.data); + } else { + Keyframe before, after; + before = channel->positionKeyframes.data[i - 1]; + after = channel->positionKeyframes.data[i]; + float t = (time - before.time) / (after.time - before.time); + vec3_lerp(vec3_init(translation, before.data), after.data, t); + } + + mat4_translate(transform, translation[0], translation[1], translation[2]); + } + + // Rotation + if (channel->rotationKeyframes.length > 0) { + i = 0; + while (i < channel->rotationKeyframes.length) { + if (channel->rotationKeyframes.data[i].time >= time) { + break; + } else { + i++; + } + } + + float rotation[4]; + if (i == 0) { + Keyframe keyframe = channel->rotationKeyframes.data[0]; + quat_init(rotation, keyframe.data); + } else if (i >= channel->rotationKeyframes.length) { + Keyframe keyframe = channel->rotationKeyframes.data[channel->rotationKeyframes.length - 1]; + quat_init(rotation, keyframe.data); + } else { + Keyframe before, after; + before = channel->rotationKeyframes.data[i - 1]; + after = channel->rotationKeyframes.data[i]; + float t = (time - before.time) / (after.time - before.time); + quat_slerp(quat_init(rotation, before.data), after.data, t); + } + + mat4_rotateQuat(transform, rotation); + } + + // Scale + if (channel->scaleKeyframes.length > 0) { + i = 0; + while (i < channel->scaleKeyframes.length) { + if (channel->scaleKeyframes.data[i].time >= time) { + break; + } else { + i++; + } + } + + float scale[3]; + if (i == 0) { + Keyframe keyframe = channel->scaleKeyframes.data[0]; + vec3_init(scale, keyframe.data); + } else if (i >= channel->scaleKeyframes.length) { + Keyframe keyframe = channel->scaleKeyframes.data[channel->scaleKeyframes.length - 1]; + vec3_init(scale, keyframe.data); + } else { + Keyframe before, after; + before = channel->scaleKeyframes.data[i - 1]; + after = channel->scaleKeyframes.data[i]; + float t = (time - before.time) / (after.time - before.time); + vec3_lerp(vec3_init(scale, before.data), after.data, t); + } + + mat4_scale(transform, scale[0], scale[1], scale[2]); } } } diff --git a/src/graphics/animator.h b/src/graphics/animator.h index 2397cf27..dbb5f4aa 100644 --- a/src/graphics/animator.h +++ b/src/graphics/animator.h @@ -1,6 +1,7 @@ #include "loaders/animation.h" -#include "lib/map/map.h" +#include "math/mat4.h" #include "util.h" +#include "lib/map/map.h" #include #pragma once @@ -28,6 +29,7 @@ Animator* lovrAnimatorCreate(AnimationData* animationData); void lovrAnimatorDestroy(const Ref* ref); void lovrAnimatorReset(Animator* animator); void lovrAnimatorUpdate(Animator* animator, float dt); +void lovrAnimatorEvaluate(Animator* animator, const char* bone, mat4 transform); int lovrAnimatorGetAnimationCount(Animator* animator); const char* lovrAnimatorGetAnimationName(Animator* animator, int index); void lovrAnimatorPlay(Animator* animator, const char* animation);