Fix #133969: Crazyspace broken with bezier curves and armature modifier
The issue was that the topology of the drawing changes when the bezier curves get resampled to poly curves in the armature modifier. This means that the crazyspace code fails to find deformed positions with the same length as the original positions. The fix does multiple things: * First, we make sure that we create an `GeometryComponentEditData` in weight paint mode. * When the armature modifier runs, we remember the current positions in this component. * Then, we store the curve offsets and weights _before_ converting the bezier curves. * Finally we deform the positions stored in the edit hint component (which have the same length as the original positions). Since the resampling just adds new points, there might be a way to avoid running the armature deformation a second time on the edit hints, but I'll leave that for another day as a performance improvement. In any case, this is only done when we actually need the deformation (e.g. in weight paint mode when we paint the weights). Pull Request: https://projects.blender.org/blender/blender/pulls/134030
This commit is contained in:
@@ -2201,9 +2201,14 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
|
||||
if (layer_attributes.contains("tint_color") || layer_attributes.contains("radius_offset")) {
|
||||
grease_pencil_do_layer_adjustments(*geometry_set.get_grease_pencil_for_write());
|
||||
}
|
||||
/* Only add the edit hint component in edit mode or sculpt mode for now so users can properly
|
||||
* select deformed drawings. */
|
||||
if (ELEM(object->mode, OB_MODE_EDIT, OB_MODE_SCULPT_GREASE_PENCIL)) {
|
||||
/* Only add the edit hint component in modes where users can potentially interact with deformed
|
||||
* drawings. */
|
||||
if (ELEM(object->mode,
|
||||
OB_MODE_EDIT,
|
||||
OB_MODE_SCULPT_GREASE_PENCIL,
|
||||
OB_MODE_VERTEX_GREASE_PENCIL,
|
||||
OB_MODE_WEIGHT_GREASE_PENCIL))
|
||||
{
|
||||
GeometryComponentEditData &edit_component =
|
||||
geometry_set.get_component_for_write<GeometryComponentEditData>();
|
||||
edit_component.grease_pencil_edit_hints_ = std::make_unique<GreasePencilEditHints>(
|
||||
|
||||
@@ -116,7 +116,21 @@ static void modify_curves(ModifierData &md,
|
||||
bke::GreasePencilDrawingEditHints *edit_hints)
|
||||
{
|
||||
auto &amd = reinterpret_cast<GreasePencilArmatureModifierData &>(md);
|
||||
modifier::greasepencil::ensure_no_bezier_curves(drawing);
|
||||
|
||||
const bool has_bezier_curves = drawing.strokes().has_curve_with_type(
|
||||
CurveType::CURVE_TYPE_BEZIER);
|
||||
|
||||
Array<int> orig_offsets;
|
||||
Array<MDeformVert> orig_dverts;
|
||||
OffsetIndices<int> orig_points_by_curve;
|
||||
if (has_bezier_curves) {
|
||||
if (edit_hints) {
|
||||
orig_dverts = drawing.strokes().deform_verts();
|
||||
orig_offsets = drawing.strokes().offsets();
|
||||
orig_points_by_curve = OffsetIndices<int>(orig_offsets.as_span());
|
||||
}
|
||||
modifier::greasepencil::ensure_no_bezier_curves(drawing);
|
||||
}
|
||||
bke::CurvesGeometry &curves = drawing.strokes_for_write();
|
||||
|
||||
/* The influence flag is where the "invert" flag is stored,
|
||||
@@ -144,12 +158,16 @@ static void modify_curves(ModifierData &md,
|
||||
Span<float3> old_positions = {static_cast<const float3 *>(old_positions_data.data),
|
||||
curves.points_num()};
|
||||
|
||||
std::optional<MutableSpan<float3>> deform_positions;
|
||||
std::optional<MutableSpan<float3x3>> deform_mats;
|
||||
if (edit_hints) {
|
||||
if (!edit_hints->deform_mats.has_value()) {
|
||||
edit_hints->deform_mats.emplace(drawing.strokes().points_num(), float3x3::identity());
|
||||
}
|
||||
deform_mats = edit_hints->deform_mats->as_mutable_span();
|
||||
if (has_bezier_curves) {
|
||||
deform_positions = edit_hints->positions_for_write();
|
||||
}
|
||||
}
|
||||
|
||||
curves_mask.foreach_index(blender::GrainSize(128), [&](const int curve_i) {
|
||||
@@ -171,6 +189,18 @@ static void modify_curves(ModifierData &md,
|
||||
dverts.slice(points),
|
||||
deformflag,
|
||||
amd.influence.vertex_group_name);
|
||||
if (deform_positions) {
|
||||
const IndexRange orig_points = orig_points_by_curve[curve_i];
|
||||
BKE_armature_deform_coords_with_curves(*amd.object,
|
||||
*ctx.object,
|
||||
&curves.vertex_group_names,
|
||||
deform_positions->slice(orig_points),
|
||||
{},
|
||||
{},
|
||||
orig_dverts.as_span().slice(orig_points),
|
||||
deformflag,
|
||||
amd.influence.vertex_group_name);
|
||||
}
|
||||
});
|
||||
|
||||
drawing.tag_positions_changed();
|
||||
@@ -187,6 +217,8 @@ static void modify_geometry_set(ModifierData *md,
|
||||
if (!geometry_set->has_grease_pencil()) {
|
||||
return;
|
||||
}
|
||||
bke::GeometryComponentEditData::remember_deformed_positions_if_necessary(*geometry_set);
|
||||
|
||||
GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write();
|
||||
const GreasePencil &grease_pencil_orig = *reinterpret_cast<GreasePencil *>(
|
||||
DEG_get_original_id(&grease_pencil.id));
|
||||
|
||||
Reference in New Issue
Block a user