[Bf-blender-cvs] [88dc274d053] master: GPencil: Convert from Mesh copying Vertex Groups

Henrik Dick noreply at git.blender.org
Tue Aug 17 20:26:14 CEST 2021


Commit: 88dc274d0533e3b4427a61718958bf84367b5077
Author: Henrik Dick
Date:   Tue Aug 17 20:04:27 2021 +0200
Branches: master
https://developer.blender.org/rB88dc274d0533e3b4427a61718958bf84367b5077

GPencil: Convert from Mesh copying Vertex Groups

This patch adds the missing ability to keep the vertex groups when converting to a grease pencil object. This is increadible useful to create rigged grease pencil objects which move together with rigged meshes.

Differential Revision: https://developer.blender.org/D12249

===================================================================

M	source/blender/blenkernel/BKE_gpencil_geom.h
M	source/blender/blenkernel/intern/gpencil_geom.cc
M	source/blender/editors/gpencil/gpencil_mesh.c
M	source/blender/editors/object/object_add.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index c1ccae7a437..29e3a74b1b2 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -169,7 +169,8 @@ bool BKE_gpencil_convert_mesh(struct Main *bmain,
                               const float matrix[4][4],
                               const int frame_offset,
                               const bool use_seams,
-                              const bool use_faces);
+                              const bool use_faces,
+                              const bool use_vgroups);
 
 void BKE_gpencil_stroke_uniform_subdivide(struct bGPdata *gpd,
                                           struct bGPDstroke *gps,
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index f8a07939096..f2042d3098c 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -2269,7 +2269,8 @@ static void gpencil_generate_edgeloops(Object *ob,
                                        const int thickness,
                                        const float offset,
                                        const float matrix[4][4],
-                                       const bool use_seams)
+                                       const bool use_seams,
+                                       const bool use_vgroups)
 {
   Mesh *me = (Mesh *)ob->data;
   if (me->totedge == 0) {
@@ -2278,9 +2279,9 @@ static void gpencil_generate_edgeloops(Object *ob,
 
   /* Arrays for all edge vertices (forward and backward) that form a edge loop.
    * This is reused for each edge-loop to create gpencil stroke. */
-  uint *stroke = (uint *)MEM_callocN(sizeof(uint) * me->totedge * 2, __func__);
-  uint *stroke_fw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__);
-  uint *stroke_bw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__);
+  uint *stroke = (uint *)MEM_mallocN(sizeof(uint) * me->totedge * 2, __func__);
+  uint *stroke_fw = (uint *)MEM_mallocN(sizeof(uint) * me->totedge, __func__);
+  uint *stroke_bw = (uint *)MEM_mallocN(sizeof(uint) * me->totedge, __func__);
 
   /* Create array with all edges. */
   GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * me->totedge, __func__);
