Animation optimization; Cleanup;

This commit is contained in:
bjorn 2019-01-18 10:11:24 -08:00 committed by Bjorn Swenson
parent 09936a8ae2
commit bea2140676
4 changed files with 60 additions and 88 deletions

View File

@ -74,7 +74,6 @@ static int libraryLoader(lua_State* L) {
const char* filename = luaL_gsub(L, path, "??", buffer);
filename = luaL_gsub(L, filename, "?", modulePath);
lua_pop(L, 2);
printf("hi\n");
if (lovrFilesystemIsFile(filename)) {
char fullPath[LOVR_PATH_MAX];

View File

@ -498,18 +498,17 @@ ModelData* lovrModelDataInit(ModelData* model, Blob* source, ModelDataIO io) {
channelIndex += animation->channelCount;
for (int j = 0; j < animation->channelCount; j++) {
ModelAnimationChannel* channel = &animation->channels[j];
ModelAttribute* times = NULL;
ModelAttribute* data = NULL;
for (int kk = (token++)->size; kk > 0; kk--) {
gltfString key = NOM_STR(json, token);
if (STR_EQ(key, "sampler")) {
gltfAnimationSampler* sampler = animationSamplers + baseSampler + NOM_INT(json, token);
channel->times = &model->attributes[sampler->input];
channel->data = &model->attributes[sampler->output];
channel->keyframeCount = channel->times->count;
times = &model->attributes[sampler->input];
data = &model->attributes[sampler->output];
channel->smoothing = sampler->smoothing;
ModelBuffer* buffer = &model->buffers[channel->times->buffer];
size_t stride = buffer->stride ? buffer->stride : (channel->times->components * sizeof(float));
float lastTime = *(float*) (buffer->data + (channel->times->count - 1) * stride + channel->times->offset);
animation->duration = MAX(lastTime, animation->duration);
channel->keyframeCount = times->count;
} else if (STR_EQ(key, "target")) {
for (int kkk = (token++)->size; kkk > 0; kkk--) {
gltfString key = NOM_STR(json, token);
@ -528,6 +527,21 @@ ModelData* lovrModelDataInit(ModelData* model, Blob* source, ModelDataIO io) {
token += NOM_VALUE(json, token);
}
}
lovrAssert(times, "Missing keyframe times");
lovrAssert(data, "Missing keyframe data");
ModelBuffer* buffer;
buffer = &model->buffers[times->buffer];
lovrAssert(times->type == F32 && (buffer->stride == 0 || buffer->stride == sizeof(float)), "Keyframe times must be tightly-packed floats");
channel->times = (float*) (buffer->data + times->offset);
buffer = &model->buffers[data->buffer];
uint8_t components = data->components;
lovrAssert(data->type == F32 && (buffer->stride == 0 || buffer->stride == sizeof(float) * components), "Keyframe data must be tightly-packed floats");
channel->data = (float*) (buffer->data + data->offset);
animation->duration = MAX(animation->duration, channel->times[channel->keyframeCount - 1]);
}
} else if (STR_EQ(key, "samplers")) {
samplerCount = token->size;

View File

@ -115,8 +115,8 @@ typedef struct {
AnimationProperty property;
SmoothMode smoothing;
int keyframeCount;
ModelAttribute* times;
ModelAttribute* data;
float* times;
float* data;
} ModelAnimationChannel;
typedef struct {

View File

@ -12,19 +12,17 @@ Animator* lovrAnimatorInit(Animator* animator, ModelData* modelData) {
animator->modelData = modelData;
vec_init(&animator->tracks);
vec_reserve(&animator->tracks, modelData->animationCount);
animator->speed = 1;
animator->speed = 1.f;
for (int i = 0; i < modelData->animationCount; i++) {
Track track = {
vec_push(&animator->tracks, ((Track) {
.time = 0.f,
.speed = 1.f,
.alpha = 1.f,
.priority = 0,
.playing = false,
.looping = false
};
vec_push(&animator->tracks, track);
}));
}
return animator;
@ -39,12 +37,12 @@ void lovrAnimatorDestroy(void* ref) {
void lovrAnimatorReset(Animator* animator) {
Track* track; int i;
vec_foreach_ptr(&animator->tracks, track, i) {
track->time = 0;
track->speed = 1;
track->time = 0.f;
track->speed = 1.f;
track->playing = false;
track->looping = false;
}
animator->speed = 1;
animator->speed = 1.f;
}
void lovrAnimatorUpdate(Animator* animator, float dt) {
@ -64,12 +62,6 @@ void lovrAnimatorUpdate(Animator* animator, float dt) {
}
}
static float* evaluateAttribute(Animator* animator, ModelAttribute* attribute, int index) {
ModelBuffer* buffer = &animator->modelData->buffers[attribute->buffer];
size_t stride = buffer->stride ? buffer->stride : (attribute->components * sizeof(float)); // TODO
return (float*) (buffer->data + index * stride + attribute->offset);
}
bool lovrAnimatorEvaluate(Animator* animator, int nodeIndex, mat4 transform) {
ModelData* modelData = animator->modelData;
float properties[3][4] = { { 0, 0, 0 }, { 0, 0, 0, 1 }, { 1, 1, 1 } };
@ -82,82 +74,49 @@ bool lovrAnimatorEvaluate(Animator* animator, int nodeIndex, mat4 transform) {
for (int j = 0; j < animation->channelCount; j++) {
ModelAnimationChannel* channel = &animation->channels[j];
if (!track->playing || channel->nodeIndex != nodeIndex) {
if (channel->nodeIndex != nodeIndex || !track->playing || track->alpha == 0.f) {
continue;
}
float duration = animator->modelData->animations[i].duration;
float time = fmodf(track->time, duration);
ModelAttribute* times = channel->times;
ModelAttribute* data = channel->data;
int k = 0;
while (k < channel->keyframeCount && *evaluateAttribute(animator, times, k) < time) {
while (k < channel->keyframeCount && channel->times[k] < time) {
k++;
}
float z = 0.f;
float value[4];
float next[4];
if (k > 0 && k <= channel->keyframeCount - 1) {
float t1 = *evaluateAttribute(animator, times, k - 1);
float t2 = *evaluateAttribute(animator, times, k);
z = (time - t1) / (t2 - t1);
bool rotate = channel->property == PROP_ROTATION;
int n = 3 + rotate;
float* (*lerp)(float* a, float* b, float t) = rotate ? quat_slerp : vec3_lerp;
if (k > 0 && k < channel->keyframeCount) {
float t1 = channel->times[k - 1];
float t2 = channel->times[k];
float z = (time - t1) / (t2 - t1);
float next[4];
memcpy(value, channel->data + (k - 1) * n, n * sizeof(float));
memcpy(next, channel->data + k * n, n * sizeof(float));
switch (channel->smoothing) {
case SMOOTH_STEP:
if (z >= .5) {
memcpy(value, next, n * sizeof(float));
}
break;
case SMOOTH_LINEAR: lerp(value, next, z); break;
case SMOOTH_CUBIC: lovrThrow("No spline interpolation yet"); break;
}
} else {
memcpy(value, channel->data + CLAMP(k, 0, channel->keyframeCount - 1) * n, n * sizeof(float));
}
switch (channel->property) {
case PROP_TRANSLATION:
case PROP_SCALE:
if (k == 0) {
vec3_init(value, evaluateAttribute(animator, data, 0));
} else if (k >= channel->keyframeCount) {
vec3_init(value, evaluateAttribute(animator, data, channel->keyframeCount - 1));
} else {
vec3_init(value, evaluateAttribute(animator, data, k - 1));
vec3_init(next, evaluateAttribute(animator, data, k));
switch (channel->smoothing) {
case SMOOTH_STEP:
if (z >= .5) {
vec3_init(value, next);
}
break;
case SMOOTH_LINEAR:
vec3_lerp(value, next, z);
break;
case SMOOTH_CUBIC:
lovrThrow("No spline interpolation yet");
break;
}
}
vec3_lerp(properties[channel->property], value, track->alpha);
break;
case PROP_ROTATION:
if (k == 0) {
quat_init(value, evaluateAttribute(animator, data, 0));
} else if (k >= channel->keyframeCount) {
quat_init(value, evaluateAttribute(animator, data, channel->keyframeCount - 1));
} else {
quat_init(value, evaluateAttribute(animator, data, k - 1));
quat_init(next, evaluateAttribute(animator, data, k));
switch (channel->smoothing) {
case SMOOTH_STEP:
if (z >= .5) {
quat_init(value, next);
}
break;
case SMOOTH_LINEAR:
quat_slerp(value, next, z);
break;
case SMOOTH_CUBIC:
lovrThrow("No spline interpolation yet");
break;
}
}
quat_slerp(properties[channel->property], value, track->alpha);
break;
if (track->alpha == 1.f) {
memcpy(properties[channel->property], value, n * sizeof(float));
} else {
lerp(properties[channel->property], value, track->alpha);
}
touched = true;