Pose Brush: Option to disable the IK anchor point

The IK chain was using an anchor point by default as it makes sense for
posing, but for creating curved shapes it is useful to be able to
disable it.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D6584
This commit is contained in:
Pablo Dobarro 2020-02-11 19:43:36 +01:00
parent 015d5eda88
commit 0ab7e32158
6 changed files with 29 additions and 9 deletions

View File

@ -620,6 +620,7 @@ def brush_settings(layout, context, brush, popover=False):
layout.prop(brush, "pose_offset")
layout.prop(brush, "pose_smooth_iterations")
layout.prop(brush, "pose_ik_segments")
layout.prop(brush, "use_pose_ik_anchored")
layout.separator()
if brush.sculpt_tool == 'SCRAPE':

View File

@ -1000,6 +1000,7 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_POSE:
br->pose_smooth_iterations = 4;
br->pose_ik_segments = 1;
br->flag2 |= BRUSH_POSE_IK_ANCHORED;
br->flag &= ~BRUSH_ALPHA_PRESSURE;
br->flag &= ~BRUSH_SPACE;
br->flag &= ~BRUSH_SPACE_ATTEN;

View File

@ -4440,5 +4440,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
br->pose_ik_segments = 1;
}
}
/* Pose brush keep anchor point. */
for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
if (br->sculpt_tool == SCULPT_TOOL_POSE) {
br->flag2 |= BRUSH_POSE_IK_ANCHORED;
}
}
}
}

View File

@ -3576,7 +3576,9 @@ static void sculpt_flip_quat_by_symm_area(float quat[3],
}
}
static void pose_solve_ik_chain(SculptPoseIKChain *ik_chain, const float initial_target[3])
static void pose_solve_ik_chain(SculptPoseIKChain *ik_chain,
const float initial_target[3],
const bool use_anchor)
{
SculptPoseIKChainSegment *segments = ik_chain->segments;
int tot_segments = ik_chain->tot_segments;
@ -3615,13 +3617,15 @@ static void pose_solve_ik_chain(SculptPoseIKChain *ik_chain, const float initial
}
/* Move back the whole chain to preserve the anchor point. */
float anchor_diff[3];
sub_v3_v3v3(
anchor_diff, segments[tot_segments - 1].initial_orig, segments[tot_segments - 1].orig);
if (use_anchor) {
float anchor_diff[3];
sub_v3_v3v3(
anchor_diff, segments[tot_segments - 1].initial_orig, segments[tot_segments - 1].orig);
for (int i = 0; i < tot_segments; i++) {
add_v3_v3(segments[i].orig, anchor_diff);
add_v3_v3(segments[i].head, anchor_diff);
for (int i = 0; i < tot_segments; i++) {
add_v3_v3(segments[i].orig, anchor_diff);
add_v3_v3(segments[i].head, anchor_diff);
}
}
}
@ -3742,8 +3746,8 @@ static void do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
copy_v3_v3(ik_target, ss->cache->true_location);
add_v3_v3(ik_target, ss->cache->grab_delta);
/* Solve the IK positions */
pose_solve_ik_chain(ik_chain, ik_target);
/* Solve the IK positions. */
pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED);
}
/* Flip the segment chain in all symmetry axis and calculate the transform matrices for each

View File

@ -458,6 +458,7 @@ typedef enum eBrushSamplingFlags {
typedef enum eBrushFlags2 {
BRUSH_MULTIPLANE_SCRAPE_DYNAMIC = (1 << 0),
BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW = (1 << 1),
BRUSH_POSE_IK_ANCHORED = (1 << 2),
} eBrushFlags2;
typedef enum {

View File

@ -2099,6 +2099,12 @@ static void rna_def_brush(BlenderRNA *brna)
prop, "Show Cursor Preview", "Preview the scrape planes in the cursor during the stroke");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_pose_ik_anchored", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_POSE_IK_ANCHORED);
RNA_def_property_ui_text(
prop, "Keep Anchor Point", "Keep the position of the last segmend in the IK chain fixed");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "invert_to_scrape_fill", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_INVERT_TO_SCRAPE_FILL);
RNA_def_property_ui_text(prop,