@@ -2311,11 +2312,6 @@ static void gpencil_generate_edgeloops(Object *ob,
   bool pending = true;
   int e = 0;
   while (pending) {
-    /* Clear arrays of stroke. */
-    memset(stroke_fw, 0, sizeof(uint) * me->totedge);
-    memset(stroke_bw, 0, sizeof(uint) * me->totedge);
-    memset(stroke, 0, sizeof(uint) * me->totedge * 2);
-
     gped = &gp_edges[e];
     /* Look first unused edge. */
     if (gped->flag != 0) {
@@ -2330,7 +2326,7 @@ static void gpencil_generate_edgeloops(Object *ob,
     stroke_bw[0] = e;
     gped->flag = 1;
 
-    /* Hash used to avoid loop over same vertice. */
+    /* Hash used to avoid loop over same vertices. */
     GHash *v_table = BLI_ghash_int_new(__func__);
     /* Look forward edges. */
     int totedges = gpencil_walk_edge(v_table, gp_edges, me->totedge, stroke_fw, e, angle, false);
@@ -2354,38 +2350,41 @@ static void gpencil_generate_edgeloops(Object *ob,
     bGPDstroke *gps_stroke = BKE_gpencil_stroke_add(
         gpf_stroke, MAX2(stroke_mat_index, 0), array_len + 1, thickness * thickness, false);
 
+    /* Create dvert data. */
+    MDeformVert *me_dvert = me->dvert;
+    if (use_vgroups && me_dvert) {
+      gps_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (array_len + 1),
+                                                     "gp_stroke_dverts");
+    }
+
     /* Create first segment. */
     float fpt[3];
-    uint v = stroke[0];
-    gped = &gp_edges[v];
-    bGPDspoint *pt = &gps_stroke->points[0];
-    mul_v3_v3fl(fpt, gped->n1, offset);
-    add_v3_v3v3(&pt->x, gped->v1_co, fpt);
-    mul_m4_v3(matrix, &pt->x);
-
-    pt->pressure = 1.0f;
-    pt->strength = 1.0f;
-
-    pt = &gps_stroke->points[1];
-    mul_v3_v3fl(fpt, gped->n2, offset);
-    add_v3_v3v3(&pt->x, gped->v2_co, fpt);
-    mul_m4_v3(matrix, &pt->x);
-
-    pt->pressure = 1.0f;
-    pt->strength = 1.0f;
-
-    /* Add next segments. */
-    for (int i = 1; i < array_len; i++) {
-      v = stroke[i];
-      gped = &gp_edges[v];
-
-      pt = &gps_stroke->points[i + 1];
-      mul_v3_v3fl(fpt, gped->n2, offset);
-      add_v3_v3v3(&pt->x, gped->v2_co, fpt);
+    for (int i = 0; i < array_len + 1; i++) {
+      int vertex_index = i == 0 ? gp_edges[stroke[0]].v1 : gp_edges[stroke[i - 1]].v2;
+      MVert *mv = &me->mvert[vertex_index];
+
+      /* Add segment. */
+      bGPDspoint *pt = &gps_stroke->points[i];
+      normal_short_to_float_v3(fpt, mv->no);
+      mul_v3_v3fl(fpt, fpt, offset);
+      add_v3_v3v3(&pt->x, mv->co, fpt);
       mul_m4_v3(matrix, &pt->x);
 
       pt->pressure = 1.0f;
       pt->strength = 1.0f;
+
+      /* Copy vertex groups from mesh. Assuming they already exist in the same order. */
+      if (use_vgroups && me_dvert) {
+        MDeformVert *dv = &gps_stroke->dvert[i];
+        MDeformVert *src_dv = &me_dvert[vertex_index];
+        dv->totweight = src_dv->totweight;
+        dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+                                              "gp_stroke_dverts_dw");
+        for (int j = 0; j < dv->totweight; j++) {
+          dv->dw[j].weight = src_dv->dw[j].weight;
+          dv->dw[j].def_nr = src_dv->dw[j].def_nr;
+        }
+      }
     }
 
     BKE_gpencil_stroke_geometry_update(gpd, gps_stroke);
@@ -2488,7 +2487,8 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
                               const float matrix[4][4],
                               const int frame_offset,
                               const bool use_seams,
-                              const bool use_faces)
+                              const bool use_faces,
+                              const bool use_vgroups)
 {
   if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) {
     return false;
@@ -2505,83 +2505,105 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
   char element_name[200];
 
   /* Need at least an edge. */
-  if (me_eval->totvert < 2) {
+  if (me_eval->totedge < 1) {
     return false;
   }
 
+  /* Create matching vertex groups. */
+  BKE_defgroup_copy_list(&gpd->vertex_group_names, &me_eval->vertex_group_names);
+  gpd->vertex_group_active_index = me_eval->vertex_group_active_index;
+
   const float default_colors[2][4] = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.7f, 0.7f, 0.7f, 1.0f}};
-  /* Create stroke material. */
+  /* Lookup existing stroke material on gp object. */
   make_element_name(ob_mesh->id.name + 2, "Stroke", 64, element_name);
   int stroke_mat_index = gpencil_material_find_index_by_name(ob_gp, element_name);
 
   if (stroke_mat_index == -1) {
+    /* Create new default stroke material as there is no existing material. */
     gpencil_add_material(
         bmain, ob_gp, element_name, default_colors[0], true, false, &stroke_mat_index);
   }
 
   /* Export faces as filled strokes. */
-  if (use_faces) {
-
+  if (use_faces && mpoly_len > 0) {
     /* Read all polygons and create fill for each. */
-    if (mpoly_len > 0) {
-      make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name);
-      /* Create Layer and Frame. */
-      bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name);
-      if (gpl_fill == nullptr) {
-        gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
-      }
-      bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
-          gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
-      int i;
-      for (i = 0; i < mpoly_len; i++) {
-        const MPoly *mp = &mpoly[i];
-
-        /* Find material. */
-        int mat_idx = 0;
-        Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
-        make_element_name(
-            ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
-        mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
-        if (mat_idx == -1) {
-          float color[4];
-          if (ma != nullptr) {
-            copy_v3_v3(color, &ma->r);
-            color[3] = 1.0f;
-          }
-          else {
-            copy_v4_v4(color, default_colors[1]);
-          }
-          gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx);
+    make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name);
+    /* Create Layer and Frame. */
+    bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name);
+    if (gpl_fill == nullptr) {
+      gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
+    }
+    bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
+        gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
+    int i;
+    for (i = 0; i < mpoly_len; i++) {
+      const MPoly *mp = &mpoly[i];
+
+      /* Find material. */
+      int mat_idx = 0;
+      Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
+      make_element_name(
+          ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
+      mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
+      if (mat_idx == -1) {
+        float color[4];
+        if (ma != nullptr) {
+          copy_v3_v3(color, &ma->r);
+          color[3] = 1.0f;
         }
+        else {
+          copy_v4_v4(color, default_colors[1]);
+        }
+        gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx);
+      }
 
-        bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, mp->totloop, 10, false);
-        gps_fill->flag |= GP_STROKE_CYCLIC;
+      bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, mp->totloop, 10, false);
+      gps_fill->flag |= GP_STROKE_CYCLIC;
 
-        /* Add points to strokes. */
-        for (int j = 0; j < mp->totloop; j++) {
-          const MLoop *ml = &mloop[mp->loopstart + j];
-          const MVert *mv = &me_eval->mvert[ml->v];
+      /* Create dvert data. *

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list