mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
Add mutable_bone_axes to IKs
This commit is contained in:
parent
ef34c3d534
commit
031fd66fed
18 changed files with 760 additions and 155 deletions
|
|
@ -189,6 +189,9 @@ void SplineIK3D::_init_joints(Skeleton3D *p_skeleton, int p_index) {
|
|||
SplineIK3DSetting *setting = sp_settings[p_index];
|
||||
cached_space = p_skeleton->get_global_transform_interpolated();
|
||||
if (!setting->simulation_dirty) {
|
||||
if (mutable_bone_axes) {
|
||||
_update_bone_axis(p_skeleton, p_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (uint32_t i = 0; i < setting->solver_info_list.size(); i++) {
|
||||
|
|
@ -205,7 +208,7 @@ void SplineIK3D::_init_joints(Skeleton3D *p_skeleton, int p_index) {
|
|||
setting->chain.push_back(p_skeleton->get_bone_global_pose(setting->joints[i].bone).origin);
|
||||
bool last = i == setting->joints.size() - 1;
|
||||
if (last && extend_end_bone && setting->end_bone_length > 0) {
|
||||
Vector3 axis = get_bone_axis(setting->end_bone.bone, setting->end_bone_direction);
|
||||
Vector3 axis = IKModifier3D::get_bone_axis(p_skeleton, setting->end_bone.bone, setting->end_bone_direction, mutable_bone_axes);
|
||||
if (axis.is_zero_approx()) {
|
||||
setting->chain_length_accum[i] = accum;
|
||||
continue;
|
||||
|
|
@ -230,6 +233,14 @@ void SplineIK3D::_init_joints(Skeleton3D *p_skeleton, int p_index) {
|
|||
setting->chain_length_accum[i] = accum;
|
||||
}
|
||||
|
||||
if (mutable_bone_axes) {
|
||||
_update_bone_axis(p_skeleton, p_index);
|
||||
#ifdef TOOLS_ENABLED
|
||||
} else {
|
||||
_make_gizmo_dirty();
|
||||
#endif // TOOLS_ENABLED
|
||||
}
|
||||
|
||||
setting->init_current_joint_rotations(p_skeleton);
|
||||
|
||||
setting->simulation_dirty = false;
|
||||
|
|
@ -243,6 +254,56 @@ void SplineIK3D::_make_simulation_dirty(int p_index) {
|
|||
setting->simulation_dirty = true;
|
||||
}
|
||||
|
||||
void SplineIK3D::_update_bone_axis(Skeleton3D *p_skeleton, int p_index) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool changed = false;
|
||||
#endif // TOOLS_ENABLED
|
||||
SplineIK3DSetting *setting = sp_settings[p_index];
|
||||
const LocalVector<BoneJoint> &joints = setting->joints;
|
||||
const LocalVector<IKModifier3DSolverInfo *> &solver_info_list = setting->solver_info_list;
|
||||
int len = (int)solver_info_list.size() - 1;
|
||||
for (int j = 0; j < len; j++) {
|
||||
if (!solver_info_list[j]) {
|
||||
continue;
|
||||
}
|
||||
Vector3 axis = p_skeleton->get_bone_pose(joints[j + 1].bone).origin;
|
||||
if (axis.is_zero_approx()) {
|
||||
continue;
|
||||
}
|
||||
// Less computing.
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (!changed) {
|
||||
Vector3 old_v = solver_info_list[j]->forward_vector;
|
||||
solver_info_list[j]->forward_vector = axis.normalized();
|
||||
changed = changed || !old_v.is_equal_approx(solver_info_list[j]->forward_vector);
|
||||
float old_l = solver_info_list[j]->length;
|
||||
solver_info_list[j]->length = axis.length();
|
||||
changed = changed || !Math::is_equal_approx(old_l, solver_info_list[j]->length);
|
||||
} else {
|
||||
solver_info_list[j]->forward_vector = axis.normalized();
|
||||
solver_info_list[j]->length = axis.length();
|
||||
}
|
||||
#else
|
||||
solver_info_list[j]->forward_vector = axis.normalized();
|
||||
solver_info_list[j]->length = axis.length();
|
||||
#endif // TOOLS_ENABLED
|
||||
}
|
||||
if (setting->extend_end_bone && len >= 0) {
|
||||
if (solver_info_list[len]) {
|
||||
Vector3 axis = IKModifier3D::get_bone_axis(p_skeleton, setting->end_bone.bone, setting->end_bone_direction, mutable_bone_axes);
|
||||
if (!axis.is_zero_approx()) {
|
||||
solver_info_list[len]->forward_vector = axis.normalized();
|
||||
solver_info_list[len]->length = setting->end_bone_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (changed) {
|
||||
_make_gizmo_dirty();
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
}
|
||||
|
||||
void SplineIK3D::_process_ik(Skeleton3D *p_skeleton, double p_delta) {
|
||||
for (uint32_t i = 0; i < settings.size(); i++) {
|
||||
_init_joints(p_skeleton, i);
|
||||
|
|
@ -430,6 +491,30 @@ void SplineIK3D::_process_joints(double p_delta, Skeleton3D *p_skeleton, SplineI
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Vector3 SplineIK3D::get_bone_vector(int p_index, int p_joint) const {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return Vector3();
|
||||
}
|
||||
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), Vector3());
|
||||
SplineIK3DSetting *setting = sp_settings[p_index];
|
||||
if (!setting) {
|
||||
return Vector3();
|
||||
}
|
||||
const LocalVector<BoneJoint> &joints = setting->joints;
|
||||
ERR_FAIL_INDEX_V(p_joint, (int)joints.size(), Vector3());
|
||||
const LocalVector<IKModifier3DSolverInfo *> &solver_info_list = setting->solver_info_list;
|
||||
if (p_joint >= (int)solver_info_list.size() || !solver_info_list[p_joint]) {
|
||||
if (p_joint == (int)joints.size() - 1) {
|
||||
return IKModifier3D::get_bone_axis(skeleton, setting->end_bone.bone, setting->end_bone_direction, mutable_bone_axes) * setting->end_bone_length;
|
||||
}
|
||||
return mutable_bone_axes ? skeleton->get_bone_pose(joints[p_joint + 1].bone).origin : skeleton->get_bone_rest(joints[p_joint + 1].bone).origin;
|
||||
}
|
||||
return solver_info_list[p_joint]->forward_vector * solver_info_list[p_joint]->length;
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
SplineIK3D::~SplineIK3D() {
|
||||
clear_settings();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue