diff --git a/paint/plugins/io_gltf/cgltf.c b/paint/plugins/io_gltf/cgltf.c index 2e421733..43c89e03 100644 --- a/paint/plugins/io_gltf/cgltf.c +++ b/paint/plugins/io_gltf/cgltf.c @@ -10,6 +10,7 @@ static bool has_next = false; static int current_node = 0; static float scale_pos = 1.0; +static int frame_count = 0; void io_gltf_parse_mesh(raw_mesh_t *raw, cgltf_mesh *mesh, float *to_world, float *scale) { cgltf_primitive *prim = NULL; @@ -261,6 +262,10 @@ void *io_gltf_parse(char *buf, size_t size, const char *path) { return raw; } +int io_gltf_frame_count() { + return frame_count; +} + void *io_gltf_parse_skinned(char *buf, size_t size, const char *path, int frame) { cgltf_options options = {0}; cgltf_data *data = NULL; @@ -269,12 +274,15 @@ void *io_gltf_parse_skinned(char *buf, size_t size, const char *path, int frame) cgltf_load_buffers(&options, data, path); // Apply animation at the given frame index by directly writing TRS on each target node + frame_count = 0; if (data->animations_count > 0) { cgltf_animation *anim = &data->animations[0]; for (cgltf_size c = 0; c < anim->channels_count; c++) { cgltf_animation_channel *ch = &anim->channels[c]; if (ch->target_node == NULL) continue; + if ((int)ch->sampler->output->count > frame_count) + frame_count = (int)ch->sampler->output->count; cgltf_size fi = (cgltf_size)frame; if (fi >= ch->sampler->output->count) fi = ch->sampler->output->count - 1; diff --git a/paint/plugins/plugins.c b/paint/plugins/plugins.c index cef5f4ac..4519b99e 100644 --- a/paint/plugins/plugins.c +++ b/paint/plugins/plugins.c @@ -14,6 +14,7 @@ void *io_psd_parse(uint8_t *buf, size_t len, const char *filename); void *io_tiff_parse(uint8_t *buf, size_t len); void *io_gltf_parse(char *buf, size_t size, const char *path); void *io_gltf_parse_skinned(char *buf, size_t size, const char *path, int frame); +int io_gltf_frame_count(); void *io_fbx_parse(char *buf, size_t size); void *io_fbx_parse_skinned(char *buf, size_t size, int frame); void proc_uv_unwrap(void *mesh); @@ -115,6 +116,10 @@ bool plugins_skin_data_apply(buffer_t *blob, int frame, i16_array_t *posa, i16_a return true; } +int plugins_skin_frame_count() { + return io_gltf_frame_count(); +} + static void *import_gltf_glb(char *path) { buffer_t *b = data_get_blob(path); data_delete_blob(path); diff --git a/paint/sources/project.c b/paint/sources/project.c index 6982f81b..fa55ab04 100644 --- a/paint/sources/project.c +++ b/paint/sources/project.c @@ -376,6 +376,17 @@ void project_reimport_mesh() { } } +i32 project_skin_frames() { + i32 frames = 0; + for (i32 i = 0; i < g_project->_->paint_objects->length; ++i) { + mesh_data_t *md = ((mesh_object_t *)g_project->_->paint_objects->buffer[i])->data; + if (md->_->skin_frames > frames) { + frames = md->_->skin_frames; + } + } + return frames; +} + bool project_reskin_mesh(int frame) { #ifdef WITH_PLUGINS bool any = false; @@ -385,12 +396,17 @@ bool project_reskin_mesh(int frame) { continue; } + // Each mesh loops over its own animation length + i32 mesh_frame = md->_->skin_frames > 0 ? frame % md->_->skin_frames : frame; + vertex_array_t *pos = mesh_data_get_vertex_array(md, "pos"); vertex_array_t *nor = mesh_data_get_vertex_array(md, "nor"); - if (!plugins_skin_data_apply(md->_->skin_blob, frame, pos->values, nor->values, &md->scale_pos)) { + if (!plugins_skin_data_apply(md->_->skin_blob, mesh_frame, pos->values, nor->values, &md->scale_pos)) { continue; } + md->_->skin_frames = plugins_skin_frame_count(); + mesh_data_build_vertices(md->_->vertex_buffer, md->vertex_arrays); any = true; }