Commit: 9d3cea5e542334fe123de00879837098afff37f0
Author: Antonioya
Date:   Mon Aug 20 11:22:25 2018 +0200
Branches: greasepencil-object
https://developer.blender.org/rB9d3cea5e542334fe123de00879837098afff37f0

Improvements in automatic weight calculation

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

M       release/scripts/startup/bl_ui/space_view3d.py
M       source/blender/editors/gpencil/gpencil_armature.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py 
b/release/scripts/startup/bl_ui/space_view3d.py
index 2edd1815c08..261129ed55c 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3539,6 +3539,15 @@ class VIEW3D_MT_edit_armature_delete(Menu):
 
 
 # ********** Grease Pencil Stroke menus **********
+class VIEW3D_MT_gpencil_autoweights(Menu):
+    bl_label = "Generate Weights"
+
+    def draw(self, context):
+        layout = self.layout
+        layout.operator("gpencil.generate_weights", text="With Empty 
Groups").mode = 'NAME'
+        layout.operator("gpencil.generate_weights", text="With Automatic 
Weights").mode = 'AUTO'
+
+
 class VIEW3D_MT_gpencil_simplify(Menu):
     bl_label = "Simplify"
 
@@ -3686,6 +3695,9 @@ class VIEW3D_MT_weight_gpencil(Menu):
         layout.operator("gpencil.vertex_group_invert", text="Invert")
         layout.operator("gpencil.vertex_group_smooth", text="Smooth")
 
+        layout.separator()
+        layout.menu("VIEW3D_MT_gpencil_autoweights")
+
 
 class VIEW3D_MT_gpencil_animation(Menu):
     bl_label = "Animation"
@@ -4967,7 +4979,6 @@ class VIEW3D_MT_gpencil_sculpt_specials(Menu):
 
     def draw(self, context):
         layout = self.layout
-        is_3d_view = context.space_data.type == 'VIEW_3D'
 
         layout.operator_context = 'INVOKE_REGION_WIN'
         layout.menu("VIEW3D_MT_assign_material")
@@ -4982,6 +4993,9 @@ class VIEW3D_MT_gpencil_sculpt_specials(Menu):
         layout.operator("gpencil.stroke_simplify_fixed", text="Simplify")
         layout.operator("gpencil.stroke_simplify", text="Simplify Adaptative")
 
+        if context.mode == 'GPENCIL_WEIGHT':
+            layout.separator()
+            layout.menu("VIEW3D_MT_gpencil_autoweights")
 
 classes = (
     VIEW3D_HT_header,
@@ -5126,6 +5140,7 @@ classes = (
     VIEW3D_PT_object_type_visibility,
     VIEW3D_PT_grease_pencil,
     VIEW3D_PT_gpencil_multi_frame,
+    VIEW3D_MT_gpencil_autoweights,
     VIEW3D_MT_gpencil_edit_specials,
     VIEW3D_MT_gpencil_sculpt_specials,
     VIEW3D_PT_quad_view,
diff --git a/source/blender/editors/gpencil/gpencil_armature.c 
b/source/blender/editors/gpencil/gpencil_armature.c
index 0f0b176dbb3..d7b00d86812 100644
--- a/source/blender/editors/gpencil/gpencil_armature.c
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -71,6 +71,7 @@
 #include "ED_mesh.h"
 
 #include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
 
 #include "gpencil_intern.h"
 
@@ -276,9 +277,24 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, 
void *datap)
        return 0;
 }
 
+/* get weight value depending of distance and decay value */
+static float get_weight(float dist, float decay_rad, float dif_rad)
+{
+       float weight = 1.0f;
+       if (dist < decay_rad) {
+               weight = 1.0f;
+       }
+       else {
+               weight = interpf(0.0f, 0.9f, (dist - decay_rad) / dif_rad);
+       }
+
+       return weight;
+}
+
 /* This functions implements the automatic computation of vertex group weights 
*/
 static void gpencil_add_verts_to_dgroups(bContext *C,
-       ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, 
Object *ob_arm)
+       ReportList *reports, Depsgraph *depsgraph, Scene *scene,
+       Object *ob, Object *ob_arm, const float ratio, const float decay)
 {
        bArmature *arm = ob_arm->data;
        Bone **bonelist, *bone;
@@ -372,7 +388,7 @@ static void gpencil_add_verts_to_dgroups(bContext *C,
                lensqr[j] = len_squared_v3v3(root[j], tip[j]);
 
                /* calculate radius squared */
-               radsqr[j] = lensqr[j] / 6.0f;
+               radsqr[j] = lensqr[j] * ratio;
        }
 
        /* loop all strokes */
@@ -412,6 +428,9 @@ static void gpencil_add_verts_to_dgroups(bContext *C,
                                                        continue;
                                                }
 
+                                               float decay_rad = radsqr[j] - 
(radsqr[j] * decay);
+                                               float dif_rad = radsqr[j] - 
decay_rad;
+
                                                for (i = 0, pt = gps->points; i 
< gps->totpoints; i++, pt++) {
                                                        MDeformVert *dvert = 
&gps->dvert[i];
                                                        float dist = 
test_point_in_cylynder(root[j], tip[j],
@@ -420,21 +439,20 @@ static void gpencil_add_verts_to_dgroups(bContext *C,
                                                        if (dist < 0) {
                                                                /* if not in 
cylinder, check if inside sphere of extremes */
                                                                weight = 0.0f;
-                                                               float rad = 
radsqr[j] * 0.75f;
                                                                dist = 
len_squared_v3v3(root[j], &pt->x);
-                                                               if (dist < rad) 
{
-                                                                       weight 
= interpf(0.0f, 0.9f, dist / rad);
+                                                               if (dist < 
radsqr[j]) {
+                                                                       weight 
= get_weight(dist, decay_rad, dif_rad);
                                                                }
                                                                else {
                                                                        dist = 
len_squared_v3v3(tip[j], &pt->x);
-                                                                       if 
(dist < rad) {
-                                                                               
weight = interpf(0.0f, 0.9f, dist / rad);
+                                                                       if 
(dist < radsqr[j]) {
+                                                                               
weight = get_weight(dist, decay_rad, dif_rad);
                                                                        }
                                                                }
                                                        }
                                                        else {
                                                                /* inside bone 
cylinder */
-                                                               weight = 1.0f;
+                                                               weight = 
get_weight(dist, decay_rad, dif_rad);
                                                        }
 
                                                        /* assign weight */
@@ -466,7 +484,7 @@ static void gpencil_add_verts_to_dgroups(bContext *C,
 
 static void gpencil_object_vgroup_calc_from_armature(bContext *C,
        ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, 
Object *ob_arm,
-       const int mode, const bool mirror)
+       const int mode, const float ratio, const float decay)
 {
        /* Lets try to create some vertex groups
         * based on the bones of the parent armature.
@@ -492,17 +510,34 @@ static void 
gpencil_object_vgroup_calc_from_armature(bContext *C,
                 * with the corresponding vertice weights for which the
                 * bone is closest.
                 */
-               gpencil_add_verts_to_dgroups(C, reports, depsgraph, scene, ob, 
ob_arm);
+               gpencil_add_verts_to_dgroups(C, reports, depsgraph, scene, ob, 
ob_arm,
+                                                                       ratio, 
decay);
        }
 }
 
 /* ***************** Generate armature weights ************************** */
 bool gpencil_generate_weights_poll(bContext *C)
 {
-       bGPdata *gpd = ED_gpencil_data_get_active(C);
-       bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
+       Object *ob = CTX_data_active_object(C);
+       Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+       bGPdata *gpd = (bGPdata *)ob->data;
+       int t = BLI_listbase_count(&gpd->layers);
 
-       return (gpl != NULL);
+       if (t == 0) {
+               return false;
+       }
+
+       GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval, 
eGpencilModifierType_Armature);
+       if (md == NULL) {
+               return false;
+       }
+       ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
+       if (mmd->object == NULL) {
+               return false;
+       }
+
+       return true;
 }
 
 static int gpencil_generate_weights_exec(bContext *C, wmOperator *op)
@@ -510,16 +545,19 @@ static int gpencil_generate_weights_exec(bContext *C, 
wmOperator *op)
        Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
+       Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
        bGPdata *gpd = (bGPdata *)ob->data;
 
-       int mode = RNA_enum_get(op->ptr, "mode");
+       const int mode = RNA_enum_get(op->ptr, "mode");
+       const float ratio = RNA_float_get(op->ptr, "ratio");
+       const float decay = RNA_float_get(op->ptr, "decay");
 
        /* sanity checks */
        if (ELEM(NULL, ob, gpd))
                return OPERATOR_CANCELLED;
 
        /* get armature from modifier */
-       GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, 
eGpencilModifierType_Armature);
+       GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval, 
eGpencilModifierType_Armature);
        if (md == NULL) {
                BKE_report(op->reports, RPT_ERROR,
                                "The grease pencil object need an Armature 
modifier");
@@ -534,7 +572,7 @@ static int gpencil_generate_weights_exec(bContext *C, 
wmOperator *op)
        }
 
        gpencil_object_vgroup_calc_from_armature(C, op->reports,depsgraph, 
scene,
-                                                                               
        ob, mmd->object, mode, false);
+                                                                               
        ob, mmd->object, mode, ratio, decay);
 
        /* notifiers */
        DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA);
@@ -546,15 +584,15 @@ static int gpencil_generate_weights_exec(bContext *C, 
wmOperator *op)
 void GPENCIL_OT_generate_weights(wmOperatorType *ot)
 {
        static const EnumPropertyItem mode_type[] = {
-       {GP_ARMATURE_NAME, "NAME", 0, "With Empty Groups", ""},
-       {GP_ARMATURE_AUTO, "AUTO", 0, "With Automatic Weights", ""},
+       {GP_ARMATURE_NAME, "NAME", 0, "Empty Groups", ""},
+       {GP_ARMATURE_AUTO, "AUTO", 0, "Automatic Weights", ""},
        {0, NULL, 0, NULL, NULL}
        };
 
        /* identifiers */
        ot->name = "Generate Automatic Weights";
        ot->idname = "GPENCIL_OT_generate_weights";
-       ot->description = "Generate automatic weights for armatures";
+       ot->description = "Generate automatic weights for armatures (requires 
armature modifier)";
 
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
@@ -563,4 +601,10 @@ void GPENCIL_OT_generate_weights(wmOperatorType *ot)
        ot->poll = gpencil_generate_weights_poll;
 
        ot->prop = RNA_def_enum(ot->srna, "mode", mode_type, 0, "Mode", "");
+
+       RNA_def_float(ot->srna, "ratio", 0.15f, 0.0f, 2.0f, "Ratio",
+               "Ratio between bone length and influence radius", 0.001f, 1.0f);
+
+       RNA_def_float(ot->srna, "decay", 0.1f, 0.0f, 1.0f, "Decay",
+               "Factor to reduce influence depending of distance to bone 
axis", 0.0f, 1.0f);
 }

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to