void SSBoneFrame_Update(struct ss_bone_frame_s *bf, float time) { float t = 1.0f - bf->animations.lerp; ss_bone_tag_p btag = bf->bone_tags; bone_tag_p src_btag, next_btag; bone_frame_p prev_bf = &bf->animations.prev_bf; bone_frame_p curr_bf = &bf->animations.current_bf; vec3_interpolate_macro(bf->bb_max, prev_bf->bb_max, curr_bf->bb_max, bf->animations.lerp, t); vec3_interpolate_macro(bf->bb_min, prev_bf->bb_min, curr_bf->bb_min, bf->animations.lerp, t); vec3_interpolate_macro(bf->centre, prev_bf->centre, curr_bf->centre, bf->animations.lerp, t); vec3_interpolate_macro(bf->pos, prev_bf->pos, curr_bf->pos, bf->animations.lerp, t); next_btag = curr_bf->bone_tags; src_btag = prev_bf->bone_tags; for(uint16_t k = 0; k < prev_bf->bone_tag_count; k++, btag++, src_btag++, next_btag++) { vec3_interpolate_macro(btag->offset, src_btag->offset, next_btag->offset, bf->animations.lerp, t); vec3_copy(btag->local_transform + 12, btag->offset); btag->local_transform[15] = 1.0f; if(k == 0) { vec3_add(btag->local_transform + 12, btag->local_transform + 12, bf->pos); vec4_slerp(btag->qrotate, src_btag->qrotate, next_btag->qrotate, bf->animations.lerp); } else { bone_tag_p ov_src_btag = src_btag; bone_tag_p ov_next_btag = next_btag; float ov_lerp = bf->animations.lerp; if(btag->alt_anim && btag->alt_anim->model && btag->alt_anim->enabled && (btag->alt_anim->model->mesh_tree[k].replace_anim != 0)) { bone_frame_p ov_curr_bf = &btag->alt_anim->prev_bf; bone_frame_p ov_next_bf = &btag->alt_anim->current_bf; ov_lerp = btag->alt_anim->lerp; ov_src_btag = ov_curr_bf->bone_tags + k; ov_next_btag = ov_next_bf->bone_tags + k; } vec4_slerp(btag->qrotate, ov_src_btag->qrotate, ov_next_btag->qrotate, ov_lerp); } Mat4_set_qrotation(btag->local_transform, btag->qrotate); } /* * build absolute coordinate matrix system */ btag = bf->bone_tags; Mat4_Copy(btag->current_transform, btag->local_transform); btag++; for(uint16_t k = 1; k < prev_bf->bone_tag_count; k++, btag++) { Mat4_Mat4_mul(btag->current_transform, btag->parent->current_transform, btag->local_transform); SSBoneFrame_TargetBoneToSlerp(bf, btag, time); } }
void SSBoneFrame_Update(struct ss_bone_frame_s *bf) { float cmd_tr[3], tr[3], t; ss_bone_tag_p btag = bf->bone_tags; bone_tag_p src_btag, next_btag; skeletal_model_p model = bf->animations.model; bone_frame_p curr_bf, next_bf; next_bf = model->animations[bf->animations.next_animation].frames + bf->animations.next_frame; curr_bf = model->animations[bf->animations.current_animation].frames + bf->animations.current_frame; t = 1.0 - bf->animations.lerp; if(bf->transform && (curr_bf->command & ANIM_CMD_MOVE)) { Mat4_vec3_rot_macro(tr, bf->transform, curr_bf->move); vec3_mul_scalar(cmd_tr, tr, bf->animations.lerp); } else { vec3_set_zero(tr); vec3_set_zero(cmd_tr); } vec3_interpolate_macro(bf->bb_max, curr_bf->bb_max, next_bf->bb_max, bf->animations.lerp, t); vec3_add(bf->bb_max, bf->bb_max, cmd_tr); vec3_interpolate_macro(bf->bb_min, curr_bf->bb_min, next_bf->bb_min, bf->animations.lerp, t); vec3_add(bf->bb_min, bf->bb_min, cmd_tr); vec3_interpolate_macro(bf->centre, curr_bf->centre, next_bf->centre, bf->animations.lerp, t); vec3_add(bf->centre, bf->centre, cmd_tr); vec3_interpolate_macro(bf->pos, curr_bf->pos, next_bf->pos, bf->animations.lerp, t); vec3_add(bf->pos, bf->pos, cmd_tr); next_btag = next_bf->bone_tags; src_btag = curr_bf->bone_tags; for(uint16_t k = 0; k < curr_bf->bone_tag_count; k++, btag++, src_btag++, next_btag++) { vec3_interpolate_macro(btag->offset, src_btag->offset, next_btag->offset, bf->animations.lerp, t); vec3_copy(btag->transform+12, btag->offset); btag->transform[15] = 1.0; if(k == 0) { vec3_add(btag->transform+12, btag->transform+12, bf->pos); vec4_slerp(btag->qrotate, src_btag->qrotate, next_btag->qrotate, bf->animations.lerp); } else { bone_tag_p ov_src_btag = src_btag; bone_tag_p ov_next_btag = next_btag; float ov_lerp = bf->animations.lerp; if(btag->alt_anim && btag->alt_anim->model && (btag->alt_anim->model->mesh_tree[k].replace_anim != 0)) { bone_frame_p ov_curr_bf = btag->alt_anim->model->animations[btag->alt_anim->current_animation].frames + btag->alt_anim->current_frame; bone_frame_p ov_next_bf = btag->alt_anim->model->animations[btag->alt_anim->next_animation].frames + btag->alt_anim->next_frame; ov_src_btag = ov_curr_bf->bone_tags + k; ov_next_btag = ov_next_bf->bone_tags + k; ov_lerp = btag->alt_anim->lerp; } vec4_slerp(btag->qrotate, ov_src_btag->qrotate, ov_next_btag->qrotate, ov_lerp); } Mat4_set_qrotation(btag->transform, btag->qrotate); } /* * build absolute coordinate matrix system */ btag = bf->bone_tags; Mat4_Copy(btag->full_transform, btag->transform); btag++; for(uint16_t k = 1; k < curr_bf->bone_tag_count; k++, btag++) { Mat4_Mat4_mul(btag->full_transform, btag->parent->full_transform, btag->transform); } for(ss_animation_p ss_anim = &bf->animations; ss_anim; ss_anim = ss_anim->next) { SSBoneFrame_TargetBoneToSlerp(bf, ss_anim); } }
void SkeletalModel_InterpolateFrames(skeletal_model_p model) { uint16_t new_frames_count; animation_frame_p anim = model->animations; bone_frame_p bf, new_bone_frames; float lerp, t; for(uint16_t i = 0; i < model->animation_count; i++, anim++) { if(anim->frames_count > 1 && anim->original_frame_rate > 1) // we can't interpolate one frame or rate < 2! { new_frames_count = (uint16_t)anim->original_frame_rate * (anim->frames_count - 1) + 1; bf = new_bone_frames = (bone_frame_p)malloc(new_frames_count * sizeof(bone_frame_t)); /* * the first frame does not changes */ bf->bone_tags = (bone_tag_p)malloc(model->mesh_count * sizeof(bone_tag_t)); bf->bone_tag_count = model->mesh_count; vec3_set_zero(bf->pos); vec3_set_zero(bf->move); bf->command = 0x00; vec3_copy(bf->centre, anim->frames[0].centre); vec3_copy(bf->pos, anim->frames[0].pos); vec3_copy(bf->bb_max, anim->frames[0].bb_max); vec3_copy(bf->bb_min, anim->frames[0].bb_min); for(uint16_t k = 0; k < model->mesh_count; k++) { vec3_copy(bf->bone_tags[k].offset, anim->frames[0].bone_tags[k].offset); vec4_copy(bf->bone_tags[k].qrotate, anim->frames[0].bone_tags[k].qrotate); } bf++; for(uint16_t j = 1; j < anim->frames_count; j++) { for(uint16_t lerp_index = 1; lerp_index <= anim->original_frame_rate; lerp_index++) { vec3_set_zero(bf->pos); vec3_set_zero(bf->move); bf->command = 0x00; lerp = ((float)lerp_index) / (float)anim->original_frame_rate; t = 1.0 - lerp; bf->bone_tags = (bone_tag_p)malloc(model->mesh_count * sizeof(bone_tag_t)); bf->bone_tag_count = model->mesh_count; bf->centre[0] = t * anim->frames[j-1].centre[0] + lerp * anim->frames[j].centre[0]; bf->centre[1] = t * anim->frames[j-1].centre[1] + lerp * anim->frames[j].centre[1]; bf->centre[2] = t * anim->frames[j-1].centre[2] + lerp * anim->frames[j].centre[2]; bf->pos[0] = t * anim->frames[j-1].pos[0] + lerp * anim->frames[j].pos[0]; bf->pos[1] = t * anim->frames[j-1].pos[1] + lerp * anim->frames[j].pos[1]; bf->pos[2] = t * anim->frames[j-1].pos[2] + lerp * anim->frames[j].pos[2]; bf->bb_max[0] = t * anim->frames[j-1].bb_max[0] + lerp * anim->frames[j].bb_max[0]; bf->bb_max[1] = t * anim->frames[j-1].bb_max[1] + lerp * anim->frames[j].bb_max[1]; bf->bb_max[2] = t * anim->frames[j-1].bb_max[2] + lerp * anim->frames[j].bb_max[2]; bf->bb_min[0] = t * anim->frames[j-1].bb_min[0] + lerp * anim->frames[j].bb_min[0]; bf->bb_min[1] = t * anim->frames[j-1].bb_min[1] + lerp * anim->frames[j].bb_min[1]; bf->bb_min[2] = t * anim->frames[j-1].bb_min[2] + lerp * anim->frames[j].bb_min[2]; for(uint16_t k = 0; k < model->mesh_count; k++) { bf->bone_tags[k].offset[0] = t * anim->frames[j-1].bone_tags[k].offset[0] + lerp * anim->frames[j].bone_tags[k].offset[0]; bf->bone_tags[k].offset[1] = t * anim->frames[j-1].bone_tags[k].offset[1] + lerp * anim->frames[j].bone_tags[k].offset[1]; bf->bone_tags[k].offset[2] = t * anim->frames[j-1].bone_tags[k].offset[2] + lerp * anim->frames[j].bone_tags[k].offset[2]; vec4_slerp(bf->bone_tags[k].qrotate, anim->frames[j-1].bone_tags[k].qrotate, anim->frames[j].bone_tags[k].qrotate, lerp); } bf++; } } /* * swap old and new animation bone brames * free old bone frames; */ for(uint16_t j = 0; j < anim->frames_count; j++) { if(anim->frames[j].bone_tag_count) { anim->frames[j].bone_tag_count = 0; free(anim->frames[j].bone_tags); anim->frames[j].bone_tags = NULL; } } free(anim->frames); anim->frames = new_bone_frames; anim->frames_count = new_frames_count; } } }