diff --git a/src/api/filesystem.c b/src/api/filesystem.c index 0524adad..d1d39277 100644 --- a/src/api/filesystem.c +++ b/src/api/filesystem.c @@ -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]; diff --git a/src/data/modelData.c b/src/data/modelData.c index 0476486e..397363b0 100644 --- a/src/data/modelData.c +++ b/src/data/modelData.c @@ -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; diff --git a/src/data/modelData.h b/src/data/modelData.h index 8a509016..96073471 100644 --- a/src/data/modelData.h +++ b/src/data/modelData.h @@ -115,8 +115,8 @@ typedef struct { AnimationProperty property; SmoothMode smoothing; int keyframeCount; - ModelAttribute* times; - ModelAttribute* data; + float* times; + float* data; } ModelAnimationChannel; typedef struct { diff --git a/src/graphics/animator.c b/src/graphics/animator.c index 7a08a6e9..bd57cdb3 100644 --- a/src/graphics/animator.c +++ b/src/graphics/animator.c @@ -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;