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