void SSBoneFrame_InitSSAnim(struct ss_animation_s *ss_anim, uint32_t anim_type_id) { ss_anim->anim_ext_flags = 0x00; ss_anim->anim_frame_flags = 0x00; ss_anim->type = anim_type_id; ss_anim->enabled = 1; ss_anim->model = NULL; ss_anim->onFrame = NULL; ss_anim->onEndFrame = NULL; ss_anim->targeting_bone = 0x00; ss_anim->targeting_flags = 0x0000; vec3_set_zero(ss_anim->target); vec4_set_zero_angle(ss_anim->current_mod); ss_anim->bone_direction[0] = 0.0f; ss_anim->bone_direction[1] = 1.0f; ss_anim->bone_direction[2] = 0.0f; ss_anim->targeting_limit[0] = 0.0f; ss_anim->targeting_limit[1] = 1.0f; ss_anim->targeting_limit[2] = 0.0f; ss_anim->targeting_limit[3] =-1.0f; vec3_set_one(ss_anim->targeting_axis_mod); ss_anim->frame_time = 0.0f; ss_anim->next_state = 0; ss_anim->lerp = 0.0; ss_anim->current_animation = 0; ss_anim->current_frame = 0; ss_anim->next_animation = 0; ss_anim->next_frame = 0; ss_anim->period = 1.0f / 30.0f; ss_anim->next = NULL; ss_anim->prev = NULL; }
void SSBoneFrame_CreateFromModel(ss_bone_frame_p bf, skeletal_model_p model) { vec3_set_zero(bf->bb_min); vec3_set_zero(bf->bb_max); vec3_set_zero(bf->centre); vec3_set_zero(bf->pos); bf->animations.type = ANIM_TYPE_BASE; bf->animations.anim_frame_flags = 0x0000; bf->animations.anim_ext_flags = 0x0000; bf->animations.frame_time = 0.0; bf->animations.period = 1.0 / 30.0; bf->animations.next_state = 0; bf->animations.lerp = 0.0; bf->animations.current_animation = 0; bf->animations.current_frame = 0; bf->animations.next_animation = 0; bf->animations.next_frame = 0; vec3_set_zero(bf->animations.target); bf->animations.bone_direction[0] = 0.0f; bf->animations.bone_direction[1] = 1.0f; bf->animations.bone_direction[2] = 0.0f; bf->animations.targeting_limit[0] = 0.0f; bf->animations.targeting_limit[1] = 1.0f; bf->animations.targeting_limit[2] = 0.0f; bf->animations.targeting_limit[3] =-1.0f; vec3_set_one(bf->animations.targeting_axis_mod); bf->animations.targeting_bone = 0x00; bf->animations.targeting_flags = 0x0000; vec4_set_zero_angle(bf->animations.current_mod); bf->animations.next = NULL; bf->animations.onFrame = NULL; bf->animations.onEndFrame = NULL; bf->transform = NULL; bf->animations.model = model; bf->bone_tag_count = model->mesh_count; bf->bone_tags = (ss_bone_tag_p)malloc(bf->bone_tag_count * sizeof(ss_bone_tag_t)); bf->bone_tags[0].parent = NULL; // root for(uint16_t i = 0; i < bf->bone_tag_count; i++) { bf->bone_tags[i].index = i; bf->bone_tags[i].mesh_base = model->mesh_tree[i].mesh_base; bf->bone_tags[i].mesh_skin = model->mesh_tree[i].mesh_skin; bf->bone_tags[i].mesh_slot = NULL; bf->bone_tags[i].alt_anim = NULL; bf->bone_tags[i].body_part = model->mesh_tree[i].body_part; vec3_copy(bf->bone_tags[i].offset, model->mesh_tree[i].offset); vec4_set_zero(bf->bone_tags[i].qrotate); Mat4_E_macro(bf->bone_tags[i].transform); Mat4_E_macro(bf->bone_tags[i].full_transform); if(i > 0) { bf->bone_tags[i].parent = bf->bone_tags + model->mesh_tree[i].parent; } } }
void SSBoneFrame_CreateFromModel(ss_bone_frame_p bf, skeletal_model_p model) { vec3_set_zero(bf->bb_min); vec3_set_zero(bf->bb_max); vec3_set_zero(bf->centre); vec3_set_zero(bf->pos); bf->transform = NULL; bf->flags = 0x0000; bf->bone_tag_count = 0; bf->bone_tags = NULL; SSBoneFrame_InitSSAnim(&bf->animations, model, ANIM_TYPE_BASE); bf->animations.model = model; if(model) { bf->bone_tag_count = model->mesh_count; bf->bone_tags = (ss_bone_tag_p)malloc(bf->bone_tag_count * sizeof(ss_bone_tag_t)); bf->bone_tags[0].parent = NULL; // root for(uint16_t i = 0; i < bf->bone_tag_count; i++) { ss_bone_tag_p b_tag = bf->bone_tags + i; b_tag->index = i; b_tag->is_hidden = 0x00; b_tag->is_targeted = 0x00; b_tag->is_axis_modded = 0x00; b_tag->mesh_base = model->mesh_tree[i].mesh_base; b_tag->mesh_replace = NULL; b_tag->mesh_skin = NULL; b_tag->mesh_slot = NULL; b_tag->skin_map = NULL; b_tag->alt_anim = NULL; b_tag->body_part = model->mesh_tree[i].body_part; vec3_copy(b_tag->offset, model->mesh_tree[i].offset); vec4_set_zero(b_tag->qrotate); Mat4_E_macro(b_tag->local_transform); Mat4_E_macro(b_tag->current_transform); vec3_set_zero(b_tag->mod.target_pos); vec4_set_zero_angle(b_tag->mod.current_q); b_tag->mod.bone_local_direction[0] = 0.0f; b_tag->mod.bone_local_direction[1] = 1.0f; b_tag->mod.bone_local_direction[2] = 0.0f; b_tag->mod.limit[0] = 0.0f; b_tag->mod.limit[1] = 1.0f; b_tag->mod.limit[2] = 0.0f; b_tag->mod.limit[3] =-1.0f; b_tag->mod.current_slerp = 1.0f; vec3_set_one(b_tag->mod.axis_mod); if(i > 0) { b_tag->parent = bf->bone_tags + model->mesh_tree[i].parent; } } } }
void SSBoneFrame_TargetBoneToSlerp(struct ss_bone_frame_s *bf, struct ss_animation_s *ss_anim) { extern float engine_frame_time; if(ss_anim->anim_ext_flags & ANIM_EXT_TARGET_TO) { ss_bone_tag_p b_tag = bf->bone_tags + ss_anim->targeting_bone; float clamped_q[4], q[4], target_dir[3], target_local[3], bone_dir[3]; Mat4_vec3_mul_inv(target_local, bf->transform, ss_anim->target); if(b_tag->parent) { Mat4_vec3_mul_inv(target_local, b_tag->parent->full_transform, target_local); } vec3_sub(target_dir, target_local, b_tag->transform + 12); if(ss_anim->targeting_flags & ANIM_TARGET_OWERRIDE_ANIM) { Mat4_vec3_rot_macro(bone_dir, b_tag->transform, ss_anim->bone_direction); } else { vec3_copy(bone_dir, ss_anim->bone_direction); } vec4_GetQuaternionRotation(q, bone_dir, target_dir); if(ss_anim->targeting_flags & ANIM_TARGET_USE_AXIS_MOD) { q[0] *= ss_anim->targeting_axis_mod[0]; q[1] *= ss_anim->targeting_axis_mod[1]; q[2] *= ss_anim->targeting_axis_mod[2]; q[3] = 1.0f - vec3_sqabs(q); q[3] = sqrtf(q[3]); } if(q[3] < ss_anim->targeting_limit[3]) { vec4_clampw(q, ss_anim->targeting_limit[3]); } vec4_slerp_to(clamped_q, ss_anim->current_mod, q, engine_frame_time * M_PI / 1.3f); vec4_copy(ss_anim->current_mod, clamped_q); SSBoneFrame_RotateBone(bf, ss_anim->current_mod, ss_anim->targeting_bone); } else if(ss_anim->current_mod[3] < 1.0f) { if(ss_anim->current_mod[3] < 0.99f) { float zero_ang[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float clamped_q[4]; vec4_slerp_to(clamped_q, ss_anim->current_mod, zero_ang, engine_frame_time * M_PI / 1.3f); vec4_copy(ss_anim->current_mod, clamped_q); SSBoneFrame_RotateBone(bf, ss_anim->current_mod, ss_anim->targeting_bone); } else { vec4_set_zero_angle(ss_anim->current_mod); } } }
void SSBoneFrame_TargetBoneToSlerp(struct ss_bone_frame_s *bf, struct ss_bone_tag_s *b_tag, float time) { b_tag->mod.current_slerp = 1.0f; if(b_tag->is_targeted) { float clamped_q[4], q[4], target_dir[3], target_local[3], bone_dir[3]; Mat4_vec3_mul_inv(target_local, bf->transform->M4x4, b_tag->mod.target_pos); if(b_tag->parent) { Mat4_vec3_mul_inv(target_local, b_tag->parent->current_transform, target_local); } vec3_sub(target_dir, target_local, b_tag->local_transform + 12); vec3_copy(bone_dir, b_tag->mod.bone_local_direction); vec4_GetQuaternionRotation(q, bone_dir, target_dir); if(q[3] < b_tag->mod.limit[3]) { vec4_clampw(q, b_tag->mod.limit[3]); } if(b_tag->is_axis_modded) { q[0] *= b_tag->mod.axis_mod[0]; q[1] *= b_tag->mod.axis_mod[1]; q[2] *= b_tag->mod.axis_mod[2]; q[3] = 1.0f - vec3_sqabs(q); q[3] = sqrtf(q[3]); } b_tag->mod.current_slerp = vec4_slerp_to(clamped_q, b_tag->mod.current_q, q, time * M_PI / 1.3f); vec4_copy(b_tag->mod.current_q, clamped_q); SSBoneFrame_RotateBone(bf, b_tag->mod.current_q, b_tag->index); } else if(b_tag->mod.current_q[3] < 1.0f) { if(b_tag->mod.current_q[3] < 0.99f) { float zero_ang[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float clamped_q[4]; vec4_slerp_to(clamped_q, b_tag->mod.current_q, zero_ang, time * M_PI / 1.3f); vec4_copy(b_tag->mod.current_q, clamped_q); SSBoneFrame_RotateBone(bf, b_tag->mod.current_q, b_tag->index); } else { vec4_set_zero_angle(b_tag->mod.current_q); } } }
struct ss_animation_s *SSBoneFrame_AddOverrideAnim(struct ss_bone_frame_s *bf, struct skeletal_model_s *sm, uint16_t anim_type) { if(!sm || (sm->mesh_count == bf->bone_tag_count)) { ss_animation_p ss_anim = (ss_animation_p)malloc(sizeof(ss_animation_t)); ss_anim->anim_ext_flags = 0x00; ss_anim->anim_frame_flags = 0x00; ss_anim->type = anim_type; ss_anim->model = sm; ss_anim->onFrame = NULL; ss_anim->onEndFrame = NULL; ss_anim->targeting_bone = 0; ss_anim->targeting_flags = 0x0000; vec3_set_zero(ss_anim->target); vec4_set_zero_angle(ss_anim->current_mod); ss_anim->bone_direction[0] = 0.0f; ss_anim->bone_direction[1] = 1.0f; ss_anim->bone_direction[2] = 0.0f; ss_anim->targeting_limit[0] = 0.0f; ss_anim->targeting_limit[1] = 1.0f; ss_anim->targeting_limit[2] = 0.0f; ss_anim->targeting_limit[3] =-1.0f; vec3_set_one(ss_anim->targeting_axis_mod); ss_anim->next = bf->animations.next; bf->animations.next = ss_anim; ss_anim->frame_time = 0.0; ss_anim->next_state = 0; ss_anim->lerp = 0.0; ss_anim->current_animation = 0; ss_anim->current_frame = 0; ss_anim->next_animation = 0; ss_anim->next_frame = 0; ss_anim->period = 1.0f / 30.0f; return ss_anim; } return NULL; }