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