GPv3: Handle vertex groups in the GPv2 conversion operator

Copies vertex group names from the GPv2 object to the new GPv3 GreasePencil data block.
Copies only those names to the drawings that are actually used by any of the strokes.
Updates group indices in `MDeformVert` data to point to local Drawing groups.

Pull Request: https://projects.blender.org/blender/blender/pulls/117860
This commit is contained in:
Lukas Tönne
2024-02-06 12:36:17 +01:00
parent 70fa30007f
commit ee9a0f6014
2 changed files with 78 additions and 1 deletions

View File

@@ -706,6 +706,7 @@ TREENODE_COMMON_METHODS_FORWARD_IMPL(LayerGroup);
namespace convert {
void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const ListBase &vertex_group_names,
GreasePencilDrawing &r_drawing);
void legacy_gpencil_to_grease_pencil(Main &main, GreasePencil &grease_pencil, bGPdata &gpd);

View File

@@ -8,6 +8,7 @@
#include "BKE_attribute.hh"
#include "BKE_curves.hh"
#include "BKE_deform.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_material.h"
@@ -19,10 +20,52 @@
#include "DNA_gpencil_legacy_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_meshdata_types.h"
namespace blender::bke::greasepencil::convert {
/**
* Find vertex groups that have assigned vertices in this drawing.
* Returns:
* - ListBase with used vertex group names (bDeformGroup)
* - Array of indices in the new vertex group list for remapping
*/
static void find_used_vertex_groups(const bGPDframe &gpf,
const ListBase &all_names,
ListBase &r_vertex_group_names,
Array<int> &r_indices)
{
const int num_vertex_groups = BLI_listbase_count(&all_names);
Array<int> is_group_used(num_vertex_groups, false);
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
if (!gps->dvert) {
continue;
}
Span<MDeformVert> dverts = {gps->dvert, gps->totpoints};
for (const MDeformVert &dvert : dverts) {
for (const MDeformWeight &weight : Span<MDeformWeight>{dvert.dw, dvert.totweight}) {
is_group_used[weight.def_nr] = true;
}
}
}
BLI_listbase_clear(&r_vertex_group_names);
r_indices.reinitialize(num_vertex_groups);
int new_group_i = 0;
int old_group_i;
LISTBASE_FOREACH_INDEX (const bDeformGroup *, def_group, &all_names, old_group_i) {
if (!is_group_used[old_group_i]) {
r_indices[old_group_i] = -1;
continue;
}
r_indices[old_group_i] = new_group_i++;
bDeformGroup *def_group_copy = static_cast<bDeformGroup *>(MEM_dupallocN(def_group));
BLI_addtail(&r_vertex_group_names, def_group_copy);
}
}
void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const ListBase &vertex_group_names,
GreasePencilDrawing &r_drawing)
{
/* Construct an empty CurvesGeometry in-place. */
@@ -54,6 +97,25 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
/* All strokes are poly curves. */
curves.fill_curve_types(CURVE_TYPE_POLY);
/* Find used vertex groups in this drawing. */
ListBase stroke_vertex_group_names;
Array<int> stroke_def_nr_map;
find_used_vertex_groups(gpf, vertex_group_names, stroke_vertex_group_names, stroke_def_nr_map);
BLI_assert(BLI_listbase_is_empty(&curves.vertex_group_names));
curves.vertex_group_names = stroke_vertex_group_names;
const bool use_dverts = !BLI_listbase_is_empty(&curves.vertex_group_names);
/* Copy vertex weights and map the vertex group indices. */
auto copy_dvert = [&](const MDeformVert &src_dvert, MDeformVert &dst_dvert) {
dst_dvert = src_dvert;
dst_dvert.dw = static_cast<MDeformWeight *>(MEM_dupallocN(src_dvert.dw));
const MutableSpan<MDeformWeight> vertex_weights = {dst_dvert.dw, dst_dvert.totweight};
for (MDeformWeight &weight : vertex_weights) {
/* Map def_nr to the reduced vertex group list. */
weight.def_nr = stroke_def_nr_map[weight.def_nr];
}
};
/* Point Attributes. */
MutableSpan<float3> positions = curves.positions_for_write();
MutableSpan<float> radii = drawing.radii_for_write();
@@ -66,6 +128,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
attributes.lookup_or_add_for_write_span<ColorGeometry4f>("vertex_color", AttrDomain::Point);
SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
".selection", AttrDomain::Point);
MutableSpan<MDeformVert> dverts = use_dverts ? curves.wrap().deform_verts_for_write() :
MutableSpan<MDeformVert>();
/* Curve Attributes. */
SpanAttributeWriter<bool> stroke_cyclic = attributes.lookup_or_add_for_write_span<bool>(
@@ -126,6 +190,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
MutableSpan<ColorGeometry4f> stroke_vertex_colors = vertex_colors.span.slice(
stroke_points_range);
MutableSpan<bool> stroke_selections = selection.span.slice(stroke_points_range);
MutableSpan<MDeformVert> stroke_dverts = use_dverts ? dverts.slice(stroke_points_range) :
MutableSpan<MDeformVert>();
/* Do first point. */
const bGPDspoint &first_pt = stroke_points.first();
@@ -143,6 +209,9 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_rotations.first() = first_pt.uv_rot;
stroke_vertex_colors.first() = ColorGeometry4f(first_pt.vert_color);
stroke_selections.first() = (first_pt.flag & GP_SPOINT_SELECT) != 0;
if (use_dverts && gps->dvert) {
copy_dvert(gps->dvert[0], stroke_dverts.first());
}
/* Do the rest of the points. */
for (const int i : stroke_points.index_range().drop_back(1)) {
@@ -156,6 +225,9 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_rotations[point_i] = pt.uv_rot;
stroke_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color);
stroke_selections[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0;
if (use_dverts && gps->dvert) {
copy_dvert(gps->dvert[point_i], stroke_dverts[point_i]);
}
}
}
@@ -225,7 +297,7 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
grease_pencil.drawing_array[i]);
/* Convert the frame to a drawing. */
legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, drawing);
legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, gpd.vertex_group_names, drawing);
/* Add the frame to the layer. */
if (GreasePencilFrame *new_frame = new_layer.add_frame(gpf->framenum, i)) {
@@ -242,6 +314,10 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
/* TODO: Update drawing user counts. */
}
/* Copy vertex group names and settings. */
BKE_defgroup_copy_list(&grease_pencil.vertex_group_names, &gpd.vertex_group_names);
grease_pencil.vertex_group_active_index = gpd.vertex_group_active_index;
/* Convert the onion skinning settings. */
grease_pencil.onion_skinning_settings.opacity = gpd.onion_factor;
grease_pencil.onion_skinning_settings.mode = gpd.onion_mode;