Skip to content

Conversation

@TokageItLab
Copy link
Member

If deterministic option is true, the previous frame's result is discarded. At this point, the new result is calculated from the bone pose excluding the IterateIK3D as the initial state. This means the result will be always equal as long as the target position and the previous bone pose are the same. However, if angular_delta_limit and max_iterations are set too small, the end bone of the chain will never reach the target.

Setting deterministic option is true and angular_delta_limit to 180 degrees will produce the same results as the old SkeletonIK in FABRIK.

Deterministic FABRIK3D:
image

Old SkeletonIK3D:
image

(As I mentioned in #110120 (comment), the handling of Tips differs)

@TokageItLab TokageItLab requested a review from a team as a code owner November 7, 2025 22:02
@TokageItLab TokageItLab requested review from a team as code owners November 7, 2025 22:02
@TokageItLab TokageItLab moved this to Ready for review in Animation Team Issue Triage Nov 7, 2025
@TokageItLab TokageItLab added this to the 4.6 milestone Nov 7, 2025
@TokageItLab TokageItLab changed the title Add Deterministic option to IK Add Deterministic option to IterateIK3D Nov 8, 2025
Copy link
Member

@fire fire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the enhancement a little.

float rot_axis_length = (global_pose.origin - parent_global_pose.origin).length() * 0.2; // Use 20% of the bone length for the rotation axis vector.
Vector3 axis = global_pose.basis.xform(axis_vector.normalized()) * rot_axis_length;
draw_line(surface_tool, global_pose.origin - axis, global_pose.origin + axis, bone_color);
float rot_axis_length = bone_vector.length() * 0.2; // Use 20% of the bone length for the rotation axis vector.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some reasoning behind the 20% magic constant?

Copy link
Member Author

@TokageItLab TokageItLab Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review should be sent #111815, though there's no particular reason. I suppose it could be set as a fixed value by the EditorSetting.

FYI, the changes added to the behavior in this PR are only below; As explained, it simply resets the state before iteration.

3893c89

void IterateIK3D::_init_joints(Skeleton3D *p_skeleton, int p_index) {
	IterateIK3DSetting *setting = iterate_settings[p_index];
	if (!setting) {
		return;
	}
	cached_space = p_skeleton->get_global_transform_interpolated();
	if (setting->simulation_dirty) {
		_clear_joints(p_index);
		setting->init_joints(p_skeleton, mutable_bone_axes);
		setting->simulation_dirty = false;
	} else if (deterministic) {
		setting->init_joints(p_skeleton, mutable_bone_axes); // <- Here.
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

2 participants