Blender  V3.3
MOD_surfacedeform.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. */
3 
8 #include "BLI_alloca.h"
9 #include "BLI_math.h"
10 #include "BLI_math_geom.h"
11 #include "BLI_task.h"
12 
13 #include "BLT_translation.h"
14 
15 #include "DNA_defaults.h"
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 #include "DNA_object_types.h"
19 #include "DNA_scene_types.h"
20 #include "DNA_screen_types.h"
21 
22 #include "BKE_bvhutils.h"
23 #include "BKE_context.h"
24 #include "BKE_deform.h"
25 #include "BKE_editmesh.h"
26 #include "BKE_lib_id.h"
27 #include "BKE_lib_query.h"
28 #include "BKE_mesh.h"
29 #include "BKE_mesh_runtime.h"
30 #include "BKE_mesh_wrapper.h"
31 #include "BKE_modifier.h"
32 #include "BKE_screen.h"
33 
34 #include "UI_interface.h"
35 #include "UI_resources.h"
36 
37 #include "BLO_read_write.h"
38 
39 #include "RNA_access.h"
40 #include "RNA_prototypes.h"
41 
42 #include "DEG_depsgraph.h"
43 #include "DEG_depsgraph_query.h"
44 
45 #include "MEM_guardedalloc.h"
46 
47 #include "MOD_ui_common.h"
48 #include "MOD_util.h"
49 
50 typedef struct SDefAdjacency {
54 
55 typedef struct SDefAdjacencyArray {
57  uint num; /* Careful, this is twice the number of polygons (avoids an extra loop) */
59 
63 typedef struct SDefEdgePolys {
64  uint polys[2], num;
66 
67 typedef struct SDefBindCalcData {
70  const SDefEdgePolys *const edge_polys;
72  const MLoopTri *const looptri;
73  const MPoly *const mpoly;
74  const MEdge *const medge;
75  const MLoop *const mloop;
77  float (*const targetCos)[3];
79  float (*const vertexCos)[3];
80  float imat[4][4];
81  const float falloff;
82  int success;
84  const MDeformVert *const dvert;
85  int const defgrp_index;
86  bool const invert_vgroup;
87  bool const sparse_bind;
89 
97 typedef struct SDefBindPoly {
99  float (*coords)[3];
103  float point_v2[2];
106  float weight_dist;
107  float weight;
110  float scales[2];
113  float scale_mid;
115  float centroid[3];
117  float centroid_v2[2];
121  float normal[3];
124  float cent_edgemid_vecs_v2[2][2];
150  bool inside;
152 
153 typedef struct SDefBindWeightData {
158 
159 typedef struct SDefDeformData {
160  const SDefVert *const bind_verts;
161  float (*const targetCos)[3];
162  float (*const vertexCos)[3];
163  const MDeformVert *const dvert;
164  int const defgrp_index;
165  bool const invert_vgroup;
166  float const strength;
168 
169 /* Bind result values */
170 enum {
177 };
178 
179 /* Infinite weight flags */
180 enum {
184 };
185 
186 static void initData(ModifierData *md)
187 {
189 
190  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(smd, modifier));
191 
193 }
194 
195 static void requiredDataMask(Object *UNUSED(ob),
196  ModifierData *md,
197  CustomData_MeshMasks *r_cddata_masks)
198 {
200 
201  /* Ask for vertex groups if we need them. */
202  if (smd->defgrp_name[0] != '\0') {
203  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
204  }
205 }
206 
207 static void freeData(ModifierData *md)
208 {
210 
211  if (smd->verts) {
212  for (int i = 0; i < smd->bind_verts_num; i++) {
213  if (smd->verts[i].binds) {
214  for (int j = 0; j < smd->verts[i].binds_num; j++) {
215  MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
217  }
218 
219  MEM_SAFE_FREE(smd->verts[i].binds);
220  }
221  }
222 
223  MEM_SAFE_FREE(smd->verts);
224  }
225 }
226 
227 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
228 {
229  const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
231 
232  BKE_modifier_copydata_generic(md, target, flag);
233 
234  if (smd->verts) {
235  tsmd->verts = MEM_dupallocN(smd->verts);
236 
237  for (int i = 0; i < smd->bind_verts_num; i++) {
238  if (smd->verts[i].binds) {
239  tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
240 
241  for (int j = 0; j < smd->verts[i].binds_num; j++) {
242  if (smd->verts[i].binds[j].vert_inds) {
243  tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds);
244  }
245 
246  if (smd->verts[i].binds[j].vert_weights) {
247  tsmd->verts[i].binds[j].vert_weights = MEM_dupallocN(
248  smd->verts[i].binds[j].vert_weights);
249  }
250  }
251  }
252  }
253  }
254 }
255 
256 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
257 {
259 
260  walk(userData, ob, (ID **)&smd->target, IDWALK_NOP);
261 }
262 
264 {
266  if (smd->target != NULL) {
268  ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
269  }
270 }
271 
272 static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges,
273  SDefAdjacency *const adj_ref,
274  SDefEdgePolys *const edge_polys)
275 {
276  MEM_freeN(edge_polys);
277 
278  MEM_freeN(adj_ref);
279 
280  MEM_freeN(vert_edges);
281 }
282 
283 static int buildAdjacencyMap(const MPoly *poly,
284  const MEdge *edge,
285  const MLoop *const mloop,
286  const uint polys_num,
287  const uint edges_num,
288  SDefAdjacencyArray *const vert_edges,
289  SDefAdjacency *adj,
290  SDefEdgePolys *const edge_polys)
291 {
292  const MLoop *loop;
293 
294  /* Find polygons adjacent to edges. */
295  for (int i = 0; i < polys_num; i++, poly++) {
296  loop = &mloop[poly->loopstart];
297 
298  for (int j = 0; j < poly->totloop; j++, loop++) {
299  if (edge_polys[loop->e].num == 0) {
300  edge_polys[loop->e].polys[0] = i;
301  edge_polys[loop->e].polys[1] = -1;
302  edge_polys[loop->e].num++;
303  }
304  else if (edge_polys[loop->e].num == 1) {
305  edge_polys[loop->e].polys[1] = i;
306  edge_polys[loop->e].num++;
307  }
308  else {
310  }
311  }
312  }
313 
314  /* Find edges adjacent to vertices */
315  for (int i = 0; i < edges_num; i++, edge++) {
316  adj->next = vert_edges[edge->v1].first;
317  adj->index = i;
318  vert_edges[edge->v1].first = adj;
319  vert_edges[edge->v1].num += edge_polys[i].num;
320  adj++;
321 
322  adj->next = vert_edges[edge->v2].first;
323  adj->index = i;
324  vert_edges[edge->v2].first = adj;
325  vert_edges[edge->v2].num += edge_polys[i].num;
326  adj++;
327  }
328 
330 }
331 
333  const MLoop *const mloop,
334  const uint edge,
335  const uint num)
336 {
337  bool found = false;
338 
339  for (int i = 0; i < num; i++) {
340  if (mloop[i].e == edge) {
341  found = true;
342  }
343  if (found) {
344  *indices = mloop[i].v;
345  indices++;
346  }
347  }
348 
349  /* Fill in remaining vertex indices that occur before the edge */
350  for (int i = 0; mloop[i].e != edge; i++) {
351  *indices = mloop[i].v;
352  indices++;
353  }
354 }
355 
357  const MLoop *const mloop,
358  const uint loopstart,
359  const uint num)
360 {
361  for (int i = loopstart; i < num; i++) {
362  *indices = mloop[i].v;
363  indices++;
364  }
365 
366  for (int i = 0; i < loopstart; i++) {
367  *indices = mloop[i].v;
368  indices++;
369  }
370 }
371 
372 BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3])
373 {
374  BVHTreeNearest nearest = {
375  .dist_sq = FLT_MAX,
376  .index = -1,
377  };
378  const MPoly *poly;
379  const MEdge *edge;
380  const MLoop *loop;
381  float t_point[3];
382  float max_dist = FLT_MAX;
383  float dist;
384  uint index = 0;
385 
386  mul_v3_m4v3(t_point, data->imat, point_co);
387 
389  data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData);
390 
391  poly = &data->mpoly[data->looptri[nearest.index].poly];
392  loop = &data->mloop[poly->loopstart];
393 
394  for (int i = 0; i < poly->totloop; i++, loop++) {
395  edge = &data->medge[loop->e];
397  point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]);
398 
399  if (dist < max_dist) {
400  max_dist = dist;
401  index = loop->e;
402  }
403  }
404 
405  edge = &data->medge[index];
406  if (len_squared_v3v3(point_co, data->targetCos[edge->v1]) <
407  len_squared_v3v3(point_co, data->targetCos[edge->v2])) {
408  return edge->v1;
409  }
410 
411  return edge->v2;
412 }
413 
414 BLI_INLINE int isPolyValid(const float coords[][2], const uint nr)
415 {
416  float prev_co[2], prev_prev_co[2];
417  float curr_vec[2], prev_vec[2];
418 
419  if (!is_poly_convex_v2(coords, nr)) {
421  }
422 
423  copy_v2_v2(prev_prev_co, coords[nr - 2]);
424  copy_v2_v2(prev_co, coords[nr - 1]);
425  sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
426  normalize_v2(prev_vec);
427 
428  for (int i = 0; i < nr; i++) {
429  sub_v2_v2v2(curr_vec, coords[i], prev_co);
430 
431  /* Check overlap between directly adjacent vertices. */
432  const float curr_len = normalize_v2(curr_vec);
433  if (curr_len < FLT_EPSILON) {
435  }
436 
437  /* Check overlap between vertices skipping one. */
438  if (len_squared_v2v2(prev_prev_co, coords[i]) < FLT_EPSILON * FLT_EPSILON) {
440  }
441 
442  /* Check for adjacent parallel edges. */
443  if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) {
445  }
446 
447  copy_v2_v2(prev_prev_co, prev_co);
448  copy_v2_v2(prev_co, coords[i]);
449  copy_v2_v2(prev_vec, curr_vec);
450  }
451 
453 }
454 
455 static void freeBindData(SDefBindWeightData *const bwdata)
456 {
457  SDefBindPoly *bpoly = bwdata->bind_polys;
458 
459  if (bwdata->bind_polys) {
460  for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
461  MEM_SAFE_FREE(bpoly->coords);
462  MEM_SAFE_FREE(bpoly->coords_v2);
463  }
464 
465  MEM_freeN(bwdata->bind_polys);
466  }
467 
468  MEM_freeN(bwdata);
469 }
470 
471 BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
472 {
473  return sinf(min_ff(point_angle / edgemid_angle, 1) * M_PI_2);
474 }
475 
477  const float point_co[3])
478 {
479  const uint nearest = nearestVert(data, point_co);
480  const SDefAdjacency *const vert_edges = data->vert_edges[nearest].first;
481  const SDefEdgePolys *const edge_polys = data->edge_polys;
482 
483  const SDefAdjacency *vedge;
484  const MPoly *poly;
485  const MLoop *loop;
486 
487  SDefBindWeightData *bwdata;
488  SDefBindPoly *bpoly;
489 
490  const float world[3] = {0.0f, 0.0f, 1.0f};
491  float avg_point_dist = 0.0f;
492  float tot_weight = 0.0f;
493  int inf_weight_flags = 0;
494 
495  bwdata = MEM_callocN(sizeof(*bwdata), "SDefBindWeightData");
496  if (bwdata == NULL) {
498  return NULL;
499  }
500 
501  bwdata->polys_num = data->vert_edges[nearest].num / 2;
502 
503  bpoly = MEM_calloc_arrayN(bwdata->polys_num, sizeof(*bpoly), "SDefBindPoly");
504  if (bpoly == NULL) {
505  freeBindData(bwdata);
507  return NULL;
508  }
509 
510  bwdata->bind_polys = bpoly;
511 
512  /* Loop over all adjacent edges,
513  * and build the #SDefBindPoly data for each poly adjacent to those. */
514  for (vedge = vert_edges; vedge; vedge = vedge->next) {
515  uint edge_ind = vedge->index;
516 
517  for (int i = 0; i < edge_polys[edge_ind].num; i++) {
518  {
519  bpoly = bwdata->bind_polys;
520 
521  for (int j = 0; j < bwdata->polys_num; bpoly++, j++) {
522  /* If coords isn't allocated, we have reached the first uninitialized `bpoly`. */
523  if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) {
524  break;
525  }
526  }
527  }
528 
529  /* Check if poly was already created by another edge or still has to be initialized */
530  if (!bpoly->coords) {
531  float angle;
532  float axis[3];
533  float tmp_vec_v2[2];
534  int is_poly_valid;
535 
536  bpoly->index = edge_polys[edge_ind].polys[i];
537  bpoly->coords = NULL;
538  bpoly->coords_v2 = NULL;
539 
540  /* Copy poly data */
541  poly = &data->mpoly[bpoly->index];
542  loop = &data->mloop[poly->loopstart];
543 
544  bpoly->verts_num = poly->totloop;
545  bpoly->loopstart = poly->loopstart;
546 
547  bpoly->coords = MEM_malloc_arrayN(
548  poly->totloop, sizeof(*bpoly->coords), "SDefBindPolyCoords");
549  if (bpoly->coords == NULL) {
550  freeBindData(bwdata);
552  return NULL;
553  }
554 
555  bpoly->coords_v2 = MEM_malloc_arrayN(
556  poly->totloop, sizeof(*bpoly->coords_v2), "SDefBindPolyCoords_v2");
557  if (bpoly->coords_v2 == NULL) {
558  freeBindData(bwdata);
560  return NULL;
561  }
562 
563  for (int j = 0; j < poly->totloop; j++, loop++) {
564  copy_v3_v3(bpoly->coords[j], data->targetCos[loop->v]);
565 
566  /* Find corner and edge indices within poly loop array */
567  if (loop->v == nearest) {
568  bpoly->corner_ind = j;
569  bpoly->edge_vert_inds[0] = (j == 0) ? (poly->totloop - 1) : (j - 1);
570  bpoly->edge_vert_inds[1] = (j == poly->totloop - 1) ? (0) : (j + 1);
571 
572  bpoly->edge_inds[0] = data->mloop[poly->loopstart + bpoly->edge_vert_inds[0]].e;
573  bpoly->edge_inds[1] = loop->e;
574  }
575  }
576 
577  /* Compute polygons parametric data. */
578  mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly->totloop);
579  normal_poly_v3(bpoly->normal, bpoly->coords, poly->totloop);
580 
581  /* Compute poly skew angle and axis */
583 
584  cross_v3_v3v3(axis, bpoly->normal, world);
585  normalize_v3(axis);
586 
587  /* Map coords onto 2d normal plane. */
588  map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle);
589 
590  zero_v2(bpoly->centroid_v2);
591  for (int j = 0; j < poly->totloop; j++) {
592  map_to_plane_axis_angle_v2_v3v3fl(bpoly->coords_v2[j], bpoly->coords[j], axis, angle);
593  madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly->totloop);
594  }
595 
596  is_poly_valid = isPolyValid(bpoly->coords_v2, poly->totloop);
597 
598  if (is_poly_valid != MOD_SDEF_BIND_RESULT_SUCCESS) {
599  freeBindData(bwdata);
600  data->success = is_poly_valid;
601  return NULL;
602  }
603 
604  bpoly->inside = isect_point_poly_v2(
605  bpoly->point_v2, bpoly->coords_v2, poly->totloop, false);
606 
607  /* Initialize weight components */
608  bpoly->weight_angular = 1.0f;
609  bpoly->weight_dist_proj = len_v2v2(bpoly->centroid_v2, bpoly->point_v2);
610  bpoly->weight_dist = len_v3v3(bpoly->centroid, point_co);
611 
612  avg_point_dist += bpoly->weight_dist;
613 
614  /* Common vertex coordinates. */
615  const float *const vert0_v2 = bpoly->coords_v2[bpoly->edge_vert_inds[0]];
616  const float *const vert1_v2 = bpoly->coords_v2[bpoly->edge_vert_inds[1]];
617  const float *const corner_v2 = bpoly->coords_v2[bpoly->corner_ind];
618 
619  /* Compute centroid to mid-edge vectors */
620  mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0], vert0_v2, corner_v2);
621  mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1], vert1_v2, corner_v2);
622 
623  sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2);
624  sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2);
625 
628 
629  /* Compute poly scales with respect to the two edges. */
630  bpoly->scales[0] = dist_to_line_v2(bpoly->centroid_v2, vert0_v2, corner_v2);
631  bpoly->scales[1] = dist_to_line_v2(bpoly->centroid_v2, vert1_v2, corner_v2);
632 
633  /* Compute the angle between the edge mid vectors. */
635  bpoly->cent_edgemid_vecs_v2[1]);
636 
637  /* Compute the angles between the corner and the edge mid vectors. The angles
638  * are computed signed in order to correctly clamp point_edgemid_angles later. */
639  float corner_angles[2];
640 
641  sub_v2_v2v2(tmp_vec_v2, corner_v2, bpoly->centroid_v2);
642  normalize_v2(tmp_vec_v2);
643 
644  corner_angles[0] = angle_signed_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[0]);
645  corner_angles[1] = angle_signed_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]);
646 
647  bpoly->corner_edgemid_angles[0] = fabsf(corner_angles[0]);
648  bpoly->corner_edgemid_angles[1] = fabsf(corner_angles[1]);
649 
650  /* Verify that the computed values are valid (the polygon isn't somehow
651  * degenerate despite having passed isPolyValid). */
652  if (bpoly->scales[0] < FLT_EPSILON || bpoly->scales[1] < FLT_EPSILON ||
653  bpoly->edgemid_angle < FLT_EPSILON || bpoly->corner_edgemid_angles[0] < FLT_EPSILON ||
654  bpoly->corner_edgemid_angles[1] < FLT_EPSILON) {
655  freeBindData(bwdata);
657  return NULL;
658  }
659 
660  /* Check for infinite weights, and compute angular data otherwise. */
661  if (bpoly->weight_dist < FLT_EPSILON) {
662  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
663  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
664  }
665  else if (bpoly->weight_dist_proj < FLT_EPSILON) {
666  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
667  }
668  else {
669  /* Compute angles between the point and the edge mid vectors. */
670  float cent_point_vec[2], point_angles[2];
671 
672  sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2);
673  normalize_v2(cent_point_vec);
674 
675  point_angles[0] = angle_signed_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[0]) *
676  signf(corner_angles[0]);
677  point_angles[1] = angle_signed_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[1]) *
678  signf(corner_angles[1]);
679 
680  if (point_angles[0] <= 0 && point_angles[1] <= 0) {
681  /* If the point is outside the corner formed by the edge mid vectors,
682  * choose to clamp the closest side and flip the other. */
683  if (point_angles[0] < point_angles[1]) {
684  point_angles[0] = bpoly->edgemid_angle - point_angles[1];
685  }
686  else {
687  point_angles[1] = bpoly->edgemid_angle - point_angles[0];
688  }
689  }
690 
691  bpoly->point_edgemid_angles[0] = max_ff(0, point_angles[0]);
692  bpoly->point_edgemid_angles[1] = max_ff(0, point_angles[1]);
693 
694  /* Compute the distance scale for the corner. The base value is the orthogonal
695  * distance from the corner to the chord, scaled by sqrt(2) to preserve the old
696  * values in case of a square grid. This doesn't use the centroid because the
697  * LOOPTRI method only uses these three vertices. */
698  bpoly->scale_mid = area_tri_v2(vert0_v2, corner_v2, vert1_v2) /
699  len_v2v2(vert0_v2, vert1_v2) * sqrtf(2);
700 
701  if (bpoly->inside) {
702  /* When inside, interpolate to centroid-based scale close to the center. */
703  float min_dist = min_ff(bpoly->scales[0], bpoly->scales[1]);
704 
705  bpoly->scale_mid = interpf(bpoly->scale_mid,
706  (bpoly->scales[0] + bpoly->scales[1]) / 2,
707  min_ff(bpoly->weight_dist_proj / min_dist, 1));
708  }
709 
710  /* Verify that the additional computed values are valid. */
711  if (bpoly->scale_mid < FLT_EPSILON ||
712  bpoly->point_edgemid_angles[0] + bpoly->point_edgemid_angles[1] < FLT_EPSILON) {
713  freeBindData(bwdata);
715  return NULL;
716  }
717  }
718  }
719  }
720  }
721 
722  avg_point_dist /= bwdata->polys_num;
723 
724  /* If weights 1 and 2 are not infinite, loop over all adjacent edges again,
725  * and build adjacency dependent angle data (depends on all polygons having been computed) */
726  if (!inf_weight_flags) {
727  for (vedge = vert_edges; vedge; vedge = vedge->next) {
728  SDefBindPoly *bpolys[2];
729  const SDefEdgePolys *epolys;
730  float ang_weights[2];
731  uint edge_ind = vedge->index;
732  uint edge_on_poly[2];
733 
734  epolys = &edge_polys[edge_ind];
735 
736  /* Find bind polys corresponding to the edge's adjacent polys */
737  bpoly = bwdata->bind_polys;
738 
739  for (int i = 0, j = 0; (i < bwdata->polys_num) && (j < epolys->num); bpoly++, i++) {
740  if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) {
741  bpolys[j] = bpoly;
742 
743  if (bpoly->edge_inds[0] == edge_ind) {
744  edge_on_poly[j] = 0;
745  }
746  else {
747  edge_on_poly[j] = 1;
748  }
749 
750  j++;
751  }
752  }
753 
754  /* Compute angular weight component */
755  if (epolys->num == 1) {
756  ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
757  bpolys[0]->edgemid_angle);
758  bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
759  }
760  else if (epolys->num == 2) {
761  ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
762  bpolys[0]->edgemid_angle);
763  ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]],
764  bpolys[1]->edgemid_angle);
765 
766  bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
767  bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
768  }
769  }
770  }
771 
772  /* Compute scaling and falloff:
773  * - Scale all weights if no infinite weight is found.
774  * - Scale only un-projected weight if projected weight is infinite.
775  * - Scale none if both are infinite. */
776  if (!inf_weight_flags) {
777  bpoly = bwdata->bind_polys;
778 
779  for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
780  float corner_angle_weights[2];
781  float scale_weight, sqr, inv_sqr;
782 
783  corner_angle_weights[0] = bpoly->point_edgemid_angles[0] / bpoly->corner_edgemid_angles[0];
784  corner_angle_weights[1] = bpoly->point_edgemid_angles[1] / bpoly->corner_edgemid_angles[1];
785 
786  if (isnan(corner_angle_weights[0]) || isnan(corner_angle_weights[1])) {
787  freeBindData(bwdata);
789  return NULL;
790  }
791 
792  /* Find which edge the point is closer to */
793  if (corner_angle_weights[0] < corner_angle_weights[1]) {
794  bpoly->dominant_edge = 0;
795  bpoly->dominant_angle_weight = corner_angle_weights[0];
796  }
797  else {
798  bpoly->dominant_edge = 1;
799  bpoly->dominant_angle_weight = corner_angle_weights[1];
800  }
801 
802  /* Check for invalid weights just in case computations fail. */
803  if (bpoly->dominant_angle_weight < 0 || bpoly->dominant_angle_weight > 1) {
804  freeBindData(bwdata);
806  return NULL;
807  }
808 
810 
811  /* Compute quadratic angular scale interpolation weight */
812  {
813  const float edge_angle_a = bpoly->point_edgemid_angles[bpoly->dominant_edge];
814  const float edge_angle_b = bpoly->point_edgemid_angles[!bpoly->dominant_edge];
815  /* Clamp so skinny faces with near zero `edgemid_angle`
816  * won't cause numeric problems. see T81988. */
817  scale_weight = edge_angle_a / max_ff(edge_angle_a, bpoly->edgemid_angle);
818  scale_weight /= scale_weight + (edge_angle_b / max_ff(edge_angle_b, bpoly->edgemid_angle));
819  }
820 
821  sqr = scale_weight * scale_weight;
822  inv_sqr = 1.0f - scale_weight;
823  inv_sqr *= inv_sqr;
824  scale_weight = sqr / (sqr + inv_sqr);
825 
826  BLI_assert(scale_weight >= 0 && scale_weight <= 1);
827 
828  /* Compute interpolated scale (no longer need the individual scales,
829  * so simply storing the result over the scale in index zero) */
830  bpoly->scales[0] = interpf(bpoly->scale_mid,
831  interpf(bpoly->scales[!bpoly->dominant_edge],
832  bpoly->scales[bpoly->dominant_edge],
833  scale_weight),
834  bpoly->dominant_angle_weight);
835 
836  /* Scale the point distance weights, and introduce falloff */
837  bpoly->weight_dist_proj /= bpoly->scales[0];
838  bpoly->weight_dist_proj = powf(bpoly->weight_dist_proj, data->falloff);
839 
840  bpoly->weight_dist /= avg_point_dist;
841  bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
842 
843  /* Re-check for infinite weights, now that all scalings and interpolations are computed */
844  if (bpoly->weight_dist < FLT_EPSILON) {
845  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
846  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
847  }
848  else if (bpoly->weight_dist_proj < FLT_EPSILON) {
849  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
850  }
851  else if (bpoly->weight_angular < FLT_EPSILON) {
852  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_ANGULAR;
853  }
854  }
855  }
856  else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) {
857  bpoly = bwdata->bind_polys;
858 
859  for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
860  /* Scale the point distance weight by average point distance, and introduce falloff */
861  bpoly->weight_dist /= avg_point_dist;
862  bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
863 
864  /* Re-check for infinite weights, now that all scalings and interpolations are computed */
865  if (bpoly->weight_dist < FLT_EPSILON) {
866  inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
867  }
868  }
869  }
870 
871  /* Final loop, to compute actual weights */
872  bpoly = bwdata->bind_polys;
873 
874  for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
875  /* Weight computation from components */
876  if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) {
877  bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f;
878  }
879  else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ) {
880  bpoly->weight = bpoly->weight_dist_proj < FLT_EPSILON ? 1.0f / bpoly->weight_dist : 0.0f;
881  }
882  else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_ANGULAR) {
883  bpoly->weight = bpoly->weight_angular < FLT_EPSILON ?
884  1.0f / bpoly->weight_dist_proj / bpoly->weight_dist :
885  0.0f;
886  }
887  else {
888  bpoly->weight = 1.0f / bpoly->weight_angular / bpoly->weight_dist_proj / bpoly->weight_dist;
889  }
890 
891  /* Apply after other kinds of scaling so the faces corner angle is always
892  * scaled in a uniform way, preventing heavily sub-divided triangle fans
893  * from having a lop-sided influence on the weighting, see T81988. */
894  bpoly->weight *= bpoly->edgemid_angle / M_PI;
895 
896  tot_weight += bpoly->weight;
897  }
898 
899  bpoly = bwdata->bind_polys;
900 
901  for (int i = 0; i < bwdata->polys_num; bpoly++, i++) {
902  bpoly->weight /= tot_weight;
903 
904  /* Evaluate if this poly is relevant to bind */
905  /* Even though the weights should add up to 1.0,
906  * the losses of weights smaller than epsilon here
907  * should be negligible... */
908  if (bpoly->weight >= FLT_EPSILON) {
909  if (bpoly->inside) {
910  bwdata->binds_num += 1;
911  }
912  else {
913  if (bpoly->dominant_angle_weight < FLT_EPSILON ||
914  1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) {
915  bwdata->binds_num += 1;
916  }
917  else {
918  bwdata->binds_num += 2;
919  }
920  }
921  }
922  }
923 
924  return bwdata;
925 }
926 
927 BLI_INLINE float computeNormalDisplacement(const float point_co[3],
928  const float point_co_proj[3],
929  const float normal[3])
930 {
931  float disp_vec[3];
932  float normal_dist;
933 
934  sub_v3_v3v3(disp_vec, point_co, point_co_proj);
935  normal_dist = len_v3(disp_vec);
936 
937  if (dot_v3v3(disp_vec, normal) < 0) {
938  normal_dist *= -1;
939  }
940 
941  return normal_dist;
942 }
943 
944 static void bindVert(void *__restrict userdata,
945  const int index,
946  const TaskParallelTLS *__restrict UNUSED(tls))
947 {
948  SDefBindCalcData *const data = (SDefBindCalcData *)userdata;
949  float point_co[3];
950  float point_co_proj[3];
951 
952  SDefBindWeightData *bwdata;
953  SDefVert *sdvert = data->bind_verts + index;
954  SDefBindPoly *bpoly;
955  SDefBind *sdbind;
956 
957  sdvert->vertex_idx = index;
958 
959  if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
960  sdvert->binds = NULL;
961  sdvert->binds_num = 0;
962  return;
963  }
964 
965  if (data->sparse_bind) {
966  float weight = 0.0f;
967 
968  if (data->dvert && data->defgrp_index != -1) {
969  weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index);
970  }
971 
972  if (data->invert_vgroup) {
973  weight = 1.0f - weight;
974  }
975 
976  if (weight <= 0) {
977  sdvert->binds = NULL;
978  sdvert->binds_num = 0;
979  return;
980  }
981  }
982 
983  copy_v3_v3(point_co, data->vertexCos[index]);
984  bwdata = computeBindWeights(data, point_co);
985 
986  if (bwdata == NULL) {
987  sdvert->binds = NULL;
988  sdvert->binds_num = 0;
989  return;
990  }
991 
992  sdvert->binds = MEM_calloc_arrayN(bwdata->binds_num, sizeof(*sdvert->binds), "SDefVertBindData");
993  if (sdvert->binds == NULL) {
995  sdvert->binds_num = 0;
996  return;
997  }
998 
999  sdvert->binds_num = bwdata->binds_num;
1000 
1001  sdbind = sdvert->binds;
1002 
1003  bpoly = bwdata->bind_polys;
1004 
1005  for (int i = 0; i < bwdata->binds_num; bpoly++) {
1006  if (bpoly->weight >= FLT_EPSILON) {
1007  if (bpoly->inside) {
1008  const MLoop *loop = &data->mloop[bpoly->loopstart];
1009 
1010  sdbind->influence = bpoly->weight;
1011  sdbind->verts_num = bpoly->verts_num;
1012 
1013  sdbind->mode = MOD_SDEF_MODE_NGON;
1014  sdbind->vert_weights = MEM_malloc_arrayN(
1015  bpoly->verts_num, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights");
1016  if (sdbind->vert_weights == NULL) {
1018  return;
1019  }
1020 
1021  sdbind->vert_inds = MEM_malloc_arrayN(
1022  bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefNgonVertInds");
1023  if (sdbind->vert_inds == NULL) {
1025  return;
1026  }
1027 
1029  sdbind->vert_weights, bpoly->coords_v2, bpoly->verts_num, bpoly->point_v2);
1030 
1031  /* Re-project vert based on weights and original poly verts,
1032  * to reintroduce poly non-planarity */
1033  zero_v3(point_co_proj);
1034  for (int j = 0; j < bpoly->verts_num; j++, loop++) {
1035  madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]);
1036  sdbind->vert_inds[j] = loop->v;
1037  }
1038 
1039  sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
1040 
1041  sdbind++;
1042  i++;
1043  }
1044  else {
1045  float tmp_vec[3];
1046  float cent[3], norm[3];
1047  float v1[3], v2[3], v3[3];
1048 
1049  if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) {
1050  sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight);
1051  sdbind->verts_num = bpoly->verts_num;
1052 
1053  sdbind->mode = MOD_SDEF_MODE_CENTROID;
1054  sdbind->vert_weights = MEM_malloc_arrayN(
1055  3, sizeof(*sdbind->vert_weights), "SDefCentVertWeights");
1056  if (sdbind->vert_weights == NULL) {
1058  return;
1059  }
1060 
1061  sdbind->vert_inds = MEM_malloc_arrayN(
1062  bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefCentVertInds");
1063  if (sdbind->vert_inds == NULL) {
1065  return;
1066  }
1067 
1068  sortPolyVertsEdge(sdbind->vert_inds,
1069  &data->mloop[bpoly->loopstart],
1070  bpoly->edge_inds[bpoly->dominant_edge],
1071  bpoly->verts_num);
1072 
1073  copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
1074  copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
1075  copy_v3_v3(v3, bpoly->centroid);
1076 
1077  mid_v3_v3v3v3(cent, v1, v2, v3);
1078  normal_tri_v3(norm, v1, v2, v3);
1079 
1080  add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
1081 
1082  /* We are sure the line is not parallel to the plane.
1083  * Checking return value just to avoid warning... */
1084  if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
1085  BLI_assert(false);
1086  }
1087 
1088  interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
1089 
1090  sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
1091 
1092  sdbind++;
1093  i++;
1094  }
1095 
1096  if (bpoly->dominant_angle_weight >= FLT_EPSILON) {
1097  sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight;
1098  sdbind->verts_num = bpoly->verts_num;
1099 
1100  sdbind->mode = MOD_SDEF_MODE_LOOPTRI;
1101  sdbind->vert_weights = MEM_malloc_arrayN(
1102  3, sizeof(*sdbind->vert_weights), "SDefTriVertWeights");
1103  if (sdbind->vert_weights == NULL) {
1105  return;
1106  }
1107 
1108  sdbind->vert_inds = MEM_malloc_arrayN(
1109  bpoly->verts_num, sizeof(*sdbind->vert_inds), "SDefTriVertInds");
1110  if (sdbind->vert_inds == NULL) {
1112  return;
1113  }
1114 
1115  sortPolyVertsTri(sdbind->vert_inds,
1116  &data->mloop[bpoly->loopstart],
1117  bpoly->edge_vert_inds[0],
1118  bpoly->verts_num);
1119 
1120  copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
1121  copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
1122  copy_v3_v3(v3, data->targetCos[sdbind->vert_inds[2]]);
1123 
1124  mid_v3_v3v3v3(cent, v1, v2, v3);
1125  normal_tri_v3(norm, v1, v2, v3);
1126 
1127  add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
1128 
1129  /* We are sure the line is not parallel to the plane.
1130  * Checking return value just to avoid warning... */
1131  if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
1132  BLI_assert(false);
1133  }
1134 
1135  interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
1136 
1137  sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
1138 
1139  sdbind++;
1140  i++;
1141  }
1142  }
1143  }
1144  }
1145 
1146  freeBindData(bwdata);
1147 }
1148 
1149 /* Remove vertices without bind data from the bind array. */
1151 {
1152  smd->bind_verts_num = 0;
1153 
1154  for (uint i = 0; i < smd->mesh_verts_num; i++) {
1155  if (smd->verts[i].binds_num > 0) {
1156  smd->verts[smd->bind_verts_num++] = smd->verts[i];
1157  }
1158  }
1159 
1160  smd->verts = MEM_reallocN_id(
1161  smd->verts, sizeof(*smd->verts) * smd->bind_verts_num, "SDefBindVerts (sparse)");
1162 }
1163 
1164 static bool surfacedeformBind(Object *ob,
1165  SurfaceDeformModifierData *smd_orig,
1166  SurfaceDeformModifierData *smd_eval,
1167  float (*vertexCos)[3],
1168  uint verts_num,
1169  uint target_polys_num,
1170  uint target_verts_num,
1171  Mesh *target,
1172  Mesh *mesh)
1173 {
1174  BVHTreeFromMesh treeData = {NULL};
1175  const MVert *mvert = target->mvert;
1176  const MPoly *mpoly = target->mpoly;
1177  const MEdge *medge = target->medge;
1178  const MLoop *mloop = target->mloop;
1179  uint tedges_num = target->totedge;
1180  int adj_result;
1181  SDefAdjacencyArray *vert_edges;
1182  SDefAdjacency *adj_array;
1183  SDefEdgePolys *edge_polys;
1184 
1185  vert_edges = MEM_calloc_arrayN(target_verts_num, sizeof(*vert_edges), "SDefVertEdgeMap");
1186  if (vert_edges == NULL) {
1187  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1188  return false;
1189  }
1190 
1191  adj_array = MEM_malloc_arrayN(tedges_num, 2 * sizeof(*adj_array), "SDefVertEdge");
1192  if (adj_array == NULL) {
1193  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1194  MEM_freeN(vert_edges);
1195  return false;
1196  }
1197 
1198  edge_polys = MEM_calloc_arrayN(tedges_num, sizeof(*edge_polys), "SDefEdgeFaceMap");
1199  if (edge_polys == NULL) {
1200  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1201  MEM_freeN(vert_edges);
1202  MEM_freeN(adj_array);
1203  return false;
1204  }
1205 
1206  smd_orig->verts = MEM_malloc_arrayN(verts_num, sizeof(*smd_orig->verts), "SDefBindVerts");
1207  if (smd_orig->verts == NULL) {
1208  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1209  freeAdjacencyMap(vert_edges, adj_array, edge_polys);
1210  return false;
1211  }
1212 
1213  BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2);
1214  if (treeData.tree == NULL) {
1215  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1216  freeAdjacencyMap(vert_edges, adj_array, edge_polys);
1217  MEM_freeN(smd_orig->verts);
1218  smd_orig->verts = NULL;
1219  return false;
1220  }
1221 
1222  adj_result = buildAdjacencyMap(
1223  mpoly, medge, mloop, target_polys_num, tedges_num, vert_edges, adj_array, edge_polys);
1224 
1225  if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
1227  ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons");
1228  freeAdjacencyMap(vert_edges, adj_array, edge_polys);
1229  free_bvhtree_from_mesh(&treeData);
1230  MEM_freeN(smd_orig->verts);
1231  smd_orig->verts = NULL;
1232  return false;
1233  }
1234 
1235  smd_orig->mesh_verts_num = verts_num;
1236  smd_orig->target_verts_num = target_verts_num;
1237  smd_orig->target_polys_num = target_polys_num;
1238 
1239  int defgrp_index;
1240  MDeformVert *dvert;
1241  MOD_get_vgroup(ob, mesh, smd_orig->defgrp_name, &dvert, &defgrp_index);
1242  const bool invert_vgroup = (smd_orig->flags & MOD_SDEF_INVERT_VGROUP) != 0;
1243  const bool sparse_bind = (smd_orig->flags & MOD_SDEF_SPARSE_BIND) != 0;
1244 
1246  .treeData = &treeData,
1247  .vert_edges = vert_edges,
1248  .edge_polys = edge_polys,
1249  .mpoly = mpoly,
1250  .medge = medge,
1251  .mloop = mloop,
1252  .looptri = BKE_mesh_runtime_looptri_ensure(target),
1253  .targetCos = MEM_malloc_arrayN(
1254  target_verts_num, sizeof(float[3]), "SDefTargetBindVertArray"),
1255  .bind_verts = smd_orig->verts,
1256  .vertexCos = vertexCos,
1257  .falloff = smd_orig->falloff,
1258  .success = MOD_SDEF_BIND_RESULT_SUCCESS,
1259  .dvert = dvert,
1260  .defgrp_index = defgrp_index,
1261  .invert_vgroup = invert_vgroup,
1262  .sparse_bind = sparse_bind,
1263  };
1264 
1265  if (data.targetCos == NULL) {
1266  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1267  freeData((ModifierData *)smd_orig);
1268  return false;
1269  }
1270 
1271  invert_m4_m4(data.imat, smd_orig->mat);
1272 
1273  for (int i = 0; i < target_verts_num; i++) {
1274  mul_v3_m4v3(data.targetCos[i], smd_orig->mat, mvert[i].co);
1275  }
1276 
1277  TaskParallelSettings settings;
1279  settings.use_threading = (verts_num > 10000);
1280  BLI_task_parallel_range(0, verts_num, &data, bindVert, &settings);
1281 
1282  MEM_freeN(data.targetCos);
1283 
1284  if (sparse_bind) {
1285  compactSparseBinds(smd_orig);
1286  }
1287  else {
1288  smd_orig->bind_verts_num = verts_num;
1289  }
1290 
1291  if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
1292  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory");
1293  freeData((ModifierData *)smd_orig);
1294  }
1295  else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
1297  ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons");
1298  freeData((ModifierData *)smd_orig);
1299  }
1300  else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
1301  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains concave polygons");
1302  freeData((ModifierData *)smd_orig);
1303  }
1304  else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
1305  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains overlapping vertices");
1306  freeData((ModifierData *)smd_orig);
1307  }
1308  else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) {
1309  /* I know this message is vague, but I could not think of a way
1310  * to explain this with a reasonably sized message.
1311  * Though it shouldn't really matter all that much,
1312  * because this is very unlikely to occur */
1313  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Target contains invalid polygons");
1314  freeData((ModifierData *)smd_orig);
1315  }
1316  else if (smd_orig->bind_verts_num == 0 || !smd_orig->verts) {
1318  BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "No vertices were bound");
1319  freeData((ModifierData *)smd_orig);
1320  }
1321 
1322  freeAdjacencyMap(vert_edges, adj_array, edge_polys);
1323  free_bvhtree_from_mesh(&treeData);
1324 
1325  return data.success == 1;
1326 }
1327 
1328 static void deformVert(void *__restrict userdata,
1329  const int index,
1330  const TaskParallelTLS *__restrict UNUSED(tls))
1331 {
1332  const SDefDeformData *const data = (SDefDeformData *)userdata;
1333  const SDefBind *sdbind = data->bind_verts[index].binds;
1334  const int sdbind_num = data->bind_verts[index].binds_num;
1335  const unsigned int vertex_idx = data->bind_verts[index].vertex_idx;
1336  float *const vertexCos = data->vertexCos[vertex_idx];
1337  float norm[3], temp[3], offset[3];
1338 
1339  /* Retrieve the value of the weight vertex group if specified. */
1340  float weight = 1.0f;
1341 
1342  if (data->dvert && data->defgrp_index != -1) {
1343  weight = BKE_defvert_find_weight(&data->dvert[vertex_idx], data->defgrp_index);
1344 
1345  if (data->invert_vgroup) {
1346  weight = 1.0f - weight;
1347  }
1348  }
1349 
1350  /* Check if this vertex will be deformed. If it is not deformed we return and avoid
1351  * unnecessary calculations. */
1352  if (weight == 0.0f) {
1353  return;
1354  }
1355 
1356  zero_v3(offset);
1357 
1358  /* Allocate a `coords_buffer` that fits all the temp-data. */
1359  int max_verts = 0;
1360  for (int j = 0; j < sdbind_num; j++) {
1361  max_verts = MAX2(max_verts, sdbind[j].verts_num);
1362  }
1363 
1364  const bool big_buffer = max_verts > 256;
1365  float(*coords_buffer)[3];
1366 
1367  if (UNLIKELY(big_buffer)) {
1368  coords_buffer = MEM_malloc_arrayN(max_verts, sizeof(*coords_buffer), __func__);
1369  }
1370  else {
1371  coords_buffer = BLI_array_alloca(coords_buffer, max_verts);
1372  }
1373 
1374  for (int j = 0; j < sdbind_num; j++, sdbind++) {
1375  for (int k = 0; k < sdbind->verts_num; k++) {
1376  copy_v3_v3(coords_buffer[k], data->targetCos[sdbind->vert_inds[k]]);
1377  }
1378 
1379  normal_poly_v3(norm, coords_buffer, sdbind->verts_num);
1380  zero_v3(temp);
1381 
1382  switch (sdbind->mode) {
1383  /* ---------- looptri mode ---------- */
1384  case MOD_SDEF_MODE_LOOPTRI: {
1385  madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
1386  madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
1387  madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
1388  break;
1389  }
1390 
1391  /* ---------- ngon mode ---------- */
1392  case MOD_SDEF_MODE_NGON: {
1393  for (int k = 0; k < sdbind->verts_num; k++) {
1394  madd_v3_v3fl(temp, coords_buffer[k], sdbind->vert_weights[k]);
1395  }
1396  break;
1397  }
1398 
1399  /* ---------- centroid mode ---------- */
1400  case MOD_SDEF_MODE_CENTROID: {
1401  float cent[3];
1402  mid_v3_v3_array(cent, coords_buffer, sdbind->verts_num);
1403 
1404  madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
1405  madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
1406  madd_v3_v3fl(temp, cent, sdbind->vert_weights[2]);
1407  break;
1408  }
1409  }
1410 
1411  /* Apply normal offset (generic for all modes) */
1412  madd_v3_v3fl(temp, norm, sdbind->normal_dist);
1413 
1414  madd_v3_v3fl(offset, temp, sdbind->influence);
1415  }
1416  /* Subtract the vertex coord to get the deformation offset. */
1417  sub_v3_v3(offset, vertexCos);
1418 
1419  /* Add the offset to start coord multiplied by the strength and weight values. */
1420  madd_v3_v3fl(vertexCos, offset, data->strength * weight);
1421 
1422  if (UNLIKELY(big_buffer)) {
1423  MEM_freeN(coords_buffer);
1424  }
1425 }
1426 
1428  const ModifierEvalContext *ctx,
1429  float (*vertexCos)[3],
1430  uint verts_num,
1431  Object *ob,
1432  Mesh *mesh)
1433 {
1435  Mesh *target;
1436  uint target_verts_num, target_polys_num;
1437 
1438  /* Exit function if bind flag is not set (free bind data if any). */
1439  if (!(smd->flags & MOD_SDEF_BIND)) {
1440  if (smd->verts != NULL) {
1441  if (!DEG_is_active(ctx->depsgraph)) {
1442  BKE_modifier_set_error(ob, md, "Attempt to bind from inactive dependency graph");
1443  return;
1444  }
1445  ModifierData *md_orig = BKE_modifier_get_original(ob, md);
1446  freeData(md_orig);
1447  }
1448  return;
1449  }
1450 
1451  Object *ob_target = smd->target;
1453  if (!target) {
1454  BKE_modifier_set_error(ob, md, "No valid target mesh");
1455  return;
1456  }
1457 
1458  target_verts_num = BKE_mesh_wrapper_vert_len(target);
1459  target_polys_num = BKE_mesh_wrapper_poly_len(target);
1460 
1461  /* If not bound, execute bind. */
1462  if (smd->verts == NULL) {
1463  if (!DEG_is_active(ctx->depsgraph)) {
1464  BKE_modifier_set_error(ob, md, "Attempt to unbind from inactive dependency graph");
1465  return;
1466  }
1467 
1469  ob, md);
1470  float tmp_mat[4][4];
1471 
1472  invert_m4_m4(tmp_mat, ob->obmat);
1473  mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->obmat);
1474 
1475  /* Avoid converting edit-mesh data, binding is an exception. */
1477 
1478  if (!surfacedeformBind(ob,
1479  smd_orig,
1480  smd,
1481  vertexCos,
1482  verts_num,
1483  target_polys_num,
1484  target_verts_num,
1485  target,
1486  mesh)) {
1487  smd->flags &= ~MOD_SDEF_BIND;
1488  }
1489  /* Early abort, this is binding 'call', no need to perform whole evaluation. */
1490  return;
1491  }
1492 
1493  /* Geometry count on the deforming mesh. */
1494  if (smd->mesh_verts_num != verts_num) {
1496  ob, md, "Vertices changed from %u to %u", smd->mesh_verts_num, verts_num);
1497  return;
1498  }
1499 
1500  /* Geometry count on the target mesh. */
1501  if (smd->target_polys_num != target_polys_num && smd->target_verts_num == 0) {
1502  /* Change in the number of polygons does not really imply change in the vertex count, but
1503  * this is how the modifier worked before the vertex count was known. Follow the legacy
1504  * logic without requirement to re-bind the mesh. */
1506  ob, md, "Target polygons changed from %u to %u", smd->target_polys_num, target_polys_num);
1507  return;
1508  }
1509  if (smd->target_verts_num != 0 && smd->target_verts_num != target_verts_num) {
1510  if (smd->target_verts_num > target_verts_num) {
1511  /* Number of vertices on the target did reduce. There is no usable recovery from this. */
1513  md,
1514  "Target vertices changed from %u to %u",
1515  smd->target_verts_num,
1516  target_verts_num);
1517  return;
1518  }
1519 
1520  /* Assume the increase in the vertex count means that the "new" vertices in the target mesh are
1521  * added after the original ones. This covers typical case when target was at the subdivision
1522  * level 0 and then subdivision was increased (i.e. for the render purposes). */
1523 
1525  md,
1526  "Target vertices changed from %u to %u, continuing anyway",
1527  smd->target_verts_num,
1528  target_verts_num);
1529 
1530  /* In theory we only need the `smd->verts_num` vertices in the `targetCos` for evaluation, but
1531  * it is not currently possible to request a subset of coordinates: the API expects that the
1532  * caller needs coordinates of all vertices and asserts for it. */
1533  }
1534 
1535  /* Early out if modifier would not affect input at all - still *after* the sanity checks
1536  * (and potential binding) above. */
1537  if (smd->strength == 0.0f) {
1538  return;
1539  }
1540 
1541  int defgrp_index;
1542  MDeformVert *dvert;
1543  MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index);
1544  const bool invert_vgroup = (smd->flags & MOD_SDEF_INVERT_VGROUP) != 0;
1545 
1546  /* Actual vertex location update starts here */
1547  SDefDeformData data = {
1548  .bind_verts = smd->verts,
1549  .targetCos = MEM_malloc_arrayN(target_verts_num, sizeof(float[3]), "SDefTargetVertArray"),
1550  .vertexCos = vertexCos,
1551  .dvert = dvert,
1552  .defgrp_index = defgrp_index,
1553  .invert_vgroup = invert_vgroup,
1554  .strength = smd->strength,
1555  };
1556 
1557  if (data.targetCos != NULL) {
1559  target, data.targetCos, target_verts_num, smd->mat);
1560 
1561  TaskParallelSettings settings;
1563  settings.use_threading = (smd->bind_verts_num > 10000);
1564  BLI_task_parallel_range(0, smd->bind_verts_num, &data, deformVert, &settings);
1565 
1566  MEM_freeN(data.targetCos);
1567  }
1568 }
1569 
1570 static void deformVerts(ModifierData *md,
1571  const ModifierEvalContext *ctx,
1572  Mesh *mesh,
1573  float (*vertexCos)[3],
1574  int verts_num)
1575 {
1577  Mesh *mesh_src = NULL;
1578 
1579  if (smd->defgrp_name[0] != '\0') {
1580  /* Only need to use mesh_src when a vgroup is used. */
1581  mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
1582  }
1583 
1584  surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src);
1585 
1586  if (!ELEM(mesh_src, NULL, mesh)) {
1587  BKE_id_free(NULL, mesh_src);
1588  }
1589 }
1590 
1591 static void deformVertsEM(ModifierData *md,
1592  const ModifierEvalContext *ctx,
1593  struct BMEditMesh *em,
1594  Mesh *mesh,
1595  float (*vertexCos)[3],
1596  int verts_num)
1597 {
1599  Mesh *mesh_src = NULL;
1600 
1601  if (smd->defgrp_name[0] != '\0') {
1602  /* Only need to use mesh_src when a vgroup is used. */
1603  mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, verts_num, false, false);
1604  }
1605 
1606  /* TODO(@campbellbarton): use edit-mode data only (remove this line). */
1607  if (mesh_src != NULL) {
1609  }
1610 
1611  surfacedeformModifier_do(md, ctx, vertexCos, verts_num, ctx->object, mesh_src);
1612 
1613  if (!ELEM(mesh_src, NULL, mesh)) {
1614  BKE_id_free(NULL, mesh_src);
1615  }
1616 }
1617 
1618 static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
1619 {
1621 
1622  /* The object type check is only needed here in case we have a placeholder
1623  * object assigned (because the library containing the mesh is missing).
1624  *
1625  * In other cases it should be impossible to have a type mismatch.
1626  */
1627  return (smd->target == NULL || smd->target->type != OB_MESH) &&
1628  !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND));
1629 }
1630 
1631 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
1632 {
1633  uiLayout *col;
1634  uiLayout *layout = panel->layout;
1635 
1636  PointerRNA ob_ptr;
1638 
1639  PointerRNA target_ptr = RNA_pointer_get(ptr, "target");
1640 
1641  bool is_bound = RNA_boolean_get(ptr, "is_bound");
1642 
1643  uiLayoutSetPropSep(layout, true);
1644 
1645  col = uiLayoutColumn(layout, false);
1646  uiLayoutSetActive(col, !is_bound);
1647  uiItemR(col, ptr, "target", 0, NULL, ICON_NONE);
1648  uiItemR(col, ptr, "falloff", 0, NULL, ICON_NONE);
1649 
1650  uiItemR(layout, ptr, "strength", 0, NULL, ICON_NONE);
1651 
1652  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
1653 
1654  col = uiLayoutColumn(layout, false);
1655  uiLayoutSetEnabled(col, !is_bound);
1656  uiLayoutSetActive(col, !is_bound && RNA_string_length(ptr, "vertex_group") != 0);
1657  uiItemR(col, ptr, "use_sparse_bind", 0, NULL, ICON_NONE);
1658 
1659  uiItemS(layout);
1660 
1661  col = uiLayoutColumn(layout, false);
1662  if (is_bound) {
1663  uiItemO(col, IFACE_("Unbind"), ICON_NONE, "OBJECT_OT_surfacedeform_bind");
1664  }
1665  else {
1666  uiLayoutSetActive(col, !RNA_pointer_is_null(&target_ptr));
1667  uiItemO(col, IFACE_("Bind"), ICON_NONE, "OBJECT_OT_surfacedeform_bind");
1668  }
1669  modifier_panel_end(layout, ptr);
1670 }
1671 
1672 static void panelRegister(ARegionType *region_type)
1673 {
1675 }
1676 
1677 static void blendWrite(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
1678 {
1680  const bool is_undo = BLO_write_is_undo(writer);
1681 
1682  if (ID_IS_OVERRIDE_LIBRARY(id_owner) && !is_undo) {
1683  BLI_assert(!ID_IS_LINKED(id_owner));
1684  const bool is_local = (md->flag & eModifierFlag_OverrideLibrary_Local) != 0;
1685  if (!is_local) {
1686  /* Modifier coming from linked data cannot be bound from an override, so we can remove all
1687  * binding data, can save a significant amount of memory. */
1688  smd.bind_verts_num = 0;
1689  smd.verts = NULL;
1690  }
1691  }
1692 
1694 
1695  if (smd.verts != NULL) {
1696  SDefVert *bind_verts = smd.verts;
1697  BLO_write_struct_array(writer, SDefVert, smd.bind_verts_num, bind_verts);
1698 
1699  for (int i = 0; i < smd.bind_verts_num; i++) {
1700  BLO_write_struct_array(writer, SDefBind, bind_verts[i].binds_num, bind_verts[i].binds);
1701 
1702  if (bind_verts[i].binds) {
1703  for (int j = 0; j < bind_verts[i].binds_num; j++) {
1705  writer, bind_verts[i].binds[j].verts_num, bind_verts[i].binds[j].vert_inds);
1706 
1707  if (ELEM(bind_verts[i].binds[j].mode, MOD_SDEF_MODE_CENTROID, MOD_SDEF_MODE_LOOPTRI)) {
1708  BLO_write_float3_array(writer, 1, bind_verts[i].binds[j].vert_weights);
1709  }
1710  else {
1712  writer, bind_verts[i].binds[j].verts_num, bind_verts[i].binds[j].vert_weights);
1713  }
1714  }
1715  }
1716  }
1717  }
1718 }
1719 
1720 static void blendRead(BlendDataReader *reader, ModifierData *md)
1721 {
1723 
1724  BLO_read_data_address(reader, &smd->verts);
1725 
1726  if (smd->verts) {
1727  for (int i = 0; i < smd->bind_verts_num; i++) {
1728  BLO_read_data_address(reader, &smd->verts[i].binds);
1729 
1730  if (smd->verts[i].binds) {
1731  for (int j = 0; j < smd->verts[i].binds_num; j++) {
1733  reader, smd->verts[i].binds[j].verts_num, &smd->verts[i].binds[j].vert_inds);
1734 
1736  BLO_read_float3_array(reader, 1, &smd->verts[i].binds[j].vert_weights);
1737  }
1738  else {
1740  reader, smd->verts[i].binds[j].verts_num, &smd->verts[i].binds[j].vert_weights);
1741  }
1742  }
1743  }
1744  }
1745  }
1746 }
1747 
1749  /* name */ N_("SurfaceDeform"),
1750  /* structName */ "SurfaceDeformModifierData",
1751  /* structSize */ sizeof(SurfaceDeformModifierData),
1752  /* srna */ &RNA_SurfaceDeformModifier,
1753  /* type */ eModifierTypeType_OnlyDeform,
1755  /* icon */ ICON_MOD_MESHDEFORM,
1756 
1757  /* copyData */ copyData,
1758 
1759  /* deformVerts */ deformVerts,
1760  /* deformMatrices */ NULL,
1761  /* deformVertsEM */ deformVertsEM,
1762  /* deformMatricesEM */ NULL,
1763  /* modifyMesh */ NULL,
1764  /* modifyGeometrySet */ NULL,
1765 
1766  /* initData */ initData,
1767  /* requiredDataMask */ requiredDataMask,
1768  /* freeData */ freeData,
1769  /* isDisabled */ isDisabled,
1770  /* updateDepsgraph */ updateDepsgraph,
1771  /* dependsOnTime */ NULL,
1772  /* dependsOnNormals */ NULL,
1773  /* foreachIDLink */ foreachIDLink,
1774  /* foreachTexLink */ NULL,
1775  /* freeRuntimeData */ NULL,
1776  /* panelRegister */ panelRegister,
1777  /* blendWrite */ blendWrite,
1778  /* blendRead */ blendRead,
1779 };
typedef float(TangentPoint)[2]
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.cc:1410
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:73
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition: bvhutils.cc:1213
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
void BKE_id_free(struct Main *bmain, void *idv)
@ IDWALK_NOP
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
int BKE_mesh_wrapper_vert_len(const struct Mesh *me)
int BKE_mesh_wrapper_poly_len(const struct Mesh *me)
void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const struct Mesh *me, float(*vert_coords)[3], int vert_coords_len, const float mat[4][4])
struct ModifierData * BKE_modifier_get_original(const struct Object *object, struct ModifierData *md)
void void BKE_modifier_set_warning(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1616
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
#define M_PI_2
Definition: BLI_math_base.h:23
MINLINE float interpf(float a, float b, float t)
MINLINE float signf(float f)
#define M_PI
Definition: BLI_math_base.h:20
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:485
MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2])
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
Definition: math_geom.c:3603
void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], float angle)
Definition: math_geom.c:4963
void interp_weights_poly_v2(float w[], float v[][2], int n, const float co[2])
bool isect_line_plane_v3(float r_isect_co[3], const float l1[3], const float l2[3], const float plane_co[3], const float plane_no[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_geom.c:2078
float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
Definition: math_geom.c:71
bool is_poly_convex_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:5806
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
bool isect_point_poly_v2(const float pt[2], const float verts[][2], unsigned int nr, bool use_holes)
float dist_to_line_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:278
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
float angle_normalized_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:461
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f)
void mid_v3_v3_array(float r[3], const float(*vec_arr)[3], unsigned int vec_arr_num)
Definition: math_vector.c:271
MINLINE void sub_v2_v2(float r[2], const float a[2])
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 copy_v2_v2(float r[2], const float a[2])
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 cross_v3_v3v3(float r[3], const float a[3], const float b[3])
float angle_signed_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:439
void mid_v2_v2v2(float r[2], const float a[2], const float b[2])
Definition: math_vector.c:244
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void zero_v2(float r[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v2(float r[2])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_vector.c:256
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:67
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
#define UNUSED(x)
#define MAX2(a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
void BLO_read_float3_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition: readfile.c:5201
void BLO_write_uint32_array(BlendWriter *writer, uint num, const uint32_t *data_ptr)
Definition: writefile.c:1576
#define BLO_read_data_address(reader, ptr_p)
void BLO_write_float3_array(BlendWriter *writer, uint num, const float *data_ptr)
Definition: writefile.c:1596
void BLO_read_float_array(BlendDataReader *reader, int array_size, float **ptr_p)
Definition: readfile.c:5193
void BLO_read_uint32_array(BlendDataReader *reader, int array_size, uint32_t **ptr_p)
Definition: readfile.c:5185
void BLO_write_float_array(BlendWriter *writer, uint num, const float *data_ptr)
Definition: writefile.c:1581
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
Definition: writefile.c:1608
#define BLO_write_struct_at_address(writer, struct_name, address, data_ptr)
#define IFACE_(msgid)
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:312
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ MOD_SDEF_BIND
@ MOD_SDEF_INVERT_VGROUP
@ MOD_SDEF_SPARSE_BIND
@ eModifierFlag_OverrideLibrary_Local
struct SurfaceDeformModifierData SurfaceDeformModifierData
@ eModifierType_SurfaceDeform
@ MOD_SDEF_MODE_LOOPTRI
@ MOD_SDEF_MODE_CENTROID
@ MOD_SDEF_MODE_NGON
Object is a sort of wrapper for general info.
@ OB_MESH
_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 GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
struct SDefBindWeightData SDefBindWeightData
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], int verts_num)
static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *em, Mesh *mesh, float(*vertexCos)[3], int verts_num)
static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges, SDefAdjacency *const adj_ref, SDefEdgePolys *const edge_polys)
BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3])
@ MOD_SDEF_BIND_RESULT_SUCCESS
@ MOD_SDEF_BIND_RESULT_CONCAVE_ERR
@ MOD_SDEF_BIND_RESULT_MEM_ERR
@ MOD_SDEF_BIND_RESULT_GENERIC_ERR
@ MOD_SDEF_BIND_RESULT_OVERLAP_ERR
@ MOD_SDEF_BIND_RESULT_NONMANY_ERR
static void freeBindData(SDefBindWeightData *const bwdata)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void deformVert(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls))
BLI_INLINE int isPolyValid(const float coords[][2], const uint nr)
BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
static void surfacedeformModifier_do(ModifierData *md, const ModifierEvalContext *ctx, float(*vertexCos)[3], uint verts_num, Object *ob, Mesh *mesh)
struct SDefBindCalcData SDefBindCalcData
static void blendRead(BlendDataReader *reader, ModifierData *md)
struct SDefAdjacency SDefAdjacency
BLI_INLINE void sortPolyVertsEdge(uint *indices, const MLoop *const mloop, const uint edge, const uint num)
static void compactSparseBinds(SurfaceDeformModifierData *smd)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static void bindVert(void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls))
BLI_INLINE void sortPolyVertsTri(uint *indices, const MLoop *const mloop, const uint loopstart, const uint num)
BLI_INLINE SDefBindWeightData * computeBindWeights(SDefBindCalcData *const data, const float point_co[3])
struct SDefBindPoly SDefBindPoly
struct SDefEdgePolys SDefEdgePolys
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
BLI_INLINE float computeNormalDisplacement(const float point_co[3], const float point_co_proj[3], const float normal[3])
struct SDefDeformData SDefDeformData
static int buildAdjacencyMap(const MPoly *poly, const MEdge *edge, const MLoop *const mloop, const uint polys_num, const uint edges_num, SDefAdjacencyArray *const vert_edges, SDefAdjacency *adj, SDefEdgePolys *const edge_polys)
static bool surfacedeformBind(Object *ob, SurfaceDeformModifierData *smd_orig, SurfaceDeformModifierData *smd_eval, float(*vertexCos)[3], uint verts_num, uint target_polys_num, uint target_verts_num, Mesh *target, Mesh *mesh)
@ MOD_SDEF_INFINITE_WEIGHT_DIST
@ MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ
@ MOD_SDEF_INFINITE_WEIGHT_ANGULAR
ModifierTypeInfo modifierType_SurfaceDeform
static void freeData(ModifierData *md)
struct SDefAdjacencyArray SDefAdjacencyArray
static void blendWrite(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
Mesh * MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float(*vertexCos)[3], const int verts_num, const bool use_normals, const bool use_orco)
Definition: MOD_util.c:167
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:235
#define C
Definition: RandGen.cpp:25
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define sinf(x)
Definition: cuda/compat.h:102
#define powf(x, y)
Definition: cuda/compat.h:103
Scene scene
World world
uint col
IconTextureDrawCall normal
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix int ccl_global int * indices
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
Definition: mallocn.c:29
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
bool isnan(double i)
Definition: numeric.h:451
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
int RNA_string_length(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5144
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
struct BVHTree * tree
Definition: BKE_bvhutils.h:50
Definition: DNA_ID.h:368
unsigned int e
unsigned int v
float co[3]
struct MEdge * medge
struct MVert * mvert
int totedge
struct MLoop * mloop
struct MPoly * mpoly
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
float obmat[4][4]
struct uiLayout * layout
SDefAdjacency * first
struct SDefAdjacency * next
const MLoop *const mloop
bool const invert_vgroup
const MEdge *const medge
const MPoly *const mpoly
BVHTreeFromMesh *const treeData
SDefVert *const bind_verts
float(*const targetCos)[3]
const MLoopTri *const looptri
float(*const vertexCos)[3]
const MDeformVert *const dvert
const SDefEdgePolys *const edge_polys
bool const sparse_bind
const SDefAdjacencyArray *const vert_edges
float corner_edgemid_angles[2]
float dominant_angle_weight
float cent_edgemid_vecs_v2[2][2]
float point_edgemid_angles[2]
float(* coords_v2)[2]
float centroid_v2[2]
float(* coords)[3]
uint edge_vert_inds[2]
SDefBindPoly * bind_polys
unsigned int verts_num
unsigned int * vert_inds
float * vert_weights
int const defgrp_index
const SDefVert *const bind_verts
bool const invert_vgroup
float(*const vertexCos)[3]
const MDeformVert *const dvert
float(*const targetCos)[3]
float const strength
unsigned int binds_num
SDefBind * binds
unsigned int vertex_idx
ccl_device_inline float sqr(float a)
Definition: util/math.h:746
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480