Blender  V3.3
armature_deform.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 <ctype.h>
11 #include <float.h>
12 #include <math.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include "MEM_guardedalloc.h"
18 
19 #include "BLI_listbase.h"
20 #include "BLI_math.h"
21 #include "BLI_task.h"
22 #include "BLI_utildefines.h"
23 
24 #include "DNA_armature_types.h"
25 #include "DNA_gpencil_types.h"
26 #include "DNA_lattice_types.h"
27 #include "DNA_listBase.h"
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_object_types.h"
31 
32 #include "BKE_action.h"
33 #include "BKE_armature.h"
34 #include "BKE_customdata.h"
35 #include "BKE_deform.h"
36 #include "BKE_editmesh.h"
37 #include "BKE_lattice.h"
38 
39 #include "DEG_depsgraph_build.h"
40 
41 #include "CLG_log.h"
42 
43 static CLG_LogRef LOG = {"bke.armature_deform"};
44 
45 /* -------------------------------------------------------------------- */
49 /* Add the effect of one bone or B-Bone segment to the accumulated result. */
50 static void pchan_deform_accumulate(const DualQuat *deform_dq,
51  const float deform_mat[4][4],
52  const float co_in[3],
53  float weight,
54  float co_accum[3],
55  DualQuat *dq_accum,
56  float mat_accum[3][3])
57 {
58  if (weight == 0.0f) {
59  return;
60  }
61 
62  if (dq_accum) {
63  BLI_assert(!co_accum);
64 
65  add_weighted_dq_dq(dq_accum, deform_dq, weight);
66  }
67  else {
68  float tmp[3];
69  mul_v3_m4v3(tmp, deform_mat, co_in);
70 
71  sub_v3_v3(tmp, co_in);
72  madd_v3_v3fl(co_accum, tmp, weight);
73 
74  if (mat_accum) {
75  float tmpmat[3][3];
76  copy_m3_m4(tmpmat, deform_mat);
77 
78  madd_m3_m3m3fl(mat_accum, mat_accum, tmpmat, weight);
79  }
80  }
81 }
82 
83 static void b_bone_deform(const bPoseChannel *pchan,
84  const float co[3],
85  float weight,
86  float vec[3],
87  DualQuat *dq,
88  float defmat[3][3])
89 {
90  const DualQuat *quats = pchan->runtime.bbone_dual_quats;
91  const Mat4 *mats = pchan->runtime.bbone_deform_mats;
92  const float(*mat)[4] = mats[0].mat;
93  float blend, y;
94  int index;
95 
96  /* Transform co to bone space and get its y component. */
97  y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1];
98 
99  /* Calculate the indices of the 2 affecting b_bone segments. */
100  BKE_pchan_bbone_deform_segment_index(pchan, y / pchan->bone->length, &index, &blend);
101 
103  &quats[index], mats[index + 1].mat, co, weight * (1.0f - blend), vec, dq, defmat);
105  &quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat);
106 }
107 
109  const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
110 {
111  float dist_sq;
112  float bdelta[3];
113  float pdelta[3];
114  float hsqr, a, l, rad;
115 
116  sub_v3_v3v3(bdelta, b2, b1);
117  l = normalize_v3(bdelta);
118 
119  sub_v3_v3v3(pdelta, vec, b1);
120 
121  a = dot_v3v3(bdelta, pdelta);
122  hsqr = len_squared_v3(pdelta);
123 
124  if (a < 0.0f) {
125  /* If we're past the end of the bone, do a spherical field attenuation thing */
126  dist_sq = len_squared_v3v3(b1, vec);
127  rad = rad1;
128  }
129  else if (a > l) {
130  /* If we're past the end of the bone, do a spherical field attenuation thing */
131  dist_sq = len_squared_v3v3(b2, vec);
132  rad = rad2;
133  }
134  else {
135  dist_sq = (hsqr - (a * a));
136 
137  if (l != 0.0f) {
138  rad = a / l;
139  rad = rad * rad2 + (1.0f - rad) * rad1;
140  }
141  else {
142  rad = rad1;
143  }
144  }
145 
146  a = rad * rad;
147  if (dist_sq < a) {
148  return 1.0f;
149  }
150 
151  l = rad + rdist;
152  l *= l;
153  if (rdist == 0.0f || dist_sq >= l) {
154  return 0.0f;
155  }
156 
157  a = sqrtf(dist_sq) - rad;
158  return 1.0f - (a * a) / (rdist * rdist);
159 }
160 
161 static float dist_bone_deform(
162  const bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
163 {
164  const Bone *bone = pchan->bone;
165  float fac, contrib = 0.0;
166 
167  if (bone == NULL) {
168  return 0.0f;
169  }
170 
171  fac = distfactor_to_bone(
172  co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
173 
174  if (fac > 0.0f) {
175  fac *= bone->weight;
176  contrib = fac;
177  if (contrib > 0.0f) {
178  if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
179  b_bone_deform(pchan, co, fac, vec, dq, mat);
180  }
181  else {
183  &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
184  }
185  }
186  }
187 
188  return contrib;
189 }
190 
191 static void pchan_bone_deform(const bPoseChannel *pchan,
192  float weight,
193  float vec[3],
194  DualQuat *dq,
195  float mat[3][3],
196  const float co[3],
197  float *contrib)
198 {
199  const Bone *bone = pchan->bone;
200 
201  if (!weight) {
202  return;
203  }
204 
205  if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) {
206  b_bone_deform(pchan, co, weight, vec, dq, mat);
207  }
208  else {
210  &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
211  }
212 
213  (*contrib) += weight;
214 }
215 
218 /* -------------------------------------------------------------------- */
224 typedef struct ArmatureUserdata {
225  const Object *ob_arm;
226  const Mesh *me_target;
230 
235 
237 
240 
243 
244  float premat[4][4];
245  float postmat[4][4];
246 
248  struct {
250  } bmesh;
252 
254  const int i,
255  const MDeformVert *dvert)
256 {
257  float(*const vert_coords)[3] = data->vert_coords;
258  float(*const vert_deform_mats)[3][3] = data->vert_deform_mats;
259  float(*const vert_coords_prev)[3] = data->vert_coords_prev;
260  const bool use_envelope = data->use_envelope;
261  const bool use_quaternion = data->use_quaternion;
262  const bool use_dverts = data->use_dverts;
263  const int armature_def_nr = data->armature_def_nr;
264 
265  DualQuat sumdq, *dq = NULL;
266  const bPoseChannel *pchan;
267  float *co, dco[3];
268  float sumvec[3], summat[3][3];
269  float *vec = NULL, (*smat)[3] = NULL;
270  float contrib = 0.0f;
271  float armature_weight = 1.0f; /* default to 1 if no overall def group */
272  float prevco_weight = 1.0f; /* weight for optional cached vertexcos */
273 
274  if (use_quaternion) {
275  memset(&sumdq, 0, sizeof(DualQuat));
276  dq = &sumdq;
277  }
278  else {
279  zero_v3(sumvec);
280  vec = sumvec;
281 
282  if (vert_deform_mats) {
283  zero_m3(summat);
284  smat = summat;
285  }
286  }
287 
288  if (armature_def_nr != -1 && dvert) {
289  armature_weight = BKE_defvert_find_weight(dvert, armature_def_nr);
290 
291  if (data->invert_vgroup) {
292  armature_weight = 1.0f - armature_weight;
293  }
294 
295  /* hackish: the blending factor can be used for blending with vert_coords_prev too */
296  if (vert_coords_prev) {
297  prevco_weight = armature_weight;
298  armature_weight = 1.0f;
299  }
300  }
301 
302  /* check if there's any point in calculating for this vert */
303  if (armature_weight == 0.0f) {
304  return;
305  }
306 
307  /* get the coord we work on */
308  co = vert_coords_prev ? vert_coords_prev[i] : vert_coords[i];
309 
310  /* Apply the object's matrix */
311  mul_m4_v3(data->premat, co);
312 
313  if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
314  const MDeformWeight *dw = dvert->dw;
315  int deformed = 0;
316  unsigned int j;
317  for (j = dvert->totweight; j != 0; j--, dw++) {
318  const uint index = dw->def_nr;
319  if (index < data->defbase_len && (pchan = data->pchan_from_defbase[index])) {
320  float weight = dw->weight;
321  const Bone *bone = pchan->bone;
322 
323  deformed = 1;
324 
325  if (bone && bone->flag & BONE_MULT_VG_ENV) {
326  weight *= distfactor_to_bone(
327  co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
328  }
329 
330  pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
331  }
332  }
333  /* If there are vertex-groups but not groups with bones (like for soft-body groups). */
334  if (deformed == 0 && use_envelope) {
335  for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
336  if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
337  contrib += dist_bone_deform(pchan, vec, dq, smat, co);
338  }
339  }
340  }
341  }
342  else if (use_envelope) {
343  for (pchan = data->ob_arm->pose->chanbase.first; pchan; pchan = pchan->next) {
344  if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
345  contrib += dist_bone_deform(pchan, vec, dq, smat, co);
346  }
347  }
348  }
349 
350  /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
351  if (contrib > 0.0001f) {
352  if (use_quaternion) {
353  normalize_dq(dq, contrib);
354 
355  if (armature_weight != 1.0f) {
356  copy_v3_v3(dco, co);
357  mul_v3m3_dq(dco, (vert_deform_mats) ? summat : NULL, dq);
358  sub_v3_v3(dco, co);
359  mul_v3_fl(dco, armature_weight);
360  add_v3_v3(co, dco);
361  }
362  else {
363  mul_v3m3_dq(co, (vert_deform_mats) ? summat : NULL, dq);
364  }
365 
366  smat = summat;
367  }
368  else {
369  mul_v3_fl(vec, armature_weight / contrib);
370  add_v3_v3v3(co, vec, co);
371  }
372 
373  if (vert_deform_mats) {
374  float pre[3][3], post[3][3], tmpmat[3][3];
375 
376  copy_m3_m4(pre, data->premat);
377  copy_m3_m4(post, data->postmat);
378  copy_m3_m3(tmpmat, vert_deform_mats[i]);
379 
380  if (!use_quaternion) { /* quaternion already is scale corrected */
381  mul_m3_fl(smat, armature_weight / contrib);
382  }
383 
384  mul_m3_series(vert_deform_mats[i], post, smat, pre, tmpmat);
385  }
386  }
387 
388  /* always, check above code */
389  mul_m4_v3(data->postmat, co);
390 
391  /* interpolate with previous modifier position using weight group */
392  if (vert_coords_prev) {
393  float mw = 1.0f - prevco_weight;
394  vert_coords[i][0] = prevco_weight * vert_coords[i][0] + mw * co[0];
395  vert_coords[i][1] = prevco_weight * vert_coords[i][1] + mw * co[1];
396  vert_coords[i][2] = prevco_weight * vert_coords[i][2] + mw * co[2];
397  }
398 }
399 
400 static void armature_vert_task(void *__restrict userdata,
401  const int i,
402  const TaskParallelTLS *__restrict UNUSED(tls))
403 {
404  const ArmatureUserdata *data = userdata;
405  const MDeformVert *dvert;
406  if (data->use_dverts || data->armature_def_nr != -1) {
407  if (data->me_target) {
408  BLI_assert(i < data->me_target->totvert);
409  if (data->me_target->dvert != NULL) {
410  dvert = data->me_target->dvert + i;
411  }
412  else {
413  dvert = NULL;
414  }
415  }
416  else if (data->dverts && i < data->dverts_len) {
417  dvert = data->dverts + i;
418  }
419  else {
420  dvert = NULL;
421  }
422  }
423  else {
424  dvert = NULL;
425  }
426 
428 }
429 
430 static void armature_vert_task_editmesh(void *__restrict userdata,
431  MempoolIterData *iter,
432  const TaskParallelTLS *__restrict UNUSED(tls))
433 {
434  const ArmatureUserdata *data = userdata;
435  BMVert *v = (BMVert *)iter;
436  const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v, data->bmesh.cd_dvert_offset);
438 }
439 
440 static void armature_vert_task_editmesh_no_dvert(void *__restrict userdata,
441  MempoolIterData *iter,
442  const TaskParallelTLS *__restrict UNUSED(tls))
443 {
444  const ArmatureUserdata *data = userdata;
445  BMVert *v = (BMVert *)iter;
447 }
448 
449 static void armature_deform_coords_impl(const Object *ob_arm,
450  const Object *ob_target,
451  float (*vert_coords)[3],
452  float (*vert_deform_mats)[3][3],
453  const int vert_coords_len,
454  const int deformflag,
455  float (*vert_coords_prev)[3],
456  const char *defgrp_name,
457  const Mesh *me_target,
458  BMEditMesh *em_target,
459  bGPDstroke *gps_target)
460 {
461  const bArmature *arm = ob_arm->data;
462  bPoseChannel **pchan_from_defbase = NULL;
463  const MDeformVert *dverts = NULL;
464  const bool use_envelope = (deformflag & ARM_DEF_ENVELOPE) != 0;
465  const bool use_quaternion = (deformflag & ARM_DEF_QUATERNION) != 0;
466  const bool invert_vgroup = (deformflag & ARM_DEF_INVERT_VGROUP) != 0;
467  int defbase_len = 0; /* safety for vertexgroup index overflow */
468  int dverts_len = 0; /* safety for vertexgroup overflow */
469  bool use_dverts = false;
470  int armature_def_nr = -1;
471  int cd_dvert_offset = -1;
472 
473  /* in editmode, or not an armature */
474  if (arm->edbo || (ob_arm->pose == NULL)) {
475  return;
476  }
477 
478  if ((ob_arm->pose->flag & POSE_RECALC) != 0) {
479  CLOG_ERROR(&LOG,
480  "Trying to evaluate influence of armature '%s' which needs Pose recalc!",
481  ob_arm->id.name);
482  BLI_assert(0);
483  }
484 
485  if (BKE_object_supports_vertex_groups(ob_target)) {
486  const ID *target_data_id = NULL;
487  if (ob_target->type == OB_MESH) {
488  target_data_id = me_target == NULL ? (const ID *)ob_target->data : &me_target->id;
489  if (em_target == NULL) {
490  const Mesh *me = (const Mesh *)target_data_id;
491  dverts = me->dvert;
492  if (dverts) {
493  dverts_len = me->totvert;
494  }
495  }
496  }
497  else if (ob_target->type == OB_LATTICE) {
498  const Lattice *lt = ob_target->data;
499  target_data_id = (const ID *)ob_target->data;
500  dverts = lt->dvert;
501  if (dverts) {
502  dverts_len = lt->pntsu * lt->pntsv * lt->pntsw;
503  }
504  }
505  else if (ob_target->type == OB_GPENCIL) {
506  target_data_id = (const ID *)ob_target->data;
507  dverts = gps_target->dvert;
508  if (dverts) {
509  dverts_len = gps_target->totpoints;
510  }
511  }
512 
513  /* Collect the vertex group names from the evaluated data. */
514  armature_def_nr = BKE_id_defgroup_name_index(target_data_id, defgrp_name);
515  const ListBase *defbase = BKE_id_defgroup_list_get(target_data_id);
516  defbase_len = BLI_listbase_count(defbase);
517 
518  /* get a vertex-deform-index to posechannel array */
519  if (deformflag & ARM_DEF_VGROUP) {
520  /* if we have a Mesh, only use dverts if it has them */
521  if (em_target) {
522  cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
523  use_dverts = (cd_dvert_offset != -1);
524  }
525  else if (me_target) {
526  use_dverts = (me_target->dvert != NULL);
527  }
528  else if (dverts) {
529  use_dverts = true;
530  }
531 
532  if (use_dverts) {
533  pchan_from_defbase = MEM_callocN(sizeof(*pchan_from_defbase) * defbase_len, "defnrToBone");
534  /* TODO(sergey): Some considerations here:
535  *
536  * - Check whether keeping this consistent across frames gives speedup.
537  */
538  int i;
539  LISTBASE_FOREACH_INDEX (bDeformGroup *, dg, defbase, i) {
540  pchan_from_defbase[i] = BKE_pose_channel_find_name(ob_arm->pose, dg->name);
541  /* exclude non-deforming bones */
542  if (pchan_from_defbase[i]) {
543  if (pchan_from_defbase[i]->bone->flag & BONE_NO_DEFORM) {
544  pchan_from_defbase[i] = NULL;
545  }
546  }
547  }
548  }
549  }
550  }
551 
553  .ob_arm = ob_arm,
554  .me_target = me_target,
555  .vert_coords = vert_coords,
556  .vert_deform_mats = vert_deform_mats,
557  .vert_coords_prev = vert_coords_prev,
558  .use_envelope = use_envelope,
559  .use_quaternion = use_quaternion,
560  .invert_vgroup = invert_vgroup,
561  .use_dverts = use_dverts,
562  .armature_def_nr = armature_def_nr,
563  .dverts = dverts,
564  .dverts_len = dverts_len,
565  .pchan_from_defbase = pchan_from_defbase,
566  .defbase_len = defbase_len,
567  .bmesh =
568  {
569  .cd_dvert_offset = cd_dvert_offset,
570  },
571  };
572 
573  float obinv[4][4];
574  invert_m4_m4(obinv, ob_target->obmat);
575 
576  mul_m4_m4m4(data.postmat, obinv, ob_arm->obmat);
577  invert_m4_m4(data.premat, data.postmat);
578 
579  if (em_target != NULL) {
580  /* While this could cause an extra loop over mesh data, in most cases this will
581  * have already been properly set. */
582  BM_mesh_elem_index_ensure(em_target->bm, BM_VERT);
583 
584  TaskParallelSettings settings;
586 
587  if (use_dverts) {
589  em_target->bm->vpool, &data, armature_vert_task_editmesh, &settings);
590  }
591  else {
593  em_target->bm->vpool, &data, armature_vert_task_editmesh_no_dvert, &settings);
594  }
595  }
596  else {
597  TaskParallelSettings settings;
599  settings.min_iter_per_thread = 32;
600  BLI_task_parallel_range(0, vert_coords_len, &data, armature_vert_task, &settings);
601  }
602 
603  if (pchan_from_defbase) {
604  MEM_freeN(pchan_from_defbase);
605  }
606 }
607 
609  const Object *ob_target,
610  float (*vert_coords)[3],
611  float (*vert_deform_mats)[3][3],
612  int vert_coords_len,
613  int deformflag,
614  float (*vert_coords_prev)[3],
615  const char *defgrp_name,
616  bGPDstroke *gps_target)
617 {
619  ob_target,
620  vert_coords,
621  vert_deform_mats,
622  vert_coords_len,
623  deformflag,
624  vert_coords_prev,
625  defgrp_name,
626  NULL,
627  NULL,
628  gps_target);
629 }
630 
632  const Object *ob_target,
633  float (*vert_coords)[3],
634  float (*vert_deform_mats)[3][3],
635  int vert_coords_len,
636  int deformflag,
637  float (*vert_coords_prev)[3],
638  const char *defgrp_name,
639  const Mesh *me_target)
640 {
642  ob_target,
643  vert_coords,
644  vert_deform_mats,
645  vert_coords_len,
646  deformflag,
647  vert_coords_prev,
648  defgrp_name,
649  me_target,
650  NULL,
651  NULL);
652 }
653 
655  const Object *ob_target,
656  float (*vert_coords)[3],
657  float (*vert_deform_mats)[3][3],
658  int vert_coords_len,
659  int deformflag,
660  float (*vert_coords_prev)[3],
661  const char *defgrp_name,
662  BMEditMesh *em_target)
663 {
665  ob_target,
666  vert_coords,
667  vert_deform_mats,
668  vert_coords_len,
669  deformflag,
670  vert_coords_prev,
671  defgrp_name,
672  NULL,
673  em_target,
674  NULL);
675 }
676 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_pchan_bbone_deform_segment_index(const struct bPoseChannel *pchan, float pos, int *r_index, float *r_blend_next)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const struct CustomData *data, int type)
support for deformation groups and hooks.
bool BKE_object_supports_vertex_groups(const struct Object *ob)
const struct ListBase * BKE_id_defgroup_list_get(const struct ID *id)
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
int BKE_id_defgroup_name_index(const struct ID *id, const char *name)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void mul_m3_fl(float R[3][3], float f)
Definition: math_matrix.c:956
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void zero_m3(float m[3][3])
Definition: math_matrix.c:23
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void madd_m3_m3m3fl(float R[3][3], const float A[3][3], const float B[3][3], float f)
Definition: math_matrix.c:1054
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
#define mul_m3_series(...)
void add_weighted_dq_dq(DualQuat *dq_sum, const DualQuat *dq, float weight)
void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq)
void normalize_dq(DualQuat *dq, float totw)
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:67
struct MempoolIterData MempoolIterData
Definition: BLI_task.h:272
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
void BLI_task_parallel_mempool(struct BLI_mempool *mempool, void *userdata, TaskParallelMempoolFunc func, const TaskParallelSettings *settings)
BLI_INLINE void BLI_parallel_mempool_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:301
#define UNUSED(x)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
@ POSE_RECALC
@ ARM_DEF_VGROUP
@ ARM_DEF_QUATERNION
@ ARM_DEF_INVERT_VGROUP
@ ARM_DEF_ENVELOPE
@ BONE_MULT_VG_ENV
@ BONE_NO_DEFORM
@ CD_MDEFORMVERT
These structs are the foundation for all linked lists in the library system.
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_MESH
@ OB_GPENCIL
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
static float dist_bone_deform(const bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
static void armature_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter, const TaskParallelTLS *__restrict UNUSED(tls))
static void pchan_bone_deform(const bPoseChannel *pchan, float weight, float vec[3], DualQuat *dq, float mat[3][3], const float co[3], float *contrib)
static void armature_vert_task_with_dvert(const ArmatureUserdata *data, const int i, const MDeformVert *dvert)
float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
static void armature_vert_task_editmesh_no_dvert(void *__restrict userdata, MempoolIterData *iter, const TaskParallelTLS *__restrict UNUSED(tls))
struct ArmatureUserdata ArmatureUserdata
void BKE_armature_deform_coords_with_mesh(const Object *ob_arm, const Object *ob_target, float(*vert_coords)[3], float(*vert_deform_mats)[3][3], int vert_coords_len, int deformflag, float(*vert_coords_prev)[3], const char *defgrp_name, const Mesh *me_target)
void BKE_armature_deform_coords_with_editmesh(const Object *ob_arm, const Object *ob_target, float(*vert_coords)[3], float(*vert_deform_mats)[3][3], int vert_coords_len, int deformflag, float(*vert_coords_prev)[3], const char *defgrp_name, BMEditMesh *em_target)
static void pchan_deform_accumulate(const DualQuat *deform_dq, const float deform_mat[4][4], const float co_in[3], float weight, float co_accum[3], DualQuat *dq_accum, float mat_accum[3][3])
void BKE_armature_deform_coords_with_gpencil_stroke(const Object *ob_arm, const Object *ob_target, float(*vert_coords)[3], float(*vert_deform_mats)[3][3], int vert_coords_len, int deformflag, float(*vert_coords_prev)[3], const char *defgrp_name, bGPDstroke *gps_target)
static void armature_deform_coords_impl(const Object *ob_arm, const Object *ob_target, float(*vert_coords)[3], float(*vert_deform_mats)[3][3], const int vert_coords_len, const int deformflag, float(*vert_coords_prev)[3], const char *defgrp_name, const Mesh *me_target, BMEditMesh *em_target, bGPDstroke *gps_target)
static void armature_vert_task(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
static CLG_LogRef LOG
static void b_bone_deform(const bPoseChannel *pchan, const float co[3], float weight, float vec[3], DualQuat *dq, float defmat[3][3])
@ BM_VERT
Definition: bmesh_class.h:383
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define sqrtf(x)
Definition: metal/compat.h:243
static unsigned a[3]
Definition: RandGen.cpp:78
float(* vert_deform_mats)[3][3]
float postmat[4][4]
bPoseChannel ** pchan_from_defbase
const MDeformVert * dverts
struct ArmatureUserdata::@80 bmesh
float(* vert_coords)[3]
float premat[4][4]
float(* vert_coords_prev)[3]
const Mesh * me_target
const Object * ob_arm
struct BMesh * bm
Definition: BKE_editmesh.h:40
CustomData vdata
Definition: bmesh_class.h:337
struct BLI_mempool * vpool
Definition: bmesh_class.h:314
float arm_head[3]
float arm_tail[3]
short segments
float rad_head
float length
float rad_tail
float dist
float weight
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
struct MDeformVert * dvert
struct MDeformWeight * dw
unsigned int def_nr
float mat[4][4]
Definition: BKE_armature.h:464
struct MDeformVert * dvert
int totvert
struct bPose * pose
float obmat[4][4]
void * data
ListBase * edbo
struct MDeformVert * dvert
struct Mat4 * bbone_deform_mats
struct DualQuat deform_dual_quat
struct DualQuat * bbone_dual_quats
struct Bone * bone
float chan_mat[4][4]
struct bPoseChannel * next
struct bPoseChannel_Runtime runtime
short flag
static int blend(const Tex *tex, const float texvec[3], TexResult *texres)