Blender  V3.3
armature_skinning.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
10 #include "DNA_armature_types.h"
11 #include "DNA_mesh_types.h"
12 #include "DNA_meshdata_types.h"
13 #include "DNA_object_types.h"
14 #include "DNA_scene_types.h"
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include "BLI_math.h"
19 #include "BLI_string_utils.h"
20 
21 #include "BKE_action.h"
22 #include "BKE_armature.h"
23 #include "BKE_deform.h"
24 #include "BKE_mesh_iterators.h"
25 #include "BKE_mesh_runtime.h"
26 #include "BKE_modifier.h"
27 #include "BKE_object_deform.h"
28 #include "BKE_report.h"
29 #include "BKE_subsurf.h"
30 
31 #include "DEG_depsgraph.h"
32 #include "DEG_depsgraph_query.h"
33 
34 #include "ED_armature.h"
35 #include "ED_mesh.h"
36 
37 #include "armature_intern.h"
38 #include "meshlaplacian.h"
39 
40 /* ******************************* Bone Skinning *********************************************** */
41 
42 static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
43 {
44  /* Bones that are deforming
45  * are regarded to be "skinnable" and are eligible for
46  * auto-skinning.
47  *
48  * This function performs 2 functions:
49  *
50  * a) It returns 1 if the bone is skinnable.
51  * If we loop over all bones with this
52  * function, we can count the number of
53  * skinnable bones.
54  * b) If the pointer data is non null,
55  * it is treated like a handle to a
56  * bone pointer -- the bone pointer
57  * is set to point at this bone, and
58  * the pointer the handle points to
59  * is incremented to point to the
60  * next member of an array of pointers
61  * to bones. This way we can loop using
62  * this function to construct an array of
63  * pointers to bones that point to all
64  * skinnable bones.
65  */
66  Bone ***hbone;
67  int a, segments;
68  struct {
69  Object *armob;
70  void *list;
71  int heat;
72  bool is_weight_paint;
73  } *data = datap;
74 
75  if (!(data->is_weight_paint) || !(bone->flag & BONE_HIDDEN_P)) {
76  if (!(bone->flag & BONE_NO_DEFORM)) {
77  if (data->heat && data->armob->pose &&
78  BKE_pose_channel_find_name(data->armob->pose, bone->name)) {
79  segments = bone->segments;
80  }
81  else {
82  segments = 1;
83  }
84 
85  if (data->list != NULL) {
86  hbone = (Bone ***)&data->list;
87 
88  for (a = 0; a < segments; a++) {
89  **hbone = bone;
90  (*hbone)++;
91  }
92  }
93  return segments;
94  }
95  }
96  return 0;
97 }
98 
99 static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
100 {
101  /* This group creates a vertex group to ob that has the
102  * same name as bone (provided the bone is skinnable).
103  * If such a vertex group already exist the routine exits.
104  */
105  if (!(bone->flag & BONE_NO_DEFORM)) {
106  if (!BKE_object_defgroup_find_name(ob, bone->name)) {
108  return 1;
109  }
110  }
111  return 0;
112 }
113 
114 static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
115 {
116  /* Bones that are deforming
117  * are regarded to be "skinnable" and are eligible for
118  * auto-skinning.
119  *
120  * This function performs 2 functions:
121  *
122  * a) If the bone is skinnable, it creates
123  * a vertex group for ob that has
124  * the name of the skinnable bone
125  * (if one doesn't exist already).
126  * b) If the pointer data is non null,
127  * it is treated like a handle to a
128  * bDeformGroup pointer -- the
129  * bDeformGroup pointer is set to point
130  * to the deform group with the bone's
131  * name, and the pointer the handle
132  * points to is incremented to point to the
133  * next member of an array of pointers
134  * to bDeformGroups. This way we can loop using
135  * this function to construct an array of
136  * pointers to bDeformGroups, all with names
137  * of skinnable bones.
138  */
139  bDeformGroup ***hgroup, *defgroup = NULL;
140  int a, segments;
141  struct {
142  Object *armob;
143  void *list;
144  int heat;
145  bool is_weight_paint;
146  } *data = datap;
147  bArmature *arm = data->armob->data;
148 
149  if (!data->is_weight_paint || !(bone->flag & BONE_HIDDEN_P)) {
150  if (!(bone->flag & BONE_NO_DEFORM)) {
151  if (data->heat && data->armob->pose &&
152  BKE_pose_channel_find_name(data->armob->pose, bone->name)) {
153  segments = bone->segments;
154  }
155  else {
156  segments = 1;
157  }
158 
159  if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
160  if (!(defgroup = BKE_object_defgroup_find_name(ob, bone->name))) {
161  defgroup = BKE_object_defgroup_add_name(ob, bone->name);
162  }
163  else if (defgroup->flag & DG_LOCK_WEIGHT) {
164  /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
165  defgroup = NULL;
166  }
167  }
168 
169  if (data->list != NULL) {
170  hgroup = (bDeformGroup ***)&data->list;
171 
172  for (a = 0; a < segments; a++) {
173  **hgroup = defgroup;
174  (*hgroup)++;
175  }
176  }
177  return segments;
178  }
179  }
180  return 0;
181 }
182 
184  Mesh *mesh,
185  float (*verts)[3],
186  int numbones,
187  Bone **bonelist,
188  bDeformGroup **dgrouplist,
189  bDeformGroup **dgroupflip,
190  float (*root)[3],
191  float (*tip)[3],
192  const int *selected,
193  float scale)
194 {
195  /* Create vertex group weights from envelopes */
196 
197  bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
198  bool use_mask = false;
199 
200  if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
202  use_mask = true;
203  }
204 
205  /* for each vertex in the mesh */
206  for (int i = 0; i < mesh->totvert; i++) {
207 
208  if (use_mask && !(mesh->mvert[i].flag & SELECT)) {
209  continue;
210  }
211 
212  int iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1;
213 
214  /* for each skinnable bone */
215  for (int j = 0; j < numbones; j++) {
216  if (!selected[j]) {
217  continue;
218  }
219 
220  Bone *bone = bonelist[j];
221  bDeformGroup *dgroup = dgrouplist[j];
222 
223  /* store the distance-factor from the vertex to the bone */
224  float distance = distfactor_to_bone(verts[i],
225  root[j],
226  tip[j],
227  bone->rad_head * scale,
228  bone->rad_tail * scale,
229  bone->dist * scale);
230 
231  /* add the vert to the deform group if (weight != 0.0) */
232  if (distance != 0.0f) {
233  ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
234  }
235  else {
236  ED_vgroup_vert_remove(ob, dgroup, i);
237  }
238 
239  /* do same for mirror */
240  if (dgroupflip && dgroupflip[j] && iflip != -1) {
241  if (distance != 0.0f) {
242  ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance, WEIGHT_REPLACE);
243  }
244  else {
245  ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
246  }
247  }
248  }
249  }
250 }
251 
252 static void add_verts_to_dgroups(ReportList *reports,
254  Scene *UNUSED(scene),
255  Object *ob,
256  Object *par,
257  int heat,
258  const bool mirror)
259 {
260  /* This functions implements the automatic computation of vertex group
261  * weights, either through envelopes or using a heat equilibrium.
262  *
263  * This function can be called both when parenting a mesh to an armature,
264  * or in weight-paint + pose-mode. In the latter case selection is taken
265  * into account and vertex weights can be mirrored.
266  *
267  * The mesh vertex positions used are either the final deformed coords
268  * from the evaluated mesh in weight-paint mode, the final sub-surface coords
269  * when parenting, or simply the original mesh coords.
270  */
271 
272  bArmature *arm = par->data;
273  Bone **bonelist, *bone;
274  bDeformGroup **dgrouplist, **dgroupflip;
275  bDeformGroup *dgroup;
276  bPoseChannel *pchan;
277  Mesh *mesh;
278  Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
279  float(*root)[3], (*tip)[3], (*verts)[3];
280  int *selected;
281  int numbones, vertsfilled = 0, segments = 0;
282  const bool wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
283  struct {
284  Object *armob;
285  void *list;
286  int heat;
287  bool is_weight_paint;
288  } looper_data;
289 
290  looper_data.armob = par;
291  looper_data.heat = heat;
292  looper_data.list = NULL;
293  looper_data.is_weight_paint = wpmode;
294 
295  /* count the number of skinnable bones */
296  numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
297 
298  if (numbones == 0) {
299  return;
300  }
301 
303  return;
304  }
305 
306  /* create an array of pointer to bones that are skinnable
307  * and fill it with all of the skinnable bones */
308  bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
309  looper_data.list = bonelist;
310  bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
311 
312  /* create an array of pointers to the deform groups that
313  * correspond to the skinnable bones (creating them
314  * as necessary. */
315  dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
316  dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");
317 
318  looper_data.list = dgrouplist;
319  bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
320 
321  /* create an array of root and tip positions transformed into
322  * global coords */
323  root = MEM_callocN(sizeof(float[3]) * numbones, "root");
324  tip = MEM_callocN(sizeof(float[3]) * numbones, "tip");
325  selected = MEM_callocN(sizeof(int) * numbones, "selected");
326 
327  for (int j = 0; j < numbones; j++) {
328  bone = bonelist[j];
329  dgroup = dgrouplist[j];
330 
331  /* handle bbone */
332  if (heat) {
333  if (segments == 0) {
334  segments = 1;
335  bbone = NULL;
336 
337  if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
338  if (bone->segments > 1) {
339  segments = bone->segments;
340  BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
341  bbone = bbone_array;
342  }
343  }
344  }
345 
346  segments--;
347  }
348 
349  /* compute root and tip */
350  if (bbone) {
351  mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
352  if ((segments + 1) < bone->segments) {
353  mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
354  }
355  else {
356  copy_v3_v3(tip[j], bone->arm_tail);
357  }
358  }
359  else {
360  copy_v3_v3(root[j], bone->arm_head);
361  copy_v3_v3(tip[j], bone->arm_tail);
362  }
363 
364  mul_m4_v3(par->obmat, root[j]);
365  mul_m4_v3(par->obmat, tip[j]);
366 
367  /* set selected */
368  if (wpmode) {
369  if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED)) {
370  selected[j] = 1;
371  }
372  }
373  else {
374  selected[j] = 1;
375  }
376 
377  /* find flipped group */
378  if (dgroup && mirror) {
379  char name_flip[MAXBONENAME];
380 
381  BLI_string_flip_side_name(name_flip, dgroup->name, false, sizeof(name_flip));
382  dgroupflip[j] = BKE_object_defgroup_find_name(ob, name_flip);
383  }
384  }
385 
386  /* create verts */
387  mesh = (Mesh *)ob->data;
388  verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");
389 
390  if (wpmode) {
391  /* if in weight paint mode, use final verts from evaluated mesh */
392  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
393  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
394  Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
395 
397  vertsfilled = 1;
398  }
400  /* is subsurf on? Lets use the verts on the limit surface then.
401  * = same amount of vertices as mesh, but vertices moved to the
402  * subsurfed position, like for 'optimal'. */
404  vertsfilled = 1;
405  }
406 
407  /* transform verts to global space */
408  for (int i = 0; i < mesh->totvert; i++) {
409  if (!vertsfilled) {
410  copy_v3_v3(verts[i], mesh->mvert[i].co);
411  }
412  mul_m4_v3(ob->obmat, verts[i]);
413  }
414 
415  /* compute the weights based on gathered vertices and bones */
416  if (heat) {
417  const char *error = NULL;
418 
420  ob, mesh, verts, numbones, dgrouplist, dgroupflip, root, tip, selected, &error);
421  if (error) {
422  BKE_report(reports, RPT_WARNING, error);
423  }
424  }
425  else {
427  mesh,
428  verts,
429  numbones,
430  bonelist,
431  dgrouplist,
432  dgroupflip,
433  root,
434  tip,
435  selected,
436  mat4_to_scale(par->obmat));
437  }
438 
439  /* only generated in some cases but can call anyway */
441 
442  /* free the memory allocated */
443  MEM_freeN(bonelist);
444  MEM_freeN(dgrouplist);
445  MEM_freeN(dgroupflip);
446  MEM_freeN(root);
447  MEM_freeN(tip);
448  MEM_freeN(selected);
449  MEM_freeN(verts);
450 }
451 
454  Scene *scene,
455  Object *ob,
456  Object *par,
457  const int mode,
458  const bool mirror)
459 {
460  /* Lets try to create some vertex groups
461  * based on the bones of the parent armature.
462  */
463  bArmature *arm = par->data;
464 
465  if (mode == ARM_GROUPS_NAME) {
466  const int defbase_tot = BKE_object_defgroup_count(ob);
467  int defbase_add;
468  /* Traverse the bone list, trying to create empty vertex
469  * groups corresponding to the bone.
470  */
471  defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
472 
473  if (defbase_add) {
474  /* It's possible there are DWeights outside the range of the current
475  * object's deform groups. In this case the new groups won't be empty T33889. */
476  ED_vgroup_data_clamp_range(ob->data, defbase_tot);
477  }
478  }
479  else if (ELEM(mode, ARM_GROUPS_ENVELOPE, ARM_GROUPS_AUTO)) {
480  /* Traverse the bone list, trying to create vertex groups
481  * that are populated with the vertices for which the
482  * bone is closest.
483  */
484  add_verts_to_dgroups(reports, depsgraph, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
485  }
486 }
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
#define MAX_BBONE_SUBDIV
Definition: BKE_armature.h:461
float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
void BKE_pchan_bbone_spline_setup(struct bPoseChannel *pchan, bool rest, bool for_deform, Mat4 *result_array)
Definition: armature.c:1178
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.cc:2051
support for deformation groups and hooks.
struct bDeformGroup * BKE_object_defgroup_find_name(const struct Object *ob, const char *name)
int BKE_object_defgroup_count(const struct Object *ob)
void BKE_mesh_foreach_mapped_vert_coords_get(struct Mesh *me_eval, float(*r_cos)[3], int totcos)
struct Mesh * mesh_get_eval_final(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
struct ModifierData * BKE_modifiers_findby_type(const struct Object *ob, ModifierType type)
Functions for dealing with objects and deform verts, used by painting and tools.
struct MDeformVert * BKE_object_defgroup_data_create(struct ID *id)
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
Definition: object_deform.c:95
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void subsurf_calculate_limit_positions(struct Mesh *me, float(*r_positions)[3])
Definition: subsurf_ccg.c:2017
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2185
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
MINLINE void copy_v3_v3(float r[3], const float a[3])
size_t BLI_string_flip_side_name(char *r_name, const char *from_name, bool strip_number, size_t name_len)
Definition: string_utils.c:112
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define MAXBONENAME
@ BONE_SELECTED
@ BONE_HIDDEN_P
@ BONE_NO_DEFORM
@ ME_EDIT_PAINT_VERT_SEL
@ ME_EDIT_PAINT_FACE_SEL
@ ME_EDIT_MIRROR_TOPO
@ eModifierType_Subsurf
@ OB_MODE_WEIGHT_PAINT
Object is a sort of wrapper for general info.
#define DG_LOCK_WEIGHT
#define ARM_GROUPS_ENVELOPE
Definition: ED_armature.h:199
#define ARM_GROUPS_NAME
Definition: ED_armature.h:198
#define ARM_GROUPS_AUTO
Definition: ED_armature.h:200
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode)
#define WEIGHT_REPLACE
Definition: ED_mesh.h:449
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum)
void ED_mesh_mirror_spatial_table_end(struct Object *ob)
int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, bool use_topology)
Definition: meshtools.cc:916
void ED_vgroup_data_clamp_range(struct ID *id, int total)
Read Guarded memory(de)allocation.
int bone_looper(struct Object *ob, struct Bone *bone, void *data, int(*bone_func)(struct Object *, struct Bone *, void *))
static void envelope_bone_weighting(Object *ob, Mesh *mesh, float(*verts)[3], int numbones, Bone **bonelist, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float(*root)[3], float(*tip)[3], const int *selected, float scale)
static void add_verts_to_dgroups(ReportList *reports, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob, Object *par, int heat, const bool mirror)
void ED_object_vgroup_calc_from_armature(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *par, const int mode, const bool mirror)
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
#define SELECT
Scene scene
const Depsgraph * depsgraph
static float verts[][3]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static void error(const char *str)
Definition: meshlaplacian.c:51
void heat_bone_weighting(Object *ob, Mesh *me, float(*verts)[3], int numbones, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float(*root)[3], float(*tip)[3], const int *selected, const char **error_str)
static unsigned a[3]
Definition: RandGen.cpp:78
T distance(const T &a, const T &b)
float arm_head[3]
char name[64]
float arm_tail[3]
short segments
float rad_head
float arm_mat[4][4]
float rad_tail
float dist
void * first
Definition: DNA_listBase.h:31
float co[3]
float mat[4][4]
Definition: BKE_armature.h:464
struct MVert * mvert
char editflag
int totvert
struct bPose * pose
float obmat[4][4]
void * data
ListBase bonebase
unsigned int layer
PointerRNA * ptr
Definition: wm_files.c:3480