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