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); } } }
int SSBoneFrame_CheckTargetBoneLimit(struct ss_bone_frame_s *bf, struct ss_bone_tag_s *b_tag, float target[3]) { float target_dir[3], target_local[3], limit_dir[3], t; Mat4_vec3_mul_inv(target_local, bf->transform->M4x4, target); 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_norm(target_dir, t); vec3_copy(limit_dir, b_tag->mod.limit); if((b_tag->mod.limit[3] == -1.0f) || (vec3_dot(limit_dir, target_dir) > b_tag->mod.limit[3])) { return 1; } return 0; }
int SSBoneFrame_CheckTargetBoneLimit(struct ss_bone_frame_s *bf, struct ss_animation_s *ss_anim) { ss_bone_tag_p b_tag = b_tag = bf->bone_tags + ss_anim->targeting_bone; float target_dir[3], target_local[3], limit_dir[3], t; 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); vec3_norm(target_dir, t); vec3_copy(limit_dir, ss_anim->targeting_limit); if((ss_anim->targeting_limit[3] == -1.0f) || (vec3_dot(limit_dir, target_dir) > ss_anim->targeting_limit[3])) { return 1; } return 0; }